radeon_hd: Improve pll probing. Let probe calls enable ss
This commit is contained in:
parent
6b6ff33d60
commit
a8307efa46
@ -171,6 +171,7 @@ pll_ppll_ss_probe(pll_info* pll, uint32 ssID)
|
|||||||
if (atom_parse_data_header(gAtomContext, index, &headerSize,
|
if (atom_parse_data_header(gAtomContext, index, &headerSize,
|
||||||
&tableMajor, &tableMinor, &headerOffset) != B_OK) {
|
&tableMajor, &tableMinor, &headerOffset) != B_OK) {
|
||||||
ERROR("%s: Couldn't parse data header\n", __func__);
|
ERROR("%s: Couldn't parse data header\n", __func__);
|
||||||
|
pll->ssEnabled = false;
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,10 +193,12 @@ pll_ppll_ss_probe(pll_info* pll, uint32 ssID)
|
|||||||
pll->ssRange = ss_info->asSS_Info[i].ucSS_Range;
|
pll->ssRange = ss_info->asSS_Info[i].ucSS_Range;
|
||||||
pll->ssReferenceDiv
|
pll->ssReferenceDiv
|
||||||
= ss_info->asSS_Info[i].ucRecommendedRef_Div;
|
= ss_info->asSS_Info[i].ucRecommendedRef_Div;
|
||||||
|
pll->ssEnabled = true;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pll->ssEnabled = false;
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,6 +215,7 @@ pll_asic_ss_probe(pll_info* pll, uint32 ssID)
|
|||||||
if (atom_parse_data_header(gAtomContext, index, &headerSize,
|
if (atom_parse_data_header(gAtomContext, index, &headerSize,
|
||||||
&tableMajor, &tableMinor, &headerOffset) != B_OK) {
|
&tableMajor, &tableMinor, &headerOffset) != B_OK) {
|
||||||
ERROR("%s: Couldn't parse data header\n", __func__);
|
ERROR("%s: Couldn't parse data header\n", __func__);
|
||||||
|
pll->ssEnabled = false;
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,6 +256,7 @@ pll_asic_ss_probe(pll_info* pll, uint32 ssID)
|
|||||||
pll->ssRate = B_LENDIAN_TO_HOST_INT16(
|
pll->ssRate = B_LENDIAN_TO_HOST_INT16(
|
||||||
ss_info->info.asSpreadSpectrum[i].usSpreadRateInKhz);
|
ss_info->info.asSpreadSpectrum[i].usSpreadRateInKhz);
|
||||||
pll->ssPercentageDiv = 100;
|
pll->ssPercentageDiv = 100;
|
||||||
|
pll->ssEnabled = true;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -281,6 +286,7 @@ pll_asic_ss_probe(pll_info* pll, uint32 ssID)
|
|||||||
pll->ssRate = B_LENDIAN_TO_HOST_INT16(
|
pll->ssRate = B_LENDIAN_TO_HOST_INT16(
|
||||||
ss_info->info_2.asSpreadSpectrum[i].usSpreadRateIn10Hz);
|
ss_info->info_2.asSpreadSpectrum[i].usSpreadRateIn10Hz);
|
||||||
pll->ssPercentageDiv = 100;
|
pll->ssPercentageDiv = 100;
|
||||||
|
pll->ssEnabled = true;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -319,15 +325,18 @@ pll_asic_ss_probe(pll_info* pll, uint32 ssID)
|
|||||||
|| ssID == ASIC_INTERNAL_MEMORY_SS)
|
|| ssID == ASIC_INTERNAL_MEMORY_SS)
|
||||||
pll->ssRate /= 100;
|
pll->ssRate /= 100;
|
||||||
|
|
||||||
|
pll->ssEnabled = true;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ERROR("%s: Unknown SS table version!\n", __func__);
|
ERROR("%s: Unknown SS table version!\n", __func__);
|
||||||
|
pll->ssEnabled = false;
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ERROR("%s: No potential spread spectrum data found!\n", __func__);
|
ERROR("%s: No potential spread spectrum data found!\n", __func__);
|
||||||
|
pll->ssEnabled = false;
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,7 +400,6 @@ pll_compute(pll_info* pll)
|
|||||||
|
|
||||||
pll->feedbackDiv = 0;
|
pll->feedbackDiv = 0;
|
||||||
pll->feedbackDivFrac = 0;
|
pll->feedbackDivFrac = 0;
|
||||||
const uint32 referenceFrequency = pll->referenceFreq;
|
|
||||||
|
|
||||||
if ((pll->flags & PLL_USE_REF_DIV) != 0) {
|
if ((pll->flags & PLL_USE_REF_DIV) != 0) {
|
||||||
TRACE("%s: using AtomBIOS reference divider\n", __func__);
|
TRACE("%s: using AtomBIOS reference divider\n", __func__);
|
||||||
@ -405,8 +413,8 @@ pll_compute(pll_info* pll)
|
|||||||
|
|
||||||
const uint32 numerator = pll->postDiv * pll->referenceDiv
|
const uint32 numerator = pll->postDiv * pll->referenceDiv
|
||||||
* targetClock;
|
* targetClock;
|
||||||
pll->feedbackDiv = numerator / referenceFrequency;
|
pll->feedbackDiv = numerator / pll->referenceFreq;
|
||||||
pll->feedbackDivFrac = numerator % referenceFrequency;
|
pll->feedbackDivFrac = numerator % pll->referenceFreq;
|
||||||
|
|
||||||
if (pll->feedbackDiv > pll->maxFeedbackDiv)
|
if (pll->feedbackDiv > pll->maxFeedbackDiv)
|
||||||
pll->feedbackDiv = pll->maxFeedbackDiv;
|
pll->feedbackDiv = pll->maxFeedbackDiv;
|
||||||
@ -415,7 +423,7 @@ pll_compute(pll_info* pll)
|
|||||||
|
|
||||||
// Put first 2 digits after the decimal point into feedbackDivFrac
|
// Put first 2 digits after the decimal point into feedbackDivFrac
|
||||||
pll->feedbackDivFrac
|
pll->feedbackDivFrac
|
||||||
= (100 * pll->feedbackDivFrac) / referenceFrequency;
|
= (100 * pll->feedbackDivFrac) / pll->referenceFreq;
|
||||||
|
|
||||||
// Now round it to one digit
|
// Now round it to one digit
|
||||||
if (pll->feedbackDivFrac >= 5) {
|
if (pll->feedbackDivFrac >= 5) {
|
||||||
@ -435,16 +443,16 @@ pll_compute(pll_info* pll)
|
|||||||
uint32 retroEncabulator = pll->postDiv * pll->referenceDiv;
|
uint32 retroEncabulator = pll->postDiv * pll->referenceDiv;
|
||||||
|
|
||||||
retroEncabulator *= targetClock;
|
retroEncabulator *= targetClock;
|
||||||
pll->feedbackDiv = retroEncabulator / referenceFrequency;
|
pll->feedbackDiv = retroEncabulator / pll->referenceFreq;
|
||||||
pll->feedbackDivFrac
|
pll->feedbackDivFrac
|
||||||
= retroEncabulator % referenceFrequency;
|
= retroEncabulator % pll->referenceFreq;
|
||||||
|
|
||||||
if (pll->feedbackDiv > pll->maxFeedbackDiv)
|
if (pll->feedbackDiv > pll->maxFeedbackDiv)
|
||||||
pll->feedbackDiv = pll->maxFeedbackDiv;
|
pll->feedbackDiv = pll->maxFeedbackDiv;
|
||||||
else if (pll->feedbackDiv < pll->minFeedbackDiv)
|
else if (pll->feedbackDiv < pll->minFeedbackDiv)
|
||||||
pll->feedbackDiv = pll->minFeedbackDiv;
|
pll->feedbackDiv = pll->minFeedbackDiv;
|
||||||
|
|
||||||
if (pll->feedbackDivFrac >= (referenceFrequency / 2))
|
if (pll->feedbackDivFrac >= (pll->referenceFreq / 2))
|
||||||
pll->feedbackDiv++;
|
pll->feedbackDiv++;
|
||||||
|
|
||||||
pll->feedbackDivFrac = 0;
|
pll->feedbackDivFrac = 0;
|
||||||
@ -461,7 +469,7 @@ pll_compute(pll_info* pll)
|
|||||||
__func__, targetClock);
|
__func__, targetClock);
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
uint32 tmp = (referenceFrequency * pll->feedbackDiv)
|
uint32 tmp = (pll->referenceFreq * pll->feedbackDiv)
|
||||||
/ (pll->postDiv * pll->referenceDiv);
|
/ (pll->postDiv * pll->referenceDiv);
|
||||||
tmp = (tmp * 1000) / targetClock;
|
tmp = (tmp * 1000) / targetClock;
|
||||||
|
|
||||||
@ -481,14 +489,14 @@ pll_compute(pll_info* pll)
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32 calculatedClock
|
uint32 calculatedClock
|
||||||
= ((referenceFrequency * pll->feedbackDiv * 10)
|
= ((pll->referenceFreq * pll->feedbackDiv * 10)
|
||||||
+ (referenceFrequency * pll->feedbackDivFrac))
|
+ (pll->referenceFreq * pll->feedbackDivFrac))
|
||||||
/ (pll->referenceDiv * pll->postDiv * 10);
|
/ (pll->referenceDiv * pll->postDiv * 10);
|
||||||
|
|
||||||
TRACE("%s: Calculated pixel clock of %" B_PRIu32 " based on:\n", __func__,
|
TRACE("%s: Calculated pixel clock of %" B_PRIu32 " based on:\n", __func__,
|
||||||
calculatedClock);
|
calculatedClock);
|
||||||
TRACE("%s: referenceFrequency: %" B_PRIu32 "; "
|
TRACE("%s: referenceFrequency: %" B_PRIu32 "; "
|
||||||
"referenceDivider: %" B_PRIu32 "\n", __func__, referenceFrequency,
|
"referenceDivider: %" B_PRIu32 "\n", __func__, pll->referenceFreq,
|
||||||
pll->referenceDiv);
|
pll->referenceDiv);
|
||||||
TRACE("%s: feedbackDivider: %" B_PRIu32 "; "
|
TRACE("%s: feedbackDivider: %" B_PRIu32 "; "
|
||||||
"feedbackDividerFrac: %" B_PRIu32 "\n", __func__, pll->feedbackDiv,
|
"feedbackDividerFrac: %" B_PRIu32 "\n", __func__, pll->feedbackDiv,
|
||||||
@ -502,7 +510,14 @@ pll_compute(pll_info* pll)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calcuate needed SS data on DCE4
|
// Calcuate needed SS data on DCE4
|
||||||
if (info.dceMajor >= 4) {
|
if (info.dceMajor >= 4 && pll->ssEnabled) {
|
||||||
|
if (pll->ssPercentageDiv == 0) {
|
||||||
|
// Avoid div by 0, shouldn't happen but be mindful of it
|
||||||
|
TRACE("%s: ssPercentageDiv is less than 0, aborting SS calcualation",
|
||||||
|
__func__);
|
||||||
|
pll->ssEnabled = false;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
uint32 amount = ((pll->feedbackDiv * 10) + pll->feedbackDivFrac);
|
uint32 amount = ((pll->feedbackDiv * 10) + pll->feedbackDivFrac);
|
||||||
amount *= pll->ssPercentage;
|
amount *= pll->ssPercentage;
|
||||||
amount /= pll->ssPercentageDiv * 100;
|
amount /= pll->ssPercentageDiv * 100;
|
||||||
@ -744,33 +759,26 @@ pll_set(display_mode* mode, uint8 crtcID)
|
|||||||
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 == 162000) {
|
if (dp_clock == 162000) {
|
||||||
pll->ssEnabled = pll_ppll_ss_probe(pll,
|
pll_ppll_ss_probe(pll, ATOM_DP_SS_ID2);
|
||||||
ATOM_DP_SS_ID2) == B_OK ? true : false;
|
|
||||||
if (!pll->ssEnabled)
|
if (!pll->ssEnabled)
|
||||||
pll->ssEnabled = pll_ppll_ss_probe(pll,
|
pll_ppll_ss_probe(pll, ATOM_DP_SS_ID1);
|
||||||
ATOM_DP_SS_ID1) == B_OK ? true : false;
|
|
||||||
} else
|
} else
|
||||||
pll->ssEnabled = pll_ppll_ss_probe(pll,
|
pll_ppll_ss_probe(pll, ATOM_DP_SS_ID1);
|
||||||
ATOM_DP_SS_ID1) == B_OK ? true : false;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ATOM_ENCODER_MODE_LVDS:
|
case ATOM_ENCODER_MODE_LVDS:
|
||||||
if (info.dceMajor >= 4)
|
if (info.dceMajor >= 4)
|
||||||
pll->ssEnabled = pll_asic_ss_probe(pll,
|
pll_asic_ss_probe(pll, gInfo->lvdsSpreadSpectrumID);
|
||||||
gInfo->lvdsSpreadSpectrumID) == B_OK ? true : false;
|
|
||||||
else
|
else
|
||||||
pll->ssEnabled = pll_ppll_ss_probe(pll,
|
pll_ppll_ss_probe(pll, gInfo->lvdsSpreadSpectrumID);
|
||||||
gInfo->lvdsSpreadSpectrumID) == B_OK ? true : false;
|
|
||||||
break;
|
break;
|
||||||
case ATOM_ENCODER_MODE_DVI:
|
case ATOM_ENCODER_MODE_DVI:
|
||||||
if (info.dceMajor >= 4)
|
if (info.dceMajor >= 4)
|
||||||
pll->ssEnabled = pll_asic_ss_probe(pll,
|
pll_asic_ss_probe(pll, ASIC_INTERNAL_SS_ON_TMDS);
|
||||||
ASIC_INTERNAL_SS_ON_TMDS) == B_OK ? true : false;
|
|
||||||
break;
|
break;
|
||||||
case ATOM_ENCODER_MODE_HDMI:
|
case ATOM_ENCODER_MODE_HDMI:
|
||||||
if (info.dceMajor >= 4)
|
if (info.dceMajor >= 4)
|
||||||
pll->ssEnabled = pll_asic_ss_probe(pll,
|
pll_asic_ss_probe(pll, ASIC_INTERNAL_SS_ON_HDMI);
|
||||||
ASIC_INTERNAL_SS_ON_HDMI) == B_OK ? true : false;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -919,8 +927,6 @@ pll_set(display_mode* mode, uint8 crtcID)
|
|||||||
|
|
||||||
status_t result = atom_execute_table(gAtomContext, index, (uint32*)&args);
|
status_t result = atom_execute_table(gAtomContext, index, (uint32*)&args);
|
||||||
|
|
||||||
// TODO: PLL forced off until we can test it
|
|
||||||
pll->ssEnabled = false;
|
|
||||||
if (pll->ssEnabled)
|
if (pll->ssEnabled)
|
||||||
display_crtc_ss(pll, ATOM_ENABLE);
|
display_crtc_ss(pll, ATOM_ENABLE);
|
||||||
else
|
else
|
||||||
|
Loading…
Reference in New Issue
Block a user