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

Reply via email to