radeon_hd: rework some pll code
* Force fractional feedback divider on APU's * Spread Spectrum is now probed more correctly across multiple encoders and cards * SS still disabled however.
This commit is contained in:
@@ -255,9 +255,6 @@ radeon_init_accelerant(int device)
|
|||||||
// probe firmware information
|
// probe firmware information
|
||||||
radeon_gpu_probe();
|
radeon_gpu_probe();
|
||||||
|
|
||||||
// disable spread spectrum as it requires lots of extra calculations
|
|
||||||
radeon_gpu_ss_disable();
|
|
||||||
|
|
||||||
// program external pll clock
|
// program external pll clock
|
||||||
pll_external_init();
|
pll_external_init();
|
||||||
|
|
||||||
|
|||||||
@@ -76,6 +76,8 @@ struct accelerant_info {
|
|||||||
uint32 displayClockFrequency;
|
uint32 displayClockFrequency;
|
||||||
uint32 dpExternalClock;
|
uint32 dpExternalClock;
|
||||||
|
|
||||||
|
uint32 lvdsSpreadSpectrumID;
|
||||||
|
|
||||||
RingQueue* ringQueue[RADEON_QUEUE_MAX]; // Ring buffer command processor
|
RingQueue* ringQueue[RADEON_QUEUE_MAX]; // Ring buffer command processor
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -200,6 +200,9 @@ connector_read_mode_lvds(uint32 connectorIndex, display_mode* mode)
|
|||||||
// Store special lvds flags the encoder setup needs
|
// Store special lvds flags the encoder setup needs
|
||||||
gConnector[connectorIndex]->lvdsFlags = lvdsInfo->info.ucLVDS_Misc;
|
gConnector[connectorIndex]->lvdsFlags = lvdsInfo->info.ucLVDS_Misc;
|
||||||
|
|
||||||
|
// Spread Spectrum ID (in SS table)
|
||||||
|
gInfo->lvdsSpreadSpectrumID = lvdsInfo->info.ucSS_Id;
|
||||||
|
|
||||||
uint16 flags = B_LENDIAN_TO_HOST_INT16(
|
uint16 flags = B_LENDIAN_TO_HOST_INT16(
|
||||||
lvdsInfo->info.sLCDTiming.susModeMiscInfo.usAccess);
|
lvdsInfo->info.sLCDTiming.susModeMiscInfo.usAccess);
|
||||||
|
|
||||||
|
|||||||
@@ -951,8 +951,7 @@ display_crtc_ss(uint8 crtcID, int command)
|
|||||||
} else if (info.dceMajor >= 2) {
|
} else if (info.dceMajor >= 2) {
|
||||||
if ((command == ATOM_DISABLE) || (pll->ssPercentage == 0)
|
if ((command == ATOM_DISABLE) || (pll->ssPercentage == 0)
|
||||||
|| (pll->ssType & ATOM_EXTERNAL_SS_MASK)) {
|
|| (pll->ssType & ATOM_EXTERNAL_SS_MASK)) {
|
||||||
// TODO: gpu_ss_disable needs pll id
|
radeon_gpu_ss_control(pll, false);
|
||||||
radeon_gpu_ss_disable();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
args.lvds_ss_2.usSpreadSpectrumPercentage
|
args.lvds_ss_2.usSpreadSpectrumPercentage
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "accelerant.h"
|
#include "accelerant.h"
|
||||||
#include "atom.h"
|
#include "atom.h"
|
||||||
#include "bios.h"
|
#include "bios.h"
|
||||||
|
#include "pll.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -715,7 +716,7 @@ radeon_gpu_ring_boot(uint32 ringType)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
radeon_gpu_ss_disable()
|
radeon_gpu_ss_control(pll_info* pll, bool enable)
|
||||||
{
|
{
|
||||||
TRACE("%s called\n", __func__);
|
TRACE("%s called\n", __func__);
|
||||||
|
|
||||||
@@ -723,25 +724,52 @@ radeon_gpu_ss_disable()
|
|||||||
uint32 ssControl;
|
uint32 ssControl;
|
||||||
|
|
||||||
if (info.chipsetID >= RADEON_CEDAR) {
|
if (info.chipsetID >= RADEON_CEDAR) {
|
||||||
// PLL1
|
switch (pll->id) {
|
||||||
ssControl = Read32(OUT, EVERGREEN_P1PLL_SS_CNTL);
|
case ATOM_PPLL1:
|
||||||
ssControl &= ~EVERGREEN_PxPLL_SS_EN;
|
// PLL1
|
||||||
Write32(OUT, EVERGREEN_P1PLL_SS_CNTL, ssControl);
|
ssControl = Read32(OUT, EVERGREEN_P1PLL_SS_CNTL);
|
||||||
// PLL2
|
if (enable)
|
||||||
ssControl = Read32(OUT, EVERGREEN_P2PLL_SS_CNTL);
|
ssControl |= EVERGREEN_PxPLL_SS_EN;
|
||||||
ssControl &= ~EVERGREEN_PxPLL_SS_EN;
|
else
|
||||||
Write32(OUT, EVERGREEN_P2PLL_SS_CNTL, ssControl);
|
ssControl &= ~EVERGREEN_PxPLL_SS_EN;
|
||||||
|
Write32(OUT, EVERGREEN_P1PLL_SS_CNTL, ssControl);
|
||||||
|
break;
|
||||||
|
case ATOM_PPLL2:
|
||||||
|
// PLL2
|
||||||
|
ssControl = Read32(OUT, EVERGREEN_P2PLL_SS_CNTL);
|
||||||
|
if (enable)
|
||||||
|
ssControl |= EVERGREEN_PxPLL_SS_EN;
|
||||||
|
else
|
||||||
|
ssControl &= ~EVERGREEN_PxPLL_SS_EN;
|
||||||
|
Write32(OUT, EVERGREEN_P2PLL_SS_CNTL, ssControl);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// DCPLL, no action
|
||||||
|
return B_OK;
|
||||||
} else if (info.chipsetID >= RADEON_RS600) {
|
} else if (info.chipsetID >= RADEON_RS600) {
|
||||||
// PLL1
|
switch (pll->id) {
|
||||||
ssControl = Read32(OUT, AVIVO_P1PLL_INT_SS_CNTL);
|
case ATOM_PPLL1:
|
||||||
ssControl &= ~1;
|
// PLL1
|
||||||
Write32(OUT, AVIVO_P1PLL_INT_SS_CNTL, ssControl);
|
ssControl = Read32(OUT, AVIVO_P1PLL_INT_SS_CNTL);
|
||||||
// PLL2
|
if (enable)
|
||||||
ssControl = Read32(OUT, AVIVO_P2PLL_INT_SS_CNTL);
|
ssControl |= 1;
|
||||||
ssControl &= ~1;
|
else
|
||||||
Write32(OUT, AVIVO_P2PLL_INT_SS_CNTL, ssControl);
|
ssControl &= ~1;
|
||||||
} else
|
Write32(OUT, AVIVO_P1PLL_INT_SS_CNTL, ssControl);
|
||||||
return B_ERROR;
|
break;
|
||||||
|
case ATOM_PPLL2:
|
||||||
|
// PLL2
|
||||||
|
ssControl = Read32(OUT, AVIVO_P2PLL_INT_SS_CNTL);
|
||||||
|
if (enable)
|
||||||
|
ssControl |= 1;
|
||||||
|
else
|
||||||
|
ssControl &= ~1;
|
||||||
|
Write32(OUT, AVIVO_P2PLL_INT_SS_CNTL, ssControl);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// DCPLL, no action
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
#include <video_configuration.h>
|
#include <video_configuration.h>
|
||||||
|
|
||||||
|
#include "pll.h"
|
||||||
|
|
||||||
|
|
||||||
// GPU Control registers. These are combined as
|
// GPU Control registers. These are combined as
|
||||||
// the registers exist on all models, some flags
|
// the registers exist on all models, some flags
|
||||||
@@ -172,7 +174,8 @@ status_t radeon_gpu_mc_idlewait();
|
|||||||
status_t radeon_gpu_mc_setup();
|
status_t radeon_gpu_mc_setup();
|
||||||
status_t radeon_gpu_ring_setup();
|
status_t radeon_gpu_ring_setup();
|
||||||
status_t radeon_gpu_ring_boot(uint32 ringType);
|
status_t radeon_gpu_ring_boot(uint32 ringType);
|
||||||
status_t radeon_gpu_ss_disable();
|
status_t radeon_gpu_ss_control(pll_info* pll, bool enable);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ pll_limit_probe(pll_info* pll)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
pll_dp_ss_probe(pll_info* pll)
|
pll_ppll_ss_probe(pll_info* pll, uint32 ssID)
|
||||||
{
|
{
|
||||||
uint8 tableMajor;
|
uint8 tableMajor;
|
||||||
uint8 tableMinor;
|
uint8 tableMinor;
|
||||||
@@ -151,7 +151,7 @@ pll_dp_ss_probe(pll_info* pll)
|
|||||||
|
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < indices; i++) {
|
for (i = 0; i < indices; i++) {
|
||||||
if (ss_info->asSS_Info[i].ucSS_Id == pll->id) {
|
if (ss_info->asSS_Info[i].ucSS_Id == ssID) {
|
||||||
pll->ssPercentage = B_LENDIAN_TO_HOST_INT16(
|
pll->ssPercentage = B_LENDIAN_TO_HOST_INT16(
|
||||||
ss_info->asSS_Info[i].usSpreadSpectrumPercentage);
|
ss_info->asSS_Info[i].usSpreadSpectrumPercentage);
|
||||||
pll->ssType = ss_info->asSS_Info[i].ucSpreadSpectrumType;
|
pll->ssType = ss_info->asSS_Info[i].ucSpreadSpectrumType;
|
||||||
@@ -175,7 +175,7 @@ pll_dp_ss_probe(pll_info* pll)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
pll_asic_ss_probe(pll_info* pll)
|
pll_asic_ss_probe(pll_info* pll, uint32 ssID)
|
||||||
{
|
{
|
||||||
uint8 tableMajor;
|
uint8 tableMajor;
|
||||||
uint8 tableMinor;
|
uint8 tableMinor;
|
||||||
@@ -207,7 +207,7 @@ pll_asic_ss_probe(pll_info* pll)
|
|||||||
|
|
||||||
for (i = 0; i < indices; i++) {
|
for (i = 0; i < indices; i++) {
|
||||||
if (ss_info->info.asSpreadSpectrum[i].ucClockIndication
|
if (ss_info->info.asSpreadSpectrum[i].ucClockIndication
|
||||||
!= pll->id) {
|
!= ssID) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
TRACE("%s: ss match found\n", __func__);
|
TRACE("%s: ss match found\n", __func__);
|
||||||
@@ -234,7 +234,7 @@ pll_asic_ss_probe(pll_info* pll)
|
|||||||
|
|
||||||
for (i = 0; i < indices; i++) {
|
for (i = 0; i < indices; i++) {
|
||||||
if (ss_info->info_2.asSpreadSpectrum[i].ucClockIndication
|
if (ss_info->info_2.asSpreadSpectrum[i].ucClockIndication
|
||||||
!= pll->id) {
|
!= ssID) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
TRACE("%s: ss match found\n", __func__);
|
TRACE("%s: ss match found\n", __func__);
|
||||||
@@ -262,7 +262,7 @@ pll_asic_ss_probe(pll_info* pll)
|
|||||||
|
|
||||||
for (i = 0; i < indices; i++) {
|
for (i = 0; i < indices; i++) {
|
||||||
if (ss_info->info_3.asSpreadSpectrum[i].ucClockIndication
|
if (ss_info->info_3.asSpreadSpectrum[i].ucClockIndication
|
||||||
!= pll->id) {
|
!= ssID) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
TRACE("%s: ss match found\n", __func__);
|
TRACE("%s: ss match found\n", __func__);
|
||||||
@@ -492,6 +492,11 @@ pll_setup_flags(pll_info* pll, uint8 crtcID)
|
|||||||
|
|
||||||
if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) != 0)
|
if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) != 0)
|
||||||
pll->flags |= PLL_PREFER_CLOSEST_LOWER;
|
pll->flags |= PLL_PREFER_CLOSEST_LOWER;
|
||||||
|
|
||||||
|
if ((info.chipsetFlags & CHIP_APU) != 0) {
|
||||||
|
// Use fractional feedback on APU's
|
||||||
|
pll->flags |= PLL_USE_FRAC_FB_DIV;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -657,12 +662,38 @@ pll_set(display_mode* mode, uint8 crtcID)
|
|||||||
pll_compute(pll);
|
pll_compute(pll);
|
||||||
// compute dividers
|
// compute dividers
|
||||||
|
|
||||||
pll_asic_ss_probe(pll);
|
radeon_shared_info &info = *gInfo->shared_info;
|
||||||
// probe spread spectrum metrics (TODO: pll_dp_ss_probe)
|
pll->ssType = 0;
|
||||||
|
|
||||||
|
switch (display_get_encoder_mode(connectorIndex)) {
|
||||||
|
case ATOM_ENCODER_MODE_DP_MST:
|
||||||
|
case ATOM_ENCODER_MODE_DP:
|
||||||
|
if (info.dceMajor >= 4)
|
||||||
|
pll_asic_ss_probe(pll, ASIC_INTERNAL_SS_ON_DP);
|
||||||
|
else {
|
||||||
|
// TODO: DP Clock == 1.62Ghz?
|
||||||
|
pll_ppll_ss_probe(pll, ATOM_DP_SS_ID1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ATOM_ENCODER_MODE_LVDS:
|
||||||
|
if (info.dceMajor >= 4)
|
||||||
|
pll_asic_ss_probe(pll, gInfo->lvdsSpreadSpectrumID);
|
||||||
|
else
|
||||||
|
pll_ppll_ss_probe(pll, gInfo->lvdsSpreadSpectrumID);
|
||||||
|
break;
|
||||||
|
case ATOM_ENCODER_MODE_DVI:
|
||||||
|
if (info.dceMajor >= 4)
|
||||||
|
pll_asic_ss_probe(pll, ASIC_INTERNAL_SS_ON_TMDS);
|
||||||
|
break;
|
||||||
|
case ATOM_ENCODER_MODE_HDMI:
|
||||||
|
if (info.dceMajor >= 4)
|
||||||
|
pll_asic_ss_probe(pll, ASIC_INTERNAL_SS_ON_HDMI);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
display_crtc_ss(crtcID, ATOM_DISABLE);
|
display_crtc_ss(crtcID, ATOM_DISABLE);
|
||||||
// disable ss
|
// disable ss
|
||||||
|
|
||||||
|
|
||||||
uint8 tableMajor;
|
uint8 tableMajor;
|
||||||
uint8 tableMinor;
|
uint8 tableMinor;
|
||||||
|
|
||||||
|
|||||||
@@ -103,8 +103,8 @@ 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_ppll_ss_probe(pll_info* pll, uint32 ssID);
|
||||||
status_t pll_asic_ss_probe(pll_info* pll);
|
status_t pll_asic_ss_probe(pll_info* pll, uint32 ssID);
|
||||||
status_t pll_set(display_mode* mode, uint8 crtcID);
|
status_t pll_set(display_mode* mode, uint8 crtcID);
|
||||||
status_t pll_pick(uint32 connectorIndex);
|
status_t pll_pick(uint32 connectorIndex);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user