drm/nouveau/fb: create tag heap from common code for all relevant chipsets
authorBen Skeggs <bskeggs@redhat.com>
Wed, 10 Oct 2012 01:31:11 +0000 (11:31 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 28 Nov 2012 23:56:31 +0000 (09:56 +1000)
A nv2x bug wrt hardcoded tag counts is now also fixed as a side-effect.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
20 files changed:
drivers/gpu/drm/nouveau/Makefile
drivers/gpu/drm/nouveau/core/include/subdev/fb.h
drivers/gpu/drm/nouveau/core/subdev/device/nv10.c
drivers/gpu/drm/nouveau/core/subdev/fb/base.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv25.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv35.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv41.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv44.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv46.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv47.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv49.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv4e.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c

index 4426f9ac6a86c969253c50d5921fd35709ed3ee8..4f08a0496d6fc941671cdc106b11f6609bd797b7 100644 (file)
@@ -64,6 +64,7 @@ nouveau-y += core/subdev/devinit/nv50.o
 nouveau-y += core/subdev/fb/base.o
 nouveau-y += core/subdev/fb/nv04.o
 nouveau-y += core/subdev/fb/nv10.o
+nouveau-y += core/subdev/fb/nv1a.o
 nouveau-y += core/subdev/fb/nv20.o
 nouveau-y += core/subdev/fb/nv25.o
 nouveau-y += core/subdev/fb/nv30.o
index 3108f19ef505e8ed5dfb4ea840f67a7021335e8a..9f3e82976ec726412dbe05a3b491455fd9831006 100644 (file)
@@ -71,6 +71,7 @@ struct nouveau_fb {
                u64 size;
                int ranks;
 
+               int  (*init)(struct nouveau_fb *);
                int  (*get)(struct nouveau_fb *, u64 size, u32 align,
                            u32 size_nc, u32 type, struct nouveau_mem **);
                void (*put)(struct nouveau_fb *, struct nouveau_mem **);
@@ -101,7 +102,7 @@ nouveau_fb(void *obj)
 
 #define nouveau_fb_create(p,e,c,d)                                             \
        nouveau_subdev_create((p), (e), (c), 0, "PFB", "fb", (d))
-int  nouveau_fb_created(struct nouveau_fb *);
+int  nouveau_fb_preinit(struct nouveau_fb *);
 void nouveau_fb_destroy(struct nouveau_fb *);
 int  nouveau_fb_init(struct nouveau_fb *);
 #define nouveau_fb_fini(p,s)                                                   \
@@ -113,6 +114,7 @@ int  _nouveau_fb_init(struct nouveau_object *);
 
 extern struct nouveau_oclass nv04_fb_oclass;
 extern struct nouveau_oclass nv10_fb_oclass;
+extern struct nouveau_oclass nv1a_fb_oclass;
 extern struct nouveau_oclass nv20_fb_oclass;
 extern struct nouveau_oclass nv25_fb_oclass;
 extern struct nouveau_oclass nv30_fb_oclass;
@@ -132,6 +134,12 @@ int  nouveau_fb_bios_memtype(struct nouveau_bios *);
 
 bool nv04_fb_memtype_valid(struct nouveau_fb *, u32 memtype);
 
+void nv10_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size,
+                      u32 pitch, u32 flags, struct nouveau_fb_tile *);
+void nv10_fb_tile_fini(struct nouveau_fb *, int i, struct nouveau_fb_tile *);
+void nv10_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *);
+
+int  nv20_fb_vram_init(struct nouveau_fb *);
 void nv20_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size,
                       u32 pitch, u32 flags, struct nouveau_fb_tile *);
 void nv20_fb_tile_fini(struct nouveau_fb *, int i, struct nouveau_fb_tile *);
@@ -142,9 +150,11 @@ void nv30_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size,
                       u32 pitch, u32 flags, struct nouveau_fb_tile *);
 void nv30_fb_tile_fini(struct nouveau_fb *, int i, struct nouveau_fb_tile *);
 
+int  nv41_fb_vram_init(struct nouveau_fb *);
 int  nv41_fb_init(struct nouveau_object *);
 void nv41_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *);
 
+int  nv44_fb_vram_init(struct nouveau_fb *);
 int  nv44_fb_init(struct nouveau_object *);
 void nv44_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *);
 
index f09accfd0e31be18d2aad50bc689fb5a6de0ce60..9c40b0fb23f62a67737159491281eef02f6ba329 100644 (file)
@@ -105,7 +105,7 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
-               device->oclass[NVDEV_SUBDEV_FB     ] = &nv10_fb_oclass;
+               device->oclass[NVDEV_SUBDEV_FB     ] = &nv1a_fb_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -159,7 +159,7 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
-               device->oclass[NVDEV_SUBDEV_FB     ] = &nv10_fb_oclass;
+               device->oclass[NVDEV_SUBDEV_FB     ] = &nv1a_fb_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
index 9fae64d60954f539315c25ef9cc52a2f1b160cd0..d6d16007ec1ac08e0e88ca35e8c4e8d20ae4e2f9 100644 (file)
@@ -57,25 +57,45 @@ nouveau_fb_bios_memtype(struct nouveau_bios *bios)
 }
 
 int
-nouveau_fb_init(struct nouveau_fb *pfb)
+nouveau_fb_preinit(struct nouveau_fb *pfb)
 {
-       int ret, i;
+       static const char *name[] = {
+               [NV_MEM_TYPE_UNKNOWN] = "unknown",
+               [NV_MEM_TYPE_STOLEN ] = "stolen system memory",
+               [NV_MEM_TYPE_SGRAM  ] = "SGRAM",
+               [NV_MEM_TYPE_SDRAM  ] = "SDRAM",
+               [NV_MEM_TYPE_DDR1   ] = "DDR1",
+               [NV_MEM_TYPE_DDR2   ] = "DDR2",
+               [NV_MEM_TYPE_DDR3   ] = "DDR3",
+               [NV_MEM_TYPE_GDDR2  ] = "GDDR2",
+               [NV_MEM_TYPE_GDDR3  ] = "GDDR3",
+               [NV_MEM_TYPE_GDDR4  ] = "GDDR4",
+               [NV_MEM_TYPE_GDDR5  ] = "GDDR5",
+       };
+       int ret, tags;
 
-       ret = nouveau_subdev_init(&pfb->base);
-       if (ret)
-               return ret;
+       tags = pfb->ram.init(pfb);
+       if (tags < 0 || !pfb->ram.size) {
+               nv_fatal(pfb, "error detecting memory configuration!!\n");
+               return (tags < 0) ? tags : -ERANGE;
+       }
 
-       for (i = 0; i < pfb->tile.regions; i++)
-               pfb->tile.prog(pfb, i, &pfb->tile.region[i]);
+       if (!nouveau_mm_initialised(&pfb->vram)) {
+               ret = nouveau_mm_init(&pfb->vram, 0, pfb->ram.size >> 12, 1);
+               if (ret)
+                       return ret;
+       }
 
-       return 0;
-}
+       if (!nouveau_mm_initialised(&pfb->tags) && tags) {
+               ret = nouveau_mm_init(&pfb->tags, 0, ++tags, 1);
+               if (ret)
+                       return ret;
+       }
 
