diff --git a/src/add-ons/accelerants/radeon_hd/atombios/atombios-obsolete.h b/src/add-ons/accelerants/radeon_hd/atombios/atombios-obsolete.h index 5a08fec0b9..95fab28492 100644 --- a/src/add-ons/accelerants/radeon_hd/atombios/atombios-obsolete.h +++ b/src/add-ons/accelerants/radeon_hd/atombios/atombios-obsolete.h @@ -1,5 +1,5 @@ /* - * Copyright 2016, Haiku, Inc. All Rights Reserved. + * Copyright 2016-2017, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -21,4 +21,22 @@ #define ATOM_S2_DFP5_DPMS_STATE 0x08000000L +// ucAction +#define ATOM_DP_ACTION_TRAINING_START 0x02 +#define ATOM_DP_ACTION_TRAINING_COMPLETE 0x03 +#define ATOM_DP_ACTION_TRAINING_PATTERN_SEL 0x04 +#define ATOM_DP_ACTION_SET_VSWING_PREEMP 0x05 +#define ATOM_DP_ACTION_GET_VSWING_PREEMP 0x06 +#define ATOM_DP_ACTION_BLANKING 0x07 + +// ucConfig +#define ATOM_DP_CONFIG_ENCODER_SEL_MASK 0x03 +#define ATOM_DP_CONFIG_DIG1_ENCODER 0x00 +#define ATOM_DP_CONFIG_DIG2_ENCODER 0x01 +#define ATOM_DP_CONFIG_EXTERNAL_ENCODER 0x02 +#define ATOM_DP_CONFIG_LINK_SEL_MASK 0x04 +#define ATOM_DP_CONFIG_LINK_A 0x00 +#define ATOM_DP_CONFIG_LINK_B 0x04 + + #endif /* _ATOMBIOS_OBSOLETE_H */ diff --git a/src/add-ons/accelerants/radeon_hd/displayport.cpp b/src/add-ons/accelerants/radeon_hd/displayport.cpp index 1cff3fcee0..d18dee323c 100644 --- a/src/add-ons/accelerants/radeon_hd/displayport.cpp +++ b/src/add-ons/accelerants/radeon_hd/displayport.cpp @@ -13,6 +13,7 @@ #include #include "accelerant_protos.h" +#include "atombios-obsolete.h" #include "connector.h" #include "mode.h" #include "edid.h" @@ -327,6 +328,28 @@ dp_aux_set_i2c_byte(uint32 connectorIndex, uint16 address, uint8* data, } +uint32 +dp_get_encoder_config(uint32 connectorIndex) +{ + uint32 result = 0; + + uint32 digEncoderID = encoder_pick_dig(connectorIndex); + if (digEncoderID) + result |= ATOM_DP_CONFIG_DIG2_ENCODER; + else + result |= ATOM_DP_CONFIG_DIG1_ENCODER; + + bool linkB = gConnector[connectorIndex]->encoder.linkEnumeration + == GRAPH_OBJECT_ENUM_ID2 ? true : false; + if (linkB) + result |= ATOM_DP_CONFIG_LINK_B; + else + result |= ATOM_DP_CONFIG_LINK_A; + + return result; +} + + uint32 dp_get_lane_count(uint32 connectorIndex, display_mode* mode) { @@ -541,17 +564,21 @@ dp_clock_equalization_ok(dp_info* dp) uint8 laneAlignment = dp->linkStatus[DP_LANE_ALIGN - DP_LANE_STATUS_0_1]; - if ((laneAlignment & DP_LANE_ALIGN_DONE) == 0) + if ((laneAlignment & DP_LANE_ALIGN_DONE) == 0) { + TRACE("%s: false. Lane alignment incomplete.\n", __func__); return false; + } int lane; for (lane = 0; lane < dp->laneCount; lane++) { uint8 laneStatus = dp_get_lane_status(dp, lane); if ((laneStatus & DP_LANE_STATUS_EQUALIZED_A) != DP_LANE_STATUS_EQUALIZED_A) { + TRACE("%s: false. Lanes not yet equalized.\n", __func__); return false; } } + TRACE("%s: true. Lanes equalized.\n", __func__); return true; } @@ -649,24 +676,39 @@ static void dp_set_tp(uint32 connectorIndex, int trainingPattern) { TRACE("%s\n", __func__); + radeon_shared_info &info = *gInfo->shared_info; + pll_info* pll = &gConnector[connectorIndex]->encoder.pll; int rawTrainingPattern = 0; - /* set training pattern on the source */ - TRACE("%s: Training with encoder...\n", __func__); - switch (trainingPattern) { - case DP_TRAIN_PATTERN_1: - rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1; - break; - case DP_TRAIN_PATTERN_2: - rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2; - break; - case DP_TRAIN_PATTERN_3: - rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3; - break; + if (info.dceMajor >= 4) { + TRACE("%s: Training with encoder...\n", __func__); + switch (trainingPattern) { + case DP_TRAIN_PATTERN_1: + rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1; + break; + case DP_TRAIN_PATTERN_2: + rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2; + break; + case DP_TRAIN_PATTERN_3: + rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3; + break; + } + encoder_dig_setup(connectorIndex, pll->pixelClock, rawTrainingPattern); + } else { + switch (trainingPattern) { + case DP_TRAIN_PATTERN_1: + rawTrainingPattern = 0; + break; + case DP_TRAIN_PATTERN_2: + rawTrainingPattern = 1; + break; + } + uint32 encoderConfig = dp_get_encoder_config(connectorIndex); + dp_encoder_service(ATOM_DP_ACTION_TRAINING_PATTERN_SEL, pll->pixelClock, + rawTrainingPattern, encoderConfig); } - encoder_dig_setup(connectorIndex, pll->pixelClock, rawTrainingPattern); // Enable training pattern on the sink dpcd_reg_write(connectorIndex, DP_TRAIN, trainingPattern); @@ -676,7 +718,7 @@ dp_set_tp(uint32 connectorIndex, int trainingPattern) status_t dp_link_train_cr(uint32 connectorIndex) { - TRACE("%s\n", __func__); + TRACE("%s: connector %" B_PRIu32 "\n", __func__, connectorIndex); dp_info* dp = &gConnector[connectorIndex]->dpInfo; @@ -748,7 +790,7 @@ dp_link_train_cr(uint32 connectorIndex) status_t dp_link_train_ce(uint32 connectorIndex, bool tp3Support) { - TRACE("%s\n", __func__); + TRACE("%s: connector %" B_PRIu32 "\n", __func__, connectorIndex); dp_info* dp = &gConnector[connectorIndex]->dpInfo; @@ -853,9 +895,16 @@ dp_link_train(uint8 crtcID) sandbox = dp_encode_link_rate(dp->linkRate); dpcd_reg_write(connectorIndex, DP_LINK_RATE, sandbox); + uint32 encoderConfig = dp_get_encoder_config(connectorIndex); + // Start link training on source - encoder_dig_setup(connectorIndex, mode->timing.pixel_clock, - ATOM_ENCODER_CMD_DP_LINK_TRAINING_START); + if (info.dceMajor >= 4) { + encoder_dig_setup(connectorIndex, mode->timing.pixel_clock, + ATOM_ENCODER_CMD_DP_LINK_TRAINING_START); + } else { + dp_encoder_service(ATOM_DP_ACTION_TRAINING_START, + mode->timing.pixel_clock, 0, encoderConfig); + } // Disable the training pattern on the sink dpcd_reg_write(connectorIndex, DP_TRAIN, DP_TRAIN_PATTERN_DISABLED); @@ -870,8 +919,13 @@ dp_link_train(uint8 crtcID) dpcd_reg_write(connectorIndex, DP_TRAIN, DP_TRAIN_PATTERN_DISABLED); // Disable the training pattern on the source - encoder_dig_setup(connectorIndex, mode->timing.pixel_clock, - ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE); + if (info.dceMajor >= 4) { + encoder_dig_setup(connectorIndex, mode->timing.pixel_clock, + ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE); + } else { + dp_encoder_service(ATOM_DP_ACTION_TRAINING_COMPLETE, + mode->timing.pixel_clock, 0, encoderConfig); + } return B_OK; } diff --git a/src/add-ons/accelerants/radeon_hd/displayport.h b/src/add-ons/accelerants/radeon_hd/displayport.h index ca93dc5caf..9432401ef4 100644 --- a/src/add-ons/accelerants/radeon_hd/displayport.h +++ b/src/add-ons/accelerants/radeon_hd/displayport.h @@ -36,6 +36,7 @@ status_t dp_aux_get_i2c_byte(uint32 connectorIndex, uint16 address, uint32 dp_get_link_rate(uint32 connectorIndex, display_mode* mode); uint32 dp_get_lane_count(uint32 connectorIndex, display_mode* mode); +uint32 dp_get_encoder_config(uint32 connectorIndex); uint8 dp_get_sink_type(uint32 connectorIndex); void dp_setup_connectors();