diff --git a/src/add-ons/accelerants/radeon_hd/accelerant.h b/src/add-ons/accelerants/radeon_hd/accelerant.h index 3ff2606296..9e3dd5195c 100644 --- a/src/add-ons/accelerants/radeon_hd/accelerant.h +++ b/src/add-ons/accelerants/radeon_hd/accelerant.h @@ -130,10 +130,10 @@ typedef struct { typedef struct { bool valid; - uint8 dpConfig[8]; // DP configuration data - uint8 dpSinkType; - uint8 dpClock; - int dpLaneCount; + uint8 config[8]; // DP configuration data + uint8 sinkType; + uint8 clock; + int laneCount; bool eDPOn; } dp_info; diff --git a/src/add-ons/accelerants/radeon_hd/connector.cpp b/src/add-ons/accelerants/radeon_hd/connector.cpp index be18ee18f5..2bb5f3abbb 100644 --- a/src/add-ons/accelerants/radeon_hd/connector.cpp +++ b/src/add-ons/accelerants/radeon_hd/connector.cpp @@ -713,6 +713,18 @@ connector_probe() } +bool +connector_is_dp(uint32 connectorIndex) +{ + if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_DP + || gConnector[connectorIndex]->type != VIDEO_CONNECTOR_EDP + || gConnector[connectorIndex]->encoder.isDPBridge == false) { + return true; + } + return false; +} + + void debug_connectors() { diff --git a/src/add-ons/accelerants/radeon_hd/connector.h b/src/add-ons/accelerants/radeon_hd/connector.h index 6522ddbaf8..c51dc60f46 100644 --- a/src/add-ons/accelerants/radeon_hd/connector.h +++ b/src/add-ons/accelerants/radeon_hd/connector.h @@ -65,6 +65,7 @@ status_t connector_attach_gpio(uint32 id, uint8 hwPin); bool connector_read_edid(uint32 connector, edid1_info* edid); status_t connector_probe(); status_t connector_probe_legacy(); +bool connector_is_dp(uint32 connectorIndex); void debug_connectors(); diff --git a/src/add-ons/accelerants/radeon_hd/displayport.cpp b/src/add-ons/accelerants/radeon_hd/displayport.cpp index 7613109b5e..8673d03a73 100644 --- a/src/add-ons/accelerants/radeon_hd/displayport.cpp +++ b/src/add-ons/accelerants/radeon_hd/displayport.cpp @@ -13,7 +13,7 @@ #include "accelerant.h" #include "accelerant_protos.h" -#include "displayport_reg.h" +#include "connector.h" #undef TRACE @@ -333,6 +333,58 @@ dp_get_link_clock(uint32 connectorIndex) } +uint32 +dp_get_link_clock_encode(uint32 dpLinkClock) +{ + switch (dpLinkClock) { + case 270000: + return DP_LINK_BW_2_7; + case 540000: + return DP_LINK_BW_5_4; + } + + return DP_LINK_BW_1_62; +} + + +uint32 +dp_get_link_clock_decode(uint32 dpLinkClock) +{ + switch (dpLinkClock) { + case DP_LINK_BW_2_7: + return 270000; + case DP_LINK_BW_5_4: + return 540000; + } + return 162000; +} + + +static uint32 +dp_get_lane_count(uint32 connectorIndex, uint32 pixelClock) +{ + // TODO: bpp hardcoded + uint32 bitsPerPixel = 32; + + uint32 maxLaneCount = gDPInfo[connectorIndex]->config[DP_MAX_LANE_COUNT] + & DP_MAX_LANE_COUNT_MASK; + + uint32 maxLinkRate = dp_get_link_clock_decode( + gDPInfo[connectorIndex]->config[DP_MAX_LINK_RATE]); + + uint32 lane; + for (lane = 1; lane < maxLaneCount; lane <<= 1) { + uint32 maxDPPixelClock = (maxLinkRate * lane * 8) / bitsPerPixel; + if (pixelClock <= maxDPPixelClock) + break; + } + TRACE("%s: connector: %" B_PRIu32 ", lanes: %" B_PRIu32 "\n", __func__, + connectorIndex, lane); + + return lane; +} + + void dp_setup_connectors() { @@ -341,14 +393,12 @@ dp_setup_connectors() for (uint32 index = 0; index < ATOM_MAX_SUPPORTED_DEVICE; index++) { gDPInfo[index]->valid = false; if (gConnector[index]->valid == false) { - gDPInfo[index]->dpConfig[0] = 0; + gDPInfo[index]->config[0] = 0; continue; } - if (gConnector[index]->type != VIDEO_CONNECTOR_DP - && gConnector[index]->type != VIDEO_CONNECTOR_EDP - && gConnector[index]->encoder.isDPBridge == false) { - gDPInfo[index]->dpConfig[0] = 0; + if (connector_is_dp(index) == false) { + gDPInfo[index]->config[0] = 0; continue; } @@ -357,23 +407,18 @@ dp_setup_connectors() uint8 auxMessage[25]; int result; - int i; result = dp_aux_read(hwPin, DP_DPCD_REV, auxMessage, 8, 0); if (result > 0) { - memcpy(gDPInfo[index]->dpConfig, auxMessage, 8); - TRACE("%s: connector #%" B_PRIu32 " DP Config:\n", __func__, index); - for (i = 0; i < 8; i++) - TRACE("%s: %02x\n", __func__, auxMessage[i]); - gDPInfo[index]->valid = true; + memcpy(gDPInfo[index]->config, auxMessage, 8); } } } status_t -dp_link_train(uint8 crtcID) +dp_link_train(uint8 crtcID, display_mode* mode) { TRACE("%s\n", __func__); @@ -384,6 +429,10 @@ dp_link_train(uint8 crtcID) return B_ERROR; } + gDPInfo[connectorIndex]->clock = dp_get_link_clock(connectorIndex); + gDPInfo[connectorIndex]->laneCount + = dp_get_lane_count(connectorIndex, mode->timing.pixel_clock); + int index = GetIndexIntoMasterTable(COMMAND, DPEncoderService); // Table version uint8 tableMajor; @@ -405,7 +454,7 @@ dp_link_train(uint8 crtcID) uint32 hwPin = gGPIOInfo[gpioID]->hwPin; uint32 dpEncoderID = 0; - if (encoder_pick_dig(crtcID) > 0) + if (encoder_pick_dig(connectorIndex) > 0) dpEncoderID |= ATOM_DP_CONFIG_DIG2_ENCODER; else dpEncoderID |= ATOM_DP_CONFIG_DIG1_ENCODER; @@ -415,22 +464,66 @@ dp_link_train(uint8 crtcID) dpEncoderID |= ATOM_DP_CONFIG_LINK_A; //uint8 dpReadInterval = dpcd_reg_read(hwPin, DP_TRAINING_AUX_RD_INTERVAL); - uint8 dpMaxLanes = dpcd_reg_read(hwPin, DP_MAX_LANE_COUNT); + uint8 sandbox = dpcd_reg_read(hwPin, DP_MAX_LANE_COUNT); radeon_shared_info &info = *gInfo->shared_info; bool dpTPS3Supported = false; - if (info.dceMajor >= 5 && (dpMaxLanes & DP_TPS3_SUPPORTED) != 0) + if (info.dceMajor >= 5 && (sandbox & DP_TPS3_SUPPORTED) != 0) dpTPS3Supported = true; - // power up the DP sink - if (gDPInfo[connectorIndex]->dpConfig[0] >= 0x11) + // DisplayPort training initialization + + // Power up the DP sink + if (gDPInfo[connectorIndex]->config[0] >= 0x11) dpcd_reg_write(hwPin, DP_SET_POWER, DP_SET_POWER_D0); - // possibly enable downspread on the sink - if (gDPInfo[connectorIndex]->dpConfig[3] & 0x1) + // Possibly enable downspread on the sink + if ((gDPInfo[connectorIndex]->config[3] & 0x1) != 0) dpcd_reg_write(hwPin, DP_DOWNSPREAD_CTRL, DP_SPREAD_AMP_0_5); else dpcd_reg_write(hwPin, DP_DOWNSPREAD_CTRL, 0); + encoder_dig_setup(connectorIndex, 0, + ATOM_ENCODER_CMD_SETUP_PANEL_MODE); + + if (gDPInfo[connectorIndex]->config[0] >= 0x11) + sandbox |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + dpcd_reg_write(hwPin, DP_LANE_COUNT_SET, sandbox); + + // Set the link rate on the DP sink + sandbox = dp_get_link_clock_encode(gDPInfo[connectorIndex]->clock); + dpcd_reg_write(hwPin, DP_LINK_BW_SET, sandbox); + + // Start link training on source + if (info.dceMajor >= 4 || !dpUseEncoder) { + encoder_dig_setup(connectorIndex, 0, + ATOM_ENCODER_CMD_DP_LINK_TRAINING_START); + } else { + ERROR("%s: TODO: cannot use AtomBIOS DPEncoderService on card!\n", + __func__); + } + + /* disable the training pattern on the sink */ + dpcd_reg_write(hwPin, DP_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_DISABLE); + + // TODO: dp_link_train_cr + // TODO: dp_link_train_ce + + snooze(400); + + /* disable the training pattern on the sink */ + dpcd_reg_write(hwPin, DP_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_DISABLE); + + /* disable the training pattern on the source */ + if (info.dceMajor >= 4 || !dpUseEncoder) { + encoder_dig_setup(connectorIndex, 0, + ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE); + } else { + ERROR("%s: TODO: cannot use AtomBIOS DPEncoderService on card!\n", + __func__); + } + return B_OK; } diff --git a/src/add-ons/accelerants/radeon_hd/displayport.h b/src/add-ons/accelerants/radeon_hd/displayport.h index a81a1397c1..70c0708a13 100644 --- a/src/add-ons/accelerants/radeon_hd/displayport.h +++ b/src/add-ons/accelerants/radeon_hd/displayport.h @@ -9,9 +9,12 @@ #define RADEON_HD_DISPLAYPORT_H +#include #include #include +#include "displayport_reg.h" + int dp_aux_write(uint32 hwPin, uint16 address, uint8* send, uint8 sendBytes, uint8 delay); @@ -23,8 +26,11 @@ status_t dp_aux_get_i2c_byte(uint32 hwPin, uint16 address, uint8* data, bool end); uint32 dp_get_link_clock(uint32 connectorIndex); +uint32 dp_get_link_clock_encode(uint32 dpLinkClock); +uint32 dp_get_link_clock_decode(uint32 dpLinkClock); + void dp_setup_connectors(); -status_t dp_link_train(uint32 connectorIndex); +status_t dp_link_train(uint8 crtcID, display_mode* mode); #endif /* RADEON_HD_DISPLAYPORT_H */ diff --git a/src/add-ons/accelerants/radeon_hd/encoder.cpp b/src/add-ons/accelerants/radeon_hd/encoder.cpp index fe1968ac09..f8b3244efe 100644 --- a/src/add-ons/accelerants/radeon_hd/encoder.cpp +++ b/src/add-ons/accelerants/radeon_hd/encoder.cpp @@ -17,7 +17,9 @@ #include "accelerant.h" #include "accelerant_protos.h" #include "bios.h" +#include "connector.h" #include "display.h" +#include "displayport.h" #include "utility.h" @@ -113,7 +115,7 @@ encoder_assign_crtc(uint8 crtcID) case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - switch (encoder_pick_dig(crtcID)) { + switch (encoder_pick_dig(connectorIndex)) { case 0: args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; @@ -178,13 +180,21 @@ encoder_assign_crtc(uint8 crtcID) uint32 -encoder_pick_dig(uint8 crtcID) +encoder_pick_dig(uint32 connectorIndex) { TRACE("%s\n", __func__); radeon_shared_info &info = *gInfo->shared_info; - uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; uint32 encoderID = gConnector[connectorIndex]->encoder.objectID; + // obtain assigned CRT + uint32 crtcID; + for (crtcID = 0; crtcID < MAX_DISPLAY; crtcID++) { + if (gDisplay[crtcID]->active != true) + continue; + if (gDisplay[crtcID]->connectorIndex == connectorIndex) + break; + } + bool linkB = gConnector[connectorIndex]->encoder.linkEnumeration == GRAPH_OBJECT_ENUM_ID2 ? true : false; @@ -405,6 +415,9 @@ encoder_digital_setup(uint32 connectorIndex, uint32 pixelClock, int command) union lvdsEncoderControl args; memset(&args, 0, sizeof(args)); + TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__, + tableMajor, tableMinor); + switch (tableMajor) { case 1: case 2: @@ -499,10 +512,10 @@ encoder_dig_setup(uint32 connectorIndex, uint32 pixelClock, int command) if (info.dceMajor > 4) index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl); else { - if (1) // TODO: pick dig encoder - index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); - else + if (encoder_pick_dig(connectorIndex)) index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); + else + index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); } // Table verson @@ -525,124 +538,140 @@ encoder_dig_setup(uint32 connectorIndex, uint32 pixelClock, int command) union digEncoderControl args; memset(&args, 0, sizeof(args)); - args.v1.ucAction = command; - args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); - uint32 encoderID = gConnector[connectorIndex]->encoder.objectID; + bool isDPBridge = gConnector[connectorIndex]->encoder.isDPBridge; + + bool linkB = gConnector[connectorIndex]->encoder.linkEnumeration + == GRAPH_OBJECT_ENUM_ID2 ? true : false; + + // determine DP panel mode + uint32 panelMode; + if (info.dceMajor >= 4 && isDPBridge) { + if (encoderID == ENCODER_OBJECT_ID_NUTMEG) + panelMode = DP_PANEL_MODE_INTERNAL_DP1_MODE; + else { + // aka ENCODER_OBJECT_ID_TRAVIS or VIDEO_CONNECTOR_EDP + panelMode = DP_PANEL_MODE_INTERNAL_DP2_MODE; + } + } else + panelMode = DP_PANEL_MODE_EXTERNAL_DP_MODE; #if 0 - if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) { - if (info.dceMajor >= 4 && 0) // TODO: 0 == if DP bridge - args.v3.ucPanelMode = DP_PANEL_MODE_INTERNAL_DP1_MODE; - else - args.v3.ucPanelMode = DP_PANEL_MODE_EXTERNAL_DP_MODE; - } else { - args.v1.ucEncoderMode = display_get_encoder_mode(connectorIndex); - - if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP - || args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) { - args.v1.ucLaneNum = dp_lane_count; - } else if (pixelClock > 165000) - args.v1.ucLaneNum = 8; - else - args.v1.ucLaneNum = 4; - - if (info.dceMajor >= 5) { - if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP - || args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) { - if (dpClock == 270000) { - args.v1.ucConfig - |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ; - } else if (dpClock == 540000) { - args.v1.ucConfig - |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ; - } - } - args.v4.acConfig.ucDigSel = dig->dig_encoder; - switch (bpc) { - case 0: - args.v4.ucBitPerColor = PANEL_BPC_UNDEFINE; - break; - case 6: - args.v4.ucBitPerColor = PANEL_6BIT_PER_COLOR; - break; - case 8: - default: - args.v4.ucBitPerColor = PANEL_8BIT_PER_COLOR; - break; - case 10: - args.v4.ucBitPerColor = PANEL_10BIT_PER_COLOR; - break; - case 12: - args.v4.ucBitPerColor = PANEL_12BIT_PER_COLOR; - break; - case 16: - args.v4.ucBitPerColor = PANEL_16BIT_PER_COLOR; - break; - } - - //if (hpdID == RADEON_HPD_NONE) - if (1) - args.v4.ucHPD_ID = 0; - else - args.v4.ucHPD_ID = hpd_id + 1; - - } else if (info.dceMajor >= 4) { - if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP - && dp_clock == 270000) { - args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ; - } - - args.v3.acConfig.ucDigSel = dig->dig_encoder; - switch (bpc) { - case 0: - args.v3.ucBitPerColor = PANEL_BPC_UNDEFINE; - break; - case 6: - args.v3.ucBitPerColor = PANEL_6BIT_PER_COLOR; - break; - case 8: - default: - args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR; - break; - case 10: - args.v3.ucBitPerColor = PANEL_10BIT_PER_COLOR; - break; - case 12: - args.v3.ucBitPerColor = PANEL_12BIT_PER_COLOR; - break; - case 16: - args.v3.ucBitPerColor = PANEL_16BIT_PER_COLOR; - break; - } - - } else { - if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP - && dp_clock == 270000) { - args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; - } - #endif - switch (encoderID) { - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: - args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1; - break; - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; - break; - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: - args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; - break; - } - #if 0 - if (dig->linkb) - args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; - else - args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; + uint32 encoderID = gConnector[connectorIndex]->encoder.objectID; + if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_EDP) { + uint8 temp = dpcd_read_reg(hwPin, DP_EDP_CONFIGURATION_CAP); + if ((temp & 1) != 0) + panelMode = DP_PANEL_MODE_INTERNAL_DP2_MODE; } #endif - return atom_execute_table(gAtomContext, index, (uint32*)&args); + TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__, + tableMajor, tableMinor); + + uint32 dpClock = dp_get_link_clock(connectorIndex); + switch (tableMinor) { + case 1: + args.v1.ucAction = command; + args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); + + if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) + args.v3.ucPanelMode = panelMode; + else { + args.v1.ucEncoderMode + = display_get_encoder_mode(connectorIndex); + } + + if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP + || args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) + && dpClock == 270000) { + args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; + } + + switch (encoderID) { + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; + break; + } + + if (linkB) + args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; + else + args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; + break; + case 2: + case 3: + args.v1.ucAction = command; + args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); + + if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) + args.v3.ucPanelMode = panelMode; + else { + args.v3.ucEncoderMode + = display_get_encoder_mode(connectorIndex); + } + + if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP + || args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) { + args.v1.ucLaneNum = gDPInfo[connectorIndex]->laneCount; + } else if (pixelClock > 165000) + args.v1.ucLaneNum = 8; + else + args.v1.ucLaneNum = 4; + + if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP + || args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) + && dpClock == 270000) { + args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; + } + + args.v3.acConfig.ucDigSel = encoder_pick_dig(connectorIndex); + + // TODO: get BPC + switch (8) { + case 0: + args.v4.ucBitPerColor = PANEL_BPC_UNDEFINE; + break; + case 6: + args.v4.ucBitPerColor = PANEL_6BIT_PER_COLOR; + break; + case 8: + default: + args.v4.ucBitPerColor = PANEL_8BIT_PER_COLOR; + break; + case 10: + args.v4.ucBitPerColor = PANEL_10BIT_PER_COLOR; + break; + case 12: + args.v4.ucBitPerColor = PANEL_12BIT_PER_COLOR; + break; + case 16: + args.v4.ucBitPerColor = PANEL_16BIT_PER_COLOR; + break; + } + break; + case 4: + args.v4.ucHPD_ID = 0; + ERROR("%s: tableMinor 4 TODO!\n", __func__); + break; + } + + status_t result = atom_execute_table(gAtomContext, index, (uint32*)&args); + + #if 0 + if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_EDP + && panelMode == DP_PANEL_MODE_INTERNAL_DP2_MODE) { + dpcd_write_reg(hwPin, DP_EDP_CONFIGURATION_SET, 1); + } + #endif + + return result; } @@ -673,6 +702,8 @@ encoder_external_setup(uint32 connectorIndex, uint32 pixelClock, int command) = (gConnector[connectorIndex]->objectID & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; + TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__, + tableMajor, tableMinor); switch (tableMajor) { case 1: // no options needed on table 1.x @@ -1053,7 +1084,7 @@ encoder_dpms_scratch(uint8 crtcID, bool power) void encoder_dpms_set(uint8 crtcID, uint8 encoderID, int mode) { - int index = 0; + int index = -1; radeon_shared_info &info = *gInfo->shared_info; DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args; @@ -1116,29 +1147,25 @@ encoder_dpms_set(uint8 crtcID, uint8 encoderID, int mode) switch (mode) { case B_DPMS_ON: args.ucAction = ATOM_ENABLE; - atom_execute_table(gAtomContext, index, (uint32*)&args); - if (info.dceMajor < 5) { - if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { - args.ucAction = ATOM_LCD_BLON; - atom_execute_table(gAtomContext, index, (uint32*)&args); - } - encoder_dpms_scratch(crtcID, true); - } break; case B_DPMS_STAND_BY: case B_DPMS_SUSPEND: case B_DPMS_OFF: args.ucAction = ATOM_DISABLE; - atom_execute_table(gAtomContext, index, (uint32*)&args); - if (info.dceMajor < 5) { - if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { - args.ucAction = ATOM_LCD_BLOFF; - atom_execute_table(gAtomContext, index, (uint32*)&args); - } - encoder_dpms_scratch(crtcID, false); - } break; } + + if (index >= 0) { + atom_execute_table(gAtomContext, index, (uint32*)&args); + if (info.dceMajor < 5) { + if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { + args.ucAction = args.ucAction == ATOM_DISABLE + ? ATOM_LCD_BLOFF : ATOM_LCD_BLON; + atom_execute_table(gAtomContext, index, (uint32*)&args); + } + encoder_dpms_scratch(crtcID, true); + } + } } diff --git a/src/add-ons/accelerants/radeon_hd/encoder.h b/src/add-ons/accelerants/radeon_hd/encoder.h index 284eb5d5af..34a6522d79 100644 --- a/src/add-ons/accelerants/radeon_hd/encoder.h +++ b/src/add-ons/accelerants/radeon_hd/encoder.h @@ -13,7 +13,7 @@ void encoder_assign_crtc(uint8 crtcID); -uint32 encoder_pick_dig(uint8 crtcID); +uint32 encoder_pick_dig(uint32 connectorIndex); void encoder_apply_quirks(uint8 crtcID); void encoder_mode_set(uint8 id, uint32 pixelClock); diff --git a/src/add-ons/accelerants/radeon_hd/mode.cpp b/src/add-ons/accelerants/radeon_hd/mode.cpp index d609c7a2de..ca2692940e 100644 --- a/src/add-ons/accelerants/radeon_hd/mode.cpp +++ b/src/add-ons/accelerants/radeon_hd/mode.cpp @@ -21,7 +21,9 @@ #include "accelerant.h" #include "accelerant_protos.h" #include "bios.h" +#include "connector.h" #include "display.h" +#include "displayport.h" #include "encoder.h" #include "pll.h" #include "utility.h" @@ -204,8 +206,23 @@ radeon_set_display_mode(display_mode* mode) display_crtc_lock(id, ATOM_DISABLE); // *** encoder commit + + // handle DisplayPort link training + if (connector_is_dp(connectorIndex)) { + if (info.dceMajor >= 4) + encoder_dig_setup(connectorIndex, + ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); + + dp_link_train(id, mode); + + if (info.dceMajor >= 4) + encoder_dig_setup(connectorIndex, + ATOM_ENCODER_CMD_DP_VIDEO_ON, 0); + } + encoder_dpms_set(id, gConnector[connectorIndex]->encoder.objectID, B_DPMS_ON); + encoder_output_lock(false); } diff --git a/src/add-ons/accelerants/radeon_hd/pll.cpp b/src/add-ons/accelerants/radeon_hd/pll.cpp index bcc1c3bf8e..c6f8b2cb2d 100644 --- a/src/add-ons/accelerants/radeon_hd/pll.cpp +++ b/src/add-ons/accelerants/radeon_hd/pll.cpp @@ -492,7 +492,7 @@ pll_set(uint8 pllID, uint32 pixelClock, uint8 crtcID) int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor); - uint32 bitsPerChannel = 8; + uint32 bitsPerColor = 8; // TODO: Digital Depth, EDID 1.4+ on digital displays // isn't in Haiku edid common code? @@ -558,7 +558,7 @@ pll_set(uint8 pllID, uint32 pixelClock, uint8 crtcID) args.v5.ucMiscInfo = 0; /* HDMI depth, etc. */ // if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK)) // args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_REF_DIV_SRC; - switch (bitsPerChannel) { + switch (bitsPerColor) { case 8: default: args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_24BPP; @@ -584,7 +584,7 @@ pll_set(uint8 pllID, uint32 pixelClock, uint8 crtcID) args.v6.ucMiscInfo = 0; /* HDMI depth, etc. */ // if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK)) // args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_REF_DIV_SRC; - switch (bitsPerChannel) { + switch (bitsPerColor) { case 8: default: args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_24BPP;