From 797f203f622164a322b9a0f962ce431e3f6ca48e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 1 Aug 2013 11:54:07 -0400 Subject: [PATCH] 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 --- drivers/gpu/drm/radeon/si_dpm.c | 44 ++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index 71a993f..88699e3 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -2903,7 +2903,8 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, { struct ni_ps *ps = ni_get_ps(rps); 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; u16 vddc, vddci; 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) || ni_dpm_vblank_too_short(rdev)) 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) 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) { 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; } else { - sclk = ps->performance_levels[0].sclk; mclk = ps->performance_levels[0].mclk; - vddc = ps->performance_levels[0].vddc; 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 */ ps->performance_levels[0].sclk = sclk; ps->performance_levels[0].mclk = mclk; ps->performance_levels[0].vddc = vddc; ps->performance_levels[0].vddci = vddci; - 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_sclk_switching) { + sclk = ps->performance_levels[0].sclk; + for (i = 1; i < ps->performance_level_count; i++) { + if (sclk < ps->performance_levels[i].sclk) + 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) { -- 2.7.4