aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/si_dpm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/radeon/si_dpm.c')
-rw-r--r--drivers/gpu/drm/radeon/si_dpm.c110
1 files changed, 106 insertions, 4 deletions
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c
index ff8b83f5e929..787cd8fd897f 100644
--- a/drivers/gpu/drm/radeon/si_dpm.c
+++ b/drivers/gpu/drm/radeon/si_dpm.c
@@ -1740,6 +1740,7 @@ struct ni_power_info *ni_get_pi(struct radeon_device *rdev);
1740struct ni_ps *ni_get_ps(struct radeon_ps *rps); 1740struct ni_ps *ni_get_ps(struct radeon_ps *rps);
1741 1741
1742extern int si_mc_load_microcode(struct radeon_device *rdev); 1742extern int si_mc_load_microcode(struct radeon_device *rdev);
1743extern void vce_v1_0_enable_mgcg(struct radeon_device *rdev, bool enable);
1743 1744
1744static int si_populate_voltage_value(struct radeon_device *rdev, 1745static int si_populate_voltage_value(struct radeon_device *rdev,
1745 const struct atom_voltage_table *table, 1746 const struct atom_voltage_table *table,
@@ -2925,9 +2926,60 @@ static struct si_dpm_quirk si_dpm_quirk_list[] = {
2925 /* PITCAIRN - https://bugs.freedesktop.org/show_bug.cgi?id=76490 */ 2926 /* PITCAIRN - https://bugs.freedesktop.org/show_bug.cgi?id=76490 */
2926 { PCI_VENDOR_ID_ATI, 0x6810, 0x1462, 0x3036, 0, 120000 }, 2927 { PCI_VENDOR_ID_ATI, 0x6810, 0x1462, 0x3036, 0, 120000 },
2927 { PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0xe271, 0, 120000 }, 2928 { PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0xe271, 0, 120000 },
2929 { PCI_VENDOR_ID_ATI, 0x6810, 0x174b, 0xe271, 85000, 90000 },
2928 { 0, 0, 0, 0 }, 2930 { 0, 0, 0, 0 },
2929}; 2931};
2930 2932
2933static u16 si_get_lower_of_leakage_and_vce_voltage(struct radeon_device *rdev,
2934 u16 vce_voltage)
2935{
2936 u16 highest_leakage = 0;
2937 struct si_power_info *si_pi = si_get_pi(rdev);
2938 int i;
2939
2940 for (i = 0; i < si_pi->leakage_voltage.count; i++){
2941 if (highest_leakage < si_pi->leakage_voltage.entries[i].voltage)
2942 highest_leakage = si_pi->leakage_voltage.entries[i].voltage;
2943 }
2944
2945 if (si_pi->leakage_voltage.count && (highest_leakage < vce_voltage))
2946 return highest_leakage;
2947
2948 return vce_voltage;
2949}
2950
2951static int si_get_vce_clock_voltage(struct radeon_device *rdev,
2952 u32 evclk, u32 ecclk, u16 *voltage)
2953{
2954 u32 i;
2955 int ret = -EINVAL;
2956 struct radeon_vce_clock_voltage_dependency_table *table =
2957 &rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
2958
2959 if (((evclk == 0) && (ecclk == 0)) ||
2960 (table && (table->count == 0))) {
2961 *voltage = 0;
2962 return 0;
2963 }
2964
2965 for (i = 0; i < table->count; i++) {
2966 if ((evclk <= table->entries[i].evclk) &&
2967 (ecclk <= table->entries[i].ecclk)) {
2968 *voltage = table->entries[i].v;
2969 ret = 0;
2970 break;
2971 }
2972 }
2973
2974 /* if no match return the highest voltage */
2975 if (ret)
2976 *voltage = table->entries[table->count - 1].v;
2977
2978 *voltage = si_get_lower_of_leakage_and_vce_voltage(rdev, *voltage);
2979
2980 return ret;
2981}
2982
2931static void si_apply_state_adjust_rules(struct radeon_device *rdev, 2983static void si_apply_state_adjust_rules(struct radeon_device *rdev,
2932 struct radeon_ps *rps) 2984 struct radeon_ps *rps)
2933{ 2985{
@@ -2936,7 +2988,7 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
2936 bool disable_mclk_switching = false; 2988 bool disable_mclk_switching = false;
2937 bool disable_sclk_switching = false; 2989 bool disable_sclk_switching = false;
2938 u32 mclk, sclk; 2990 u32 mclk, sclk;
2939 u16 vddc, vddci; 2991 u16 vddc, vddci, min_vce_voltage = 0;
2940 u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc; 2992 u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc;
2941 u32 max_sclk = 0, max_mclk = 0; 2993 u32 max_sclk = 0, max_mclk = 0;
2942 int i; 2994 int i;
@@ -2955,6 +3007,16 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
2955 ++p; 3007 ++p;
2956 } 3008 }
2957 3009
3010 if (rps->vce_active) {
3011 rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk;
3012 rps->ecclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].ecclk;
3013 si_get_vce_clock_voltage(rdev, rps->evclk, rps->ecclk,
3014 &min_vce_voltage);
3015 } else {
3016 rps->evclk = 0;
3017 rps->ecclk = 0;
3018 }
3019
2958 if ((rdev->pm.dpm.new_active_crtc_count > 1) || 3020 if ((rdev->pm.dpm.new_active_crtc_count > 1) ||
2959 ni_dpm_vblank_too_short(rdev)) 3021 ni_dpm_vblank_too_short(rdev))
2960 disable_mclk_switching = true; 3022 disable_mclk_switching = true;
@@ -3035,6 +3097,13 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
3035 vddc = ps->performance_levels[0].vddc; 3097 vddc = ps->performance_levels[0].vddc;
3036 } 3098 }
3037 3099
3100 if (rps->vce_active) {
3101 if (sclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk)
3102 sclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk;
3103 if (mclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].mclk)
3104 mclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].mclk;
3105 }
3106
3038 /* adjusted low state */ 3107 /* adjusted low state */
3039 ps->performance_levels[0].sclk = sclk; 3108 ps->performance_levels[0].sclk = sclk;
3040 ps->performance_levels[0].mclk = mclk; 3109 ps->performance_levels[0].mclk = mclk;
@@ -3084,6 +3153,8 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
3084 &ps->performance_levels[i]); 3153 &ps->performance_levels[i]);
3085 3154
3086 for (i = 0; i < ps->performance_level_count; i++) { 3155 for (i = 0; i < ps->performance_level_count; i++) {
3156 if (ps->performance_levels[i].vddc < min_vce_voltage)
3157 ps->performance_levels[i].vddc = min_vce_voltage;
3087 btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk, 3158 btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
3088 ps->performance_levels[i].sclk, 3159 ps->performance_levels[i].sclk,
3089 max_limits->vddc, &ps->performance_levels[i].vddc); 3160 max_limits->vddc, &ps->performance_levels[i].vddc);
@@ -3110,7 +3181,6 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
3110 if (ps->performance_levels[i].vddc > rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc) 3181 if (ps->performance_levels[i].vddc > rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc)
3111 ps->dc_compatible = false; 3182 ps->dc_compatible = false;
3112 } 3183 }
3113
3114} 3184}
3115 3185
3116#if 0 3186#if 0
@@ -5859,6 +5929,21 @@ static void si_set_pcie_lane_width_in_smc(struct radeon_device *rdev,
5859 } 5929 }
5860} 5930}
5861 5931
5932static void si_set_vce_clock(struct radeon_device *rdev,
5933 struct radeon_ps *new_rps,
5934 struct radeon_ps *old_rps)
5935{
5936 if ((old_rps->evclk != new_rps->evclk) ||
5937 (old_rps->ecclk != new_rps->ecclk)) {
5938 /* turn the clocks on when encoding, off otherwise */
5939 if (new_rps->evclk || new_rps->ecclk)
5940 vce_v1_0_enable_mgcg(rdev, false);
5941 else
5942 vce_v1_0_enable_mgcg(rdev, true);
5943 radeon_set_vce_clocks(rdev, new_rps->evclk, new_rps->ecclk);
5944 }
5945}
5946
5862void si_dpm_setup_asic(struct radeon_device *rdev) 5947void si_dpm_setup_asic(struct radeon_device *rdev)
5863{ 5948{
5864 int r; 5949 int r;
@@ -6547,6 +6632,7 @@ int si_dpm_set_power_state(struct radeon_device *rdev)
6547 return ret; 6632 return ret;
6548 } 6633 }
6549 ni_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps); 6634 ni_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
6635 si_set_vce_clock(rdev, new_ps, old_ps);
6550 if (eg_pi->pcie_performance_request) 6636 if (eg_pi->pcie_performance_request)
6551 si_notify_link_speed_change_after_state_change(rdev, new_ps, old_ps); 6637 si_notify_link_speed_change_after_state_change(rdev, new_ps, old_ps);
6552 ret = si_set_power_state_conditionally_enable_ulv(rdev, new_ps); 6638 ret = si_set_power_state_conditionally_enable_ulv(rdev, new_ps);
@@ -6793,6 +6879,21 @@ static int si_parse_power_table(struct radeon_device *rdev)
6793 power_state_offset += 2 + power_state->v2.ucNumDPMLevels; 6879 power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
6794 } 6880 }
6795 rdev->pm.dpm.num_ps = state_array->ucNumEntries; 6881 rdev->pm.dpm.num_ps = state_array->ucNumEntries;
6882
6883 /* fill in the vce power states */
6884 for (i = 0; i < RADEON_MAX_VCE_LEVELS; i++) {
6885 u32 sclk, mclk;
6886 clock_array_index = rdev->pm.dpm.vce_states[i].clk_idx;
6887 clock_info = (union pplib_clock_info *)
6888 &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
6889 sclk = le16_to_cpu(clock_info->si.usEngineClockLow);
6890 sclk |= clock_info->si.ucEngineClockHigh << 16;
6891 mclk = le16_to_cpu(clock_info->si.usMemoryClockLow);
6892 mclk |= clock_info->si.ucMemoryClockHigh << 16;
6893 rdev->pm.dpm.vce_states[i].sclk = sclk;
6894 rdev->pm.dpm.vce_states[i].mclk = mclk;
6895 }
6896
6796 return 0; 6897 return 0;
6797} 6898}
6798 6899
@@ -6837,10 +6938,11 @@ int si_dpm_init(struct radeon_device *rdev)
6837 if (ret) 6938 if (ret)
6838 return ret; 6939 return ret;
6839 6940
6840 ret = si_parse_power_table(rdev); 6941 ret = r600_parse_extended_power_table(rdev);
6841 if (ret) 6942 if (ret)
6842 return ret; 6943 return ret;
6843 ret = r600_parse_extended_power_table(rdev); 6944
6945 ret = si_parse_power_table(rdev);
6844 if (ret) 6946 if (ret)
6845 return ret; 6947 return ret;
6846 6948