* malloc an array of pointers to hold active crt info, mode, limits, etc.

Plan to move gRegister into the crt struct at some point.
* Few style fixes
* Added function to probe edid of attached monitors and populate CRT info
* Disable VGA control modifications temporarly while I hammer out some issues.
* Fix radeon card model checks (bitwise & is not |)
* Finally fix? blanking start / end calculations using porch
* Use mask for setting sync polarity
* Add overscan (8 pixels is default?)
* Disable PLLSet/Power for the moment as it seems to muck things up.
* is_mode_supported now validates if a mode line is with the monitors
  h/v sync frequencies (how does is_mode_supported know what crt the os wants?)
* PLL Write/Read don't actually use the PLL Write/Read functions (thanks AMD!)
* Added better PLL legacy (r600-r610) support
* Consistantly give no DCCG on legacy cards.
* Tracing!


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42191 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Alexander von Gluck IV 2011-06-15 18:22:06 +00:00
parent 58ddd30b23
commit d1d65a79cb
6 changed files with 278 additions and 64 deletions

View File

@ -34,6 +34,7 @@ extern "C" void _sPrintf(const char *format, ...);
struct accelerant_info *gInfo;
struct register_info *gRegister;
crt_info *gCRT[MAX_CRT];
class AreaCloner {
@ -100,9 +101,18 @@ init_common(int device, bool isClone)
if (gInfo == NULL || gRegister == NULL)
return B_NO_MEMORY;
for (uint32 id = 0; id < MAX_CRT; id++) {
gCRT[id] = (crt_info *)malloc(sizeof(crt_info));
if (gCRT[id] == NULL)
return B_NO_MEMORY;
}
memset(gInfo, 0, sizeof(accelerant_info));
memset(gRegister, 0, sizeof(register_info));
for (uint32 id = 0; id < MAX_CRT; id++)
memset(gCRT[id], 0, sizeof(crt_info));
gInfo->is_clone = isClone;
gInfo->device = device;
@ -167,6 +177,9 @@ uninit_common(void)
free(gInfo);
free(gRegister);
for (uint32 id = 0; id < MAX_CRT; id++)
free(gCRT[id]);
}
@ -177,7 +190,7 @@ init_registers(uint8 crtid)
radeon_shared_info &info = *gInfo->shared_info;
if (info.device_chipset >= RADEON_R800) {
uint16_t offset = 0;
uint32 offset = 0;
// AMD Eyefinity on Evergreen GPUs
if (crtid == 1) {

View File

@ -18,6 +18,10 @@
#include <edid.h>
#define MAX_CRT 6
// eyefinity limit
struct accelerant_info {
vuint8 *regs;
area_id regs_area;
@ -77,6 +81,14 @@ struct register_info {
};
typedef struct {
uint32 vfreq_max;
uint32 vfreq_min;
uint32 hfreq_max;
uint32 hfreq_min;
} crt_info;
#define HEAD_MODE_A_ANALOG 0x01
#define HEAD_MODE_B_DIGITAL 0x02
#define HEAD_MODE_CLONE 0x03
@ -89,8 +101,10 @@ struct register_info {
#define PLL 0x4 // PLL calls
#define MC 0x5 // Memory Controler calls
extern accelerant_info *gInfo;
extern register_info *gRegister;
extern crt_info *gCRT[MAX_CRT];
status_t init_registers(uint8 crtid);
@ -121,12 +135,12 @@ _read32MC(uint32 offset)
_write32(RS600_MC_INDEX, ((offset & RS600_MC_INDEX_ADDR_MASK)
| RS600_MC_INDEX_CITF_ARB0));
return _read32(RS600_MC_DATA);
} else if (info.device_chipset == (RADEON_R600 & 0x90)
|| info.device_chipset == (RADEON_R700 & 0x40)) {
} else if (info.device_chipset == (RADEON_R600 | 0x90)
|| info.device_chipset == (RADEON_R700 | 0x40)) {
_write32(RS690_MC_INDEX, (offset & RS690_MC_INDEX_ADDR_MASK));
return _read32(RS690_MC_DATA);
} else if (info.device_chipset == (RADEON_R700 & 0x80)
|| info.device_chipset == (RADEON_R800 & 0x80)) {
} else if (info.device_chipset == (RADEON_R700 | 0x80)
|| info.device_chipset == (RADEON_R800 | 0x80)) {
_write32(RS780_MC_INDEX, offset & RS780_MC_INDEX_ADDR_MASK);
return _read32(RS780_MC_DATA);
}
@ -145,14 +159,14 @@ _write32MC(uint32 offset, uint32 data)
_write32(RS600_MC_INDEX, ((offset & RS600_MC_INDEX_ADDR_MASK)
| RS600_MC_INDEX_CITF_ARB0 | RS600_MC_INDEX_WR_EN));
_write32(RS600_MC_DATA, data);
} else if (info.device_chipset == (RADEON_R600 & 0x90)
|| info.device_chipset == (RADEON_R700 & 0x40)) {
} else if (info.device_chipset == (RADEON_R600 | 0x90)
|| info.device_chipset == (RADEON_R700 | 0x40)) {
_write32(RS690_MC_INDEX, ((offset & RS690_MC_INDEX_ADDR_MASK)
| RS690_MC_INDEX_WR_EN));
_write32(RS690_MC_DATA, data);
_write32(RS690_MC_INDEX, RS690_MC_INDEX_WR_ACK);
} else if (info.device_chipset == (RADEON_R700 & 0x80)
|| info.device_chipset == (RADEON_R800 & 0x80)) {
} else if (info.device_chipset == (RADEON_R700 | 0x80)
|| info.device_chipset == (RADEON_R800 | 0x80)) {
_write32(RS780_MC_INDEX, ((offset & RS780_MC_INDEX_ADDR_MASK)
| RS780_MC_INDEX_WR_EN));
_write32(RS780_MC_DATA, data);
@ -187,7 +201,8 @@ Read32(uint32 subsystem, uint32 offset)
case CRT:
return _read32(offset);
case PLL:
return _read32PLL(offset);
return _read32(offset);
//return _read32PLL(offset);
case MC:
return _read32MC(offset);
};
@ -207,7 +222,8 @@ Write32(uint32 subsystem, uint32 offset, uint32 value)
_write32(offset, value);
return;
case PLL:
_write32PLL(offset, value);
_write32(offset, value);
//_write32PLL(offset, value);
return;
case MC:
_write32MC(offset, value);
@ -230,7 +246,8 @@ Write32Mask(uint32 subsystem, uint32 offset, uint32 value, uint32 mask)
temp = _read32(offset);
break;
case PLL:
temp = _read32PLL(offset);
temp = _read32(offset);
//temp = _read32PLL(offset);
break;
case MC:
temp = _read32MC(offset);
@ -251,7 +268,8 @@ Write32Mask(uint32 subsystem, uint32 offset, uint32 value, uint32 mask)
_write32(offset, temp);
return;
case PLL:
_write32PLL(offset, temp);
_write32(offset, temp);
//_write32PLL(offset, temp);
return;
case MC:
_write32MC(offset, temp);

View File

@ -38,6 +38,8 @@ create_mode_list(void)
const color_space kRadeonHDSpaces[] = {B_RGB32_LITTLE, B_RGB24_LITTLE,
B_RGB16_LITTLE, B_RGB15_LITTLE, B_CMAP8};
detect_crt_ranges();
gInfo->mode_list_area = create_display_modes("radeon HD modes",
gInfo->shared_info->has_edid ? &gInfo->shared_info->edid_info : NULL,
NULL, 0, kRadeonHDSpaces,
@ -148,12 +150,14 @@ CardFBSet(display_mode *mode)
get_color_space_format(*mode, colorMode, bytesPerRow, bitsPerPixel);
#if 0
// Disable VGA mode to enable Radeon extended registers
Write32Mask(VGA, VGA_RENDER_CONTROL, 0, 0x00030000);
Write32Mask(VGA, VGA_MODE_CONTROL, 0, 0x00000030);
Write32Mask(VGA, VGA_HDP_CONTROL, 0x00010010, 0x00010010);
Write32Mask(VGA, gRegister->vgaControl, 0, D1VGA_MODE_ENABLE
| D1VGA_TIMING_SELECT | D1VGA_SYNC_POLARITY_SELECT);
#endif
// disable R/B swap, disable tiling, disable 16bit alpha, etc.
Write32Mask(CRT, gRegister->grphEnable, 1, 0x00000001);
@ -190,7 +194,7 @@ CardFBSet(display_mode *mode)
uint64_t fbAddress = gInfo->shared_info->frame_buffer_phys;
// Tell GPU which frame buffer address to draw from
if (gInfo->shared_info->device_chipset >= (uint16)(RADEON_R700 & 0x70)) {
if (gInfo->shared_info->device_chipset >= (RADEON_R700 | 0x70)) {
Write32(CRT, gRegister->grphPrimarySurfaceAddrHigh,
(fbAddress >> 32) & 0xf);
Write32(CRT, gRegister->grphSecondarySurfaceAddrHigh,
@ -235,14 +239,15 @@ CardModeSet(display_mode *mode)
Write32(CRT, gRegister->crtHTotal,
displayTiming.h_total - 1);
#if 0
// determine blanking based on passed modeline
uint16 blankStart = displayTiming.h_display;
uint16 blankEnd = displayTiming.h_total;
// Calculate blanking
uint16 frontPorch = displayTiming.h_sync_start - displayTiming.h_display;
uint16 backPorch = displayTiming.h_total - displayTiming.h_sync_end;
uint16 blankStart = frontPorch - OVERSCAN;
uint16 blankEnd = backPorch;
Write32(CRT, gRegister->crtHBlank,
blankStart | (blankEnd << 16));
#endif
Write32(CRT, gRegister->crtHSync,
(displayTiming.h_sync_end - displayTiming.h_sync_start) << 16);
@ -255,13 +260,14 @@ CardModeSet(display_mode *mode)
Write32(CRT, gRegister->crtVTotal,
displayTiming.v_total - 1);
#if 0
blankStart = displayTiming.v_display;
blankEnd = displayTiming.v_total;
frontPorch = displayTiming.v_sync_start - displayTiming.v_display;
backPorch = displayTiming.v_total - displayTiming.v_sync_end;
blankStart = frontPorch - OVERSCAN;
blankEnd = backPorch;
Write32(CRT, gRegister->crtVBlank,
blankStart | (blankEnd << 16));
#endif
// Set Interlace if specified within mode line
if (displayTiming.flags & B_TIMING_INTERLACED) {
@ -276,9 +282,8 @@ CardModeSet(display_mode *mode)
(displayTiming.v_sync_end - displayTiming.v_sync_start) << 16);
// set flag for neg. V sync. M76 Register Reference Guide 2-258
// we don't need a mask here as this is the only param for Vertical
Write32(CRT, gRegister->crtVPolarity,
displayTiming.flags & B_POSITIVE_VSYNC ? 0 : 1);
Write32Mask(CRT, gRegister->crtVPolarity,
displayTiming.flags & B_POSITIVE_VSYNC ? 0 : 1, 0x1);
/* set D1CRTC_HORZ_COUNT_BY2_EN to 0;
should only be set to 1 on 30bpp DVI modes
@ -296,9 +301,9 @@ CardModeScale(display_mode *mode)
// For now, no overscan support
Write32(CRT, D1MODE_EXT_OVERSCAN_LEFT_RIGHT,
(0 << 16) | 0); // LEFT | RIGHT
(OVERSCAN << 16) | OVERSCAN); // LEFT | RIGHT
Write32(CRT, D1MODE_EXT_OVERSCAN_TOP_BOTTOM,
(0 << 16) | 0); // TOP | BOTTOM
(OVERSCAN << 16) | OVERSCAN); // TOP | BOTTOM
// No scaling
Write32(CRT, gRegister->sclUpdate, (1<<16));// Lock
@ -336,12 +341,21 @@ radeon_set_display_mode(display_mode *mode)
CardBlankSet(true);
CardFBSet(mode);
CardBlankSet(false);
CardModeSet(mode);
CardModeScale(mode);
#if 0
PLLSet(0, mode->timing.pixel_clock);
PLLPower(0, RHD_POWER_ON);
DACPower(0, RHD_POWER_ON);
CardBlankSet(false);
#endif
// ensure graphics are enabled and powered on
Write32Mask(CRT, D1GRPH_ENABLE, 0x00000001, 0x00000001);
snooze(2);
Write32Mask(CRT, D1CRTC_CONTROL, 0, 0x01000000); /* enable read requests */
Write32Mask(CRT, D1CRTC_CONTROL, 1, 1);
int32 crtstatus = Read32(CRT, D1CRTC_STATUS);
TRACE("CRT0 Status: 0x%X\n", crtstatus);
@ -405,22 +419,47 @@ radeon_get_pixel_clock_limits(display_mode *mode, uint32 *_low, uint32 *_high)
bool
is_mode_supported(display_mode *mode)
{
TRACE("MODE: %d ; %d %d %d %d ; %d %d %d %d\n",
mode->timing.pixel_clock, mode->timing.h_display,
mode->timing.h_sync_start, mode->timing.h_sync_end,
mode->timing.h_total, mode->timing.v_display,
mode->timing.v_sync_start, mode->timing.v_sync_end,
mode->timing.v_total);
// Validate modeline is within a sane range
if (is_mode_sane(mode) != B_OK)
return false;
// TODO : Look at min and max monitor freqs and verify selected
// mode is within tolerances.
#if 0
int crtid = 0;
uint32 crtid = 0;
edid1_detailed_monitor *monitor
= &gInfo->shared_info->edid_info.detailed_monitor[crtid + 1];
edid1_monitor_range& range = monitor->data.monitor_range;
// if we have edid info, check frequency adginst crt reported valid ranges
if (gInfo->shared_info->has_edid) {
TRACE("%s CRT Min/Max H %d/%d; CRT Min/Max V %d/%d\n", __func__,
range.min_h, range.max_h, range.min_v, range.max_v);
#endif
uint32 hfreq = mode->timing.pixel_clock / mode->timing.h_total;
if (hfreq > gCRT[crtid]->hfreq_max + 1
|| hfreq < gCRT[crtid]->hfreq_min - 1) {
TRACE("!!! hfreq : %d , hfreq_min : %d, hfreq_max : %d\n",
hfreq, gCRT[crtid]->hfreq_min, gCRT[crtid]->hfreq_max);
TRACE("!!! %dx%d falls outside of CRT %d's valid "
"horizontal range.\n", mode->timing.h_display,
mode->timing.v_display, crtid);
return false;
}
uint32 vfreq = mode->timing.pixel_clock / ((mode->timing.v_total
* mode->timing.h_total) / 1000);
if (vfreq > gCRT[crtid]->vfreq_max + 1
|| vfreq < gCRT[crtid]->vfreq_min - 1) {
TRACE("!!! vfreq : %d , vfreq_min : %d, vfreq_max : %d\n",
vfreq, gCRT[crtid]->vfreq_min, gCRT[crtid]->vfreq_max);
TRACE("!!! %dx%d falls outside of CRT %d's valid vertical range\n",
mode->timing.h_display, mode->timing.v_display, crtid);
return false;
}
TRACE("%dx%d is within CRT %d's valid frequency range\n",
mode->timing.h_display, mode->timing.v_display, crtid);
}
return true;
}
@ -478,3 +517,34 @@ is_mode_sane(display_mode *mode)
return B_OK;
}
// TODO : Move to a new "monitors.c" file
status_t
detect_crt_ranges()
{
edid1_info *edid = &gInfo->shared_info->edid_info;
int crtid = 0;
// edid indexes are not in order
for (uint32 index = 0; index < MAX_CRT; index++) {
edid1_detailed_monitor *monitor
= &edid->detailed_monitor[index];
if (monitor->monitor_desc_type
== EDID1_MONITOR_RANGES) {
edid1_monitor_range range = monitor->data.monitor_range;
gCRT[crtid]->vfreq_min = range.min_v; /* in Hz */
gCRT[crtid]->vfreq_max = range.max_v;
gCRT[crtid]->hfreq_min = range.min_h; /* in kHz */
gCRT[crtid]->hfreq_max = range.max_h;
TRACE("CRT %d : v_min %d : v_max %d : h_min %d : h_max %d\n",
crtid, gCRT[crtid]->vfreq_min, gCRT[crtid]->vfreq_max,
gCRT[crtid]->hfreq_min, gCRT[crtid]->hfreq_max);
crtid++;
}
}
return B_OK;
}

View File

@ -21,7 +21,10 @@
#define FMT1_REG_OFFSET 0x0000
#define FMT2_REG_OFFSET 0x800
#define OVERSCAN 8
// default overscan? Applied to all sides
status_t detect_crt_ranges();
status_t create_mode_list(void);
bool is_mode_supported(display_mode* mode);
status_t is_mode_sane(display_mode *mode);

View File

@ -134,7 +134,6 @@ PLLCalculate(uint32 pixelClock, uint16 *reference, uint16 *feedback,
status_t
PLLPower(uint8 pllIndex, int command)
{
uint16 pllControlReg = (pllIndex == 1) ? P2PLL_CNTL : P1PLL_CNTL;
bool hasDccg = DCCGCLKAvailable(pllIndex);
@ -179,6 +178,8 @@ PLLPower(uint8 pllIndex, int command)
default:
TRACE("%s: PLL Power Shutdown\n", __func__);
radeon_shared_info &info = *gInfo->shared_info;
if (hasDccg)
DCCGCLKSet(pllIndex, RV620_DCCGCLK_RELEASE);
@ -186,20 +187,22 @@ PLLPower(uint8 pllIndex, int command)
// Reset
snooze(2);
// Sometimes we have to keep an unused PLL running. Xorg Bug #18016
if ((Read32(PLL, RV620_EXT1_DIFF_POST_DIV_CNTL)
& RV62_EXT1_DIFF_DRIVER_ENABLE) == 0) {
Write32Mask(PLL, pllControlReg, 0x02, 0x02);
// Power Down
} else {
TRACE("%s: PHYA differential clock driver not disabled\n",
__func__);
if (info.device_chipset >= (RADEON_R600 | 0x20)) {
// Sometimes we have to keep an unused PLL running. X Bug #18016
if ((Read32(PLL, RV620_EXT1_DIFF_POST_DIV_CNTL)
& RV62_EXT1_DIFF_DRIVER_ENABLE) == 0) {
Write32Mask(PLL, pllControlReg, 0x02, 0x02);
// Power Down
} else {
TRACE("%s: PHYA differential clock driver not disabled\n",
__func__);
}
snooze(200);
Write32Mask(PLL, pllControlReg, 0x2000, 0x2000);
// Reset anti-glitch?
}
snooze(200);
Write32Mask(PLL, pllControlReg, 0x2000, 0x2000);
// Reset anti-glitch?
}
return B_OK;
@ -209,22 +212,121 @@ PLLPower(uint8 pllIndex, int command)
status_t
PLLSet(uint8 pllIndex, uint32 pixelClock)
{
TRACE("%s: enter to set pixel clock %d\n", __func__,
(int)pixelClock);
radeon_shared_info &info = *gInfo->shared_info;
bool hasDccg = DCCGCLKAvailable(pllIndex);
TRACE("%s: card has DCCG = %c\n", __func__, hasDccg ? 'y' : 'n');
uint16 reference = 0;
uint16 feedback = 0;
uint16 post = 0;
PLLCalculate(pixelClock, &reference, &feedback, &post);
if (info.device_chipset >= (RADEON_R600 | 0x20)) {
TRACE("%s : setting pixel clock %d on r620+\n", __func__,
(int)pixelClock);
PLLSetLowR620(pllIndex, pixelClock, reference,
feedback, post);
} else if (info.device_chipset < (RADEON_R600 | 0x20)) {
TRACE("%s : setting pixel clock %d on r600-r610\n", __func__,
(int)pixelClock);
PLLSetLowLegacy(pllIndex, pixelClock, reference,
feedback, post);
}
return B_OK;
}
void
PLLSetLowLegacy(uint8 pllIndex, uint32 pixelClock, uint16 reference,
uint16 feedback, uint16 post)
{
uint32 feedbackTemp = feedback << 16;
uint32 referenceTemp = reference;
radeon_shared_info &info = *gInfo->shared_info;
if (info.device_chipset == RADEON_R600)
feedbackTemp |= 0x00000030;
else if (info.device_chipset > RADEON_R600) {
if (feedback <= 0x24)
feedbackTemp |= 0x00000030;
else if (feedback <= 0x3F)
feedbackTemp |= 0x00000020;
} else
feedbackTemp |= Read32(PLL, EXT1_PPLL_FB_DIV) & 0x00000030;
uint32 postTemp = Read32(PLL, EXT1_PPLL_POST_DIV) & ~0x0000007F;
postTemp |= post & 0x0000007F;
uint32 control;
if (info.device_chipset == RADEON_R600)
control = 0x01130704;
else
PLLControlTable(RV610PLLControl, feedback);
if (!control)
control = Read32(PLL, EXT1_PPLL_CNTL);
Write32Mask(PLL, P1PLL_INT_SS_CNTL, 0, 0x00000001);
// Disable Spread Spectrum
Write32(PLL, EXT1_PPLL_REF_DIV_SRC, 0x01); /* XTAL */
Write32(PLL, EXT1_PPLL_POST_DIV_SRC, 0x00); /* source = reference */
Write32(PLL, EXT1_PPLL_UPDATE_LOCK, 0x01); /* lock */
Write32(PLL, EXT1_PPLL_REF_DIV, referenceTemp);
Write32(PLL, EXT1_PPLL_FB_DIV, feedbackTemp);
Write32(PLL, EXT1_PPLL_POST_DIV, postTemp);
Write32(PLL, EXT1_PPLL_CNTL, control);
Write32Mask(PLL, EXT1_PPLL_UPDATE_CNTL, 0x00010000, 0x00010000);
// No autoreset
Write32Mask(PLL, P1PLL_CNTL, 0, 0x04);
// Don't bypass calibration
/* We need to reset the anti glitch logic */
Write32Mask(PLL, P1PLL_CNTL, 0, 0x00000002);
// Power up
/* reset anti glitch logic */
Write32Mask(PLL, P1PLL_CNTL, 0x00002000, 0x00002000);
snooze(2);
Write32Mask(PLL, P1PLL_CNTL, 0, 0x00002000);
/* powerdown and reset */
Write32Mask(PLL, P1PLL_CNTL, 0x00000003, 0x00000003);
snooze(2);
Write32(PLL, EXT1_PPLL_UPDATE_LOCK, 0);
// Unlock
Write32Mask(PLL, EXT1_PPLL_UPDATE_CNTL, 0, 0x01);
// Done updating
Write32Mask(PLL, P1PLL_CNTL, 0, 0x02);
// Power up PLL
snooze(2);
PLLCalibrate(pllIndex);
Write32(PLL, EXT1_PPLL_POST_DIV_SRC, 0x01);
// Set source as PLL
// TODO : If CRT2 ah-la R500PLLCRTCGrab
PLLCRTCGrab(pllIndex, false);
}
void
PLLSetLowR620(uint8 pllIndex, uint32 pixelClock, uint16 reference,
uint16 feedback, uint16 post)
{
radeon_shared_info &info = *gInfo->shared_info;
bool hasDccg = DCCGCLKAvailable(pllIndex);
TRACE("%s: card has DCCG = %c\n", __func__, hasDccg ? 'y' : 'n');
if (hasDccg)
DCCGCLKSet(pllIndex, RV620_DCCGCLK_RESET);
@ -259,7 +361,8 @@ PLLSet(uint8 pllIndex, uint32 pixelClock)
postDivider |= post & 0x0000007F;
uint32 control;
if (info.device_chipset >= (RADEON_R600 & 0x70))
if (info.device_chipset >= (RADEON_R600 | 0x70))
control = PLLControlTable(RV670PLLControl, feedback);
else
control = PLLControlTable(RV610PLLControl, feedback);
@ -324,14 +427,12 @@ PLLSet(uint8 pllIndex, uint32 pixelClock)
DCCGCLKSet(pllIndex, RV620_DCCGCLK_GRAB);
TRACE("%s: PLLSet exit\n", __func__);
return B_OK;
}
status_t
PLLCalibrate(uint8 pllIndex)
{
uint16 pllControlReg = (pllIndex == 1) ? P2PLL_CNTL : P1PLL_CNTL;
Write32Mask(PLL, pllControlReg, 1, 0x01);
@ -407,6 +508,11 @@ PLLCRTCGrab(uint8 pllIndex, bool crt2)
bool
DCCGCLKAvailable(uint8 pllIndex)
{
radeon_shared_info &info = *gInfo->shared_info;
if (info.device_chipset < (RADEON_R600 | 0x20))
return false;
uint32 dccg = Read32(PLL, DCCG_DISP_CLK_SRCSEL) & 0x03;
if (dccg & 0x02)

View File

@ -42,6 +42,10 @@ struct PLL_Control {
status_t PLLCalculate(uint32 pixelClock, uint16 *reference, uint16 *feedback,
uint16 *post);
status_t PLLSet(uint8 pllIndex, uint32 pixelClock);
void PLLSetLowLegacy(uint8 pllIndex, uint32 pixelClock, uint16 reference,
uint16 feedback, uint16 post);
void PLLSetLowR620(uint8 pllIndex, uint32 pixelClock, uint16 reference,
uint16 feedback, uint16 post);
status_t PLLPower(uint8 pllIndex, int command);
status_t PLLCalibrate(uint8 pllIndex);
void PLLCRTCGrab(uint8 pllIndex, bool crt2);