diff --git a/src/add-ons/accelerants/radeon_hd/Jamfile b/src/add-ons/accelerants/radeon_hd/Jamfile index c6613d21e5..e4e7da9650 100644 --- a/src/add-ons/accelerants/radeon_hd/Jamfile +++ b/src/add-ons/accelerants/radeon_hd/Jamfile @@ -13,6 +13,7 @@ Addon radeon_hd.accelerant : engine.cpp hooks.cpp pll.cpp + dac.cpp mode.cpp bios.cpp create_display_modes.cpp diff --git a/src/add-ons/accelerants/radeon_hd/accelerant.h b/src/add-ons/accelerants/radeon_hd/accelerant.h index 1c3c64834f..afb5b626a6 100644 --- a/src/add-ons/accelerants/radeon_hd/accelerant.h +++ b/src/add-ons/accelerants/radeon_hd/accelerant.h @@ -13,6 +13,7 @@ #include "mode.h" #include "radeon_hd.h" #include "pll.h" +#include "dac.h" #include diff --git a/src/add-ons/accelerants/radeon_hd/dac.cpp b/src/add-ons/accelerants/radeon_hd/dac.cpp new file mode 100644 index 0000000000..b72092ae7c --- /dev/null +++ b/src/add-ons/accelerants/radeon_hd/dac.cpp @@ -0,0 +1,158 @@ +/* + * Copyright 2006-2011, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Alexander von Gluck, kallisti5@unixzen.com + */ + + +#include "accelerant_protos.h" +#include "accelerant.h" +#include "utility.h" +#include "dac.h" + + +#define TRACE_DAC +#ifdef TRACE_DAC +extern "C" void _sPrintf(const char *format, ...); +# define TRACE(x...) _sPrintf("radeon_hd: " x) +#else +# define TRACE(x...) ; +#endif + + +void +DACGetElectrical(uint8 type, uint8 dac, + uint8 *bandgap, uint8 *whitefine) +{ + radeon_shared_info &info = *gInfo->shared_info; + + // These lookups are based on PCIID, maybe need + // to extract more from AtomBIOS? + struct + { + uint16 pciIdMin; + uint16 pciIdMax; + uint8 bandgap[2][4]; + uint8 whitefine[2][4]; + } list[] = { + { 0x791E, 0x791F, + { { 0x07, 0x07, 0x07, 0x07 }, + { 0x07, 0x07, 0x07, 0x07 } }, + { { 0x09, 0x09, 0x04, 0x09 }, + { 0x09, 0x09, 0x04, 0x09 } }, + }, + { 0x793F, 0x7942, + { { 0x09, 0x09, 0x09, 0x09 }, + { 0x09, 0x09, 0x09, 0x09 } }, + { { 0x0a, 0x0a, 0x08, 0x0a }, + { 0x0a, 0x0a, 0x08, 0x0a } }, + }, + { 0x9500, 0x9519, + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + { { 0x00, 0x00, 0x20, 0x00 }, + { 0x25, 0x25, 0x26, 0x26 } }, + }, + { 0, 0, + { { 0, 0, 0, 0 }, + { 0, 0, 0, 0 } }, + { { 0, 0, 0, 0 }, + { 0, 0, 0, 0 } } + } + }; + + *bandgap = 0; + *whitefine = 0; + + // TODO : ATOM BIOS Bandgap / Whitefine lookup + + if (*bandgap == 0 || *whitefine == 0) { + int i = 0; + while (list[i].pciIdMin != 0) { + if (list[i].pciIdMin <= info.device_id + && list[i].pciIdMax >= info.device_id) { + if (*bandgap == 0) *bandgap = list[i].bandgap[dac][type]; + if (*whitefine == 0) *whitefine = list[i].whitefine[dac][type]; + break; + } + i++; + } + if (list[i].pciIdMin != 0) + TRACE("%s: found new BandGap / WhiteFine in table for card!\n", + __func__); + } +} + + +void +DACSet(uint8 dacIndex, uint32 crtid) +{ + bool istv = false; + uint8 bandGap; + uint8 whiteFine; + + // BIG TODO : NTSC, PAL, ETC. We assume VGA for now + uint8 standard = FORMAT_VGA; /* VGA */ + + DACGetElectrical(standard, dacIndex, &bandGap, &whiteFine); + + uint32 mask = 0; + if (bandGap) mask |= 0xFF << 16; + if (whiteFine) mask |= 0xFF << 8; + + uint32 dacOffset = (dacIndex == 1) ? REG_DACB_OFFSET : REG_DACA_OFFSET; + + Write32Mask(OUT, dacOffset + DACA_CONTROL1, standard, 0x000000FF); + /* white level fine adjust */ + Write32Mask(OUT, dacOffset + DACA_CONTROL1, (bandGap << 16) + | (whiteFine << 8), mask); + + if (istv) { + /* tv enable */ + if (dacIndex) /* TV mux only available on DACB */ + Write32Mask(OUT, dacOffset + DACA_CONTROL2, + 0x00000100, 0x0000FF00); + + /* select tv encoder */ + Write32Mask(OUT, dacOffset + DACA_SOURCE_SELECT, + 0x00000002, 0x00000003); + } else { + if (dacIndex) /* TV mux only available on DACB */ + Write32Mask(OUT, dacOffset + DACA_CONTROL2, 0, 0x0000FF00); + + /* select a crtc */ + Write32Mask(OUT, dacOffset + DACA_SOURCE_SELECT, + crtid & 0x01, 0x00000003); + } + + Write32Mask(OUT, dacOffset + DACA_FORCE_OUTPUT_CNTL, + 0x00000701, 0x00000701); + Write32Mask(OUT, dacOffset + DACA_FORCE_DATA, + 0, 0x0000FFFF); +} + + +void +DACPower(uint8 dacIndex, int mode) +{ + uint32 dacOffset = (dacIndex == 1) ? REG_DACB_OFFSET : REG_DACA_OFFSET; + uint32 powerdown; + + switch (mode) { + // TODO : RHD_POWER_OFF, etc + case RHD_POWER_ON: + // TODO : SensedType Detection? + powerdown = 0; + Write32(OUT, dacOffset + DACA_ENABLE, 1); + Write32(OUT, dacOffset + DACA_POWERDOWN, 0); + snooze(14); + Write32Mask(OUT, dacOffset + DACA_POWERDOWN, powerdown, 0xFFFFFF00); + snooze(2); + Write32(OUT, dacOffset + DACA_FORCE_OUTPUT_CNTL, 0); + Write32Mask(OUT, dacOffset + DACA_SYNC_SELECT, 0, 0x00000101); + Write32(OUT, dacOffset + DACA_SYNC_TRISTATE_CONTROL, 0); + return; + } +} diff --git a/src/add-ons/accelerants/radeon_hd/dac.h b/src/add-ons/accelerants/radeon_hd/dac.h new file mode 100644 index 0000000000..4fb485d6d6 --- /dev/null +++ b/src/add-ons/accelerants/radeon_hd/dac.h @@ -0,0 +1,29 @@ +/* + * Copyright 2006-2011, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Alexander von Gluck, kallisti5@unixzen.com + */ + +#ifndef RADEON_HD_DAC_H +#define RADEON_HD_DAC_H + +// DAC Offsets +#define REG_DACA_OFFSET 0 +#define REG_DACB_OFFSET 0x200 +#define RV620_REG_DACA_OFFSET 0 +#define RV620_REG_DACB_OFFSET 0x100 + +// Signal types +#define FORMAT_PAL 0x0 +#define FORMAT_NTSC 0x1 +#define FORMAT_VGA 0x2 +#define FORMAT_TvCV 0x3 + +void DACGetElectrical(uint8 type, uint8 dac, uint8 *bandgap, uint8 *whitefine); +void DACSet(uint8 dacIndex, uint32 crtid); +void DACPower(uint8 dacIndex, int mode); + + +#endif diff --git a/src/add-ons/accelerants/radeon_hd/mode.cpp b/src/add-ons/accelerants/radeon_hd/mode.cpp index 3dc8ca3926..e386fce277 100644 --- a/src/add-ons/accelerants/radeon_hd/mode.cpp +++ b/src/add-ons/accelerants/radeon_hd/mode.cpp @@ -335,7 +335,7 @@ CardModeScale(display_mode *mode) status_t radeon_set_display_mode(display_mode *mode) { - int crtNumber = 0; + uint8 crtNumber = 0; init_registers(crtNumber); @@ -344,19 +344,20 @@ radeon_set_display_mode(display_mode *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); - #endif + // Set pixel clock + DACSet(0, 0); + // Set DAC A to crt 0 - // ensure graphics are enabled and powered on + // ensure graphics are enabled and powered on (CRT Power) + // aka D1Power Write32Mask(CRT, D1GRPH_ENABLE, 0x00000001, 0x00000001); snooze(2); Write32Mask(CRT, D1CRTC_CONTROL, 0, 0x01000000); /* enable read requests */ Write32Mask(CRT, D1CRTC_CONTROL, 1, 1); + DACPower(0, RHD_POWER_ON); + int32 crtstatus = Read32(CRT, D1CRTC_STATUS); TRACE("CRT0 Status: 0x%X\n", crtstatus); diff --git a/src/add-ons/accelerants/radeon_hd/pll.cpp b/src/add-ons/accelerants/radeon_hd/pll.cpp index e50c5771b3..5297ea887d 100644 --- a/src/add-ons/accelerants/radeon_hd/pll.cpp +++ b/src/add-ons/accelerants/radeon_hd/pll.cpp @@ -576,26 +576,3 @@ DCCGCLKSet(uint8 pllIndex, int set) } } - -void -DACPower(uint8 dacIndex, int mode) -{ - uint32 dacOffset = (dacIndex == 1) ? REG_DACB_OFFSET : REG_DACA_OFFSET; - uint32 powerdown; - - switch (mode) { - case RHD_POWER_ON: - // TODO : SensedType Detection? - powerdown = 0; - Write32(OUT, dacOffset + DACA_ENABLE, 1); - Write32(OUT, dacOffset + DACA_POWERDOWN, 0); - snooze(14); - Write32Mask(OUT, dacOffset + DACA_POWERDOWN, powerdown, 0xFFFFFF00); - snooze(2); - Write32(OUT, dacOffset + DACA_FORCE_OUTPUT_CNTL, 0); - Write32Mask(OUT, dacOffset + DACA_SYNC_SELECT, 0, 0x00000101); - Write32(OUT, dacOffset + DACA_SYNC_TRISTATE_CONTROL, 0); - return; - } -} - diff --git a/src/add-ons/accelerants/radeon_hd/pll.h b/src/add-ons/accelerants/radeon_hd/pll.h index 6604707fc4..4a9a7d603f 100644 --- a/src/add-ons/accelerants/radeon_hd/pll.h +++ b/src/add-ons/accelerants/radeon_hd/pll.h @@ -26,12 +26,6 @@ #define RV620_DCCGCLK_GRAB 1 #define RV620_DCCGCLK_RELEASE 2 -// DAC Offsets -#define REG_DACA_OFFSET 0 -#define REG_DACB_OFFSET 0x200 -#define RV620_REG_DACA_OFFSET 0 -#define RV620_REG_DACB_OFFSET 0x100 - struct PLL_Control { uint16 feedbackDivider; // 0xFFFF is the endmarker @@ -51,7 +45,6 @@ status_t PLLCalibrate(uint8 pllIndex); void PLLCRTCGrab(uint8 pllIndex, bool crt2); bool DCCGCLKAvailable(uint8 pllIndex); void DCCGCLKSet(uint8 pllIndex, int set); -void DACPower(uint8 dacIndex, int mode); #endif /* RADEON_HD_PLL_H */