Merge branch 'drm-nouveau-fixes-3.8' of git://anongit.freedesktop.org/git/nouveau/linux-2.6 into drm-next

Fixes the accel support for nvd9 + kepler chipsets, also fixes GK106 support.

* 'drm-nouveau-fixes-3.8' of git://anongit.freedesktop.org/git/nouveau/linux-2.6:
  drm/nve0/graph: fix fuc, and enable acceleration on all known chipsets
  drm/nvc0/graph: fix fuc, and enable acceleration on GF119
  drm/nouveau/bios: cache ramcfg strap on later chipsets
  drm/nouveau/mxm: silence output if no bios data
  drm/nouveau/bios: parse/display extra version component
  drm/nouveau/bios: implement opcode 0xa9
  drm/nouveau/bios: update gpio parsing apis to match current design
  drm/nouveau: initial support for GK106
This commit is contained in:
Dave Airlie 2012-12-30 13:01:52 +10:00
commit 344f9067d5
21 changed files with 392 additions and 245 deletions

View file

@ -57,6 +57,11 @@ chipsets:
.b16 #nve4_gpc_mmio_tail
.b16 #nve4_tpc_mmio_head
.b16 #nve4_tpc_mmio_tail
.b8 0xe6 0 0 0
.b16 #nve4_gpc_mmio_head
.b16 #nve4_gpc_mmio_tail
.b16 #nve4_tpc_mmio_head
.b16 #nve4_tpc_mmio_tail
.b8 0 0 0 0
// GPC mmio lists

View file

