* move all register calculation into init_registers to

keep things simple to troubleshoot
* use crt offset only on evergreen, else use AMD provided
  register locations
* init_registers(crtid) is called before making register calls
  to a monitor.
* init_registers supports 1-2 displays on r600-r700
* init_registers supports 1-6 displays on r800+ (AMD eyefinity)
* restore CardBlankSet function in a more simple form
  (still needs init_registers addition)


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41757 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Alexander von Gluck IV 2011-05-26 04:51:57 +00:00
parent dc3bd077cd
commit 5f6744a8cd
3 changed files with 193 additions and 118 deletions

View File

@ -164,51 +164,121 @@ uninit_common(void)
/*! Populate gRegister with device dependant register locations */
static status_t
init_registers(uint16 chipset)
status_t
init_registers(uint8 crtid)
{
if (chipset >= RADEON_R800) {
gRegister->regOffsetCRT0 = EVERGREEN_CRTC0_REGISTER_OFFSET;
gRegister->regOffsetCRT1 = EVERGREEN_CRTC1_REGISTER_OFFSET;
gRegister->grphEnable = EVERGREEN_GRPH_ENABLE;
gRegister->grphControl = EVERGREEN_GRPH_CONTROL;
gRegister->grphSwapControl = EVERGREEN_GRPH_SWAP_CONTROL;
radeon_shared_info &info = *gInfo->shared_info;
if (info.device_chipset >= RADEON_R800) {
uint16_t offset = 0;
// AMD Eyefinity on Evergreen GPUs
if (crtid == 1)
offset = EVERGREEN_CRTC1_REGISTER_OFFSET;
else if (crtid == 2)
offset = EVERGREEN_CRTC2_REGISTER_OFFSET;
else if (crtid == 3)
offset = EVERGREEN_CRTC3_REGISTER_OFFSET;
else if (crtid == 4)
offset = EVERGREEN_CRTC4_REGISTER_OFFSET;
else if (crtid == 5)
offset = EVERGREEN_CRTC5_REGISTER_OFFSET;
else
offset = EVERGREEN_CRTC0_REGISTER_OFFSET;
// Evergreen+ is crtoffset + register
gRegister->grphEnable = offset + EVERGREEN_GRPH_ENABLE;
gRegister->grphControl = offset + EVERGREEN_GRPH_CONTROL;
gRegister->grphSwapControl = offset + EVERGREEN_GRPH_SWAP_CONTROL;
gRegister->grphPrimarySurfaceAddr
= EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS;
gRegister->grphPitch = EVERGREEN_GRPH_PITCH;
gRegister->grphSurfaceOffsetX = EVERGREEN_GRPH_SURFACE_OFFSET_X;
gRegister->grphSurfaceOffsetY = EVERGREEN_GRPH_SURFACE_OFFSET_Y;
gRegister->grphXStart = EVERGREEN_GRPH_X_START;
gRegister->grphYStart = EVERGREEN_GRPH_Y_START;
gRegister->grphXEnd = EVERGREEN_GRPH_X_END;
gRegister->grphYEnd = EVERGREEN_GRPH_Y_END;
gRegister->modeDesktopHeight = EVERGREEN_DESKTOP_HEIGHT;
gRegister->viewportStart = EVERGREEN_VIEWPORT_START;
gRegister->viewportSize = EVERGREEN_VIEWPORT_SIZE;
} else if (chipset >= RADEON_R600 && chipset < RADEON_R800) {
gRegister->regOffsetCRT0 = D1_REG_OFFSET;
gRegister->regOffsetCRT1 = D2_REG_OFFSET;
gRegister->grphEnable = D1GRPH_ENABLE;
gRegister->grphControl = D1GRPH_CONTROL;
gRegister->grphSwapControl = D1GRPH_SWAP_CNTL;
gRegister->grphPrimarySurfaceAddr = D1GRPH_PRIMARY_SURFACE_ADDRESS;
gRegister->grphPitch = D1GRPH_PITCH;
gRegister->grphSurfaceOffsetX = D1GRPH_SURFACE_OFFSET_X;
gRegister->grphSurfaceOffsetY = D1GRPH_SURFACE_OFFSET_Y;
gRegister->grphXStart = D1GRPH_X_START;
gRegister->grphYStart = D1GRPH_Y_START;
gRegister->grphXEnd = D1GRPH_X_END;
gRegister->grphYEnd = D1GRPH_Y_END;
gRegister->modeDesktopHeight = D1MODE_DESKTOP_HEIGHT;
gRegister->viewportStart = D1MODE_VIEWPORT_START;
gRegister->viewportSize = D1MODE_VIEWPORT_SIZE;
= offset + EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS;
gRegister->grphPitch = offset + EVERGREEN_GRPH_PITCH;
gRegister->grphSurfaceOffsetX
= offset + EVERGREEN_GRPH_SURFACE_OFFSET_X;
gRegister->grphSurfaceOffsetY
= offset + EVERGREEN_GRPH_SURFACE_OFFSET_Y;
gRegister->grphXStart = offset + EVERGREEN_GRPH_X_START;
gRegister->grphYStart = offset + EVERGREEN_GRPH_Y_START;
gRegister->grphXEnd = offset + EVERGREEN_GRPH_X_END;
gRegister->grphYEnd = offset + EVERGREEN_GRPH_Y_END;
gRegister->modeDesktopHeight = offset + EVERGREEN_DESKTOP_HEIGHT;
gRegister->modeDataFormat = offset + EVERGREEN_DATA_FORMAT;
gRegister->viewportStart = offset + EVERGREEN_VIEWPORT_START;
gRegister->viewportSize = offset + EVERGREEN_VIEWPORT_SIZE;
} else if (info.device_chipset >= RADEON_R600
&& info.device_chipset < RADEON_R800) {
// r600 - r700 are D1 or D2 based on primary / secondary crt
gRegister->grphEnable
= (crtid == 1) ? D2GRPH_ENABLE : D1GRPH_ENABLE;
gRegister->grphControl
= (crtid == 1) ? D2GRPH_CONTROL : D1GRPH_CONTROL;
gRegister->grphSwapControl
= (crtid == 1) ? D2GRPH_SWAP_CNTL : D1GRPH_SWAP_CNTL;
gRegister->grphPrimarySurfaceAddr
= (crtid == 1) ? D2GRPH_PRIMARY_SURFACE_ADDRESS
: D1GRPH_PRIMARY_SURFACE_ADDRESS;
gRegister->grphPitch
= (crtid == 1) ? D2GRPH_PITCH : D1GRPH_PITCH;
gRegister->grphSurfaceOffsetX
= (crtid == 1) ? D2GRPH_SURFACE_OFFSET_X : D1GRPH_SURFACE_OFFSET_X;
gRegister->grphSurfaceOffsetY
= (crtid == 1) ? D2GRPH_SURFACE_OFFSET_Y : D1GRPH_SURFACE_OFFSET_Y;
gRegister->grphXStart
= (crtid == 1) ? D2GRPH_X_START : D1GRPH_X_START;
gRegister->grphYStart
= (crtid == 1) ? D2GRPH_Y_START : D1GRPH_Y_START;
gRegister->grphXEnd
= (crtid == 1) ? D2GRPH_X_END : D1GRPH_X_END;
gRegister->grphYEnd
= (crtid == 1) ? D2GRPH_Y_END : D1GRPH_Y_END;
gRegister->modeDesktopHeight
= (crtid == 1) ? D2MODE_DESKTOP_HEIGHT : D1MODE_DESKTOP_HEIGHT;
gRegister->modeDataFormat
= (crtid == 1) ? D2MODE_DATA_FORMAT : D1MODE_DATA_FORMAT;
gRegister->viewportStart
= (crtid == 1) ? D2MODE_VIEWPORT_START : D1MODE_VIEWPORT_START;
gRegister->viewportSize
= (crtid == 1) ? D2MODE_VIEWPORT_SIZE : D1MODE_VIEWPORT_SIZE;
} else {
// this really shouldn't happen unless a driver PCIID chipset is wrong
TRACE("%s, unknown Radeon chipset: r%X\n", __func__, chipset);
TRACE("%s, unknown Radeon chipset: r%X\n", __func__,
info.device_chipset);
return B_ERROR;
}
TRACE("%s, registers for ATI chipset r%X initialized\n", __func__, chipset);
// Populate common registers
// TODO : Wait.. this doesn't work with Eyefinity > crt 1.
gRegister->modeCenter
= (crtid == 1) ? D2MODE_CENTER : D1MODE_CENTER;
gRegister->crtHPolarity
= (crtid == 1) ? D2CRTC_H_SYNC_A_CNTL : D1CRTC_H_SYNC_A_CNTL;
gRegister->crtVPolarity
= (crtid == 1) ? D2CRTC_V_SYNC_A_CNTL : D1CRTC_V_SYNC_A_CNTL;
gRegister->crtHTotal
= (crtid == 1) ? D2CRTC_H_TOTAL : D1CRTC_H_TOTAL;
gRegister->crtVTotal
= (crtid == 1) ? D2CRTC_V_TOTAL : D1CRTC_V_TOTAL;
gRegister->crtHSync
= (crtid == 1) ? D2CRTC_H_SYNC_A : D1CRTC_H_SYNC_A;
gRegister->crtVSync
= (crtid == 1) ? D2CRTC_V_SYNC_A : D1CRTC_V_SYNC_A;
gRegister->crtHBlank
= (crtid == 1) ? D2CRTC_H_BLANK_START_END : D1CRTC_H_BLANK_START_END;
gRegister->crtVBlank
= (crtid == 1) ? D2CRTC_V_BLANK_START_END : D1CRTC_V_BLANK_START_END;
gRegister->crtInterlace
= (crtid == 1) ? D2CRTC_INTERLACE_CONTROL : D1CRTC_INTERLACE_CONTROL;
gRegister->crtCountControl
= (crtid == 1) ? D2CRTC_COUNT_CONTROL : D1CRTC_COUNT_CONTROL;
gRegister->sclEnable
= (crtid == 1) ? D2SCL_ENABLE : D1SCL_ENABLE;
gRegister->sclTapControl
= (crtid == 1) ? D2SCL_TAP_CONTROL : D1SCL_TAP_CONTROL;
TRACE("%s, registers for ATI chipset r%X crt #%d loaded\n", __func__,
info.device_chipset, crtid);
return B_OK;
}
@ -232,7 +302,9 @@ radeon_init_accelerant(int device)
init_lock(&info.accelerant_lock, "radeon hd accelerant");
init_lock(&info.engine_lock, "radeon hd engine");
status = init_registers(info.device_chipset);
status = init_registers(0);
// Initilize registers for crt0 to begin
if (status != B_OK)
return status;

View File

@ -1,9 +1,10 @@
/*
* Copyright 2006-2008, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2011, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de
* Alexander von Gluck, kallisti5@unixzen.com
*/
#ifndef RADEON_HD_ACCELERANT_H
#define RADEON_HD_ACCELERANT_H
@ -38,8 +39,6 @@ struct accelerant_info {
struct register_info {
uint16_t regOffsetCRT0;
uint16_t regOffsetCRT1;
uint16_t grphEnable;
uint16_t grphControl;
uint16_t grphSwapControl;
@ -51,9 +50,23 @@ struct register_info {
uint16_t grphYStart;
uint16_t grphXEnd;
uint16_t grphYEnd;
uint16_t crtCountControl;
uint16_t crtInterlace;
uint16_t crtHPolarity;
uint16_t crtVPolarity;
uint16_t crtHSync;
uint16_t crtVSync;
uint16_t crtHBlank;
uint16_t crtVBlank;
uint16_t crtHTotal;
uint16_t crtVTotal;
uint16_t modeDesktopHeight;
uint16_t modeDataFormat;
uint16_t modeCenter;
uint16_t viewportStart;
uint16_t viewportSize;
uint16_t sclEnable;
uint16_t sclTapControl;
};
@ -65,6 +78,10 @@ struct register_info {
extern accelerant_info *gInfo;
extern register_info *gRegister;
status_t init_registers(uint8 crtid);
// register access
inline uint32

View File

@ -130,64 +130,56 @@ get_color_space_format(const display_mode &mode, uint32 &colorMode,
// Blacks the screen out, useful for mode setting
//static void
//CardBlankSet(int crtNumber, bool blank)
//{
// int blackColorReg;
// int blankControlReg;
//
// if (crtNumber == 1) {
// blackColorReg = D2CRTC_BLACK_COLOR;
// blankControlReg = D2CRTC_BLANK_CONTROL;
// } else {
// blackColorReg = D1CRTC_BLACK_COLOR;
// blankControlReg = D1CRTC_BLANK_CONTROL;
// }
//
// write32(blackColorReg, 0);
// write32AtMask(blankControlReg, blank ? 1 << 8 : 0, 1 << 8);
//}
static void
CardBlankSet(bool blank)
{
int blackColorReg;
int blankControlReg;
blackColorReg = D1CRTC_BLACK_COLOR;
blankControlReg = D1CRTC_BLANK_CONTROL;
write32(blackColorReg, 0);
write32AtMask(blankControlReg, blank ? 1 << 8 : 0, 1 << 8);
}
static void
CardFBSet(int crtNumber, display_mode *mode)
CardFBSet(display_mode *mode)
{
uint32 colorMode;
uint32 bytesPerRow;
uint32 bitsPerPixel;
uint16_t regOffset = (crtNumber == 0)
? gRegister->regOffsetCRT0 : gRegister->regOffsetCRT1;
get_color_space_format(*mode, colorMode, bytesPerRow, bitsPerPixel);
// disable R/B swap, disable tiling, disable 16bit alpha, etc.
write32AtMask(regOffset + gRegister->grphEnable, 1, 0x00000001);
write32(regOffset + gRegister->grphControl, 0);
write32AtMask(gRegister->grphEnable, 1, 0x00000001);
write32(gRegister->grphControl, 0);
// set color mode on video card
switch (mode->space) {
case B_CMAP8:
write32AtMask(regOffset + gRegister->grphControl,
write32AtMask(gRegister->grphControl,
0, 0x00000703);
break;
case B_RGB15_LITTLE:
write32AtMask(regOffset + gRegister->grphControl,
write32AtMask(gRegister->grphControl,
0x000001, 0x00000703);
break;
case B_RGB16_LITTLE:
write32AtMask(regOffset + gRegister->grphControl,
write32AtMask(gRegister->grphControl,
0x000101, 0x00000703);
break;
case B_RGB24_LITTLE:
case B_RGB32_LITTLE:
default:
write32AtMask(regOffset + gRegister->grphControl,
write32AtMask(gRegister->grphControl,
0x000002, 0x00000703);
break;
}
write32(regOffset + gRegister->grphSwapControl, 0);
write32(gRegister->grphSwapControl, 0);
// only for chipsets > r600
// R5xx - RS690 case is GRPH_CONTROL bit 16
@ -196,19 +188,19 @@ CardFBSet(int crtNumber, display_mode *mode)
uint32 fbAddress = gInfo->shared_info->frame_buffer_phys;
write32(regOffset + gRegister->grphPrimarySurfaceAddr,
write32(gRegister->grphPrimarySurfaceAddr,
fbAddress);
write32(regOffset + gRegister->grphPitch, bytesPerRow / 4);
write32(regOffset + gRegister->grphSurfaceOffsetX, 0);
write32(regOffset + gRegister->grphSurfaceOffsetY, 0);
write32(regOffset + gRegister->grphXStart, 0);
write32(regOffset + gRegister->grphYStart, 0);
write32(regOffset + gRegister->grphXEnd, mode->virtual_width);
write32(regOffset + gRegister->grphYEnd, mode->virtual_height);
write32(gRegister->grphPitch, bytesPerRow / 4);
write32(gRegister->grphSurfaceOffsetX, 0);
write32(gRegister->grphSurfaceOffsetY, 0);
write32(gRegister->grphXStart, 0);
write32(gRegister->grphYStart, 0);
write32(gRegister->grphXEnd, mode->virtual_width);
write32(gRegister->grphYEnd, mode->virtual_height);
/* D1Mode registers */
write32(regOffset + gRegister->modeDesktopHeight, mode->virtual_height);
write32(gRegister->modeDesktopHeight, mode->virtual_height);
// update shared info
gInfo->shared_info->bytes_per_row = bytesPerRow;
@ -218,12 +210,9 @@ CardFBSet(int crtNumber, display_mode *mode)
static void
CardModeSet(int crtNumber, display_mode *mode)
CardModeSet(display_mode *mode)
{
uint16_t regOffset = (crtNumber == 0)
? gRegister->regOffsetCRT0 : gRegister->regOffsetCRT1;
//CardBlankSet(crtNumber, true);
CardBlankSet(true);
display_timing& displayTiming = mode->timing;
@ -231,69 +220,68 @@ CardModeSet(int crtNumber, display_mode *mode)
__func__, displayTiming.h_display, displayTiming.v_display);
// enable read requests
write32AtMask(regOffset + gRegister->grphControl, 0, 0x01000000);
write32AtMask(gRegister->grphControl, 0, 0x01000000);
// *** Horizontal
write32(regOffset + D1CRTC_H_TOTAL, displayTiming.h_total - 1);
write32(gRegister->crtHTotal,
displayTiming.h_total - 1);
// determine blanking based on passed modeline
//uint16 blankStart = displayTiming.h_display;
//uint16 blankEnd = displayTiming.h_total;
//write32(regOffset + D1CRTC_H_BLANK_START_END,
//write32(gRegister->crtHBlank,
// blankStart | (blankEnd << 16));
write32(regOffset + D1CRTC_H_SYNC_A,
write32(gRegister->crtHSync,
(displayTiming.h_sync_end - displayTiming.h_sync_start) << 16);
// set flag for neg. H sync. M76 Register Reference Guide 2-256
write32AtMask(regOffset + D1CRTC_H_SYNC_A_CNTL,
write32AtMask(gRegister->crtHPolarity,
displayTiming.flags & B_POSITIVE_HSYNC ? 0 : 1, 0x1);
// *** Vertical
write32(regOffset + D1CRTC_V_TOTAL, displayTiming.v_total - 1);
write32(gRegister->crtVTotal,
displayTiming.v_total - 1);
//blankStart = displayTiming.v_display;
//blankEnd = displayTiming.v_total;
//write32(regOffset + D1CRTC_V_BLANK_START_END,
//write32(gRegister->crtVBlank,
// blankStart | (blankEnd << 16));
// Set Interlace if specified within mode line
if (displayTiming.flags & B_TIMING_INTERLACED) {
write32(regOffset + D1CRTC_INTERLACE_CONTROL, 0x1);
write32(regOffset + D1MODE_DATA_FORMAT, 0x1);
write32(gRegister->crtInterlace, 0x1);
write32(gRegister->modeDataFormat, 0x1);
} else {
write32(regOffset + D1CRTC_INTERLACE_CONTROL, 0x0);
write32(regOffset + D1MODE_DATA_FORMAT, 0x0);
write32(gRegister->crtInterlace, 0x0);
write32(gRegister->modeDataFormat, 0x0);
}
write32(regOffset + D1CRTC_V_SYNC_A,
write32(gRegister->crtVSync,
(displayTiming.v_sync_end - displayTiming.v_sync_start) << 16);
// set flag for neg. V sync. M76 Register Reference Guide 2-258
// we don't need a mask here as this is the only param for Vertical
write32(regOffset + D1CRTC_V_SYNC_A_CNTL,
write32(gRegister->crtVPolarity,
displayTiming.flags & B_POSITIVE_VSYNC ? 0 : 1);
/* set D1CRTC_HORZ_COUNT_BY2_EN to 0;
should only be set to 1 on 30bpp DVI modes
*/
write32AtMask(regOffset + D1CRTC_COUNT_CONTROL, 0x0, 0x1);
write32AtMask(gRegister->crtCountControl, 0x0, 0x1);
//CardBlankSet(crtNumber, false);
CardBlankSet(false);
}
static void
CardModeScale(int crtNumber, display_mode *mode)
CardModeScale(display_mode *mode)
{
uint16_t regOffset = (crtNumber == 0)
? gRegister->regOffsetCRT0 : gRegister->regOffsetCRT1;
write32(regOffset + gRegister->viewportSize,
write32(gRegister->viewportSize,
mode->timing.v_display | (mode->timing.h_display << 16));
write32(regOffset + gRegister->viewportStart, 0);
write32(gRegister->viewportStart, 0);
/* write32(regOffset + D1MODE_EXT_OVERSCAN_LEFT_RIGHT,
(Overscan.OverscanLeft << 16) | Overscan.OverscanRight);
@ -302,9 +290,9 @@ CardModeScale(int crtNumber, display_mode *mode)
*/
// No scaling
write32(regOffset + D1SCL_ENABLE, 0);
write32(regOffset + D1SCL_TAP_CONTROL, 0);
write32(regOffset + D1MODE_CENTER, 0);
write32(gRegister->sclEnable, 0);
write32(gRegister->sclTapControl, 0);
write32(gRegister->modeCenter, 0);
#if 0
// Auto scale keeping aspect ratio
@ -331,16 +319,13 @@ radeon_set_display_mode(display_mode *mode)
{
int crtNumber = 0;
CardFBSet(crtNumber, mode);
CardModeSet(crtNumber, mode);
CardModeScale(crtNumber, mode);
init_registers(crtNumber);
CardFBSet(mode);
CardModeSet(mode);
CardModeScale(mode);
uint16_t regOffset = (crtNumber == 0)
? gRegister->regOffsetCRT0 : gRegister->regOffsetCRT1;
int32 cardstatus = read32(regOffset + D1CRTC_STATUS);
TRACE("Card Status: 0x%X\n", cardstatus);
int32 crtstatus = read32(D1CRTC_STATUS);
TRACE("CRT0 Status: 0x%X\n", crtstatus);
return B_OK;
}
@ -377,7 +362,8 @@ radeon_get_pixel_clock_limits(display_mode *mode, uint32 *_low, uint32 *_high)
/*
if (_low != NULL) {
// lower limit of about 48Hz vertical refresh
uint32 totalClocks = (uint32)mode->timing.h_total * (uint32)mode->timing.v_total;
uint32 totalClocks = (uint32)mode->timing.h_total
*(uint32)mode->timing.v_total;
uint32 low = (totalClocks * 48L) / 1000L;
if (low < gInfo->shared_info->pll_info.min_frequency)
low = gInfo->shared_info->pll_info.min_frequency;