Commit 344f9067 authored by Dave Airlie's avatar Dave Airlie

Merge branch 'drm-nouveau-fixes-3.8' of...

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
parents a49f0d1e eca15296
...@@ -57,6 +57,11 @@ chipsets: ...@@ -57,6 +57,11 @@ chipsets:
.b16 #nve4_gpc_mmio_tail .b16 #nve4_gpc_mmio_tail
.b16 #nve4_tpc_mmio_head .b16 #nve4_tpc_mmio_head
.b16 #nve4_tpc_mmio_tail .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 .b8 0 0 0 0
// GPC mmio lists // GPC mmio lists
......
...@@ -34,13 +34,16 @@ uint32_t nve0_grgpc_data[] = { ...@@ -34,13 +34,16 @@ uint32_t nve0_grgpc_data[] = {
0x00000000, 0x00000000,
/* 0x0064: chipsets */ /* 0x0064: chipsets */
0x000000e4, 0x000000e4,
0x01040080, 0x0110008c,
0x014c0104, 0x01580110,
0x000000e7, 0x000000e7,
0x01040080, 0x0110008c,
0x014c0104, 0x01580110,
0x000000e6,
0x0110008c,
0x01580110,
0x00000000, 0x00000000,
/* 0x0080: nve4_gpc_mmio_head */ /* 0x008c: nve4_gpc_mmio_head */
0x00000380, 0x00000380,
0x04000400, 0x04000400,
0x0800040c, 0x0800040c,
...@@ -74,8 +77,8 @@ uint32_t nve0_grgpc_data[] = { ...@@ -74,8 +77,8 @@ uint32_t nve0_grgpc_data[] = {
0x14003100, 0x14003100,
0x000031d0, 0x000031d0,
0x040031e0, 0x040031e0,
/* 0x0104: nve4_gpc_mmio_tail */ /* 0x0110: nve4_gpc_mmio_tail */
/* 0x0104: nve4_tpc_mmio_head */ /* 0x0110: nve4_tpc_mmio_head */
0x00000048, 0x00000048,
0x00000064, 0x00000064,
0x00000088, 0x00000088,
......
...@@ -754,6 +754,16 @@ ctx_mmio_exec: ...@@ -754,6 +754,16 @@ ctx_mmio_exec:
// on load it means: "a save preceeded this load" // on load it means: "a save preceeded this load"
// //
ctx_xfer: 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 not $p1 #ctx_xfer_pre
bra $p2 #ctx_xfer_pre_load bra $p2 #ctx_xfer_pre_load
ctx_xfer_pre: ctx_xfer_pre:
......
...@@ -799,79 +799,80 @@ uint32_t nvc0_grhub_code[] = { ...@@ -799,79 +799,80 @@ uint32_t nvc0_grhub_code[] = {
0x01fa0613, 0x01fa0613,
0xf803f806, 0xf803f806,
/* 0x0829: ctx_xfer */ /* 0x0829: ctx_xfer */
0x0611f400, 0x00f7f100,
/* 0x082f: ctx_xfer_pre */ 0x06f4b60c,
0xf01102f4, 0xd004e7f0,
0x21f510f7, /* 0x0836: ctx_xfer_idle */
0x21f50698, 0xfecf80fe,
0x11f40631, 0x00e4f100,
/* 0x083d: ctx_xfer_pre_load */ 0xf91bf420,
0x02f7f01c, 0xf40611f4,
0x065721f5, /* 0x0846: ctx_xfer_pre */
0x066621f5, 0xf7f01102,
0x067821f5, 0x9821f510,
0x21f5f4bd, 0x3121f506,
0x21f50657, 0x1c11f406,
/* 0x0856: ctx_xfer_exec */ /* 0x0854: ctx_xfer_pre_load */
0x019806b8, 0xf502f7f0,
0x1427f116, 0xf5065721,
0x0624b604, 0xf5066621,
0xf10020d0, 0xbd067821,
0xf0a500e7, 0x5721f5f4,
0x1fb941e3, 0xb821f506,
0x8d21f402, /* 0x086d: ctx_xfer_exec */
0xf004e0b6, 0x16019806,
0x2cf001fc, 0x041427f1,
0x0124b602, 0xd00624b6,
0xf405f2fd, 0xe7f10020,
0x17f18d21, 0xe3f0a500,
0x13f04afc, 0x021fb941,
0x0c27f002, 0xb68d21f4,
0xf50012d0, 0xfcf004e0,
0xf1020721, 0x022cf001,
0xf047fc27, 0xfd0124b6,
0x20d00223, 0x21f405f2,
0x012cf000, 0xfc17f18d,
0xd00320b6, 0x0213f04a,
0xacf00012, 0xd00c27f0,
0x06a5f001, 0x21f50012,
0x9800b7f0, 0x27f10207,
0x0d98140c, 0x23f047fc,
0x00e7f015, 0x0020d002,
0x015c21f5, 0xb6012cf0,
0xf508a7f0, 0x12d00320,
0xf5010321, 0x01acf000,
0xf4020721, 0xf006a5f0,
0xa7f02201, 0x0c9800b7,
0xc921f40c, 0x150d9814,
0x0a1017f1, 0xf500e7f0,
0xf00614b6, 0xf0015c21,
0x12d00527, 0x21f508a7,
/* 0x08dd: ctx_xfer_post_save_wait */ 0x21f50103,
0x0012cf00, 0x01f40207,
0xf40522fd, 0x0ca7f022,
0x02f4fa1b, 0xf1c921f4,
/* 0x08e9: ctx_xfer_post */ 0xb60a1017,
0x02f7f032, 0x27f00614,
0x065721f5, 0x0012d005,
0x21f5f4bd, /* 0x08f4: ctx_xfer_post_save_wait */
0x21f50698, 0xfd0012cf,
0x21f50226, 0x1bf40522,
0xf4bd0666, 0x3202f4fa,
0x065721f5, /* 0x0900: ctx_xfer_post */
0x981011f4, 0xf502f7f0,
0x11fd8001, 0xbd065721,
0x070bf405, 0x9821f5f4,
0x07df21f5, 0x2621f506,
/* 0x0914: ctx_xfer_no_post_mmio */ 0x6621f502,
0x064921f5, 0xf5f4bd06,
/* 0x0918: ctx_xfer_done */ 0xf4065721,
0x000000f8, 0x01981011,
0x00000000, 0x0511fd80,
0x00000000, 0xf5070bf4,
0x00000000, /* 0x092b: ctx_xfer_no_post_mmio */
0x00000000, 0xf507df21,
0x00000000, /* 0x092f: ctx_xfer_done */
0xf8064921,
0x00000000, 0x00000000,
0x00000000, 0x00000000,
0x00000000, 0x00000000,
......
...@@ -44,6 +44,9 @@ chipsets: ...@@ -44,6 +44,9 @@ chipsets:
.b8 0xe7 0 0 0 .b8 0xe7 0 0 0
.b16 #nve4_hub_mmio_head .b16 #nve4_hub_mmio_head
.b16 #nve4_hub_mmio_tail .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 .b8 0 0 0 0
nve4_hub_mmio_head: nve4_hub_mmio_head:
...@@ -680,6 +683,16 @@ ctx_mmio_exec: ...@@ -680,6 +683,16 @@ ctx_mmio_exec:
// on load it means: "a save preceeded this load" // on load it means: "a save preceeded this load"
// //
ctx_xfer: 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 not $p1 #ctx_xfer_pre
bra $p2 #ctx_xfer_pre_load bra $p2 #ctx_xfer_pre_load
ctx_xfer_pre: ctx_xfer_pre:
......
...@@ -30,11 +30,13 @@ uint32_t nve0_grhub_data[] = { ...@@ -30,11 +30,13 @@ uint32_t nve0_grhub_data[] = {
0x00000000, 0x00000000,
/* 0x005c: chipsets */ /* 0x005c: chipsets */
0x000000e4, 0x000000e4,
0x013c0070, 0x01440078,
0x000000e7, 0x000000e7,
0x013c0070, 0x01440078,
0x000000e6,
0x01440078,
0x00000000, 0x00000000,
/* 0x0070: nve4_hub_mmio_head */ /* 0x0078: nve4_hub_mmio_head */
0x0417e91c, 0x0417e91c,
0x04400204, 0x04400204,
0x18404010, 0x18404010,
...@@ -86,9 +88,7 @@ uint32_t nve0_grhub_data[] = { ...@@ -86,9 +88,7 @@ uint32_t nve0_grhub_data[] = {
0x00408840, 0x00408840,
0x08408900, 0x08408900,
0x00408980, 0x00408980,
/* 0x013c: nve4_hub_mmio_tail */ /* 0x0144: nve4_hub_mmio_tail */
0x00000000,
0x00000000,
0x00000000, 0x00000000,
0x00000000, 0x00000000,
0x00000000, 0x00000000,
...@@ -781,77 +781,78 @@ uint32_t nve0_grhub_code[] = { ...@@ -781,77 +781,78 @@ uint32_t nve0_grhub_code[] = {
0x0613f002, 0x0613f002,
0xf80601fa, 0xf80601fa,
/* 0x07fb: ctx_xfer */ /* 0x07fb: ctx_xfer */
0xf400f803, 0xf100f803,
0x02f40611, 0xb60c00f7,
/* 0x0801: ctx_xfer_pre */ 0xe7f006f4,
0x10f7f00d, 0x80fed004,
0x067221f5, /* 0x0808: ctx_xfer_idle */
/* 0x080b: ctx_xfer_pre_load */ 0xf100fecf,
0xf01c11f4, 0xf42000e4,
0x21f502f7, 0x11f4f91b,
0x21f50631, 0x0d02f406,
0x21f50640, /* 0x0818: ctx_xfer_pre */
0xf4bd0652, 0xf510f7f0,
0x063121f5, 0xf4067221,
0x069221f5, /* 0x0822: ctx_xfer_pre_load */
/* 0x0824: ctx_xfer_exec */ 0xf7f01c11,
0xf1160198, 0x3121f502,
0xb6041427, 0x4021f506,
0x20d00624, 0x5221f506,
0x00e7f100, 0xf5f4bd06,
0x41e3f0a5, 0xf5063121,
0xf4021fb9, /* 0x083b: ctx_xfer_exec */
0xe0b68d21, 0x98069221,
0x01fcf004, 0x27f11601,
0xb6022cf0, 0x24b60414,
0xf2fd0124, 0x0020d006,
0x8d21f405, 0xa500e7f1,
0x4afc17f1, 0xb941e3f0,
0xf00213f0, 0x21f4021f,
0x12d00c27, 0x04e0b68d,
0x0721f500, 0xf001fcf0,
0xfc27f102, 0x24b6022c,
0x0223f047, 0x05f2fd01,
0xf00020d0, 0xf18d21f4,
0x20b6012c, 0xf04afc17,
0x0012d003, 0x27f00213,
0xf001acf0, 0x0012d00c,
0xb7f006a5, 0x020721f5,
0x140c9800, 0x47fc27f1,
0xf0150d98, 0xd00223f0,
0x21f500e7, 0x2cf00020,
0xa7f0015c, 0x0320b601,
0x0321f508, 0xf00012d0,
0x0721f501, 0xa5f001ac,
0x2201f402, 0x00b7f006,
0xf40ca7f0, 0x98140c98,
0x17f1c921, 0xe7f0150d,
0x14b60a10, 0x5c21f500,
0x0527f006, 0x08a7f001,
/* 0x08ab: ctx_xfer_post_save_wait */ 0x010321f5,
0xcf0012d0, 0x020721f5,
0x22fd0012, 0xf02201f4,
0xfa1bf405, 0x21f40ca7,
/* 0x08b7: ctx_xfer_post */ 0x1017f1c9,
0xf02e02f4, 0x0614b60a,
0x21f502f7, 0xd00527f0,
0xf4bd0631, /* 0x08c2: ctx_xfer_post_save_wait */
0x067221f5, 0x12cf0012,
0x022621f5, 0x0522fd00,
0x064021f5, 0xf4fa1bf4,
0x21f5f4bd, /* 0x08ce: ctx_xfer_post */
0x11f40631, 0xf7f02e02,
0x80019810, 0x3121f502,
0xf40511fd, 0xf5f4bd06,
0x21f5070b, 0xf5067221,
/* 0x08e2: ctx_xfer_no_post_mmio */ 0xf5022621,
/* 0x08e2: ctx_xfer_done */ 0xbd064021,
0x00f807b1, 0x3121f5f4,
0x00000000, 0x1011f406,
0x00000000, 0xfd800198,
0x00000000, 0x0bf40511,
0x00000000, 0xb121f507,
0x00000000, /* 0x08f9: ctx_xfer_no_post_mmio */
0x00000000, /* 0x08f9: ctx_xfer_done */
0x0000f807,
0x00000000, 0x00000000,
}; };
...@@ -516,18 +516,9 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -516,18 +516,9 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
{ {
struct nouveau_device *device = nv_device(parent); struct nouveau_device *device = nv_device(parent);
struct nvc0_graph_priv *priv; struct nvc0_graph_priv *priv;
bool enable = true;
int ret, i; int ret, i;
switch (device->chipset) { ret = nouveau_graph_create(parent, engine, oclass, true, &priv);
case 0xd9: /* known broken without binary driver firmware */
enable = false;
break;
default:
break;
}
ret = nouveau_graph_create(parent, engine, oclass, enable, &priv);
*pobject = nv_object(priv); *pobject = nv_object(priv);
if (ret) if (ret)
return ret; return ret;
......
...@@ -121,6 +121,7 @@ nvc0_graph_class(void *obj) ...@@ -121,6 +121,7 @@ nvc0_graph_class(void *obj)
return 0x9297; return 0x9297;
case 0xe4: case 0xe4:
case 0xe7: case 0xe7:
case 0xe6:
return 0xa097; return 0xa097;
default: default:
return 0; return 0;
......
...@@ -203,7 +203,7 @@ nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -203,7 +203,7 @@ nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nvc0_graph_priv *priv; struct nvc0_graph_priv *priv;
int ret, i; 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); *pobject = nv_object(priv);
if (ret) if (ret)
return ret; return ret;
...@@ -252,6 +252,7 @@ nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -252,6 +252,7 @@ nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv->magic_not_rop_nr = 1; priv->magic_not_rop_nr = 1;
break; break;
case 0xe7: case 0xe7:
case 0xe6:
priv->magic_not_rop_nr = 1; priv->magic_not_rop_nr = 1;
break; break;
default: default:
......
...@@ -17,6 +17,7 @@ struct nouveau_bios { ...@@ -17,6 +17,7 @@ struct nouveau_bios {
u8 chip; u8 chip;
u8 minor; u8 minor;
u8 micro; u8 micro;
u8 patch;
} version; } version;
}; };
......
...@@ -25,9 +25,11 @@ struct dcb_gpio_func { ...@@ -25,9 +25,11 @@ struct dcb_gpio_func {
u8 param; u8 param;
}; };
u16 dcb_gpio_table(struct nouveau_bios *); 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); u16 dcb_gpio_entry(struct nouveau_bios *, int idx, int ent, u8 *ver, u8 *len);
int dcb_gpio_parse(struct nouveau_bios *, int idx, u8 func, u8 line, u16 dcb_gpio_parse(struct nouveau_bios *, int idx, int ent, u8 *ver, u8 *len,
struct dcb_gpio_func *); 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 #endif
...@@ -13,6 +13,7 @@ struct nvbios_init { ...@@ -13,6 +13,7 @@ struct nvbios_init {
u32 nested; u32 nested;
u16 repeat; u16 repeat;
u16 repend; u16 repend;
u32 ramcfg;
}; };
int nvbios_exec(struct nvbios_init *); int nvbios_exec(struct nvbios_init *);
......
...@@ -11,7 +11,7 @@ struct nouveau_gpio { ...@@ -11,7 +11,7 @@ struct nouveau_gpio {
struct nouveau_subdev base; struct nouveau_subdev base;
/* hardware interfaces */ /* 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 (*drive)(struct nouveau_gpio *, int line, int dir, int out);
int (*sense)(struct nouveau_gpio *, int line); int (*sense)(struct nouveau_gpio *, int line);
void (*irq_enable)(struct nouveau_gpio *, int line, bool); void (*irq_enable)(struct nouveau_gpio *, int line, bool);
......
...@@ -447,6 +447,7 @@ nouveau_bios_ctor(struct nouveau_object *parent, ...@@ -447,6 +447,7 @@ nouveau_bios_ctor(struct nouveau_object *parent,
bios->version.chip = nv_ro08(bios, bit_i.offset + 2); bios->version.chip = nv_ro08(bios, bit_i.offset + 2);
bios->version.minor = nv_ro08(bios, bit_i.offset + 1); bios->version.minor = nv_ro08(bios, bit_i.offset + 1);
bios->version.micro = nv_ro08(bios, bit_i.offset + 0); bios->version.micro = nv_ro08(bios, bit_i.offset + 0);
bios->version.patch = nv_ro08(bios, bit_i.offset + 4);
} else } else
if (bmp_version(bios)) { if (bmp_version(bios)) {
bios->version.major = nv_ro08(bios, bios->bmp_offset + 13); bios->version.major = nv_ro08(bios, bios->bmp_offset + 13);
...@@ -455,9 +456,9 @@ nouveau_bios_ctor(struct nouveau_object *parent, ...@@ -455,9 +456,9 @@ nouveau_bios_ctor(struct nouveau_object *parent,
bios->version.micro = nv_ro08(bios, bios->bmp_offset + 10); 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.major, bios->version.chip,
bios->version.minor, bios->version.micro); bios->version.minor, bios->version.micro, bios->version.patch);
return 0; return 0;
} }
......
...@@ -27,84 +27,105 @@ ...@@ -27,84 +27,105 @@
#include <subdev/bios/gpio.h> #include <subdev/bios/gpio.h>
u16 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 data = 0x0000;
u16 dcb = dcb_table(bios, &ver, &hdr, &cnt, &len); u16 dcb = dcb_table(bios, ver, hdr, cnt, len);
if (dcb) { if (dcb) {
if (ver >= 0x30 && hdr >= 0x0c) if (*ver >= 0x30 && *hdr >= 0x0c)
return nv_ro16(bios, dcb + 0x0a); data = nv_ro16(bios, dcb + 0x0a);
if (ver >= 0x22 && nv_ro08(bios, dcb - 1) >= 0x13) else
return nv_ro16(bios, dcb - 0x0f); 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 0x0000; return data;
} }
u16 u16
dcb_gpio_entry(struct nouveau_bios *bios, int idx, int ent, u8 *ver) dcb_gpio_entry(struct nouveau_bios *bios, int idx, int ent, u8 *ver, u8 *len)
{ {
u16 gpio = dcb_gpio_table(bios); u8 hdr, cnt;
if (gpio) { u16 gpio = !idx ? dcb_gpio_table(bios, ver, &hdr, &cnt, len) : 0x0000;
*ver = nv_ro08(bios, gpio); if (gpio && ent < cnt)
if (*ver < 0x30 && ent < nv_ro08(bios, gpio + 2)) return gpio + hdr + (ent * *len);
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; return 0x0000;
} }
int u16
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) struct dcb_gpio_func *gpio)
{ {
u8 ver, hdr, cnt, len; u16 data = dcb_gpio_entry(bios, idx, ent, ver, len);
u16 entry; if (data) {
int i = -1; if (*ver < 0x40) {
u16 info = nv_ro16(bios, data);
while ((entry = dcb_gpio_entry(bios, idx, ++i, &ver))) {
if (ver < 0x40) {
u16 data = nv_ro16(bios, entry);
*gpio = (struct dcb_gpio_func) { *gpio = (struct dcb_gpio_func) {
.line = (data & 0x001f) >> 0, .line = (info & 0x001f) >> 0,
.func = (data & 0x07e0) >> 5, .func = (info & 0x07e0) >> 5,
.log[0] = (data & 0x1800) >> 11, .log[0] = (info & 0x1800) >> 11,
.log[1] = (data & 0x6000) >> 13, .log[1] = (info & 0x6000) >> 13,
.param = !!(data & 0x8000), .param = !!(info & 0x8000),
}; };
} else } else
if (ver < 0x41) { if (*ver < 0x41) {
u32 data = nv_ro32(bios, entry); u32 info = nv_ro32(bios, data);
*gpio = (struct dcb_gpio_func) { *gpio = (struct dcb_gpio_func) {
.line = (data & 0x0000001f) >> 0, .line = (info & 0x0000001f) >> 0,
.func = (data & 0x0000ff00) >> 8, .func = (info & 0x0000ff00) >> 8,
.log[0] = (data & 0x18000000) >> 27, .log[0] = (info & 0x18000000) >> 27,
.log[1] = (data & 0x60000000) >> 29, .log[1] = (info & 0x60000000) >> 29,
.param = !!(data & 0x80000000), .param = !!(info & 0x80000000),
}; };
} else { } else {
u32 data = nv_ro32(bios, entry + 0); u32 info = nv_ro32(bios, data + 0);
u8 data1 = nv_ro32(bios, entry + 4); u8 info1 = nv_ro32(bios, data + 4);
*gpio = (struct dcb_gpio_func) { *gpio = (struct dcb_gpio_func) {
.line = (data & 0x0000003f) >> 0, .line = (info & 0x0000003f) >> 0,
.func = (data & 0x0000ff00) >> 8, .func = (info & 0x0000ff00) >> 8,
.log[0] = (data1 & 0x30) >> 4, .log[0] = (info1 & 0x30) >> 4,
.log[1] = (data1 & 0xc0) >> 6, .log[1] = (info1 & 0xc0) >> 6,
.param = !!(data & 0x80000000), .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) && if ((line == 0xff || line == gpio->line) &&
(func == 0xff || func == gpio->func)) (func == 0xff || func == gpio->func))
return 0; return data;
} }
/* DCB 2.2, fixed TVDAC GPIO data */ /* DCB 2.2, fixed TVDAC GPIO data */
if ((entry = dcb_table(bios, &ver, &hdr, &cnt, &len))) { if ((data = dcb_table(bios, ver, &hdr, &cnt, len))) {
if (ver >= 0x22 && ver < 0x30 && func == DCB_GPIO_TVDAC0) { if (*ver >= 0x22 && *ver < 0x30 && func == DCB_GPIO_TVDAC0) {
u8 conf = nv_ro08(bios, entry - 5); u8 conf = nv_ro08(bios, data - 5);
u8 addr = nv_ro08(bios, entry - 4); u8 addr = nv_ro08(bios, data - 4);
if (conf & 0x01) { if (conf & 0x01) {
*gpio = (struct dcb_gpio_func) { *gpio = (struct dcb_gpio_func) {
.func = DCB_GPIO_TVDAC0, .func = DCB_GPIO_TVDAC0,
...@@ -112,10 +133,11 @@ dcb_gpio_parse(struct nouveau_bios *bios, int idx, u8 func, u8 line, ...@@ -112,10 +133,11 @@ dcb_gpio_parse(struct nouveau_bios *bios, int idx, u8 func, u8 line,
.log[0] = !!(conf & 0x02), .log[0] = !!(conf & 0x02),
.log[1] = !(conf & 0x02), .log[1] = !(conf & 0x02),
}; };
return 0; *ver = 0x00;
return data;
} }
} }
} }
return -EINVAL; return 0x0000;
} }
...@@ -2,11 +2,12 @@ ...@@ -2,11 +2,12 @@
#include <core/device.h> #include <core/device.h>
#include <subdev/bios.h> #include <subdev/bios.h>
#include <subdev/bios/conn.h>
#include <subdev/bios/bmp.h> #include <subdev/bios/bmp.h>
#include <subdev/bios/bit.h> #include <subdev/bios/bit.h>
#include <subdev/bios/conn.h>
#include <subdev/bios/dcb.h> #include <subdev/bios/dcb.h>
#include <subdev/bios/dp.h> #include <subdev/bios/dp.h>
#include <subdev/bios/gpio.h>
#include <subdev/bios/init.h> #include <subdev/bios/init.h>
#include <subdev/devinit.h> #include <subdev/devinit.h>
#include <subdev/clock.h> #include <subdev/clock.h>
...@@ -409,10 +410,26 @@ init_ram_restrict_group_count(struct nvbios_init *init) ...@@ -409,10 +410,26 @@ init_ram_restrict_group_count(struct nvbios_init *init)
return 0x00; 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 static u8
init_ram_restrict(struct nvbios_init *init) 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); u16 table = init_ram_restrict_table(init);
if (table) if (table)
return nv_ro08(init->bios, table + strap); return nv_ro08(init->bios, table + strap);
...@@ -1781,7 +1798,7 @@ init_gpio(struct nvbios_init *init) ...@@ -1781,7 +1798,7 @@ init_gpio(struct nvbios_init *init)
init->offset += 1; init->offset += 1;
if (init_exec(init) && gpio && gpio->reset) 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) ...@@ -1995,6 +2012,47 @@ init_i2c_long_if(struct nvbios_init *init)
init_exec_set(init, false); 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 { static struct nvbios_init_opcode {
void (*exec)(struct nvbios_init *); void (*exec)(struct nvbios_init *);
} init_opcode[] = { } init_opcode[] = {
...@@ -2059,6 +2117,7 @@ static struct nvbios_init_opcode { ...@@ -2059,6 +2117,7 @@ static struct nvbios_init_opcode {
[0x98] = { init_auxch }, [0x98] = { init_auxch },
[0x99] = { init_zm_auxch }, [0x99] = { init_zm_auxch },
[0x9a] = { init_i2c_long_if }, [0x9a] = { init_i2c_long_if },
[0xa9] = { init_gpio_ne },
}; };
#define init_opcode_nr (sizeof(init_opcode) / sizeof(init_opcode[0])) #define init_opcode_nr (sizeof(init_opcode) / sizeof(init_opcode[0]))
......
...@@ -109,6 +109,34 @@ nve0_identify(struct nouveau_device *device) ...@@ -109,6 +109,34 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass; device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass;
device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
break; 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: default:
nv_fatal(device, "unknown Kepler chipset\n"); nv_fatal(device, "unknown Kepler chipset\n");
return -EINVAL; return -EINVAL;
......
...@@ -43,10 +43,15 @@ static int ...@@ -43,10 +43,15 @@ static int
nouveau_gpio_find(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, nouveau_gpio_find(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line,
struct dcb_gpio_func *func) struct dcb_gpio_func *func)
{ {
struct nouveau_bios *bios = nouveau_bios(gpio);
u8 ver, len;
u16 data;
if (line == 0xff && tag == 0xff) if (line == 0xff && tag == 0xff)
return -EINVAL; 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; return 0;
/* Apple iMac G4 NV18 */ /* Apple iMac G4 NV18 */
...@@ -265,7 +270,7 @@ nouveau_gpio_init(struct nouveau_gpio *gpio) ...@@ -265,7 +270,7 @@ nouveau_gpio_init(struct nouveau_gpio *gpio)
int ret = nouveau_subdev_init(&gpio->base); int ret = nouveau_subdev_init(&gpio->base);
if (ret == 0 && gpio->reset) { if (ret == 0 && gpio->reset) {
if (dmi_check_system(gpio_reset_ids)) if (dmi_check_system(gpio_reset_ids))
gpio->reset(gpio); gpio->reset(gpio, DCB_GPIO_UNUSED);
} }
return ret; return ret;
} }
...@@ -29,15 +29,15 @@ struct nv50_gpio_priv { ...@@ -29,15 +29,15 @@ struct nv50_gpio_priv {
}; };
static void 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 nouveau_bios *bios = nouveau_bios(gpio);
struct nv50_gpio_priv *priv = (void *)gpio; struct nv50_gpio_priv *priv = (void *)gpio;
u8 ver, len;
u16 entry; u16 entry;
u8 ver;
int ent = -1; 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 }; static const u32 regs[] = { 0xe100, 0xe28c };
u32 data = nv_ro32(bios, entry); u32 data = nv_ro32(bios, entry);
u8 line = (data & 0x0000001f); u8 line = (data & 0x0000001f);
...@@ -48,7 +48,8 @@ nv50_gpio_reset(struct nouveau_gpio *gpio) ...@@ -48,7 +48,8 @@ nv50_gpio_reset(struct nouveau_gpio *gpio)
u32 val = (unk1 << 16) | unk0; u32 val = (unk1 << 16) | unk0;
u32 reg = regs[line >> 4]; line &= 0x0f; u32 reg = regs[line >> 4]; line &= 0x0f;
if (func == 0xff) if ( func == DCB_GPIO_UNUSED ||
(match != DCB_GPIO_UNUSED && match != func))
continue; continue;
gpio->set(gpio, 0, func, line, defs); gpio->set(gpio, 0, func, line, defs);
......
...@@ -29,15 +29,15 @@ struct nvd0_gpio_priv { ...@@ -29,15 +29,15 @@ struct nvd0_gpio_priv {
}; };
static void 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 nouveau_bios *bios = nouveau_bios(gpio);
struct nvd0_gpio_priv *priv = (void *)gpio; struct nvd0_gpio_priv *priv = (void *)gpio;
u8 ver, len;
u16 entry; u16 entry;
u8 ver;
int ent = -1; 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); u32 data = nv_ro32(bios, entry);
u8 line = (data & 0x0000003f); u8 line = (data & 0x0000003f);
u8 defs = !!(data & 0x00000080); u8 defs = !!(data & 0x00000080);
...@@ -45,7 +45,8 @@ nvd0_gpio_reset(struct nouveau_gpio *gpio) ...@@ -45,7 +45,8 @@ nvd0_gpio_reset(struct nouveau_gpio *gpio)
u8 unk0 = (data & 0x00ff0000) >> 16; u8 unk0 = (data & 0x00ff0000) >> 16;
u8 unk1 = (data & 0x1f000000) >> 24; u8 unk1 = (data & 0x1f000000) >> 24;
if (func == 0xff) if ( func == DCB_GPIO_UNUSED ||
(match != DCB_GPIO_UNUSED && match != func))
continue; continue;
gpio->set(gpio, 0, func, line, defs); gpio->set(gpio, 0, func, line, defs);
......
...@@ -260,7 +260,7 @@ nouveau_mxm_create_(struct nouveau_object *parent, ...@@ -260,7 +260,7 @@ nouveau_mxm_create_(struct nouveau_object *parent,
data = mxm_table(bios, &ver, &len); data = mxm_table(bios, &ver, &len);
if (!data || !(ver = nv_ro08(bios, data))) { 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; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment