drm/nouveau/bios: store aux addr independently of i2c
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
Родитель
a7468451e3
Коммит
309a5702c2
|
@ -16,6 +16,7 @@ struct dcb_i2c_entry {
|
|||
u8 drive;
|
||||
u8 sense;
|
||||
u8 share;
|
||||
u8 auxch;
|
||||
};
|
||||
|
||||
u16 dcb_i2c_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
if (i2c && *ver >= 0x41) {
|
||||
nv_warn(bios, "ccb %02x not supported\n", *ver);
|
||||
return 0x0000;
|
||||
}
|
||||
|
||||
if (i2c && *ver >= 0x30) {
|
||||
*ver = nv_ro08(bios, i2c + 0);
|
||||
*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;
|
||||
u16 ent = dcb_i2c_entry(bios, idx, &ver, &len);
|
||||
if (ent) {
|
||||
info->type = nv_ro08(bios, ent + 3);
|
||||
info->share = DCB_I2C_UNUSED;
|
||||
if (ver < 0x30) {
|
||||
info->type &= 0x07;
|
||||
if (ver >= 0x30) {
|
||||
info->type = nv_ro08(bios, ent + 0x03);
|
||||
} else {
|
||||
info->type = nv_ro08(bios, ent + 0x03) & 0x07;
|
||||
if (info->type == 0x07)
|
||||
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) {
|
||||
case DCB_I2C_NV04_BIT:
|
||||
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);
|
||||
return 0;
|
||||
case DCB_I2C_NVIO_BIT:
|
||||
case DCB_I2C_NVIO_AUX:
|
||||
info->drive = nv_ro08(bios, ent + 0) & 0x0f;
|
||||
if (nv_ro08(bios, ent + 1) & 0x01) {
|
||||
info->share = nv_ro08(bios, ent + 1) >> 1;
|
||||
info->share &= 0x0f;
|
||||
}
|
||||
if (nv_ro08(bios, ent + 1) & 0x01)
|
||||
info->share = nv_ro08(bios, ent + 1) >> 1;
|
||||
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;
|
||||
case DCB_I2C_UNUSED:
|
||||
return 0;
|
||||
|
|
|
@ -473,18 +473,56 @@ nouveau_i2c_extdev_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
|
||||
nouveau_i2c_create_(struct nouveau_object *parent,
|
||||
struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass,
|
||||
int length, void **pobject)
|
||||
{
|
||||
const struct nouveau_i2c_impl *impl = (void *)oclass;
|
||||
struct nouveau_bios *bios = nouveau_bios(parent);
|
||||
struct nouveau_i2c *i2c;
|
||||
struct nouveau_object *object;
|
||||
struct dcb_i2c_entry info;
|
||||
int ret, i, j, index = -1, pad;
|
||||
int ret, i, j, index = -1;
|
||||
struct dcb_output outp;
|
||||
u8 ver, hdr;
|
||||
u32 data;
|
||||
|
@ -507,36 +545,17 @@ nouveau_i2c_create_(struct nouveau_object *parent,
|
|||
INIT_LIST_HEAD(&i2c->ports);
|
||||
|
||||
while (!dcb_i2c_parse(bios, ++index, &info)) {
|
||||
if (info.type == DCB_I2C_UNUSED)
|
||||
switch (info.type) {
|
||||
case DCB_I2C_NV04_BIT:
|
||||
case DCB_I2C_NV4E_BIT:
|
||||
case DCB_I2C_NVIO_BIT:
|
||||
case DCB_I2C_NVIO_AUX:
|
||||
nouveau_i2c_create_port(i2c, index, info.type, &info);
|
||||
break;
|
||||
case DCB_I2C_UNUSED:
|
||||
default:
|
||||
continue;
|
||||
|
||||
if (info.share != DCB_I2C_UNUSED) {
|
||||
if (info.type == DCB_I2C_NVIO_AUX)
|
||||
pad = info.drive;
|
||||
else
|
||||
pad = info.share;
|
||||
oclass = impl->pad_s;
|
||||
} else {
|
||||
pad = 0x100 + info.drive;
|
||||
oclass = impl->pad_x;
|
||||
}
|
||||
|
||||
ret = nouveau_object_ctor(NULL, *pobject, oclass,
|
||||
NULL, pad, &parent);
|
||||
if (ret < 0)
|
||||
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
|
||||
|
|
|
@ -238,8 +238,8 @@ nv94_aux_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
port->base.aux = info->drive;
|
||||
port->addr = info->drive;
|
||||
port->base.aux = info->auxch;
|
||||
port->addr = info->auxch;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче