drm/nv50-/devinit: prevent use of engines marked as disabled by hw/vbios
authorIlia Mirkin <imirkin@alum.mit.edu>
Tue, 14 Jan 2014 06:29:06 +0000 (16:29 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Thu, 23 Jan 2014 03:39:13 +0000 (13:39 +1000)
Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
17 files changed:
drivers/gpu/drm/nouveau/Makefile
drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c
drivers/gpu/drm/nouveau/core/engine/copy/nve0.c
drivers/gpu/drm/nouveau/core/engine/device/nv50.c
drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
drivers/gpu/drm/nouveau/core/include/subdev/devinit.h
drivers/gpu/drm/nouveau/core/subdev/devinit/base.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h
drivers/gpu/drm/nouveau/core/subdev/devinit/nv84.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/devinit/nv98.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nvaf.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h

index d1dd49b..e88145b 100644 (file)
@@ -72,7 +72,10 @@ nouveau-y += core/subdev/devinit/nv10.o
 nouveau-y += core/subdev/devinit/nv1a.o
 nouveau-y += core/subdev/devinit/nv20.o
 nouveau-y += core/subdev/devinit/nv50.o
+nouveau-y += core/subdev/devinit/nv84.o
+nouveau-y += core/subdev/devinit/nv98.o
 nouveau-y += core/subdev/devinit/nva3.o
+nouveau-y += core/subdev/devinit/nvaf.o
 nouveau-y += core/subdev/devinit/nvc0.o
 nouveau-y += core/subdev/fb/base.o
 nouveau-y += core/subdev/fb/nv04.o
index 993df09..ac3291f 100644 (file)
@@ -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);
index 30f1ef1..748a61e 100644 (file)
@@ -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);
index 5ae9447..81d5c26 100644 (file)
@@ -90,7 +90,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv50_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
@@ -118,7 +118,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv50_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
@@ -146,7 +146,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv50_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
@@ -174,7 +174,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv94_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
@@ -202,7 +202,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv94_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
@@ -230,7 +230,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv98_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
@@ -258,7 +258,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
@@ -286,7 +286,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nvaa_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv98_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
@@ -314,7 +314,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nvaa_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv98_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
@@ -430,7 +430,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nva3_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvaf_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
index 378a015..d52c0f5 100644 (file)
@@ -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);
index fb1fe6a..20725b3 100644 (file)
@@ -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);
index 42aa6b9..a488c36 100644 (file)
@@ -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);
index e59384d..ed1ac68 100644 (file)
@@ -23,7 +23,10 @@ extern struct nouveau_oclass *nv10_devinit_oclass;
 extern struct nouveau_oclass *nv1a_devinit_oclass;
 extern struct nouveau_oclass *nv20_devinit_oclass;
 extern struct nouveau_oclass *nv50_devinit_oclass;
+extern struct nouveau_oclass *nv84_devinit_oclass;
+extern struct nouveau_oclass *nv98_devinit_oclass;
 extern struct nouveau_oclass *nva3_devinit_oclass;
+extern struct nouveau_oclass *nvaf_devinit_oclass;
 extern struct nouveau_oclass *nvc0_devinit_oclass;
 
 #endif
index 6013c42..6b23d9a 100644 (file)
@@ -44,12 +44,21 @@ _nouveau_devinit_fini(struct nouveau_object *object, bool suspend)
 int
 _nouveau_devinit_init(struct nouveau_object *object)
 {
+       struct nouveau_devinit_impl *impl = (void *)object->oclass;
        struct nouveau_devinit *devinit = (void *)object;
-       int ret = nouveau_subdev_init(&devinit->base);
+       int ret;
+
+       ret = nouveau_subdev_init(&devinit->base);
+       if (ret)
+               return ret;
+
+       ret = nvbios_init(&devinit->base, devinit->post);
        if (ret)
                return ret;
 
-       return nvbios_init(&devinit->base, devinit->post);
+       if (impl->disable)
+               nv_device(devinit)->disable_mask |= impl->disable(devinit);
+       return 0;
 }
 
 int
index f81509e..b46c62a 100644 (file)
@@ -30,7 +30,7 @@
 
 #include "nv50.h"
 
-static int
+int
 nv50_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
 {
        struct nv50_devinit_priv *priv = (void *)devinit;
@@ -74,6 +74,19 @@ nv50_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
        return 0;
 }
 
