|
@@ -2928,6 +2928,56 @@ static struct si_dpm_quirk si_dpm_quirk_list[] = {
|
|
{ 0, 0, 0, 0 },
|
|
{ 0, 0, 0, 0 },
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+static u16 si_get_lower_of_leakage_and_vce_voltage(struct radeon_device *rdev,
|
|
|
|
+ u16 vce_voltage)
|
|
|
|
+{
|
|
|
|
+ u16 highest_leakage = 0;
|
|
|
|
+ struct si_power_info *si_pi = si_get_pi(rdev);
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < si_pi->leakage_voltage.count; i++){
|
|
|
|
+ if (highest_leakage < si_pi->leakage_voltage.entries[i].voltage)
|
|
|
|
+ highest_leakage = si_pi->leakage_voltage.entries[i].voltage;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (si_pi->leakage_voltage.count && (highest_leakage < vce_voltage))
|
|
|
|
+ return highest_leakage;
|
|
|
|
+
|
|
|
|
+ return vce_voltage;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int si_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;
|
|
|
|
+
|
|
|
|
+ *voltage = si_get_lower_of_leakage_and_vce_voltage(rdev, *voltage);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
static void si_apply_state_adjust_rules(struct radeon_device *rdev,
|
|
static void si_apply_state_adjust_rules(struct radeon_device *rdev,
|
|
struct radeon_ps *rps)
|
|
struct radeon_ps *rps)
|
|
{
|
|
{
|
|
@@ -2936,7 +2986,7 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
|
|
bool disable_mclk_switching = false;
|
|
bool disable_mclk_switching = false;
|
|
bool disable_sclk_switching = false;
|
|
bool disable_sclk_switching = false;
|
|
u32 mclk, sclk;
|
|
u32 mclk, sclk;
|
|
- u16 vddc, vddci;
|
|
|
|
|
|
+ u16 vddc, vddci, min_vce_voltage = 0;
|
|
u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc;
|
|
u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc;
|
|
u32 max_sclk = 0, max_mclk = 0;
|
|
u32 max_sclk = 0, max_mclk = 0;
|
|
int i;
|
|
int i;
|
|
@@ -2955,6 +3005,16 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
|
|
++p;
|
|
++p;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (rps->vce_active) {
|
|
|
|
+ rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk;
|
|
|
|
+ rps->ecclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].ecclk;
|
|
|
|
+ si_get_vce_clock_voltage(rdev, rps->evclk, rps->ecclk,
|
|
|
|
+ &min_vce_voltage);
|
|
|
|
+ } else {
|
|
|
|
+ rps->evclk = 0;
|
|
|
|
+ rps->ecclk = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
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;
|
|
@@ -3035,6 +3095,13 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
|
|
vddc = ps->performance_levels[0].vddc;
|
|
vddc = ps->performance_levels[0].vddc;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (rps->vce_active) {
|
|
|
|
+ if (sclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk)
|
|
|
|
+ sclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk;
|
|
|
|
+ if (mclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].mclk)
|
|
|
|
+ mclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].mclk;
|
|
|
|
+ }
|
|
|
|
+
|
|
/* 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;
|
|
@@ -3084,6 +3151,8 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
|
|
&ps->performance_levels[i]);
|
|
&ps->performance_levels[i]);
|
|
|
|
|
|
for (i = 0; i < ps->performance_level_count; i++) {
|
|
for (i = 0; i < ps->performance_level_count; i++) {
|
|
|
|
+ if (ps->performance_levels[i].vddc < min_vce_voltage)
|
|
|
|
+ ps->performance_levels[i].vddc = min_vce_voltage;
|
|
btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
|
|
btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
|
|
ps->performance_levels[i].sclk,
|
|
ps->performance_levels[i].sclk,
|
|
max_limits->vddc, &ps->performance_levels[i].vddc);
|
|
max_limits->vddc, &ps->performance_levels[i].vddc);
|
|
@@ -3110,7 +3179,6 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
|
|
if (ps->performance_levels[i].vddc > rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc)
|
|
if (ps->performance_levels[i].vddc > rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc)
|
|
ps->dc_compatible = false;
|
|
ps->dc_compatible = false;
|
|
}
|
|
}
|
|
-
|
|
|
|
}
|
|
}
|
|
|
|
|
|
#if 0
|
|
#if 0
|
|
@@ -5859,6 +5927,15 @@ static void si_set_pcie_lane_width_in_smc(struct radeon_device *rdev,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void si_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);
|
|
|
|
+}
|
|
|
|
+
|
|
void si_dpm_setup_asic(struct radeon_device *rdev)
|
|
void si_dpm_setup_asic(struct radeon_device *rdev)
|
|
{
|
|
{
|
|
int r;
|
|
int r;
|
|
@@ -6547,6 +6624,7 @@ int si_dpm_set_power_state(struct radeon_device *rdev)
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
ni_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
|
|
ni_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
|
|
|
|
+ si_set_vce_clock(rdev, new_ps, old_ps);
|
|
if (eg_pi->pcie_performance_request)
|
|
if (eg_pi->pcie_performance_request)
|
|
si_notify_link_speed_change_after_state_change(rdev, new_ps, old_ps);
|
|
si_notify_link_speed_change_after_state_change(rdev, new_ps, old_ps);
|
|
ret = si_set_power_state_conditionally_enable_ulv(rdev, new_ps);
|
|
ret = si_set_power_state_conditionally_enable_ulv(rdev, new_ps);
|
|
@@ -6793,6 +6871,21 @@ static int si_parse_power_table(struct radeon_device *rdev)
|
|
power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
|
|
power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
|
|
}
|
|
}
|
|
rdev->pm.dpm.num_ps = state_array->ucNumEntries;
|
|
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, mclk;
|
|
|
|
+ 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->si.usEngineClockLow);
|
|
|
|
+ sclk |= clock_info->si.ucEngineClockHigh << 16;
|
|
|
|
+ mclk = le16_to_cpu(clock_info->si.usMemoryClockLow);
|
|
|
|
+ mclk |= clock_info->si.ucMemoryClockHigh << 16;
|
|
|
|
+ rdev->pm.dpm.vce_states[i].sclk = sclk;
|
|
|
|
+ rdev->pm.dpm.vce_states[i].mclk = mclk;
|
|
|
|
+ }
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -6837,10 +6930,11 @@ int si_dpm_init(struct radeon_device *rdev)
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
- ret = si_parse_power_table(rdev);
|
|
|
|
|
|
+ ret = r600_parse_extended_power_table(rdev);
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|
|
- ret = r600_parse_extended_power_table(rdev);
|
|
|
|
|
|
+
|
|
|
|
+ ret = si_parse_power_table(rdev);
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|
|
|
|
|