aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorZhenyu Wang <zhenyuw@linux.intel.com>2010-04-07 21:43:27 -0400
committerEric Anholt <eric@anholt.net>2010-04-12 12:23:44 -0400
commite3421a189447c0b8cd0aff5c299f53b5ab7c38f6 (patch)
treed32b718e1aabcfcff03b3492f13fa7502d8bc7c3 /drivers
parent0f229062a13204120dcd23168ad008e559bb1376 (diff)
drm/i915: enable DP/eDP for Sandybridge/Cougarpoint
DP on Cougarpoint has new training pattern definitions, and new transcoder DP control register is used to determine the mapping for transcoder and DP digital output. And eDP for Sandybridge has new voltage and pre-emphasis level definitions. Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com> Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h1
-rw-r--r--drivers/gpu/drm/i915/intel_display.c41
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c131
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 6ffabab3bb6..790fef32afe 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);
1001extern void g4x_disable_fbc(struct drm_device *dev); 1001extern void g4x_disable_fbc(struct drm_device *dev);
1002 1002
1003extern void intel_detect_pch (struct drm_device *dev); 1003extern void intel_detect_pch (struct drm_device *dev);
1004extern 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 606924ef65a..1a7c7ac66ef 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 8f2dd65abac..a0e18b01612 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
623intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, 631intel_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 */
893static uint32_t
894intel_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
878static uint8_t 911static uint8_t
879intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE], 912intel_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 */
1343int
1344intel_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
1271void 1364void
1272intel_dp_init(struct drm_device *dev, int output_reg) 1365intel_dp_init(struct drm_device *dev, int output_reg)
1273{ 1366{