radeon_hd: clean up clock units
* Ensure we store all clock units as khz or n * 10 off from AtomBIOS unit expected * Perform DDC setup of external encoder
This commit is contained in:
@@ -72,7 +72,7 @@ struct accelerant_info {
|
|||||||
|
|
||||||
volatile uint32 dpms_mode; // current driver dpms mode
|
volatile uint32 dpms_mode; // current driver dpms mode
|
||||||
|
|
||||||
uint16 maximumPixelClock;
|
uint32 maximumPixelClock;
|
||||||
uint32 displayClockFrequency;
|
uint32 displayClockFrequency;
|
||||||
uint32 dpExternalClock;
|
uint32 dpExternalClock;
|
||||||
|
|
||||||
@@ -138,7 +138,7 @@ struct encoder_info {
|
|||||||
bool valid;
|
bool valid;
|
||||||
uint16 objectID;
|
uint16 objectID;
|
||||||
uint32 type;
|
uint32 type;
|
||||||
uint16 capabilities;
|
uint32 capabilities;
|
||||||
uint32 linkEnumeration; // ex. linkb == GRAPH_OBJECT_ENUM_ID2
|
uint32 linkEnumeration; // ex. linkb == GRAPH_OBJECT_ENUM_ID2
|
||||||
bool isExternal;
|
bool isExternal;
|
||||||
bool isDPBridge;
|
bool isDPBridge;
|
||||||
|
|||||||
@@ -267,29 +267,26 @@ detect_displays()
|
|||||||
if (gConnector[id]->type == VIDEO_CONNECTOR_DP) {
|
if (gConnector[id]->type == VIDEO_CONNECTOR_DP) {
|
||||||
TRACE("%s: connector(%" B_PRIu32 "): Checking DP.\n", __func__, id);
|
TRACE("%s: connector(%" B_PRIu32 "): Checking DP.\n", __func__, id);
|
||||||
|
|
||||||
|
if (gConnector[id]->encoderExternal.valid == true) {
|
||||||
|
// If this has a valid external encoder (dp bridge)
|
||||||
|
// normally TRAVIS (LVDS) or NUTMEG (VGA)
|
||||||
|
TRACE("%s: external encoder, performing bridge DDC setup\n",
|
||||||
|
__func__);
|
||||||
|
encoder_external_setup(id,
|
||||||
|
EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP);
|
||||||
|
}
|
||||||
edid1_info* edid = &gDisplay[displayIndex]->edidData;
|
edid1_info* edid = &gDisplay[displayIndex]->edidData;
|
||||||
gDisplay[displayIndex]->attached
|
gDisplay[displayIndex]->attached
|
||||||
= ddc2_dp_read_edid1(id, edid);
|
= ddc2_dp_read_edid1(id, edid);
|
||||||
|
|
||||||
|
// TODO: DDC Router switching for DisplayPort (and others?)
|
||||||
|
|
||||||
if (gDisplay[displayIndex]->attached) {
|
if (gDisplay[displayIndex]->attached) {
|
||||||
TRACE("%s: connector(%" B_PRIu32 "): Found DisplayPort EDID!\n",
|
TRACE("%s: connector(%" B_PRIu32 "): Found DisplayPort EDID!\n",
|
||||||
__func__);
|
__func__);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Handle external DP brides - ??
|
|
||||||
#if 0
|
|
||||||
if (gConnector[id]->encoderExternal.isDPBridge == true) {
|
|
||||||
// If this is a DisplayPort Bridge, setup ddc on bus
|
|
||||||
// TRAVIS (LVDS) or NUTMEG (VGA)
|
|
||||||
TRACE("%s: is bridge, performing bridge DDC setup\n", __func__);
|
|
||||||
encoder_external_setup(id, 23860,
|
|
||||||
EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP);
|
|
||||||
gDisplay[displayIndex]->attached = true;
|
|
||||||
|
|
||||||
// TODO: DDC Router switching for DisplayPort (and others?)
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (gConnector[id]->type == VIDEO_CONNECTOR_LVDS) {
|
if (gConnector[id]->type == VIDEO_CONNECTOR_LVDS) {
|
||||||
display_mode preferredMode;
|
display_mode preferredMode;
|
||||||
|
|||||||
@@ -970,7 +970,7 @@ dp_is_dp12_capable(uint32 connectorIndex)
|
|||||||
uint32 capabilities = gConnector[connectorIndex]->encoder.capabilities;
|
uint32 capabilities = gConnector[connectorIndex]->encoder.capabilities;
|
||||||
|
|
||||||
if (info.dceMajor >= 5
|
if (info.dceMajor >= 5
|
||||||
&& gInfo->dpExternalClock >= 53900
|
&& gInfo->dpExternalClock >= 539000
|
||||||
&& (capabilities & ATOM_ENCODER_CAP_RECORD_HBR2) != 0) {
|
&& (capabilities & ATOM_ENCODER_CAP_RECORD_HBR2) != 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,21 +68,24 @@ radeon_gpu_probe()
|
|||||||
if (info.dceMajor >= 4) {
|
if (info.dceMajor >= 4) {
|
||||||
gInfo->displayClockFrequency = B_LENDIAN_TO_HOST_INT32(
|
gInfo->displayClockFrequency = B_LENDIAN_TO_HOST_INT32(
|
||||||
firmwareInfo->info_21.ulDefaultDispEngineClkFreq);
|
firmwareInfo->info_21.ulDefaultDispEngineClkFreq);
|
||||||
|
gInfo->displayClockFrequency *= 10;
|
||||||
if (gInfo->displayClockFrequency == 0) {
|
if (gInfo->displayClockFrequency == 0) {
|
||||||
if (info.dceMajor >= 5)
|
if (info.dceMajor >= 5)
|
||||||
gInfo->displayClockFrequency = 54000;
|
gInfo->displayClockFrequency = 540000;
|
||||||
else
|
else
|
||||||
gInfo->displayClockFrequency = 60000;
|
gInfo->displayClockFrequency = 600000;
|
||||||
}
|
}
|
||||||
gInfo->dpExternalClock = B_LENDIAN_TO_HOST_INT16(
|
gInfo->dpExternalClock = B_LENDIAN_TO_HOST_INT16(
|
||||||
firmwareInfo->info_21.usUniphyDPModeExtClkFreq);
|
firmwareInfo->info_21.usUniphyDPModeExtClkFreq);
|
||||||
|
gInfo->dpExternalClock *= 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
gInfo->maximumPixelClock = B_LENDIAN_TO_HOST_INT16(
|
gInfo->maximumPixelClock = B_LENDIAN_TO_HOST_INT16(
|
||||||
firmwareInfo->info.usMaxPixelClock);
|
firmwareInfo->info.usMaxPixelClock);
|
||||||
|
gInfo->maximumPixelClock *= 10;
|
||||||
|
|
||||||
if (gInfo->maximumPixelClock == 0)
|
if (gInfo->maximumPixelClock == 0)
|
||||||
gInfo->maximumPixelClock = 40000;
|
gInfo->maximumPixelClock = 400000;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,16 @@ extern "C" void _sPrintf(const char* format, ...);
|
|||||||
|
|
||||||
#define ERROR(x...) _sPrintf("radeon_hd: " x)
|
#define ERROR(x...) _sPrintf("radeon_hd: " x)
|
||||||
|
|
||||||
|
// Pixel Clock Storage
|
||||||
|
// kHz Value Result
|
||||||
|
// Haiku: 104000 khz 104 Mhz
|
||||||
|
// Linux: 104000 khz 104 Mhz
|
||||||
|
// AtomBIOS: 10400 * 10 khz 104 Mhz
|
||||||
|
// Ghz
|
||||||
|
// Haiku: 162000 * 10 khz 1.62 Ghz
|
||||||
|
// Linux: 162000 * 10 khz 1.62 Ghz
|
||||||
|
// AtomBIOS: 16200 * 10 Khz 0.162 * 10 Ghz
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
pll_limit_probe(pll_info* pll)
|
pll_limit_probe(pll_info* pll)
|
||||||
@@ -118,9 +128,9 @@ pll_limit_probe(pll_info* pll)
|
|||||||
pll->pllInMax = B_LENDIAN_TO_HOST_INT16(
|
pll->pllInMax = B_LENDIAN_TO_HOST_INT16(
|
||||||
firmwareInfo->info.usMaxPixelClockPLL_Input) * 10;
|
firmwareInfo->info.usMaxPixelClockPLL_Input) * 10;
|
||||||
|
|
||||||
TRACE("%s: referenceFreq: %" B_PRIu16 "; pllOutMin: %" B_PRIu16 "; "
|
TRACE("%s: referenceFreq: %" B_PRIu32 "; pllOutMin: %" B_PRIu32 "; "
|
||||||
" pllOutMax: %" B_PRIu16 "; pllInMin: %" B_PRIu16 ";"
|
" pllOutMax: %" B_PRIu32 "; pllInMin: %" B_PRIu32 ";"
|
||||||
"pllInMax: %" B_PRIu16 "\n", __func__, pll->referenceFreq,
|
"pllInMax: %" B_PRIu32 "\n", __func__, pll->referenceFreq,
|
||||||
pll->pllOutMin, pll->pllOutMax, pll->pllInMin, pll->pllInMax);
|
pll->pllOutMin, pll->pllOutMax, pll->pllInMin, pll->pllInMax);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -205,7 +215,7 @@ pll_asic_ss_probe(pll_info* pll, uint32 ssID)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
TRACE("%s: ss match found\n", __func__);
|
TRACE("%s: ss match found\n", __func__);
|
||||||
if (pll->pixelClock > B_LENDIAN_TO_HOST_INT32(
|
if (pll->pixelClock * 10 > B_LENDIAN_TO_HOST_INT32(
|
||||||
ss_info->info.asSpreadSpectrum[i].ulTargetClockRange)) {
|
ss_info->info.asSpreadSpectrum[i].ulTargetClockRange)) {
|
||||||
TRACE("%s: pixelClock > targetClockRange!\n", __func__);
|
TRACE("%s: pixelClock > targetClockRange!\n", __func__);
|
||||||
continue;
|
continue;
|
||||||
@@ -232,7 +242,7 @@ pll_asic_ss_probe(pll_info* pll, uint32 ssID)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
TRACE("%s: ss match found\n", __func__);
|
TRACE("%s: ss match found\n", __func__);
|
||||||
if (pll->pixelClock > B_LENDIAN_TO_HOST_INT32(
|
if (pll->pixelClock * 10 > B_LENDIAN_TO_HOST_INT32(
|
||||||
ss_info->info_2.asSpreadSpectrum[i].ulTargetClockRange)) {
|
ss_info->info_2.asSpreadSpectrum[i].ulTargetClockRange)) {
|
||||||
TRACE("%s: pixelClock > targetClockRange!\n", __func__);
|
TRACE("%s: pixelClock > targetClockRange!\n", __func__);
|
||||||
continue;
|
continue;
|
||||||
@@ -260,7 +270,7 @@ pll_asic_ss_probe(pll_info* pll, uint32 ssID)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
TRACE("%s: ss match found\n", __func__);
|
TRACE("%s: ss match found\n", __func__);
|
||||||
if (pll->pixelClock > B_LENDIAN_TO_HOST_INT32(
|
if (pll->pixelClock * 10 > B_LENDIAN_TO_HOST_INT32(
|
||||||
ss_info->info_3.asSpreadSpectrum[i].ulTargetClockRange)) {
|
ss_info->info_3.asSpreadSpectrum[i].ulTargetClockRange)) {
|
||||||
TRACE("%s: pixelClock > targetClockRange!\n", __func__);
|
TRACE("%s: pixelClock > targetClockRange!\n", __func__);
|
||||||
continue;
|
continue;
|
||||||
@@ -433,11 +443,15 @@ pll_compute(pll_info* pll)
|
|||||||
+ (referenceFrequency * pll->feedbackDivFrac))
|
+ (referenceFrequency * pll->feedbackDivFrac))
|
||||||
/ (pll->referenceDiv * pll->postDiv * 10);
|
/ (pll->referenceDiv * pll->postDiv * 10);
|
||||||
|
|
||||||
TRACE("%s: pixel clock: %" B_PRIu32 " gives:"
|
TRACE("%s: Calculated pixel clock of %" B_PRIu32 " based on:\n", __func__,
|
||||||
" feedbackDivider = %" B_PRIu32 ".%" B_PRIu32
|
calculatedClock);
|
||||||
"; referenceDivider = %" B_PRIu32 "; postDivider = %" B_PRIu32 "\n",
|
TRACE("%s: referenceFrequency: %" B_PRIu32 "; "
|
||||||
__func__, pll->adjustedClock, pll->feedbackDiv, pll->feedbackDivFrac,
|
"referenceDivider: %" B_PRIu32 "\n", __func__, referenceFrequency,
|
||||||
pll->referenceDiv, pll->postDiv);
|
pll->referenceDiv);
|
||||||
|
TRACE("%s: feedbackDivider: %" B_PRIu32 "; "
|
||||||
|
"feedbackDividerFrac: %" B_PRIu32 "\n", __func__, pll->feedbackDiv,
|
||||||
|
pll->feedbackDivFrac);
|
||||||
|
TRACE("%s: postDivider: %" B_PRIu32 "\n", __func__, pll->postDiv);
|
||||||
|
|
||||||
if (pll->adjustedClock != calculatedClock) {
|
if (pll->adjustedClock != calculatedClock) {
|
||||||
TRACE("%s: pixel clock %" B_PRIu32 " was changed to %" B_PRIu32 "\n",
|
TRACE("%s: pixel clock %" B_PRIu32 " was changed to %" B_PRIu32 "\n",
|
||||||
@@ -579,9 +593,10 @@ pll_adjust(pll_info* pll, display_mode* mode, uint8 crtcID)
|
|||||||
TRACE("%s: encoderMode is DP\n", __func__);
|
TRACE("%s: encoderMode is DP\n", __func__);
|
||||||
args.v3.sInput.ucDispPllConfig
|
args.v3.sInput.ucDispPllConfig
|
||||||
|= DISPPLL_CONFIG_COHERENT_MODE;
|
|= DISPPLL_CONFIG_COHERENT_MODE;
|
||||||
/* 16200 or 27000 */
|
/* 162000 or 270000 */
|
||||||
uint32 dpLinkSpeed
|
uint32 dpLinkSpeed
|
||||||
= dp_get_link_rate(connectorIndex, mode);
|
= dp_get_link_rate(connectorIndex, mode);
|
||||||
|
/* 16200 or 27000 */
|
||||||
args.v3.sInput.usPixelClock
|
args.v3.sInput.usPixelClock
|
||||||
= B_HOST_TO_LENDIAN_INT16(dpLinkSpeed / 10);
|
= B_HOST_TO_LENDIAN_INT16(dpLinkSpeed / 10);
|
||||||
} else if ((connectorFlags & ATOM_DEVICE_DFP_SUPPORT)
|
} else if ((connectorFlags & ATOM_DEVICE_DFP_SUPPORT)
|
||||||
@@ -608,8 +623,7 @@ pll_adjust(pll_info* pll, display_mode* mode, uint8 crtcID)
|
|||||||
atom_execute_table(gAtomContext, index, (uint32*)&args);
|
atom_execute_table(gAtomContext, index, (uint32*)&args);
|
||||||
|
|
||||||
// get returned adjusted clock
|
// get returned adjusted clock
|
||||||
pll->adjustedClock
|
pll->adjustedClock = B_LENDIAN_TO_HOST_INT32(
|
||||||
= B_LENDIAN_TO_HOST_INT32(
|
|
||||||
args.v3.sOutput.ulDispPllFreq);
|
args.v3.sOutput.ulDispPllFreq);
|
||||||
pll->adjustedClock *= 10;
|
pll->adjustedClock *= 10;
|
||||||
// convert to kHz for storage
|
// convert to kHz for storage
|
||||||
@@ -650,7 +664,7 @@ pll_set(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;
|
||||||
uint32 dp_clock = gConnector[connectorIndex]->dpInfo.linkRate / 10;
|
uint32 dp_clock = gConnector[connectorIndex]->dpInfo.linkRate;
|
||||||
bool ssEnabled = false;
|
bool ssEnabled = false;
|
||||||
|
|
||||||
pll->pixelClock = mode->timing.pixel_clock;
|
pll->pixelClock = mode->timing.pixel_clock;
|
||||||
@@ -671,7 +685,7 @@ pll_set(display_mode* mode, uint8 crtcID)
|
|||||||
if (info.dceMajor >= 4)
|
if (info.dceMajor >= 4)
|
||||||
pll_asic_ss_probe(pll, ASIC_INTERNAL_SS_ON_DP);
|
pll_asic_ss_probe(pll, ASIC_INTERNAL_SS_ON_DP);
|
||||||
else {
|
else {
|
||||||
if (dp_clock == 16200) {
|
if (dp_clock == 162000) {
|
||||||
ssEnabled = pll_ppll_ss_probe(pll, ATOM_DP_SS_ID2);
|
ssEnabled = pll_ppll_ss_probe(pll, ATOM_DP_SS_ID2);
|
||||||
if (!ssEnabled)
|
if (!ssEnabled)
|
||||||
// id2 failed, try id1
|
// id2 failed, try id1
|
||||||
@@ -889,13 +903,14 @@ pll_external_set(uint32 clock)
|
|||||||
// If the default DC PLL clock is specified,
|
// If the default DC PLL clock is specified,
|
||||||
// SetPixelClock provides the dividers.
|
// SetPixelClock provides the dividers.
|
||||||
args.v5.ucCRTC = ATOM_CRTC_INVALID;
|
args.v5.ucCRTC = ATOM_CRTC_INVALID;
|
||||||
args.v5.usPixelClock = B_HOST_TO_LENDIAN_INT16(clock);
|
args.v5.usPixelClock = B_HOST_TO_LENDIAN_INT16(clock / 10);
|
||||||
args.v5.ucPpll = ATOM_DCPLL;
|
args.v5.ucPpll = ATOM_DCPLL;
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
// If the default DC PLL clock is specified,
|
// If the default DC PLL clock is specified,
|
||||||
// SetPixelClock provides the dividers.
|
// SetPixelClock provides the dividers.
|
||||||
args.v6.ulDispEngClkFreq = B_HOST_TO_LENDIAN_INT32(clock);
|
args.v6.ulDispEngClkFreq
|
||||||
|
= B_HOST_TO_LENDIAN_INT32(clock / 10);
|
||||||
if (dceVersion == 601)
|
if (dceVersion == 601)
|
||||||
args.v6.ucPpll = ATOM_EXT_PLL1;
|
args.v6.ucPpll = ATOM_EXT_PLL1;
|
||||||
else if (dceVersion >= 600)
|
else if (dceVersion >= 600)
|
||||||
|
|||||||
Reference in New Issue
Block a user