[PATCH 2/3] drm/nv50/devinit: set the disable mask based on the hwunits registers

Ilia Mirkin imirkin at alum.mit.edu
Thu Jan 9 18:19:12 PST 2014


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



More information about the dri-devel mailing list