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

View File

@ -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 */

View File

@ -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;
}

View File

@ -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) {

View File

@ -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);

View File

@ -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,

View File

@ -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);

View File

@ -9,6 +9,7 @@
#define RADEON_HD_PLL_H
#include <Accelerant.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);
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 */