-int
-_nouveau_fb_init(struct nouveau_object *object)
-{
-       struct nouveau_fb *pfb = (void *)object;
-       return nouveau_fb_init(pfb);
+       nv_info(pfb, "RAM type: %s\n", name[pfb->ram.type]);
+       nv_info(pfb, "RAM size: %d MiB\n", (int)(pfb->ram.size >> 20));
+       nv_info(pfb, "   ZCOMP: %d tags\n", tags);
+       return 0;
 }
 
 void
@@ -97,30 +117,24 @@ _nouveau_fb_dtor(struct nouveau_object *object)
        struct nouveau_fb *pfb = (void *)object;
        nouveau_fb_destroy(pfb);
 }
-
 int
-nouveau_fb_created(struct nouveau_fb *pfb)
+nouveau_fb_init(struct nouveau_fb *pfb)
 {
-       static const char *name[] = {
-               [NV_MEM_TYPE_UNKNOWN] = "unknown",
-               [NV_MEM_TYPE_STOLEN ] = "stolen system memory",
-               [NV_MEM_TYPE_SGRAM  ] = "SGRAM",
-               [NV_MEM_TYPE_SDRAM  ] = "SDRAM",
-               [NV_MEM_TYPE_DDR1   ] = "DDR1",
-               [NV_MEM_TYPE_DDR2   ] = "DDR2",
-               [NV_MEM_TYPE_DDR3   ] = "DDR3",
-               [NV_MEM_TYPE_GDDR2  ] = "GDDR2",
-               [NV_MEM_TYPE_GDDR3  ] = "GDDR3",
-               [NV_MEM_TYPE_GDDR4  ] = "GDDR4",
-               [NV_MEM_TYPE_GDDR5  ] = "GDDR5",
-       };
+       int ret, i;
 
-       if (pfb->ram.size == 0) {
-               nv_fatal(pfb, "no vram detected!!\n");
-               return -ERANGE;
-       }
+       ret = nouveau_subdev_init(&pfb->base);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < pfb->tile.regions; i++)
+               pfb->tile.prog(pfb, i, &pfb->tile.region[i]);
 
-       nv_info(pfb, "RAM type: %s\n", name[pfb->ram.type]);
-       nv_info(pfb, "RAM size: %d MiB\n", (int)(pfb->ram.size >> 20));
        return 0;
 }
+
+int
+_nouveau_fb_init(struct nouveau_object *object)
+{
+       struct nouveau_fb *pfb = (void *)object;
+       return nouveau_fb_init(pfb);
+}
index eb06836b69f7e6dc1acc4d842604dc3beb31d7c8..6e369f85361e2cc3e972fdf67690f421b79edb66 100644 (file)
@@ -55,6 +55,37 @@ nv04_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags)
        return false;
 }
 
+static int
+nv04_fb_vram_init(struct nouveau_fb *pfb)
+{
+       u32 boot0 = nv_rd32(pfb, NV04_PFB_BOOT_0);
+       if (boot0 & 0x00000100) {
+               pfb->ram.size  = ((boot0 >> 12) & 0xf) * 2 + 2;
+               pfb->ram.size *= 1024 * 1024;
+       } else {
+               switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) {
+               case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB:
+                       pfb->ram.size = 32 * 1024 * 1024;
+                       break;
+               case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB:
+                       pfb->ram.size = 16 * 1024 * 1024;
+                       break;
+               case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB:
+                       pfb->ram.size = 8 * 1024 * 1024;
+                       break;
+               case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB:
+                       pfb->ram.size = 4 * 1024 * 1024;
+                       break;
+               }
+       }
+
+       if ((boot0 & 0x00000038) <= 0x10)
+               pfb->ram.type = NV_MEM_TYPE_SGRAM;
+       else
+               pfb->ram.type = NV_MEM_TYPE_SDRAM;
+       return 0;
+}
+
 static int
 nv04_fb_init(struct nouveau_object *object)
 {
@@ -79,7 +110,6 @@ nv04_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
             struct nouveau_object **pobject)
 {
        struct nv04_fb_priv *priv;
-       u32 boot0;
        int ret;
 
        ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -87,35 +117,9 @@ nv04_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       boot0 = nv_rd32(priv, NV04_PFB_BOOT_0);
-       if (boot0 & 0x00000100) {
-               priv->base.ram.size  = ((boot0 >> 12) & 0xf) * 2 + 2;
-               priv->base.ram.size *= 1024 * 1024;
-       } else {
-               switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) {
-               case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB:
-                       priv->base.ram.size = 32 * 1024 * 1024;
-                       break;
-               case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB:
-                       priv->base.ram.size = 16 * 1024 * 1024;
-                       break;
-               case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB:
-                       priv->base.ram.size = 8 * 1024 * 1024;
-                       break;
-               case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB:
-                       priv->base.ram.size = 4 * 1024 * 1024;
-                       break;
-               }
-       }
-
-       if ((boot0 & 0x00000038) <= 0x10)
-               priv->base.ram.type = NV_MEM_TYPE_SGRAM;
-       else
-               priv->base.ram.type = NV_MEM_TYPE_SDRAM;
-
-
        priv->base.memtype_valid = nv04_fb_memtype_valid;
-       return nouveau_fb_created(&priv->base);
+       priv->base.ram.init = nv04_fb_vram_init;
+       return nouveau_fb_preinit(&priv->base);
 }
 
 struct nouveau_oclass
index 12193d9dd2a63110cc5be7f0a14d34c7b87ddd88..edbbe26e858dc15b0a034125a4a3d5e14f0fae1b 100644 (file)
@@ -30,7 +30,20 @@ struct nv10_fb_priv {
        struct nouveau_fb base;
 };
 
-static void
+static int
+nv10_fb_vram_init(struct nouveau_fb *pfb)
+{
+       u32 cfg0 = nv_rd32(pfb, 0x100200);
+       if (cfg0 & 0x00000001)
+               pfb->ram.type = NV_MEM_TYPE_DDR1;
+       else
+               pfb->ram.type = NV_MEM_TYPE_SDRAM;
+
+       pfb->ram.size = nv_rd32(pfb, 0x10020c) & 0xff000000;
+       return 0;
+}
+
+void
 nv10_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch,
                  u32 flags, struct nouveau_fb_tile *tile)
 {
@@ -39,7 +52,7 @@ nv10_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch,
        tile->pitch = pitch;
 }
 
