radeon_hd: reorganize some pll code
* Move DisplayPort external pixel clock out of pll as this frequency is card-wide. * Add new function to pull display clock frequency and other card-wide settings. * Set displayDefault frequency card-wide * My DisplayPort LVDS bridge laptop now kind of works (a clock somewhere seems a little off though)
This commit is contained in:
parent
5f44fcce9f
commit
63624e404b
@ -252,9 +252,15 @@ radeon_init_accelerant(int device)
|
||||
|
||||
radeon_init_bios(gInfo->rom);
|
||||
|
||||
// probe firmware information
|
||||
radeon_gpu_probe();
|
||||
|
||||
// disable spread spectrum as it requires lots of extra calculations
|
||||
radeon_gpu_ss_disable();
|
||||
|
||||
// program external pll clock
|
||||
pll_external_init();
|
||||
|
||||
// find GPIO pins from AtomBIOS
|
||||
gpio_probe();
|
||||
|
||||
|
@ -72,6 +72,10 @@ struct accelerant_info {
|
||||
|
||||
volatile uint32 dpms_mode; // current driver dpms mode
|
||||
|
||||
uint16 maximumPixelClock;
|
||||
uint32 displayClockFrequency;
|
||||
uint32 dpExternalClock;
|
||||
|
||||
RingQueue* ringQueue[RADEON_QUEUE_MAX]; // Ring buffer command processor
|
||||
};
|
||||
|
||||
|
@ -1351,7 +1351,7 @@ transmitter_dig_setup(uint32 connectorIndex, uint32 pixelClock,
|
||||
|
||||
// Select the PLL for the PHY
|
||||
// DP PHY to be clocked from external src if possible
|
||||
if (isDP && pll->dpExternalClock) {
|
||||
if (isDP && gInfo->dpExternalClock) {
|
||||
// use external clock source
|
||||
args.v3.acConfig.ucRefClkSource = ATOM_DCPLL;
|
||||
} else
|
||||
@ -1418,7 +1418,7 @@ transmitter_dig_setup(uint32 connectorIndex, uint32 pixelClock,
|
||||
// Select the PLL for the PHY
|
||||
// DP PHY to be clocked from external src if possible
|
||||
if (isDP) {
|
||||
if (pll->dpExternalClock > 0) {
|
||||
if (gInfo->dpExternalClock > 0) {
|
||||
args.v4.acConfig.ucRefClkSource
|
||||
= ENCODER_REFCLK_SRC_EXTCLK;
|
||||
} else {
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include "accelerant_protos.h"
|
||||
#include "accelerant.h"
|
||||
#include "atom.h"
|
||||
#include "bios.h"
|
||||
#include "utility.h"
|
||||
|
||||
@ -30,6 +31,62 @@
|
||||
#define ERROR(x...) _sPrintf("radeon_hd: " x)
|
||||
|
||||
|
||||
status_t
|
||||
radeon_gpu_probe()
|
||||
{
|
||||
uint8 tableMajor;
|
||||
uint8 tableMinor;
|
||||
uint16 tableOffset;
|
||||
|
||||
gInfo->displayClockFrequency = 0;
|
||||
gInfo->dpExternalClock = 0;
|
||||
|
||||
int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
|
||||
if (atom_parse_data_header(gAtomContext, index, NULL,
|
||||
&tableMajor, &tableMinor, &tableOffset) != B_OK) {
|
||||
ERROR("%s: Couldn't parse data header\n", __func__);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
|
||||
tableMajor, tableMinor);
|
||||
|
||||
union atomFirmwareInfo {
|
||||
ATOM_FIRMWARE_INFO info;
|
||||
ATOM_FIRMWARE_INFO_V1_2 info_12;
|
||||
ATOM_FIRMWARE_INFO_V1_3 info_13;
|
||||
ATOM_FIRMWARE_INFO_V1_4 info_14;
|
||||
ATOM_FIRMWARE_INFO_V2_1 info_21;
|
||||
ATOM_FIRMWARE_INFO_V2_2 info_22;
|
||||
};
|
||||
union atomFirmwareInfo* firmwareInfo
|
||||
= (union atomFirmwareInfo*)(gAtomContext->bios + tableOffset);
|
||||
|
||||
radeon_shared_info &info = *gInfo->shared_info;
|
||||
|
||||
if (info.dceMajor >= 4) {
|
||||
gInfo->displayClockFrequency = B_LENDIAN_TO_HOST_INT32(
|
||||
firmwareInfo->info_21.ulDefaultDispEngineClkFreq);
|
||||
if (gInfo->displayClockFrequency == 0) {
|
||||
if (info.dceMajor >= 5)
|
||||
gInfo->displayClockFrequency = 54000;
|
||||
else
|
||||
gInfo->displayClockFrequency = 60000;
|
||||
}
|
||||
gInfo->dpExternalClock = B_LENDIAN_TO_HOST_INT16(
|
||||
firmwareInfo->info_21.usUniphyDPModeExtClkFreq);
|
||||
}
|
||||
|
||||
gInfo->maximumPixelClock = B_LENDIAN_TO_HOST_INT16(
|
||||
firmwareInfo->info.usMaxPixelClock);
|
||||
|
||||
if (gInfo->maximumPixelClock == 0)
|
||||
gInfo->maximumPixelClock = 40000;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
radeon_gpu_reset()
|
||||
{
|
||||
|
@ -164,6 +164,7 @@
|
||||
#define SOFT_RESET_IA (1 << 15)
|
||||
|
||||
|
||||
status_t radeon_gpu_probe();
|
||||
status_t radeon_gpu_reset();
|
||||
void radeon_gpu_mc_halt(struct gpu_state *gpuState);
|
||||
void radeon_gpu_mc_resume(struct gpu_state *gpuState);
|
||||
|
@ -38,8 +38,6 @@ extern "C" void _sPrintf(const char* format, ...);
|
||||
status_t
|
||||
pll_limit_probe(pll_info* pll)
|
||||
{
|
||||
radeon_shared_info &info = *gInfo->shared_info;
|
||||
|
||||
uint8 tableMajor;
|
||||
uint8 tableMinor;
|
||||
uint16 tableOffset;
|
||||
@ -120,12 +118,6 @@ pll_limit_probe(pll_info* pll)
|
||||
pll->pllInMax = B_LENDIAN_TO_HOST_INT16(
|
||||
firmwareInfo->info.usMaxPixelClockPLL_Input) * 10;
|
||||
|
||||
if (info.dceMajor >= 4) {
|
||||
pll->dpExternalClock = B_LENDIAN_TO_HOST_INT16(
|
||||
firmwareInfo->info_21.usUniphyDPModeExtClkFreq);
|
||||
} else
|
||||
pll->dpExternalClock = 0;
|
||||
|
||||
TRACE("%s: referenceFreq: %" B_PRIu16 "; pllOutMin: %" B_PRIu16 "; "
|
||||
" pllOutMax: %" B_PRIu16 "; pllInMin: %" B_PRIu16 ";"
|
||||
"pllInMax: %" B_PRIu16 "\n", __func__, pll->referenceFreq,
|
||||
@ -810,6 +802,86 @@ pll_set(display_mode* mode, uint8 crtcID)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
pll_external_set(uint32 clock)
|
||||
{
|
||||
TRACE("%s: set external pll clock to %" B_PRIu32 "\n", __func__, clock);
|
||||
|
||||
if (clock == 0)
|
||||
ERROR("%s: Warning: default display clock is 0?\n", __func__);
|
||||
|
||||
// also known as PLL display engineering
|
||||
uint8 tableMajor;
|
||||
uint8 tableMinor;
|
||||
|
||||
int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
|
||||
atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor);
|
||||
|
||||
TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
|
||||
tableMajor, tableMinor);
|
||||
|
||||
union setPixelClock {
|
||||
SET_PIXEL_CLOCK_PS_ALLOCATION base;
|
||||
PIXEL_CLOCK_PARAMETERS v1;
|
||||
PIXEL_CLOCK_PARAMETERS_V2 v2;
|
||||
PIXEL_CLOCK_PARAMETERS_V3 v3;
|
||||
PIXEL_CLOCK_PARAMETERS_V5 v5;
|
||||
PIXEL_CLOCK_PARAMETERS_V6 v6;
|
||||
};
|
||||
union setPixelClock args;
|
||||
memset(&args, 0, sizeof(args));
|
||||
|
||||
radeon_shared_info &info = *gInfo->shared_info;
|
||||
uint32 dceVersion = (info.dceMajor * 100) + info.dceMinor;
|
||||
switch (tableMajor) {
|
||||
case 1:
|
||||
switch(tableMinor) {
|
||||
case 5:
|
||||
// If the default DC PLL clock is specified,
|
||||
// SetPixelClock provides the dividers.
|
||||
args.v5.ucCRTC = ATOM_CRTC_INVALID;
|
||||
args.v5.usPixelClock = B_HOST_TO_LENDIAN_INT16(clock);
|
||||
args.v5.ucPpll = ATOM_DCPLL;
|
||||
break;
|
||||
case 6:
|
||||
// If the default DC PLL clock is specified,
|
||||
// SetPixelClock provides the dividers.
|
||||
args.v6.ulDispEngClkFreq = B_HOST_TO_LENDIAN_INT32(clock);
|
||||
if (dceVersion == 601)
|
||||
args.v6.ucPpll = ATOM_EXT_PLL1;
|
||||
else if (dceVersion >= 600)
|
||||
args.v6.ucPpll = ATOM_PPLL0;
|
||||
else
|
||||
args.v6.ucPpll = ATOM_DCPLL;
|
||||
break;
|
||||
default:
|
||||
ERROR("%s: Unknown table version %" B_PRIu8
|
||||
".%" B_PRIu8 "\n", __func__, tableMajor, tableMinor);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERROR("%s: Unknown table version %" B_PRIu8
|
||||
".%" B_PRIu8 "\n", __func__, tableMajor, tableMinor);
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
pll_external_init()
|
||||
{
|
||||
radeon_shared_info &info = *gInfo->shared_info;
|
||||
|
||||
if (info.dceMajor >= 6) {
|
||||
pll_external_set(gInfo->displayClockFrequency);
|
||||
} else if (info.dceMajor >= 4) {
|
||||
// TODO: SS enabled? disable
|
||||
pll_external_set(gInfo->displayClockFrequency);
|
||||
// TODO: SS enabled? enable
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
pll_pick(uint32 connectorIndex)
|
||||
{
|
||||
@ -837,7 +909,7 @@ pll_pick(uint32 connectorIndex)
|
||||
} else if (info.dceMajor >= 5) {
|
||||
pll->id = ATOM_DCPLL;
|
||||
return B_OK;
|
||||
} else if (pll->dpExternalClock) {
|
||||
} else if (gInfo->dpExternalClock) {
|
||||
pll->id = ATOM_PPLL_INVALID;
|
||||
return B_OK;
|
||||
}
|
||||
|
@ -49,9 +49,6 @@ struct pll_info {
|
||||
/* pixel clock to be programmed (kHz)*/
|
||||
uint32 pixelClock;
|
||||
|
||||
/* external DisplayPort clock freq */
|
||||
uint32 dpExternalClock;
|
||||
|
||||
/* flags for the current clock */
|
||||
uint32 flags;
|
||||
|
||||
@ -100,6 +97,8 @@ struct pll_info {
|
||||
};
|
||||
|
||||
|
||||
void pll_external_init();
|
||||
status_t pll_external_set(uint32 clock);
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user