@ -34,13 +34,16 @@ uint32_t nve0_grgpc_data[] = {
0x00000000,
/* 0x0064: chipsets */
0x000000e4,
0x01040080,
0x014c0104,
0x0110008c,
0x01580110,
0x000000e7,
0x01040080,
0x014c0104,
0x0110008c,
0x01580110,
0x000000e6,
0x0110008c,
0x01580110,
0x00000000,
/* 0x0080: nve4_gpc_mmio_head */
/* 0x008c: nve4_gpc_mmio_head */
0x00000380,
0x04000400,
0x0800040c,
@ -74,8 +77,8 @@ uint32_t nve0_grgpc_data[] = {
0x14003100,
0x000031d0,
0x040031e0,
/* 0x0104: nve4_gpc_mmio_tail */
/* 0x0104: nve4_tpc_mmio_head */
/* 0x0110: nve4_gpc_mmio_tail */
/* 0x0110: nve4_tpc_mmio_head */
0x00000048,
0x00000064,
0x00000088,

View file

@ -754,6 +754,16 @@ ctx_mmio_exec:
// on load it means: "a save preceeded this load"
//
ctx_xfer:
// according to mwk, some kind of wait for idle
mov $r15 0xc00
shl b32 $r15 6
mov $r14 4
iowr I[$r15 + 0x200] $r14
ctx_xfer_idle:
iord $r14 I[$r15 + 0x000]
and $r14 0x2000
bra ne #ctx_xfer_idle
bra not $p1 #ctx_xfer_pre
bra $p2 #ctx_xfer_pre_load
ctx_xfer_pre:

View file

@ -799,79 +799,80 @@ uint32_t nvc0_grhub_code[] = {
0x01fa0613,
0xf803f806,
/* 0x0829: ctx_xfer */
0x0611f400,
/* 0x082f: ctx_xfer_pre */
0xf01102f4,
0x21f510f7,
0x21f50698,
0x11f40631,
/* 0x083d: ctx_xfer_pre_load */
0x02f7f01c,
0x065721f5,
0x066621f5,
0x067821f5,
0x21f5f4bd,
0x21f50657,
/* 0x0856: ctx_xfer_exec */
0x019806b8,
0x1427f116,
0x0624b604,
0xf10020d0,
0xf0a500e7,
0x1fb941e3,
0x8d21f402,
0xf004e0b6,
0x2cf001fc,
0x0124b602,
0xf405f2fd,
0x17f18d21,
0x13f04afc,
0x0c27f002,
0xf50012d0,
0xf1020721,
0xf047fc27,
0x20d00223,
0x012cf000,
0xd00320b6,
0xacf00012,
0x06a5f001,
0x9800b7f0,
0x0d98140c,
0x00e7f015,
0x015c21f5,
0xf508a7f0,
0xf5010321,
0xf4020721,
0xa7f02201,
0xc921f40c,
0x0a1017f1,
0xf00614b6,
0x12d00527,
/* 0x08dd: ctx_xfer_post_save_wait */
0x0012cf00,
0xf40522fd,
0x02f4fa1b,
/* 0x08e9: ctx_xfer_post */
0x02f7f032,
0x065721f5,
0x21f5f4bd,
0x21f50698,
0x21f50226,
0xf4bd0666,
0x065721f5,
0x981011f4,
0x11fd8001,
0x070bf405,
0x07df21f5,
/* 0x0914: ctx_xfer_no_post_mmio */
0x064921f5,
/* 0x0918: ctx_xfer_done */
0x000000f8,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00f7f100,
0x06f4b60c,
0xd004e7f0,
/* 0x0836: ctx_xfer_idle */
0xfecf80fe,
0x00e4f100,
0xf91bf420,
0xf40611f4,
/* 0x0846: ctx_xfer_pre */
0xf7f01102,
0x9821f510,
0x3121f506,
0x1c11f406,
/* 0x0854: ctx_xfer_pre_load */
0xf502f7f0,
0xf5065721,
0xf5066621,
0xbd067821,
0x5721f5f4,
0xb821f506,
/* 0x086d: ctx_xfer_exec */
0x16019806,
0x041427f1,
0xd00624b6,
0xe7f10020,
0xe3f0a500,
0x021fb941,
0xb68d21f4,
0xfcf004e0,
0x022cf001,
0xfd0124b6,
0x21f405f2,
0xfc17f18d,
0x0213f04a,
0xd00c27f0,
0x21f50012,
0x27f10207,
0x23f047fc,
0x0020d002,
0xb6012cf0,
0x12d00320,
0x01acf000,
0xf006a5f0,
0x0c9800b7,
0x150d9814,
0xf500e7f0,
0xf0015c21,
0x21f508a7,
0x21f50103,
0x01f40207,
0x0ca7f022,
0xf1c921f4,
0xb60a1017,
0x27f00614,
0x0012d005,
/* 0x08f4: ctx_xfer_post_save_wait */
0xfd0012cf,
0x1bf40522,
0x3202f4fa,
/* 0x0900: ctx_xfer_post */
0xf502f7f0,
0xbd065721,
0x9821f5f4,
0x2621f506,
0x6621f502,
0xf5f4bd06,
0xf4065721,
0x01981011,
0x0511fd80,
0xf5070bf4,
/* 0x092b: ctx_xfer_no_post_mmio */
0xf507df21,
/* 0x092f: ctx_xfer_done */
0xf8064921,
0x00000000,
0x00000000,
0x00000000,

View file

@ -44,6 +44,9 @@ chipsets:
.b8 0xe7 0 0 0
.b16 #nve4_hub_mmio_head
.b16 #nve4_hub_mmio_tail
.b8 0xe6 0 0 0
.b16 #nve4_hub_mmio_head
.b16 #nve4_hub_mmio_tail
.b8 0 0 0 0
nve4_hub_mmio_head:
@ -680,6 +683,16 @@ ctx_mmio_exec:
// on load it means: "a save preceeded this load"
//
ctx_xfer:
// according to mwk, some kind of wait for idle
mov $r15 0xc00
shl b32 $r15 6
mov $r14 4
iowr I[$r15 + 0x200] $r14
ctx_xfer_idle:
iord $r14 I[$r15 + 0x000]
and $r14 0x2000
bra ne #ctx_xfer_idle
bra not $p1 #ctx_xfer_pre
bra $p2 #ctx_xfer_pre_load
ctx_xfer_pre:

View file

@ -30,11 +30,13 @@ uint32_t nve0_grhub_data[] = {
0x00000000,
/* 0x005c: chipsets */
0x000000e4,
0x013c0070,
0x01440078,
0x000000e7,
0x013c0070,
0x01440078,
0x000000e6,
0x01440078,
0x00000000,
/* 0x0070: nve4_hub_mmio_head */
/* 0x0078: nve4_hub_mmio_head */
0x0417e91c,
0x04400204,
0x18404010,
@ -86,9 +88,7 @@ uint32_t nve0_grhub_data[] = {
0x00408840,
0x08408900,
0x00408980,
/* 0x013c: nve4_hub_mmio_tail */
0x00000000,
0x00000000,
/* 0x0144: nve4_hub_mmio_tail */
0x00000000,
0x00000000,
0x00000000,
@ -781,77 +781,78 @@ uint32_t nve0_grhub_code[] = {
0x0613f002,
0xf80601fa,
/* 0x07fb: ctx_xfer */
0xf400f803,
0x02f40611,
/* 0x0801: ctx_xfer_pre */
0x10f7f00d,
0x067221f5,
/* 0x080b: ctx_xfer_pre_load */
0xf01c11f4,
0x21f502f7,
0x21f50631,
0x21f50640,
0xf4bd0652,
0x063121f5,
0x069221f5,
/* 0x0824: ctx_xfer_exec */
0xf1160198,
0xb6041427,
0x20d00624,
0x00e7f100,
0x41e3f0a5,
0xf4021fb9,
0xe0b68d21,
0x01fcf004,
0xb6022cf0,
0xf2fd0124,
0x8d21f405,
0x4afc17f1,
0xf00213f0,
0x12d00c27,
0x0721f500,
0xfc27f102,
0x0223f047,
0xf00020d0,
0x20b6012c,
0x0012d003,
0xf001acf0,
0xb7f006a5,
0x140c9800,
0xf0150d98,
0x21f500e7,
0xa7f0015c,
0x0321f508,
0x0721f501,
0x2201f402,
0xf40ca7f0,
0x17f1c921,
0x14b60a10,
0x0527f006,
/* 0x08ab: ctx_xfer_post_save_wait */
0xcf0012d0,
0x22fd0012,
0xfa1bf405,
/* 0x08b7: ctx_xfer_post */
0xf02e02f4,
0x21f502f7,
0xf4bd0631,
0x067221f5,
0x022621f5,
0x064021f5,
0x21f5f4bd,
0x11f40631,
0x80019810,
0xf40511fd,
0x21f5070b,
/* 0x08e2: ctx_xfer_no_post_mmio */
/* 0x08e2: ctx_xfer_done */
0x00f807b1,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0xf100f803,
0xb60c00f7,
0xe7f006f4,
0x80fed004,
/* 0x0808: ctx_xfer_idle */
0xf100fecf,
0xf42000e4,
0x11f4f91b,
0x0d02f406,
/* 0x0818: ctx_xfer_pre */
0xf510f7f0,
0xf4067221,
/* 0x0822: ctx_xfer_pre_load */
0xf7f01c11,
0x3121f502,
0x4021f506,
0x5221f506,
0xf5f4bd06,
0xf5063121,
/* 0x083b: ctx_xfer_exec */
0x98069221,
0x27f11601,
0x24b60414,
0x0020d006,
0xa500e7f1,
0xb941e3f0,
0x21f4021f,
0x04e0b68d,
0xf001fcf0,
0x24b6022c,
0x05f2fd01,
0xf18d21f4,
0xf04afc17,
0x27f00213,
0x0012d00c,
0x020721f5,
0x47fc27f1,
0xd00223f0,
0x2cf00020,
0x0320b601,
0xf00012d0,
0xa5f001ac,
0x00b7f006,
0x98140c98,
0xe7f0150d,
0x5c21f500,
0x08a7f001,
0x010321f5,
0x020721f5,
0xf02201f4,
0x21f40ca7,
0x1017f1c9,
0x0614b60a,
0xd00527f0,
/* 0x08c2: ctx_xfer_post_save_wait */
0x12cf0012,
0x0522fd00,
0xf4fa1bf4,
/* 0x08ce: ctx_xfer_post */
0xf7f02e02,
0x3121f502,
0xf5f4bd06,
0xf5067221,
0xf5022621,
0xbd064021,
0x3121f5f4,
0x1011f406,
0xfd800198,
0x0bf40511,
0xb121f507,
/* 0x08f9: ctx_xfer_no_post_mmio */
/* 0x08f9: ctx_xfer_done */
0x0000f807,
0x00000000,
};

View file

@ -516,18 +516,9 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
{
struct nouveau_device *device = nv_device(parent);
struct nvc0_graph_priv *priv;
bool enable = true;
int ret, i;
switch (device->chipset) {
case 0xd9: /* known broken without binary driver firmware */
enable = false;
break;
default:
break;
}
ret = nouveau_graph_create(parent, engine, oclass, enable, &priv);
ret = nouveau_graph_create(parent, engine, oclass, true, &priv);
*pobject = nv_object(priv);
if (ret)
return ret;

View file

@ -121,6 +121,7 @@ nvc0_graph_class(void *obj)
return 0x9297;
case 0xe4:
case 0xe7:
case 0xe6:
return 0xa097;
default:
return 0;

View file

@ -203,7 +203,7 @@ nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nvc0_graph_priv *priv;
int ret, i;
ret = nouveau_graph_create(parent, engine, oclass, false, &priv);
ret = nouveau_graph_create(parent, engine, oclass, true, &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
@ -252,6 +252,7 @@ nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv->magic_not_rop_nr = 1;
break;
case 0xe7:
case 0xe6:
priv->magic_not_rop_nr = 1;
break;
default:

View file

@ -17,6 +17,7 @@ struct nouveau_bios {
u8 chip;
u8 minor;
u8 micro;
u8 patch;
} version;
};

View file

@ -25,9 +25,11 @@ struct dcb_gpio_func {
u8 param;
};
u16 dcb_gpio_table(struct nouveau_bios *);
u16 dcb_gpio_entry(struct nouveau_bios *, int idx, int ent, u8 *ver);
int dcb_gpio_parse(struct nouveau_bios *, int idx, u8 func, u8 line,
u16 dcb_gpio_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
u16 dcb_gpio_entry(struct nouveau_bios *, int idx, int ent, u8 *ver, u8 *len);
u16 dcb_gpio_parse(struct nouveau_bios *, int idx, int ent, u8 *ver, u8 *len,
struct dcb_gpio_func *);
u16 dcb_gpio_match(struct nouveau_bios *, int idx, u8 func, u8 line,
u8 *ver, u8 *len, struct dcb_gpio_func *);
#endif

View file

@ -13,6 +13,7 @@ struct nvbios_init {
u32 nested;
u16 repeat;
u16 repend;
u32 ramcfg;
};
int nvbios_exec(struct nvbios_init *);

View file

@ -11,7 +11,7 @@ struct nouveau_gpio {
struct nouveau_subdev base;
/* hardware interfaces */
void (*reset)(struct nouveau_gpio *);
void (*reset)(struct nouveau_gpio *, u8 func);
int (*drive)(struct nouveau_gpio *, int line, int dir, int out);
int (*sense)(struct nouveau_gpio *, int line);
void (*irq_enable)(struct nouveau_gpio *, int line, bool);

View file

@ -447,6 +447,7 @@ nouveau_bios_ctor(struct nouveau_object *parent,
bios->version.chip = nv_ro08(bios, bit_i.offset + 2);
bios->version.minor = nv_ro08(bios, bit_i.offset + 1);
bios->version.micro = nv_ro08(bios, bit_i.offset + 0);
bios->version.patch = nv_ro08(bios, bit_i.offset + 4);
} else
if (bmp_version(bios)) {
bios->version.major = nv_ro08(bios, bios->bmp_offset + 13);
@ -455,9 +456,9 @@ nouveau_bios_ctor(struct nouveau_object *parent,
bios->version.micro = nv_ro08(bios, bios->bmp_offset + 10);
}
nv_info(bios, "version %02x.%02x.%02x.%02x\n",
nv_info(bios, "version %02x.%02x.%02x.%02x.%02x\n",
bios->version.major, bios->version.chip,
bios->version.minor, bios->version.micro);
bios->version.minor, bios->version.micro, bios->version.patch);
return 0;
}

View file

@ -27,84 +27,105 @@
#include <subdev/bios/gpio.h>
u16
dcb_gpio_table(struct nouveau_bios *bios)
dcb_gpio_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
{
u8 ver, hdr, cnt, len;
u16 dcb = dcb_table(bios, &ver, &hdr, &cnt, &len);
u16 data = 0x0000;
u16 dcb = dcb_table(bios, ver, hdr, cnt, len);
if (dcb) {
if (ver >= 0x30 && hdr >= 0x0c)
return nv_ro16(bios, dcb + 0x0a);
if (ver >= 0x22 && nv_ro08(bios, dcb - 1) >= 0x13)
return nv_ro16(bios, dcb - 0x0f);
if (*ver >= 0x30 && *hdr >= 0x0c)
data = nv_ro16(bios, dcb + 0x0a);
else
if (*ver >= 0x22 && nv_ro08(bios, dcb - 1) >= 0x13)
data = nv_ro16(bios, dcb - 0x0f);
if (data) {
*ver = nv_ro08(bios, data + 0x00);
if (*ver < 0x30) {
*hdr = 3;
*cnt = nv_ro08(bios, data + 0x02);
*len = nv_ro08(bios, data + 0x01);
} else
if (*ver <= 0x41) {
*hdr = nv_ro08(bios, data + 0x01);
*cnt = nv_ro08(bios, data + 0x02);
*len = nv_ro08(bios, data + 0x03);
} else {
data = 0x0000;
}
}
}
return data;
}
u16
dcb_gpio_entry(struct nouveau_bios *bios, int idx, int ent, u8 *ver, u8 *len)
{
u8 hdr, cnt;
u16 gpio = !idx ? dcb_gpio_table(bios, ver, &hdr, &cnt, len) : 0x0000;
if (gpio && ent < cnt)
return gpio + hdr + (ent * *len);
return 0x0000;
}
u16
dcb_gpio_entry(struct nouveau_bios *bios, int idx, int ent, u8 *ver)
{
u16 gpio = dcb_gpio_table(bios);
if (gpio) {
*ver = nv_ro08(bios, gpio);
if (*ver < 0x30 && ent < nv_ro08(bios, gpio + 2))
return gpio + 3 + (ent * nv_ro08(bios, gpio + 1));
else if (ent < nv_ro08(bios, gpio + 2))
return gpio + nv_ro08(bios, gpio + 1) +
(ent * nv_ro08(bios, gpio + 3));
}
return 0x0000;
}
int
dcb_gpio_parse(struct nouveau_bios *bios, int idx, u8 func, u8 line,
dcb_gpio_parse(struct nouveau_bios *bios, int idx, int ent, u8 *ver, u8 *len,
struct dcb_gpio_func *gpio)
{
u8 ver, hdr, cnt, len;
u16 entry;
int i = -1;
while ((entry = dcb_gpio_entry(bios, idx, ++i, &ver))) {
if (ver < 0x40) {
u16 data = nv_ro16(bios, entry);
u16 data = dcb_gpio_entry(bios, idx, ent, ver, len);
if (data) {
if (*ver < 0x40) {
u16 info = nv_ro16(bios, data);
*gpio = (struct dcb_gpio_func) {
.line = (data & 0x001f) >> 0,
.func = (data & 0x07e0) >> 5,
.log[0] = (data & 0x1800) >> 11,
.log[1] = (data & 0x6000) >> 13,
.param = !!(data & 0x8000),
.line = (info & 0x001f) >> 0,
.func = (info & 0x07e0) >> 5,
.log[0] = (info & 0x1800) >> 11,
.log[1] = (info & 0x6000) >> 13,
.param = !!(info & 0x8000),
};
} else
if (ver < 0x41) {
u32 data = nv_ro32(bios, entry);
if (*ver < 0x41) {
u32 info = nv_ro32(bios, data);
*gpio = (struct dcb_gpio_func) {
.line = (data & 0x0000001f) >> 0,
.func = (data & 0x0000ff00) >> 8,
.log[0] = (data & 0x18000000) >> 27,
.log[1] = (data & 0x60000000) >> 29,
.param = !!(data & 0x80000000),
.line = (info & 0x0000001f) >> 0,
.func = (info & 0x0000ff00) >> 8,
.log[0] = (info & 0x18000000) >> 27,
.log[1] = (info & 0x60000000) >> 29,
.param = !!(info & 0x80000000),
};
} else {
u32 data = nv_ro32(bios, entry + 0);
u8 data1 = nv_ro32(bios, entry + 4);
u32 info = nv_ro32(bios, data + 0);
u8 info1 = nv_ro32(bios, data + 4);
*gpio = (struct dcb_gpio_func) {
.line = (data & 0x0000003f) >> 0,
.func = (data & 0x0000ff00) >> 8,
.log[0] = (data1 & 0x30) >> 4,
.log[1] = (data1 & 0xc0) >> 6,
.param = !!(data & 0x80000000),
.line = (info & 0x0000003f) >> 0,
.func = (info & 0x0000ff00) >> 8,
.log[0] = (info1 & 0x30) >> 4,
.log[1] = (info1 & 0xc0) >> 6,
.param = !!(info & 0x80000000),
};
}
}
return data;
}
u16
dcb_gpio_match(struct nouveau_bios *bios, int idx, u8 func, u8 line,
u8 *ver, u8 *len, struct dcb_gpio_func *gpio)
{
u8 hdr, cnt, i = 0;
u16 data;
while ((data = dcb_gpio_parse(bios, idx, i++, ver, len, gpio))) {
if ((line == 0xff || line == gpio->line) &&
(func == 0xff || func == gpio->func))
return 0;
return data;
}
/* DCB 2.2, fixed TVDAC GPIO data */
if ((entry = dcb_table(bios, &ver, &hdr, &cnt, &len))) {
if (ver >= 0x22 && ver < 0x30 && func == DCB_GPIO_TVDAC0) {
u8 conf = nv_ro08(bios, entry - 5);
u8 addr = nv_ro08(bios, entry - 4);
if ((data = dcb_table(bios, ver, &hdr, &cnt, len))) {
if (*ver >= 0x22 && *ver < 0x30 && func == DCB_GPIO_TVDAC0) {
u8 conf = nv_ro08(bios, data - 5);
u8 addr = nv_ro08(bios, data - 4);
if (conf & 0x01) {
*gpio = (struct dcb_gpio_func) {
.func = DCB_GPIO_TVDAC0,
@ -112,10 +133,11 @@ dcb_gpio_parse(struct nouveau_bios *bios, int idx, u8 func, u8 line,
.log[0] = !!(conf & 0x02),
.log[1] = !(conf & 0x02),
};
return 0;
*ver = 0x00;
return data;
}
}
}
return -EINVAL;
return 0x0000;
}

View file

@ -2,11 +2,12 @@
#include <core/device.h>
#include <subdev/bios.h>
#include <subdev/bios/conn.h>
#include <subdev/bios/bmp.h>
#include <subdev/bios/bit.h>
#include <subdev/bios/conn.h>
#include <subdev/bios/dcb.h>
#include <subdev/bios/dp.h>
#include <subdev/bios/gpio.h>
#include <subdev/bios/init.h>
#include <subdev/devinit.h>
#include <subdev/clock.h>
@ -409,10 +410,26 @@ init_ram_restrict_group_count(struct nvbios_init *init)
return 0x00;
}
static u8
init_ram_restrict_strap(struct nvbios_init *init)
{
/* This appears to be the behaviour of the VBIOS parser, and *is*
* important to cache the NV_PEXTDEV_BOOT0 on later chipsets to
* avoid fucking up the memory controller (somehow) by reading it
* on every INIT_RAM_RESTRICT_ZM_GROUP opcode.
*
* Preserving the non-caching behaviour on earlier chipsets just
* in case *not* re-reading the strap causes similar breakage.
*/
if (!init->ramcfg || init->bios->version.major < 0x70)
init->ramcfg = init_rd32(init, 0x101000);
return (init->ramcfg & 0x00000003c) >> 2;
}
static u8
init_ram_restrict(struct nvbios_init *init)
{
u32 strap = (init_rd32(init, 0x101000) & 0x0000003c) >> 2;
u8 strap = init_ram_restrict_strap(init);
u16 table = init_ram_restrict_table(init);
if (table)
return nv_ro08(init->bios, table + strap);
@ -1781,7 +1798,7 @@ init_gpio(struct nvbios_init *init)
init->offset += 1;
if (init_exec(init) && gpio && gpio->reset)
gpio->reset(gpio);
gpio->reset(gpio, DCB_GPIO_UNUSED);
}
/**
@ -1995,6 +2012,47 @@ init_i2c_long_if(struct nvbios_init *init)
init_exec_set(init, false);
}
/**
* INIT_GPIO_NE - opcode 0xa9
*
*/
static void
init_gpio_ne(struct nvbios_init *init)
{
struct nouveau_bios *bios = init->bios;
struct nouveau_gpio *gpio = nouveau_gpio(bios);
struct dcb_gpio_func func;
u8 count = nv_ro08(bios, init->offset + 1);
u8 idx = 0, ver, len;
u16 data, i;
trace("GPIO_NE\t");
init->offset += 2;
for (i = init->offset; i < init->offset + count; i++)
cont("0x%02x ", nv_ro08(bios, i));
cont("\n");
while ((data = dcb_gpio_parse(bios, 0, idx++, &ver, &len, &func))) {
if (func.func != DCB_GPIO_UNUSED) {
for (i = init->offset; i < init->offset + count; i++) {
if (func.func == nv_ro08(bios, i))
break;
}
trace("\tFUNC[0x%02x]", func.func);
if (i == (init->offset + count)) {
cont(" *");
if (init_exec(init) && gpio && gpio->reset)
gpio->reset(gpio, func.func);
}
cont("\n");
}
}
init->offset += count;
}
static struct nvbios_init_opcode {
void (*exec)(struct nvbios_init *);
} init_opcode[] = {
@ -2059,6 +2117,7 @@ static struct nvbios_init_opcode {
[0x98] = { init_auxch },
[0x99] = { init_zm_auxch },
[0x9a] = { init_i2c_long_if },
[0xa9] = { init_gpio_ne },
};
#define init_opcode_nr (sizeof(init_opcode) / sizeof(init_opcode[0]))

View file

@ -109,6 +109,34 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass;
device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
break;
case 0xe6:
device->cname = "GK106";
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass;
device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass;
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = &nve0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nve0_graph_oclass;
device->oclass[NVDEV_ENGINE_DISP ] = &nve0_disp_oclass;
device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass;
device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass;
device->oclass[NVDEV_ENGINE_BSP ] = &nve0_bsp_oclass;
device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass;
device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
break;
default:
nv_fatal(device, "unknown Kepler chipset\n");
return -EINVAL;

View file

@ -43,10 +43,15 @@ static int
nouveau_gpio_find(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line,
struct dcb_gpio_func *func)
{
struct nouveau_bios *bios = nouveau_bios(gpio);
u8 ver, len;
u16 data;
if (line == 0xff && tag == 0xff)
return -EINVAL;
if (!dcb_gpio_parse(nouveau_bios(gpio), idx, tag, line, func))
data = dcb_gpio_match(bios, idx, tag, line, &ver, &len, func);
if (data)
return 0;
/* Apple iMac G4 NV18 */
@ -265,7 +270,7 @@ nouveau_gpio_init(struct nouveau_gpio *gpio)
int ret = nouveau_subdev_init(&gpio->base);
if (ret == 0 && gpio->reset) {
if (dmi_check_system(gpio_reset_ids))
gpio->reset(gpio);
gpio->reset(gpio, DCB_GPIO_UNUSED);
}
return ret;
}

View file

@ -29,15 +29,15 @@ struct nv50_gpio_priv {
};
static void
nv50_gpio_reset(struct nouveau_gpio *gpio)
nv50_gpio_reset(struct nouveau_gpio *gpio, u8 match)
{
struct nouveau_bios *bios = nouveau_bios(gpio);
struct nv50_gpio_priv *priv = (void *)gpio;
u8 ver, len;
u16 entry;
u8 ver;
int ent = -1;
while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver))) {
while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver, &len))) {
static const u32 regs[] = { 0xe100, 0xe28c };
u32 data = nv_ro32(bios, entry);
u8 line = (data & 0x0000001f);
@ -48,7 +48,8 @@ nv50_gpio_reset(struct nouveau_gpio *gpio)
u32 val = (unk1 << 16) | unk0;
u32 reg = regs[line >> 4]; line &= 0x0f;
if (func == 0xff)
if ( func == DCB_GPIO_UNUSED ||
(match != DCB_GPIO_UNUSED && match != func))
continue;
gpio->set(gpio, 0, func, line, defs);

View file

@ -29,15 +29,15 @@ struct nvd0_gpio_priv {
};
static void
nvd0_gpio_reset(struct nouveau_gpio *gpio)
nvd0_gpio_reset(struct nouveau_gpio *gpio, u8 match)
{
struct nouveau_bios *bios = nouveau_bios(gpio);
struct nvd0_gpio_priv *priv = (void *)gpio;
u8 ver, len;
u16 entry;
u8 ver;
int ent = -1;
while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver))) {
while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver, &len))) {
u32 data = nv_ro32(bios, entry);
u8 line = (data & 0x0000003f);
u8 defs = !!(data & 0x00000080);
@ -45,7 +45,8 @@ nvd0_gpio_reset(struct nouveau_gpio *gpio)
u8 unk0 = (data & 0x00ff0000) >> 16;
u8 unk1 = (data & 0x1f000000) >> 24;
if (func == 0xff)
if ( func == DCB_GPIO_UNUSED ||
(match != DCB_GPIO_UNUSED && match != func))
continue;
gpio->set(gpio, 0, func, line, defs);

View file

@ -260,7 +260,7 @@ nouveau_mxm_create_(struct nouveau_object *parent,
data = mxm_table(bios, &ver, &len);
if (!data || !(ver = nv_ro08(bios, data))) {
nv_info(mxm, "no VBIOS data, nothing to do\n");
nv_debug(mxm, "no VBIOS data, nothing to do\n");
return 0;
}