diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_pm.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_pm.c | 46 |
1 files changed, 37 insertions, 9 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index d4d1c39a0e99..a4b57493aa78 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -28,6 +28,7 @@ #define RADEON_RECLOCK_DELAY_MS 200 #define RADEON_WAIT_VBLANK_TIMEOUT 200 +static bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish); static void radeon_pm_set_clocks_locked(struct radeon_device *rdev); static void radeon_pm_set_clocks(struct radeon_device *rdev); static void radeon_pm_idle_work_handler(struct work_struct *work); @@ -179,6 +180,16 @@ static void radeon_get_power_state(struct radeon_device *rdev, rdev->pm.requested_power_state->non_clock_info.pcie_lanes); } +static inline void radeon_sync_with_vblank(struct radeon_device *rdev) +{ + if (rdev->pm.active_crtcs) { + rdev->pm.vblank_sync = false; + wait_event_timeout( + rdev->irq.vblank_queue, rdev->pm.vblank_sync, + msecs_to_jiffies(RADEON_WAIT_VBLANK_TIMEOUT)); + } +} + static void radeon_set_power_state(struct radeon_device *rdev) { /* if *_clock_mode are the same, *_power_state are as well */ @@ -189,11 +200,28 @@ static void radeon_set_power_state(struct radeon_device *rdev) rdev->pm.requested_clock_mode->sclk, rdev->pm.requested_clock_mode->mclk, rdev->pm.requested_power_state->non_clock_info.pcie_lanes); + /* set pcie lanes */ + /* TODO */ + /* set voltage */ + /* TODO */ + /* set engine clock */ + radeon_sync_with_vblank(rdev); + radeon_pm_debug_check_in_vbl(rdev, false); radeon_set_engine_clock(rdev, rdev->pm.requested_clock_mode->sclk); + radeon_pm_debug_check_in_vbl(rdev, true); + +#if 0 /* set memory clock */ + if (rdev->asic->set_memory_clock) { + radeon_sync_with_vblank(rdev); + radeon_pm_debug_check_in_vbl(rdev, false); + radeon_set_memory_clock(rdev, rdev->pm.requested_clock_mode->mclk); + radeon_pm_debug_check_in_vbl(rdev, true); + } +#endif rdev->pm.current_power_state = rdev->pm.requested_power_state; rdev->pm.current_clock_mode = rdev->pm.requested_clock_mode; @@ -229,6 +257,12 @@ int radeon_pm_init(struct radeon_device *rdev) return 0; } +void radeon_pm_fini(struct radeon_device *rdev) +{ + if (rdev->pm.i2c_bus) + radeon_i2c_destroy(rdev->pm.i2c_bus); +} + void radeon_pm_compute_clocks(struct radeon_device *rdev) { struct drm_device *ddev = rdev->ddev; @@ -245,7 +279,8 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev) list_for_each_entry(connector, &ddev->mode_config.connector_list, head) { if (connector->encoder && - connector->dpms != DRM_MODE_DPMS_OFF) { + connector->encoder->crtc && + connector->dpms != DRM_MODE_DPMS_OFF) { radeon_crtc = to_radeon_crtc(connector->encoder->crtc); rdev->pm.active_crtcs |= (1 << radeon_crtc->crtc_id); ++count; @@ -333,10 +368,7 @@ static void radeon_pm_set_clocks_locked(struct radeon_device *rdev) break; } - /* check if we are in vblank */ - radeon_pm_debug_check_in_vbl(rdev, false); radeon_set_power_state(rdev); - radeon_pm_debug_check_in_vbl(rdev, true); rdev->pm.planned_action = PM_ACTION_NONE; } @@ -353,10 +385,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev) rdev->pm.req_vblank |= (1 << 1); drm_vblank_get(rdev->ddev, 1); } - if (rdev->pm.active_crtcs) - wait_event_interruptible_timeout( - rdev->irq.vblank_queue, 0, - msecs_to_jiffies(RADEON_WAIT_VBLANK_TIMEOUT)); + radeon_pm_set_clocks_locked(rdev); if (rdev->pm.req_vblank & (1 << 0)) { rdev->pm.req_vblank &= ~(1 << 0); drm_vblank_put(rdev->ddev, 0); @@ -366,7 +395,6 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev) drm_vblank_put(rdev->ddev, 1); } - radeon_pm_set_clocks_locked(rdev); mutex_unlock(&rdev->cp.mutex); } |