forked from Minki/linux
drm/radeon/kms: enable UVD as needed (v9)
When using UVD, the driver must switch to a special UVD power state. In the CS ioctl, switch to the power state and schedule work to change the power state back, when the work comes up, check if uvd is still busy and if not, switch back to the user state, otherwise, reschedule the work. Note: We really need some better way to decide when to switch out of the uvd power state. Switching power states while playback is active make uvd angry. V2: fix locking. V3: switch from timer to delayed work V4: check fence driver for UVD jobs, reduce timeout to 1 second and rearm timeout on activity v5: rebase on new dpm tree v6: rebase on interim uvd on demand changes v7: fix UVD when DPM is disabled v8: unify non-DPM and DPM UVD handling v9: remove leftover idle work struct Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Christian König <deathsimple@vodafone.de>
This commit is contained in:
parent
0c4aaeae44
commit
8a227555a8
@ -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;
|
||||
};
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user