aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_mem.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-03-17 19:45:20 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-04-08 20:12:02 -0400
commita76fb4e8ffe42144529e21fe1e609b762e8eb5cc (patch)
tree3215f63360ffb93d685582edeca2e48ee7646170 /drivers/gpu/drm/nouveau/nouveau_mem.c
parent952eb63543552deb1bf1113739d59d29172d7755 (diff)
drm/nouveau: detect vram amount once, and save the value
As opposed to repeatedly reading the amount back from the GPU every time we need to know the VRAM size. We should now fail to load gracefully on detecting no VRAM, rather than something potentially messy happening. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_mem.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mem.c96
1 files changed, 48 insertions, 48 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
index a4d5ecc6ed5a..775a7017af64 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -477,9 +477,30 @@ void nouveau_mem_close(struct drm_device *dev)
477 } 477 }
478} 478}
479 479
480/*XXX won't work on BSD because of pci_read_config_dword */
481static uint32_t 480static uint32_t
482nouveau_mem_fb_amount_igp(struct drm_device *dev) 481nouveau_mem_detect_nv04(struct drm_device *dev)
482{
483 uint32_t boot0 = nv_rd32(dev, NV03_BOOT_0);
484
485 if (boot0 & 0x00000100)
486 return (((boot0 >> 12) & 0xf) * 2 + 2) * 1024 * 1024;
487
488 switch (boot0 & NV03_BOOT_0_RAM_AMOUNT) {
489 case NV04_BOOT_0_RAM_AMOUNT_32MB:
490 return 32 * 1024 * 1024;
491 case NV04_BOOT_0_RAM_AMOUNT_16MB:
492 return 16 * 1024 * 1024;
493 case NV04_BOOT_0_RAM_AMOUNT_8MB:
494 return 8 * 1024 * 1024;
495 case NV04_BOOT_0_RAM_AMOUNT_4MB:
496 return 4 * 1024 * 1024;
497 }
498
499 return 0;
500}
501
502static uint32_t
503nouveau_mem_detect_nforce(struct drm_device *dev)
483{ 504{
484 struct drm_nouveau_private *dev_priv = dev->dev_private; 505 struct drm_nouveau_private *dev_priv = dev->dev_private;
485 struct pci_dev *bridge; 506 struct pci_dev *bridge;
@@ -491,11 +512,11 @@ nouveau_mem_fb_amount_igp(struct drm_device *dev)
491 return 0; 512 return 0;
492 } 513 }
493 514
494 if (dev_priv->flags&NV_NFORCE) { 515 if (dev_priv->flags & NV_NFORCE) {
495 pci_read_config_dword(bridge, 0x7C, &mem); 516 pci_read_config_dword(bridge, 0x7C, &mem);
496 return (uint64_t)(((mem >> 6) & 31) + 1)*1024*1024; 517 return (uint64_t)(((mem >> 6) & 31) + 1)*1024*1024;
497 } else 518 } else
498 if (dev_priv->flags&NV_NFORCE2) { 519 if (dev_priv->flags & NV_NFORCE2) {
499 pci_read_config_dword(bridge, 0x84, &mem); 520 pci_read_config_dword(bridge, 0x84, &mem);
500 return (uint64_t)(((mem >> 4) & 127) + 1)*1024*1024; 521 return (uint64_t)(((mem >> 4) & 127) + 1)*1024*1024;
501 } 522 }
@@ -505,50 +526,32 @@ nouveau_mem_fb_amount_igp(struct drm_device *dev)
505} 526}
506 527
507/* returns the amount of FB ram in bytes */ 528/* returns the amount of FB ram in bytes */
508uint64_t nouveau_mem_fb_amount(struct drm_device *dev) 529int
530nouveau_mem_detect(struct drm_device *dev)
509{ 531{
510 struct drm_nouveau_private *dev_priv = dev->dev_private; 532 struct drm_nouveau_private *dev_priv = dev->dev_private;
511 uint32_t boot0; 533
512 534 if (dev_priv->card_type == NV_04) {
513 switch (dev_priv->card_type) { 535 dev_priv->vram_size = nouveau_mem_detect_nv04(dev);
514 case NV_04: 536 } else
515 boot0 = nv_rd32(dev, NV03_BOOT_0); 537 if (dev_priv->flags & (NV_NFORCE | NV_NFORCE2)) {
516 if (boot0 & 0x00000100) 538 dev_priv->vram_size = nouveau_mem_detect_nforce(dev);
517 return (((boot0 >> 12) & 0xf) * 2 + 2) * 1024 * 1024; 539 } else {
518 540 dev_priv->vram_size = nv_rd32(dev, NV04_FIFO_DATA);
519 switch (boot0 & NV03_BOOT_0_RAM_AMOUNT) { 541 dev_priv->vram_size &= NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK;
520 case NV04_BOOT_0_RAM_AMOUNT_32MB: 542 if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac)
521 return 32 * 1024 * 1024; 543 dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10) << 12;
522 case NV04_BOOT_0_RAM_AMOUNT_16MB:
523 return 16 * 1024 * 1024;
524 case NV04_BOOT_0_RAM_AMOUNT_8MB:
525 return 8 * 1024 * 1024;
526 case NV04_BOOT_0_RAM_AMOUNT_4MB:
527 return 4 * 1024 * 1024;
528 }
529 break;
530 case NV_10:
531 case NV_20:
532 case NV_30:
533 case NV_40:
534 case NV_50:
535 default:
536 if (dev_priv->flags & (NV_NFORCE | NV_NFORCE2)) {
537 return nouveau_mem_fb_amount_igp(dev);
538 } else {
539 uint64_t mem;
540 mem = (nv_rd32(dev, NV04_FIFO_DATA) &
541 NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK) >>
542 NV10_FIFO_DATA_RAM_AMOUNT_MB_SHIFT;
543 return mem * 1024 * 1024;
544 }
545 break;
546 } 544 }
547 545
548 NV_ERROR(dev, 546 NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
549 "Unable to detect video ram size. Please report your setup to " 547 if (dev_priv->vram_sys_base) {
550 DRIVER_EMAIL "\n"); 548 NV_INFO(dev, "Stolen system memory at: 0x%010llx\n",
551 return 0; 549 dev_priv->vram_sys_base);
550 }
551
552 if (dev_priv->vram_size)
553 return 0;
554 return -ENOMEM;
552} 555}
553 556
554#if __OS_HAS_AGP 557#if __OS_HAS_AGP
@@ -659,15 +662,12 @@ nouveau_mem_init(struct drm_device *dev)
659 spin_lock_init(&dev_priv->ttm.bo_list_lock); 662 spin_lock_init(&dev_priv->ttm.bo_list_lock);
660 spin_lock_init(&dev_priv->tile.lock); 663 spin_lock_init(&dev_priv->tile.lock);
661 664
662 dev_priv->fb_available_size = nouveau_mem_fb_amount(dev); 665 dev_priv->fb_available_size = dev_priv->vram_size;
663
664 dev_priv->fb_mappable_pages = dev_priv->fb_available_size; 666 dev_priv->fb_mappable_pages = dev_priv->fb_available_size;
665 if (dev_priv->fb_mappable_pages > drm_get_resource_len(dev, 1)) 667 if (dev_priv->fb_mappable_pages > drm_get_resource_len(dev, 1))
666 dev_priv->fb_mappable_pages = drm_get_resource_len(dev, 1); 668 dev_priv->fb_mappable_pages = drm_get_resource_len(dev, 1);
667 dev_priv->fb_mappable_pages >>= PAGE_SHIFT; 669 dev_priv->fb_mappable_pages >>= PAGE_SHIFT;
668 670
669 NV_INFO(dev, "%d MiB VRAM\n", (int)(dev_priv->fb_available_size >> 20));
670
671 /* remove reserved space at end of vram from available amount */ 671 /* remove reserved space at end of vram from available amount */
672 dev_priv->fb_available_size -= dev_priv->ramin_rsvd_vram; 672 dev_priv->fb_available_size -= dev_priv->ramin_rsvd_vram;
673 dev_priv->fb_aper_free = dev_priv->fb_available_size; 673 dev_priv->fb_aper_free = dev_priv->fb_available_size;