From 84bcfa3d4bc3f64b82bb80e0b5e88e284f191627 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Tue, 12 Jul 2011 20:14:31 +0000 Subject: [PATCH] * Add mc.cpp for memory controller functions * Remove read32MC as it doesn't apply to radeon cards >= r600 * Add tmds.cpp for tmds connected monitor management (current radeons only have TMDSA for the moment) still needs TDMSPower, etc. * Add some MC calls to mode.cpp, causes KDL so commented out atm. * Add command to idle all DACs (although POWER_RESET doesn't do anything on DACs, we should be consistent) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42416 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/accelerants/radeon_hd/Jamfile | 2 + .../accelerants/radeon_hd/accelerant.cpp | 1 + .../accelerants/radeon_hd/accelerant.h | 66 ++------------ src/add-ons/accelerants/radeon_hd/dac.cpp | 13 +++ src/add-ons/accelerants/radeon_hd/dac.h | 1 + src/add-ons/accelerants/radeon_hd/mc.cpp | 88 +++++++++++++++++++ src/add-ons/accelerants/radeon_hd/mc.h | 22 +++++ src/add-ons/accelerants/radeon_hd/mode.cpp | 15 +++- src/add-ons/accelerants/radeon_hd/mode.h | 1 + src/add-ons/accelerants/radeon_hd/tmds.cpp | 52 +++++++++++ src/add-ons/accelerants/radeon_hd/tmds.h | 15 ++++ 11 files changed, 216 insertions(+), 60 deletions(-) create mode 100644 src/add-ons/accelerants/radeon_hd/mc.cpp create mode 100644 src/add-ons/accelerants/radeon_hd/mc.h create mode 100644 src/add-ons/accelerants/radeon_hd/tmds.cpp create mode 100644 src/add-ons/accelerants/radeon_hd/tmds.h diff --git a/src/add-ons/accelerants/radeon_hd/Jamfile b/src/add-ons/accelerants/radeon_hd/Jamfile index e4e7da9650..55d9702f7e 100644 --- a/src/add-ons/accelerants/radeon_hd/Jamfile +++ b/src/add-ons/accelerants/radeon_hd/Jamfile @@ -13,7 +13,9 @@ Addon radeon_hd.accelerant : engine.cpp hooks.cpp pll.cpp + mc.cpp dac.cpp + tmds.cpp mode.cpp bios.cpp create_display_modes.cpp diff --git a/src/add-ons/accelerants/radeon_hd/accelerant.cpp b/src/add-ons/accelerants/radeon_hd/accelerant.cpp index fd99a4ddd7..2b8cea78eb 100644 --- a/src/add-ons/accelerants/radeon_hd/accelerant.cpp +++ b/src/add-ons/accelerants/radeon_hd/accelerant.cpp @@ -13,6 +13,7 @@ #include "utility.h" #include "pll.h" +#include "mc.h" #include #include diff --git a/src/add-ons/accelerants/radeon_hd/accelerant.h b/src/add-ons/accelerants/radeon_hd/accelerant.h index fcb2cc8545..be03fd1f1b 100644 --- a/src/add-ons/accelerants/radeon_hd/accelerant.h +++ b/src/add-ons/accelerants/radeon_hd/accelerant.h @@ -14,6 +14,7 @@ #include "radeon_hd.h" #include "pll.h" #include "dac.h" +#include "tmds.h" #include @@ -85,6 +86,8 @@ struct register_info { typedef struct { + uint16 location; + uint16 locationIndex; uint32 vfreq_max; uint32 vfreq_min; uint32 hfreq_max; @@ -129,54 +132,6 @@ _write32(uint32 offset, uint32 value) } -inline uint32 -_read32MC(uint32 offset) -{ - radeon_shared_info &info = *gInfo->shared_info; - - if (info.device_chipset == RADEON_R600) { - _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)) { - _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)) { - _write32(RS780_MC_INDEX, offset & RS780_MC_INDEX_ADDR_MASK); - return _read32(RS780_MC_DATA); - } - - // eh. - return _read32(offset); -} - - -inline void -_write32MC(uint32 offset, uint32 data) -{ - radeon_shared_info &info = *gInfo->shared_info; - - if (info.device_chipset == RADEON_R600) { - _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)) { - _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)) { - _write32(RS780_MC_INDEX, ((offset & RS780_MC_INDEX_ADDR_MASK) - | RS780_MC_INDEX_WR_EN)); - _write32(RS780_MC_DATA, data); - } -} - - inline uint32 _read32PLL(uint16 offset) { @@ -200,14 +155,13 @@ Read32(uint32 subsystem, uint32 offset) default: case OUT: case VGA: + case MC: return _read32(offset); case CRT: return _read32(offset); case PLL: return _read32(offset); //return _read32PLL(offset); - case MC: - return _read32MC(offset); }; } @@ -219,6 +173,7 @@ Write32(uint32 subsystem, uint32 offset, uint32 value) default: case OUT: case VGA: + case MC: _write32(offset, value); return; case CRT: @@ -228,9 +183,6 @@ Write32(uint32 subsystem, uint32 offset, uint32 value) _write32(offset, value); //_write32PLL(offset, value); return; - case MC: - _write32MC(offset, value); - return; }; } @@ -243,6 +195,7 @@ Write32Mask(uint32 subsystem, uint32 offset, uint32 value, uint32 mask) default: case OUT: case VGA: + case MC: temp = _read32(offset); break; case CRT: @@ -252,9 +205,6 @@ Write32Mask(uint32 subsystem, uint32 offset, uint32 value, uint32 mask) temp = _read32(offset); //temp = _read32PLL(offset); break; - case MC: - temp = _read32MC(offset); - break; }; // only effect mask @@ -265,6 +215,7 @@ Write32Mask(uint32 subsystem, uint32 offset, uint32 value, uint32 mask) default: case OUT: case VGA: + case MC: _write32(offset, temp); return; case CRT: @@ -274,9 +225,6 @@ Write32Mask(uint32 subsystem, uint32 offset, uint32 value, uint32 mask) _write32(offset, temp); //_write32PLL(offset, temp); return; - case MC: - _write32MC(offset, temp); - return; }; } diff --git a/src/add-ons/accelerants/radeon_hd/dac.cpp b/src/add-ons/accelerants/radeon_hd/dac.cpp index 9c9c0d7258..72067d28f8 100644 --- a/src/add-ons/accelerants/radeon_hd/dac.cpp +++ b/src/add-ons/accelerants/radeon_hd/dac.cpp @@ -375,3 +375,16 @@ DACPower(uint8 dacIndex, int mode) DACPowerModern(dacIndex, mode); } + +void +DACAllIdle() +{ + // This really doesn't do anything on DAC monitors + // Implimented for completeness + uint8 i; + + for (i = 0; i < 2; i++) { + DACPower(i, RHD_POWER_RESET); + } +} + diff --git a/src/add-ons/accelerants/radeon_hd/dac.h b/src/add-ons/accelerants/radeon_hd/dac.h index 271e9b7d5f..9aa34f3b8a 100644 --- a/src/add-ons/accelerants/radeon_hd/dac.h +++ b/src/add-ons/accelerants/radeon_hd/dac.h @@ -26,6 +26,7 @@ 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); +void DACAllIdle(); #endif diff --git a/src/add-ons/accelerants/radeon_hd/mc.cpp b/src/add-ons/accelerants/radeon_hd/mc.cpp new file mode 100644 index 0000000000..e25869c4c1 --- /dev/null +++ b/src/add-ons/accelerants/radeon_hd/mc.cpp @@ -0,0 +1,88 @@ +/* + * 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 "mc.h" + + +/* Read32/Write32 for MC can hande the fact that some cards need to write + to a special MC interface, while others just write to the card directly. + As of R600 - R800 though the special MC interface doesn't seem to exist +*/ + + +#define TRACE_MC +#ifdef TRACE_MC +extern "C" void _sPrintf(const char *format, ...); +# define TRACE(x...) _sPrintf("radeon_hd: " x) +#else +# define TRACE(x...) ; +#endif + + +uint64 +MCFBLocation(uint16 chipset, uint32* size) +{ + // TODO : R800 : This is only valid for all R6xx and R7xx? + uint32 fbLocationReg = Read32(MC, R7XX_MC_VM_FB_LOCATION); + *size = (((fbLocationReg & 0xFFFF0000) + - ((fbLocationReg & 0xFFFF) << 16))) << 8; + return (fbLocationReg & 0xFFFF) << 24; +} + + +uint32 +MCIdle() +{ + uint32 turboencabulator; + if (!((turboencabulator = Read32(MC, SRBM_STATUS)) & + (VMC_BUSY_bit | MCB_BUSY_bit | + MCDZ_BUSY_bit | MCDY_BUSY_bit | MCDX_BUSY_bit | MCDW_BUSY_bit))) + return 0; + + return turboencabulator; +} + + +status_t +MCFBSetup(uint32 newFbLocation, uint32 newFbSize) +{ + uint32 oldFbSize; + uint64 oldFbLocation = MCFBLocation(0, &oldFbSize); + + if (oldFbLocation == newFbLocation + && oldFbSize == newFbSize) { + TRACE("%s: not adjusting frame buffer as it is already correct\n", + __func__); + return B_OK; + } + + if (oldFbLocation >> 32) + TRACE("%s: board claims to use a frame buffer address > 32-bits\n", + __func__); + + uint32 idleState = MCIdle(); + if (idleState > 0) { + TRACE("%s: Cannot modify non-idle MC! idleState: %X\n", + __func__, idleState); + return B_ERROR; + } + + TRACE("%s: Setting MC/FB from 0x%08X to 0x%08X [size 0x%08X]\n", + __func__, oldFbLocation, newFbLocation, newFbSize); + + // The MC Write32 will handle cards needing a special MC read/write register + Write32(MC, R6XX_MC_VM_FB_LOCATION, + R6XX_FB_LOCATION(newFbLocation, newFbSize)); + Write32(MC, R6XX_HDP_NONSURFACE_BASE, R6XX_HDP_LOCATION(newFbLocation)); + + return B_OK; +} diff --git a/src/add-ons/accelerants/radeon_hd/mc.h b/src/add-ons/accelerants/radeon_hd/mc.h new file mode 100644 index 0000000000..2ef458bfa1 --- /dev/null +++ b/src/add-ons/accelerants/radeon_hd/mc.h @@ -0,0 +1,22 @@ +/* + * 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_MC_H +#define RADEON_HD_MC_H + + +#define R6XX_FB_LOCATION(address, size) \ + (((((address) + (size)) >> 8) & 0xFFFF0000) | (((address) >> 24) & 0xFFFF)) +#define R6XX_HDP_LOCATION(address) \ + ((((address) >> 8) & 0x00FF0000)) + + +uint64 MCFBLocation(uint16 chipset, uint32* size); +status_t MCFBSetup(uint32 newFbLocation, uint32 newFbSize); + + +#endif diff --git a/src/add-ons/accelerants/radeon_hd/mode.cpp b/src/add-ons/accelerants/radeon_hd/mode.cpp index 3c23770fde..0adfdd9934 100644 --- a/src/add-ons/accelerants/radeon_hd/mode.cpp +++ b/src/add-ons/accelerants/radeon_hd/mode.cpp @@ -149,6 +149,17 @@ CardFBSet(display_mode *mode) get_color_space_format(*mode, colorMode, bytesPerRow, bitsPerPixel); + #if 0 + // TMDSAllIdle // DVI / HDMI + // LVTMAAllIdle // DVI + DACAllIdle(); + + // Set the inital frame buffer location in the memory controler + uint32 mcFbSize; + MCFBLocation(0, &mcFbSize); + MCFBSetup(Read32(OUT, R6XX_CONFIG_FB_BASE), mcFbSize); + #endif + Write32(CRT, gRegister->grphUpdate, (1<<16)); // Lock for update (isn't this normally the other way around on VGA? @@ -316,12 +327,14 @@ radeon_set_display_mode(display_mode *mode) init_registers(crtNumber); - // TODO : this obviously breaks horribly on attached multiple outputs + // TODO Populate gCRT with interface connection if (DACSense(0)) dacNumber = 0; else if (DACSense(1)) dacNumber = 1; + TMDSSense(0); // DVI / HDMI + CardFBSet(mode); CardModeSet(mode); CardModeScale(mode); diff --git a/src/add-ons/accelerants/radeon_hd/mode.h b/src/add-ons/accelerants/radeon_hd/mode.h index cc481311a9..1ab7165cc4 100644 --- a/src/add-ons/accelerants/radeon_hd/mode.h +++ b/src/add-ons/accelerants/radeon_hd/mode.h @@ -13,6 +13,7 @@ #include #include +#include "mc.h" #define T_POSITIVE_SYNC (B_POSITIVE_HSYNC | B_POSITIVE_VSYNC) diff --git a/src/add-ons/accelerants/radeon_hd/tmds.cpp b/src/add-ons/accelerants/radeon_hd/tmds.cpp new file mode 100644 index 0000000000..2d7f46b446 --- /dev/null +++ b/src/add-ons/accelerants/radeon_hd/tmds.cpp @@ -0,0 +1,52 @@ +/* + * 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 "tmds.h" + + +#define TRACE_TMDS +#ifdef TRACE_TMDS +extern "C" void _sPrintf(const char *format, ...); +# define TRACE(x...) _sPrintf("radeon_hd: " x) +#else +# define TRACE(x...) ; +#endif + + +bool +TMDSSense(uint8 tmdsIndex) +{ + // For now radeon cards only have TMDSA and no TMDSB + + // Backup current TMDS values + uint32 loadDetect = Read32(OUT, TMDSA_LOAD_DETECT); + + // Call TMDS load detect on TMDSA + Write32Mask(OUT, TMDSA_LOAD_DETECT, 0x00000001, 0x00000001); + snooze(1); + + // Check result of TMDS load detect + bool result = Read32(OUT, TMDSA_LOAD_DETECT) & 0x00000010; + + // Restore saved value + Write32Mask(OUT, TMDSA_LOAD_DETECT, loadDetect, 0x00000001); + + if (result) { + TRACE("%s: TMDS%d: Display device attached\n", __func__, tmdsIndex); + } else { + TRACE("%s: TMDS%d: No display device attached\n", __func__, tmdsIndex); + } + + return result; +} + + diff --git a/src/add-ons/accelerants/radeon_hd/tmds.h b/src/add-ons/accelerants/radeon_hd/tmds.h new file mode 100644 index 0000000000..37a9b21408 --- /dev/null +++ b/src/add-ons/accelerants/radeon_hd/tmds.h @@ -0,0 +1,15 @@ +/* + * 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_TMDS_H +#define RADEON_HD_TMDS_H + + +bool TMDSSense(uint8 tmdsIndex); + + +#endif