@@ -1246,6 +1246,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;
};
@@ -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);
@@ -699,7 +699,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;
@@ -769,8 +770,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;
@@ -1223,6 +1232,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)
@@ -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,