From 7ad2d31cb692597f7918fce2f52a4c1949fbcf8d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 11 Dec 2011 00:30:05 +1000 Subject: [PATCH] drm/nouveau: move vram detection funcs to chipset-specific fb code Also, display detected memory type in logs - though, we don't even try to detect this yet. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_drv.c | 4 ++ drivers/gpu/drm/nouveau/nouveau_drv.h | 18 +++++- drivers/gpu/drm/nouveau/nouveau_mem.c | 103 ++++++++++---------------------- drivers/gpu/drm/nouveau/nouveau_state.c | 14 +++-- drivers/gpu/drm/nouveau/nv04_fb.c | 29 +++++++++ drivers/gpu/drm/nouveau/nv10_fb.c | 35 +++++++++++ 6 files changed, 127 insertions(+), 76 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 81d7962..4567e8c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -57,6 +57,10 @@ MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM"); int nouveau_vram_notify = 0; module_param_named(vram_notify, nouveau_vram_notify, int, 0400); +MODULE_PARM_DESC(vram_type, "Override detected VRAM type"); +char *nouveau_vram_type; +module_param_named(vram_type, nouveau_vram_type, charp, 0400); + MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)"); int nouveau_duallink = 1; module_param_named(duallink, nouveau_duallink, int, 0400); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index b827098..36b50e5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -772,6 +772,19 @@ struct drm_nouveau_private { } tile; /* VRAM/fb configuration */ + enum { + NV_MEM_TYPE_UNKNOWN = 0, + NV_MEM_TYPE_STOLEN, + NV_MEM_TYPE_SGRAM, + NV_MEM_TYPE_SDRAM, + NV_MEM_TYPE_DDR1, + NV_MEM_TYPE_DDR2, + NV_MEM_TYPE_DDR3, + NV_MEM_TYPE_GDDR2, + NV_MEM_TYPE_GDDR3, + NV_MEM_TYPE_GDDR4, + NV_MEM_TYPE_GDDR5 + } vram_type; uint64_t vram_size; uint64_t vram_sys_base; @@ -846,6 +859,7 @@ extern int nouveau_uscript_lvds; extern int nouveau_uscript_tmds; extern int nouveau_vram_pushbuf; extern int nouveau_vram_notify; +extern char *nouveau_vram_type; extern int nouveau_fbpercrtc; extern int nouveau_tv_disable; extern char *nouveau_tv_norm; @@ -894,7 +908,6 @@ extern void nouveau_mem_gart_fini(struct drm_device *); extern int nouveau_mem_init_agp(struct drm_device *); extern int nouveau_mem_reset_agp(struct drm_device *); extern void nouveau_mem_close(struct drm_device *); -extern int nouveau_mem_detect(struct drm_device *); extern bool nouveau_mem_flags_valid(struct drm_device *, u32 tile_flags); extern struct nouveau_tile_reg *nv10_mem_set_tiling( struct drm_device *dev, uint32_t addr, uint32_t size, @@ -1126,10 +1139,13 @@ void nouveau_dp_tu_update(struct drm_device *, int, int, u32, u32); u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_entry *, u8 **); /* nv04_fb.c */ +extern int nv04_fb_vram_init(struct drm_device *); extern int nv04_fb_init(struct drm_device *); extern void nv04_fb_takedown(struct drm_device *); /* nv10_fb.c */ +extern int nv10_fb_vram_init(struct drm_device *dev); +extern int nv1a_fb_vram_init(struct drm_device *dev); extern int nv10_fb_init(struct drm_device *); extern void nv10_fb_takedown(struct drm_device *); extern void nv10_fb_init_tile_region(struct drm_device *dev, int i, diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index c3a5745..4a65831 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -192,75 +192,6 @@ nouveau_mem_gart_fini(struct drm_device *dev) } } -static uint32_t -nouveau_mem_detect_nv04(struct drm_device *dev) -{ - uint32_t boot0 = nv_rd32(dev, NV04_PFB_BOOT_0); - - if (boot0 & 0x00000100) - return (((boot0 >> 12) & 0xf) * 2 + 2) * 1024 * 1024; - - switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) { - case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB: - return 32 * 1024 * 1024; - case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB: - return 16 * 1024 * 1024; - case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB: - return 8 * 1024 * 1024; - case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB: - return 4 * 1024 * 1024; - } - - return 0; -} - -static uint32_t -nouveau_mem_detect_nforce(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct pci_dev *bridge; - uint32_t mem; - - bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1)); - if (!bridge) { - NV_ERROR(dev, "no bridge device\n"); - return 0; - } - - if (dev_priv->flags & NV_NFORCE) { - pci_read_config_dword(bridge, 0x7C, &mem); - return (uint64_t)(((mem >> 6) & 31) + 1)*1024*1024; - } else - if (dev_priv->flags & NV_NFORCE2) { - pci_read_config_dword(bridge, 0x84, &mem); - return (uint64_t)(((mem >> 4) & 127) + 1)*1024*1024; - } - - NV_ERROR(dev, "impossible!\n"); - return 0; -} - -int -nouveau_mem_detect(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - if (dev_priv->card_type == NV_04) { - dev_priv->vram_size = nouveau_mem_detect_nv04(dev); - } else - if (dev_priv->flags & (NV_NFORCE | NV_NFORCE2)) { - dev_priv->vram_size = nouveau_mem_detect_nforce(dev); - } else - if (dev_priv->card_type < NV_50) { - dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); - dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK; - } - - if (dev_priv->vram_size) - return 0; - return -ENOMEM; -} - bool nouveau_mem_flags_valid(struct drm_device *dev, u32 tile_flags) { @@ -385,11 +316,29 @@ nouveau_mem_init_agp(struct drm_device *dev) return 0; } +static const struct vram_types { + int value; + const char *name; +} vram_type_map[] = { + { 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" }, + { NV_MEM_TYPE_UNKNOWN, "unknown type" } +}; + int nouveau_mem_vram_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; + const struct vram_types *vram_type; int ret, dma_bits; dma_bits = 32; @@ -427,7 +376,21 @@ nouveau_mem_vram_init(struct drm_device *dev) return ret; } - NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20)); + vram_type = vram_type_map; + while (vram_type->value != NV_MEM_TYPE_UNKNOWN) { + if (nouveau_vram_type) { + if (!strcasecmp(nouveau_vram_type, vram_type->name)) + break; + dev_priv->vram_type = vram_type->value; + } else { + if (vram_type->value == dev_priv->vram_type) + break; + } + vram_type++; + } + + NV_INFO(dev, "Detected %dMiB VRAM (%s)\n", + (int)(dev_priv->vram_size >> 20), vram_type->name); if (dev_priv->vram_sys_base) { NV_INFO(dev, "Stolen system memory at: 0x%010llx\n", dev_priv->vram_sys_base); diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 912839c..dba3e90 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -87,7 +87,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.clocks_get = nv04_pm_clocks_get; engine->pm.clocks_pre = nv04_pm_clocks_pre; engine->pm.clocks_set = nv04_pm_clocks_set; - engine->vram.init = nouveau_mem_detect; + engine->vram.init = nv04_fb_vram_init; engine->vram.takedown = nouveau_stub_takedown; engine->vram.flags_valid = nouveau_mem_flags_valid; break; @@ -134,7 +134,11 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.clocks_get = nv04_pm_clocks_get; engine->pm.clocks_pre = nv04_pm_clocks_pre; engine->pm.clocks_set = nv04_pm_clocks_set; - engine->vram.init = nouveau_mem_detect; + if (dev_priv->chipset == 0x1a || + dev_priv->chipset == 0x1f) + engine->vram.init = nv1a_fb_vram_init; + else + engine->vram.init = nv10_fb_vram_init; engine->vram.takedown = nouveau_stub_takedown; engine->vram.flags_valid = nouveau_mem_flags_valid; break; @@ -181,7 +185,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.clocks_get = nv04_pm_clocks_get; engine->pm.clocks_pre = nv04_pm_clocks_pre; engine->pm.clocks_set = nv04_pm_clocks_set; - engine->vram.init = nouveau_mem_detect; + engine->vram.init = nv10_fb_vram_init; engine->vram.takedown = nouveau_stub_takedown; engine->vram.flags_valid = nouveau_mem_flags_valid; break; @@ -230,7 +234,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.clocks_set = nv04_pm_clocks_set; engine->pm.voltage_get = nouveau_voltage_gpio_get; engine->pm.voltage_set = nouveau_voltage_gpio_set; - engine->vram.init = nouveau_mem_detect; + engine->vram.init = nv10_fb_vram_init; engine->vram.takedown = nouveau_stub_takedown; engine->vram.flags_valid = nouveau_mem_flags_valid; break; @@ -286,7 +290,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.temp_get = nv40_temp_get; engine->pm.pwm_get = nv40_pm_pwm_get; engine->pm.pwm_set = nv40_pm_pwm_set; - engine->vram.init = nouveau_mem_detect; + engine->vram.init = nv10_fb_vram_init; engine->vram.takedown = nouveau_stub_takedown; engine->vram.flags_valid = nouveau_mem_flags_valid; break; diff --git a/drivers/gpu/drm/nouveau/nv04_fb.c b/drivers/gpu/drm/nouveau/nv04_fb.c index 638cf60..db16c47 100644 --- a/drivers/gpu/drm/nouveau/nv04_fb.c +++ b/drivers/gpu/drm/nouveau/nv04_fb.c @@ -4,6 +4,35 @@ #include "nouveau_drm.h" int +nv04_fb_vram_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + u32 boot0 = nv_rd32(dev, NV04_PFB_BOOT_0); + + if (boot0 & 0x00000100) { + dev_priv->vram_size = ((boot0 >> 12) & 0xf) * 2 + 2; + dev_priv->vram_size *= 1024 * 1024; + } else { + switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) { + case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB: + dev_priv->vram_size = 32 * 1024 * 1024; + break; + case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB: + dev_priv->vram_size = 16 * 1024 * 1024; + break; + case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB: + dev_priv->vram_size = 8 * 1024 * 1024; + break; + case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB: + dev_priv->vram_size = 4 * 1024 * 1024; + break; + } + } + + return 0; +} + +int nv04_fb_init(struct drm_device *dev) { /* This is what the DDX did for NV_ARCH_04, but a mmio-trace shows diff --git a/drivers/gpu/drm/nouveau/nv10_fb.c b/drivers/gpu/drm/nouveau/nv10_fb.c index f78181a..7b17dea 100644 --- a/drivers/gpu/drm/nouveau/nv10_fb.c +++ b/drivers/gpu/drm/nouveau/nv10_fb.c @@ -3,6 +3,41 @@ #include "nouveau_drv.h" #include "nouveau_drm.h" +int +nv1a_fb_vram_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct pci_dev *bridge; + uint32_t mem, mib; + + bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1)); + if (!bridge) { + NV_ERROR(dev, "no bridge device\n"); + return 0; + } + + if (dev_priv->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; + } + + dev_priv->vram_size = mib * 1024 * 1024; + return 0; +} + +int +nv10_fb_vram_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + u32 fifo_data = nv_rd32(dev, NV04_PFB_FIFO_DATA); + + dev_priv->vram_size = fifo_data & NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK; + return 0; +} + static struct drm_mm_node * nv20_fb_alloc_tag(struct drm_device *dev, uint32_t size) { -- 2.7.4