diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 41 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 131 |
3 files changed, 154 insertions, 19 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6ffabab3bb60..790fef32afef 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -1001,6 +1001,7 @@ extern void i8xx_disable_fbc(struct drm_device *dev); | |||
1001 | extern void g4x_disable_fbc(struct drm_device *dev); | 1001 | extern void g4x_disable_fbc(struct drm_device *dev); |
1002 | 1002 | ||
1003 | extern void intel_detect_pch (struct drm_device *dev); | 1003 | extern void intel_detect_pch (struct drm_device *dev); |
1004 | extern int intel_trans_dp_port_sel (struct drm_crtc *crtc); | ||
1004 | 1005 | ||
1005 | /** | 1006 | /** |
1006 | * Lock test for when it's just for synchronization of ring access. | 1007 | * Lock test for when it's just for synchronization of ring access. |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 606924ef65a6..1a7c7ac66efd 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -1893,6 +1893,39 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
1893 | /* wait one idle pattern time */ | 1893 | /* wait one idle pattern time */ |
1894 | udelay(100); | 1894 | udelay(100); |
1895 | 1895 | ||
1896 | /* For PCH DP, enable TRANS_DP_CTL */ | ||
1897 | if (HAS_PCH_CPT(dev) && | ||
1898 | intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { | ||
1899 | int trans_dp_ctl = (pipe == 0) ? TRANS_DP_CTL_A : TRANS_DP_CTL_B; | ||
1900 | int reg; | ||
1901 | |||
1902 | reg = I915_READ(trans_dp_ctl); | ||
1903 | reg &= ~TRANS_DP_PORT_SEL_MASK; | ||
1904 | reg = TRANS_DP_OUTPUT_ENABLE | | ||
1905 | TRANS_DP_ENH_FRAMING | | ||
1906 | TRANS_DP_VSYNC_ACTIVE_HIGH | | ||
1907 | TRANS_DP_HSYNC_ACTIVE_HIGH; | ||
1908 | |||
1909 | switch (intel_trans_dp_port_sel(crtc)) { | ||
1910 | case PCH_DP_B: | ||
1911 | reg |= TRANS_DP_PORT_SEL_B; | ||
1912 | break; | ||
1913 | case PCH_DP_C: | ||
1914 | reg |= TRANS_DP_PORT_SEL_C; | ||
1915 | break; | ||
1916 | case PCH_DP_D: | ||
1917 | reg |= TRANS_DP_PORT_SEL_D; | ||
1918 | break; | ||
1919 | default: | ||
1920 | DRM_DEBUG_KMS("Wrong PCH DP port return. Guess port B\n"); | ||
1921 | reg |= TRANS_DP_PORT_SEL_B; | ||
1922 | break; | ||
1923 | } | ||
1924 | |||
1925 | I915_WRITE(trans_dp_ctl, reg); | ||
1926 | POSTING_READ(trans_dp_ctl); | ||
1927 | } | ||
1928 | |||
1896 | /* enable PCH transcoder */ | 1929 | /* enable PCH transcoder */ |
1897 | temp = I915_READ(transconf_reg); | 1930 | temp = I915_READ(transconf_reg); |
1898 | /* | 1931 | /* |
@@ -2030,6 +2063,14 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
2030 | udelay(100); | 2063 | udelay(100); |
2031 | 2064 | ||
2032 | if (HAS_PCH_CPT(dev)) { | 2065 | if (HAS_PCH_CPT(dev)) { |
2066 | /* disable TRANS_DP_CTL */ | ||
2067 | int trans_dp_ctl = (pipe == 0) ? TRANS_DP_CTL_A : TRANS_DP_CTL_B; | ||
2068 | int reg; | ||
2069 | |||
2070 | reg = I915_READ(trans_dp_ctl); | ||
2071 | reg &= ~(TRANS_DP_OUTPUT_ENABLE | TRANS_DP_PORT_SEL_MASK); | ||
2072 | I915_WRITE(trans_dp_ctl, reg); | ||
2073 | POSTING_READ(trans_dp_ctl); | ||
2033 | 2074 | ||
2034 | /* disable DPLL_SEL */ | 2075 | /* disable DPLL_SEL */ |
2035 | temp = I915_READ(PCH_DPLL_SEL); | 2076 | temp = I915_READ(PCH_DPLL_SEL); |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 8f2dd65abaca..a0e18b01612e 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -221,19 +221,27 @@ intel_dp_aux_ch(struct intel_encoder *intel_encoder, | |||
221 | uint32_t ctl; | 221 | uint32_t ctl; |
222 | uint32_t status; | 222 | uint32_t status; |
223 | uint32_t aux_clock_divider; | 223 | uint32_t aux_clock_divider; |
224 | int try; | 224 | int try, precharge; |
225 | 225 | ||
226 | /* The clock divider is based off the hrawclk, | 226 | /* The clock divider is based off the hrawclk, |
227 | * and would like to run at 2MHz. So, take the | 227 | * and would like to run at 2MHz. So, take the |
228 | * hrawclk value and divide by 2 and use that | 228 | * hrawclk value and divide by 2 and use that |
229 | */ | 229 | */ |
230 | if (IS_eDP(intel_encoder)) | 230 | if (IS_eDP(intel_encoder)) { |
231 | aux_clock_divider = 225; /* eDP input clock at 450Mhz */ | 231 | if (IS_GEN6(dev)) |
232 | else if (HAS_PCH_SPLIT(dev)) | 232 | aux_clock_divider = 200; /* SNB eDP input clock at 400Mhz */ |
233 | else | ||
234 | aux_clock_divider = 225; /* eDP input clock at 450Mhz */ | ||
235 | } else if (HAS_PCH_SPLIT(dev)) | ||
233 | aux_clock_divider = 62; /* IRL input clock fixed at 125Mhz */ | 236 | aux_clock_divider = 62; /* IRL input clock fixed at 125Mhz */ |
234 | else | 237 | else |
235 | aux_clock_divider = intel_hrawclk(dev) / 2; | 238 | aux_clock_divider = intel_hrawclk(dev) / 2; |
236 | 239 | ||
240 | if (IS_GEN6(dev)) | ||
241 | precharge = 3; | ||
242 | else | ||
243 | precharge = 5; | ||
244 | |||
237 | /* Must try at least 3 times according to DP spec */ | 245 | /* Must try at least 3 times according to DP spec */ |
238 | for (try = 0; try < 5; try++) { | 246 | for (try = 0; try < 5; try++) { |
239 | /* Load the send data into the aux channel data registers */ | 247 | /* Load the send data into the aux channel data registers */ |
@@ -246,7 +254,7 @@ intel_dp_aux_ch(struct intel_encoder *intel_encoder, | |||
246 | ctl = (DP_AUX_CH_CTL_SEND_BUSY | | 254 | ctl = (DP_AUX_CH_CTL_SEND_BUSY | |
247 | DP_AUX_CH_CTL_TIME_OUT_400us | | 255 | DP_AUX_CH_CTL_TIME_OUT_400us | |
248 | (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | | 256 | (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | |
249 | (5 << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | | 257 | (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | |
250 | (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) | | 258 | (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) | |
251 | DP_AUX_CH_CTL_DONE | | 259 | DP_AUX_CH_CTL_DONE | |
252 | DP_AUX_CH_CTL_TIME_OUT_ERROR | | 260 | DP_AUX_CH_CTL_TIME_OUT_ERROR | |
@@ -623,17 +631,22 @@ static void | |||
623 | intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | 631 | intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, |
624 | struct drm_display_mode *adjusted_mode) | 632 | struct drm_display_mode *adjusted_mode) |
625 | { | 633 | { |
634 | struct drm_device *dev = encoder->dev; | ||
626 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | 635 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); |
627 | struct intel_dp_priv *dp_priv = intel_encoder->dev_priv; | 636 | struct intel_dp_priv *dp_priv = intel_encoder->dev_priv; |
628 | struct drm_crtc *crtc = intel_encoder->enc.crtc; | 637 | struct drm_crtc *crtc = intel_encoder->enc.crtc; |
629 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 638 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
630 | 639 | ||
631 | dp_priv->DP = (DP_LINK_TRAIN_OFF | | 640 | dp_priv->DP = (DP_VOLTAGE_0_4 | |
632 | DP_VOLTAGE_0_4 | | ||
633 | DP_PRE_EMPHASIS_0 | | 641 | DP_PRE_EMPHASIS_0 | |
634 | DP_SYNC_VS_HIGH | | 642 | DP_SYNC_VS_HIGH | |
635 | DP_SYNC_HS_HIGH); | 643 | DP_SYNC_HS_HIGH); |
636 | 644 | ||
645 | if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder)) | ||
646 | dp_priv->DP |= DP_LINK_TRAIN_OFF_CPT; | ||
647 | else | ||
648 | dp_priv->DP |= DP_LINK_TRAIN_OFF; | ||
649 | |||
637 | switch (dp_priv->lane_count) { | 650 | switch (dp_priv->lane_count) { |
638 | case 1: | 651 | case 1: |
639 | dp_priv->DP |= DP_PORT_WIDTH_1; | 652 | dp_priv->DP |= DP_PORT_WIDTH_1; |
@@ -661,7 +674,8 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
661 | dp_priv->DP |= DP_ENHANCED_FRAMING; | 674 | dp_priv->DP |= DP_ENHANCED_FRAMING; |
662 | } | 675 | } |
663 | 676 | ||
664 | if (intel_crtc->pipe == 1) | 677 | /* CPT DP's pipe select is decided in TRANS_DP_CTL */ |
678 | if (intel_crtc->pipe == 1 && !HAS_PCH_CPT(dev)) | ||
665 | dp_priv->DP |= DP_PIPEB_SELECT; | 679 | dp_priv->DP |= DP_PIPEB_SELECT; |
666 | 680 | ||
667 | if (IS_eDP(intel_encoder)) { | 681 | if (IS_eDP(intel_encoder)) { |
@@ -875,6 +889,25 @@ intel_dp_signal_levels(uint8_t train_set, int lane_count) | |||
875 | return signal_levels; | 889 | return signal_levels; |
876 | } | 890 | } |
877 | 891 | ||
892 | /* Gen6's DP voltage swing and pre-emphasis control */ | ||
893 | static uint32_t | ||
894 | intel_gen6_edp_signal_levels(uint8_t train_set) | ||
895 | { | ||
896 | switch (train_set & (DP_TRAIN_VOLTAGE_SWING_MASK|DP_TRAIN_PRE_EMPHASIS_MASK)) { | ||
897 | case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0: | ||
898 | return EDP_LINK_TRAIN_400MV_0DB_SNB_B; | ||
899 | case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6: | ||
900 | return EDP_LINK_TRAIN_400MV_6DB_SNB_B; | ||
901 | case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5: | ||
902 | return EDP_LINK_TRAIN_600MV_3_5DB_SNB_B; | ||
903 | case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0: | ||
904 | return EDP_LINK_TRAIN_800MV_0DB_SNB_B; | ||
905 | default: | ||
906 | DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level\n"); | ||
907 | return EDP_LINK_TRAIN_400MV_0DB_SNB_B; | ||
908 | } | ||
909 | } | ||
910 | |||
878 | static uint8_t | 911 | static uint8_t |
879 | intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE], | 912 | intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE], |
880 | int lane) | 913 | int lane) |
@@ -968,23 +1001,38 @@ intel_dp_link_train(struct intel_encoder *intel_encoder, uint32_t DP, | |||
968 | bool channel_eq = false; | 1001 | bool channel_eq = false; |
969 | bool first = true; | 1002 | bool first = true; |
970 | int tries; | 1003 | int tries; |
1004 | u32 reg; | ||
971 | 1005 | ||
972 | /* Write the link configuration data */ | 1006 | /* Write the link configuration data */ |
973 | intel_dp_aux_native_write(intel_encoder, 0x100, | 1007 | intel_dp_aux_native_write(intel_encoder, 0x100, |
974 | link_configuration, DP_LINK_CONFIGURATION_SIZE); | 1008 | link_configuration, DP_LINK_CONFIGURATION_SIZE); |
975 | 1009 | ||
976 | DP |= DP_PORT_EN; | 1010 | DP |= DP_PORT_EN; |
977 | DP &= ~DP_LINK_TRAIN_MASK; | 1011 | if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder)) |
1012 | DP &= ~DP_LINK_TRAIN_MASK_CPT; | ||
1013 | else | ||
1014 | DP &= ~DP_LINK_TRAIN_MASK; | ||
978 | memset(train_set, 0, 4); | 1015 | memset(train_set, 0, 4); |
979 | voltage = 0xff; | 1016 | voltage = 0xff; |
980 | tries = 0; | 1017 | tries = 0; |
981 | clock_recovery = false; | 1018 | clock_recovery = false; |
982 | for (;;) { | 1019 | for (;;) { |
983 | /* Use train_set[0] to set the voltage and pre emphasis values */ | 1020 | /* Use train_set[0] to set the voltage and pre emphasis values */ |
984 | uint32_t signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count); | 1021 | uint32_t signal_levels; |
985 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; | 1022 | if (IS_GEN6(dev) && IS_eDP(intel_encoder)) { |
1023 | signal_levels = intel_gen6_edp_signal_levels(train_set[0]); | ||
1024 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; | ||
1025 | } else { | ||
1026 | signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count); | ||
1027 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; | ||
1028 | } | ||
986 | 1029 | ||
987 | if (!intel_dp_set_link_train(intel_encoder, DP | DP_LINK_TRAIN_PAT_1, | 1030 | if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder)) |
1031 | reg = DP | DP_LINK_TRAIN_PAT_1_CPT; | ||
1032 | else | ||
1033 | reg = DP | DP_LINK_TRAIN_PAT_1; | ||
1034 | |||
1035 | if (!intel_dp_set_link_train(intel_encoder, reg, | ||
988 | DP_TRAINING_PATTERN_1, train_set, first)) | 1036 | DP_TRAINING_PATTERN_1, train_set, first)) |
989 | break; | 1037 | break; |
990 | first = false; | 1038 | first = false; |
@@ -1024,11 +1072,23 @@ intel_dp_link_train(struct intel_encoder *intel_encoder, uint32_t DP, | |||
1024 | channel_eq = false; | 1072 | channel_eq = false; |
1025 | for (;;) { | 1073 | for (;;) { |
1026 | /* Use train_set[0] to set the voltage and pre emphasis values */ | 1074 | /* Use train_set[0] to set the voltage and pre emphasis values */ |
1027 | uint32_t signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count); | 1075 | uint32_t signal_levels; |
1028 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; | 1076 | |
1077 | if (IS_GEN6(dev) && IS_eDP(intel_encoder)) { | ||
1078 | signal_levels = intel_gen6_edp_signal_levels(train_set[0]); | ||
1079 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; | ||
1080 | } else { | ||
1081 | signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count); | ||
1082 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; | ||
1083 | } | ||
1084 | |||
1085 | if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder)) | ||
1086 | reg = DP | DP_LINK_TRAIN_PAT_2_CPT; | ||
1087 | else | ||
1088 | reg = DP | DP_LINK_TRAIN_PAT_2; | ||
1029 | 1089 | ||
1030 | /* channel eq pattern */ | 1090 | /* channel eq pattern */ |
1031 | if (!intel_dp_set_link_train(intel_encoder, DP | DP_LINK_TRAIN_PAT_2, | 1091 | if (!intel_dp_set_link_train(intel_encoder, reg, |
1032 | DP_TRAINING_PATTERN_2, train_set, | 1092 | DP_TRAINING_PATTERN_2, train_set, |
1033 | false)) | 1093 | false)) |
1034 | break; | 1094 | break; |
@@ -1051,7 +1111,12 @@ intel_dp_link_train(struct intel_encoder *intel_encoder, uint32_t DP, | |||
1051 | ++tries; | 1111 | ++tries; |
1052 | } | 1112 | } |
1053 | 1113 | ||
1054 | I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_OFF); | 1114 | if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder)) |
1115 | reg = DP | DP_LINK_TRAIN_OFF_CPT; | ||
1116 | else | ||
1117 | reg = DP | DP_LINK_TRAIN_OFF; | ||
1118 | |||
1119 | I915_WRITE(dp_priv->output_reg, reg); | ||
1055 | POSTING_READ(dp_priv->output_reg); | 1120 | POSTING_READ(dp_priv->output_reg); |
1056 | intel_dp_aux_native_write_1(intel_encoder, | 1121 | intel_dp_aux_native_write_1(intel_encoder, |
1057 | DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE); | 1122 | DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE); |
@@ -1073,9 +1138,15 @@ intel_dp_link_down(struct intel_encoder *intel_encoder, uint32_t DP) | |||
1073 | udelay(100); | 1138 | udelay(100); |
1074 | } | 1139 | } |
1075 | 1140 | ||
1076 | DP &= ~DP_LINK_TRAIN_MASK; | 1141 | if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder)) { |
1077 | I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE); | 1142 | DP &= ~DP_LINK_TRAIN_MASK_CPT; |
1078 | POSTING_READ(dp_priv->output_reg); | 1143 | I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT); |
1144 | POSTING_READ(dp_priv->output_reg); | ||
1145 | } else { | ||
1146 | DP &= ~DP_LINK_TRAIN_MASK; | ||
1147 | I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE); | ||
1148 | POSTING_READ(dp_priv->output_reg); | ||
1149 | } | ||
1079 | 1150 | ||
1080 | udelay(17000); | 1151 | udelay(17000); |
1081 | 1152 | ||
@@ -1268,6 +1339,28 @@ intel_dp_hot_plug(struct intel_encoder *intel_encoder) | |||
1268 | intel_dp_check_link_status(intel_encoder); | 1339 | intel_dp_check_link_status(intel_encoder); |
1269 | } | 1340 | } |
1270 | 1341 | ||
1342 | /* Return which DP Port should be selected for Transcoder DP control */ | ||
1343 | int | ||
1344 | intel_trans_dp_port_sel (struct drm_crtc *crtc) | ||
1345 | { | ||
1346 | struct drm_device *dev = crtc->dev; | ||
1347 | struct drm_mode_config *mode_config = &dev->mode_config; | ||
1348 | struct drm_encoder *encoder; | ||
1349 | struct intel_encoder *intel_encoder = NULL; | ||
1350 | |||
1351 | list_for_each_entry(encoder, &mode_config->encoder_list, head) { | ||
1352 | if (!encoder || encoder->crtc != crtc) | ||
1353 | continue; | ||
1354 | |||
1355 | intel_encoder = enc_to_intel_encoder(encoder); | ||
1356 | if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) { | ||
1357 | struct intel_dp_priv *dp_priv = intel_encoder->dev_priv; | ||
1358 | return dp_priv->output_reg; | ||
1359 | } | ||
1360 | } | ||
1361 | return -1; | ||
1362 | } | ||
1363 | |||
1271 | void | 1364 | void |
1272 | intel_dp_init(struct drm_device *dev, int output_reg) | 1365 | intel_dp_init(struct drm_device *dev, int output_reg) |
1273 | { | 1366 | { |