From f2fe29a0db13c08df7d88755775246f91c290ebf Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sat, 9 Jul 2011 05:23:51 +0000 Subject: [PATCH] * 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 --- src/add-ons/accelerants/radeon_hd/dac.cpp | 73 ++++++++++++++++++++++ src/add-ons/accelerants/radeon_hd/dac.h | 1 + src/add-ons/accelerants/radeon_hd/mode.cpp | 59 ++++++++++------- src/add-ons/accelerants/radeon_hd/mode.h | 4 +- src/add-ons/accelerants/radeon_hd/pll.cpp | 25 ++++++-- src/add-ons/accelerants/radeon_hd/pll.h | 2 +- 6 files changed, 133 insertions(+), 31 deletions(-) diff --git a/src/add-ons/accelerants/radeon_hd/dac.cpp b/src/add-ons/accelerants/radeon_hd/dac.cpp index 82e490a2b8..a260d3e11a 100644 --- a/src/add-ons/accelerants/radeon_hd/dac.cpp +++ b/src/add-ons/accelerants/radeon_hd/dac.cpp @@ -22,6 +22,79 @@ extern "C" void _sPrintf(const char *format, ...); #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 DACGetElectrical(uint8 type, uint8 dac, uint8 *bandgap, uint8 *whitefine) diff --git a/src/add-ons/accelerants/radeon_hd/dac.h b/src/add-ons/accelerants/radeon_hd/dac.h index e69d06d69f..271e9b7d5f 100644 --- a/src/add-ons/accelerants/radeon_hd/dac.h +++ b/src/add-ons/accelerants/radeon_hd/dac.h @@ -22,6 +22,7 @@ #define FORMAT_TvCV 0x3 +bool DACSense(uint8 dacIndex); void DACGetElectrical(uint8 type, uint8 dac, uint8 *bandgap, uint8 *whitefine); void DACSet(uint8 dacIndex, uint32 crtid); void DACPower(uint8 dacIndex, int mode); diff --git a/src/add-ons/accelerants/radeon_hd/mode.cpp b/src/add-ons/accelerants/radeon_hd/mode.cpp index f41fb4d52a..a6813a058e 100644 --- a/src/add-ons/accelerants/radeon_hd/mode.cpp +++ b/src/add-ons/accelerants/radeon_hd/mode.cpp @@ -128,10 +128,12 @@ get_color_space_format(const display_mode &mode, uint32 &colorMode, // Blacks the screen out, useful for mode setting static void -CardBlankSet(bool blank) +CardBlankSet(uint8 crtid, bool blank) { - int blackColorReg = D1CRTC_BLACK_COLOR; - int blankControlReg = D1CRTC_BLANK_CONTROL; + int blackColorReg + = (crtid == 1) ? D2CRTC_BLACK_COLOR : D1CRTC_BLACK_COLOR; + int blankControlReg + = (crtid == 1) ? D2CRTC_BLANK_CONTROL : D1CRTC_BLANK_CONTROL; Write32(CRT, blackColorReg, 0); Write32Mask(CRT, blankControlReg, blank ? 1 << 8 : 0, 1 << 8); @@ -233,12 +235,10 @@ CardModeSet(display_mode *mode) Write32(CRT, gRegister->crtHTotal, displayTiming.h_total - 1); - // 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; + // Blanking + uint16 blankStart = displayTiming.h_total + + displayTiming.h_display - displayTiming.h_sync_start; + uint16 blankEnd = displayTiming.h_total - displayTiming.h_sync_start; Write32(CRT, gRegister->crtHBlank, blankStart | (blankEnd << 16)); @@ -254,11 +254,9 @@ CardModeSet(display_mode *mode) Write32(CRT, gRegister->crtVTotal, displayTiming.v_total - 1); - frontPorch = displayTiming.v_sync_start - displayTiming.v_display; - backPorch = displayTiming.v_total - displayTiming.v_sync_end; - - blankStart = frontPorch - OVERSCAN; - blankEnd = backPorch; + blankStart = displayTiming.v_total + + displayTiming.v_display - displayTiming.v_sync_start; + blankEnd = displayTiming.v_total - displayTiming.v_sync_start; Write32(CRT, gRegister->crtVBlank, blankStart | (blankEnd << 16)); @@ -290,13 +288,14 @@ static void CardModeScale(display_mode *mode) { // 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, (OVERSCAN << 16) | OVERSCAN); // LEFT | RIGHT Write32(CRT, D1MODE_EXT_OVERSCAN_TOP_BOTTOM, (OVERSCAN << 16) | OVERSCAN); // TOP | BOTTOM + #endif Write32(CRT, gRegister->viewportStart, 0); Write32(CRT, gRegister->viewportSize, @@ -305,7 +304,7 @@ CardModeScale(display_mode *mode) Write32(CRT, gRegister->sclTapControl, 0); Write32(CRT, gRegister->modeCenter, 2); // 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) { uint8 crtNumber = 0; + uint8 dacNumber = 0; 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); CardModeSet(mode); CardModeScale(mode); - PLLSet(0, mode->timing.pixel_clock); + + PLLSet(dacNumber, mode->timing.pixel_clock); // Set pixel clock Write32(CRT, D1GRPH_LUT_SEL, 0); - DACSet(crtNumber, 0); - // Set DAC A to crt 0 - DACPower(crtNumber, RHD_POWER_ON); - CardBlankSet(false); + DACSet(dacNumber, crtNumber); + + // TODO : Shutdown unused PLL/DAC + + // 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); TRACE("CRT0 Status: 0x%X\n", crtstatus); + crtstatus = Read32(CRT, D2CRTC_STATUS); + TRACE("CRT1 Status: 0x%X\n", crtstatus); return B_OK; } diff --git a/src/add-ons/accelerants/radeon_hd/mode.h b/src/add-ons/accelerants/radeon_hd/mode.h index 2a4e67aad2..cc481311a9 100644 --- a/src/add-ons/accelerants/radeon_hd/mode.h +++ b/src/add-ons/accelerants/radeon_hd/mode.h @@ -21,8 +21,8 @@ #define FMT1_REG_OFFSET 0x0000 #define FMT2_REG_OFFSET 0x800 -#define OVERSCAN 8 - // default overscan? Applied to all sides +#define OVERSCAN 0 + // TODO : Overscan and scaling support status_t detect_crt_ranges(); status_t create_mode_list(void); diff --git a/src/add-ons/accelerants/radeon_hd/pll.cpp b/src/add-ons/accelerants/radeon_hd/pll.cpp index 473c1a2ffb..8aa05f97bf 100644 --- a/src/add-ons/accelerants/radeon_hd/pll.cpp +++ b/src/add-ons/accelerants/radeon_hd/pll.cpp @@ -187,9 +187,15 @@ PLLPower(uint8 pllIndex, int command) snooze(2); 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 - if ((Read32(PLL, RV620_EXT1_DIFF_POST_DIV_CNTL) - & RV62_EXT1_DIFF_DRIVER_ENABLE) == 0) { + if ((Read32(PLL, pllDiffPostReg) + & pllDiffDriverEnable) == 0) { Write32Mask(PLL, pllControlReg, 0x02, 0x02); // Power Down } else { @@ -201,6 +207,11 @@ PLLPower(uint8 pllIndex, int command) Write32Mask(PLL, pllControlReg, 0x2000, 0x2000); // 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); // 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); // needed and undocumented - PLLCRTCGrab(pllIndex, false); + // TODO : better way to grab crt to work on? + PLLCRTCGrab(pllIndex, gRegister->crtid); if (hasDccg) DCCGCLKSet(pllIndex, RV620_DCCGCLK_GRAB); @@ -492,11 +505,11 @@ PLLCalibrate(uint8 pllIndex) void -PLLCRTCGrab(uint8 pllIndex, bool crt2) +PLLCRTCGrab(uint8 pllIndex, uint8 crtid) { bool pll2IsCurrent; - if (!crt2) { + if (crtid == 0) { pll2IsCurrent = Read32(PLL, PCLK_CRTC1_CNTL) & 0x00010000; Write32Mask(PLL, PCLK_CRTC1_CNTL, (pllIndex == 0) ? 0x00010000 : 0, diff --git a/src/add-ons/accelerants/radeon_hd/pll.h b/src/add-ons/accelerants/radeon_hd/pll.h index 4a9a7d603f..5733e2b004 100644 --- a/src/add-ons/accelerants/radeon_hd/pll.h +++ b/src/add-ons/accelerants/radeon_hd/pll.h @@ -42,7 +42,7 @@ 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); +void PLLCRTCGrab(uint8 pllIndex, uint8 crtid); bool DCCGCLKAvailable(uint8 pllIndex); void DCCGCLKSet(uint8 pllIndex, int set);