diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2010-01-12 17:54:34 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-02-08 18:44:02 -0500 |
commit | bcc1c2a1d22974215e39dc87ce746ba9a39223e5 (patch) | |
tree | 62ae9dfab266202240307fc3998806c1d4655552 /drivers/gpu/drm/radeon/atombios_dp.c | |
parent | e97bd974448ce90f8e4720499d84580bcd6a2f7a (diff) |
drm/radeon/kms: add initial Evergreen support (Radeon HD 5xxx)
This adds initial Evergreen KMS support, it doesn't include
any acceleration features or interrupt handling yet.
Major changes are DCE4 handling for PLLs for the > 2 crtcs.
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/atombios_dp.c')
-rw-r--r-- | drivers/gpu/drm/radeon/atombios_dp.c | 62 |
1 files changed, 41 insertions, 21 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 71060114d5de..0b6f2cef1c52 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 | 339 | ||
@@ -339,29 +343,31 @@ bool radeon_process_aux_ch(struct radeon_i2c_chan *chan, u8 *req_bytes, | |||
339 | 343 | ||
340 | memcpy(base, req_bytes, num_bytes); | 344 | memcpy(base, req_bytes, num_bytes); |
341 | 345 | ||
342 | args.lpAuxRequest = 0; | 346 | args.v1.lpAuxRequest = 0; |
343 | args.lpDataOut = 16; | 347 | args.v1.lpDataOut = 16; |
344 | args.ucDataOutLen = 0; | 348 | args.v1.ucDataOutLen = 0; |
345 | args.ucChannelID = chan->rec.i2c_id; | 349 | args.v1.ucChannelID = chan->rec.i2c_id; |
346 | args.ucDelay = delay / 10; | 350 | args.v1.ucDelay = delay / 10; |
351 | if (ASIC_IS_DCE4(rdev)) | ||
352 | args.v2.ucHPD_ID = chan->rec.hpd_id; | ||
347 | 353 | ||
348 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 354 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
349 | 355 | ||
350 | if (args.ucReplyStatus) { | 356 | if (args.v1.ucReplyStatus) { |
351 | DRM_DEBUG("failed to get auxch %02x%02x %02x %02x 0x%02x %02x\n", | 357 | DRM_DEBUG("failed to get auxch %02x%02x %02x %02x 0x%02x %02x\n", |
352 | req_bytes[1], req_bytes[0], req_bytes[2], req_bytes[3], | 358 | req_bytes[1], req_bytes[0], req_bytes[2], req_bytes[3], |
353 | chan->rec.i2c_id, args.ucReplyStatus); | 359 | chan->rec.i2c_id, args.v1.ucReplyStatus); |
354 | return false; | 360 | return false; |
355 | } | 361 | } |
356 | 362 | ||
357 | if (args.ucDataOutLen && read_byte && read_buf_len) { | 363 | if (args.v1.ucDataOutLen && read_byte && read_buf_len) { |
358 | if (read_buf_len < args.ucDataOutLen) { | 364 | if (read_buf_len < args.v1.ucDataOutLen) { |
359 | DRM_ERROR("Buffer to small for return answer %d %d\n", | 365 | DRM_ERROR("Buffer to small for return answer %d %d\n", |
360 | read_buf_len, args.ucDataOutLen); | 366 | read_buf_len, args.v1.ucDataOutLen); |
361 | return false; | 367 | return false; |
362 | } | 368 | } |
363 | { | 369 | { |
364 | int len = min(read_buf_len, args.ucDataOutLen); | 370 | int len = min(read_buf_len, args.v1.ucDataOutLen); |
365 | memcpy(read_byte, base + 16, len); | 371 | memcpy(read_byte, base + 16, len); |
366 | } | 372 | } |
367 | } | 373 | } |
@@ -622,12 +628,19 @@ void dp_link_train(struct drm_encoder *encoder, | |||
622 | dp_set_link_bw_lanes(radeon_connector, link_configuration); | 628 | dp_set_link_bw_lanes(radeon_connector, link_configuration); |
623 | /* disable downspread on the sink */ | 629 | /* disable downspread on the sink */ |
624 | dp_set_downspread(radeon_connector, 0); | 630 | dp_set_downspread(radeon_connector, 0); |
625 | /* start training on the source */ | 631 | if (ASIC_IS_DCE4(rdev)) { |
626 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_START, | 632 | /* start training on the source */ |
627 | dig_connector->dp_clock, enc_id, 0); | 633 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_START); |
628 | /* set training pattern 1 on the source */ | 634 | /* set training pattern 1 on the source */ |
629 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, | 635 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1); |
630 | dig_connector->dp_clock, enc_id, 0); | 636 | } else { |
637 | /* start training on the source */ | ||
638 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_START, | ||
639 | dig_connector->dp_clock, enc_id, 0); | ||
640 | /* set training pattern 1 on the source */ | ||
641 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, | ||
642 | dig_connector->dp_clock, enc_id, 0); | ||
643 | } | ||
631 | 644 | ||
632 | /* set initial vs/emph */ | 645 | /* set initial vs/emph */ |
633 | memset(train_set, 0, 4); | 646 | memset(train_set, 0, 4); |
@@ -687,8 +700,11 @@ void dp_link_train(struct drm_encoder *encoder, | |||
687 | /* set training pattern 2 on the sink */ | 700 | /* set training pattern 2 on the sink */ |
688 | dp_set_training(radeon_connector, DP_TRAINING_PATTERN_2); | 701 | dp_set_training(radeon_connector, DP_TRAINING_PATTERN_2); |
689 | /* set training pattern 2 on the source */ | 702 | /* set training pattern 2 on the source */ |
690 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, | 703 | if (ASIC_IS_DCE4(rdev)) |
691 | dig_connector->dp_clock, enc_id, 1); | 704 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2); |
705 | else | ||
706 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, | ||
707 | dig_connector->dp_clock, enc_id, 1); | ||
692 | 708 | ||
693 | /* channel equalization loop */ | 709 | /* channel equalization loop */ |
694 | tries = 0; | 710 | tries = 0; |
@@ -725,7 +741,11 @@ void dp_link_train(struct drm_encoder *encoder, | |||
725 | >> DP_TRAIN_PRE_EMPHASIS_SHIFT); | 741 | >> DP_TRAIN_PRE_EMPHASIS_SHIFT); |
726 | 742 | ||
727 | /* disable the training pattern on the sink */ | 743 | /* disable the training pattern on the sink */ |
728 | dp_set_training(radeon_connector, DP_TRAINING_PATTERN_DISABLE); | 744 | if (ASIC_IS_DCE4(rdev)) |
745 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE); | ||
746 | else | ||
747 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_COMPLETE, | ||
748 | dig_connector->dp_clock, enc_id, 0); | ||
729 | 749 | ||
730 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_COMPLETE, | 750 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_COMPLETE, |
731 | dig_connector->dp_clock, enc_id, 0); | 751 | dig_connector->dp_clock, enc_id, 0); |