drm/radeon/dpm: adjust power state properly for UVD on SI
There are some hardware issue with reclocking on SI when UVD is active, so use a stable power state when UVD is active. Fixes possible hangs and performance issues when using UVD on SI. Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
@@ -2903,7 +2903,8 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
|
|||||||
{
|
{
|
||||||
struct ni_ps *ps = ni_get_ps(rps);
|
struct ni_ps *ps = ni_get_ps(rps);
|
||||||
struct radeon_clock_and_voltage_limits *max_limits;
|
struct radeon_clock_and_voltage_limits *max_limits;
|
||||||
bool disable_mclk_switching;
|
bool disable_mclk_switching = false;
|
||||||
|
bool disable_sclk_switching = false;
|
||||||
u32 mclk, sclk;
|
u32 mclk, sclk;
|
||||||
u16 vddc, vddci;
|
u16 vddc, vddci;
|
||||||
int i;
|
int i;
|
||||||
@@ -2911,8 +2912,11 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
|
|||||||
if ((rdev->pm.dpm.new_active_crtc_count > 1) ||
|
if ((rdev->pm.dpm.new_active_crtc_count > 1) ||
|
||||||
ni_dpm_vblank_too_short(rdev))
|
ni_dpm_vblank_too_short(rdev))
|
||||||
disable_mclk_switching = true;
|
disable_mclk_switching = true;
|
||||||
else
|
|
||||||
disable_mclk_switching = false;
|
if (rps->vclk || rps->dclk) {
|
||||||
|
disable_mclk_switching = true;
|
||||||
|
disable_sclk_switching = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (rdev->pm.dpm.ac_power)
|
if (rdev->pm.dpm.ac_power)
|
||||||
max_limits = &rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
|
max_limits = &rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
|
||||||
@@ -2940,27 +2944,43 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
|
|||||||
|
|
||||||
if (disable_mclk_switching) {
|
if (disable_mclk_switching) {
|
||||||
mclk = ps->performance_levels[ps->performance_level_count - 1].mclk;
|
mclk = ps->performance_levels[ps->performance_level_count - 1].mclk;
|
||||||
sclk = ps->performance_levels[0].sclk;
|
|
||||||
vddc = ps->performance_levels[0].vddc;
|
|
||||||
vddci = ps->performance_levels[ps->performance_level_count - 1].vddci;
|
vddci = ps->performance_levels[ps->performance_level_count - 1].vddci;
|
||||||
} else {
|
} else {
|
||||||
sclk = ps->performance_levels[0].sclk;
|
|
||||||
mclk = ps->performance_levels[0].mclk;
|
mclk = ps->performance_levels[0].mclk;
|
||||||
vddc = ps->performance_levels[0].vddc;
|
|
||||||
vddci = ps->performance_levels[0].vddci;
|
vddci = ps->performance_levels[0].vddci;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (disable_sclk_switching) {
|
||||||
|
sclk = ps->performance_levels[ps->performance_level_count - 1].sclk;
|
||||||
|
vddc = ps->performance_levels[ps->performance_level_count - 1].vddc;
|
||||||
|
} else {
|
||||||
|
sclk = ps->performance_levels[0].sclk;
|
||||||
|
vddc = ps->performance_levels[0].vddc;
|
||||||
|
}
|
||||||
|
|
||||||
/* adjusted low state */
|
/* adjusted low state */
|
||||||
ps->performance_levels[0].sclk = sclk;
|
ps->performance_levels[0].sclk = sclk;
|
||||||
ps->performance_levels[0].mclk = mclk;
|
ps->performance_levels[0].mclk = mclk;
|
||||||
ps->performance_levels[0].vddc = vddc;
|
ps->performance_levels[0].vddc = vddc;
|
||||||
ps->performance_levels[0].vddci = vddci;
|
ps->performance_levels[0].vddci = vddci;
|
||||||
|
|
||||||
for (i = 1; i < ps->performance_level_count; i++) {
|
if (disable_sclk_switching) {
|
||||||
if (ps->performance_levels[i].sclk < ps->performance_levels[i - 1].sclk)
|
sclk = ps->performance_levels[0].sclk;
|
||||||
ps->performance_levels[i].sclk = ps->performance_levels[i - 1].sclk;
|
for (i = 1; i < ps->performance_level_count; i++) {
|
||||||
if (ps->performance_levels[i].vddc < ps->performance_levels[i - 1].vddc)
|
if (sclk < ps->performance_levels[i].sclk)
|
||||||
ps->performance_levels[i].vddc = ps->performance_levels[i - 1].vddc;
|
sclk = ps->performance_levels[i].sclk;
|
||||||
|
}
|
||||||
|
for (i = 0; i < ps->performance_level_count; i++) {
|
||||||
|
ps->performance_levels[i].sclk = sclk;
|
||||||
|
ps->performance_levels[i].vddc = vddc;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i = 1; i < ps->performance_level_count; i++) {
|
||||||
|
if (ps->performance_levels[i].sclk < ps->performance_levels[i - 1].sclk)
|
||||||
|
ps->performance_levels[i].sclk = ps->performance_levels[i - 1].sclk;
|
||||||
|
if (ps->performance_levels[i].vddc < ps->performance_levels[i - 1].vddc)
|
||||||
|
ps->performance_levels[i].vddc = ps->performance_levels[i - 1].vddc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disable_mclk_switching) {
|
if (disable_mclk_switching) {
|
||||||
|
Reference in New Issue
Block a user