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:
parent
f0e29955bf
commit
4e7e3e331d
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user