diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2010-03-17 19:45:20 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-04-08 20:12:02 -0400 |
commit | a76fb4e8ffe42144529e21fe1e609b762e8eb5cc (patch) | |
tree | 3215f63360ffb93d685582edeca2e48ee7646170 /drivers/gpu/drm/nouveau/nouveau_mem.c | |
parent | 952eb63543552deb1bf1113739d59d29172d7755 (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.c | 96 |
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 */ | ||
481 | static uint32_t | 480 | static uint32_t |
482 | nouveau_mem_fb_amount_igp(struct drm_device *dev) | 481 | nouveau_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 | |||
502 | static uint32_t | ||
503 | nouveau_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 */ |
508 | uint64_t nouveau_mem_fb_amount(struct drm_device *dev) | 529 | int |
530 | nouveau_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; |