diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_dp.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 102 |
1 files changed, 83 insertions, 19 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index afec65c5ad8a..0715911cbd84 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -206,7 +206,12 @@ intel_dp_aux_ch(struct intel_output *intel_output, | |||
206 | * and would like to run at 2MHz. So, take the | 206 | * and would like to run at 2MHz. So, take the |
207 | * hrawclk value and divide by 2 and use that | 207 | * hrawclk value and divide by 2 and use that |
208 | */ | 208 | */ |
209 | aux_clock_divider = intel_hrawclk(dev) / 2; | 209 | /* IGDNG: input clock fixed at 125Mhz, so aux_bit_clk always 62 */ |
210 | if (IS_IGDNG(dev)) | ||
211 | aux_clock_divider = 62; | ||
212 | else | ||
213 | aux_clock_divider = intel_hrawclk(dev) / 2; | ||
214 | |||
210 | /* Must try at least 3 times according to DP spec */ | 215 | /* Must try at least 3 times according to DP spec */ |
211 | for (try = 0; try < 5; try++) { | 216 | for (try = 0; try < 5; try++) { |
212 | /* Load the send data into the aux channel data registers */ | 217 | /* Load the send data into the aux channel data registers */ |
@@ -493,22 +498,40 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
493 | intel_dp_compute_m_n(3, lane_count, | 498 | intel_dp_compute_m_n(3, lane_count, |
494 | mode->clock, adjusted_mode->clock, &m_n); | 499 | mode->clock, adjusted_mode->clock, &m_n); |
495 | 500 | ||
496 | if (intel_crtc->pipe == 0) { | 501 | if (IS_IGDNG(dev)) { |
497 | I915_WRITE(PIPEA_GMCH_DATA_M, | 502 | if (intel_crtc->pipe == 0) { |
498 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | | 503 | I915_WRITE(TRANSA_DATA_M1, |
499 | m_n.gmch_m); | 504 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | |
500 | I915_WRITE(PIPEA_GMCH_DATA_N, | 505 | m_n.gmch_m); |
501 | m_n.gmch_n); | 506 | I915_WRITE(TRANSA_DATA_N1, m_n.gmch_n); |
502 | I915_WRITE(PIPEA_DP_LINK_M, m_n.link_m); | 507 | I915_WRITE(TRANSA_DP_LINK_M1, m_n.link_m); |
503 | I915_WRITE(PIPEA_DP_LINK_N, m_n.link_n); | 508 | I915_WRITE(TRANSA_DP_LINK_N1, m_n.link_n); |
509 | } else { | ||
510 | I915_WRITE(TRANSB_DATA_M1, | ||
511 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | | ||
512 | m_n.gmch_m); | ||
513 | I915_WRITE(TRANSB_DATA_N1, m_n.gmch_n); | ||
514 | I915_WRITE(TRANSB_DP_LINK_M1, m_n.link_m); | ||
515 | I915_WRITE(TRANSB_DP_LINK_N1, m_n.link_n); | ||
516 | } | ||
504 | } else { | 517 | } else { |
505 | I915_WRITE(PIPEB_GMCH_DATA_M, | 518 | if (intel_crtc->pipe == 0) { |
506 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | | 519 | I915_WRITE(PIPEA_GMCH_DATA_M, |
507 | m_n.gmch_m); | 520 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | |
508 | I915_WRITE(PIPEB_GMCH_DATA_N, | 521 | m_n.gmch_m); |
509 | m_n.gmch_n); | 522 | I915_WRITE(PIPEA_GMCH_DATA_N, |
510 | I915_WRITE(PIPEB_DP_LINK_M, m_n.link_m); | 523 | m_n.gmch_n); |
511 | I915_WRITE(PIPEB_DP_LINK_N, m_n.link_n); | 524 | I915_WRITE(PIPEA_DP_LINK_M, m_n.link_m); |
525 | I915_WRITE(PIPEA_DP_LINK_N, m_n.link_n); | ||
526 | } else { | ||
527 | I915_WRITE(PIPEB_GMCH_DATA_M, | ||
528 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | | ||
529 | m_n.gmch_m); | ||
530 | I915_WRITE(PIPEB_GMCH_DATA_N, | ||
531 | m_n.gmch_n); | ||
532 | I915_WRITE(PIPEB_DP_LINK_M, m_n.link_m); | ||
533 | I915_WRITE(PIPEB_DP_LINK_N, m_n.link_n); | ||
534 | } | ||
512 | } | 535 | } |
513 | } | 536 | } |
514 | 537 | ||
@@ -935,6 +958,12 @@ intel_dp_link_down(struct intel_output *intel_output, uint32_t DP) | |||
935 | struct drm_i915_private *dev_priv = dev->dev_private; | 958 | struct drm_i915_private *dev_priv = dev->dev_private; |
936 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | 959 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; |
937 | 960 | ||
961 | DP &= ~DP_LINK_TRAIN_MASK; | ||
962 | I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE); | ||
963 | POSTING_READ(dp_priv->output_reg); | ||
964 | |||
965 | udelay(17000); | ||
966 | |||
938 | I915_WRITE(dp_priv->output_reg, DP & ~DP_PORT_EN); | 967 | I915_WRITE(dp_priv->output_reg, DP & ~DP_PORT_EN); |
939 | POSTING_READ(dp_priv->output_reg); | 968 | POSTING_READ(dp_priv->output_reg); |
940 | } | 969 | } |
@@ -978,6 +1007,24 @@ intel_dp_check_link_status(struct intel_output *intel_output) | |||
978 | intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration); | 1007 | intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration); |
979 | } | 1008 | } |
980 | 1009 | ||
1010 | static enum drm_connector_status | ||
1011 | igdng_dp_detect(struct drm_connector *connector) | ||
1012 | { | ||
1013 | struct intel_output *intel_output = to_intel_output(connector); | ||
1014 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
1015 | enum drm_connector_status status; | ||
1016 | |||
1017 | status = connector_status_disconnected; | ||
1018 | if (intel_dp_aux_native_read(intel_output, | ||
1019 | 0x000, dp_priv->dpcd, | ||
1020 | sizeof (dp_priv->dpcd)) == sizeof (dp_priv->dpcd)) | ||
1021 | { | ||
1022 | if (dp_priv->dpcd[0] != 0) | ||
1023 | status = connector_status_connected; | ||
1024 | } | ||
1025 | return status; | ||
1026 | } | ||
1027 | |||
981 | /** | 1028 | /** |
982 | * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection. | 1029 | * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection. |
983 | * | 1030 | * |
@@ -996,6 +1043,9 @@ intel_dp_detect(struct drm_connector *connector) | |||
996 | 1043 | ||
997 | dp_priv->has_audio = false; | 1044 | dp_priv->has_audio = false; |
998 | 1045 | ||
1046 | if (IS_IGDNG(dev)) | ||
1047 | return igdng_dp_detect(connector); | ||
1048 | |||
999 | temp = I915_READ(PORT_HOTPLUG_EN); | 1049 | temp = I915_READ(PORT_HOTPLUG_EN); |
1000 | 1050 | ||
1001 | I915_WRITE(PORT_HOTPLUG_EN, | 1051 | I915_WRITE(PORT_HOTPLUG_EN, |
@@ -1106,6 +1156,7 @@ intel_dp_init(struct drm_device *dev, int output_reg) | |||
1106 | struct drm_connector *connector; | 1156 | struct drm_connector *connector; |
1107 | struct intel_output *intel_output; | 1157 | struct intel_output *intel_output; |
1108 | struct intel_dp_priv *dp_priv; | 1158 | struct intel_dp_priv *dp_priv; |
1159 | const char *name = NULL; | ||
1109 | 1160 | ||
1110 | intel_output = kcalloc(sizeof(struct intel_output) + | 1161 | intel_output = kcalloc(sizeof(struct intel_output) + |
1111 | sizeof(struct intel_dp_priv), 1, GFP_KERNEL); | 1162 | sizeof(struct intel_dp_priv), 1, GFP_KERNEL); |
@@ -1139,9 +1190,22 @@ intel_dp_init(struct drm_device *dev, int output_reg) | |||
1139 | drm_sysfs_connector_add(connector); | 1190 | drm_sysfs_connector_add(connector); |
1140 | 1191 | ||
1141 | /* Set up the DDC bus. */ | 1192 | /* Set up the DDC bus. */ |
1142 | intel_dp_i2c_init(intel_output, | 1193 | switch (output_reg) { |
1143 | (output_reg == DP_B) ? "DPDDC-B" : | 1194 | case DP_B: |
1144 | (output_reg == DP_C) ? "DPDDC-C" : "DPDDC-D"); | 1195 | case PCH_DP_B: |
1196 | name = "DPDDC-B"; | ||
1197 | break; | ||
1198 | case DP_C: | ||
1199 | case PCH_DP_C: | ||
1200 | name = "DPDDC-C"; | ||
1201 | break; | ||
1202 | case DP_D: | ||
1203 | case PCH_DP_D: | ||
1204 | name = "DPDDC-D"; | ||
1205 | break; | ||
1206 | } | ||
1207 | |||
1208 | intel_dp_i2c_init(intel_output, name); | ||
1145 | intel_output->ddc_bus = &dp_priv->adapter; | 1209 | intel_output->ddc_bus = &dp_priv->adapter; |
1146 | intel_output->hot_plug = intel_dp_hot_plug; | 1210 | intel_output->hot_plug = intel_dp_hot_plug; |
1147 | 1211 | ||