+static u64
+nv50_devinit_disable(struct nouveau_devinit *devinit)
+{
+       struct nv50_devinit_priv *priv = (void *)devinit;
+       u32 r001540 = nv_rd32(priv, 0x001540);
+       u64 disable = 0ULL;
+
+       if (!(r001540 & 0x40000000))
+               disable |= (1ULL << NVDEV_ENGINE_MPEG);
+
+       return disable;
+}
+
 int
 nv50_devinit_init(struct nouveau_object *object)
 {
@@ -146,4 +159,5 @@ nv50_devinit_oclass = &(struct nouveau_devinit_impl) {
                .fini = _nouveau_devinit_fini,
        },
        .pll_set = nv50_devinit_pll_set,
+       .disable = nv50_devinit_disable,
 }.base;
index f87e483..141c27e 100644 (file)
@@ -11,5 +11,8 @@ int  nv50_devinit_ctor(struct nouveau_object *, struct nouveau_object *,
                       struct nouveau_oclass *, void *, u32,
                       struct nouveau_object **);
 int  nv50_devinit_init(struct nouveau_object *);
+int  nv50_devinit_pll_set(struct nouveau_devinit *, u32, u32);
+
+int  nva3_devinit_pll_set(struct nouveau_devinit *, u32, u32);
 
 #endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv84.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv84.c
new file mode 100644 (file)
index 0000000..7874225
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "nv50.h"
+
+static u64
+nv84_devinit_disable(struct nouveau_devinit *devinit)
+{
+       struct nv50_devinit_priv *priv = (void *)devinit;
+       u32 r001540 = nv_rd32(priv, 0x001540);
+       u32 r00154c = nv_rd32(priv, 0x00154c);
+       u64 disable = 0ULL;
+
+       if (!(r001540 & 0x40000000)) {
+               disable |= (1ULL << NVDEV_ENGINE_MPEG);
+               disable |= (1ULL << NVDEV_ENGINE_VP);
+               disable |= (1ULL << NVDEV_ENGINE_BSP);
+               disable |= (1ULL << NVDEV_ENGINE_CRYPT);
+       }
+
+       if (!(r00154c & 0x00000004))
+               disable |= (1ULL << NVDEV_ENGINE_DISP);
+       if (!(r00154c & 0x00000020))
+               disable |= (1ULL << NVDEV_ENGINE_BSP);
+       if (!(r00154c & 0x00000040))
+               disable |= (1ULL << NVDEV_ENGINE_CRYPT);
+
+       return disable;
+}
+
+struct nouveau_oclass *
+nv84_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0x84),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv50_devinit_ctor,
+               .dtor = _nouveau_devinit_dtor,
+               .init = nv50_devinit_init,
+               .fini = _nouveau_devinit_fini,
+       },
+       .pll_set = nv50_devinit_pll_set,
+       .disable = nv84_devinit_disable,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv98.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv98.c
new file mode 100644 (file)
index 0000000..2b0e963
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "nv50.h"
+
+static u64
+nv98_devinit_disable(struct nouveau_devinit *devinit)
+{
+       struct nv50_devinit_priv *priv = (void *)devinit;
+       u32 r001540 = nv_rd32(priv, 0x001540);
+       u32 r00154c = nv_rd32(priv, 0x00154c);
+       u64 disable = 0ULL;
+
+       if (!(r001540 & 0x40000000)) {
+               disable |= (1ULL << NVDEV_ENGINE_VP);
+               disable |= (1ULL << NVDEV_ENGINE_BSP);
+               disable |= (1ULL << NVDEV_ENGINE_PPP);
+       }
+
+       if (!(r00154c & 0x00000004))
+               disable |= (1ULL << NVDEV_ENGINE_DISP);
+       if (!(r00154c & 0x00000020))
+               disable |= (1ULL << NVDEV_ENGINE_BSP);
+       if (!(r00154c & 0x00000040))
+               disable |= (1ULL << NVDEV_ENGINE_CRYPT);
+
+       return disable;
+}
+
+struct nouveau_oclass *
+nv98_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0x98),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv50_devinit_ctor,
+               .dtor = _nouveau_devinit_dtor,
+               .init = nv50_devinit_init,
+               .fini = _nouveau_devinit_fini,
+       },
+       .pll_set = nv50_devinit_pll_set,
+       .disable = nv98_devinit_disable,
+}.base;
index 67f5594..6dedf1d 100644 (file)
@@ -24,7 +24,7 @@
 
 #include "nv50.h"
 
-static int
+int
 nva3_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
 {
        struct nv50_devinit_priv *priv = (void *)devinit;
@@ -58,6 +58,29 @@ nva3_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
        return ret;
 }
 
