hrev43448 adds 3 changesets to branch 'master' old head: 11d60eaa36f9472dca83833070fd2d1b4714fb6b new head: 654dc4bfabac752ddf61e5e55db77800dfccd531 ---------------------------------------------------------------------------- 60b7d1d: Add i2c DP AUX communication calls * remove posix return * pass GPIO hwLine through vs connector index * variable scope cleanup * make lowest level dp aux AtomBIOS call static, non-public as it is always called by connector code 7a13bce: More work towards DP support. * add DPBridge encoder flag and set during connector detection * if external bridge found, do external DDC setup * pass connectorIndex vs displayIndex to encoder_*_setup * some of the DP AUX channel stuff should go into accelerant common code some day like i2c. 654dc4b: Use bridge encoder flag vs making direct calls to check [ Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> ] ---------------------------------------------------------------------------- 6 files changed, 208 insertions(+), 57 deletions(-) src/add-ons/accelerants/radeon_hd/accelerant.h | 1 + src/add-ons/accelerants/radeon_hd/connector.cpp | 192 ++++++++++++++++--- src/add-ons/accelerants/radeon_hd/connector.h | 11 +- src/add-ons/accelerants/radeon_hd/encoder.cpp | 39 ++-- src/add-ons/accelerants/radeon_hd/encoder.h | 20 ++- src/add-ons/accelerants/radeon_hd/pll.cpp | 2 +- ############################################################################ Commit: 60b7d1defbf486d4f77a2edaef21095fac407376 URL: http://cgit.haiku-os.org/haiku/commit/?id=60b7d1d Author: Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> Date: Fri Dec 9 21:36:33 2011 UTC Add i2c DP AUX communication calls * remove posix return * pass GPIO hwLine through vs connector index * variable scope cleanup * make lowest level dp aux AtomBIOS call static, non-public as it is always called by connector code ---------------------------------------------------------------------------- diff --git a/src/add-ons/accelerants/radeon_hd/connector.cpp b/src/add-ons/accelerants/radeon_hd/connector.cpp index 5bcaef8..cf08969 100644 --- a/src/add-ons/accelerants/radeon_hd/connector.cpp +++ b/src/add-ons/accelerants/radeon_hd/connector.cpp @@ -35,15 +35,13 @@ union aux_channel_transaction { }; -int -dp_aux_speak(uint8 connectorIndex, uint8 *send, int sendBytes, +static int +dp_aux_speak(uint32 hwLine, uint8 *send, int sendBytes, uint8 *recv, int recvBytes, uint8 delay, uint8 *ack) { - uint32 gpioID = gConnector[connectorIndex]->gpioID; - - if (gGPIOInfo[gpioID]->valid != true) { + if (hwLine == 0) { ERROR("%s: cannot speak on invalid GPIO pin!\n", __func__); - return -B_IO_ERROR; + return B_IO_ERROR; } union aux_channel_transaction args; @@ -57,7 +55,7 @@ dp_aux_speak(uint8 connectorIndex, uint8 *send, int sendBytes, args.v1.lpAuxRequest = 0; args.v1.lpDataOut = 16; args.v1.ucDataOutLen = 0; - args.v1.ucChannelID = gGPIOInfo[gpioID]->hw_line; + args.v1.ucChannelID = hwLine; args.v1.ucDelay = delay / 10; //if (ASIC_IS_DCE4(rdev)) @@ -91,7 +89,7 @@ dp_aux_speak(uint8 connectorIndex, uint8 *send, int sendBytes, int -dp_aux_write(uint32 connectorIndex, uint16 address, +dp_aux_write(uint32 hwLine, uint16 address, uint8 *send, uint8 sendBytes, uint8 delay) { uint8 auxMessage[20]; @@ -106,18 +104,16 @@ dp_aux_write(uint32 connectorIndex, uint16 address, auxMessage[3] = (auxMessageBytes << 4) | (sendBytes - 1); memcpy(&auxMessage[4], send, sendBytes); - int ret; uint8 retry; - uint8 ack; for (retry = 0; retry < 4; retry++) { - - ret = dp_aux_speak(connectorIndex, auxMessage, auxMessageBytes, + uint8 ack; + int result = dp_aux_speak(hwLine, auxMessage, auxMessageBytes, NULL, 0, delay, &ack); - if (ret == B_BUSY) + if (result == B_BUSY) continue; - else if (ret < B_OK) - return ret; + else if (result < B_OK) + return result; if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) return sendBytes; @@ -132,7 +128,7 @@ dp_aux_write(uint32 connectorIndex, uint16 address, int -dp_aux_read(uint32 connectorIndex, uint16 address, +dp_aux_read(uint32 hwLine, uint16 address, uint8 *recv, int recvBytes, uint8 delay) { uint8 auxMessage[4]; @@ -143,20 +139,19 @@ dp_aux_read(uint32 connectorIndex, uint16 address, auxMessage[2] = AUX_NATIVE_READ << 4; auxMessage[3] = (auxMessageBytes << 4) | (recvBytes - 1); - int ret; uint8 retry; - uint8 ack; for (retry = 0; retry < 4; retry++) { - ret = dp_aux_speak(connectorIndex, auxMessage, auxMessageBytes, + uint8 ack; + int result = dp_aux_speak(hwLine, auxMessage, auxMessageBytes, recv, recvBytes, delay, &ack); - if (ret == B_BUSY) + if (result == B_BUSY) continue; - else if (ret < B_OK) - return ret; + else if (result < B_OK) + return result; if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) - return ret; + return result; else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) snooze(400); else @@ -167,6 +162,149 @@ dp_aux_read(uint32 connectorIndex, uint16 address, } +status_t +dp_aux_get_i2c_byte(uint32 hwLine, uint16 address, uint8* data, bool end) +{ + uint8 auxMessage[5]; + int auxMessageBytes = 4; // 4 for read + + /* Set up the command byte */ + auxMessage[2] = AUX_I2C_READ << 4; + if (end == false) + auxMessage[2] |= AUX_I2C_MOT << 4; + + auxMessage[0] = address; + auxMessage[1] = address >> 8; + + auxMessage[3] = auxMessageBytes << 4; + + int retry; + for (retry = 0; retry < 4; retry++) { + uint8 ack; + uint8 reply[2]; + int replyBytes = 1; + + int result = dp_aux_speak(hwLine, auxMessage, auxMessageBytes, + reply, replyBytes, 0, &ack); + if (result == B_BUSY) + continue; + else if (result < 0) { + ERROR("%s: aux_ch failed: %d\n", __func__, result); + return B_ERROR; + } + + switch (ack & AUX_NATIVE_REPLY_MASK) { + case AUX_NATIVE_REPLY_ACK: + // I2C-over-AUX Reply field is only valid for AUX_ACK + break; + case AUX_NATIVE_REPLY_NACK: + TRACE("%s: aux_ch native nack\n", __func__); + return B_IO_ERROR; + case AUX_NATIVE_REPLY_DEFER: + TRACE("%s: aux_ch native defer\n", __func__); + snooze(400); + continue; + default: + TRACE("%s: aux_ch invalid native reply: 0x%02x\n", + __func__, ack); + return B_ERROR; + } + + switch (ack & AUX_I2C_REPLY_MASK) { + case AUX_I2C_REPLY_ACK: + *data = reply[0]; + return B_OK; + case AUX_I2C_REPLY_NACK: + TRACE("%s: aux_i2c nack\n", __func__); + return B_IO_ERROR; + case AUX_I2C_REPLY_DEFER: + TRACE("%s: aux_i2c defer\n", __func__); + snooze(400); + break; + default: + TRACE("%s: aux_i2c invalid native reply: 0x%02x\n", + __func__, ack); + return B_ERROR; + } + } + + TRACE("%s: aux i2c too many retries, giving up.\n", __func__); + return B_ERROR; +} + + +status_t +dp_aux_set_i2c_byte(uint32 hwLine, uint16 address, uint8* data, bool end) +{ + uint8 auxMessage[5]; + int auxMessageBytes = 5; // 5 for write + + /* Set up the command byte */ + auxMessage[2] = AUX_I2C_WRITE << 4; + if (end == false) + auxMessage[2] |= AUX_I2C_MOT << 4; + + auxMessage[0] = address; + auxMessage[1] = address >> 8; + + auxMessage[3] = auxMessageBytes << 4; + auxMessage[4] = *data; + + int retry; + for (retry = 0; retry < 4; retry++) { + uint8 ack; + uint8 reply[2]; + int replyBytes = 1; + + int result = dp_aux_speak(hwLine, auxMessage, auxMessageBytes, + reply, replyBytes, 0, &ack); + if (result == B_BUSY) + continue; + else if (result < 0) { + ERROR("%s: aux_ch failed: %d\n", __func__, result); + return B_ERROR; + } + + switch (ack & AUX_NATIVE_REPLY_MASK) { + case AUX_NATIVE_REPLY_ACK: + // I2C-over-AUX Reply field is only valid for AUX_ACK + break; + case AUX_NATIVE_REPLY_NACK: + TRACE("%s: aux_ch native nack\n", __func__); + return B_IO_ERROR; + case AUX_NATIVE_REPLY_DEFER: + TRACE("%s: aux_ch native defer\n", __func__); + snooze(400); + continue; + default: + TRACE("%s: aux_ch invalid native reply: 0x%02x\n", + __func__, ack); + return B_ERROR; + } + + switch (ack & AUX_I2C_REPLY_MASK) { + case AUX_I2C_REPLY_ACK: + // Success! + return B_OK; + case AUX_I2C_REPLY_NACK: + TRACE("%s: aux_i2c nack\n", __func__); + return B_IO_ERROR; + case AUX_I2C_REPLY_DEFER: + TRACE("%s: aux_i2c defer\n", __func__); + snooze(400); + break; + default: + TRACE("%s: aux_i2c invalid native reply: 0x%02x\n", + __func__, ack); + return B_ERROR; + } + } + + TRACE("%s: aux i2c too many retries, giving up.\n", __func__); + return B_OK; +} + + static void gpio_lock_i2c(void* cookie, bool lock) { diff --git a/src/add-ons/accelerants/radeon_hd/connector.h b/src/add-ons/accelerants/radeon_hd/connector.h index 108e59f..1efd178 100644 --- a/src/add-ons/accelerants/radeon_hd/connector.h +++ b/src/add-ons/accelerants/radeon_hd/connector.h @@ -78,12 +78,15 @@ const int connector_convert[] = { }; -int dp_aux_speak(uint8 connectorIndex, uint8 *send, int sendBytes, - uint8 *recv, int recvBytes, uint8 delay, uint8 *ack); -int dp_aux_write(uint32 connectorIndex, uint16 address, uint8 *send, +int dp_aux_write(uint32 hwLine, uint16 address, uint8 *send, uint8 sendBytes, uint8 delay); -int dp_aux_read(uint32 connectorIndex, uint16 address, uint8 *recv, +int dp_aux_read(uint32 hwLine, uint16 address, uint8 *recv, int recvBytes, uint8 delay); +status_t dp_aux_set_i2c_byte(uint32 hwLine, uint16 address, + uint8* data, bool end); +status_t dp_aux_get_i2c_byte(uint32 hwLine, uint16 address, + uint8* data, bool end); + status_t gpio_probe(); status_t connector_attach_gpio(uint32 id, uint8 hw_line); ############################################################################ Commit: 7a13bce56dcb354289764f5499e0ac6ebe66377f URL: http://cgit.haiku-os.org/haiku/commit/?id=7a13bce Author: Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> Date: Fri Dec 9 22:39:22 2011 UTC More work towards DP support. * add DPBridge encoder flag and set during connector detection * if external bridge found, do external DDC setup * pass connectorIndex vs displayIndex to encoder_*_setup * some of the DP AUX channel stuff should go into accelerant common code some day like i2c. ---------------------------------------------------------------------------- diff --git a/src/add-ons/accelerants/radeon_hd/accelerant.h b/src/add-ons/accelerants/radeon_hd/accelerant.h index a8149a7..7a01e88 100644 --- a/src/add-ons/accelerants/radeon_hd/accelerant.h +++ b/src/add-ons/accelerants/radeon_hd/accelerant.h @@ -134,6 +134,7 @@ struct encoder_info { uint32 type; uint32 flags; bool isExternal; + bool isDPBridge; bool isHDMI; bool isTV; struct pll_info pll; diff --git a/src/add-ons/accelerants/radeon_hd/connector.cpp b/src/add-ons/accelerants/radeon_hd/connector.cpp index cf08969..8983741 100644 --- a/src/add-ons/accelerants/radeon_hd/connector.cpp +++ b/src/add-ons/accelerants/radeon_hd/connector.cpp @@ -914,6 +914,8 @@ connector_probe() = encoderType; gConnector[connectorIndex]->encoder.isExternal = encoder_is_external(encoderID); + gConnector[connectorIndex]->encoder.isDPBridge + = encoder_is_dp_bridge(encoderID); pll_limit_probe( &gConnector[connectorIndex]->encoder.pll); @@ -995,6 +997,12 @@ connector_probe() break; } + if (gConnector[connectorIndex]->encoder.isDPBridge == true) { + TRACE("%s: is bridge, performing bridge DDC setup\n", __func__); + encoder_external_setup(connectorIndex, 0, + EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP); + } + connectorIndex++; } // END for each valid connector } // end for each display path diff --git a/src/add-ons/accelerants/radeon_hd/encoder.cpp b/src/add-ons/accelerants/radeon_hd/encoder.cpp index 8d6390d..5181ea7 100644 --- a/src/add-ons/accelerants/radeon_hd/encoder.cpp +++ b/src/add-ons/accelerants/radeon_hd/encoder.cpp @@ -206,19 +206,20 @@ encoder_mode_set(uint8 id, uint32 pixelClock) case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: case ENCODER_OBJECT_ID_INTERNAL_DAC2: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: - encoder_analog_setup(id, pixelClock, ATOM_ENABLE); + encoder_analog_setup(connectorIndex, pixelClock, ATOM_ENABLE); if ((encoderFlags & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) != 0) { - encoder_tv_setup(id, pixelClock, ATOM_ENABLE); + encoder_tv_setup(connectorIndex, pixelClock, ATOM_ENABLE); } else { - encoder_tv_setup(id, pixelClock, ATOM_DISABLE); + encoder_tv_setup(connectorIndex, pixelClock, ATOM_DISABLE); } break; case ENCODER_OBJECT_ID_INTERNAL_TMDS1: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: case ENCODER_OBJECT_ID_INTERNAL_LVDS: case ENCODER_OBJECT_ID_INTERNAL_LVTM1: - encoder_digital_setup(id, pixelClock, PANEL_ENCODER_ACTION_ENABLE); + encoder_digital_setup(connectorIndex, pixelClock, + PANEL_ENCODER_ACTION_ENABLE); break; case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: @@ -228,7 +229,8 @@ encoder_mode_set(uint8 id, uint32 pixelClock) //atombios_dig_transmitter_setup(encoder, // ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); // TODO: Disable the dig transmitter - encoder_dig_setup(id, pixelClock, ATOM_ENCODER_CMD_SETUP); + encoder_dig_setup(connectorIndex, pixelClock, + ATOM_ENCODER_CMD_SETUP); // Setup and enable the dig encoder //atombios_dig_transmitter_setup(encoder, @@ -238,11 +240,11 @@ encoder_mode_set(uint8 id, uint32 pixelClock) //atombios_dig_transmitter_setup(encoder, // ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); // Disable the dig transmitter - encoder_dig_setup(id, pixelClock, ATOM_DISABLE); + encoder_dig_setup(connectorIndex, pixelClock, ATOM_DISABLE); // Disable the dig encoder /* setup and enable the encoder and transmitter */ - encoder_dig_setup(id, pixelClock, ATOM_ENABLE); + encoder_dig_setup(connectorIndex, pixelClock, ATOM_ENABLE); // Setup and enable the dig encoder //atombios_dig_transmitter_setup(encoder, @@ -275,10 +277,10 @@ encoder_mode_set(uint8 id, uint32 pixelClock) case ENCODER_OBJECT_ID_VT1623: case ENCODER_OBJECT_ID_HDMI_SI1930: if (info.dceMajor >= 4 && info.dceMinor >= 1) { - encoder_external_setup(id, pixelClock, + encoder_external_setup(connectorIndex, pixelClock, EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); } else { - encoder_external_setup(id, pixelClock, + encoder_external_setup(connectorIndex, pixelClock, ATOM_ENABLE); } break; @@ -291,9 +293,8 @@ encoder_mode_set(uint8 id, uint32 pixelClock) status_t -encoder_tv_setup(uint8 id, uint32 pixelClock, int command) +encoder_tv_setup(uint32 connectorIndex, uint32 pixelClock, int command) { - uint32 connectorIndex = gDisplay[id]->connectorIndex; uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags; TV_ENCODER_CONTROL_PS_ALLOCATION args; @@ -323,12 +324,10 @@ union lvds_encoder_control { status_t -encoder_digital_setup(uint8 id, uint32 pixelClock, int command) +encoder_digital_setup(uint32 connectorIndex, uint32 pixelClock, int command) { TRACE("%s\n", __func__); - uint32 connectorIndex = gDisplay[id]->connectorIndex; - union lvds_encoder_control args; memset(&args, 0, sizeof(args)); @@ -455,11 +454,10 @@ union dig_encoder_control { status_t -encoder_dig_setup(uint8 id, uint32 pixelClock, int command) +encoder_dig_setup(uint32 connectorIndex, uint32 pixelClock, int command) { radeon_shared_info &info = *gInfo->shared_info; - uint32 connectorIndex = gDisplay[id]->connectorIndex; uint32 encoderID = gConnector[connectorIndex]->encoder.objectID; union dig_encoder_control args; @@ -612,7 +610,7 @@ union external_encoder_control { status_t -encoder_external_setup(uint8 id, uint32 pixelClock, int command) +encoder_external_setup(uint32 connectorIndex, uint32 pixelClock, int command) { TRACE("%s\n", __func__); @@ -620,7 +618,6 @@ encoder_external_setup(uint8 id, uint32 pixelClock, int command) union external_encoder_control args; memset(&args, 0, sizeof(args)); - uint32 connectorIndex = gDisplay[id]->connectorIndex; int connectorObjectID = (gConnector[connectorIndex]->objectID & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; @@ -764,12 +761,10 @@ encoder_external_setup(uint8 id, uint32 pixelClock, int command) status_t -encoder_analog_setup(uint8 id, uint32 pixelClock, int command) +encoder_analog_setup(uint32 connectorIndex, uint32 pixelClock, int command) { TRACE("%s\n", __func__); - uint32 connectorIndex = gDisplay[id]->connectorIndex; - int index = 0; DAC_ENCODER_CONTROL_PS_ALLOCATION args; memset(&args, 0, sizeof(args)); @@ -797,7 +792,7 @@ encoder_analog_setup(uint8 id, uint32 pixelClock, int command) bool -encoder_analog_load_detect(uint8 connectorIndex) +encoder_analog_load_detect(uint32 connectorIndex) { uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags; uint32 encoderID = gConnector[connectorIndex]->encoder.objectID; diff --git a/src/add-ons/accelerants/radeon_hd/encoder.h b/src/add-ons/accelerants/radeon_hd/encoder.h index 3327aa0..66d5137 100644 --- a/src/add-ons/accelerants/radeon_hd/encoder.h +++ b/src/add-ons/accelerants/radeon_hd/encoder.h @@ -9,15 +9,21 @@ #define RADEON_HD_ENCODER_H -void encoder_assign_crtc(uint8 crt_id); +void encoder_assign_crtc(uint8 crtID); void encoder_apply_quirks(uint8 crtcID); void encoder_mode_set(uint8 id, uint32 pixelClock); -status_t encoder_analog_setup(uint8 id, uint32 pixelClock, int command); -status_t encoder_digital_setup(uint8 id, uint32 pixelClock, int command); -status_t encoder_dig_setup(uint8 id, uint32 pixelClock, int command); -status_t encoder_external_setup(uint8 id, uint32 pixelClock, int command); -status_t encoder_tv_setup(uint8 id, uint32 pixelClock, int command); -bool encoder_analog_load_detect(uint8 connectorIndex); +status_t encoder_analog_setup(uint32 connectorIndex, + uint32 pixelClock, int command); +status_t encoder_digital_setup(uint32 connectorIndex, + uint32 pixelClock, int command); +status_t encoder_dig_setup(uint32 connectorIndex, + uint32 pixelClock, int command); +status_t encoder_external_setup(uint32 connectorIndex, + uint32 pixelClock, int command); +status_t encoder_tv_setup(uint32 connectorIndex, + uint32 pixelClock, int command); + +bool encoder_analog_load_detect(uint32 connectorIndex); void encoder_output_lock(bool lock); void encoder_crtc_scratch(uint8 crtcID); void encoder_dpms_scratch(uint8 crtcID, bool power); ############################################################################ Revision: hrev43448 Commit: 654dc4bfabac752ddf61e5e55db77800dfccd531 URL: http://cgit.haiku-os.org/haiku/commit/?id=654dc4b Author: Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> Date: Fri Dec 9 22:47:26 2011 UTC Use bridge encoder flag vs making direct calls to check ---------------------------------------------------------------------------- diff --git a/src/add-ons/accelerants/radeon_hd/pll.cpp b/src/add-ons/accelerants/radeon_hd/pll.cpp index 555ed45..4fcd54c 100644 --- a/src/add-ons/accelerants/radeon_hd/pll.cpp +++ b/src/add-ons/accelerants/radeon_hd/pll.cpp @@ -342,7 +342,7 @@ pll_adjust(pll_info *pll, uint8 crtcID) bool dpBridge = false; if ((encoderFlags & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) - || encoder_is_dp_bridge(encoderID)) { + || gConnector[connectorIndex]->encoder.isDPBridge) { TRACE("%s: external DP bridge detected!\n", __func__); dpBridge = true; }