This will turn off PDISPLAY/PCRYPT/PCOPY0/video engines on cards where they are marked as disabled either by the hardware of VBIOS.
See https://bugs.freedesktop.org/show_bug.cgi?id=58378 Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu> --- An earlier version of this patch was tested. I added the DISP disable since then, and rejiggered the way the function was called (turns out that nv50_init function is called by nvc0 as well). drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c | 72 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h | 2 + 2 files changed, 74 insertions(+) diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c index 6df7224..f4d32c6 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c @@ -74,6 +74,74 @@ nv50_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq) return 0; } +static void +nv50_disable_engines(struct nouveau_object *object) +{ + struct nouveau_device *device = nv_device(object); + bool vdec; + u32 r154c; + + /* check for disabled engines */ + vdec = nv_rd32(device, 0x1540) & 0x40000000; + if (device->chipset > 0x50) + r154c = nv_rd32(device, 0x154c); + else + r154c = ~0U; + + if (!(r154c & 0x4)) + device->disable_mask |= 1ULL << NVDEV_ENGINE_DISP; + + switch (device->chipset) { + case 0x50: + if (!vdec) + device->disable_mask |= 1ULL << NVDEV_ENGINE_MPEG; + break; + case 0x84: + case 0x86: + case 0x92: + case 0x94: + case 0x96: + case 0xa0: + if (!vdec) { + device->disable_mask |= 1ULL << NVDEV_ENGINE_MPEG; + device->disable_mask |= 1ULL << NVDEV_ENGINE_VP; + } + if (!vdec || !(r154c & 0x20)) + device->disable_mask |= 1ULL << NVDEV_ENGINE_BSP; + if (!vdec || !(r154c & 0x40)) + device->disable_mask |= 1ULL << NVDEV_ENGINE_CRYPT; + break; + case 0x98: + case 0xaa: + case 0xac: + if (!vdec) { + device->disable_mask |= 1ULL << NVDEV_ENGINE_VP; + device->disable_mask |= 1ULL << NVDEV_ENGINE_PPP; + } + if (!vdec || !(r154c & 0x20)) + device->disable_mask |= 1ULL << NVDEV_ENGINE_BSP; + if (!(r154c & 0x40)) + device->disable_mask |= 1ULL << NVDEV_ENGINE_CRYPT; + break; + case 0xaf: + if (!(r154c & 0x40)) + device->disable_mask |= 1ULL << NVDEV_ENGINE_VIC; + /* fallthrough */ + case 0xa3: + case 0xa5: + case 0xa8: + if (!vdec) { + device->disable_mask |= 1ULL << NVDEV_ENGINE_VP; + device->disable_mask |= 1ULL << NVDEV_ENGINE_PPP; + } + if (!(r154c & 0x20)) + device->disable_mask |= 1ULL << NVDEV_ENGINE_BSP; + if (!(r154c & 0x200)) + device->disable_mask |= 1ULL << NVDEV_ENGINE_COPY0; + break; + } +} + int nv50_devinit_init(struct nouveau_object *object) { @@ -117,6 +185,9 @@ nv50_devinit_init(struct nouveau_object *object) i++; } + if (priv->disable_engines) + priv->disable_engines(object); + return 0; } @@ -134,6 +205,7 @@ nv50_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; priv->base.pll_set = nv50_devinit_pll_set; + priv->disable_engines = nv50_disable_engines; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h index 7d622e2..f17a368 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h @@ -18,6 +18,8 @@ void setPLL_double_lowregs(struct nouveau_devinit *, u32, struct nouveau_pll_val struct nv50_devinit_priv { struct nouveau_devinit base; + + void (*disable_engines)(struct nouveau_object *); }; int nv50_devinit_init(struct nouveau_object *); -- 1.8.3.2