diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 5d4731b66e7d..84c459d447e8 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1241,6 +1241,7 @@ struct radeon_dpm { int current_active_crtc_count; /* special states active */ bool thermal_active; + bool uvd_active; /* thermal handling */ struct radeon_dpm_thermal thermal; }; diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 7e265a58141f..4f6b22b799ba 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -550,6 +550,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) return r; } + /* XXX pick SD/HD/MVC */ if (parser.ring == R600_RING_TYPE_UVD_INDEX) radeon_uvd_note_usage(rdev); diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 2998e75423a0..a97af88a81de 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -696,7 +696,8 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev) if (rdev->pm.dpm.user_state != rdev->pm.dpm.state) { /* add other state override checks here */ - if (!rdev->pm.dpm.thermal_active) + if ((!rdev->pm.dpm.thermal_active) && + (!rdev->pm.dpm.uvd_active)) rdev->pm.dpm.state = rdev->pm.dpm.user_state; } dpm_state = rdev->pm.dpm.state; @@ -766,8 +767,16 @@ void radeon_dpm_enable_power_state(struct radeon_device *rdev, case POWER_STATE_TYPE_INTERNAL_THERMAL: rdev->pm.dpm.thermal_active = true; break; + case POWER_STATE_TYPE_INTERNAL_UVD: + case POWER_STATE_TYPE_INTERNAL_UVD_SD: + case POWER_STATE_TYPE_INTERNAL_UVD_HD: + case POWER_STATE_TYPE_INTERNAL_UVD_HD2: + case POWER_STATE_TYPE_INTERNAL_UVD_MVC: + rdev->pm.dpm.uvd_active = true; + break; default: rdev->pm.dpm.thermal_active = false; + rdev->pm.dpm.uvd_active = false; break; } rdev->pm.dpm.state = dpm_state; @@ -1220,6 +1229,7 @@ static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev) radeon_dpm_change_power_state_locked(rdev); mutex_unlock(&rdev->pm.mutex); + } void radeon_pm_compute_clocks(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index fdc77d1eaac8..ce5a10c8d338 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -699,11 +699,19 @@ static void radeon_uvd_idle_work_handler(struct work_struct *work) struct radeon_device *rdev = container_of(work, struct radeon_device, uvd.idle_work.work); - if (radeon_fence_count_emitted(rdev, R600_RING_TYPE_UVD_INDEX) == 0) - radeon_set_uvd_clocks(rdev, 0, 0); - else + if (radeon_fence_count_emitted(rdev, R600_RING_TYPE_UVD_INDEX) == 0) { + if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) { + mutex_lock(&rdev->pm.mutex); + rdev->pm.dpm.uvd_active = false; + mutex_unlock(&rdev->pm.mutex); + radeon_pm_compute_clocks(rdev); + } else { + radeon_set_uvd_clocks(rdev, 0, 0); + } + } else { schedule_delayed_work(&rdev->uvd.idle_work, msecs_to_jiffies(UVD_IDLE_TIMEOUT_MS)); + } } void radeon_uvd_note_usage(struct radeon_device *rdev) @@ -711,8 +719,14 @@ void radeon_uvd_note_usage(struct radeon_device *rdev) bool set_clocks = !cancel_delayed_work_sync(&rdev->uvd.idle_work); set_clocks &= schedule_delayed_work(&rdev->uvd.idle_work, msecs_to_jiffies(UVD_IDLE_TIMEOUT_MS)); - if (set_clocks) - radeon_set_uvd_clocks(rdev, 53300, 40000); + if (set_clocks) { + if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) { + /* XXX pick SD/HD/MVC */ + radeon_dpm_enable_power_state(rdev, POWER_STATE_TYPE_INTERNAL_UVD); + } else { + radeon_set_uvd_clocks(rdev, 53300, 40000); + } + } } static unsigned radeon_uvd_calc_upll_post_div(unsigned vco_freq,