mirror of
https://github.com/torvalds/linux.git
synced 2024-11-06 03:51:48 +00:00
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:
commit
344f9067d5
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -121,6 +121,7 @@ nvc0_graph_class(void *obj)
|
||||
return 0x9297;
|
||||
case 0xe4:
|
||||
case 0xe7:
|
||||
case 0xe6:
|
||||
return 0xa097;
|
||||
default:
|
||||
return 0;
|
||||
|
@ -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:
|
||||
|
@ -17,6 +17,7 @@ struct nouveau_bios {
|
||||
u8 chip;
|
||||
u8 minor;
|
||||
u8 micro;
|
||||
u8 patch;
|
||||
} version;
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -13,6 +13,7 @@ struct nvbios_init {
|
||||
u32 nested;
|
||||
u16 repeat;
|
||||
u16 repend;
|
||||
u32 ramcfg;
|
||||
};
|
||||
|
||||
int nvbios_exec(struct nvbios_init *);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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]))
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user