diff --git a/src/add-ons/accelerants/radeon_hd/display.cpp b/src/add-ons/accelerants/radeon_hd/display.cpp index 5c2ff1a745..3478e791b3 100644 --- a/src/add-ons/accelerants/radeon_hd/display.cpp +++ b/src/add-ons/accelerants/radeon_hd/display.cpp @@ -320,7 +320,7 @@ detect_connectors_legacy() gConnector[connectorIndex]->encoder.type = encoder_type_lookup(encoderID, (1 << i)); gConnector[connectorIndex]->encoder.isExternal - = encoder_isexternal(encoderID); + = encoder_is_external(encoderID); radeon_gpu_i2c_attach(connectorIndex, ci.sucI2cId.ucAccess); @@ -519,7 +519,7 @@ detect_connectors() gConnector[connectorIndex]->encoder.type = encoderType; gConnector[connectorIndex]->encoder.isExternal - = encoder_isexternal(encoderID); + = encoder_is_external(encoderID); pll_limit_probe( &gConnector[connectorIndex]->encoder.pll); diff --git a/src/add-ons/accelerants/radeon_hd/encoder.cpp b/src/add-ons/accelerants/radeon_hd/encoder.cpp index 9160d66d00..e598f349b5 100644 --- a/src/add-ons/accelerants/radeon_hd/encoder.cpp +++ b/src/add-ons/accelerants/radeon_hd/encoder.cpp @@ -1250,7 +1250,7 @@ encoder_type_lookup(uint32 encoderID, uint32 connectorFlags) bool -encoder_isexternal(uint32 encoderID) +encoder_is_external(uint32 encoderID) { switch (encoderID) { case ENCODER_OBJECT_ID_SI170B: @@ -1267,3 +1267,26 @@ encoder_isexternal(uint32 encoderID) return false; } + + +bool +encoder_is_dp_bridge(uint32 encoderID) { + switch (encoderID) { + case ENCODER_OBJECT_ID_TRAVIS: + case ENCODER_OBJECT_ID_NUTMEG: + return true; + } + return false; +} + + +uint32 +encoder_get_dp_link_clock(uint32 connectorIndex) { + uint16 encoderID = gConnector[connectorIndex]->encoder.objectID; + + if (encoderID == ENCODER_OBJECT_ID_NUTMEG) + return 270000; + + // TODO: calculate DisplayPort max pixel clock based on bpp and DP channels + return 162000; +} diff --git a/src/add-ons/accelerants/radeon_hd/encoder.h b/src/add-ons/accelerants/radeon_hd/encoder.h index abe6b61741..6611931a5e 100644 --- a/src/add-ons/accelerants/radeon_hd/encoder.h +++ b/src/add-ons/accelerants/radeon_hd/encoder.h @@ -24,7 +24,9 @@ void encoder_dpms_scratch(uint8 crtcID, bool power); void encoder_dpms_set(uint8 crtcID, uint8 encoderID, int mode); uint32 encoder_object_lookup(uint32 encoderFlags, uint8 dacID); uint32 encoder_type_lookup(uint32 encoderID, uint32 connectorFlags); -bool encoder_isexternal(uint32 encoderID); +bool encoder_is_external(uint32 encoderID); +bool encoder_is_dp_bridge(uint32 encoderID); +uint32 encoder_get_dp_link_clock(uint32 connectorIndex); #endif /* RADEON_HD_ENCODER_H */ diff --git a/src/add-ons/accelerants/radeon_hd/pll.cpp b/src/add-ons/accelerants/radeon_hd/pll.cpp index 610874e116..a666c42fbb 100644 --- a/src/add-ons/accelerants/radeon_hd/pll.cpp +++ b/src/add-ons/accelerants/radeon_hd/pll.cpp @@ -338,6 +338,15 @@ pll_adjust(pll_info *pll, uint8 crtcID) uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; uint32 encoderID = gConnector[connectorIndex]->encoder.objectID; uint32 encoderMode = display_get_encoder_mode(connectorIndex); + uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags; + bool dpBridge = false; + + if ((encoderFlags & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) + || encoder_is_dp_bridge(encoderID)) { + TRACE("%s: external DP bridge detected!\n", __func__); + dpBridge = true; + } + if (info.dceMajor >= 3) { union adjust_pixel_clock args; @@ -385,13 +394,43 @@ pll_adjust(pll_info *pll, uint8 crtcID) args.v3.sInput.ucDispPllConfig |= DISPPLL_CONFIG_SS_ENABLE; } - // TODO: if ATOM_DEVICE_DFP_SUPPORT - // TODO: display port DP - // TODO: is DP? - args.v3.sInput.ucExtTransmitterID = 0; + // Handle DP adjustments + if (encoderMode == ATOM_ENCODER_MODE_DP + || encoderMode == ATOM_ENCODER_MODE_DP_MST) { + TRACE("%s: encoderMode is DP\n", __func__); + args.v3.sInput.ucDispPllConfig + |= DISPPLL_CONFIG_COHERENT_MODE; + /* 16200 or 27000 */ + uint32 dpLinkSpeed + = encoder_get_dp_link_clock(connectorIndex); + args.v3.sInput.usPixelClock + = B_LENDIAN_TO_HOST_INT16(dpLinkSpeed / 10); + } else if ((encoderFlags & ATOM_DEVICE_DFP_SUPPORT) + != 0) { + TRACE("%s: encoderFlags are DFP but not DP mode.\n", + __func__); + #if 0 + if (encoderMode == ATOM_ENCODER_MODE_HDMI) { + /* deep color support */ + args.v3.sInput.usPixelClock = + cpu_to_le16((mode->clock * bpc / 8) / 10); + } + #endif + if (pixelClock > 165000) { + args.v3.sInput.ucDispPllConfig + |= DISPPLL_CONFIG_DUAL_LINK; + } + if (1) { // dig coherent mode? + args.v3.sInput.ucDispPllConfig + |= DISPPLL_CONFIG_COHERENT_MODE; + } + } + + args.v3.sInput.ucExtTransmitterID = dpBridge ? 1 : 0; atom_execute_table(gAtomContext, index, (uint32*)&args); + // get returned adjusted clock pll->pixelClock = B_LENDIAN_TO_HOST_INT32(