From 5f6744a8cd01e15c8aa5b35ecd5fe695d970e923 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Thu, 26 May 2011 04:51:57 +0000 Subject: [PATCH] * 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 --- .../accelerants/radeon_hd/accelerant.cpp | 150 +++++++++++++----- .../accelerants/radeon_hd/accelerant.h | 23 ++- src/add-ons/accelerants/radeon_hd/mode.cpp | 138 ++++++++-------- 3 files changed, 193 insertions(+), 118 deletions(-) diff --git a/src/add-ons/accelerants/radeon_hd/accelerant.cpp b/src/add-ons/accelerants/radeon_hd/accelerant.cpp index 74b6267cfe..51bb5b9015 100644 --- a/src/add-ons/accelerants/radeon_hd/accelerant.cpp +++ b/src/add-ons/accelerants/radeon_hd/accelerant.cpp @@ -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; diff --git a/src/add-ons/accelerants/radeon_hd/accelerant.h b/src/add-ons/accelerants/radeon_hd/accelerant.h index b8cb1fcf60..a0f5431914 100644 --- a/src/add-ons/accelerants/radeon_hd/accelerant.h +++ b/src/add-ons/accelerants/radeon_hd/accelerant.h @@ -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 diff --git a/src/add-ons/accelerants/radeon_hd/mode.cpp b/src/add-ons/accelerants/radeon_hd/mode.cpp index b54c399333..84ada0b512 100644 --- a/src/add-ons/accelerants/radeon_hd/mode.cpp +++ b/src/add-ons/accelerants/radeon_hd/mode.cpp @@ -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;