-static void
+void
 nv10_fb_tile_fini(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)
 {
        tile->addr  = 0;
@@ -48,7 +61,7 @@ nv10_fb_tile_fini(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)
        tile->zcomp = 0;
 }
 
-static void
+void
 nv10_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)
 {
        nv_wr32(pfb, 0x100244 + (i * 0x10), tile->limit);
@@ -62,7 +75,6 @@ nv10_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
             struct nouveau_oclass *oclass, void *data, u32 size,
             struct nouveau_object **pobject)
 {
-       struct nouveau_device *device = nv_device(parent);
        struct nv10_fb_priv *priv;
        int ret;
 
@@ -71,42 +83,13 @@ nv10_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       if (device->chipset == 0x1a ||  device->chipset == 0x1f) {
-               struct pci_dev *bridge;
-               u32 mem, mib;
-
-               bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1));
-               if (!bridge) {
-                       nv_fatal(device, "no bridge device\n");
-                       return 0;
-               }
-
-               if (device->chipset == 0x1a) {
-                       pci_read_config_dword(bridge, 0x7c, &mem);
-                       mib = ((mem >> 6) & 31) + 1;
-               } else {
-                       pci_read_config_dword(bridge, 0x84, &mem);
-                       mib = ((mem >> 4) & 127) + 1;
-               }
-
-               priv->base.ram.type = NV_MEM_TYPE_STOLEN;
-               priv->base.ram.size = mib * 1024 * 1024;
-       } else {
-               u32 cfg0 = nv_rd32(priv, 0x100200);
-               if (cfg0 & 0x00000001)
-                       priv->base.ram.type = NV_MEM_TYPE_DDR1;
-               else
-                       priv->base.ram.type = NV_MEM_TYPE_SDRAM;
-
-               priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
-       }
-
        priv->base.memtype_valid = nv04_fb_memtype_valid;
+       priv->base.ram.init = nv10_fb_vram_init;
        priv->base.tile.regions = 8;
        priv->base.tile.init = nv10_fb_tile_init;
        priv->base.tile.fini = nv10_fb_tile_fini;
        priv->base.tile.prog = nv10_fb_tile_prog;
-       return nouveau_fb_created(&priv->base);
+       return nouveau_fb_preinit(&priv->base);
 }
 
 struct nouveau_oclass
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c
new file mode 100644 (file)
index 0000000..4836684
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2010 Francisco Jerez.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 OWNER(S) AND/OR ITS SUPPLIERS 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.
+ *
+ */
+
+#include <subdev/fb.h>
+
+struct nv1a_fb_priv {
+       struct nouveau_fb base;
+};
+
+static int
+nv1a_fb_vram_init(struct nouveau_fb *pfb)
+{
+       struct pci_dev *bridge;
+       u32 mem, mib;
+
+       bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1));
+       if (!bridge) {
+               nv_fatal(pfb, "no bridge device\n");
+               return -ENODEV;
+       }
+
+       if (nv_device(pfb)->chipset == 0x1a) {
+               pci_read_config_dword(bridge, 0x7c, &mem);
+               mib = ((mem >> 6) & 31) + 1;
+       } else {
+               pci_read_config_dword(bridge, 0x84, &mem);
+               mib = ((mem >> 4) & 127) + 1;
+       }
+
+       pfb->ram.type = NV_MEM_TYPE_STOLEN;
+       pfb->ram.size = mib * 1024 * 1024;
+       return 0;
+}
+
+static int
+nv1a_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+            struct nouveau_oclass *oclass, void *data, u32 size,
+            struct nouveau_object **pobject)
+{
+       struct nv1a_fb_priv *priv;
+       int ret;
+
+       ret = nouveau_fb_create(parent, engine, oclass, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       priv->base.memtype_valid = nv04_fb_memtype_valid;
+       priv->base.ram.init = nv1a_fb_vram_init;
+       priv->base.tile.regions = 8;
+       priv->base.tile.init = nv10_fb_tile_init;
+       priv->base.tile.fini = nv10_fb_tile_fini;
+       priv->base.tile.prog = nv10_fb_tile_prog;
+       return nouveau_fb_preinit(&priv->base);
+}
+
+struct nouveau_oclass
+nv1a_fb_oclass = {
+       .handle = NV_SUBDEV(FB, 0x1a),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv1a_fb_ctor,
+               .dtor = _nouveau_fb_dtor,
+               .init = _nouveau_fb_init,
+               .fini = _nouveau_fb_fini,
+       },
+};
index 307d5c73b7048f7619d0ab0ce78f982e96b4c0f2..d26adee63c1ef4089ac3c258ac04e10e8533d7e7 100644 (file)
@@ -30,6 +30,22 @@ struct nv20_fb_priv {
        struct nouveau_fb base;
 };
 
+int
+nv20_fb_vram_init(struct nouveau_fb *pfb)
+{
+       u32 pbus1218 = nv_rd32(pfb, 0x001218);
+
+       switch (pbus1218 & 0x00000300) {
+       case 0x00000000: pfb->ram.type = NV_MEM_TYPE_SDRAM; break;
+       case 0x00000100: pfb->ram.type = NV_MEM_TYPE_DDR1; break;
+       case 0x00000200: pfb->ram.type = NV_MEM_TYPE_GDDR3; break;
+       case 0x00000300: pfb->ram.type = NV_MEM_TYPE_GDDR2; break;
+       }
+       pfb->ram.size = nv_rd32(pfb, 0x10020c) & 0xff000000;
+
+       return nv_rd32(pfb, 0x100320);
+}
+
 void
 nv20_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch,
                  u32 flags, struct nouveau_fb_tile *tile)
