diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_device.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_device.c | 87 |
1 files changed, 66 insertions, 21 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 7b629e305560..dd279da90546 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -226,20 +226,20 @@ void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) { u64 size_af, size_bf; - size_af = 0xFFFFFFFF - mc->vram_end; - size_bf = mc->vram_start; + size_af = ((0xFFFFFFFF - mc->vram_end) + mc->gtt_base_align) & ~mc->gtt_base_align; + size_bf = mc->vram_start & ~mc->gtt_base_align; if (size_bf > size_af) { if (mc->gtt_size > size_bf) { dev_warn(rdev->dev, "limiting GTT\n"); mc->gtt_size = size_bf; } - mc->gtt_start = mc->vram_start - mc->gtt_size; + mc->gtt_start = (mc->vram_start & ~mc->gtt_base_align) - mc->gtt_size; } else { if (mc->gtt_size > size_af) { dev_warn(rdev->dev, "limiting GTT\n"); mc->gtt_size = size_af; } - mc->gtt_start = mc->vram_end + 1; + mc->gtt_start = (mc->vram_end + 1 + mc->gtt_base_align) & ~mc->gtt_base_align; } mc->gtt_end = mc->gtt_start + mc->gtt_size - 1; dev_info(rdev->dev, "GTT: %lluM 0x%08llX - 0x%08llX\n", @@ -299,24 +299,24 @@ void radeon_update_bandwidth_info(struct radeon_device *rdev) sclk = radeon_get_engine_clock(rdev); mclk = rdev->clock.default_mclk; - a.full = rfixed_const(100); - rdev->pm.sclk.full = rfixed_const(sclk); - rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a); - rdev->pm.mclk.full = rfixed_const(mclk); - rdev->pm.mclk.full = rfixed_div(rdev->pm.mclk, a); + a.full = dfixed_const(100); + rdev->pm.sclk.full = dfixed_const(sclk); + rdev->pm.sclk.full = dfixed_div(rdev->pm.sclk, a); + rdev->pm.mclk.full = dfixed_const(mclk); + rdev->pm.mclk.full = dfixed_div(rdev->pm.mclk, a); - a.full = rfixed_const(16); + a.full = dfixed_const(16); /* core_bandwidth = sclk(Mhz) * 16 */ - rdev->pm.core_bandwidth.full = rfixed_div(rdev->pm.sclk, a); + rdev->pm.core_bandwidth.full = dfixed_div(rdev->pm.sclk, a); } else { sclk = radeon_get_engine_clock(rdev); mclk = radeon_get_memory_clock(rdev); - a.full = rfixed_const(100); - rdev->pm.sclk.full = rfixed_const(sclk); - rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a); - rdev->pm.mclk.full = rfixed_const(mclk); - rdev->pm.mclk.full = rfixed_div(rdev->pm.mclk, a); + a.full = dfixed_const(100); + rdev->pm.sclk.full = dfixed_const(sclk); + rdev->pm.sclk.full = dfixed_div(rdev->pm.sclk, a); + rdev->pm.mclk.full = dfixed_const(mclk); + rdev->pm.mclk.full = dfixed_div(rdev->pm.mclk, a); } } @@ -546,8 +546,10 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero /* don't suspend or resume card normally */ rdev->powered_down = false; radeon_resume_kms(dev); + drm_kms_helper_poll_enable(dev); } else { printk(KERN_INFO "radeon: switched off\n"); + drm_kms_helper_poll_disable(dev); radeon_suspend_kms(dev, pmm); /* don't suspend or resume card normally */ rdev->powered_down = true; @@ -599,9 +601,11 @@ int radeon_device_init(struct radeon_device *rdev, spin_lock_init(&rdev->ih.lock); mutex_init(&rdev->gem.mutex); mutex_init(&rdev->pm.mutex); + mutex_init(&rdev->vram_mutex); rwlock_init(&rdev->fence_drv.lock); INIT_LIST_HEAD(&rdev->gem.objects); init_waitqueue_head(&rdev->irq.vblank_queue); + init_waitqueue_head(&rdev->irq.idle_queue); /* setup workqueue */ rdev->wq = create_workqueue("radeon"); @@ -671,7 +675,7 @@ int radeon_device_init(struct radeon_device *rdev, /* Acceleration not working on AGP card try again * with fallback to PCI or PCIE GART */ - radeon_gpu_reset(rdev); + radeon_asic_reset(rdev); radeon_fini(rdev); radeon_agp_disable(rdev); r = radeon_init(rdev); @@ -691,6 +695,8 @@ void radeon_device_fini(struct radeon_device *rdev) { DRM_INFO("radeon: finishing device.\n"); rdev->shutdown = true; + /* evict vram memory */ + radeon_bo_evict_vram(rdev); radeon_fini(rdev); destroy_workqueue(rdev->wq); vga_switcheroo_unregister_client(rdev->pdev); @@ -707,6 +713,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) { struct radeon_device *rdev; struct drm_crtc *crtc; + struct drm_connector *connector; int r; if (dev == NULL || dev->dev_private == NULL) { @@ -719,6 +726,12 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) if (rdev->powered_down) return 0; + + /* turn off display hw */ + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); + } + /* unpin the front buffers */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb); @@ -728,9 +741,10 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) continue; } robj = rfb->obj->driver_private; - if (robj != rdev->fbdev_rbo) { + /* don't unpin kernel fb objects */ + if (!radeon_fbdev_robj_is_fb(rdev, robj)) { r = radeon_bo_reserve(robj, false); - if (unlikely(r == 0)) { + if (r == 0) { radeon_bo_unpin(robj); radeon_bo_unreserve(robj); } @@ -743,11 +757,14 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) radeon_save_bios_scratch_regs(rdev); + radeon_pm_suspend(rdev); radeon_suspend(rdev); radeon_hpd_fini(rdev); /* evict remaining vram memory */ radeon_bo_evict_vram(rdev); + radeon_agp_suspend(rdev); + pci_save_state(dev->pdev); if (state.event == PM_EVENT_SUSPEND) { /* Shut down the device */ @@ -755,13 +772,14 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) pci_set_power_state(dev->pdev, PCI_D3hot); } acquire_console_sem(); - fb_set_suspend(rdev->fbdev_info, 1); + radeon_fbdev_set_suspend(rdev, 1); release_console_sem(); return 0; } int radeon_resume_kms(struct drm_device *dev) { + struct drm_connector *connector; struct radeon_device *rdev = dev->dev_private; if (rdev->powered_down) @@ -778,8 +796,15 @@ int radeon_resume_kms(struct drm_device *dev) /* resume AGP if in use */ radeon_agp_resume(rdev); radeon_resume(rdev); + radeon_pm_resume(rdev); radeon_restore_bios_scratch_regs(rdev); - fb_set_suspend(rdev->fbdev_info, 0); + + /* turn on display hw */ + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); + } + + radeon_fbdev_set_suspend(rdev, 0); release_console_sem(); /* reset hpd state */ @@ -789,6 +814,26 @@ int radeon_resume_kms(struct drm_device *dev) return 0; } +int radeon_gpu_reset(struct radeon_device *rdev) +{ + int r; + + radeon_save_bios_scratch_regs(rdev); + radeon_suspend(rdev); + + r = radeon_asic_reset(rdev); + if (!r) { + dev_info(rdev->dev, "GPU reset succeed\n"); + radeon_resume(rdev); + radeon_restore_bios_scratch_regs(rdev); + drm_helper_resume_force_mode(rdev->ddev); + return 0; + } + /* bad news, how to tell it to userspace ? */ + dev_info(rdev->dev, "GPU reset failed\n"); + return r; +} + /* * Debugfs |