diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/atombios_dp.c')
-rw-r--r-- | drivers/gpu/drm/radeon/atombios_dp.c | 64 |
1 files changed, 42 insertions, 22 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 99915a682d59..8a133bda00a2 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c | |||
@@ -321,6 +321,10 @@ static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE], | |||
321 | train_set[lane] = v | p; | 321 | train_set[lane] = v | p; |
322 | } | 322 | } |
323 | 323 | ||
324 | union aux_channel_transaction { | ||
325 | PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1; | ||
326 | PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2; | ||
327 | }; | ||
324 | 328 | ||
325 | /* radeon aux chan functions */ | 329 | /* radeon aux chan functions */ |
326 | bool radeon_process_aux_ch(struct radeon_i2c_chan *chan, u8 *req_bytes, | 330 | bool radeon_process_aux_ch(struct radeon_i2c_chan *chan, u8 *req_bytes, |
@@ -329,7 +333,7 @@ bool radeon_process_aux_ch(struct radeon_i2c_chan *chan, u8 *req_bytes, | |||
329 | { | 333 | { |
330 | struct drm_device *dev = chan->dev; | 334 | struct drm_device *dev = chan->dev; |
331 | struct radeon_device *rdev = dev->dev_private; | 335 | struct radeon_device *rdev = dev->dev_private; |
332 | PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION args; | 336 | union aux_channel_transaction args; |
333 | int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); | 337 | int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); |
334 | unsigned char *base; | 338 | unsigned char *base; |
335 | int retry_count = 0; | 339 | int retry_count = 0; |
@@ -341,31 +345,33 @@ bool radeon_process_aux_ch(struct radeon_i2c_chan *chan, u8 *req_bytes, | |||
341 | retry: | 345 | retry: |
342 | memcpy(base, req_bytes, num_bytes); | 346 | memcpy(base, req_bytes, num_bytes); |
343 | 347 | ||
344 | args.lpAuxRequest = 0; | 348 | args.v1.lpAuxRequest = 0; |
345 | args.lpDataOut = 16; | 349 | args.v1.lpDataOut = 16; |
346 | args.ucDataOutLen = 0; | 350 | args.v1.ucDataOutLen = 0; |
347 | args.ucChannelID = chan->rec.i2c_id; | 351 | args.v1.ucChannelID = chan->rec.i2c_id; |
348 | args.ucDelay = delay / 10; | 352 | args.v1.ucDelay = delay / 10; |
353 | if (ASIC_IS_DCE4(rdev)) | ||
354 | args.v2.ucHPD_ID = chan->rec.hpd_id; | ||
349 | 355 | ||
350 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 356 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
351 | 357 | ||
352 | if (args.ucReplyStatus && !args.ucDataOutLen) { | 358 | if (args.v1.ucReplyStatus && !args.v1.ucDataOutLen) { |
353 | if (args.ucReplyStatus == 0x20 && retry_count++ < 10) | 359 | if (args.v1.ucReplyStatus == 0x20 && retry_count++ < 10) |
354 | goto retry; | 360 | goto retry; |
355 | DRM_DEBUG("failed to get auxch %02x%02x %02x %02x 0x%02x %02x after %d retries\n", | 361 | DRM_DEBUG("failed to get auxch %02x%02x %02x %02x 0x%02x %02x after %d retries\n", |
356 | req_bytes[1], req_bytes[0], req_bytes[2], req_bytes[3], | 362 | req_bytes[1], req_bytes[0], req_bytes[2], req_bytes[3], |
357 | chan->rec.i2c_id, args.ucReplyStatus, retry_count); | 363 | chan->rec.i2c_id, args.v1.ucReplyStatus, retry_count); |
358 | return false; | 364 | return false; |
359 | } | 365 | } |
360 | 366 | ||
361 | if (args.ucDataOutLen && read_byte && read_buf_len) { | 367 | if (args.v1.ucDataOutLen && read_byte && read_buf_len) { |
362 | if (read_buf_len < args.ucDataOutLen) { | 368 | if (read_buf_len < args.v1.ucDataOutLen) { |
363 | DRM_ERROR("Buffer to small for return answer %d %d\n", | 369 | DRM_ERROR("Buffer to small for return answer %d %d\n", |
364 | read_buf_len, args.ucDataOutLen); | 370 | read_buf_len, args.v1.ucDataOutLen); |
365 | return false; | 371 | return false; |
366 | } | 372 | } |
367 | { | 373 | { |
368 | int len = min(read_buf_len, args.ucDataOutLen); | 374 | int len = min(read_buf_len, args.v1.ucDataOutLen); |
369 | memcpy(read_byte, base + 16, len); | 375 | memcpy(read_byte, base + 16, len); |
370 | } | 376 | } |
371 | } | 377 | } |
@@ -626,12 +632,19 @@ void dp_link_train(struct drm_encoder *encoder, | |||
626 | dp_set_link_bw_lanes(radeon_connector, link_configuration); | 632 | dp_set_link_bw_lanes(radeon_connector, link_configuration); |
627 | /* disable downspread on the sink */ | 633 | /* disable downspread on the sink */ |
628 | dp_set_downspread(radeon_connector, 0); | 634 | dp_set_downspread(radeon_connector, 0); |
629 | /* start training on the source */ | 635 | if (ASIC_IS_DCE4(rdev)) { |
630 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_START, | 636 | /* start training on the source */ |
631 | dig_connector->dp_clock, enc_id, 0); | 637 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_START); |
632 | /* set training pattern 1 on the source */ | 638 | /* set training pattern 1 on the source */ |
633 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, | 639 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1); |
634 | dig_connector->dp_clock, enc_id, 0); | 640 | } else { |
641 | /* start training on the source */ | ||
642 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_START, | ||
643 | dig_connector->dp_clock, enc_id, 0); | ||
644 | /* set training pattern 1 on the source */ | ||
645 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, | ||
646 | dig_connector->dp_clock, enc_id, 0); | ||
647 | } | ||
635 | 648 | ||
636 | /* set initial vs/emph */ | 649 | /* set initial vs/emph */ |
637 | memset(train_set, 0, 4); | 650 | memset(train_set, 0, 4); |
@@ -691,8 +704,11 @@ void dp_link_train(struct drm_encoder *encoder, | |||
691 | /* set training pattern 2 on the sink */ | 704 | /* set training pattern 2 on the sink */ |
692 | dp_set_training(radeon_connector, DP_TRAINING_PATTERN_2); | 705 | dp_set_training(radeon_connector, DP_TRAINING_PATTERN_2); |
693 | /* set training pattern 2 on the source */ | 706 | /* set training pattern 2 on the source */ |
694 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, | 707 | if (ASIC_IS_DCE4(rdev)) |
695 | dig_connector->dp_clock, enc_id, 1); | 708 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2); |
709 | else | ||
710 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, | ||
711 | dig_connector->dp_clock, enc_id, 1); | ||
696 | 712 | ||
697 | /* channel equalization loop */ | 713 | /* channel equalization loop */ |
698 | tries = 0; | 714 | tries = 0; |
@@ -729,7 +745,11 @@ void dp_link_train(struct drm_encoder *encoder, | |||
729 | >> DP_TRAIN_PRE_EMPHASIS_SHIFT); | 745 | >> DP_TRAIN_PRE_EMPHASIS_SHIFT); |
730 | 746 | ||
731 | /* disable the training pattern on the sink */ | 747 | /* disable the training pattern on the sink */ |
732 | dp_set_training(radeon_connector, DP_TRAINING_PATTERN_DISABLE); | 748 | if (ASIC_IS_DCE4(rdev)) |
749 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE); | ||
750 | else | ||
751 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_COMPLETE, | ||
752 | dig_connector->dp_clock, enc_id, 0); | ||
733 | 753 | ||
734 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_COMPLETE, | 754 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_COMPLETE, |
735 | dig_connector->dp_clock, enc_id, 0); | 755 | dig_connector->dp_clock, enc_id, 0); |