+static u64
+nva3_devinit_disable(struct nouveau_devinit *devinit)
+{
+       struct nv50_devinit_priv *priv = (void *)devinit;
+       u32 r001540 = nv_rd32(priv, 0x001540);
+       u32 r00154c = nv_rd32(priv, 0x00154c);
+       u64 disable = 0ULL;
+
+       if (!(r001540 & 0x40000000)) {
+               disable |= (1ULL << NVDEV_ENGINE_VP);
+               disable |= (1ULL << NVDEV_ENGINE_PPP);
+       }
+
+       if (!(r00154c & 0x00000004))
+               disable |= (1ULL << NVDEV_ENGINE_DISP);
+       if (!(r00154c & 0x00000020))
+               disable |= (1ULL << NVDEV_ENGINE_BSP);
+       if (!(r00154c & 0x00000200))
+               disable |= (1ULL << NVDEV_ENGINE_COPY0);
+
+       return disable;
+}
+
 struct nouveau_oclass *
 nva3_devinit_oclass = &(struct nouveau_devinit_impl) {
        .base.handle = NV_SUBDEV(DEVINIT, 0xa3),
@@ -68,4 +91,5 @@ nva3_devinit_oclass = &(struct nouveau_devinit_impl) {
                .fini = _nouveau_devinit_fini,
        },
        .pll_set = nva3_devinit_pll_set,
+       .disable = nva3_devinit_disable,
 }.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nvaf.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvaf.c
new file mode 100644 (file)
index 0000000..4fc68d2
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "nv50.h"
+
+static u64
+nvaf_devinit_disable(struct nouveau_devinit *devinit)
+{
+       struct nv50_devinit_priv *priv = (void *)devinit;
+       u32 r001540 = nv_rd32(priv, 0x001540);
+       u32 r00154c = nv_rd32(priv, 0x00154c);
+       u64 disable = 0;
+
+       if (!(r001540 & 0x40000000)) {
+               disable |= (1ULL << NVDEV_ENGINE_VP);
+               disable |= (1ULL << NVDEV_ENGINE_PPP);
+       }
+
+       if (!(r00154c & 0x00000004))
+               disable |= (1ULL << NVDEV_ENGINE_DISP);
+       if (!(r00154c & 0x00000020))
+               disable |= (1ULL << NVDEV_ENGINE_BSP);
+       if (!(r00154c & 0x00000040))
+               disable |= (1ULL << NVDEV_ENGINE_VIC);
+       if (!(r00154c & 0x00000200))
+               disable |= (1ULL << NVDEV_ENGINE_COPY0);
+
+       return disable;
+}
+
+struct nouveau_oclass *
+nvaf_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0xaf),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv50_devinit_ctor,
+               .dtor = _nouveau_devinit_dtor,
+               .init = nv50_devinit_init,
+               .fini = _nouveau_devinit_fini,
+       },
+       .pll_set = nva3_devinit_pll_set,
+       .disable = nvaf_devinit_disable,
+}.base;
index ced0e82..fa7e637 100644 (file)
@@ -59,6 +59,33 @@ nvc0_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
        return ret;
 }
 
+static u64
+nvc0_devinit_disable(struct nouveau_devinit *devinit)
+{
+       struct nv50_devinit_priv *priv = (void *)devinit;
+       u32 r022500 = nv_rd32(priv, 0x022500);
+       u64 disable = 0ULL;
+
+       if (r022500 & 0x00000001)
+               disable |= (1ULL << NVDEV_ENGINE_DISP);
+
+       if (r022500 & 0x00000002) {
+               disable |= (1ULL << NVDEV_ENGINE_VP);
+               disable |= (1ULL << NVDEV_ENGINE_PPP);
+       }
+
+       if (r022500 & 0x00000004)
+               disable |= (1ULL << NVDEV_ENGINE_BSP);
+       if (r022500 & 0x00000008)
+               disable |= (1ULL << NVDEV_ENGINE_VENC);
+       if (r022500 & 0x00000100)
+               disable |= (1ULL << NVDEV_ENGINE_COPY0);
+       if (r022500 & 0x00000200)
+               disable |= (1ULL << NVDEV_ENGINE_COPY1);
+
+       return disable;
+}
+
 static int
 nvc0_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                  struct nouveau_oclass *oclass, void *data, u32 size,
@@ -87,4 +114,5 @@ nvc0_devinit_oclass = &(struct nouveau_devinit_impl) {
                .fini = _nouveau_devinit_fini,
        },
        .pll_set = nvc0_devinit_pll_set,
+       .disable = nvc0_devinit_disable,
 }.base;
index ae8de97..c4179b6 100644 (file)
@@ -10,6 +10,7 @@ struct nouveau_devinit_impl {
        struct nouveau_oclass base;
        void (*meminit)(struct nouveau_devinit *);
        int  (*pll_set)(struct nouveau_devinit *, u32 type, u32 freq);
+       u64  (*disable)(struct nouveau_devinit *);
 };
 
 #define nouveau_devinit_create(p,e,o,d)                                        \