diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_dp.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 79 |
1 files changed, 38 insertions, 41 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 9caccd03dccb..9ab8708ac6ba 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -239,7 +239,6 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, | |||
239 | uint32_t ch_data = ch_ctl + 4; | 239 | uint32_t ch_data = ch_ctl + 4; |
240 | int i; | 240 | int i; |
241 | int recv_bytes; | 241 | int recv_bytes; |
242 | uint32_t ctl; | ||
243 | uint32_t status; | 242 | uint32_t status; |
244 | uint32_t aux_clock_divider; | 243 | uint32_t aux_clock_divider; |
245 | int try, precharge; | 244 | int try, precharge; |
@@ -263,41 +262,43 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, | |||
263 | else | 262 | else |
264 | precharge = 5; | 263 | precharge = 5; |
265 | 264 | ||
265 | if (I915_READ(ch_ctl) & DP_AUX_CH_CTL_SEND_BUSY) { | ||
266 | DRM_ERROR("dp_aux_ch not started status 0x%08x\n", | ||
267 | I915_READ(ch_ctl)); | ||
268 | return -EBUSY; | ||
269 | } | ||
270 | |||
266 | /* Must try at least 3 times according to DP spec */ | 271 | /* Must try at least 3 times according to DP spec */ |
267 | for (try = 0; try < 5; try++) { | 272 | for (try = 0; try < 5; try++) { |
268 | /* Load the send data into the aux channel data registers */ | 273 | /* Load the send data into the aux channel data registers */ |
269 | for (i = 0; i < send_bytes; i += 4) { | 274 | for (i = 0; i < send_bytes; i += 4) |
270 | uint32_t d = pack_aux(send + i, send_bytes - i); | 275 | I915_WRITE(ch_data + i, |
271 | 276 | pack_aux(send + i, send_bytes - i)); | |
272 | I915_WRITE(ch_data + i, d); | ||
273 | } | ||
274 | |||
275 | ctl = (DP_AUX_CH_CTL_SEND_BUSY | | ||
276 | DP_AUX_CH_CTL_TIME_OUT_400us | | ||
277 | (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | | ||
278 | (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | | ||
279 | (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) | | ||
280 | DP_AUX_CH_CTL_DONE | | ||
281 | DP_AUX_CH_CTL_TIME_OUT_ERROR | | ||
282 | DP_AUX_CH_CTL_RECEIVE_ERROR); | ||
283 | 277 | ||
284 | /* Send the command and wait for it to complete */ | 278 | /* Send the command and wait for it to complete */ |
285 | I915_WRITE(ch_ctl, ctl); | 279 | I915_WRITE(ch_ctl, |
286 | (void) I915_READ(ch_ctl); | 280 | DP_AUX_CH_CTL_SEND_BUSY | |
281 | DP_AUX_CH_CTL_TIME_OUT_400us | | ||
282 | (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | | ||
283 | (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | | ||
284 | (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) | | ||
285 | DP_AUX_CH_CTL_DONE | | ||
286 | DP_AUX_CH_CTL_TIME_OUT_ERROR | | ||
287 | DP_AUX_CH_CTL_RECEIVE_ERROR); | ||
287 | for (;;) { | 288 | for (;;) { |
288 | udelay(100); | ||
289 | status = I915_READ(ch_ctl); | 289 | status = I915_READ(ch_ctl); |
290 | if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) | 290 | if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) |
291 | break; | 291 | break; |
292 | udelay(100); | ||
292 | } | 293 | } |
293 | 294 | ||
294 | /* Clear done status and any errors */ | 295 | /* Clear done status and any errors */ |
295 | I915_WRITE(ch_ctl, (status | | 296 | I915_WRITE(ch_ctl, |
296 | DP_AUX_CH_CTL_DONE | | 297 | status | |
297 | DP_AUX_CH_CTL_TIME_OUT_ERROR | | 298 | DP_AUX_CH_CTL_DONE | |
298 | DP_AUX_CH_CTL_RECEIVE_ERROR)); | 299 | DP_AUX_CH_CTL_TIME_OUT_ERROR | |
299 | (void) I915_READ(ch_ctl); | 300 | DP_AUX_CH_CTL_RECEIVE_ERROR); |
300 | if ((status & DP_AUX_CH_CTL_TIME_OUT_ERROR) == 0) | 301 | if (status & DP_AUX_CH_CTL_DONE) |
301 | break; | 302 | break; |
302 | } | 303 | } |
303 | 304 | ||
@@ -324,15 +325,12 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, | |||
324 | /* Unload any bytes sent back from the other side */ | 325 | /* Unload any bytes sent back from the other side */ |
325 | recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >> | 326 | recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >> |
326 | DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT); | 327 | DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT); |
327 | |||
328 | if (recv_bytes > recv_size) | 328 | if (recv_bytes > recv_size) |
329 | recv_bytes = recv_size; | 329 | recv_bytes = recv_size; |
330 | 330 | ||
331 | for (i = 0; i < recv_bytes; i += 4) { | 331 | for (i = 0; i < recv_bytes; i += 4) |
332 | uint32_t d = I915_READ(ch_data + i); | 332 | unpack_aux(I915_READ(ch_data + i), |
333 | 333 | recv + i, recv_bytes - i); | |
334 | unpack_aux(d, recv + i, recv_bytes - i); | ||
335 | } | ||
336 | 334 | ||
337 | return recv_bytes; | 335 | return recv_bytes; |
338 | } | 336 | } |
@@ -1140,18 +1138,14 @@ static bool | |||
1140 | intel_dp_set_link_train(struct intel_dp *intel_dp, | 1138 | intel_dp_set_link_train(struct intel_dp *intel_dp, |
1141 | uint32_t dp_reg_value, | 1139 | uint32_t dp_reg_value, |
1142 | uint8_t dp_train_pat, | 1140 | uint8_t dp_train_pat, |
1143 | uint8_t train_set[4], | 1141 | uint8_t train_set[4]) |
1144 | bool first) | ||
1145 | { | 1142 | { |
1146 | struct drm_device *dev = intel_dp->base.enc.dev; | 1143 | struct drm_device *dev = intel_dp->base.enc.dev; |
1147 | struct drm_i915_private *dev_priv = dev->dev_private; | 1144 | struct drm_i915_private *dev_priv = dev->dev_private; |
1148 | struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.enc.crtc); | ||
1149 | int ret; | 1145 | int ret; |
1150 | 1146 | ||
1151 | I915_WRITE(intel_dp->output_reg, dp_reg_value); | 1147 | I915_WRITE(intel_dp->output_reg, dp_reg_value); |
1152 | POSTING_READ(intel_dp->output_reg); | 1148 | POSTING_READ(intel_dp->output_reg); |
1153 | if (first) | ||
1154 | intel_wait_for_vblank(dev, intel_crtc->pipe); | ||
1155 | 1149 | ||
1156 | intel_dp_aux_native_write_1(intel_dp, | 1150 | intel_dp_aux_native_write_1(intel_dp, |
1157 | DP_TRAINING_PATTERN_SET, | 1151 | DP_TRAINING_PATTERN_SET, |
@@ -1176,10 +1170,15 @@ intel_dp_link_train(struct intel_dp *intel_dp) | |||
1176 | uint8_t voltage; | 1170 | uint8_t voltage; |
1177 | bool clock_recovery = false; | 1171 | bool clock_recovery = false; |
1178 | bool channel_eq = false; | 1172 | bool channel_eq = false; |
1179 | bool first = true; | ||
1180 | int tries; | 1173 | int tries; |
1181 | u32 reg; | 1174 | u32 reg; |
1182 | uint32_t DP = intel_dp->DP; | 1175 | uint32_t DP = intel_dp->DP; |
1176 | struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.enc.crtc); | ||
1177 | |||
1178 | /* Enable output, wait for it to become active */ | ||
1179 | I915_WRITE(intel_dp->output_reg, intel_dp->DP); | ||
1180 | POSTING_READ(intel_dp->output_reg); | ||
1181 | intel_wait_for_vblank(dev, intel_crtc->pipe); | ||
1183 | 1182 | ||
1184 | /* Write the link configuration data */ | 1183 | /* Write the link configuration data */ |
1185 | intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, | 1184 | intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, |
@@ -1212,9 +1211,8 @@ intel_dp_link_train(struct intel_dp *intel_dp) | |||
1212 | reg = DP | DP_LINK_TRAIN_PAT_1; | 1211 | reg = DP | DP_LINK_TRAIN_PAT_1; |
1213 | 1212 | ||
1214 | if (!intel_dp_set_link_train(intel_dp, reg, | 1213 | if (!intel_dp_set_link_train(intel_dp, reg, |
1215 | DP_TRAINING_PATTERN_1, train_set, first)) | 1214 | DP_TRAINING_PATTERN_1, train_set)) |
1216 | break; | 1215 | break; |
1217 | first = false; | ||
1218 | /* Set training pattern 1 */ | 1216 | /* Set training pattern 1 */ |
1219 | 1217 | ||
1220 | udelay(100); | 1218 | udelay(100); |
@@ -1268,8 +1266,7 @@ intel_dp_link_train(struct intel_dp *intel_dp) | |||
1268 | 1266 | ||
1269 | /* channel eq pattern */ | 1267 | /* channel eq pattern */ |
1270 | if (!intel_dp_set_link_train(intel_dp, reg, | 1268 | if (!intel_dp_set_link_train(intel_dp, reg, |
1271 | DP_TRAINING_PATTERN_2, train_set, | 1269 | DP_TRAINING_PATTERN_2, train_set)) |
1272 | false)) | ||
1273 | break; | 1270 | break; |
1274 | 1271 | ||
1275 | udelay(400); | 1272 | udelay(400); |
@@ -1388,7 +1385,7 @@ ironlake_dp_detect(struct drm_connector *connector) | |||
1388 | * \return false if DP port is disconnected. | 1385 | * \return false if DP port is disconnected. |
1389 | */ | 1386 | */ |
1390 | static enum drm_connector_status | 1387 | static enum drm_connector_status |
1391 | intel_dp_detect(struct drm_connector *connector) | 1388 | intel_dp_detect(struct drm_connector *connector, bool force) |
1392 | { | 1389 | { |
1393 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1390 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
1394 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); | 1391 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |