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
This commit is contained in:
Alexander von Gluck IV
2012-08-05 12:15:35 -05:00
parent f0e29955bf
commit 4e7e3e331d
7 changed files with 109 additions and 50 deletions
+4 -1
View File
@@ -40,7 +40,10 @@ typedef struct {
uint32 dp_encode_link_rate(uint32 linkRate); uint32 dp_encode_link_rate(uint32 linkRate);
uint32 dp_decode_link_rate(uint32 rawLinkRate); 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 */ #endif /* _DP_H */
+16 -27
View File
@@ -60,32 +60,21 @@ dp_decode_link_rate(uint32 rawLinkRate)
uint32 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; return (linkRate * laneCount * 8) / bpp;
size_t pixelsPerChunk; }
status_t result = get_pixel_size_for((color_space)mode->space, &pixelChunk,
NULL, &pixelsPerChunk);
uint32
if (result != B_OK) { dp_get_link_rate_max(dp_info* dpInfo)
TRACE("%s: Invalid color space!\n", __func__); {
return 0; return dp_decode_link_rate(dpInfo->config[DP_MAX_LINK_RATE]);
} }
uint32 bitsPerPixel = (pixelChunk / pixelsPerChunk) * 8;
uint32
uint32 maxLaneCount = dpInfo->config[DP_MAX_LANE_COUNT] dp_get_lane_count_max(dp_info* dpInfo)
& DP_MAX_LANE_COUNT_MASK; {
uint32 maxLinkRate = dp_decode_link_rate(dpInfo->config[DP_MAX_LINK_RATE]); return dpInfo->config[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK;
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;
} }
@@ -321,15 +321,81 @@ dp_aux_set_i2c_byte(uint32 hwPin, uint16 address, uint8* data, bool end)
uint32 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; uint16 encoderID = gConnector[connectorIndex]->encoderExternal.objectID;
if (encoderID == ENCODER_OBJECT_ID_NUTMEG) if (encoderID == ENCODER_OBJECT_ID_NUTMEG)
return 270000; return 270000;
// TODO: calculate DisplayPort max pixel clock based on bpp and DP channels dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo;
return 162000; 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; dpInfo->valid = true;
memcpy(dpInfo->config, auxMessage, 8); memcpy(dpInfo->config, auxMessage, 8);
} }
dpInfo->linkRate = dp_get_link_clock(index);
} }
} }
@@ -686,11 +750,10 @@ dp_link_train_ce(uint32 connectorIndex)
status_t status_t
dp_link_train(uint8 crtcID, display_mode* mode) dp_link_train(uint32 connectorIndex, display_mode* mode)
{ {
TRACE("%s\n", __func__); TRACE("%s\n", __func__);
uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
dp_info* dp = &gConnector[connectorIndex]->dpInfo; dp_info* dp = &gConnector[connectorIndex]->dpInfo;
if (dp->valid != true) { if (dp->valid != true) {
@@ -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, status_t dp_aux_get_i2c_byte(uint32 hwPin, uint16 address,
uint8* data, bool end); 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(); 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_cr(uint32 connectorIndex);
status_t dp_link_train_ce(uint32 connectorIndex); status_t dp_link_train_ce(uint32 connectorIndex);
+7 -5
View File
@@ -167,11 +167,13 @@ radeon_set_display_mode(display_mode* mode)
continue; continue;
uint32 connectorIndex = gDisplay[id]->connectorIndex; uint32 connectorIndex = gDisplay[id]->connectorIndex;
dp_info *dpInfo = &gConnector[connectorIndex]->dpInfo;
// Determine DP lanes if DP // Determine DP lanes if DP
if (connector_is_dp(connectorIndex)) if (connector_is_dp(connectorIndex)) {
dpInfo->laneCount = dp_get_lane_count(dpInfo, mode); 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 // *** crtc and encoder prep
encoder_output_lock(true); encoder_output_lock(true);
@@ -184,7 +186,7 @@ radeon_set_display_mode(display_mode* mode)
// *** CRT controler mode set // *** CRT controler mode set
// TODO: program SS // 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 // TODO: check if ATOM_PPLL1 is used and use ATOM_PPLL2 if so
display_crtc_set_dtd(id, mode); display_crtc_set_dtd(id, mode);
@@ -207,7 +209,7 @@ radeon_set_display_mode(display_mode* mode)
encoder_dig_setup(connectorIndex, encoder_dig_setup(connectorIndex,
ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
dp_link_train(id, mode); dp_link_train(connectorIndex, mode);
if (info.dceMajor >= 4) if (info.dceMajor >= 4)
encoder_dig_setup(connectorIndex, encoder_dig_setup(connectorIndex,
+6 -6
View File
@@ -503,7 +503,7 @@ pll_setup_flags(pll_info* pll, uint8 crtcID)
status_t 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; radeon_shared_info &info = *gInfo->shared_info;
@@ -585,7 +585,7 @@ pll_adjust(pll_info* pll, uint8 crtcID)
|= DISPPLL_CONFIG_COHERENT_MODE; |= DISPPLL_CONFIG_COHERENT_MODE;
/* 16200 or 27000 */ /* 16200 or 27000 */
uint32 dpLinkSpeed uint32 dpLinkSpeed
= dp_get_link_clock(connectorIndex); = dp_get_link_rate(connectorIndex, mode);
args.v3.sInput.usPixelClock args.v3.sInput.usPixelClock
= B_HOST_TO_LENDIAN_INT16(dpLinkSpeed / 10); = B_HOST_TO_LENDIAN_INT16(dpLinkSpeed / 10);
} else if ((encoderFlags & ATOM_DEVICE_DFP_SUPPORT) } else if ((encoderFlags & ATOM_DEVICE_DFP_SUPPORT)
@@ -650,17 +650,17 @@ pll_adjust(pll_info* pll, uint8 crtcID)
status_t status_t
pll_set(uint8 pllID, uint32 pixelClock, uint8 crtcID) pll_set(uint8 pllID, display_mode* mode, uint8 crtcID)
{ {
uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
pll_info* pll = &gConnector[connectorIndex]->encoder.pll; pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
pll->pixelClock = pixelClock; pll->pixelClock = mode->timing.pixel_clock;
pll->id = pllID; pll->id = pllID;
pll_setup_flags(pll, crtcID); pll_setup_flags(pll, crtcID);
// set up any special flags // set up any special flags
pll_adjust(pll, crtcID); pll_adjust(pll, mode, crtcID);
// get any needed clock adjustments, set reference/post dividers // get any needed clock adjustments, set reference/post dividers
pll_compute(pll); pll_compute(pll);
// compute dividers // 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", 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); status_t result = atom_execute_table(gAtomContext, index, (uint32*)&args);
+3 -2
View File
@@ -9,6 +9,7 @@
#define RADEON_HD_PLL_H #define RADEON_HD_PLL_H
#include <Accelerant.h>
#include <SupportDefs.h> #include <SupportDefs.h>
@@ -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); status_t pll_compute(pll_info* pll);
void pll_setup_flags(pll_info* pll, uint8 crtcID); void pll_setup_flags(pll_info* pll, uint8 crtcID);
status_t pll_limit_probe(pll_info* pll); status_t pll_limit_probe(pll_info* pll);
status_t pll_dp_ss_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_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 */ #endif /* RADEON_HD_PLL_H */