* 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
This commit is contained in:
Alexander von Gluck IV
2011-07-12 20:14:31 +00:00
parent a133bc725c
commit 84bcfa3d4b
11 changed files with 216 additions and 60 deletions
@@ -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
@@ -13,6 +13,7 @@
#include "utility.h"
#include "pll.h"
#include "mc.h"
#include <errno.h>
#include <stdlib.h>
+7 -59
View File
@@ -14,6 +14,7 @@
#include "radeon_hd.h"
#include "pll.h"
#include "dac.h"
#include "tmds.h"
#include <edid.h>
@@ -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;
};
}
+13
View File
@@ -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);
}
}
+1
View File
@@ -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
+88
View File
@@ -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;
}
+22
View File
@@ -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
+14 -1
View File
@@ -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);
+1
View File
@@ -13,6 +13,7 @@
#include <ddc.h>
#include <edid.h>
#include "mc.h"
#define T_POSITIVE_SYNC (B_POSITIVE_HSYNC | B_POSITIVE_VSYNC)
@@ -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;
}
+15
View File
@@ -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