diff options
author | Roy Spliet <r.spliet@student.tudelft.nl> | 2011-03-27 18:13:11 +0200 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2011-05-16 10:47:43 +1000 |
commit | 50066f8117d79163b96d3bf778c41961be1fe5cd (patch) | |
tree | a3425c1d9108768fac80d3e2fc508d3babeb2023 /drivers/gpu | |
parent | 7795bee0c437aff7fb188afe750fe79a7a971a2c (diff) |
drm/nouveau: improve memtiming table parsing
Improves the parsing of the memory timing table on NV50-NV98revA1 chipsets.
Added stepping to drm_nouveau_private to make sure newer NV98 (105M) is
zero rather than incorrect.
Signed-off-by: Roy Spliet <r.spliet@student.tudelft.nl>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_mem.c | 45 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_state.c | 2 |
3 files changed, 35 insertions, 14 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 711ee0d9627d..0f5f797e500c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -466,6 +466,7 @@ struct nouveau_pm_memtiming { u32 reg_100234; u32 reg_100238; u32 reg_10023c; + u32 reg_100240; }; struct nouveau_pm_memtimings { @@ -637,6 +638,7 @@ struct drm_nouveau_private { enum nouveau_card_type card_type; /* exact chipset, derived from NV_PMC_BOOT_0 */ int chipset; + int stepping; int flags; void __iomem *mmio; diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index e177a62967e0..cf1731bbb032 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -597,9 +597,9 @@ nouveau_mem_timing_init(struct drm_device *dev) if (!memtimings->timing) return; - /* Get "some number" from the timing reg for NV_40 + /* Get "some number" from the timing reg for NV_40 and NV_50 * Used in calculations later */ - if (dev_priv->card_type == NV_40) { + if (dev_priv->card_type >= NV_40 && dev_priv->chipset < 0x98) { magic_number = (nv_rd32(dev, 0x100228) & 0x0f000000) >> 24; } @@ -643,7 +643,7 @@ nouveau_mem_timing_init(struct drm_device *dev) /* XXX: I don't trust the -1's and +1's... they must come * from somewhere! */ timing->reg_100224 = (tUNK_0 + tUNK_19 + 1 + magic_number) << 24 | - tUNK_18 << 16 | + max(tUNK_18, (u8) 1) << 16 | (tUNK_1 + tUNK_19 + 1 + magic_number) << 8; if (dev_priv->chipset == 0xa8) { timing->reg_100224 |= (tUNK_2 - 1); @@ -652,17 +652,27 @@ nouveau_mem_timing_init(struct drm_device *dev) } timing->reg_100228 = (tUNK_12 << 16 | tUNK_11 << 8 | tUNK_10); - if (dev_priv->chipset >= 0xa3 && dev_priv->chipset < 0xaa) { + if (dev_priv->chipset >= 0xa3 && dev_priv->chipset < 0xaa) timing->reg_100228 |= (tUNK_19 - 1) << 24; - } + else + timing->reg_100228 |= magic_number << 24; if (dev_priv->card_type == NV_40) { /* NV40: don't know what the rest of the regs are.. * And don't need to know either */ - timing->reg_100228 |= 0x20200000 | magic_number << 24; + timing->reg_100228 |= 0x20200000; } else if (dev_priv->card_type >= NV_50) { - /* XXX: reg_10022c */ - timing->reg_10022c = tUNK_2 - 1; + if (dev_priv->chipset < 0x98 || + (dev_priv->chipset == 0x98 && + dev_priv->stepping <= 0xa1)) { + timing->reg_10022c = (0x14 + tUNK_2) << 24 | + 0x16 << 16 | + (tUNK_2 - 1) << 8 | + (tUNK_2 - 1); + } else { + /* XXX: reg_10022c for recentish cards */ + timing->reg_10022c = tUNK_2 - 1; + } timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 | tUNK_13 << 8 | tUNK_13); @@ -670,23 +680,29 @@ nouveau_mem_timing_init(struct drm_device *dev) timing->reg_100234 = (tRAS << 24 | tRC); timing->reg_100234 += max(tUNK_10, tUNK_11) << 16; - if (dev_priv->chipset < 0xa3) { + if (dev_priv->chipset < 0x98 || + (dev_priv->chipset == 0x98 && + dev_priv->stepping <= 0xa1)) { timing->reg_100234 |= (tUNK_2 + 2) << 8; } else { /* XXX: +6? */ timing->reg_100234 |= (tUNK_19 + 6) << 8; } - /* XXX; reg_100238, reg_10023c - * reg_100238: 0x00?????? - * reg_10023c: 0x!!??0202 for NV50+ cards (empirical evidence) */ + /* XXX; reg_100238 + * reg_100238: 0x00?????? */ timing->reg_10023c = 0x202; - if (dev_priv->chipset < 0xa3) { + if (dev_priv->chipset < 0x98 || + (dev_priv->chipset == 0x98 && + dev_priv->stepping <= 0xa1)) { timing->reg_10023c |= 0x4000000 | (tUNK_2 - 1) << 16; } else { - /* currently unknown + /* XXX: reg_10023c + * currently unknown * 10023c seen as 06xxxxxx, 0bxxxxxx or 0fxxxxxx */ } + + /* XXX: reg_100240? */ } NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i, @@ -695,6 +711,7 @@ nouveau_mem_timing_init(struct drm_device *dev) NV_DEBUG(dev, " 230: %08x %08x %08x %08x\n", timing->reg_100230, timing->reg_100234, timing->reg_100238, timing->reg_10023c); + NV_DEBUG(dev, " 240: %08x\n", timing->reg_100240); } memtimings->nr_timing = entries; diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index e04c4b651955..4b4992824bbf 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -913,11 +913,13 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) /* Time to determine the card architecture */ reg0 = nv_rd32(dev, NV03_PMC_BOOT_0); + dev_priv->stepping = 0; /* XXX: add stepping for pre-NV10? */ /* We're dealing with >=NV10 */ if ((reg0 & 0x0f000000) > 0) { /* Bit 27-20 contain the architecture in hex */ dev_priv->chipset = (reg0 & 0xff00000) >> 20; + dev_priv->stepping = (reg0 & 0xff); /* NV04 or NV05 */ } else if ((reg0 & 0xff00fff0) == 0x20004000) { if (reg0 & 0x00f00000) |