aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2012-10-09 21:31:11 -0400
committerBen Skeggs <bskeggs@redhat.com>2012-11-28 18:56:31 -0500
commitdac1558d49d0a9f932babd66144459ef3dd5dfa9 (patch)
treea5837e36f65e798578565923e639036639e83593
parent268d5a30173a77a6e762d98adb8d411ccd714b25 (diff)
drm/nouveau/fb: create tag heap from common code for all relevant chipsets
A nv2x bug wrt hardcoded tag counts is now also fixed as a side-effect. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/Makefile1
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/fb.h12
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/device/nv10.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/base.c84
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c62
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c53
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c89
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c37
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nv25.c21
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c13
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nv35.c13
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c30
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nv41.c30
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nv44.c30
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nv46.c15
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nv47.c15
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nv49.c31
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nv4e.c15
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c191
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c126
20 files changed, 468 insertions, 404 deletions
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile
index 4426f9ac6a86..4f08a0496d6f 100644
--- a/drivers/gpu/drm/nouveau/Makefile
+++ b/drivers/gpu/drm/nouveau/Makefile
@@ -64,6 +64,7 @@ nouveau-y += core/subdev/devinit/nv50.o
64nouveau-y += core/subdev/fb/base.o 64nouveau-y += core/subdev/fb/base.o
65nouveau-y += core/subdev/fb/nv04.o 65nouveau-y += core/subdev/fb/nv04.o
66nouveau-y += core/subdev/fb/nv10.o 66nouveau-y += core/subdev/fb/nv10.o
67nouveau-y += core/subdev/fb/nv1a.o
67nouveau-y += core/subdev/fb/nv20.o 68nouveau-y += core/subdev/fb/nv20.o
68nouveau-y += core/subdev/fb/nv25.o 69nouveau-y += core/subdev/fb/nv25.o
69nouveau-y += core/subdev/fb/nv30.o 70nouveau-y += core/subdev/fb/nv30.o
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h
index 3108f19ef505..9f3e82976ec7 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h
@@ -71,6 +71,7 @@ struct nouveau_fb {
71 u64 size; 71 u64 size;
72 int ranks; 72 int ranks;
73 73
74 int (*init)(struct nouveau_fb *);
74 int (*get)(struct nouveau_fb *, u64 size, u32 align, 75 int (*get)(struct nouveau_fb *, u64 size, u32 align,
75 u32 size_nc, u32 type, struct nouveau_mem **); 76 u32 size_nc, u32 type, struct nouveau_mem **);
76 void (*put)(struct nouveau_fb *, struct nouveau_mem **); 77 void (*put)(struct nouveau_fb *, struct nouveau_mem **);
@@ -101,7 +102,7 @@ nouveau_fb(void *obj)
101 102
102#define nouveau_fb_create(p,e,c,d) \ 103#define nouveau_fb_create(p,e,c,d) \
103 nouveau_subdev_create((p), (e), (c), 0, "PFB", "fb", (d)) 104 nouveau_subdev_create((p), (e), (c), 0, "PFB", "fb", (d))
104int nouveau_fb_created(struct nouveau_fb *); 105int nouveau_fb_preinit(struct nouveau_fb *);
105void nouveau_fb_destroy(struct nouveau_fb *); 106void nouveau_fb_destroy(struct nouveau_fb *);
106int nouveau_fb_init(struct nouveau_fb *); 107int nouveau_fb_init(struct nouveau_fb *);
107#define nouveau_fb_fini(p,s) \ 108#define nouveau_fb_fini(p,s) \
@@ -113,6 +114,7 @@ int _nouveau_fb_init(struct nouveau_object *);
113 114
114extern struct nouveau_oclass nv04_fb_oclass; 115extern struct nouveau_oclass nv04_fb_oclass;
115extern struct nouveau_oclass nv10_fb_oclass; 116extern struct nouveau_oclass nv10_fb_oclass;
117extern struct nouveau_oclass nv1a_fb_oclass;
116extern struct nouveau_oclass nv20_fb_oclass; 118extern struct nouveau_oclass nv20_fb_oclass;
117extern struct nouveau_oclass nv25_fb_oclass; 119extern struct nouveau_oclass nv25_fb_oclass;
118extern struct nouveau_oclass nv30_fb_oclass; 120extern struct nouveau_oclass nv30_fb_oclass;
@@ -132,6 +134,12 @@ int nouveau_fb_bios_memtype(struct nouveau_bios *);
132 134
133bool nv04_fb_memtype_valid(struct nouveau_fb *, u32 memtype); 135bool nv04_fb_memtype_valid(struct nouveau_fb *, u32 memtype);
134 136
137void nv10_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size,
138 u32 pitch, u32 flags, struct nouveau_fb_tile *);
139void nv10_fb_tile_fini(struct nouveau_fb *, int i, struct nouveau_fb_tile *);
140void nv10_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *);
141
142int nv20_fb_vram_init(struct nouveau_fb *);
135void nv20_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size, 143void nv20_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size,
136 u32 pitch, u32 flags, struct nouveau_fb_tile *); 144 u32 pitch, u32 flags, struct nouveau_fb_tile *);
137void nv20_fb_tile_fini(struct nouveau_fb *, int i, struct nouveau_fb_tile *); 145void 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,
142 u32 pitch, u32 flags, struct nouveau_fb_tile *); 150 u32 pitch, u32 flags, struct nouveau_fb_tile *);
143void nv30_fb_tile_fini(struct nouveau_fb *, int i, struct nouveau_fb_tile *); 151void nv30_fb_tile_fini(struct nouveau_fb *, int i, struct nouveau_fb_tile *);
144 152
153int nv41_fb_vram_init(struct nouveau_fb *);
145int nv41_fb_init(struct nouveau_object *); 154int nv41_fb_init(struct nouveau_object *);
146void nv41_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *); 155void nv41_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *);
147 156
157int nv44_fb_vram_init(struct nouveau_fb *);
148int nv44_fb_init(struct nouveau_object *); 158int nv44_fb_init(struct nouveau_object *);
149void nv44_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *); 159void nv44_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *);
150 160
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c
index f09accfd0e31..9c40b0fb23f6 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c
@@ -105,7 +105,7 @@ nv10_identify(struct nouveau_device *device)
105 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 105 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
106 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 106 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
107 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 107 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
108 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; 108 device->oclass[NVDEV_SUBDEV_FB ] = &nv1a_fb_oclass;
109 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; 109 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
110 device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; 110 device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
111 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; 111 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -159,7 +159,7 @@ nv10_identify(struct nouveau_device *device)
159 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 159 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
160 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 160 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
161 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 161 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
162 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; 162 device->oclass[NVDEV_SUBDEV_FB ] = &nv1a_fb_oclass;
163 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; 163 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
164 device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; 164 device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
165 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; 165 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/base.c b/drivers/gpu/drm/nouveau/core/subdev/fb/base.c
index 9fae64d60954..d6d16007ec1a 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/base.c
@@ -57,25 +57,45 @@ nouveau_fb_bios_memtype(struct nouveau_bios *bios)
57} 57}
58 58
59int 59int
60nouveau_fb_init(struct nouveau_fb *pfb) 60nouveau_fb_preinit(struct nouveau_fb *pfb)
61{ 61{
62 int ret, i; 62 static const char *name[] = {
63 [NV_MEM_TYPE_UNKNOWN] = "unknown",
64 [NV_MEM_TYPE_STOLEN ] = "stolen system memory",
65 [NV_MEM_TYPE_SGRAM ] = "SGRAM",
66 [NV_MEM_TYPE_SDRAM ] = "SDRAM",
67 [NV_MEM_TYPE_DDR1 ] = "DDR1",
68 [NV_MEM_TYPE_DDR2 ] = "DDR2",
69 [NV_MEM_TYPE_DDR3 ] = "DDR3",
70 [NV_MEM_TYPE_GDDR2 ] = "GDDR2",
71 [NV_MEM_TYPE_GDDR3 ] = "GDDR3",
72 [NV_MEM_TYPE_GDDR4 ] = "GDDR4",
73 [NV_MEM_TYPE_GDDR5 ] = "GDDR5",
74 };
75 int ret, tags;
63 76
64 ret = nouveau_subdev_init(&pfb->base); 77 tags = pfb->ram.init(pfb);
65 if (ret) 78 if (tags < 0 || !pfb->ram.size) {
66 return ret; 79 nv_fatal(pfb, "error detecting memory configuration!!\n");
80 return (tags < 0) ? tags : -ERANGE;
81 }
67 82
68 for (i = 0; i < pfb->tile.regions; i++) 83 if (!nouveau_mm_initialised(&pfb->vram)) {
69 pfb->tile.prog(pfb, i, &pfb->tile.region[i]); 84 ret = nouveau_mm_init(&pfb->vram, 0, pfb->ram.size >> 12, 1);
85 if (ret)
86 return ret;
87 }
70 88
71 return 0; 89 if (!nouveau_mm_initialised(&pfb->tags) && tags) {
72} 90 ret = nouveau_mm_init(&pfb->tags, 0, ++tags, 1);
91 if (ret)
92 return ret;
93 }
73 94
74int 95 nv_info(pfb, "RAM type: %s\n", name[pfb->ram.type]);
75_nouveau_fb_init(struct nouveau_object *object) 96 nv_info(pfb, "RAM size: %d MiB\n", (int)(pfb->ram.size >> 20));
76{ 97 nv_info(pfb, " ZCOMP: %d tags\n", tags);
77 struct nouveau_fb *pfb = (void *)object; 98 return 0;
78 return nouveau_fb_init(pfb);
79} 99}
80 100
81void 101void
@@ -97,30 +117,24 @@ _nouveau_fb_dtor(struct nouveau_object *object)
97 struct nouveau_fb *pfb = (void *)object; 117 struct nouveau_fb *pfb = (void *)object;
98 nouveau_fb_destroy(pfb); 118 nouveau_fb_destroy(pfb);
99} 119}
100
101int 120int
102nouveau_fb_created(struct nouveau_fb *pfb) 121nouveau_fb_init(struct nouveau_fb *pfb)
103{ 122{
104 static const char *name[] = { 123 int ret, i;
105 [NV_MEM_TYPE_UNKNOWN] = "unknown",
106 [NV_MEM_TYPE_STOLEN ] = "stolen system memory",
107 [NV_MEM_TYPE_SGRAM ] = "SGRAM",
108 [NV_MEM_TYPE_SDRAM ] = "SDRAM",
109 [NV_MEM_TYPE_DDR1 ] = "DDR1",
110 [NV_MEM_TYPE_DDR2 ] = "DDR2",
111 [NV_MEM_TYPE_DDR3 ] = "DDR3",
112 [NV_MEM_TYPE_GDDR2 ] = "GDDR2",
113 [NV_MEM_TYPE_GDDR3 ] = "GDDR3",
114 [NV_MEM_TYPE_GDDR4 ] = "GDDR4",
115 [NV_MEM_TYPE_GDDR5 ] = "GDDR5",
116 };
117 124
118 if (pfb->ram.size == 0) { 125 ret = nouveau_subdev_init(&pfb->base);
119 nv_fatal(pfb, "no vram detected!!\n"); 126 if (ret)
120 return -ERANGE; 127 return ret;
121 } 128
129 for (i = 0; i < pfb->tile.regions; i++)
130 pfb->tile.prog(pfb, i, &pfb->tile.region[i]);
122 131
123 nv_info(pfb, "RAM type: %s\n", name[pfb->ram.type]);
124 nv_info(pfb, "RAM size: %d MiB\n", (int)(pfb->ram.size >> 20));
125 return 0; 132 return 0;
126} 133}
134
135int
136_nouveau_fb_init(struct nouveau_object *object)
137{
138 struct nouveau_fb *pfb = (void *)object;
139 return nouveau_fb_init(pfb);
140}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c
index eb06836b69f7..6e369f85361e 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c
@@ -56,6 +56,37 @@ nv04_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags)
56} 56}
57 57
58static int 58static int
59nv04_fb_vram_init(struct nouveau_fb *pfb)
60{
61 u32 boot0 = nv_rd32(pfb, NV04_PFB_BOOT_0);
62 if (boot0 & 0x00000100) {
63 pfb->ram.size = ((boot0 >> 12) & 0xf) * 2 + 2;
64 pfb->ram.size *= 1024 * 1024;
65 } else {
66 switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) {
67 case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB:
68 pfb->ram.size = 32 * 1024 * 1024;
69 break;
70 case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB:
71 pfb->ram.size = 16 * 1024 * 1024;
72 break;
73 case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB:
74 pfb->ram.size = 8 * 1024 * 1024;
75 break;
76 case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB:
77 pfb->ram.size = 4 * 1024 * 1024;
78 break;
79 }
80 }
81
82 if ((boot0 & 0x00000038) <= 0x10)
83 pfb->ram.type = NV_MEM_TYPE_SGRAM;
84 else
85 pfb->ram.type = NV_MEM_TYPE_SDRAM;
86 return 0;
87}
88
89static int
59nv04_fb_init(struct nouveau_object *object) 90nv04_fb_init(struct nouveau_object *object)
60{ 91{
61 struct nv04_fb_priv *priv = (void *)object; 92 struct nv04_fb_priv *priv = (void *)object;
@@ -79,7 +110,6 @@ nv04_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
79 struct nouveau_object **pobject) 110 struct nouveau_object **pobject)
80{ 111{
81 struct nv04_fb_priv *priv; 112 struct nv04_fb_priv *priv;
82 u32 boot0;
83 int ret; 113 int ret;
84 114
85 ret = nouveau_fb_create(parent, engine, oclass, &priv); 115 ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -87,35 +117,9 @@ nv04_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
87 if (ret) 117 if (ret)
88 return ret; 118 return ret;
89 119
90 boot0 = nv_rd32(priv, NV04_PFB_BOOT_0);
91 if (boot0 & 0x00000100) {
92 priv->base.ram.size = ((boot0 >> 12) & 0xf) * 2 + 2;
93 priv->base.ram.size *= 1024 * 1024;
94 } else {
95 switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) {
96 case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB:
97 priv->base.ram.size = 32 * 1024 * 1024;
98 break;
99 case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB:
100 priv->base.ram.size = 16 * 1024 * 1024;
101 break;
102 case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB:
103 priv->base.ram.size = 8 * 1024 * 1024;
104 break;
105 case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB:
106 priv->base.ram.size = 4 * 1024 * 1024;
107 break;
108 }
109 }
110
111 if ((boot0 & 0x00000038) <= 0x10)
112 priv->base.ram.type = NV_MEM_TYPE_SGRAM;
113 else
114 priv->base.ram.type = NV_MEM_TYPE_SDRAM;
115
116
117 priv->base.memtype_valid = nv04_fb_memtype_valid; 120 priv->base.memtype_valid = nv04_fb_memtype_valid;
118 return nouveau_fb_created(&priv->base); 121 priv->base.ram.init = nv04_fb_vram_init;
122 return nouveau_fb_preinit(&priv->base);
119} 123}
120 124
121struct nouveau_oclass 125struct nouveau_oclass
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c
index 12193d9dd2a6..edbbe26e858d 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c
@@ -30,7 +30,20 @@ struct nv10_fb_priv {
30 struct nouveau_fb base; 30 struct nouveau_fb base;
31}; 31};
32 32
33static void 33static int
34nv10_fb_vram_init(struct nouveau_fb *pfb)
35{
36 u32 cfg0 = nv_rd32(pfb, 0x100200);
37 if (cfg0 & 0x00000001)
38 pfb->ram.type = NV_MEM_TYPE_DDR1;
39 else
40 pfb->ram.type = NV_MEM_TYPE_SDRAM;
41
42 pfb->ram.size = nv_rd32(pfb, 0x10020c) & 0xff000000;
43 return 0;
44}
45
46void
34nv10_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch, 47nv10_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch,
35 u32 flags, struct nouveau_fb_tile *tile) 48 u32 flags, struct nouveau_fb_tile *tile)
36{ 49{
@@ -39,7 +52,7 @@ nv10_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch,
39 tile->pitch = pitch; 52 tile->pitch = pitch;
40} 53}
41 54
42static void 55void
43nv10_fb_tile_fini(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) 56nv10_fb_tile_fini(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)
44{ 57{
45 tile->addr = 0; 58 tile->addr = 0;
@@ -48,7 +61,7 @@ nv10_fb_tile_fini(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)
48 tile->zcomp = 0; 61 tile->zcomp = 0;
49} 62}
50 63
51static void 64void
52nv10_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) 65nv10_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)
53{ 66{
54 nv_wr32(pfb, 0x100244 + (i * 0x10), tile->limit); 67 nv_wr32(pfb, 0x100244 + (i * 0x10), tile->limit);
@@ -62,7 +75,6 @@ nv10_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
62 struct nouveau_oclass *oclass, void *data, u32 size, 75 struct nouveau_oclass *oclass, void *data, u32 size,
63 struct nouveau_object **pobject) 76 struct nouveau_object **pobject)
64{ 77{
65 struct nouveau_device *device = nv_device(parent);
66 struct nv10_fb_priv *priv; 78 struct nv10_fb_priv *priv;
67 int ret; 79 int ret;
68 80
@@ -71,42 +83,13 @@ nv10_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
71 if (ret) 83 if (ret)
72 return ret; 84 return ret;
73 85
74 if (device->chipset == 0x1a || device->chipset == 0x1f) {
75 struct pci_dev *bridge;
76 u32 mem, mib;
77
78 bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1));
79 if (!bridge) {
80 nv_fatal(device, "no bridge device\n");
81 return 0;
82 }
83
84 if (device->chipset == 0x1a) {
85 pci_read_config_dword(bridge, 0x7c, &mem);
86 mib = ((mem >> 6) & 31) + 1;
87 } else {
88 pci_read_config_dword(bridge, 0x84, &mem);
89 mib = ((mem >> 4) & 127) + 1;
90 }
91
92 priv->base.ram.type = NV_MEM_TYPE_STOLEN;
93 priv->base.ram.size = mib * 1024 * 1024;
94 } else {
95 u32 cfg0 = nv_rd32(priv, 0x100200);
96 if (cfg0 & 0x00000001)
97 priv->base.ram.type = NV_MEM_TYPE_DDR1;
98 else
99 priv->base.ram.type = NV_MEM_TYPE_SDRAM;
100
101 priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
102 }
103
104 priv->base.memtype_valid = nv04_fb_memtype_valid; 86 priv->base.memtype_valid = nv04_fb_memtype_valid;
87 priv->base.ram.init = nv10_fb_vram_init;
105 priv->base.tile.regions = 8; 88 priv->base.tile.regions = 8;
106 priv->base.tile.init = nv10_fb_tile_init; 89 priv->base.tile.init = nv10_fb_tile_init;
107 priv->base.tile.fini = nv10_fb_tile_fini; 90 priv->base.tile.fini = nv10_fb_tile_fini;
108 priv->base.tile.prog = nv10_fb_tile_prog; 91 priv->base.tile.prog = nv10_fb_tile_prog;
109 return nouveau_fb_created(&priv->base); 92 return nouveau_fb_preinit(&priv->base);
110} 93}
111 94
112struct nouveau_oclass 95struct 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
index 000000000000..48366841db4a
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c
@@ -0,0 +1,89 @@
1/*
2 * Copyright (C) 2010 Francisco Jerez.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27#include <subdev/fb.h>
28
29struct nv1a_fb_priv {
30 struct nouveau_fb base;
31};
32
33static int
34nv1a_fb_vram_init(struct nouveau_fb *pfb)
35{
36 struct pci_dev *bridge;
37 u32 mem, mib;
38
39 bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1));
40 if (!bridge) {
41 nv_fatal(pfb, "no bridge device\n");
42 return -ENODEV;
43 }
44
45 if (nv_device(pfb)->chipset == 0x1a) {
46 pci_read_config_dword(bridge, 0x7c, &mem);
47 mib = ((mem >> 6) & 31) + 1;
48 } else {
49 pci_read_config_dword(bridge, 0x84, &mem);
50 mib = ((mem >> 4) & 127) + 1;
51 }
52
53 pfb->ram.type = NV_MEM_TYPE_STOLEN;
54 pfb->ram.size = mib * 1024 * 1024;
55 return 0;
56}
57
58static int
59nv1a_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
60 struct nouveau_oclass *oclass, void *data, u32 size,
61 struct nouveau_object **pobject)
62{
63 struct nv1a_fb_priv *priv;
64 int ret;
65
66 ret = nouveau_fb_create(parent, engine, oclass, &priv);
67 *pobject = nv_object(priv);
68 if (ret)
69 return ret;
70
71 priv->base.memtype_valid = nv04_fb_memtype_valid;
72 priv->base.ram.init = nv1a_fb_vram_init;
73 priv->base.tile.regions = 8;
74 priv->base.tile.init = nv10_fb_tile_init;
75 priv->base.tile.fini = nv10_fb_tile_fini;
76 priv->base.tile.prog = nv10_fb_tile_prog;
77 return nouveau_fb_preinit(&priv->base);
78}
79
80struct nouveau_oclass
81nv1a_fb_oclass = {
82 .handle = NV_SUBDEV(FB, 0x1a),
83 .ofuncs = &(struct nouveau_ofuncs) {
84 .ctor = nv1a_fb_ctor,
85 .dtor = _nouveau_fb_dtor,
86 .init = _nouveau_fb_init,
87 .fini = _nouveau_fb_fini,
88 },
89};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c
index 307d5c73b704..d26adee63c1e 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c
@@ -30,6 +30,22 @@ struct nv20_fb_priv {
30 struct nouveau_fb base; 30 struct nouveau_fb base;
31}; 31};
32 32
33int
34nv20_fb_vram_init(struct nouveau_fb *pfb)
35{
36 u32 pbus1218 = nv_rd32(pfb, 0x001218);
37
38 switch (pbus1218 & 0x00000300) {
39 case 0x00000000: pfb->ram.type = NV_MEM_TYPE_SDRAM; break;
40 case 0x00000100: pfb->ram.type = NV_MEM_TYPE_DDR1; break;
41 case 0x00000200: pfb->ram.type = NV_MEM_TYPE_GDDR3; break;
42 case 0x00000300: pfb->ram.type = NV_MEM_TYPE_GDDR2; break;
43 }
44 pfb->ram.size = nv_rd32(pfb, 0x10020c) & 0xff000000;
45
46 return nv_rd32(pfb, 0x100320);
47}
48
33void 49void
34nv20_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch, 50nv20_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch,
35 u32 flags, struct nouveau_fb_tile *tile) 51 u32 flags, struct nouveau_fb_tile *tile)
@@ -92,9 +108,7 @@ nv20_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
92 struct nouveau_oclass *oclass, void *data, u32 size, 108 struct nouveau_oclass *oclass, void *data, u32 size,
93 struct nouveau_object **pobject) 109 struct nouveau_object **pobject)
94{ 110{
95 struct nouveau_device *device = nv_device(parent);
96 struct nv20_fb_priv *priv; 111 struct nv20_fb_priv *priv;
97 u32 pbus1218;
98 int ret; 112 int ret;
99 113
100 ret = nouveau_fb_create(parent, engine, oclass, &priv); 114 ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -102,29 +116,14 @@ nv20_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
102 if (ret) 116 if (ret)
103 return ret; 117 return ret;
104 118
105 pbus1218 = nv_rd32(priv, 0x001218);
106 switch (pbus1218 & 0x00000300) {
107 case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break;
108 case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
109 case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
110 case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_GDDR2; break;
111 }
112 priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
113
114 if (device->chipset >= 0x25)
115 ret = nouveau_mm_init(&priv->base.tags, 0, 64 * 1024, 1);
116 else
117 ret = nouveau_mm_init(&priv->base.tags, 0, 32 * 1024, 1);
118 if (ret)
119 return ret;
120
121 priv->base.memtype_valid = nv04_fb_memtype_valid; 119 priv->base.memtype_valid = nv04_fb_memtype_valid;
120 priv->base.ram.init = nv20_fb_vram_init;
122 priv->base.tile.regions = 8; 121 priv->base.tile.regions = 8;
123 priv->base.tile.init = nv20_fb_tile_init; 122 priv->base.tile.init = nv20_fb_tile_init;
124 priv->base.tile.comp = nv20_fb_tile_comp; 123 priv->base.tile.comp = nv20_fb_tile_comp;
125 priv->base.tile.fini = nv20_fb_tile_fini; 124 priv->base.tile.fini = nv20_fb_tile_fini;
126 priv->base.tile.prog = nv20_fb_tile_prog; 125 priv->base.tile.prog = nv20_fb_tile_prog;
127 return nouveau_fb_created(&priv->base); 126 return nouveau_fb_preinit(&priv->base);
128} 127}
129 128
130struct nouveau_oclass 129struct nouveau_oclass
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv25.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv25.c
index 7529353bc1de..b6858ca6de86 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv25.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv25.c
@@ -60,9 +60,7 @@ nv25_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
60 struct nouveau_oclass *oclass, void *data, u32 size, 60 struct nouveau_oclass *oclass, void *data, u32 size,
61 struct nouveau_object **pobject) 61 struct nouveau_object **pobject)
62{ 62{
63 struct nouveau_device *device = nv_device(parent);
64 struct nv25_fb_priv *priv; 63 struct nv25_fb_priv *priv;
65 u32 pbus1218;
66 int ret; 64 int ret;
67 65
68 ret = nouveau_fb_create(parent, engine, oclass, &priv); 66 ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -70,29 +68,14 @@ nv25_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
70 if (ret) 68 if (ret)
71 return ret; 69 return ret;
72 70
73 pbus1218 = nv_rd32(priv, 0x001218);
74 switch (pbus1218 & 0x00000300) {
75 case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break;
76 case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
77 case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
78 case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_GDDR2; break;
79 }
80 priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
81
82 if (device->chipset >= 0x25)
83 ret = nouveau_mm_init(&priv->base.tags, 0, 64 * 1024, 1);
84 else
85 ret = nouveau_mm_init(&priv->base.tags, 0, 32 * 1024, 1);
86 if (ret)
87 return ret;
88
89 priv->base.memtype_valid = nv04_fb_memtype_valid; 71 priv->base.memtype_valid = nv04_fb_memtype_valid;
72 priv->base.ram.init = nv20_fb_vram_init;
90 priv->base.tile.regions = 8; 73 priv->base.tile.regions = 8;
91 priv->base.tile.init = nv20_fb_tile_init; 74 priv->base.tile.init = nv20_fb_tile_init;
92 priv->base.tile.comp = nv25_fb_tile_comp; 75 priv->base.tile.comp = nv25_fb_tile_comp;
93 priv->base.tile.fini = nv20_fb_tile_fini; 76 priv->base.tile.fini = nv20_fb_tile_fini;
94 priv->base.tile.prog = nv20_fb_tile_prog; 77 priv->base.tile.prog = nv20_fb_tile_prog;
95 return nouveau_fb_created(&priv->base); 78 return nouveau_fb_preinit(&priv->base);
96} 79}
97 80
98struct nouveau_oclass 81struct nouveau_oclass
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c
index d6ed18cc8e84..c4ab975ac83f 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c
@@ -123,7 +123,6 @@ nv30_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
123 struct nouveau_object **pobject) 123 struct nouveau_object **pobject)
124{ 124{
125 struct nv30_fb_priv *priv; 125 struct nv30_fb_priv *priv;
126 u32 pbus1218;
127 int ret; 126 int ret;
128 127
129 ret = nouveau_fb_create(parent, engine, oclass, &priv); 128 ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -131,22 +130,14 @@ nv30_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
131 if (ret) 130 if (ret)
132 return ret; 131 return ret;
133 132
134 pbus1218 = nv_rd32(priv, 0x001218);
135 switch (pbus1218 & 0x00000300) {
136 case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break;
137 case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
138 case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
139 case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_GDDR2; break;
140 }
141 priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
142
143 priv->base.memtype_valid = nv04_fb_memtype_valid; 133 priv->base.memtype_valid = nv04_fb_memtype_valid;
134 priv->base.ram.init = nv20_fb_vram_init;
144 priv->base.tile.regions = 8; 135 priv->base.tile.regions = 8;
145 priv->base.tile.init = nv30_fb_tile_init; 136 priv->base.tile.init = nv30_fb_tile_init;
146 priv->base.tile.comp = nv30_fb_tile_comp; 137 priv->base.tile.comp = nv30_fb_tile_comp;
147 priv->base.tile.fini = nv30_fb_tile_fini; 138 priv->base.tile.fini = nv30_fb_tile_fini;
148 priv->base.tile.prog = nv20_fb_tile_prog; 139 priv->base.tile.prog = nv20_fb_tile_prog;
149 return nouveau_fb_created(&priv->base); 140 return nouveau_fb_preinit(&priv->base);
150} 141}
151 142
152struct nouveau_oclass 143struct nouveau_oclass
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv35.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv35.c
index 1c313db8a560..e87086af2311 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv35.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv35.c
@@ -43,7 +43,6 @@ nv35_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
43 struct nouveau_object **pobject) 43 struct nouveau_object **pobject)
44{ 44{
45 struct nv35_fb_priv *priv; 45 struct nv35_fb_priv *priv;
46 u32 pbus1218;
47 int ret; 46 int ret;
48 47
49 ret = nouveau_fb_create(parent, engine, oclass, &priv); 48 ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -51,22 +50,14 @@ nv35_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
51 if (ret) 50 if (ret)
52 return ret; 51 return ret;
53 52
54 pbus1218 = nv_rd32(priv, 0x001218);
55 switch (pbus1218 & 0x00000300) {
56 case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break;
57 case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
58 case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
59 case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_GDDR2; break;
60 }
61 priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
62
63 priv->base.memtype_valid = nv04_fb_memtype_valid; 53 priv->base.memtype_valid = nv04_fb_memtype_valid;
54 priv->base.ram.init = nv20_fb_vram_init;
64 priv->base.tile.regions = 8; 55 priv->base.tile.regions = 8;
65 priv->base.tile.init = nv30_fb_tile_init; 56 priv->base.tile.init = nv30_fb_tile_init;
66 priv->base.tile.comp = nv35_fb_tile_comp; 57 priv->base.tile.comp = nv35_fb_tile_comp;
67 priv->base.tile.fini = nv30_fb_tile_fini; 58 priv->base.tile.fini = nv30_fb_tile_fini;
68 priv->base.tile.prog = nv20_fb_tile_prog; 59 priv->base.tile.prog = nv20_fb_tile_prog;
69 return nouveau_fb_created(&priv->base); 60 return nouveau_fb_preinit(&priv->base);
70} 61}
71 62
72struct nouveau_oclass 63struct nouveau_oclass
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c
index 425bb1d7ab2b..e942e5b9d66d 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c
@@ -30,6 +30,21 @@ struct nv40_fb_priv {
30 struct nouveau_fb base; 30 struct nouveau_fb base;
31}; 31};
32 32
33static int
34nv40_fb_vram_init(struct nouveau_fb *pfb)
35{
36 u32 pbus1218 = nv_rd32(pfb, 0x001218);
37 switch (pbus1218 & 0x00000300) {
38 case 0x00000000: pfb->ram.type = NV_MEM_TYPE_SDRAM; break;
39 case 0x00000100: pfb->ram.type = NV_MEM_TYPE_DDR1; break;
40 case 0x00000200: pfb->ram.type = NV_MEM_TYPE_GDDR3; break;
41 case 0x00000300: pfb->ram.type = NV_MEM_TYPE_DDR2; break;
42 }
43
44 pfb->ram.size = nv_rd32(pfb, 0x10020c) & 0xff000000;
45 return nv_rd32(pfb, 0x100320);
46}
47
33static void 48static void
34nv40_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags, 49nv40_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags,
35 struct nouveau_fb_tile *tile) 50 struct nouveau_fb_tile *tile)
@@ -56,9 +71,7 @@ nv40_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
56 struct nouveau_oclass *oclass, void *data, u32 size, 71 struct nouveau_oclass *oclass, void *data, u32 size,
57 struct nouveau_object **pobject) 72 struct nouveau_object **pobject)
58{ 73{
59 struct nouveau_device *device = nv_device(parent);
60 struct nv40_fb_priv *priv; 74 struct nv40_fb_priv *priv;
61 u32 pbus1218;
62 int ret; 75 int ret;
63 76
64 ret = nouveau_fb_create(parent, engine, oclass, &priv); 77 ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -66,23 +79,14 @@ nv40_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
66 if (ret) 79 if (ret)
67 return ret; 80 return ret;
68 81
69 pbus1218 = nv_rd32(priv, 0x001218);
70 switch (pbus1218 & 0x00000300) {
71 case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break;
72 case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
73 case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
74 case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_DDR2; break;
75 }
76
77 priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
78
79 priv->base.memtype_valid = nv04_fb_memtype_valid; 82 priv->base.memtype_valid = nv04_fb_memtype_valid;
83 priv->base.ram.init = nv40_fb_vram_init;
80 priv->base.tile.regions = 8; 84 priv->base.tile.regions = 8;
81 priv->base.tile.init = nv30_fb_tile_init; 85 priv->base.tile.init = nv30_fb_tile_init;
82 priv->base.tile.comp = nv40_fb_tile_comp; 86 priv->base.tile.comp = nv40_fb_tile_comp;
83 priv->base.tile.fini = nv30_fb_tile_fini; 87 priv->base.tile.fini = nv30_fb_tile_fini;
84 priv->base.tile.prog = nv20_fb_tile_prog; 88 priv->base.tile.prog = nv20_fb_tile_prog;
85 return nouveau_fb_created(&priv->base); 89 return nouveau_fb_preinit(&priv->base);
86} 90}
87 91
88 92
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv41.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv41.c
index 3c974173e184..6ddf82ab038a 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv41.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv41.c
@@ -30,6 +30,21 @@ struct nv41_fb_priv {
30 struct nouveau_fb base; 30 struct nouveau_fb base;
31}; 31};
32 32
33int
34nv41_fb_vram_init(struct nouveau_fb *pfb)
35{
36 u32 pfb474 = nv_rd32(pfb, 0x100474);
37 if (pfb474 & 0x00000004)
38 pfb->ram.type = NV_MEM_TYPE_GDDR3;
39 if (pfb474 & 0x00000002)
40 pfb->ram.type = NV_MEM_TYPE_DDR2;
41 if (pfb474 & 0x00000001)
42 pfb->ram.type = NV_MEM_TYPE_DDR1;
43
44 pfb->ram.size = nv_rd32(pfb, 0x10020c) & 0xff000000;
45 return nv_rd32(pfb, 0x100320);
46}
47
33void 48void
34nv41_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) 49nv41_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)
35{ 50{
@@ -59,9 +74,7 @@ nv41_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
59 struct nouveau_oclass *oclass, void *data, u32 size, 74 struct nouveau_oclass *oclass, void *data, u32 size,
60 struct nouveau_object **pobject) 75 struct nouveau_object **pobject)
61{ 76{
62 struct nouveau_device *device = nv_device(parent);
63 struct nv41_fb_priv *priv; 77 struct nv41_fb_priv *priv;
64 u32 pfb474;
65 int ret; 78 int ret;
66 79
67 ret = nouveau_fb_create(parent, engine, oclass, &priv); 80 ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -69,22 +82,13 @@ nv41_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
69 if (ret) 82 if (ret)
70 return ret; 83 return ret;
71 84
72 pfb474 = nv_rd32(priv, 0x100474);
73 if (pfb474 & 0x00000004)
74 priv->base.ram.type = NV_MEM_TYPE_GDDR3;
75 if (pfb474 & 0x00000002)
76 priv->base.ram.type = NV_MEM_TYPE_DDR2;
77 if (pfb474 & 0x00000001)
78 priv->base.ram.type = NV_MEM_TYPE_DDR1;
79
80 priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
81
82 priv->base.memtype_valid = nv04_fb_memtype_valid; 85 priv->base.memtype_valid = nv04_fb_memtype_valid;
86 priv->base.ram.init = nv41_fb_vram_init;
83 priv->base.tile.regions = 12; 87 priv->base.tile.regions = 12;
84 priv->base.tile.init = nv30_fb_tile_init; 88 priv->base.tile.init = nv30_fb_tile_init;
85 priv->base.tile.fini = nv30_fb_tile_fini; 89 priv->base.tile.fini = nv30_fb_tile_fini;
86 priv->base.tile.prog = nv41_fb_tile_prog; 90 priv->base.tile.prog = nv41_fb_tile_prog;
87 return nouveau_fb_created(&priv->base); 91 return nouveau_fb_preinit(&priv->base);
88} 92}
89 93
90 94
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv44.c
index 538b0de8152b..46d6518c1a80 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv44.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv44.c
@@ -30,6 +30,21 @@ struct nv44_fb_priv {
30 struct nouveau_fb base; 30 struct nouveau_fb base;
31}; 31};
32 32
33int
34nv44_fb_vram_init(struct nouveau_fb *pfb)
35{
36 u32 pfb474 = nv_rd32(pfb, 0x100474);
37 if (pfb474 & 0x00000004)
38 pfb->ram.type = NV_MEM_TYPE_GDDR3;
39 if (pfb474 & 0x00000002)
40 pfb->ram.type = NV_MEM_TYPE_DDR2;
41 if (pfb474 & 0x00000001)
42 pfb->ram.type = NV_MEM_TYPE_DDR1;
43
44 pfb->ram.size = nv_rd32(pfb, 0x10020c) & 0xff000000;
45 return 0;
46}
47
33static void 48static void
34nv44_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch, 49nv44_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch,
35 u32 flags, struct nouveau_fb_tile *tile) 50 u32 flags, struct nouveau_fb_tile *tile)
@@ -69,9 +84,7 @@ nv44_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
69 struct nouveau_oclass *oclass, void *data, u32 size, 84 struct nouveau_oclass *oclass, void *data, u32 size,
70 struct nouveau_object **pobject) 85 struct nouveau_object **pobject)
71{ 86{
72 struct nouveau_device *device = nv_device(parent);
73 struct nv44_fb_priv *priv; 87 struct nv44_fb_priv *priv;
74 u32 pfb474;
75 int ret; 88 int ret;
76 89
77 ret = nouveau_fb_create(parent, engine, oclass, &priv); 90 ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -79,22 +92,13 @@ nv44_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
79 if (ret) 92 if (ret)
80 return ret; 93 return ret;
81 94
82 pfb474 = nv_rd32(priv, 0x100474);
83 if (pfb474 & 0x00000004)
84 priv->base.ram.type = NV_MEM_TYPE_GDDR3;
85 if (pfb474 & 0x00000002)
86 priv->base.ram.type = NV_MEM_TYPE_DDR2;
87 if (pfb474 & 0x00000001)
88 priv->base.ram.type = NV_MEM_TYPE_DDR1;
89
90 priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
91
92 priv->base.memtype_valid = nv04_fb_memtype_valid; 95 priv->base.memtype_valid = nv04_fb_memtype_valid;
96 priv->base.ram.init = nv44_fb_vram_init;
93 priv->base.tile.regions = 12; 97 priv->base.tile.regions = 12;
94 priv->base.tile.init = nv44_fb_tile_init; 98 priv->base.tile.init = nv44_fb_tile_init;
95 priv->base.tile.fini = nv30_fb_tile_fini; 99 priv->base.tile.fini = nv30_fb_tile_fini;
96 priv->base.tile.prog = nv44_fb_tile_prog; 100 priv->base.tile.prog = nv44_fb_tile_prog;
97 return nouveau_fb_created(&priv->base); 101 return nouveau_fb_preinit(&priv->base);
98} 102}
99 103
100 104
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv46.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv46.c
index 57b6ff28db01..b8fcbd6f80b4 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv46.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv46.c
@@ -49,9 +49,7 @@ nv46_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
49 struct nouveau_oclass *oclass, void *data, u32 size, 49 struct nouveau_oclass *oclass, void *data, u32 size,
50 struct nouveau_object **pobject) 50 struct nouveau_object **pobject)
51{ 51{
52 struct nouveau_device *device = nv_device(parent);
53 struct nv46_fb_priv *priv; 52 struct nv46_fb_priv *priv;
54 u32 pfb474;
55 int ret; 53 int ret;
56 54
57 ret = nouveau_fb_create(parent, engine, oclass, &priv); 55 ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -59,22 +57,13 @@ nv46_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
59 if (ret) 57 if (ret)
60 return ret; 58 return ret;
61 59
62 pfb474 = nv_rd32(priv, 0x100474);
63 if (pfb474 & 0x00000004)
64 priv->base.ram.type = NV_MEM_TYPE_GDDR3;
65 if (pfb474 & 0x00000002)
66 priv->base.ram.type = NV_MEM_TYPE_DDR2;
67 if (pfb474 & 0x00000001)
68 priv->base.ram.type = NV_MEM_TYPE_DDR1;
69
70 priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
71
72 priv->base.memtype_valid = nv04_fb_memtype_valid; 60 priv->base.memtype_valid = nv04_fb_memtype_valid;
61 priv->base.ram.init = nv44_fb_vram_init;
73 priv->base.tile.regions = 15; 62 priv->base.tile.regions = 15;
74 priv->base.tile.init = nv46_fb_tile_init; 63 priv->base.tile.init = nv46_fb_tile_init;
75 priv->base.tile.fini = nv30_fb_tile_fini; 64 priv->base.tile.fini = nv30_fb_tile_fini;
76 priv->base.tile.prog = nv44_fb_tile_prog; 65 priv->base.tile.prog = nv44_fb_tile_prog;
77 return nouveau_fb_created(&priv->base); 66 return nouveau_fb_preinit(&priv->base);
78} 67}
79 68
80 69
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv47.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv47.c
index 6fb5305781f2..bfe1962df50b 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv47.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv47.c
@@ -35,9 +35,7 @@ nv47_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
35 struct nouveau_oclass *oclass, void *data, u32 size, 35 struct nouveau_oclass *oclass, void *data, u32 size,
36 struct nouveau_object **pobject) 36 struct nouveau_object **pobject)
37{ 37{
38 struct nouveau_device *device = nv_device(parent);
39 struct nv47_fb_priv *priv; 38 struct nv47_fb_priv *priv;
40 u32 pfb474;
41 int ret; 39 int ret;
42 40
43 ret = nouveau_fb_create(parent, engine, oclass, &priv); 41 ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -45,22 +43,13 @@ nv47_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
45 if (ret) 43 if (ret)
46 return ret; 44 return ret;
47 45
48 pfb474 = nv_rd32(priv, 0x100474);
49 if (pfb474 & 0x00000004)
50 priv->base.ram.type = NV_MEM_TYPE_GDDR3;
51 if (pfb474 & 0x00000002)
52 priv->base.ram.type = NV_MEM_TYPE_DDR2;
53 if (pfb474 & 0x00000001)
54 priv->base.ram.type = NV_MEM_TYPE_DDR1;
55
56 priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
57
58 priv->base.memtype_valid = nv04_fb_memtype_valid; 46 priv->base.memtype_valid = nv04_fb_memtype_valid;
47 priv->base.ram.init = nv41_fb_vram_init;
59 priv->base.tile.regions = 15; 48 priv->base.tile.regions = 15;
60 priv->base.tile.init = nv30_fb_tile_init; 49 priv->base.tile.init = nv30_fb_tile_init;
61 priv->base.tile.fini = nv30_fb_tile_fini; 50 priv->base.tile.fini = nv30_fb_tile_fini;
62 priv->base.tile.prog = nv41_fb_tile_prog; 51 priv->base.tile.prog = nv41_fb_tile_prog;
63 return nouveau_fb_created(&priv->base); 52 return nouveau_fb_preinit(&priv->base);
64} 53}
65 54
66 55
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv49.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv49.c
index a88638f14c72..3d64195b737f 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv49.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv49.c
@@ -31,13 +31,27 @@ struct nv49_fb_priv {
31}; 31};
32 32
33static int 33static int
34nv49_fb_vram_init(struct nouveau_fb *pfb)
35{
36 u32 pfb914 = nv_rd32(pfb, 0x100914);
37
38 switch (pfb914 & 0x00000003) {
39 case 0x00000000: pfb->ram.type = NV_MEM_TYPE_DDR1; break;
40 case 0x00000001: pfb->ram.type = NV_MEM_TYPE_DDR2; break;
41 case 0x00000002: pfb->ram.type = NV_MEM_TYPE_GDDR3; break;
42 case 0x00000003: break;
43 }
44
45 pfb->ram.size = nv_rd32(pfb, 0x10020c) & 0xff000000;
46 return nv_rd32(pfb, 0x100320);
47}
48
49static int
34nv49_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 50nv49_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
35 struct nouveau_oclass *oclass, void *data, u32 size, 51 struct nouveau_oclass *oclass, void *data, u32 size,
36 struct nouveau_object **pobject) 52 struct nouveau_object **pobject)
37{ 53{
38 struct nouveau_device *device = nv_device(parent);
39 struct nv49_fb_priv *priv; 54 struct nv49_fb_priv *priv;
40 u32 pfb914;
41 int ret; 55 int ret;
42 56
43 ret = nouveau_fb_create(parent, engine, oclass, &priv); 57 ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -45,23 +59,14 @@ nv49_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
45 if (ret) 59 if (ret)
46 return ret; 60 return ret;
47 61
48 pfb914 = nv_rd32(priv, 0x100914);
49 switch (pfb914 & 0x00000003) {
50 case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
51 case 0x00000001: priv->base.ram.type = NV_MEM_TYPE_DDR2; break;
52 case 0x00000002: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
53 case 0x00000003: break;
54 }
55
56 priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
57
58 priv->base.memtype_valid = nv04_fb_memtype_valid; 62 priv->base.memtype_valid = nv04_fb_memtype_valid;
63 priv->base.ram.init = nv49_fb_vram_init;
59 priv->base.tile.regions = 15; 64 priv->base.tile.regions = 15;
60 priv->base.tile.init = nv30_fb_tile_init; 65 priv->base.tile.init = nv30_fb_tile_init;
61 priv->base.tile.fini = nv30_fb_tile_fini; 66 priv->base.tile.fini = nv30_fb_tile_fini;
62 priv->base.tile.prog = nv41_fb_tile_prog; 67 priv->base.tile.prog = nv41_fb_tile_prog;
63 68
64 return nouveau_fb_created(&priv->base); 69 return nouveau_fb_preinit(&priv->base);
65} 70}
66 71
67 72
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv4e.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv4e.c
index fab8b19df4ee..9b79994159f4 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv4e.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv4e.c
@@ -31,11 +31,18 @@ struct nv4e_fb_priv {
31}; 31};
32 32
33static int 33static int
34nv4e_fb_vram_init(struct nouveau_fb *pfb)
35{
36 pfb->ram.size = nv_rd32(pfb, 0x10020c) & 0xff000000;
37 pfb->ram.type = NV_MEM_TYPE_STOLEN;
38 return 0;
39}
40
41static int
34nv4e_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 42nv4e_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
35 struct nouveau_oclass *oclass, void *data, u32 size, 43 struct nouveau_oclass *oclass, void *data, u32 size,
36 struct nouveau_object **pobject) 44 struct nouveau_object **pobject)
37{ 45{
38 struct nouveau_device *device = nv_device(parent);
39 struct nv4e_fb_priv *priv; 46 struct nv4e_fb_priv *priv;
40 int ret; 47 int ret;
41 48
@@ -44,17 +51,15 @@ nv4e_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
44 if (ret) 51 if (ret)
45 return ret; 52 return ret;
46 53
47 priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
48 priv->base.ram.type = NV_MEM_TYPE_STOLEN;
49 priv->base.memtype_valid = nv04_fb_memtype_valid; 54 priv->base.memtype_valid = nv04_fb_memtype_valid;
55 priv->base.ram.init = nv4e_fb_vram_init;
50 priv->base.tile.regions = 12; 56 priv->base.tile.regions = 12;
51 priv->base.tile.init = nv46_fb_tile_init; 57 priv->base.tile.init = nv46_fb_tile_init;
52 priv->base.tile.fini = nv30_fb_tile_fini; 58 priv->base.tile.fini = nv30_fb_tile_fini;
53 priv->base.tile.prog = nv44_fb_tile_prog; 59 priv->base.tile.prog = nv44_fb_tile_prog;
54 return nouveau_fb_created(&priv->base); 60 return nouveau_fb_preinit(&priv->base);
55} 61}
56 62
57
58struct nouveau_oclass 63struct nouveau_oclass
59nv4e_fb_oclass = { 64nv4e_fb_oclass = {
60 .handle = NV_SUBDEV(FB, 0x4e), 65 .handle = NV_SUBDEV(FB, 0x4e),
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
index 5f570806143a..2c1ee3f6feef 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
@@ -51,6 +51,101 @@ nv50_fb_memtype_valid(struct nouveau_fb *pfb, u32 memtype)
51 return types[(memtype & 0xff00) >> 8] != 0; 51 return types[(memtype & 0xff00) >> 8] != 0;
52} 52}
53 53
54static u32
55nv50_fb_vram_rblock(struct nouveau_fb *pfb)
56{
57 int i, parts, colbits, rowbitsa, rowbitsb, banks;
58 u64 rowsize, predicted;
59 u32 r0, r4, rt, ru, rblock_size;
60
61 r0 = nv_rd32(pfb, 0x100200);
62 r4 = nv_rd32(pfb, 0x100204);
63 rt = nv_rd32(pfb, 0x100250);
64 ru = nv_rd32(pfb, 0x001540);
65 nv_debug(pfb, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru);
66
67 for (i = 0, parts = 0; i < 8; i++) {
68 if (ru & (0x00010000 << i))
69 parts++;
70 }
71
72 colbits = (r4 & 0x0000f000) >> 12;
73 rowbitsa = ((r4 & 0x000f0000) >> 16) + 8;
74 rowbitsb = ((r4 & 0x00f00000) >> 20) + 8;
75 banks = 1 << (((r4 & 0x03000000) >> 24) + 2);
76
77 rowsize = parts * banks * (1 << colbits) * 8;
78 predicted = rowsize << rowbitsa;
79 if (r0 & 0x00000004)
80 predicted += rowsize << rowbitsb;
81
82 if (predicted != pfb->ram.size) {
83 nv_warn(pfb, "memory controller reports %d MiB VRAM\n",
84 (u32)(pfb->ram.size >> 20));
85 }
86
87 rblock_size = rowsize;
88 if (rt & 1)
89 rblock_size *= 3;
90
91 nv_debug(pfb, "rblock %d bytes\n", rblock_size);
92 return rblock_size;
93}
94
95static int
96nv50_fb_vram_init(struct nouveau_fb *pfb)
97{
98 struct nouveau_device *device = nv_device(pfb);
99 struct nouveau_bios *bios = nouveau_bios(device);
100 const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
101 const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
102 u32 size;
103 int ret;
104
105 pfb->ram.size = nv_rd32(pfb, 0x10020c);
106 pfb->ram.size = (pfb->ram.size & 0xffffff00) |
107 ((pfb->ram.size & 0x000000ff) << 32);
108
109 size = (pfb->ram.size >> 12) - rsvd_head - rsvd_tail;
110 switch (device->chipset) {
111 case 0xaa:
112 case 0xac:
113 case 0xaf: /* IGPs, no reordering, no real VRAM */
114 ret = nouveau_mm_init(&pfb->vram, rsvd_head, size, 1);
115 if (ret)
116 return ret;
117
118 pfb->ram.type = NV_MEM_TYPE_STOLEN;
119 pfb->ram.stolen = (u64)nv_rd32(pfb, 0x100e10) << 12;
120 break;
121 default:
122 switch (nv_rd32(pfb, 0x100714) & 0x00000007) {
123 case 0: pfb->ram.type = NV_MEM_TYPE_DDR1; break;
124 case 1:
125 if (nouveau_fb_bios_memtype(bios) == NV_MEM_TYPE_DDR3)
126 pfb->ram.type = NV_MEM_TYPE_DDR3;
127 else
128 pfb->ram.type = NV_MEM_TYPE_DDR2;
129 break;
130 case 2: pfb->ram.type = NV_MEM_TYPE_GDDR3; break;
131 case 3: pfb->ram.type = NV_MEM_TYPE_GDDR4; break;
132 case 4: pfb->ram.type = NV_MEM_TYPE_GDDR5; break;
133 default:
134 break;
135 }
136
137 ret = nouveau_mm_init(&pfb->vram, rsvd_head, size,
138 nv50_fb_vram_rblock(pfb) >> 12);
139 if (ret)
140 return ret;
141
142 pfb->ram.ranks = (nv_rd32(pfb, 0x100200) & 0x4) ? 2 : 1;
143 break;
144 }
145
146 return nv_rd32(pfb, 0x100320);
147}
148
54static int 149static int
55nv50_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, 150nv50_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
56 u32 memtype, struct nouveau_mem **pmem) 151 u32 memtype, struct nouveau_mem **pmem)
@@ -140,58 +235,13 @@ nv50_fb_vram_del(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
140 kfree(mem); 235 kfree(mem);
141} 236}
142 237
143static u32
144nv50_vram_rblock(struct nv50_fb_priv *priv)
145{
146 int i, parts, colbits, rowbitsa, rowbitsb, banks;
147 u64 rowsize, predicted;
148 u32 r0, r4, rt, ru, rblock_size;
149
150 r0 = nv_rd32(priv, 0x100200);
151 r4 = nv_rd32(priv, 0x100204);
152 rt = nv_rd32(priv, 0x100250);
153 ru = nv_rd32(priv, 0x001540);
154 nv_debug(priv, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru);
155
156 for (i = 0, parts = 0; i < 8; i++) {
157 if (ru & (0x00010000 << i))
158 parts++;
159 }
160
161 colbits = (r4 & 0x0000f000) >> 12;
162 rowbitsa = ((r4 & 0x000f0000) >> 16) + 8;
163 rowbitsb = ((r4 & 0x00f00000) >> 20) + 8;
164 banks = 1 << (((r4 & 0x03000000) >> 24) + 2);
165
166 rowsize = parts * banks * (1 << colbits) * 8;
167 predicted = rowsize << rowbitsa;
168 if (r0 & 0x00000004)
169 predicted += rowsize << rowbitsb;
170
171 if (predicted != priv->base.ram.size) {
172 nv_warn(priv, "memory controller reports %d MiB VRAM\n",
173 (u32)(priv->base.ram.size >> 20));
174 }
175
176 rblock_size = rowsize;
177 if (rt & 1)
178 rblock_size *= 3;
179
180 nv_debug(priv, "rblock %d bytes\n", rblock_size);
181 return rblock_size;
182}
183
184static int 238static int
185nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 239nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
186 struct nouveau_oclass *oclass, void *data, u32 size, 240 struct nouveau_oclass *oclass, void *data, u32 size,
187 struct nouveau_object **pobject) 241 struct nouveau_object **pobject)
188{ 242{
189 struct nouveau_device *device = nv_device(parent); 243 struct nouveau_device *device = nv_device(parent);
190 struct nouveau_bios *bios = nouveau_bios(device);
191 const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
192 const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
193 struct nv50_fb_priv *priv; 244 struct nv50_fb_priv *priv;
194 u32 tags;
195 int ret; 245 int ret;
196 246
197 ret = nouveau_fb_create(parent, engine, oclass, &priv); 247 ret = nouveau_fb_create(parent, engine, oclass, &priv);
@@ -199,54 +249,6 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
199 if (ret) 249 if (ret)
200 return ret; 250 return ret;
201 251
202 switch (nv_rd32(priv, 0x100714) & 0x00000007) {
203 case 0: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
204 case 1:
205 if (nouveau_fb_bios_memtype(bios) == NV_MEM_TYPE_DDR3)
206 priv->base.ram.type = NV_MEM_TYPE_DDR3;
207 else
208 priv->base.ram.type = NV_MEM_TYPE_DDR2;
209 break;
210 case 2: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
211 case 3: priv->base.ram.type = NV_MEM_TYPE_GDDR4; break;
212 case 4: priv->base.ram.type = NV_MEM_TYPE_GDDR5; break;
213 default:
214 break;
215 }
216
217 priv->base.ram.size = nv_rd32(priv, 0x10020c);
218 priv->base.ram.size = (priv->base.ram.size & 0xffffff00) |
219 ((priv->base.ram.size & 0x000000ff) << 32);
220
221 tags = nv_rd32(priv, 0x100320);
222 ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1);
223 if (ret)
224 return ret;
225
226 nv_debug(priv, "%d compression tags\n", tags);
227
228 size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail;
229 switch (device->chipset) {
230 case 0xaa:
231 case 0xac:
232 case 0xaf: /* IGPs, no reordering, no real VRAM */
233 ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size, 1);
234 if (ret)
235 return ret;
236
237 priv->base.ram.stolen = (u64)nv_rd32(priv, 0x100e10) << 12;
238 priv->base.ram.type = NV_MEM_TYPE_STOLEN;
239 break;
240 default:
241 ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size,
242 nv50_vram_rblock(priv) >> 12);
243 if (ret)
244 return ret;
245
246 priv->base.ram.ranks = (nv_rd32(priv, 0x100200) & 0x4) ? 2 : 1;
247 break;
248 }
249
250 priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); 252 priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
251 if (priv->r100c08_page) { 253 if (priv->r100c08_page) {
252 priv->r100c08 = pci_map_page(device->pdev, priv->r100c08_page, 254 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,
259 } 261 }
260 262
261 priv->base.memtype_valid = nv50_fb_memtype_valid; 263 priv->base.memtype_valid = nv50_fb_memtype_valid;
264 priv->base.ram.init = nv50_fb_vram_init;
262 priv->base.ram.get = nv50_fb_vram_new; 265 priv->base.ram.get = nv50_fb_vram_new;
263 priv->base.ram.put = nv50_fb_vram_del; 266 priv->base.ram.put = nv50_fb_vram_del;
264 return nouveau_fb_created(&priv->base); 267 return nouveau_fb_preinit(&priv->base);
265} 268}
266 269
267static void 270static void
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
index 9f59f2bf0079..306bdf121452 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
@@ -62,6 +62,65 @@ nvc0_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags)
62} 62}
63 63
64static int 64static int
65nvc0_fb_vram_init(struct nouveau_fb *pfb)
66{
67 struct nouveau_bios *bios = nouveau_bios(pfb);
68 const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
69 const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
70 u32 parts = nv_rd32(pfb, 0x022438);
71 u32 pmask = nv_rd32(pfb, 0x022554);
72 u32 bsize = nv_rd32(pfb, 0x10f20c);
73 u32 offset, length;
74 bool uniform = true;
75 int ret, part;
76
77 nv_debug(pfb, "0x100800: 0x%08x\n", nv_rd32(pfb, 0x100800));
78 nv_debug(pfb, "parts 0x%08x mask 0x%08x\n", parts, pmask);
79
80 pfb->ram.type = nouveau_fb_bios_memtype(bios);
81 pfb->ram.ranks = (nv_rd32(pfb, 0x10f200) & 0x00000004) ? 2 : 1;
82
83 /* read amount of vram attached to each memory controller */
84 for (part = 0; part < parts; part++) {
85 if (!(pmask & (1 << part))) {
86 u32 psize = nv_rd32(pfb, 0x11020c + (part * 0x1000));
87 if (psize != bsize) {
88 if (psize < bsize)
89 bsize = psize;
90 uniform = false;
91 }
92
93 nv_debug(pfb, "%d: mem_amount 0x%08x\n", part, psize);
94 pfb->ram.size += (u64)psize << 20;
95 }
96 }
97
98 /* if all controllers have the same amount attached, there's no holes */
99 if (uniform) {
100 offset = rsvd_head;
101 length = (pfb->ram.size >> 12) - rsvd_head - rsvd_tail;
102 return nouveau_mm_init(&pfb->vram, offset, length, 1);
103 }
104
105 /* otherwise, address lowest common amount from 0GiB */
106 ret = nouveau_mm_init(&pfb->vram, rsvd_head, (bsize << 8) * parts, 1);
107 if (ret)
108 return ret;
109
110 /* and the rest starting from (8GiB + common_size) */
111 offset = (0x0200000000ULL >> 12) + (bsize << 8);
112 length = (pfb->ram.size >> 12) - (bsize << 8) - rsvd_tail;
113
114 ret = nouveau_mm_init(&pfb->vram, offset, length, 0);
115 if (ret) {
116 nouveau_mm_fini(&pfb->vram);
117 return ret;
118 }
119
120 return 0;
121}
122
123static int
65nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, 124nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
66 u32 memtype, struct nouveau_mem **pmem) 125 u32 memtype, struct nouveau_mem **pmem)
67{ 126{
@@ -139,66 +198,6 @@ nvc0_fb_dtor(struct nouveau_object *object)
139} 198}
140 199
141static int 200static int
142nvc0_vram_detect(struct nvc0_fb_priv *priv)
143{
144 struct nouveau_bios *bios = nouveau_bios(priv);
145 struct nouveau_fb *pfb = &priv->base;
146 const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
147 const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
148 u32 parts = nv_rd32(priv, 0x022438);
149 u32 pmask = nv_rd32(priv, 0x022554);
150 u32 bsize = nv_rd32(priv, 0x10f20c);
151 u32 offset, length;
152 bool uniform = true;
153 int ret, part;
154
155 nv_debug(priv, "0x100800: 0x%08x\n", nv_rd32(priv, 0x100800));
156 nv_debug(priv, "parts 0x%08x mask 0x%08x\n", parts, pmask);
157
158 priv->base.ram.type = nouveau_fb_bios_memtype(bios);
159 priv->base.ram.ranks = (nv_rd32(priv, 0x10f200) & 0x00000004) ? 2 : 1;
160
161 /* read amount of vram attached to each memory controller */
162 for (part = 0; part < parts; part++) {
163 if (!(pmask & (1 << part))) {
164 u32 psize = nv_rd32(priv, 0x11020c + (part * 0x1000));
165 if (psize != bsize) {
166 if (psize < bsize)
167 bsize = psize;
168 uniform = false;
169 }
170
171 nv_debug(priv, "%d: mem_amount 0x%08x\n", part, psize);
172 priv->base.ram.size += (u64)psize << 20;
173 }
174 }
175
176 /* if all controllers have the same amount attached, there's no holes */
177 if (uniform) {
178 offset = rsvd_head;
179 length = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail;
180 return nouveau_mm_init(&pfb->vram, offset, length, 1);
181 }
182
183 /* otherwise, address lowest common amount from 0GiB */
184 ret = nouveau_mm_init(&pfb->vram, rsvd_head, (bsize << 8) * parts, 1);
185 if (ret)
186 return ret;
187
188 /* and the rest starting from (8GiB + common_size) */
189 offset = (0x0200000000ULL >> 12) + (bsize << 8);
190 length = (priv->base.ram.size >> 12) - (bsize << 8) - rsvd_tail;
191
192 ret = nouveau_mm_init(&pfb->vram, offset, length, 0);
193 if (ret) {
194 nouveau_mm_fini(&pfb->vram);
195 return ret;
196 }
197
198 return 0;
199}
200
201static int
202nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 201nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
203 struct nouveau_oclass *oclass, void *data, u32 size, 202 struct nouveau_oclass *oclass, void *data, u32 size,
204 struct nouveau_object **pobject) 203 struct nouveau_object **pobject)
@@ -213,13 +212,10 @@ nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
213 return ret; 212 return ret;
214 213
215 priv->base.memtype_valid = nvc0_fb_memtype_valid; 214 priv->base.memtype_valid = nvc0_fb_memtype_valid;
215 priv->base.ram.init = nvc0_fb_vram_init;
216 priv->base.ram.get = nvc0_fb_vram_new; 216 priv->base.ram.get = nvc0_fb_vram_new;
217 priv->base.ram.put = nv50_fb_vram_del; 217 priv->base.ram.put = nv50_fb_vram_del;
218 218
219 ret = nvc0_vram_detect(priv);
220 if (ret)
221 return ret;
222
223 priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); 219 priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
224 if (!priv->r100c10_page) 220 if (!priv->r100c10_page)
225 return -ENOMEM; 221 return -ENOMEM;
@@ -229,7 +225,7 @@ nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
229 if (pci_dma_mapping_error(device->pdev, priv->r100c10)) 225 if (pci_dma_mapping_error(device->pdev, priv->r100c10))
230 return -EFAULT; 226 return -EFAULT;
231 227
232 return nouveau_fb_created(&priv->base); 228 return nouveau_fb_preinit(&priv->base);
233} 229}
234 230
235 231