From 4489cd62e5a2a4900422424457c6e8dca875056b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 22 Mar 2013 15:59:10 -0400 Subject: [PATCH] drm/radeon/dpm: validate voltages against dispclk requirements Validate the voltages against the voltage requirements of the dispclk. We currently don't adjust the disp clock so it never changes, but we need to filter out voltage levels that are too low none the less. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/btc_dpm.c | 28 +++++++++++++++++++++--- drivers/gpu/drm/radeon/ni_dpm.c | 21 +++++++++++++++++- drivers/gpu/drm/radeon/radeon.h | 2 ++ drivers/gpu/drm/radeon/radeon_atombios.c | 1 + 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/btc_dpm.c b/drivers/gpu/drm/radeon/btc_dpm.c index e0d315e7fd01..a55b23dce6da 100644 --- a/drivers/gpu/drm/radeon/btc_dpm.c +++ b/drivers/gpu/drm/radeon/btc_dpm.c @@ -2178,21 +2178,26 @@ static void btc_apply_state_adjust_rules(struct radeon_device *rdev, ps->low.mclk, max_limits->vddci, &ps->low.vddci); btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk, ps->low.mclk, max_limits->vddc, &ps->low.vddc); - /* XXX validate the voltage required for display */ + btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk, + rdev->clock.current_dispclk, max_limits->vddc, &ps->low.vddc); + btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk, ps->medium.sclk, max_limits->vddc, &ps->medium.vddc); btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk, ps->medium.mclk, max_limits->vddci, &ps->medium.vddci); btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk, ps->medium.mclk, max_limits->vddc, &ps->medium.vddc); - /* XXX validate the voltage required for display */ + btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk, + rdev->clock.current_dispclk, max_limits->vddc, &ps->medium.vddc); + btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk, ps->high.sclk, max_limits->vddc, &ps->high.vddc); btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk, ps->high.mclk, max_limits->vddci, &ps->high.vddci); btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk, ps->high.mclk, max_limits->vddc, &ps->high.vddc); - /* XXX validate the voltage required for display */ + btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk, + rdev->clock.current_dispclk, max_limits->vddc, &ps->high.vddc); btc_apply_voltage_delta_rules(rdev, max_limits->vddc, max_limits->vddci, &ps->low.vddc, &ps->low.vddci); @@ -2495,6 +2500,22 @@ int btc_dpm_init(struct radeon_device *rdev) if (ret) return ret; + rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries = + kzalloc(4 * sizeof(struct radeon_clock_voltage_dependency_entry), GFP_KERNEL); + if (!rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) { + r600_free_extended_power_table(rdev); + return -ENOMEM; + } + rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count = 4; + rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].clk = 0; + rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].v = 0; + rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].clk = 36000; + rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].v = 800; + rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].clk = 54000; + rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].v = 800; + rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].clk = 72000; + rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].v = 800; + if (rdev->pm.dpm.voltage_response_time == 0) rdev->pm.dpm.voltage_response_time = R600_VOLTAGERESPONSETIME_DFLT; if (rdev->pm.dpm.backbias_response_time == 0) @@ -2628,6 +2649,7 @@ void btc_dpm_fini(struct radeon_device *rdev) } kfree(rdev->pm.dpm.ps); kfree(rdev->pm.dpm.priv); + kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries); r600_free_extended_power_table(rdev); } diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c index af059655055d..21c064badaa2 100644 --- a/drivers/gpu/drm/radeon/ni_dpm.c +++ b/drivers/gpu/drm/radeon/ni_dpm.c @@ -866,7 +866,9 @@ static void ni_apply_state_adjust_rules(struct radeon_device *rdev, btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk, ps->performance_levels[i].mclk, max_limits->vddc, &ps->performance_levels[i].vddc); - /* XXX validate the voltage required for display */ + btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk, + rdev->clock.current_dispclk, + max_limits->vddc, &ps->performance_levels[i].vddc); } for (i = 0; i < ps->performance_level_count; i++) { @@ -3910,6 +3912,22 @@ int ni_dpm_init(struct radeon_device *rdev) if (ret) return ret; + rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries = + kzalloc(4 * sizeof(struct radeon_clock_voltage_dependency_entry), GFP_KERNEL); + if (!rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) { + r600_free_extended_power_table(rdev); + return -ENOMEM; + } + rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count = 4; + rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].clk = 0; + rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].v = 0; + rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].clk = 36000; + rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].v = 720; + rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].clk = 54000; + rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].v = 810; + rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].clk = 72000; + rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].v = 900; + ni_patch_dependency_tables_based_on_leakage(rdev); if (rdev->pm.dpm.voltage_response_time == 0) @@ -4094,6 +4112,7 @@ void ni_dpm_fini(struct radeon_device *rdev) } kfree(rdev->pm.dpm.ps); kfree(rdev->pm.dpm.priv); + kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries); r600_free_extended_power_table(rdev); } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index e6ded6fc186b..9de8ae20bc99 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -200,6 +200,7 @@ struct radeon_clock { uint32_t default_mclk; uint32_t default_sclk; uint32_t default_dispclk; + uint32_t current_dispclk; uint32_t dp_extclk; uint32_t max_pixel_clock; }; @@ -1298,6 +1299,7 @@ struct radeon_dpm_dynamic_state { struct radeon_clock_voltage_dependency_table vddc_dependency_on_sclk; struct radeon_clock_voltage_dependency_table vddci_dependency_on_mclk; struct radeon_clock_voltage_dependency_table vddc_dependency_on_mclk; + struct radeon_clock_voltage_dependency_table vddc_dependency_on_dispclk; struct radeon_clock_array valid_sclk_values; struct radeon_clock_array valid_mclk_values; struct radeon_clock_and_voltage_limits max_clock_voltage_on_dc; diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 0ac7294867a3..c707ed034713 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1243,6 +1243,7 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) } rdev->clock.dp_extclk = le16_to_cpu(firmware_info->info_21.usUniphyDPModeExtClkFreq); + rdev->clock.current_dispclk = rdev->clock.default_dispclk; } *dcpll = *p1pll; -- 2.34.1