@@ -92,9 +108,7 @@ nv20_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
             struct nouveau_oclass *oclass, void *data, u32 size,
             struct nouveau_object **pobject)
 {
-       struct nouveau_device *device = nv_device(parent);
        struct nv20_fb_priv *priv;
-       u32 pbus1218;
        int ret;
 
        ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -102,29 +116,14 @@ nv20_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       pbus1218 = nv_rd32(priv, 0x001218);
-       switch (pbus1218 & 0x00000300) {
-       case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break;
-       case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
-       case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
-       case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_GDDR2; break;
-       }
-       priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
-
-       if (device->chipset >= 0x25)
-               ret = nouveau_mm_init(&priv->base.tags, 0, 64 * 1024, 1);
-       else
-               ret = nouveau_mm_init(&priv->base.tags, 0, 32 * 1024, 1);
-       if (ret)
-               return ret;
-
        priv->base.memtype_valid = nv04_fb_memtype_valid;
+       priv->base.ram.init = nv20_fb_vram_init;
        priv->base.tile.regions = 8;
        priv->base.tile.init = nv20_fb_tile_init;
        priv->base.tile.comp = nv20_fb_tile_comp;
        priv->base.tile.fini = nv20_fb_tile_fini;
        priv->base.tile.prog = nv20_fb_tile_prog;
-       return nouveau_fb_created(&priv->base);
+       return nouveau_fb_preinit(&priv->base);
 }
 
 struct nouveau_oclass
index 7529353bc1de18591ce95694d34e46252fb6d591..b6858ca6de863f180a05a041fcfc83b05b3d15bb 100644 (file)
@@ -60,9 +60,7 @@ nv25_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
             struct nouveau_oclass *oclass, void *data, u32 size,
             struct nouveau_object **pobject)
 {
-       struct nouveau_device *device = nv_device(parent);
        struct nv25_fb_priv *priv;
-       u32 pbus1218;
        int ret;
 
        ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -70,29 +68,14 @@ nv25_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       pbus1218 = nv_rd32(priv, 0x001218);
-       switch (pbus1218 & 0x00000300) {
-       case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break;
-       case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
-       case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
-       case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_GDDR2; break;
-       }
-       priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
-
-       if (device->chipset >= 0x25)
-               ret = nouveau_mm_init(&priv->base.tags, 0, 64 * 1024, 1);
-       else
-               ret = nouveau_mm_init(&priv->base.tags, 0, 32 * 1024, 1);
-       if (ret)
-               return ret;
-
        priv->base.memtype_valid = nv04_fb_memtype_valid;
+       priv->base.ram.init = nv20_fb_vram_init;
        priv->base.tile.regions = 8;
        priv->base.tile.init = nv20_fb_tile_init;
        priv->base.tile.comp = nv25_fb_tile_comp;
        priv->base.tile.fini = nv20_fb_tile_fini;
        priv->base.tile.prog = nv20_fb_tile_prog;
-       return nouveau_fb_created(&priv->base);
+       return nouveau_fb_preinit(&priv->base);
 }
 
 struct nouveau_oclass
index d6ed18cc8e8403a2c32448dfe043a466f080059f..c4ab975ac83f2104112c0e75db6c3e1481aee468 100644 (file)
@@ -123,7 +123,6 @@ nv30_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
             struct nouveau_object **pobject)
 {
        struct nv30_fb_priv *priv;
-       u32 pbus1218;
        int ret;
 
        ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -131,22 +130,14 @@ nv30_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       pbus1218 = nv_rd32(priv, 0x001218);
-       switch (pbus1218 & 0x00000300) {
-       case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break;
-       case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
-       case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
-       case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_GDDR2; break;
-       }
-       priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
-
        priv->base.memtype_valid = nv04_fb_memtype_valid;
+       priv->base.ram.init = nv20_fb_vram_init;
        priv->base.tile.regions = 8;
        priv->base.tile.init = nv30_fb_tile_init;
        priv->base.tile.comp = nv30_fb_tile_comp;
        priv->base.tile.fini = nv30_fb_tile_fini;
        priv->base.tile.prog = nv20_fb_tile_prog;
-       return nouveau_fb_created(&priv->base);
+       return nouveau_fb_preinit(&priv->base);
 }
 
 struct nouveau_oclass
index 1c313db8a5606ad56e6f86b849503e2ecc10f8e3..e87086af2311c2c132d480d25716e438f21fc06c 100644 (file)
@@ -43,7 +43,6 @@ nv35_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
             struct nouveau_object **pobject)
 {
        struct nv35_fb_priv *priv;
-       u32 pbus1218;
        int ret;
 
        ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -51,22 +50,14 @@ nv35_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       pbus1218 = nv_rd32(priv, 0x001218);
-       switch (pbus1218 & 0x00000300) {
-       case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break;
-       case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
-       case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
-       case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_GDDR2; break;
-       }
-       priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
-
        priv->base.memtype_valid = nv04_fb_memtype_valid;
+       priv->base.ram.init = nv20_fb_vram_init;
        priv->base.tile.regions = 8;
        priv->base.tile.init = nv30_fb_tile_init;
        priv->base.tile.comp = nv35_fb_tile_comp;
        priv->base.tile.fini = nv30_fb_tile_fini;
        priv->base.tile.prog = nv20_fb_tile_prog;
-       return nouveau_fb_created(&priv->base);
+       return nouveau_fb_preinit(&priv->base);
 }
 
 struct nouveau_oclass
index 425bb1d7ab2b0661047979889c6d663b9ac5cbf2..e942e5b9d66d3aa5418eceb1a34b3b400d9ed542 100644 (file)
@@ -30,6 +30,21 @@ struct nv40_fb_priv {
        struct nouveau_fb base;
 };
 
+static int
+nv40_fb_vram_init(struct nouveau_fb *pfb)
+{
+       u32 pbus1218 = nv_rd32(pfb, 0x001218);
+       switch (pbus1218 & 0x00000300) {
+       case 0x00000000: pfb->ram.type = NV_MEM_TYPE_SDRAM; break;
+       case 0x00000100: pfb->ram.type = NV_MEM_TYPE_DDR1; break;
+       case 0x00000200: pfb->ram.type = NV_MEM_TYPE_GDDR3; break;
+       case 0x00000300: pfb->ram.type = NV_MEM_TYPE_DDR2; break;
+       }
+
+       pfb->ram.size = nv_rd32(pfb, 0x10020c) & 0xff000000;
+       return nv_rd32(pfb, 0x100320);
+}
+
 static void
 nv40_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags,
                  struct nouveau_fb_tile *tile)
@@ -56,9 +71,7 @@ nv40_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
             struct nouveau_oclass *oclass, void *data, u32 size,
             struct nouveau_object **pobject)
 {
-       struct nouveau_device *device = nv_device(parent);
        struct nv40_fb_priv *priv;
-       u32 pbus1218;
        int ret;
 
        ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -66,23 +79,14 @@ nv40_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       pbus1218 = nv_rd32(priv, 0x001218);
-       switch (pbus1218 & 0x00000300) {
-       case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break;
-       case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
-       case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
-       case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_DDR2; break;
-       }
-
-       priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
-
        priv->base.memtype_valid = nv04_fb_memtype_valid;
+       priv->base.ram.init = nv40_fb_vram_init;
        priv->base.tile.regions = 8;
        priv->base.tile.init = nv30_fb_tile_init;
        priv->base.tile.comp = nv40_fb_tile_comp;
        priv->base.tile.fini = nv30_fb_tile_fini;
        priv->base.tile.prog = nv20_fb_tile_prog;
-       return nouveau_fb_created(&priv->base);
+       return nouveau_fb_preinit(&priv->base);
 }
 
 
