diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_device.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_device.c | 93 |
1 files changed, 70 insertions, 23 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index df988142e6b0..02bcdb1240c0 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
@@ -44,10 +44,11 @@ void radeon_surface_init(struct radeon_device *rdev) | |||
44 | if (rdev->family < CHIP_R600) { | 44 | if (rdev->family < CHIP_R600) { |
45 | int i; | 45 | int i; |
46 | 46 | ||
47 | for (i = 0; i < 8; i++) { | 47 | for (i = 0; i < RADEON_GEM_MAX_SURFACES; i++) { |
48 | WREG32(RADEON_SURFACE0_INFO + | 48 | if (rdev->surface_regs[i].bo) |
49 | i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO), | 49 | radeon_bo_get_surface_reg(rdev->surface_regs[i].bo); |
50 | 0); | 50 | else |
51 | radeon_clear_surface_reg(rdev, i); | ||
51 | } | 52 | } |
52 | /* enable surfaces */ | 53 | /* enable surfaces */ |
53 | WREG32(RADEON_SURFACE_CNTL, 0); | 54 | WREG32(RADEON_SURFACE_CNTL, 0); |
@@ -208,6 +209,24 @@ bool radeon_card_posted(struct radeon_device *rdev) | |||
208 | 209 | ||
209 | } | 210 | } |
210 | 211 | ||
212 | bool radeon_boot_test_post_card(struct radeon_device *rdev) | ||
213 | { | ||
214 | if (radeon_card_posted(rdev)) | ||
215 | return true; | ||
216 | |||
217 | if (rdev->bios) { | ||
218 | DRM_INFO("GPU not posted. posting now...\n"); | ||
219 | if (rdev->is_atom_bios) | ||
220 | atom_asic_init(rdev->mode_info.atom_context); | ||
221 | else | ||
222 | radeon_combios_asic_init(rdev->ddev); | ||
223 | return true; | ||
224 | } else { | ||
225 | dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); | ||
226 | return false; | ||
227 | } | ||
228 | } | ||
229 | |||
211 | int radeon_dummy_page_init(struct radeon_device *rdev) | 230 | int radeon_dummy_page_init(struct radeon_device *rdev) |
212 | { | 231 | { |
213 | rdev->dummy_page.page = alloc_page(GFP_DMA32 | GFP_KERNEL | __GFP_ZERO); | 232 | rdev->dummy_page.page = alloc_page(GFP_DMA32 | GFP_KERNEL | __GFP_ZERO); |
@@ -444,27 +463,36 @@ static uint32_t cail_reg_read(struct card_info *info, uint32_t reg) | |||
444 | return r; | 463 | return r; |
445 | } | 464 | } |
446 | 465 | ||
447 | static struct card_info atom_card_info = { | ||
448 | .dev = NULL, | ||
449 | .reg_read = cail_reg_read, | ||
450 | .reg_write = cail_reg_write, | ||
451 | .mc_read = cail_mc_read, | ||
452 | .mc_write = cail_mc_write, | ||
453 | .pll_read = cail_pll_read, | ||
454 | .pll_write = cail_pll_write, | ||
455 | }; | ||
456 | |||
457 | int radeon_atombios_init(struct radeon_device *rdev) | 466 | int radeon_atombios_init(struct radeon_device *rdev) |
458 | { | 467 | { |
459 | atom_card_info.dev = rdev->ddev; | 468 | struct card_info *atom_card_info = |
460 | rdev->mode_info.atom_context = atom_parse(&atom_card_info, rdev->bios); | 469 | kzalloc(sizeof(struct card_info), GFP_KERNEL); |
470 | |||
471 | if (!atom_card_info) | ||
472 | return -ENOMEM; | ||
473 | |||
474 | rdev->mode_info.atom_card_info = atom_card_info; | ||
475 | atom_card_info->dev = rdev->ddev; | ||
476 | atom_card_info->reg_read = cail_reg_read; | ||
477 | atom_card_info->reg_write = cail_reg_write; | ||
478 | atom_card_info->mc_read = cail_mc_read; | ||
479 | atom_card_info->mc_write = cail_mc_write; | ||
480 | atom_card_info->pll_read = cail_pll_read; | ||
481 | atom_card_info->pll_write = cail_pll_write; | ||
482 | |||
483 | rdev->mode_info.atom_context = atom_parse(atom_card_info, rdev->bios); | ||
461 | radeon_atom_initialize_bios_scratch_regs(rdev->ddev); | 484 | radeon_atom_initialize_bios_scratch_regs(rdev->ddev); |
485 | atom_allocate_fb_scratch(rdev->mode_info.atom_context); | ||
462 | return 0; | 486 | return 0; |
463 | } | 487 | } |
464 | 488 | ||
465 | void radeon_atombios_fini(struct radeon_device *rdev) | 489 | void radeon_atombios_fini(struct radeon_device *rdev) |
466 | { | 490 | { |
467 | kfree(rdev->mode_info.atom_context); | 491 | if (rdev->mode_info.atom_context) { |
492 | kfree(rdev->mode_info.atom_context->scratch); | ||
493 | kfree(rdev->mode_info.atom_context); | ||
494 | } | ||
495 | kfree(rdev->mode_info.atom_card_info); | ||
468 | } | 496 | } |
469 | 497 | ||
470 | int radeon_combios_init(struct radeon_device *rdev) | 498 | int radeon_combios_init(struct radeon_device *rdev) |
@@ -539,16 +567,24 @@ int radeon_device_init(struct radeon_device *rdev, | |||
539 | mutex_init(&rdev->cs_mutex); | 567 | mutex_init(&rdev->cs_mutex); |
540 | mutex_init(&rdev->ib_pool.mutex); | 568 | mutex_init(&rdev->ib_pool.mutex); |
541 | mutex_init(&rdev->cp.mutex); | 569 | mutex_init(&rdev->cp.mutex); |
570 | if (rdev->family >= CHIP_R600) | ||
571 | spin_lock_init(&rdev->ih.lock); | ||
572 | mutex_init(&rdev->gem.mutex); | ||
542 | rwlock_init(&rdev->fence_drv.lock); | 573 | rwlock_init(&rdev->fence_drv.lock); |
543 | INIT_LIST_HEAD(&rdev->gem.objects); | 574 | INIT_LIST_HEAD(&rdev->gem.objects); |
544 | 575 | ||
576 | /* setup workqueue */ | ||
577 | rdev->wq = create_workqueue("radeon"); | ||
578 | if (rdev->wq == NULL) | ||
579 | return -ENOMEM; | ||
580 | |||
545 | /* Set asic functions */ | 581 | /* Set asic functions */ |
546 | r = radeon_asic_init(rdev); | 582 | r = radeon_asic_init(rdev); |
547 | if (r) { | 583 | if (r) { |
548 | return r; | 584 | return r; |
549 | } | 585 | } |
550 | 586 | ||
551 | if (radeon_agpmode == -1) { | 587 | if (rdev->flags & RADEON_IS_AGP && radeon_agpmode == -1) { |
552 | radeon_agp_disable(rdev); | 588 | radeon_agp_disable(rdev); |
553 | } | 589 | } |
554 | 590 | ||
@@ -615,6 +651,7 @@ void radeon_device_fini(struct radeon_device *rdev) | |||
615 | DRM_INFO("radeon: finishing device.\n"); | 651 | DRM_INFO("radeon: finishing device.\n"); |
616 | rdev->shutdown = true; | 652 | rdev->shutdown = true; |
617 | radeon_fini(rdev); | 653 | radeon_fini(rdev); |
654 | destroy_workqueue(rdev->wq); | ||
618 | vga_client_register(rdev->pdev, NULL, NULL, NULL); | 655 | vga_client_register(rdev->pdev, NULL, NULL, NULL); |
619 | iounmap(rdev->rmmio); | 656 | iounmap(rdev->rmmio); |
620 | rdev->rmmio = NULL; | 657 | rdev->rmmio = NULL; |
@@ -628,6 +665,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) | |||
628 | { | 665 | { |
629 | struct radeon_device *rdev = dev->dev_private; | 666 | struct radeon_device *rdev = dev->dev_private; |
630 | struct drm_crtc *crtc; | 667 | struct drm_crtc *crtc; |
668 | int r; | ||
631 | 669 | ||
632 | if (dev == NULL || rdev == NULL) { | 670 | if (dev == NULL || rdev == NULL) { |
633 | return -ENODEV; | 671 | return -ENODEV; |
@@ -638,26 +676,31 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) | |||
638 | /* unpin the front buffers */ | 676 | /* unpin the front buffers */ |
639 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 677 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
640 | struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb); | 678 | struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb); |
641 | struct radeon_object *robj; | 679 | struct radeon_bo *robj; |
642 | 680 | ||
643 | if (rfb == NULL || rfb->obj == NULL) { | 681 | if (rfb == NULL || rfb->obj == NULL) { |
644 | continue; | 682 | continue; |
645 | } | 683 | } |
646 | robj = rfb->obj->driver_private; | 684 | robj = rfb->obj->driver_private; |
647 | if (robj != rdev->fbdev_robj) { | 685 | if (robj != rdev->fbdev_rbo) { |
648 | radeon_object_unpin(robj); | 686 | r = radeon_bo_reserve(robj, false); |
687 | if (unlikely(r == 0)) { | ||
688 | radeon_bo_unpin(robj); | ||
689 | radeon_bo_unreserve(robj); | ||
690 | } | ||
649 | } | 691 | } |
650 | } | 692 | } |
651 | /* evict vram memory */ | 693 | /* evict vram memory */ |
652 | radeon_object_evict_vram(rdev); | 694 | radeon_bo_evict_vram(rdev); |
653 | /* wait for gpu to finish processing current batch */ | 695 | /* wait for gpu to finish processing current batch */ |
654 | radeon_fence_wait_last(rdev); | 696 | radeon_fence_wait_last(rdev); |
655 | 697 | ||
656 | radeon_save_bios_scratch_regs(rdev); | 698 | radeon_save_bios_scratch_regs(rdev); |
657 | 699 | ||
658 | radeon_suspend(rdev); | 700 | radeon_suspend(rdev); |
701 | radeon_hpd_fini(rdev); | ||
659 | /* evict remaining vram memory */ | 702 | /* evict remaining vram memory */ |
660 | radeon_object_evict_vram(rdev); | 703 | radeon_bo_evict_vram(rdev); |
661 | 704 | ||
662 | pci_save_state(dev->pdev); | 705 | pci_save_state(dev->pdev); |
663 | if (state.event == PM_EVENT_SUSPEND) { | 706 | if (state.event == PM_EVENT_SUSPEND) { |
@@ -683,11 +726,15 @@ int radeon_resume_kms(struct drm_device *dev) | |||
683 | return -1; | 726 | return -1; |
684 | } | 727 | } |
685 | pci_set_master(dev->pdev); | 728 | pci_set_master(dev->pdev); |
729 | /* resume AGP if in use */ | ||
730 | radeon_agp_resume(rdev); | ||
686 | radeon_resume(rdev); | 731 | radeon_resume(rdev); |
687 | radeon_restore_bios_scratch_regs(rdev); | 732 | radeon_restore_bios_scratch_regs(rdev); |
688 | fb_set_suspend(rdev->fbdev_info, 0); | 733 | fb_set_suspend(rdev->fbdev_info, 0); |
689 | release_console_sem(); | 734 | release_console_sem(); |
690 | 735 | ||
736 | /* reset hpd state */ | ||
737 | radeon_hpd_init(rdev); | ||
691 | /* blat the mode back in */ | 738 | /* blat the mode back in */ |
692 | drm_helper_resume_force_mode(dev); | 739 | drm_helper_resume_force_mode(dev); |
693 | return 0; | 740 | return 0; |