Ilia Mirkin
2014-Jan-10 02:19 UTC
[Nouveau] [PATCH 1/3] drm/nouveau: provide a way for devinit to mark engines as disabled
Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu> --- I decided to let the user still specify config=BLA=1 to override the hw disable in case we get something wrong or for double-checking stuff, but I suspect it won't really be used much. I'm not terribly fond of the message text, if you come up with something better, feel free to drop it in. drivers/gpu/drm/nouveau/core/core/engine.c | 21 ++++++++++++++++----- drivers/gpu/drm/nouveau/core/include/core/device.h | 1 + 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/core/engine.c b/drivers/gpu/drm/nouveau/core/core/engine.c index c8bed4a..0405fba 100644 --- a/drivers/gpu/drm/nouveau/core/core/engine.c +++ b/drivers/gpu/drm/nouveau/core/core/engine.c @@ -34,6 +34,7 @@ nouveau_engine_create_(struct nouveau_object *parent, int length, void **pobject) { struct nouveau_engine *engine; + struct nouveau_device *device; int ret; ret = nouveau_subdev_create_(parent, engobj, oclass, NV_ENGINE_CLASS, @@ -42,11 +43,21 @@ nouveau_engine_create_(struct nouveau_object *parent, if (ret) return ret; - if ( parent && - !nouveau_boolopt(nv_device(parent)->cfgopt, iname, enable)) { - if (!enable) - nv_warn(engine, "disabled, %s=1 to enable\n", iname); - return -ENODEV; + if (parent) { + device = nv_device(parent); + if (device->disable_mask & (1ULL << (oclass->handle & 0xff))) { + if (nouveau_boolopt(device->cfgopt, iname, false)) { + nv_warn(engine, "hardware is marked as disabled, but obeying explicit enable\n"); + } else { + nv_info(engine, "hardware is marked as disabled\n"); + return -ENODEV; + } + } + if (!nouveau_boolopt(device->cfgopt, iname, enable)) { + if (!enable) + nv_warn(engine, "disabled, %s=1 to enable\n", iname); + return -ENODEV; + } } INIT_LIST_HEAD(&engine->contexts); diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h b/drivers/gpu/drm/nouveau/core/include/core/device.h index ac2881d..d04c523 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/device.h +++ b/drivers/gpu/drm/nouveau/core/include/core/device.h @@ -70,6 +70,7 @@ struct nouveau_device { const char *dbgopt; const char *name; const char *cname; + u64 disable_mask; enum { NV_04 = 0x04, -- 1.8.3.2
Ilia Mirkin
2014-Jan-10 02:19 UTC
[Nouveau] [PATCH 2/3] drm/nv50/devinit: set the disable mask based on the hwunits registers
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
Ilia Mirkin
2014-Jan-10 02:19 UTC
[Nouveau] [PATCH 3/3] drm/nvc0/devinit: set the disable mask based on punits register
This replaces the custom disable checks throughout the implementations. As a side-effect this will honor hw disables on video decoding engines as well as PDISP on nvc0:nvd0. Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu> --- Not strictly needed, but I think it's nice to unify it all. (And it also handles the video engines which were missing the checks.) It seems to me that PCE2 can be disabled as well with the higher bits on NVE0+, but the old code didn't do it, so I left it alone. It looks like there's also a SW_DISABLE register at 0x22580, should we look at it as well? Again, leaving to a future patch to avoid regressions. drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c | 6 ------ drivers/gpu/drm/nouveau/core/engine/copy/nve0.c | 6 ------ drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c | 3 --- drivers/gpu/drm/nouveau/core/engine/disp/nve0.c | 3 --- drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c | 3 --- drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c | 23 ++++++++++++++++++++++ 6 files changed, 23 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c index 993df09..ac3291f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c @@ -105,9 +105,6 @@ nvc0_copy0_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nvc0_copy_priv *priv; int ret; - if (nv_rd32(parent, 0x022500) & 0x00000100) - return -ENODEV; - ret = nouveau_falcon_create(parent, engine, oclass, 0x104000, true, "PCE0", "copy0", &priv); *pobject = nv_object(priv); @@ -133,9 +130,6 @@ nvc0_copy1_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nvc0_copy_priv *priv; int ret; - if (nv_rd32(parent, 0x022500) & 0x00000200) - return -ENODEV; - ret = nouveau_falcon_create(parent, engine, oclass, 0x105000, true, "PCE1", "copy1", &priv); *pobject = nv_object(priv); diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c b/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c index 30f1ef1..748a61e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c @@ -88,9 +88,6 @@ nve0_copy0_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nve0_copy_priv *priv; int ret; - if (nv_rd32(parent, 0x022500) & 0x00000100) - return -ENODEV; - ret = nouveau_engine_create(parent, engine, oclass, true, "PCE0", "copy0", &priv); *pobject = nv_object(priv); @@ -112,9 +109,6 @@ nve0_copy1_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nve0_copy_priv *priv; int ret; - if (nv_rd32(parent, 0x022500) & 0x00000200) - return -ENODEV; - ret = nouveau_engine_create(parent, engine, oclass, true, "PCE1", "copy1", &priv); *pobject = nv_object(priv); diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c index 378a015..d52c0f5 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c @@ -967,9 +967,6 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, int heads = nv_rd32(parent, 0x022448); int ret; - if (nv_rd32(parent, 0x022500) & 0x00000001) - return -ENODEV; - ret = nouveau_disp_create(parent, engine, oclass, heads, "PDISP", "display", &priv); *pobject = nv_object(priv); diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c index fb1fe6a..20725b3 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c @@ -54,9 +54,6 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, int heads = nv_rd32(parent, 0x022448); int ret; - if (nv_rd32(parent, 0x022500) & 0x00000001) - return -ENODEV; - ret = nouveau_disp_create(parent, engine, oclass, heads, "PDISP", "display", &priv); *pobject = nv_object(priv); diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c index 42aa6b9..a488c36 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c @@ -54,9 +54,6 @@ nvf0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, int heads = nv_rd32(parent, 0x022448); int ret; - if (nv_rd32(parent, 0x022500) & 0x00000001) - return -ENODEV; - ret = nouveau_disp_create(parent, engine, oclass, heads, "PDISP", "display", &priv); *pobject = nv_object(priv); diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c index 19e265b..8ded642 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c @@ -59,6 +59,28 @@ nvc0_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq) return ret; } +static void +nvc0_disable_engines(struct nouveau_object *object) +{ + struct nouveau_device *device = nv_device(object); + u32 r22500 = nv_rd32(device, 0x22500); + + if (r22500 & 0x001) + device->disable_mask |= 1ULL << NVDEV_ENGINE_DISP; + if (r22500 & 0x002) { + device->disable_mask |= 1ULL << NVDEV_ENGINE_VP; + device->disable_mask |= 1ULL << NVDEV_ENGINE_PPP; + } + if (r22500 & 0x004) + device->disable_mask |= 1ULL << NVDEV_ENGINE_BSP; + if (device->chipset > 0xd0 && (r22500 & 0x008)) + device->disable_mask |= 1ULL << NVDEV_ENGINE_VENC; + if (r22500 & 0x100) + device->disable_mask |= 1ULL << NVDEV_ENGINE_COPY0; + if (r22500 & 0x200) + device->disable_mask |= 1ULL << NVDEV_ENGINE_COPY1; +} + static int nvc0_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, @@ -73,6 +95,7 @@ nvc0_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; priv->base.pll_set = nvc0_devinit_pll_set; + priv->disable_engines = nvc0_disable_engines; if (nv_rd32(priv, 0x022500) & 0x00000001) priv->base.post = true; return 0; -- 1.8.3.2
Reasonably Related Threads
- [PATCH] devinit: lock/unlock crtc regs for all devices, not just pre-nv50
- [PATCH] devinit: lock/unlock crtc regs for all devices, not just pre-nv50
- [PATCH] devinit/gf100-: detect if BIOS invoked devinit
- [PATCH] nouveau: Load firmware for BSP/VP engines on NV84-NV96, NVA0
- [PATCH 1/7] drm/nouveau: remove prototype for non-existent nouveau_connector_bpp