Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 309a5702 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/bios: store aux addr independently of i2c



Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent a7468451
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@ struct dcb_i2c_entry {
	u8 drive;
	u8 drive;
	u8 sense;
	u8 sense;
	u8 share;
	u8 share;
	u8 auxch;
};
};


u16 dcb_i2c_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
u16 dcb_i2c_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
+21 −9
Original line number Original line Diff line number Diff line
@@ -39,6 +39,11 @@ dcb_i2c_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
			i2c = nv_ro16(bios, dcb + 4);
			i2c = nv_ro16(bios, dcb + 4);
	}
	}


	if (i2c && *ver >= 0x41) {
		nv_warn(bios, "ccb %02x not supported\n", *ver);
		return 0x0000;
	}

	if (i2c && *ver >= 0x30) {
	if (i2c && *ver >= 0x30) {
		*ver = nv_ro08(bios, i2c + 0);
		*ver = nv_ro08(bios, i2c + 0);
		*hdr = nv_ro08(bios, i2c + 1);
		*hdr = nv_ro08(bios, i2c + 1);
@@ -70,14 +75,19 @@ dcb_i2c_parse(struct nouveau_bios *bios, u8 idx, struct dcb_i2c_entry *info)
	u8  ver, len;
	u8  ver, len;
	u16 ent = dcb_i2c_entry(bios, idx, &ver, &len);
	u16 ent = dcb_i2c_entry(bios, idx, &ver, &len);
	if (ent) {
	if (ent) {
		info->type  = nv_ro08(bios, ent + 3);
		if (ver >= 0x30) {
		info->share = DCB_I2C_UNUSED;
			info->type = nv_ro08(bios, ent + 0x03);
		if (ver < 0x30) {
		} else {
			info->type &= 0x07;
			info->type = nv_ro08(bios, ent + 0x03) & 0x07;
			if (info->type == 0x07)
			if (info->type == 0x07)
				info->type = DCB_I2C_UNUSED;
				info->type = DCB_I2C_UNUSED;
		}
		}


		info->drive = DCB_I2C_UNUSED;
		info->sense = DCB_I2C_UNUSED;
		info->share = DCB_I2C_UNUSED;
		info->auxch = DCB_I2C_UNUSED;

		switch (info->type) {
		switch (info->type) {
		case DCB_I2C_NV04_BIT:
		case DCB_I2C_NV04_BIT:
			info->drive = nv_ro08(bios, ent + 0);
			info->drive = nv_ro08(bios, ent + 0);
@@ -87,12 +97,14 @@ dcb_i2c_parse(struct nouveau_bios *bios, u8 idx, struct dcb_i2c_entry *info)
			info->drive = nv_ro08(bios, ent + 1);
			info->drive = nv_ro08(bios, ent + 1);
			return 0;
			return 0;
		case DCB_I2C_NVIO_BIT:
		case DCB_I2C_NVIO_BIT:
		case DCB_I2C_NVIO_AUX:
			info->drive = nv_ro08(bios, ent + 0) & 0x0f;
			info->drive = nv_ro08(bios, ent + 0) & 0x0f;
			if (nv_ro08(bios, ent + 1) & 0x01) {
			if (nv_ro08(bios, ent + 1) & 0x01)
				info->share = nv_ro08(bios, ent + 1) >> 1;
				info->share = nv_ro08(bios, ent + 1) >> 1;
				info->share &= 0x0f;
			return 0;
			}
		case DCB_I2C_NVIO_AUX:
			info->auxch = nv_ro08(bios, ent + 0) & 0x0f;
			if (nv_ro08(bios, ent + 1) & 0x01)
				info->share = info->auxch;
			return 0;
			return 0;
		case DCB_I2C_UNUSED:
		case DCB_I2C_UNUSED:
			return 0;
			return 0;
+49 −30
Original line number Original line Diff line number Diff line
@@ -473,18 +473,56 @@ nouveau_i2c_extdev_sclass[] = {
	nouveau_anx9805_sclass,
	nouveau_anx9805_sclass,
};
};


static void
nouveau_i2c_create_port(struct nouveau_i2c *i2c, int index, u8 type,
			struct dcb_i2c_entry *info)
{
	const struct nouveau_i2c_impl *impl = (void *)nv_oclass(i2c);
	struct nouveau_oclass *oclass;
	struct nouveau_object *parent;
	struct nouveau_object *object;
	int ret, pad;

	if (info->share != DCB_I2C_UNUSED) {
		pad    = info->share;
		oclass = impl->pad_s;
	} else {
		if (type != DCB_I2C_NVIO_AUX)
			pad = 0x100 + info->drive;
		else
			pad = 0x100 + info->auxch;
		oclass = impl->pad_x;
	}

	ret = nouveau_object_ctor(NULL, nv_object(i2c), oclass, NULL, pad,
				 &parent);
	if (ret < 0)
		return;

	oclass = impl->sclass;
	do {
		ret = -EINVAL;
		if (oclass->handle == type) {
			ret = nouveau_object_ctor(parent, nv_object(i2c),
						  oclass, info, index,
						 &object);
		}
	} while (ret && (++oclass)->handle);

	nouveau_object_ref(NULL, &parent);
}

int
int
nouveau_i2c_create_(struct nouveau_object *parent,
nouveau_i2c_create_(struct nouveau_object *parent,
		    struct nouveau_object *engine,
		    struct nouveau_object *engine,
		    struct nouveau_oclass *oclass,
		    struct nouveau_oclass *oclass,
		    int length, void **pobject)
		    int length, void **pobject)
{
{
	const struct nouveau_i2c_impl *impl = (void *)oclass;
	struct nouveau_bios *bios = nouveau_bios(parent);
	struct nouveau_bios *bios = nouveau_bios(parent);
	struct nouveau_i2c *i2c;
	struct nouveau_i2c *i2c;
	struct nouveau_object *object;
	struct nouveau_object *object;
	struct dcb_i2c_entry info;
	struct dcb_i2c_entry info;
	int ret, i, j, index = -1, pad;
	int ret, i, j, index = -1;
	struct dcb_output outp;
	struct dcb_output outp;
	u8  ver, hdr;
	u8  ver, hdr;
	u32 data;
	u32 data;
@@ -507,36 +545,17 @@ nouveau_i2c_create_(struct nouveau_object *parent,
	INIT_LIST_HEAD(&i2c->ports);
	INIT_LIST_HEAD(&i2c->ports);


	while (!dcb_i2c_parse(bios, ++index, &info)) {
	while (!dcb_i2c_parse(bios, ++index, &info)) {
		if (info.type == DCB_I2C_UNUSED)
		switch (info.type) {
			continue;
		case DCB_I2C_NV04_BIT:

		case DCB_I2C_NV4E_BIT:
		if (info.share != DCB_I2C_UNUSED) {
		case DCB_I2C_NVIO_BIT:
			if (info.type == DCB_I2C_NVIO_AUX)
		case DCB_I2C_NVIO_AUX:
				pad = info.drive;
			nouveau_i2c_create_port(i2c, index, info.type, &info);
			else
			break;
				pad = info.share;
		case DCB_I2C_UNUSED:
			oclass = impl->pad_s;
		default:
		} else {
			pad = 0x100 + info.drive;
			oclass = impl->pad_x;
		}

		ret = nouveau_object_ctor(NULL, *pobject, oclass,
					  NULL, pad, &parent);
		if (ret < 0)
			continue;
			continue;

		oclass = impl->sclass;
		do {
			ret = -EINVAL;
			if (oclass->handle == info.type) {
				ret = nouveau_object_ctor(parent, *pobject,
							  oclass, &info,
							  index, &object);
		}
		}
		} while (ret && (++oclass)->handle);

		nouveau_object_ref(NULL, &parent);
	}
	}


	/* in addition to the busses specified in the i2c table, there
	/* in addition to the busses specified in the i2c table, there
+2 −2
Original line number Original line Diff line number Diff line
@@ -238,8 +238,8 @@ nv94_aux_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
	if (ret)
	if (ret)
		return ret;
		return ret;


	port->base.aux = info->drive;
	port->base.aux = info->auxch;
	port->addr = info->drive;
	port->addr = info->auxch;
	return 0;
	return 0;
}
}