@@ -937,6 +937,226 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc,
937
937
return true;
938
938
}
939
939
940
+ struct skl_wrpll_params {
941
+ uint32_t dco_fraction ;
942
+ uint32_t dco_integer ;
943
+ uint32_t qdiv_ratio ;
944
+ uint32_t qdiv_mode ;
945
+ uint32_t kdiv ;
946
+ uint32_t pdiv ;
947
+ uint32_t central_freq ;
948
+ };
949
+
950
+ static void
951
+ skl_ddi_calculate_wrpll (int clock /* in Hz */ ,
952
+ struct skl_wrpll_params * wrpll_params )
953
+ {
954
+ uint64_t afe_clock = clock * 5 ; /* AFE Clock is 5x Pixel clock */
955
+ uint64_t dco_central_freq [3 ] = {8400000000 , 9000000000 , 9600000000 };
956
+ uint32_t min_dco_deviation = 400 ;
957
+ uint32_t min_dco_index = 3 ;
958
+ uint32_t P0 [4 ] = {1 , 2 , 3 , 7 };
959
+ uint32_t P2 [4 ] = {1 , 2 , 3 , 5 };
960
+ bool found = false;
961
+ uint32_t candidate_p = 0 ;
962
+ uint32_t candidate_p0 [3 ] = {0 }, candidate_p1 [3 ] = {0 };
963
+ uint32_t candidate_p2 [3 ] = {0 };
964
+ uint32_t dco_central_freq_deviation [3 ];
965
+ uint32_t i , P1 , k , dco_count ;
966
+ bool retry_with_odd = false;
967
+ uint64_t dco_freq ;
968
+
969
+ /* Determine P0, P1 or P2 */
970
+ for (dco_count = 0 ; dco_count < 3 ; dco_count ++ ) {
971
+ found = false;
972
+ candidate_p =
973
+ div64_u64 (dco_central_freq [dco_count ], afe_clock );
974
+ if (retry_with_odd == false)
975
+ candidate_p = (candidate_p % 2 == 0 ?
976
+ candidate_p : candidate_p + 1 );
977
+
978
+ for (P1 = 1 ; P1 < candidate_p ; P1 ++ ) {
979
+ for (i = 0 ; i < 4 ; i ++ ) {
980
+ if (!(P0 [i ] != 1 || P1 == 1 ))
981
+ continue ;
982
+
983
+ for (k = 0 ; k < 4 ; k ++ ) {
984
+ if (P1 != 1 && P2 [k ] != 2 )
985
+ continue ;
986
+
987
+ if (candidate_p == P0 [i ] * P1 * P2 [k ]) {
988
+ /* Found possible P0, P1, P2 */
989
+ found = true;
990
+ candidate_p0 [dco_count ] = P0 [i ];
991
+ candidate_p1 [dco_count ] = P1 ;
992
+ candidate_p2 [dco_count ] = P2 [k ];
993
+ goto found ;
994
+ }
995
+
996
+ }
997
+ }
998
+ }
999
+
1000
+ found :
1001
+ if (found ) {
1002
+ dco_central_freq_deviation [dco_count ] =
1003
+ div64_u64 (10000 *
1004
+ abs_diff ((candidate_p * afe_clock ),
1005
+ dco_central_freq [dco_count ]),
1006
+ dco_central_freq [dco_count ]);
1007
+
1008
+ if (dco_central_freq_deviation [dco_count ] <
1009
+ min_dco_deviation ) {
1010
+ min_dco_deviation =
1011
+ dco_central_freq_deviation [dco_count ];
1012
+ min_dco_index = dco_count ;
1013
+ }
1014
+ }
1015
+
1016
+ if (min_dco_index > 2 && dco_count == 2 ) {
1017
+ retry_with_odd = true;
1018
+ dco_count = 0 ;
1019
+ }
1020
+ }
1021
+
1022
+ if (min_dco_index > 2 ) {
1023
+ WARN (1 , "No valid values found for the given pixel clock\n" );
1024
+ } else {
1025
+ wrpll_params -> central_freq = dco_central_freq [min_dco_index ];
1026
+
1027
+ switch (dco_central_freq [min_dco_index ]) {
1028
+ case 9600000000 :
1029
+ wrpll_params -> central_freq = 0 ;
1030
+ break ;
1031
+ case 9000000000 :
1032
+ wrpll_params -> central_freq = 1 ;
1033
+ break ;
1034
+ case 8400000000 :
1035
+ wrpll_params -> central_freq = 3 ;
1036
+ }
1037
+
1038
+ switch (candidate_p0 [min_dco_index ]) {
1039
+ case 1 :
1040
+ wrpll_params -> pdiv = 0 ;
1041
+ break ;
1042
+ case 2 :
1043
+ wrpll_params -> pdiv = 1 ;
1044
+ break ;
1045
+ case 3 :
1046
+ wrpll_params -> pdiv = 2 ;
1047
+ break ;
1048
+ case 7 :
1049
+ wrpll_params -> pdiv = 4 ;
1050
+ break ;
1051
+ default :
1052
+ WARN (1 , "Incorrect PDiv\n" );
1053
+ }
1054
+
1055
+ switch (candidate_p2 [min_dco_index ]) {
1056
+ case 5 :
1057
+ wrpll_params -> kdiv = 0 ;
1058
+ break ;
1059
+ case 2 :
1060
+ wrpll_params -> kdiv = 1 ;
1061
+ break ;
1062
+ case 3 :
1063
+ wrpll_params -> kdiv = 2 ;
1064
+ break ;
1065
+ case 1 :
1066
+ wrpll_params -> kdiv = 3 ;
1067
+ break ;
1068
+ default :
1069
+ WARN (1 , "Incorrect KDiv\n" );
1070
+ }
1071
+
1072
+ wrpll_params -> qdiv_ratio = candidate_p1 [min_dco_index ];
1073
+ wrpll_params -> qdiv_mode =
1074
+ (wrpll_params -> qdiv_ratio == 1 ) ? 0 : 1 ;
1075
+
1076
+ dco_freq = candidate_p0 [min_dco_index ] *
1077
+ candidate_p1 [min_dco_index ] *
1078
+ candidate_p2 [min_dco_index ] * afe_clock ;
1079
+
1080
+ /*
1081
+ * Intermediate values are in Hz.
1082
+ * Divide by MHz to match bsepc
1083
+ */
1084
+ wrpll_params -> dco_integer = div_u64 (dco_freq , (24 * MHz (1 )));
1085
+ wrpll_params -> dco_fraction =
1086
+ div_u64 (((div_u64 (dco_freq , 24 ) -
1087
+ wrpll_params -> dco_integer * MHz (1 )) * 0x8000 ), MHz (1 ));
1088
+
1089
+ }
1090
+ }
1091
+
1092
+
1093
+ static bool
1094
+ skl_ddi_pll_select (struct intel_crtc * intel_crtc ,
1095
+ struct intel_encoder * intel_encoder ,
1096
+ int clock )
1097
+ {
1098
+ struct intel_shared_dpll * pll ;
1099
+ uint32_t ctrl1 , cfgcr1 , cfgcr2 ;
1100
+
1101
+ /*
1102
+ * See comment in intel_dpll_hw_state to understand why we always use 0
1103
+ * as the DPLL id in this function.
1104
+ */
1105
+
1106
+ ctrl1 = DPLL_CTRL1_OVERRIDE (0 );
1107
+
1108
+ if (intel_encoder -> type == INTEL_OUTPUT_HDMI ) {
1109
+ struct skl_wrpll_params wrpll_params = { 0 , };
1110
+
1111
+ ctrl1 |= DPLL_CTRL1_HDMI_MODE (0 );
1112
+
1113
+ skl_ddi_calculate_wrpll (clock * 1000 , & wrpll_params );
1114
+
1115
+ cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE |
1116
+ DPLL_CFGCR1_DCO_FRACTION (wrpll_params .dco_fraction ) |
1117
+ wrpll_params .dco_integer ;
1118
+
1119
+ cfgcr2 = DPLL_CFGCR2_QDIV_RATIO (wrpll_params .qdiv_ratio ) |
1120
+ DPLL_CFGCR2_QDIV_MODE (wrpll_params .qdiv_mode ) |
1121
+ DPLL_CFGCR2_KDIV (wrpll_params .kdiv ) |
1122
+ DPLL_CFGCR2_PDIV (wrpll_params .pdiv ) |
1123
+ wrpll_params .central_freq ;
1124
+ } else if (intel_encoder -> type == INTEL_OUTPUT_DISPLAYPORT ) {
1125
+ struct drm_encoder * encoder = & intel_encoder -> base ;
1126
+ struct intel_dp * intel_dp = enc_to_intel_dp (encoder );
1127
+
1128
+ switch (intel_dp -> link_bw ) {
1129
+ case DP_LINK_BW_1_62 :
1130
+ ctrl1 |= DPLL_CRTL1_LINK_RATE (DPLL_CRTL1_LINK_RATE_810 , 0 );
1131
+ break ;
1132
+ case DP_LINK_BW_2_7 :
1133
+ ctrl1 |= DPLL_CRTL1_LINK_RATE (DPLL_CRTL1_LINK_RATE_1350 , 0 );
1134
+ break ;
1135
+ case DP_LINK_BW_5_4 :
1136
+ ctrl1 |= DPLL_CRTL1_LINK_RATE (DPLL_CRTL1_LINK_RATE_2700 , 0 );
1137
+ break ;
1138
+ }
1139
+
1140
+ cfgcr1 = cfgcr2 = 0 ;
1141
+ } else /* eDP */
1142
+ return true;
1143
+
1144
+ intel_crtc -> new_config -> dpll_hw_state .ctrl1 = ctrl1 ;
1145
+ intel_crtc -> new_config -> dpll_hw_state .cfgcr1 = cfgcr1 ;
1146
+ intel_crtc -> new_config -> dpll_hw_state .cfgcr2 = cfgcr2 ;
1147
+
1148
+ pll = intel_get_shared_dpll (intel_crtc );
1149
+ if (pll == NULL ) {
1150
+ DRM_DEBUG_DRIVER ("failed to find PLL for pipe %c\n" ,
1151
+ pipe_name (intel_crtc -> pipe ));
1152
+ return false;
1153
+ }
1154
+
1155
+ /* shared DPLL id 0 is DPLL 1 */
1156
+ intel_crtc -> new_config -> ddi_pll_sel = pll -> id + 1 ;
1157
+
1158
+ return true;
1159
+ }
940
1160
941
1161
/*
942
1162
* Tries to find a *shared* PLL for the CRTC and store it in
@@ -947,11 +1167,15 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc,
947
1167
*/
948
1168
bool intel_ddi_pll_select (struct intel_crtc * intel_crtc )
949
1169
{
1170
+ struct drm_device * dev = intel_crtc -> base .dev ;
950
1171
struct intel_encoder * intel_encoder =
951
1172
intel_ddi_get_crtc_new_encoder (intel_crtc );
952
1173
int clock = intel_crtc -> new_config -> port_clock ;
953
1174
954
- return hsw_ddi_pll_select (intel_crtc , intel_encoder , clock );
1175
+ if (IS_SKYLAKE (dev ))
1176
+ return skl_ddi_pll_select (intel_crtc , intel_encoder , clock );
1177
+ else
1178
+ return hsw_ddi_pll_select (intel_crtc , intel_encoder , clock );
955
1179
}
956
1180
957
1181
void intel_ddi_set_pipe_settings (struct drm_crtc * crtc )
0 commit comments