index 3c974173e184c4cdad8b3d907378f127846d281a..6ddf82ab038aec2fc00b5d37f4be1ef6dfec830b 100644 (file)
@@ -30,6 +30,21 @@ struct nv41_fb_priv {
        struct nouveau_fb base;
 };
 
+int
+nv41_fb_vram_init(struct nouveau_fb *pfb)
+{
+       u32 pfb474 = nv_rd32(pfb, 0x100474);
+       if (pfb474 & 0x00000004)
+               pfb->ram.type = NV_MEM_TYPE_GDDR3;
+       if (pfb474 & 0x00000002)
+               pfb->ram.type = NV_MEM_TYPE_DDR2;
+       if (pfb474 & 0x00000001)
+               pfb->ram.type = NV_MEM_TYPE_DDR1;
+
+       pfb->ram.size = nv_rd32(pfb, 0x10020c) & 0xff000000;
+       return nv_rd32(pfb, 0x100320);
+}
+
 void
 nv41_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)
 {
@@ -59,9 +74,7 @@ nv41_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
             struct nouveau_oclass *oclass, void *data, u32 size,
             struct nouveau_object **pobject)
 {
-       struct nouveau_device *device = nv_device(parent);
        struct nv41_fb_priv *priv;
-       u32 pfb474;
        int ret;
 
        ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -69,22 +82,13 @@ nv41_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       pfb474 = nv_rd32(priv, 0x100474);
-       if (pfb474 & 0x00000004)
-               priv->base.ram.type = NV_MEM_TYPE_GDDR3;
-       if (pfb474 & 0x00000002)
-               priv->base.ram.type = NV_MEM_TYPE_DDR2;
-       if (pfb474 & 0x00000001)
-               priv->base.ram.type = NV_MEM_TYPE_DDR1;
-
-       priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
-
        priv->base.memtype_valid = nv04_fb_memtype_valid;
+       priv->base.ram.init = nv41_fb_vram_init;
        priv->base.tile.regions = 12;
        priv->base.tile.init = nv30_fb_tile_init;
        priv->base.tile.fini = nv30_fb_tile_fini;
        priv->base.tile.prog = nv41_fb_tile_prog;
-       return nouveau_fb_created(&priv->base);
+       return nouveau_fb_preinit(&priv->base);
 }
 
 
index 538b0de8152b148deeb68716feaf227cc3ce310c..46d6518c1a80ebc7dd0f669d30cc04a335987f34 100644 (file)
@@ -30,6 +30,21 @@ struct nv44_fb_priv {
        struct nouveau_fb base;
 };
 
+int
+nv44_fb_vram_init(struct nouveau_fb *pfb)
+{
+       u32 pfb474 = nv_rd32(pfb, 0x100474);
+       if (pfb474 & 0x00000004)
+               pfb->ram.type = NV_MEM_TYPE_GDDR3;
+       if (pfb474 & 0x00000002)
+               pfb->ram.type = NV_MEM_TYPE_DDR2;
+       if (pfb474 & 0x00000001)
+               pfb->ram.type = NV_MEM_TYPE_DDR1;
+
+       pfb->ram.size = nv_rd32(pfb, 0x10020c) & 0xff000000;
+       return 0;
+}
+
 static void
 nv44_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch,
                  u32 flags, struct nouveau_fb_tile *tile)
@@ -69,9 +84,7 @@ nv44_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
             struct nouveau_oclass *oclass, void *data, u32 size,
             struct nouveau_object **pobject)
 {
-       struct nouveau_device *device = nv_device(parent);
        struct nv44_fb_priv *priv;
-       u32 pfb474;
        int ret;
 
        ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -79,22 +92,13 @@ nv44_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       pfb474 = nv_rd32(priv, 0x100474);
-       if (pfb474 & 0x00000004)
-               priv->base.ram.type = NV_MEM_TYPE_GDDR3;
-       if (pfb474 & 0x00000002)
-               priv->base.ram.type = NV_MEM_TYPE_DDR2;
-       if (pfb474 & 0x00000001)
-               priv->base.ram.type = NV_MEM_TYPE_DDR1;
-
-       priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
-
        priv->base.memtype_valid = nv04_fb_memtype_valid;
+       priv->base.ram.init = nv44_fb_vram_init;
        priv->base.tile.regions = 12;
        priv->base.tile.init = nv44_fb_tile_init;
        priv->base.tile.fini = nv30_fb_tile_fini;
        priv->base.tile.prog = nv44_fb_tile_prog;
-       return nouveau_fb_created(&priv->base);
+       return nouveau_fb_preinit(&priv->base);
 }
 
 
index 57b6ff28db01e784a5807db6741347df7475eee8..b8fcbd6f80b4a6572cd56eba298014daa5f826f0 100644 (file)
@@ -49,9 +49,7 @@ nv46_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
             struct nouveau_oclass *oclass, void *data, u32 size,
             struct nouveau_object **pobject)
 {
-       struct nouveau_device *device = nv_device(parent);
        struct nv46_fb_priv *priv;
-       u32 pfb474;
        int ret;
 
        ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -59,22 +57,13 @@ nv46_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       pfb474 = nv_rd32(priv, 0x100474);
-       if (pfb474 & 0x00000004)
-               priv->base.ram.type = NV_MEM_TYPE_GDDR3;
-       if (pfb474 & 0x00000002)
-               priv->base.ram.type = NV_MEM_TYPE_DDR2;
-       if (pfb474 & 0x00000001)
-               priv->base.ram.type = NV_MEM_TYPE_DDR1;
-
-       priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
-
        priv->base.memtype_valid = nv04_fb_memtype_valid;
+       priv->base.ram.init = nv44_fb_vram_init;
        priv->base.tile.regions = 15;
        priv->base.tile.init = nv46_fb_tile_init;
        priv->base.tile.fini = nv30_fb_tile_fini;
        priv->base.tile.prog = nv44_fb_tile_prog;
-       return nouveau_fb_created(&priv->base);
+       return nouveau_fb_preinit(&priv->base);
 }
 
 
