* Final (hopefully?) calculation for blank start/end
* Lets actually call PLLPower after PLLSet * Improve screen blanking function * Detect DAC/PLL to use separately from CRT id * Add DACSense that senses displays on DACA/DACB * Grab CRT in PLL code via gRegister crtid * Set overscan to 0 for now * Setting extended video modes now kinda works sometimes :-/ git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42397 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
8f3fe015dc
commit
f2fe29a0db
@ -22,6 +22,79 @@ extern "C" void _sPrintf(const char *format, ...);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
DACSense(uint8 dacIndex)
|
||||||
|
{
|
||||||
|
uint32 dacOffset = (dacIndex == 1) ? REG_DACB_OFFSET : REG_DACA_OFFSET;
|
||||||
|
|
||||||
|
// Backup current DAC values
|
||||||
|
uint32 compEnable = Read32(OUT, dacOffset + DACA_COMPARATOR_ENABLE);
|
||||||
|
uint32 control1 = Read32(OUT, dacOffset + DACA_CONTROL1);
|
||||||
|
uint32 control2 = Read32(OUT, dacOffset + DACA_CONTROL2);
|
||||||
|
uint32 detectControl = Read32(OUT, dacOffset + DACA_AUTODETECT_CONTROL);
|
||||||
|
uint32 enable = Read32(OUT, dacOffset + DACA_ENABLE);
|
||||||
|
|
||||||
|
Write32(OUT, dacOffset + DACA_ENABLE, 1);
|
||||||
|
// Acknowledge autodetect
|
||||||
|
Write32Mask(OUT, dacOffset + DACA_AUTODETECT_INT_CONTROL, 0x01, 0x01);
|
||||||
|
Write32Mask(OUT, dacOffset + DACA_AUTODETECT_CONTROL, 0, 0x00000003);
|
||||||
|
Write32Mask(OUT, dacOffset + DACA_CONTROL2, 0, 0x00000001);
|
||||||
|
Write32Mask(OUT, dacOffset + DACA_CONTROL2, 0, 0x00ff0000);
|
||||||
|
|
||||||
|
Write32(OUT, dacOffset + DACA_FORCE_DATA, 0);
|
||||||
|
Write32Mask(OUT, dacOffset + DACA_CONTROL2, 0x00000001, 0x0000001);
|
||||||
|
|
||||||
|
Write32Mask(OUT, dacOffset + DACA_COMPARATOR_ENABLE,
|
||||||
|
0x00070000, 0x00070101);
|
||||||
|
Write32(OUT, dacOffset + DACA_CONTROL1, 0x00050802);
|
||||||
|
Write32Mask(OUT, dacOffset + DACA_POWERDOWN, 0, 0x00000001);
|
||||||
|
// Shutdown Bandgap voltage reference
|
||||||
|
|
||||||
|
snooze(5);
|
||||||
|
|
||||||
|
Write32Mask(OUT, dacOffset + DACA_POWERDOWN, 0, 0x01010100);
|
||||||
|
// Shutdown RGB
|
||||||
|
|
||||||
|
Write32(OUT, dacOffset + DACA_FORCE_DATA, 0x1e6);
|
||||||
|
// 486 out of 1024
|
||||||
|
snooze(200);
|
||||||
|
|
||||||
|
Write32Mask(OUT, dacOffset + DACA_POWERDOWN, 0x01010100, 0x01010100);
|
||||||
|
// Enable RGB
|
||||||
|
snooze(88);
|
||||||
|
|
||||||
|
Write32Mask(OUT, dacOffset + DACA_POWERDOWN, 0, 0x01010100);
|
||||||
|
// Shutdown RGB
|
||||||
|
|
||||||
|
Write32Mask(OUT, dacOffset + DACA_COMPARATOR_ENABLE,
|
||||||
|
0x00000100, 0x00000100);
|
||||||
|
|
||||||
|
snooze(100);
|
||||||
|
|
||||||
|
// Get detected RGB channels
|
||||||
|
// If only G is found, it could be a monochrome monitor, but we
|
||||||
|
// don't bother checking.
|
||||||
|
uint8 out = (Read32(OUT, dacOffset + DACA_COMPARATOR_OUTPUT) & 0x0E) >> 1;
|
||||||
|
|
||||||
|
// Restore stored DAC values
|
||||||
|
Write32Mask(OUT, dacOffset + DACA_COMPARATOR_ENABLE,
|
||||||
|
compEnable, 0x00FFFFFF);
|
||||||
|
Write32(OUT, dacOffset + DACA_CONTROL1, control1);
|
||||||
|
Write32Mask(OUT, dacOffset + DACA_CONTROL2, control2, 0x000001FF);
|
||||||
|
Write32Mask(OUT, dacOffset + DACA_AUTODETECT_CONTROL,
|
||||||
|
detectControl, 0x000000FF);
|
||||||
|
Write32Mask(OUT, dacOffset + DACA_ENABLE, enable, 0x000000FF);
|
||||||
|
|
||||||
|
if (out == 0x7) {
|
||||||
|
TRACE("%s: DAC%d : Display device attached\n", __func__, dacIndex);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
TRACE("%s: DAC%d : No display device attached\n", __func__, dacIndex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
DACGetElectrical(uint8 type, uint8 dac,
|
DACGetElectrical(uint8 type, uint8 dac,
|
||||||
uint8 *bandgap, uint8 *whitefine)
|
uint8 *bandgap, uint8 *whitefine)
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#define FORMAT_TvCV 0x3
|
#define FORMAT_TvCV 0x3
|
||||||
|
|
||||||
|
|
||||||
|
bool DACSense(uint8 dacIndex);
|
||||||
void DACGetElectrical(uint8 type, uint8 dac, uint8 *bandgap, uint8 *whitefine);
|
void DACGetElectrical(uint8 type, uint8 dac, uint8 *bandgap, uint8 *whitefine);
|
||||||
void DACSet(uint8 dacIndex, uint32 crtid);
|
void DACSet(uint8 dacIndex, uint32 crtid);
|
||||||
void DACPower(uint8 dacIndex, int mode);
|
void DACPower(uint8 dacIndex, int mode);
|
||||||
|
@ -128,10 +128,12 @@ get_color_space_format(const display_mode &mode, uint32 &colorMode,
|
|||||||
|
|
||||||
// Blacks the screen out, useful for mode setting
|
// Blacks the screen out, useful for mode setting
|
||||||
static void
|
static void
|
||||||
CardBlankSet(bool blank)
|
CardBlankSet(uint8 crtid, bool blank)
|
||||||
{
|
{
|
||||||
int blackColorReg = D1CRTC_BLACK_COLOR;
|
int blackColorReg
|
||||||
int blankControlReg = D1CRTC_BLANK_CONTROL;
|
= (crtid == 1) ? D2CRTC_BLACK_COLOR : D1CRTC_BLACK_COLOR;
|
||||||
|
int blankControlReg
|
||||||
|
= (crtid == 1) ? D2CRTC_BLANK_CONTROL : D1CRTC_BLANK_CONTROL;
|
||||||
|
|
||||||
Write32(CRT, blackColorReg, 0);
|
Write32(CRT, blackColorReg, 0);
|
||||||
Write32Mask(CRT, blankControlReg, blank ? 1 << 8 : 0, 1 << 8);
|
Write32Mask(CRT, blankControlReg, blank ? 1 << 8 : 0, 1 << 8);
|
||||||
@ -233,12 +235,10 @@ CardModeSet(display_mode *mode)
|
|||||||
Write32(CRT, gRegister->crtHTotal,
|
Write32(CRT, gRegister->crtHTotal,
|
||||||
displayTiming.h_total - 1);
|
displayTiming.h_total - 1);
|
||||||
|
|
||||||
// Calculate blanking
|
// Blanking
|
||||||
uint16 frontPorch = displayTiming.h_sync_start - displayTiming.h_display;
|
uint16 blankStart = displayTiming.h_total
|
||||||
uint16 backPorch = displayTiming.h_total - displayTiming.h_sync_end;
|
+ displayTiming.h_display - displayTiming.h_sync_start;
|
||||||
|
uint16 blankEnd = displayTiming.h_total - displayTiming.h_sync_start;
|
||||||
uint16 blankStart = frontPorch - OVERSCAN;
|
|
||||||
uint16 blankEnd = backPorch;
|
|
||||||
|
|
||||||
Write32(CRT, gRegister->crtHBlank,
|
Write32(CRT, gRegister->crtHBlank,
|
||||||
blankStart | (blankEnd << 16));
|
blankStart | (blankEnd << 16));
|
||||||
@ -254,11 +254,9 @@ CardModeSet(display_mode *mode)
|
|||||||
Write32(CRT, gRegister->crtVTotal,
|
Write32(CRT, gRegister->crtVTotal,
|
||||||
displayTiming.v_total - 1);
|
displayTiming.v_total - 1);
|
||||||
|
|
||||||
frontPorch = displayTiming.v_sync_start - displayTiming.v_display;
|
blankStart = displayTiming.v_total
|
||||||
backPorch = displayTiming.v_total - displayTiming.v_sync_end;
|
+ displayTiming.v_display - displayTiming.v_sync_start;
|
||||||
|
blankEnd = displayTiming.v_total - displayTiming.v_sync_start;
|
||||||
blankStart = frontPorch - OVERSCAN;
|
|
||||||
blankEnd = backPorch;
|
|
||||||
|
|
||||||
Write32(CRT, gRegister->crtVBlank,
|
Write32(CRT, gRegister->crtVBlank,
|
||||||
blankStart | (blankEnd << 16));
|
blankStart | (blankEnd << 16));
|
||||||
@ -290,13 +288,14 @@ static void
|
|||||||
CardModeScale(display_mode *mode)
|
CardModeScale(display_mode *mode)
|
||||||
{
|
{
|
||||||
// No scaling
|
// No scaling
|
||||||
//Write32(CRT, gRegister->sclUpdate, (1<<16));// Lock
|
Write32(CRT, gRegister->sclUpdate, (1<<16));// Lock
|
||||||
|
|
||||||
// For now, default overscan
|
#if 0
|
||||||
Write32(CRT, D1MODE_EXT_OVERSCAN_LEFT_RIGHT,
|
Write32(CRT, D1MODE_EXT_OVERSCAN_LEFT_RIGHT,
|
||||||
(OVERSCAN << 16) | OVERSCAN); // LEFT | RIGHT
|
(OVERSCAN << 16) | OVERSCAN); // LEFT | RIGHT
|
||||||
Write32(CRT, D1MODE_EXT_OVERSCAN_TOP_BOTTOM,
|
Write32(CRT, D1MODE_EXT_OVERSCAN_TOP_BOTTOM,
|
||||||
(OVERSCAN << 16) | OVERSCAN); // TOP | BOTTOM
|
(OVERSCAN << 16) | OVERSCAN); // TOP | BOTTOM
|
||||||
|
#endif
|
||||||
|
|
||||||
Write32(CRT, gRegister->viewportStart, 0);
|
Write32(CRT, gRegister->viewportStart, 0);
|
||||||
Write32(CRT, gRegister->viewportSize,
|
Write32(CRT, gRegister->viewportSize,
|
||||||
@ -305,7 +304,7 @@ CardModeScale(display_mode *mode)
|
|||||||
Write32(CRT, gRegister->sclTapControl, 0);
|
Write32(CRT, gRegister->sclTapControl, 0);
|
||||||
Write32(CRT, gRegister->modeCenter, 2);
|
Write32(CRT, gRegister->modeCenter, 2);
|
||||||
// D1MODE_DATA_FORMAT?
|
// D1MODE_DATA_FORMAT?
|
||||||
//Write32(CRT, gRegister->sclUpdate, 0); // Unlock
|
Write32(CRT, gRegister->sclUpdate, 0); // Unlock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -313,24 +312,40 @@ status_t
|
|||||||
radeon_set_display_mode(display_mode *mode)
|
radeon_set_display_mode(display_mode *mode)
|
||||||
{
|
{
|
||||||
uint8 crtNumber = 0;
|
uint8 crtNumber = 0;
|
||||||
|
uint8 dacNumber = 0;
|
||||||
|
|
||||||
init_registers(crtNumber);
|
init_registers(crtNumber);
|
||||||
|
|
||||||
|
// TODO : this obviously breaks horribly on attached multiple outputs
|
||||||
|
if (DACSense(0))
|
||||||
|
dacNumber = 0;
|
||||||
|
else if (DACSense(1))
|
||||||
|
dacNumber = 1;
|
||||||
|
|
||||||
CardFBSet(mode);
|
CardFBSet(mode);
|
||||||
CardModeSet(mode);
|
CardModeSet(mode);
|
||||||
CardModeScale(mode);
|
CardModeScale(mode);
|
||||||
PLLSet(0, mode->timing.pixel_clock);
|
|
||||||
|
PLLSet(dacNumber, mode->timing.pixel_clock);
|
||||||
// Set pixel clock
|
// Set pixel clock
|
||||||
|
|
||||||
Write32(CRT, D1GRPH_LUT_SEL, 0);
|
Write32(CRT, D1GRPH_LUT_SEL, 0);
|
||||||
|
|
||||||
DACSet(crtNumber, 0);
|
DACSet(dacNumber, crtNumber);
|
||||||
// Set DAC A to crt 0
|
|
||||||
DACPower(crtNumber, RHD_POWER_ON);
|
// TODO : Shutdown unused PLL/DAC
|
||||||
CardBlankSet(false);
|
|
||||||
|
// Power up the output
|
||||||
|
PLLPower(dacNumber, RHD_POWER_ON);
|
||||||
|
DACPower(dacNumber, RHD_POWER_ON);
|
||||||
|
|
||||||
|
// Ensure screen isn't blanked
|
||||||
|
CardBlankSet(crtNumber, false);
|
||||||
|
|
||||||
int32 crtstatus = Read32(CRT, D1CRTC_STATUS);
|
int32 crtstatus = Read32(CRT, D1CRTC_STATUS);
|
||||||
TRACE("CRT0 Status: 0x%X\n", crtstatus);
|
TRACE("CRT0 Status: 0x%X\n", crtstatus);
|
||||||
|
crtstatus = Read32(CRT, D2CRTC_STATUS);
|
||||||
|
TRACE("CRT1 Status: 0x%X\n", crtstatus);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,8 @@
|
|||||||
#define FMT1_REG_OFFSET 0x0000
|
#define FMT1_REG_OFFSET 0x0000
|
||||||
#define FMT2_REG_OFFSET 0x800
|
#define FMT2_REG_OFFSET 0x800
|
||||||
|
|
||||||
#define OVERSCAN 8
|
#define OVERSCAN 0
|
||||||
// default overscan? Applied to all sides
|
// TODO : Overscan and scaling support
|
||||||
|
|
||||||
status_t detect_crt_ranges();
|
status_t detect_crt_ranges();
|
||||||
status_t create_mode_list(void);
|
status_t create_mode_list(void);
|
||||||
|
@ -187,9 +187,15 @@ PLLPower(uint8 pllIndex, int command)
|
|||||||
snooze(2);
|
snooze(2);
|
||||||
|
|
||||||
if (info.device_chipset >= (RADEON_R600 | 0x20)) {
|
if (info.device_chipset >= (RADEON_R600 | 0x20)) {
|
||||||
|
uint16 pllDiffPostReg
|
||||||
|
= (pllIndex == 1) ? RV620_EXT2_DIFF_POST_DIV_CNTL
|
||||||
|
: RV620_EXT1_DIFF_POST_DIV_CNTL;
|
||||||
|
uint16 pllDiffDriverEnable
|
||||||
|
= (pllIndex == 1) ? RV62_EXT2_DIFF_DRIVER_ENABLE
|
||||||
|
: RV62_EXT1_DIFF_DRIVER_ENABLE;
|
||||||
// Sometimes we have to keep an unused PLL running. X Bug #18016
|
// Sometimes we have to keep an unused PLL running. X Bug #18016
|
||||||
if ((Read32(PLL, RV620_EXT1_DIFF_POST_DIV_CNTL)
|
if ((Read32(PLL, pllDiffPostReg)
|
||||||
& RV62_EXT1_DIFF_DRIVER_ENABLE) == 0) {
|
& pllDiffDriverEnable) == 0) {
|
||||||
Write32Mask(PLL, pllControlReg, 0x02, 0x02);
|
Write32Mask(PLL, pllControlReg, 0x02, 0x02);
|
||||||
// Power Down
|
// Power Down
|
||||||
} else {
|
} else {
|
||||||
@ -201,6 +207,11 @@ PLLPower(uint8 pllIndex, int command)
|
|||||||
|
|
||||||
Write32Mask(PLL, pllControlReg, 0x2000, 0x2000);
|
Write32Mask(PLL, pllControlReg, 0x2000, 0x2000);
|
||||||
// Reset anti-glitch?
|
// Reset anti-glitch?
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Write32Mask(PLL, pllControlReg, 0x02, 0x02);
|
||||||
|
// Power Down
|
||||||
|
snooze(200);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,7 +344,8 @@ PLLSetLowLegacy(uint8 pllIndex, uint32 pixelClock, uint16 reference,
|
|||||||
Write32(PLL, pllExtPostDivSrc, 0x01);
|
Write32(PLL, pllExtPostDivSrc, 0x01);
|
||||||
// Set source as PLL
|
// Set source as PLL
|
||||||
|
|
||||||
PLLCRTCGrab(pllIndex, false);
|
// TODO : better way to grab crt to work on?
|
||||||
|
PLLCRTCGrab(pllIndex, gRegister->crtid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -448,7 +460,8 @@ PLLSetLowR620(uint8 pllIndex, uint32 pixelClock, uint16 reference,
|
|||||||
Write32Mask(PLL, pllCntl, 0, 0x80000000);
|
Write32Mask(PLL, pllCntl, 0, 0x80000000);
|
||||||
// needed and undocumented
|
// needed and undocumented
|
||||||
|
|
||||||
PLLCRTCGrab(pllIndex, false);
|
// TODO : better way to grab crt to work on?
|
||||||
|
PLLCRTCGrab(pllIndex, gRegister->crtid);
|
||||||
|
|
||||||
if (hasDccg)
|
if (hasDccg)
|
||||||
DCCGCLKSet(pllIndex, RV620_DCCGCLK_GRAB);
|
DCCGCLKSet(pllIndex, RV620_DCCGCLK_GRAB);
|
||||||
@ -492,11 +505,11 @@ PLLCalibrate(uint8 pllIndex)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PLLCRTCGrab(uint8 pllIndex, bool crt2)
|
PLLCRTCGrab(uint8 pllIndex, uint8 crtid)
|
||||||
{
|
{
|
||||||
bool pll2IsCurrent;
|
bool pll2IsCurrent;
|
||||||
|
|
||||||
if (!crt2) {
|
if (crtid == 0) {
|
||||||
pll2IsCurrent = Read32(PLL, PCLK_CRTC1_CNTL) & 0x00010000;
|
pll2IsCurrent = Read32(PLL, PCLK_CRTC1_CNTL) & 0x00010000;
|
||||||
|
|
||||||
Write32Mask(PLL, PCLK_CRTC1_CNTL, (pllIndex == 0) ? 0x00010000 : 0,
|
Write32Mask(PLL, PCLK_CRTC1_CNTL, (pllIndex == 0) ? 0x00010000 : 0,
|
||||||
|
@ -42,7 +42,7 @@ void PLLSetLowR620(uint8 pllIndex, uint32 pixelClock, uint16 reference,
|
|||||||
uint16 feedback, uint16 post);
|
uint16 feedback, uint16 post);
|
||||||
status_t PLLPower(uint8 pllIndex, int command);
|
status_t PLLPower(uint8 pllIndex, int command);
|
||||||
status_t PLLCalibrate(uint8 pllIndex);
|
status_t PLLCalibrate(uint8 pllIndex);
|
||||||
void PLLCRTCGrab(uint8 pllIndex, bool crt2);
|
void PLLCRTCGrab(uint8 pllIndex, uint8 crtid);
|
||||||
bool DCCGCLKAvailable(uint8 pllIndex);
|
bool DCCGCLKAvailable(uint8 pllIndex);
|
||||||
void DCCGCLKSet(uint8 pllIndex, int set);
|
void DCCGCLKSet(uint8 pllIndex, int set);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user