From 4e7e3e331d4b0d1edfb94f52507b04163dc001f8 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sun, 5 Aug 2012 12:15:35 -0500 Subject: [PATCH] radeon_hd: display port improvements * Remove non-generic radeon dp_get_lane_count * Set lane count and link rate at set_display_mode * Pass entire mode to pll_set vs only pixel clock for DP code * Add helpers for DP config data to common code * Obtain more correct link rate --- headers/private/graphics/common/dp.h | 5 +- src/add-ons/accelerants/common/dp.cpp | 43 ++++------- .../accelerants/radeon_hd/displayport.cpp | 77 +++++++++++++++++-- .../accelerants/radeon_hd/displayport.h | 5 +- src/add-ons/accelerants/radeon_hd/mode.cpp | 12 +-- src/add-ons/accelerants/radeon_hd/pll.cpp | 12 +-- src/add-ons/accelerants/radeon_hd/pll.h | 5 +- 7 files changed, 109 insertions(+), 50 deletions(-) diff --git a/headers/private/graphics/common/dp.h b/headers/private/graphics/common/dp.h index e9d2396196..149da7e895 100644 --- a/headers/private/graphics/common/dp.h +++ b/headers/private/graphics/common/dp.h @@ -40,7 +40,10 @@ typedef struct { uint32 dp_encode_link_rate(uint32 linkRate); uint32 dp_decode_link_rate(uint32 rawLinkRate); -uint32 dp_get_lane_count(dp_info* dpInfo, display_mode* mode); +uint32 dp_get_lane_count_max(dp_info* dpInfo); +uint32 dp_get_link_rate_max(dp_info* dpInfo); + +uint32 dp_get_pixel_clock_max(int linkRate, int laneCount, int bpp); #endif /* _DP_H */ diff --git a/src/add-ons/accelerants/common/dp.cpp b/src/add-ons/accelerants/common/dp.cpp index 8b9c5764fd..9cd31b5b77 100644 --- a/src/add-ons/accelerants/common/dp.cpp +++ b/src/add-ons/accelerants/common/dp.cpp @@ -60,32 +60,21 @@ dp_decode_link_rate(uint32 rawLinkRate) uint32 -dp_get_lane_count(dp_info* dpInfo, display_mode* mode) +dp_get_pixel_clock_max(int linkRate, int laneCount, int bpp) { - size_t pixelChunk; - size_t pixelsPerChunk; - status_t result = get_pixel_size_for((color_space)mode->space, &pixelChunk, - NULL, &pixelsPerChunk); - - if (result != B_OK) { - TRACE("%s: Invalid color space!\n", __func__); - return 0; - } - - uint32 bitsPerPixel = (pixelChunk / pixelsPerChunk) * 8; - - uint32 maxLaneCount = dpInfo->config[DP_MAX_LANE_COUNT] - & DP_MAX_LANE_COUNT_MASK; - uint32 maxLinkRate = dp_decode_link_rate(dpInfo->config[DP_MAX_LINK_RATE]); - - uint32 lane; - for (lane = 1; lane < maxLaneCount; lane <<= 1) { - uint32 maxDPPixelClock = (maxLinkRate * lane * 8) / bitsPerPixel; - if (mode->timing.pixel_clock <= maxDPPixelClock) - break; - } - - TRACE("%s: Lanes: %" B_PRIu32 "\n", __func__, lane); - - return lane; + return (linkRate * laneCount * 8) / bpp; +} + + +uint32 +dp_get_link_rate_max(dp_info* dpInfo) +{ + return dp_decode_link_rate(dpInfo->config[DP_MAX_LINK_RATE]); +} + + +uint32 +dp_get_lane_count_max(dp_info* dpInfo) +{ + return dpInfo->config[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK; } diff --git a/src/add-ons/accelerants/radeon_hd/displayport.cpp b/src/add-ons/accelerants/radeon_hd/displayport.cpp index e291c2cf65..b442ab26d1 100644 --- a/src/add-ons/accelerants/radeon_hd/displayport.cpp +++ b/src/add-ons/accelerants/radeon_hd/displayport.cpp @@ -321,15 +321,81 @@ dp_aux_set_i2c_byte(uint32 hwPin, uint16 address, uint8* data, bool end) uint32 -dp_get_link_clock(uint32 connectorIndex) +dp_get_lane_count(uint32 connectorIndex, display_mode* mode) +{ + // Radeon specific + dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo; + + size_t pixelChunk; + size_t pixelsPerChunk; + status_t result = get_pixel_size_for((color_space)mode->space, &pixelChunk, + NULL, &pixelsPerChunk); + + if (result != B_OK) { + TRACE("%s: Invalid color space!\n", __func__); + return 0; + } + + uint32 bitsPerPixel = (pixelChunk / pixelsPerChunk) * 8; + + uint32 dpMaxLinkRate = dp_get_link_rate_max(dpInfo); + uint32 dpMaxLaneCount = dp_get_lane_count_max(dpInfo); + + uint32 lane; + for (lane = 1; lane < dpMaxLaneCount; lane <<= 1) { + uint32 maxPixelClock = dp_get_pixel_clock_max(dpMaxLinkRate, lane, + bitsPerPixel); + if (mode->timing.pixel_clock <= maxPixelClock) + break; + } + + TRACE("%s: Lanes: %" B_PRIu32 "\n", __func__, lane); + return lane; +} + + +uint32 +dp_get_link_rate(uint32 connectorIndex, display_mode* mode) { uint16 encoderID = gConnector[connectorIndex]->encoderExternal.objectID; if (encoderID == ENCODER_OBJECT_ID_NUTMEG) return 270000; - // TODO: calculate DisplayPort max pixel clock based on bpp and DP channels - return 162000; + dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo; + uint32 laneCount = dp_get_lane_count(connectorIndex, mode); + + size_t pixelChunk; + size_t pixelsPerChunk; + status_t result = get_pixel_size_for((color_space)mode->space, &pixelChunk, + NULL, &pixelsPerChunk); + + if (result != B_OK) { + TRACE("%s: Invalid color space!\n", __func__); + return 0; + } + + uint32 bitsPerPixel = (pixelChunk / pixelsPerChunk) * 8; + + uint32 maxPixelClock + = dp_get_pixel_clock_max(162000, laneCount, bitsPerPixel); + if (mode->timing.pixel_clock <= maxPixelClock) + return 162000; + + maxPixelClock = dp_get_pixel_clock_max(270000, laneCount, bitsPerPixel); + if (mode->timing.pixel_clock <= maxPixelClock) + return 270000; + + // TODO: DisplayPort 1.2 + #if 0 + if (is_dp12_capable(connectorIndex)) { + maxPixelClock = dp_get_pixel_clock_max(540000, laneCount, bitsPerPixel); + if (mode->timing.pixel_clock <= maxPixelClock) + return 540000; + } + #endif + + return dp_get_link_rate_max(dpInfo); } @@ -364,8 +430,6 @@ dp_setup_connectors() dpInfo->valid = true; memcpy(dpInfo->config, auxMessage, 8); } - - dpInfo->linkRate = dp_get_link_clock(index); } } @@ -686,11 +750,10 @@ dp_link_train_ce(uint32 connectorIndex) status_t -dp_link_train(uint8 crtcID, display_mode* mode) +dp_link_train(uint32 connectorIndex, display_mode* mode) { TRACE("%s\n", __func__); - uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; dp_info* dp = &gConnector[connectorIndex]->dpInfo; if (dp->valid != true) { diff --git a/src/add-ons/accelerants/radeon_hd/displayport.h b/src/add-ons/accelerants/radeon_hd/displayport.h index 570934a431..fe5f3b8d5e 100644 --- a/src/add-ons/accelerants/radeon_hd/displayport.h +++ b/src/add-ons/accelerants/radeon_hd/displayport.h @@ -31,11 +31,12 @@ status_t dp_aux_set_i2c_byte(uint32 hwPin, uint16 address, 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_rate(uint32 connectorIndex, display_mode* mode); +uint32 dp_get_lane_count(uint32 connectorIndex, display_mode* mode); void dp_setup_connectors(); -status_t dp_link_train(uint8 crtcID, display_mode* mode); +status_t dp_link_train(uint32 connectorIndex, display_mode* mode); status_t dp_link_train_cr(uint32 connectorIndex); status_t dp_link_train_ce(uint32 connectorIndex); diff --git a/src/add-ons/accelerants/radeon_hd/mode.cpp b/src/add-ons/accelerants/radeon_hd/mode.cpp index c0b5c3d773..03176397a4 100644 --- a/src/add-ons/accelerants/radeon_hd/mode.cpp +++ b/src/add-ons/accelerants/radeon_hd/mode.cpp @@ -167,11 +167,13 @@ radeon_set_display_mode(display_mode* mode) continue; uint32 connectorIndex = gDisplay[id]->connectorIndex; - dp_info *dpInfo = &gConnector[connectorIndex]->dpInfo; // Determine DP lanes if DP - if (connector_is_dp(connectorIndex)) - dpInfo->laneCount = dp_get_lane_count(dpInfo, mode); + if (connector_is_dp(connectorIndex)) { + dp_info *dpInfo = &gConnector[connectorIndex]->dpInfo; + dpInfo->laneCount = dp_get_lane_count(connectorIndex, mode); + dpInfo->linkRate = dp_get_link_rate(connectorIndex, mode); + } // *** crtc and encoder prep encoder_output_lock(true); @@ -184,7 +186,7 @@ radeon_set_display_mode(display_mode* mode) // *** CRT controler mode set // TODO: program SS - pll_set(ATOM_PPLL1, mode->timing.pixel_clock, id); + pll_set(ATOM_PPLL1, mode, id); // TODO: check if ATOM_PPLL1 is used and use ATOM_PPLL2 if so display_crtc_set_dtd(id, mode); @@ -207,7 +209,7 @@ radeon_set_display_mode(display_mode* mode) encoder_dig_setup(connectorIndex, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); - dp_link_train(id, mode); + dp_link_train(connectorIndex, mode); if (info.dceMajor >= 4) encoder_dig_setup(connectorIndex, diff --git a/src/add-ons/accelerants/radeon_hd/pll.cpp b/src/add-ons/accelerants/radeon_hd/pll.cpp index 167f507003..829a367625 100644 --- a/src/add-ons/accelerants/radeon_hd/pll.cpp +++ b/src/add-ons/accelerants/radeon_hd/pll.cpp @@ -503,7 +503,7 @@ pll_setup_flags(pll_info* pll, uint8 crtcID) status_t -pll_adjust(pll_info* pll, uint8 crtcID) +pll_adjust(pll_info* pll, display_mode* mode, uint8 crtcID) { radeon_shared_info &info = *gInfo->shared_info; @@ -585,7 +585,7 @@ pll_adjust(pll_info* pll, uint8 crtcID) |= DISPPLL_CONFIG_COHERENT_MODE; /* 16200 or 27000 */ uint32 dpLinkSpeed - = dp_get_link_clock(connectorIndex); + = dp_get_link_rate(connectorIndex, mode); args.v3.sInput.usPixelClock = B_HOST_TO_LENDIAN_INT16(dpLinkSpeed / 10); } else if ((encoderFlags & ATOM_DEVICE_DFP_SUPPORT) @@ -650,17 +650,17 @@ pll_adjust(pll_info* pll, uint8 crtcID) status_t -pll_set(uint8 pllID, uint32 pixelClock, uint8 crtcID) +pll_set(uint8 pllID, display_mode* mode, uint8 crtcID) { uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; pll_info* pll = &gConnector[connectorIndex]->encoder.pll; - pll->pixelClock = pixelClock; + pll->pixelClock = mode->timing.pixel_clock; pll->id = pllID; pll_setup_flags(pll, crtcID); // set up any special flags - pll_adjust(pll, crtcID); + pll_adjust(pll, mode, crtcID); // get any needed clock adjustments, set reference/post dividers pll_compute(pll); // compute dividers @@ -799,7 +799,7 @@ pll_set(uint8 pllID, uint32 pixelClock, uint8 crtcID) } TRACE("%s: set adjusted pixel clock %" B_PRIu32 " (was %" B_PRIu32 ")\n", - __func__, pll->pixelClock, pixelClock); + __func__, pll->pixelClock, mode->timing.pixel_clock); status_t result = atom_execute_table(gAtomContext, index, (uint32*)&args); diff --git a/src/add-ons/accelerants/radeon_hd/pll.h b/src/add-ons/accelerants/radeon_hd/pll.h index be358572f4..128e6c03ee 100644 --- a/src/add-ons/accelerants/radeon_hd/pll.h +++ b/src/add-ons/accelerants/radeon_hd/pll.h @@ -9,6 +9,7 @@ #define RADEON_HD_PLL_H +#include #include @@ -99,13 +100,13 @@ struct pll_info { }; -status_t pll_adjust(pll_info* pll, uint8 crtcID); +status_t pll_adjust(pll_info* pll, display_mode* mode, uint8 crtcID); status_t pll_compute(pll_info* pll); void pll_setup_flags(pll_info* pll, uint8 crtcID); status_t pll_limit_probe(pll_info* pll); status_t pll_dp_ss_probe(pll_info* pll); status_t pll_asic_ss_probe(pll_info* pll); -status_t pll_set(uint8 pllID, uint32 pixelClock, uint8 crtcID); +status_t pll_set(uint8 pllID, display_mode* mode, uint8 crtcID); #endif /* RADEON_HD_PLL_H */