index 6fb5305781f230c6695705b62a7cd1b986e6cc6a..bfe1962df50bcad024dd3fb8e3d9046d1f4ae4f6 100644 (file)
@@ -35,9 +35,7 @@ nv47_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
             struct nouveau_oclass *oclass, void *data, u32 size,
             struct nouveau_object **pobject)
 {
-       struct nouveau_device *device = nv_device(parent);
        struct nv47_fb_priv *priv;
-       u32 pfb474;
        int ret;
 
        ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -45,22 +43,13 @@ nv47_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       pfb474 = nv_rd32(priv, 0x100474);
-       if (pfb474 & 0x00000004)
-               priv->base.ram.type = NV_MEM_TYPE_GDDR3;
-       if (pfb474 & 0x00000002)
-               priv->base.ram.type = NV_MEM_TYPE_DDR2;
-       if (pfb474 & 0x00000001)
-               priv->base.ram.type = NV_MEM_TYPE_DDR1;
-
-       priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
-
        priv->base.memtype_valid = nv04_fb_memtype_valid;
+       priv->base.ram.init = nv41_fb_vram_init;
        priv->base.tile.regions = 15;
        priv->base.tile.init = nv30_fb_tile_init;
        priv->base.tile.fini = nv30_fb_tile_fini;
        priv->base.tile.prog = nv41_fb_tile_prog;
-       return nouveau_fb_created(&priv->base);
+       return nouveau_fb_preinit(&priv->base);
 }
 
 
index a88638f14c729694c2bf64b3534829483486a233..3d64195b737fbf2668b1a2ece857d017ea9ce66b 100644 (file)
@@ -30,14 +30,28 @@ struct nv49_fb_priv {
        struct nouveau_fb base;
 };
 
+static int
+nv49_fb_vram_init(struct nouveau_fb *pfb)
+{
+       u32 pfb914 = nv_rd32(pfb, 0x100914);
+
+       switch (pfb914 & 0x00000003) {
+       case 0x00000000: pfb->ram.type = NV_MEM_TYPE_DDR1; break;
+       case 0x00000001: pfb->ram.type = NV_MEM_TYPE_DDR2; break;
+       case 0x00000002: pfb->ram.type = NV_MEM_TYPE_GDDR3; break;
+       case 0x00000003: break;
+       }
+
+       pfb->ram.size = nv_rd32(pfb, 0x10020c) & 0xff000000;
+       return nv_rd32(pfb, 0x100320);
+}
+
 static int
 nv49_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
             struct nouveau_oclass *oclass, void *data, u32 size,
             struct nouveau_object **pobject)
 {
-       struct nouveau_device *device = nv_device(parent);
        struct nv49_fb_priv *priv;
-       u32 pfb914;
        int ret;
 
        ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -45,23 +59,14 @@ nv49_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       pfb914 = nv_rd32(priv, 0x100914);
-       switch (pfb914 & 0x00000003) {
-       case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
-       case 0x00000001: priv->base.ram.type = NV_MEM_TYPE_DDR2; break;
-       case 0x00000002: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
-       case 0x00000003: break;
-       }
-
-       priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
-
        priv->base.memtype_valid = nv04_fb_memtype_valid;
+       priv->base.ram.init = nv49_fb_vram_init;
        priv->base.tile.regions = 15;
        priv->base.tile.init = nv30_fb_tile_init;
        priv->base.tile.fini = nv30_fb_tile_fini;
        priv->base.tile.prog = nv41_fb_tile_prog;
 
-       return nouveau_fb_created(&priv->base);
+       return nouveau_fb_preinit(&priv->base);
 }
 
 
index fab8b19df4ee5e4d5171d8a800eb9bb70b7abcdd..9b79994159f4e3508aac0973e0d34444dfa35d0f 100644 (file)
@@ -30,12 +30,19 @@ struct nv4e_fb_priv {
        struct nouveau_fb base;
 };
 
+static int
+nv4e_fb_vram_init(struct nouveau_fb *pfb)
+{
+       pfb->ram.size = nv_rd32(pfb, 0x10020c) & 0xff000000;
+       pfb->ram.type = NV_MEM_TYPE_STOLEN;
+       return 0;
+}
+
 static int
 nv4e_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
             struct nouveau_oclass *oclass, void *data, u32 size,
             struct nouveau_object **pobject)
 {
-       struct nouveau_device *device = nv_device(parent);
        struct nv4e_fb_priv *priv;
        int ret;
 
@@ -44,17 +51,15 @@ nv4e_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
-       priv->base.ram.type = NV_MEM_TYPE_STOLEN;
        priv->base.memtype_valid = nv04_fb_memtype_valid;
+       priv->base.ram.init = nv4e_fb_vram_init;
        priv->base.tile.regions = 12;
        priv->base.tile.init = nv46_fb_tile_init;
        priv->base.tile.fini = nv30_fb_tile_fini;
        priv->base.tile.prog = nv44_fb_tile_prog;
-       return nouveau_fb_created(&priv->base);
+       return nouveau_fb_preinit(&priv->base);
 }
 
-
 struct nouveau_oclass
 nv4e_fb_oclass = {
        .handle = NV_SUBDEV(FB, 0x4e),
index 5f570806143ad0fb35fcd67017acf07513b563e4..2c1ee3f6feef9ba04d6db3137144c9523d68aed3 100644 (file)
@@ -51,6 +51,101 @@ nv50_fb_memtype_valid(struct nouveau_fb *pfb, u32 memtype)
        return types[(memtype & 0xff00) >> 8] != 0;
 }
 
