drm/radeon/dpm: add vce dpm support for TN
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
0fda42ac40
commit
11fe3d6edb
@ -985,6 +985,15 @@ static void trinity_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev
|
||||
trinity_setup_uvd_clocks(rdev, new_rps, old_rps);
|
||||
}
|
||||
|
||||
static void trinity_set_vce_clock(struct radeon_device *rdev,
|
||||
struct radeon_ps *new_rps,
|
||||
struct radeon_ps *old_rps)
|
||||
{
|
||||
if ((old_rps->evclk != new_rps->evclk) ||
|
||||
(old_rps->ecclk != new_rps->ecclk))
|
||||
radeon_set_vce_clocks(rdev, new_rps->evclk, new_rps->ecclk);
|
||||
}
|
||||
|
||||
static void trinity_program_ttt(struct radeon_device *rdev)
|
||||
{
|
||||
struct trinity_power_info *pi = trinity_get_pi(rdev);
|
||||
@ -1246,6 +1255,7 @@ int trinity_dpm_set_power_state(struct radeon_device *rdev)
|
||||
trinity_force_level_0(rdev);
|
||||
trinity_unforce_levels(rdev);
|
||||
trinity_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
|
||||
trinity_set_vce_clock(rdev, new_ps, old_ps);
|
||||
}
|
||||
trinity_release_mutex(rdev);
|
||||
|
||||
@ -1483,7 +1493,35 @@ static void trinity_adjust_uvd_state(struct radeon_device *rdev,
|
||||
}
|
||||
}
|
||||
|
||||
static int trinity_get_vce_clock_voltage(struct radeon_device *rdev,
|
||||
u32 evclk, u32 ecclk, u16 *voltage)
|
||||
{
|
||||
u32 i;
|
||||
int ret = -EINVAL;
|
||||
struct radeon_vce_clock_voltage_dependency_table *table =
|
||||
&rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
|
||||
|
||||
if (((evclk == 0) && (ecclk == 0)) ||
|
||||
(table && (table->count == 0))) {
|
||||
*voltage = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < table->count; i++) {
|
||||
if ((evclk <= table->entries[i].evclk) &&
|
||||
(ecclk <= table->entries[i].ecclk)) {
|
||||
*voltage = table->entries[i].v;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* if no match return the highest voltage */
|
||||
if (ret)
|
||||
*voltage = table->entries[table->count - 1].v;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
|
||||
struct radeon_ps *new_rps,
|
||||
@ -1496,6 +1534,7 @@ static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
|
||||
u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */
|
||||
u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
|
||||
u32 i;
|
||||
u16 min_vce_voltage;
|
||||
bool force_high;
|
||||
u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
|
||||
|
||||
@ -1504,6 +1543,14 @@ static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
|
||||
|
||||
trinity_adjust_uvd_state(rdev, new_rps);
|
||||
|
||||
if (new_rps->vce_active) {
|
||||
new_rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk;
|
||||
new_rps->ecclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].ecclk;
|
||||
} else {
|
||||
new_rps->evclk = 0;
|
||||
new_rps->ecclk = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < ps->num_levels; i++) {
|
||||
if (ps->levels[i].vddc_index < min_voltage)
|
||||
ps->levels[i].vddc_index = min_voltage;
|
||||
@ -1512,6 +1559,17 @@ static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
|
||||
ps->levels[i].sclk =
|
||||
trinity_get_valid_engine_clock(rdev, min_sclk);
|
||||
|
||||
/* patch in vce limits */
|
||||
if (new_rps->vce_active) {
|
||||
/* sclk */
|
||||
if (ps->levels[i].sclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk)
|
||||
ps->levels[i].sclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk;
|
||||
/* vddc */
|
||||
trinity_get_vce_clock_voltage(rdev, new_rps->evclk, new_rps->ecclk, &min_vce_voltage);
|
||||
if (ps->levels[i].vddc_index < min_vce_voltage)
|
||||
ps->levels[i].vddc_index = min_vce_voltage;
|
||||
}
|
||||
|
||||
ps->levels[i].ds_divider_index =
|
||||
sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr);
|
||||
|
||||
@ -1733,6 +1791,19 @@ static int trinity_parse_power_table(struct radeon_device *rdev)
|
||||
power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
|
||||
}
|
||||
rdev->pm.dpm.num_ps = state_array->ucNumEntries;
|
||||
|
||||
/* fill in the vce power states */
|
||||
for (i = 0; i < RADEON_MAX_VCE_LEVELS; i++) {
|
||||
u32 sclk;
|
||||
clock_array_index = rdev->pm.dpm.vce_states[i].clk_idx;
|
||||
clock_info = (union pplib_clock_info *)
|
||||
&clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
|
||||
sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
|
||||
sclk |= clock_info->sumo.ucEngineClockHigh << 16;
|
||||
rdev->pm.dpm.vce_states[i].sclk = sclk;
|
||||
rdev->pm.dpm.vce_states[i].mclk = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1914,6 +1985,10 @@ int trinity_dpm_init(struct radeon_device *rdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = r600_parse_extended_power_table(rdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = trinity_parse_power_table(rdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -2000,6 +2075,7 @@ void trinity_dpm_fini(struct radeon_device *rdev)
|
||||
}
|
||||
kfree(rdev->pm.dpm.ps);
|
||||
kfree(rdev->pm.dpm.priv);
|
||||
r600_free_extended_power_table(rdev);
|
||||
}
|
||||
|
||||
u32 trinity_dpm_get_sclk(struct radeon_device *rdev, bool low)
|
||||
|
Loading…
x
Reference in New Issue
Block a user