From ce4dcec9f40f1db660d65098a8fe1d66326224c4 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Wed, 8 Jan 2014 17:40:33 -0500 Subject: [PATCH] drm/nv50/device: honor engine disable registers Some cards are missing PCRYPT and other engines. In PCRYPT's case, that makes async buffer copying not work, for the others it's more of an annoyance. See https://bugs.freedesktop.org/show_bug.cgi?id=58378 Signed-off-by: Ilia Mirkin --- drivers/gpu/drm/nouveau/core/engine/device/nv50.c | 70 +++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c index db3fc7b..c59072c 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c @@ -53,9 +53,22 @@ #include #include +#define disable_engine(device, engine) \ + disable_engine_(device, NVDEV_ENGINE_ ## engine, #engine) + +static void +disable_engine_(struct nouveau_device *device, int engine, const char *name) +{ + nv_info(device, "%s hardware missing, disabling\n", name); + device->oclass[engine] = NULL; +} + int nv50_identify(struct nouveau_device *device) { + u32 r154c; + bool vdec; + switch (device->chipset) { case 0x50: device->cname = "G80"; @@ -456,5 +469,62 @@ nv50_identify(struct nouveau_device *device) return -EINVAL; } + /* Perform engine disables here based on the enabled units registers. */ + vdec = nv_rd32(device, 0x1540) & 0x40000000; + if (device->chipset > 0x50) + r154c = nv_rd32(device, 0x154c); + else + r154c = 0; + + switch (device->chipset) { + case 0x50: + if (!vdec) + disable_engine(device, MPEG); + break; + case 0x84: + case 0x86: + case 0x92: + case 0x94: + case 0x96: + case 0xa0: + if (!vdec) { + disable_engine(device, MPEG); + disable_engine(device, VP); + } + if (!vdec || !(r154c & 0x20)) + disable_engine(device, BSP); + if (!vdec || !(r154c & 0x40)) + disable_engine(device, CRYPT); + break; + case 0x98: + case 0xaa: + case 0xac: + if (!vdec) { + disable_engine(device, VP); + disable_engine(device, PPP); + } + if (!vdec || !(r154c & 0x20)) + disable_engine(device, BSP); + if (!(r154c & 0x40)) + disable_engine(device, CRYPT); + break; + case 0xaf: + if (!(r154c & 0x40)) + disable_engine(device, VIC); + /* fallthrough */ + case 0xa3: + case 0xa5: + case 0xa8: + if (!vdec) { + disable_engine(device, VP); + disable_engine(device, PPP); + } + if (!(r154c & 0x20)) + disable_engine(device, BSP); + if (!(r154c & 0x200)) + disable_engine(device, COPY0); + break; + } + return 0; } -- 1.8.3.2