+static u32
+nv50_fb_vram_rblock(struct nouveau_fb *pfb)
+{
+       int i, parts, colbits, rowbitsa, rowbitsb, banks;
+       u64 rowsize, predicted;
+       u32 r0, r4, rt, ru, rblock_size;
+
+       r0 = nv_rd32(pfb, 0x100200);
+       r4 = nv_rd32(pfb, 0x100204);
+       rt = nv_rd32(pfb, 0x100250);
+       ru = nv_rd32(pfb, 0x001540);
+       nv_debug(pfb, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru);
+
+       for (i = 0, parts = 0; i < 8; i++) {
+               if (ru & (0x00010000 << i))
+                       parts++;
+       }
+
+       colbits  =  (r4 & 0x0000f000) >> 12;
+       rowbitsa = ((r4 & 0x000f0000) >> 16) + 8;
+       rowbitsb = ((r4 & 0x00f00000) >> 20) + 8;
+       banks    = 1 << (((r4 & 0x03000000) >> 24) + 2);
+
+       rowsize = parts * banks * (1 << colbits) * 8;
+       predicted = rowsize << rowbitsa;
+       if (r0 & 0x00000004)
+               predicted += rowsize << rowbitsb;
+
+       if (predicted != pfb->ram.size) {
+               nv_warn(pfb, "memory controller reports %d MiB VRAM\n",
+                       (u32)(pfb->ram.size >> 20));
+       }
+
+       rblock_size = rowsize;
+       if (rt & 1)
+               rblock_size *= 3;
+
+       nv_debug(pfb, "rblock %d bytes\n", rblock_size);
+       return rblock_size;
+}
+
+static int
+nv50_fb_vram_init(struct nouveau_fb *pfb)
+{
+       struct nouveau_device *device = nv_device(pfb);
+       struct nouveau_bios *bios = nouveau_bios(device);
+       const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
+       const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
+       u32 size;
+       int ret;
+
+       pfb->ram.size = nv_rd32(pfb, 0x10020c);
+       pfb->ram.size = (pfb->ram.size & 0xffffff00) |
+                      ((pfb->ram.size & 0x000000ff) << 32);
+
+       size = (pfb->ram.size >> 12) - rsvd_head - rsvd_tail;
+       switch (device->chipset) {
+       case 0xaa:
+       case 0xac:
+       case 0xaf: /* IGPs, no reordering, no real VRAM */
+               ret = nouveau_mm_init(&pfb->vram, rsvd_head, size, 1);
+               if (ret)
+                       return ret;
+
+               pfb->ram.type   = NV_MEM_TYPE_STOLEN;
+               pfb->ram.stolen = (u64)nv_rd32(pfb, 0x100e10) << 12;
+               break;
+       default:
+               switch (nv_rd32(pfb, 0x100714) & 0x00000007) {
+               case 0: pfb->ram.type = NV_MEM_TYPE_DDR1; break;
+               case 1:
+                       if (nouveau_fb_bios_memtype(bios) == NV_MEM_TYPE_DDR3)
+                               pfb->ram.type = NV_MEM_TYPE_DDR3;
+                       else
+                               pfb->ram.type = NV_MEM_TYPE_DDR2;
+                       break;
+               case 2: pfb->ram.type = NV_MEM_TYPE_GDDR3; break;
+               case 3: pfb->ram.type = NV_MEM_TYPE_GDDR4; break;
+               case 4: pfb->ram.type = NV_MEM_TYPE_GDDR5; break;
+               default:
+                       break;
+               }
+
+               ret = nouveau_mm_init(&pfb->vram, rsvd_head, size,
+                                     nv50_fb_vram_rblock(pfb) >> 12);
+               if (ret)
+                       return ret;
+
+               pfb->ram.ranks = (nv_rd32(pfb, 0x100200) & 0x4) ? 2 : 1;
+               break;
+       }
+
+       return nv_rd32(pfb, 0x100320);
+}
+
 static int
 nv50_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
                 u32 memtype, struct nouveau_mem **pmem)
@@ -140,58 +235,13 @@ nv50_fb_vram_del(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
        kfree(mem);
 }
 
-static u32
-nv50_vram_rblock(struct nv50_fb_priv *priv)
-{
-       int i, parts, colbits, rowbitsa, rowbitsb, banks;
-       u64 rowsize, predicted;
-       u32 r0, r4, rt, ru, rblock_size;
-
-       r0 = nv_rd32(priv, 0x100200);
-       r4 = nv_rd32(priv, 0x100204);
-       rt = nv_rd32(priv, 0x100250);
-       ru = nv_rd32(priv, 0x001540);
-       nv_debug(priv, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru);
-
-       for (i = 0, parts = 0; i < 8; i++) {
-               if (ru & (0x00010000 << i))
-                       parts++;
-       }
-
-       colbits  =  (r4 & 0x0000f000) >> 12;
-       rowbitsa = ((r4 & 0x000f0000) >> 16) + 8;
-       rowbitsb = ((r4 & 0x00f00000) >> 20) + 8;
-       banks    = 1 << (((r4 & 0x03000000) >> 24) + 2);
-
-       rowsize = parts * banks * (1 << colbits) * 8;
-       predicted = rowsize << rowbitsa;
-       if (r0 & 0x00000004)
-               predicted += rowsize << rowbitsb;
-
-       if (predicted != priv->base.ram.size) {
-               nv_warn(priv, "memory controller reports %d MiB VRAM\n",
-                       (u32)(priv->base.ram.size >> 20));
-       }
-
-       rblock_size = rowsize;
-       if (rt & 1)
-               rblock_size *= 3;
-
-       nv_debug(priv, "rblock %d bytes\n", rblock_size);
-       return rblock_size;
-}
-
 static int
 nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
             struct nouveau_oclass *oclass, void *data, u32 size,
             struct nouveau_object **pobject)
 {
        struct nouveau_device *device = nv_device(parent);
-       struct nouveau_bios *bios = nouveau_bios(device);
-       const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
-       const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
        struct nv50_fb_priv *priv;
-       u32 tags;
        int ret;
 
        ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -199,54 +249,6 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       switch (nv_rd32(priv, 0x100714) & 0x00000007) {
-       case 0: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
-       case 1:
-               if (nouveau_fb_bios_memtype(bios) == NV_MEM_TYPE_DDR3)
-                       priv->base.ram.type = NV_MEM_TYPE_DDR3;
-               else
-                       priv->base.ram.type = NV_MEM_TYPE_DDR2;
-               break;
-       case 2: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
-       case 3: priv->base.ram.type = NV_MEM_TYPE_GDDR4; break;
-       case 4: priv->base.ram.type = NV_MEM_TYPE_GDDR5; break;
-       default:
-               break;
-       }
-
-       priv->base.ram.size = nv_rd32(priv, 0x10020c);
-       priv->base.ram.size = (priv->base.ram.size & 0xffffff00) |
-                            ((priv->base.ram.size & 0x000000ff) << 32);
-
-       tags = nv_rd32(priv, 0x100320);
-       ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1);
-       if (ret)
-               return ret;
-
-       nv_debug(priv, "%d compression tags\n", tags);
-
-       size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail;
-       switch (device->chipset) {
-       case 0xaa:
-       case 0xac:
-       case 0xaf: /* IGPs, no reordering, no real VRAM */
-               ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size, 1);
-               if (ret)
-                       return ret;
-
-               priv->base.ram.stolen = (u64)nv_rd32(priv, 0x100e10) << 12;
-               priv->base.ram.type = NV_MEM_TYPE_STOLEN;
-               break;
-       default:
-               ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size,
-                                     nv50_vram_rblock(priv) >> 12);
-               if (ret)
-                       return ret;
-
-               priv->base.ram.ranks = (nv_rd32(priv, 0x100200) & 0x4) ? 2 : 1;
-               break;
-       }
-
        priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
        if (priv->r100c08_page) {
                priv->r100c08 = pci_map_page(device->pdev, priv->r100c08_page,
@@ -259,9 +261,10 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        }
 
        priv->base.memtype_valid = nv50_fb_memtype_valid;
+       priv->base.ram.init = nv50_fb_vram_init;
        priv->base.ram.get = nv50_fb_vram_new;
        priv->base.ram.put = nv50_fb_vram_del;
-       return nouveau_fb_created(&priv->base);
+       return nouveau_fb_preinit(&priv->base);
 }
 
 static void
