From caba557020d1e7cbb0dd21811e453589fb51ba53 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 6 Dec 2012 14:45:57 +1000 Subject: [PATCH 1/8] drm/nouveau: initial support for GK106 Modesetting seems to work alright, as does graphics (using binary driver fuc from nve7...). Lots to be done no doubt, but this'll get an image on the screen for people. Signed-off-by: Ben Skeggs --- .../gpu/drm/nouveau/core/engine/graph/nvc0.h | 1 + .../gpu/drm/nouveau/core/engine/graph/nve0.c | 1 + .../gpu/drm/nouveau/core/subdev/device/nve0.c | 28 +++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h index 18d2210e12eb..a1e78de46456 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h @@ -121,6 +121,7 @@ nvc0_graph_class(void *obj) return 0x9297; case 0xe4: case 0xe7: + case 0xe6: return 0xa097; default: return 0; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c index 539d4c72f192..261cfce2728c 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c @@ -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: diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index 9b7881e76634..03a652876e73 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -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; From d2bcea686f21e11415828fcca21a4eb200c6251f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 7 Dec 2012 10:09:17 +1000 Subject: [PATCH 2/8] drm/nouveau/bios: update gpio parsing apis to match current design Signed-off-by: Ben Skeggs --- .../nouveau/core/include/subdev/bios/gpio.h | 8 +- .../gpu/drm/nouveau/core/subdev/bios/gpio.c | 134 ++++++++++-------- .../gpu/drm/nouveau/core/subdev/gpio/base.c | 7 +- .../gpu/drm/nouveau/core/subdev/gpio/nv50.c | 4 +- .../gpu/drm/nouveau/core/subdev/gpio/nvd0.c | 4 +- 5 files changed, 93 insertions(+), 64 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h index 2bf178082a36..e6563b5cb08e 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h @@ -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 diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c b/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c index c90d4aa3ae4f..c84e93fa6d95 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c @@ -27,84 +27,105 @@ #include 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; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c index acf818c58bf0..39f267c3241e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c @@ -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 */ diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c index f3502c961cd9..da2341392ced 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c @@ -33,11 +33,11 @@ nv50_gpio_reset(struct nouveau_gpio *gpio) { 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); diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c index 8d18fcad26e0..cda607f24230 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c @@ -33,11 +33,11 @@ nvd0_gpio_reset(struct nouveau_gpio *gpio) { 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); From 1ed731668d011d0ee894d949b80dc3d11fc9ef75 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 7 Dec 2012 13:46:52 +1000 Subject: [PATCH 3/8] drm/nouveau/bios: implement opcode 0xa9 Signed-off-by: Ben Skeggs --- .../drm/nouveau/core/include/subdev/gpio.h | 2 +- .../gpu/drm/nouveau/core/subdev/bios/init.c | 47 ++++++++++++++++++- .../gpu/drm/nouveau/core/subdev/gpio/base.c | 2 +- .../gpu/drm/nouveau/core/subdev/gpio/nv50.c | 5 +- .../gpu/drm/nouveau/core/subdev/gpio/nvd0.c | 5 +- 5 files changed, 53 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h b/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h index 9ea2b12cc15d..b75e8f18e52c 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h @@ -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); diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c index ae168bbb86d8..98f78cf318b0 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c @@ -2,11 +2,12 @@ #include #include -#include #include #include +#include #include #include +#include #include #include #include @@ -1781,7 +1782,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 +1996,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 +2101,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])) diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c index 39f267c3241e..9fb0f9b92d49 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c @@ -270,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; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c index da2341392ced..bf13a1200f26 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c @@ -29,7 +29,7 @@ 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; @@ -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); diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c index cda607f24230..83e8b8f16e6a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c @@ -29,7 +29,7 @@ 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; @@ -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); From 0dd660d4ab9ceb48f24f4df2ebab3e73d908a1e8 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 11 Dec 2012 12:49:18 +1000 Subject: [PATCH 4/8] drm/nouveau/bios: parse/display extra version component Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/include/subdev/bios.h | 1 + drivers/gpu/drm/nouveau/core/subdev/bios/base.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios.h index d145b25e6be4..5bd1ca8cd20d 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios.h @@ -17,6 +17,7 @@ struct nouveau_bios { u8 chip; u8 minor; u8 micro; + u8 patch; } version; }; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c index dd111947eb86..f621f69fa1a2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c @@ -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; } From 3d8ec277394ee0cf9fdd5a411017c3b4f1b0aff2 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 11 Dec 2012 13:32:59 +1000 Subject: [PATCH 5/8] drm/nouveau/mxm: silence output if no bios data Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/mxm/base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c index 93e3ddf7303a..e286e132c7e7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c @@ -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; } From 5ddf4d4a543dd3303b20d7e9a4b3549589c5f095 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 20 Dec 2012 07:48:51 +1000 Subject: [PATCH 6/8] drm/nouveau/bios: cache ramcfg strap on later chipsets This fixes suspend/resume on at least Quadro 400. Signed-off-by: Ben Skeggs --- .../nouveau/core/include/subdev/bios/init.h | 1 + .../gpu/drm/nouveau/core/subdev/bios/init.c | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/init.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/init.h index e69a8bdc6e97..ca2f6bf37f46 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/init.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/init.h @@ -13,6 +13,7 @@ struct nvbios_init { u32 nested; u16 repeat; u16 repend; + u32 ramcfg; }; int nvbios_exec(struct nvbios_init *); diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c index 98f78cf318b0..2917d552689b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c @@ -410,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); From 902530693ef38f3bb007efae594e54443d84fa56 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 20 Dec 2012 12:50:52 +1000 Subject: [PATCH 7/8] drm/nvc0/graph: fix fuc, and enable acceleration on GF119 Signed-off-by: Ben Skeggs --- .../nouveau/core/engine/graph/fuc/hubnvc0.fuc | 10 ++ .../core/engine/graph/fuc/hubnvc0.fuc.h | 147 +++++++++--------- .../gpu/drm/nouveau/core/engine/graph/nvc0.c | 11 +- 3 files changed, 85 insertions(+), 83 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc index acfc457654bd..0bcfa4d447e5 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc @@ -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: diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h index 85a8d556f484..bb03d2a1d57b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h @@ -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, diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c index 47a02081d708..45aff5f5085a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c @@ -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; From eca15296a9c2a5d5d7d8281a710ba4bd0c2e7cd3 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 20 Dec 2012 12:52:06 +1000 Subject: [PATCH 8/8] drm/nve0/graph: fix fuc, and enable acceleration on all known chipsets Also adds GK106 to chipsets known by ucode. Signed-off-by: Ben Skeggs --- .../nouveau/core/engine/graph/fuc/gpcnve0.fuc | 5 + .../core/engine/graph/fuc/gpcnve0.fuc.h | 17 +- .../nouveau/core/engine/graph/fuc/hubnve0.fuc | 13 ++ .../core/engine/graph/fuc/hubnve0.fuc.h | 157 +++++++++--------- .../gpu/drm/nouveau/core/engine/graph/nve0.c | 2 +- 5 files changed, 108 insertions(+), 86 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc index 7b715fda2763..62ab231cd6b6 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc @@ -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 diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h index 26c2165bad0f..09ee4702c8b2 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h @@ -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, diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc index 138eeaa28665..7fe9d7cf486b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc @@ -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: diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h index decf0c60ca3b..e3421af68ab9 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h @@ -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, }; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c index 261cfce2728c..9f82e9702b46 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c @@ -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;