diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/si_dpm.c')
-rw-r--r-- | drivers/gpu/drm/radeon/si_dpm.c | 110 |
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); | |||
1740 | struct ni_ps *ni_get_ps(struct radeon_ps *rps); | 1740 | struct ni_ps *ni_get_ps(struct radeon_ps *rps); |
1741 | 1741 | ||
1742 | extern int si_mc_load_microcode(struct radeon_device *rdev); | 1742 | extern int si_mc_load_microcode(struct radeon_device *rdev); |
1743 | extern void vce_v1_0_enable_mgcg(struct radeon_device *rdev, bool enable); | ||
1743 | 1744 | ||
1744 | static int si_populate_voltage_value(struct radeon_device *rdev, | 1745 | static 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 | ||
2933 | static 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 | |||
2951 | static 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 | |||
2931 | static void si_apply_state_adjust_rules(struct radeon_device *rdev, | 2983 | static 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 | ||
5932 | static 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 | |||
5862 | void si_dpm_setup_asic(struct radeon_device *rdev) | 5947 | void 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 | ||