index 9f59f2bf00796fe25e75b5602a226769a816772c..306bdf121452e6e9da8d6ddeb7ba6210ddeb0bde 100644 (file)
@@ -61,6 +61,65 @@ nvc0_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags)
        return likely((types[memtype] == 1));
 }
 
+static int
+nvc0_fb_vram_init(struct nouveau_fb *pfb)
+{
+       struct nouveau_bios *bios = nouveau_bios(pfb);
+       const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
+       const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
+       u32 parts = nv_rd32(pfb, 0x022438);
+       u32 pmask = nv_rd32(pfb, 0x022554);
+       u32 bsize = nv_rd32(pfb, 0x10f20c);
+       u32 offset, length;
+       bool uniform = true;
+       int ret, part;
+
+       nv_debug(pfb, "0x100800: 0x%08x\n", nv_rd32(pfb, 0x100800));
+       nv_debug(pfb, "parts 0x%08x mask 0x%08x\n", parts, pmask);
+
+       pfb->ram.type = nouveau_fb_bios_memtype(bios);
+       pfb->ram.ranks = (nv_rd32(pfb, 0x10f200) & 0x00000004) ? 2 : 1;
+
+       /* read amount of vram attached to each memory controller */
+       for (part = 0; part < parts; part++) {
+               if (!(pmask & (1 << part))) {
+                       u32 psize = nv_rd32(pfb, 0x11020c + (part * 0x1000));
+                       if (psize != bsize) {
+                               if (psize < bsize)
+                                       bsize = psize;
+                               uniform = false;
+                       }
+
+                       nv_debug(pfb, "%d: mem_amount 0x%08x\n", part, psize);
+                       pfb->ram.size += (u64)psize << 20;
+               }
+       }
+
+       /* if all controllers have the same amount attached, there's no holes */
+       if (uniform) {
+               offset = rsvd_head;
+               length = (pfb->ram.size >> 12) - rsvd_head - rsvd_tail;
+               return nouveau_mm_init(&pfb->vram, offset, length, 1);
+       }
+
+       /* otherwise, address lowest common amount from 0GiB */
+       ret = nouveau_mm_init(&pfb->vram, rsvd_head, (bsize << 8) * parts, 1);
+       if (ret)
+               return ret;
+
+       /* and the rest starting from (8GiB + common_size) */
+       offset = (0x0200000000ULL >> 12) + (bsize << 8);
+       length = (pfb->ram.size >> 12) - (bsize << 8) - rsvd_tail;
+
+       ret = nouveau_mm_init(&pfb->vram, offset, length, 0);
+       if (ret) {
+               nouveau_mm_fini(&pfb->vram);
+               return ret;
+       }
+
+       return 0;
+}
+
 static int
 nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
                 u32 memtype, struct nouveau_mem **pmem)
@@ -138,66 +197,6 @@ nvc0_fb_dtor(struct nouveau_object *object)
        nouveau_fb_destroy(&priv->base);
 }
 
-static int
-nvc0_vram_detect(struct nvc0_fb_priv *priv)
-{
-       struct nouveau_bios *bios = nouveau_bios(priv);
-       struct nouveau_fb *pfb = &priv->base;
-       const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
-       const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
-       u32 parts = nv_rd32(priv, 0x022438);
-       u32 pmask = nv_rd32(priv, 0x022554);
-       u32 bsize = nv_rd32(priv, 0x10f20c);
-       u32 offset, length;
-       bool uniform = true;
-       int ret, part;
-
-       nv_debug(priv, "0x100800: 0x%08x\n", nv_rd32(priv, 0x100800));
-       nv_debug(priv, "parts 0x%08x mask 0x%08x\n", parts, pmask);
-
-       priv->base.ram.type = nouveau_fb_bios_memtype(bios);
-       priv->base.ram.ranks = (nv_rd32(priv, 0x10f200) & 0x00000004) ? 2 : 1;
-
-       /* read amount of vram attached to each memory controller */
-       for (part = 0; part < parts; part++) {
-               if (!(pmask & (1 << part))) {
-                       u32 psize = nv_rd32(priv, 0x11020c + (part * 0x1000));
-                       if (psize != bsize) {
-                               if (psize < bsize)
-                                       bsize = psize;
-                               uniform = false;
-                       }
-
-                       nv_debug(priv, "%d: mem_amount 0x%08x\n", part, psize);
-                       priv->base.ram.size += (u64)psize << 20;
-               }
-       }
-
-       /* if all controllers have the same amount attached, there's no holes */
-       if (uniform) {
-               offset = rsvd_head;
-               length = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail;
-               return nouveau_mm_init(&pfb->vram, offset, length, 1);
-       }
-
-       /* otherwise, address lowest common amount from 0GiB */
-       ret = nouveau_mm_init(&pfb->vram, rsvd_head, (bsize << 8) * parts, 1);
-       if (ret)
-               return ret;
-
-       /* and the rest starting from (8GiB + common_size) */
-       offset = (0x0200000000ULL >> 12) + (bsize << 8);
-       length = (priv->base.ram.size >> 12) - (bsize << 8) - rsvd_tail;
-
-       ret = nouveau_mm_init(&pfb->vram, offset, length, 0);
-       if (ret) {
-               nouveau_mm_fini(&pfb->vram);
-               return ret;
-       }
-
-       return 0;
-}
-
 static int
 nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
             struct nouveau_oclass *oclass, void *data, u32 size,
@@ -213,13 +212,10 @@ nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                return ret;
 
        priv->base.memtype_valid = nvc0_fb_memtype_valid;
+       priv->base.ram.init = nvc0_fb_vram_init;
        priv->base.ram.get = nvc0_fb_vram_new;
        priv->base.ram.put = nv50_fb_vram_del;
 
-       ret = nvc0_vram_detect(priv);
-       if (ret)
-               return ret;
-
        priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
        if (!priv->r100c10_page)
                return -ENOMEM;
@@ -229,7 +225,7 @@ nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (pci_dma_mapping_error(device->pdev, priv->r100c10))
                return -EFAULT;
 
-       return nouveau_fb_created(&priv->base);
+       return nouveau_fb_preinit(&priv->base);
 }