diff --git a/src/atombios_output.c b/src/atombios_output.c index 51a7d44..424396f 100644 --- a/src/atombios_output.c +++ b/src/atombios_output.c @@ -496,6 +496,23 @@ dp_link_clock_for_mode_clock(int mode_clock) return 0; } +/* + * DIG Encoder/Transmitter Setup + * + * DCE 3.0/3.1 + * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA. + * Supports up to 3 digital outputs + * - 2 DIG encoder blocks. + * DIG1 can drive UNIPHY link A or link B + * DIG2 can drive UNIPHY link B or LVTMA + * + * DCE 3.2 + * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B). + * Supports up to 5 digital outputs + * - 2 DIG encoder blocks. + * DIG1/2 can drive UNIPHY0/1/2 link A or link B + * + */ static int atombios_output_dig_encoder_setup(xf86OutputPtr output, int action) { @@ -523,7 +540,10 @@ atombios_output_dig_encoder_setup(xf86OutputPtr output, int action) } else { switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: - index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); + if (radeon_output->linkb) + index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); + else + index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); num = 1; break; case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: @@ -628,7 +648,10 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action) else { switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: - index = GetIndexIntoMasterTable(COMMAND, DIG1TransmitterControl); + if (radeon_output->linkb) + index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl); + else + index = GetIndexIntoMasterTable(COMMAND, DIG1TransmitterControl); break; case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl); @@ -687,7 +710,10 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action) switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: - disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; + if (radeon_output->linkb) + disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; + else + disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; if (info->IsIGP) { if (clock > 165000) { disp_data.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | @@ -1487,11 +1513,6 @@ atombios_output_mode_set(xf86OutputPtr output, atombios_output_yuv_setup(output, FALSE); } - if (radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT && radeon_output->MonType == MT_DP) { - do_displayport_dance(output, mode, adjusted_mode); - return; - } - switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_TMDS1: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: @@ -1511,6 +1532,11 @@ atombios_output_mode_set(xf86OutputPtr output, atombios_output_dig_encoder_setup(output, ATOM_ENABLE); atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_SETUP); atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE); + + if (radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT && radeon_output->MonType == MT_DP) { + do_displayport_dance(output, mode, adjusted_mode); + //return; + } break; case ENCODER_OBJECT_ID_INTERNAL_DDI: atombios_output_ddia_setup(output, ATOM_ENABLE); @@ -1771,7 +1797,7 @@ RADEONProcessAuxCH(xf86OutputPtr output, char *req_bytes, int num_bytes, uint8_t args.lpAuxRequest = 0; args.lpDataOut = 16; args.ucDataOutLen = 0; - args.ucChannelID = 0x92; + args.ucChannelID = radeon_output->ucI2cId; args.ucDelay = 0; data.exec.index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); @@ -1823,7 +1849,9 @@ RADEONDPEncoderService(xf86OutputPtr output, int action, uint8_t ucconfig) int RADEON_DP_GetSinkType(xf86OutputPtr output) { - return RADEONDPEncoderService(output, ATOM_DP_ACTION_GET_SINK_TYPE, 0x92); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + return RADEONDPEncoderService(output, ATOM_DP_ACTION_GET_SINK_TYPE, radeon_output->ucI2cId); } @@ -2154,6 +2182,8 @@ atom_dp_set_link_train(xf86OutputPtr output, uint8_t dp_train_pat, uint8_t train static void do_displayport_dance(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) { ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(output->scrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; int num_lane = dp_lanes_for_mode_clock(mode->Clock); int dp_clock = dp_link_clock_for_mode_clock(mode->Clock); Bool clock_recovery; @@ -2162,6 +2192,22 @@ static void do_displayport_dance(xf86OutputPtr output, DisplayModePtr mode, Disp uint8_t train_set[4]; ErrorF("Doing displayport DANCE lanes:%d %d\n", num_lane, dp_clock); + if (IS_DCE32_VARIANT) { + if (radeon_output->dig_block) + RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_START, + ATOM_DP_CONFIG_DIG2_ENCODER); + else + RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_START, + ATOM_DP_CONFIG_DIG1_ENCODER); + } else { + if (radeon_output->linkb) + RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_START, + ATOM_DP_CONFIG_DIG2_ENCODER); + else + RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_START, + ATOM_DP_CONFIG_DIG1_ENCODER); + } + memset(train_set, 0, 4); /* loop around doing configuration reads and DP encoder setups */ clock_recovery = FALSE; @@ -2191,5 +2237,19 @@ static void do_displayport_dance(xf86OutputPtr output, DisplayModePtr mode, Disp (train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT); - + if (IS_DCE32_VARIANT) { + if (radeon_output->dig_block) + RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_COMPLETE, + ATOM_DP_CONFIG_DIG2_ENCODER); + else + RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_COMPLETE, + ATOM_DP_CONFIG_DIG1_ENCODER); + } else { + if (radeon_output->linkb) + RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_COMPLETE, + ATOM_DP_CONFIG_DIG2_ENCODER); + else + RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_COMPLETE, + ATOM_DP_CONFIG_DIG1_ENCODER); + } } diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c index 6375626..5727b88 100644 --- a/src/radeon_atombios.c +++ b/src/radeon_atombios.c @@ -1575,8 +1575,10 @@ rhdAtomParseI2CRecord(ScrnInfoPtr pScrn, atomBiosHandlePtr handle, ATOM_I2C_RECORD *Record, int i) { RADEONInfoPtr info = RADEONPTR (pScrn); + uint8_t *temp = &Record->sucI2cId; info->BiosConnector[i].i2c_line_mux = Record->sucI2cId.bfI2C_LineMux; + info->BiosConnector[i].ucI2cId = *temp; return RADEONLookupGPIOLineForDDC(pScrn, Record->sucI2cId.bfI2C_LineMux); } diff --git a/src/radeon_output.c b/src/radeon_output.c index 94fdb12..cf415d0 100644 --- a/src/radeon_output.c +++ b/src/radeon_output.c @@ -2773,6 +2773,7 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn) radeon_output->load_detection = info->BiosConnector[i].load_detection; radeon_output->linkb = info->BiosConnector[i].linkb; radeon_output->connector_id = info->BiosConnector[i].connector_object; + radeon_output->ucI2cId = info->BiosConnector[i].ucI2cId; if ((conntype == CONNECTOR_DVI_D) || (conntype == CONNECTOR_DVI_I) || diff --git a/src/radeon_probe.h b/src/radeon_probe.h index abd7612..7717031 100644 --- a/src/radeon_probe.h +++ b/src/radeon_probe.h @@ -239,6 +239,7 @@ typedef struct { Bool load_detection; Bool linkb; uint16_t connector_object; + uint8_t ucI2cId; } RADEONBIOSConnector; typedef struct _RADEONOutputPrivateRec { @@ -285,6 +286,7 @@ typedef struct _RADEONOutputPrivateRec { char dp_bus_name[20]; uint32_t dp_i2c_addr, dp_i2c_running; uint8_t dpcp8[8]; + uint8_t ucI2cId; } RADEONOutputPrivateRec, *RADEONOutputPrivatePtr; struct avivo_pll_state {