aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2011-12-12 08:03:14 -0500
committerBen Skeggs <bskeggs@redhat.com>2012-03-13 03:05:35 -0400
commitff92a6cda74c0a51cb723f5e224124cf74e62f25 (patch)
treeb5973d168c9b2dfcbacfaf9e8bbbc124c7c6d8c5 /drivers
parentd81c19e312a22bdcebef1370f3af30a146670787 (diff)
drm/nv20-nv40: add memory type detection
NV20/NV30 is partially educated guesswork at this point, based on any information around about available memory types and a horribly unspeakable amount of vbios image scouring. I'm not entirely certain the GDDR3 define is correct, I have not spotted a single vbios with that value yet (though it is mentioned in some 1218-using nv4x vbios), but there are reports that some nv3x did use it.. NV40(100914) confirmed by switching an NV49 to DDR1/DDR2 values and making sure that the binary driver behaviour showed it had detected DDR1/DDR2 instead of GDDR3 before dying horribly. NV40(100474) confirmed by doing much the same task as above on an NV44, except this was *much* easier as changing the values didn't seem to have any noticable effect on the memory controller aside from changing the binary driver's behaviour. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_state.c2
-rw-r--r--drivers/gpu/drm/nouveau/nv20_fb.c11
-rw-r--r--drivers/gpu/drm/nouveau/nv40_fb.c45
4 files changed, 57 insertions, 2 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 576b0f67a8ba..59031d308fcc 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -1173,6 +1173,7 @@ extern void nv30_fb_init_tile_region(struct drm_device *dev, int i,
1173extern void nv30_fb_free_tile_region(struct drm_device *dev, int i); 1173extern void nv30_fb_free_tile_region(struct drm_device *dev, int i);
1174 1174
1175/* nv40_fb.c */ 1175/* nv40_fb.c */
1176extern int nv40_fb_vram_init(struct drm_device *dev);
1176extern int nv40_fb_init(struct drm_device *); 1177extern int nv40_fb_init(struct drm_device *);
1177extern void nv40_fb_takedown(struct drm_device *); 1178extern void nv40_fb_takedown(struct drm_device *);
1178extern void nv40_fb_set_tile_region(struct drm_device *dev, int i); 1179extern void nv40_fb_set_tile_region(struct drm_device *dev, int i);
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index 6c262e1aaf9e..a30d7af58eb3 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -290,7 +290,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
290 engine->pm.temp_get = nv40_temp_get; 290 engine->pm.temp_get = nv40_temp_get;
291 engine->pm.pwm_get = nv40_pm_pwm_get; 291 engine->pm.pwm_get = nv40_pm_pwm_get;
292 engine->pm.pwm_set = nv40_pm_pwm_set; 292 engine->pm.pwm_set = nv40_pm_pwm_set;
293 engine->vram.init = nv20_fb_vram_init; 293 engine->vram.init = nv40_fb_vram_init;
294 engine->vram.takedown = nouveau_stub_takedown; 294 engine->vram.takedown = nouveau_stub_takedown;
295 engine->vram.flags_valid = nouveau_mem_flags_valid; 295 engine->vram.flags_valid = nouveau_mem_flags_valid;
296 break; 296 break;
diff --git a/drivers/gpu/drm/nouveau/nv20_fb.c b/drivers/gpu/drm/nouveau/nv20_fb.c
index 6585c27186da..19bd64059a66 100644
--- a/drivers/gpu/drm/nouveau/nv20_fb.c
+++ b/drivers/gpu/drm/nouveau/nv20_fb.c
@@ -100,8 +100,17 @@ int
100nv20_fb_vram_init(struct drm_device *dev) 100nv20_fb_vram_init(struct drm_device *dev)
101{ 101{
102 struct drm_nouveau_private *dev_priv = dev->dev_private; 102 struct drm_nouveau_private *dev_priv = dev->dev_private;
103 u32 mem_size = nv_rd32(dev, 0x10020c);
104 u32 pbus1218 = nv_rd32(dev, 0x001218);
105
106 dev_priv->vram_size = mem_size & 0xff000000;
107 switch (pbus1218 & 0x00000300) {
108 case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_SDRAM; break;
109 case 0x00000100: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break;
110 case 0x00000200: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break;
111 case 0x00000300: dev_priv->vram_type = NV_MEM_TYPE_GDDR2; break;
112 }
103 113
104 dev_priv->vram_size = nv_rd32(dev, 0x10020c) & 0xff000000;
105 return 0; 114 return 0;
106} 115}
107 116
diff --git a/drivers/gpu/drm/nouveau/nv40_fb.c b/drivers/gpu/drm/nouveau/nv40_fb.c
index f0ac2a768c67..7fbcb334c096 100644
--- a/drivers/gpu/drm/nouveau/nv40_fb.c
+++ b/drivers/gpu/drm/nouveau/nv40_fb.c
@@ -72,6 +72,51 @@ nv44_fb_init_gart(struct drm_device *dev)
72} 72}
73 73
74int 74int
75nv40_fb_vram_init(struct drm_device *dev)
76{
77 struct drm_nouveau_private *dev_priv = dev->dev_private;
78
79 /* 0x001218 is actually present on a few other NV4X I looked at,
80 * and even contains sane values matching 0x100474. From looking
81 * at various vbios images however, this isn't the case everywhere.
82 * So, I chose to use the same regs I've seen NVIDIA reading around
83 * the memory detection, hopefully that'll get us the right numbers
84 */
85 if (dev_priv->chipset == 0x40) {
86 u32 pbus1218 = nv_rd32(dev, 0x001218);
87 switch (pbus1218 & 0x00000300) {
88 case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_SDRAM; break;
89 case 0x00000100: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break;
90 case 0x00000200: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break;
91 case 0x00000300: dev_priv->vram_type = NV_MEM_TYPE_DDR2; break;
92 }
93 } else
94 if (dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b) {
95 u32 pfb914 = nv_rd32(dev, 0x100914);
96 switch (pfb914 & 0x00000003) {
97 case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break;
98 case 0x00000001: dev_priv->vram_type = NV_MEM_TYPE_DDR2; break;
99 case 0x00000002: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break;
100 case 0x00000003: break;
101 }
102 } else
103 if (dev_priv->chipset != 0x4e) {
104 u32 pfb474 = nv_rd32(dev, 0x100474);
105 if (pfb474 & 0x00000004)
106 dev_priv->vram_type = NV_MEM_TYPE_GDDR3;
107 if (pfb474 & 0x00000002)
108 dev_priv->vram_type = NV_MEM_TYPE_DDR2;
109 if (pfb474 & 0x00000001)
110 dev_priv->vram_type = NV_MEM_TYPE_DDR1;
111 } else {
112 dev_priv->vram_type = NV_MEM_TYPE_STOLEN;
113 }
114
115 dev_priv->vram_size = nv_rd32(dev, 0x10020c) & 0xff000000;
116 return 0;
117}
118
119int
75nv40_fb_init(struct drm_device *dev) 120nv40_fb_init(struct drm_device *dev)
76{ 121{
77 struct drm_nouveau_private *dev_priv = dev->dev_private; 122 struct drm_nouveau_private *dev_priv = dev->dev_private;