* 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:
Alexander von Gluck IV 2011-07-09 05:23:51 +00:00
parent 8f3fe015dc
commit f2fe29a0db
6 changed files with 133 additions and 31 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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;
} }

View File

@ -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);

View File

@ -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,

View File

@ -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);