diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/radeon.h | 17 | ||||
-rw-r--r-- | src/radeon_display.c | 1862 | ||||
-rw-r--r-- | src/radeon_driver.c | 1810 |
4 files changed, 1881 insertions, 1810 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 7e6af9c..ad64d55 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -81,7 +81,7 @@ radeon_drv_ladir = @moduledir@/drivers radeon_drv_la_SOURCES = \ radeon_accel.c radeon_mergedfb.c radeon_cursor.c radeon_dga.c \ radeon_driver.c radeon_video.c radeon_bios.c radeon_mm_i2c.c \ - radeon_vip.c radeon_misc.c $(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) + radeon_vip.c radeon_misc.c radeon_display.c $(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) theatre_detect_drv_la_LTLIBRARIES = theatre_detect_drv.la theatre_detect_drv_la_LDFLAGS = -module -avoid-version diff --git a/src/radeon.h b/src/radeon.h index 6402e48..9ad539d 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -79,6 +79,13 @@ #include "picturestr.h" #endif +#ifndef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) +#endif +#ifndef MIN +#define MIN(a,b) ((a)>(b)?(b):(a)) +#endif + typedef enum { OPTION_NOACCEL, OPTION_SW_CURSOR, @@ -861,6 +868,16 @@ extern Bool RADEONGetLVDSInfoFromBIOS (ScrnInfoPtr pScrn); extern Bool RADEONGetTMDSInfoFromBIOS (ScrnInfoPtr pScrn); extern Bool RADEONGetHardCodedEDIDFromBIOS (ScrnInfoPtr pScrn); +extern void RADEONInitDispBandwidth(ScrnInfoPtr pScrn); +extern Bool RADEONI2cInit(ScrnInfoPtr pScrn); +extern void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag); +extern void RADEONGetPanelInfo(ScrnInfoPtr pScrn); +extern void RADEONUnblank(ScrnInfoPtr pScrn); +extern void RADEONBlank(ScrnInfoPtr pScrn); +extern void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, + int PowerManagementMode, + int flags); + #ifdef XF86DRI #ifdef USE_XAA extern void RADEONAccelInitCP(ScreenPtr pScreen, XAAInfoRecPtr a); diff --git a/src/radeon_display.c b/src/radeon_display.c new file mode 100644 index 0000000..fa9d2f5 --- /dev/null +++ b/src/radeon_display.c @@ -0,0 +1,1862 @@ +/* $XdotOrg: driver/xf86-video-ati/src/radeon_driver.c,v 1.116 2006/04/29 21:30:23 daenzer Exp $ */ +/* + * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and + * VA Linux Systems Inc., Fremont, California. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation on the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR + * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> +#include <stdio.h> + +/* X and server generic header files */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "fbdevhw.h" +#include "vgaHW.h" + +/* Driver data structures */ +#include "radeon.h" +#include "radeon_reg.h" +#include "radeon_macros.h" +#include "radeon_probe.h" +#include "radeon_version.h" +#include "radeon_mergedfb.h" + +#ifdef XF86DRI +#define _XF86DRI_SERVER_ +#include "radeon_dri.h" +#include "radeon_sarea.h" +#include "sarea.h" +#endif + +const char *MonTypeName[7] = { + "AUTO", + "NONE", + "CRT", + "LVDS", + "TMDS", + "CTV", + "STV" +}; + +const RADEONMonitorType MonTypeID[7] = { + MT_UNKNOWN, /* this is just a dummy value for AUTO DETECTION */ + MT_NONE, /* NONE -> NONE */ + MT_CRT, /* CRT -> CRT */ + MT_LCD, /* Laptop LCDs are driven via LVDS port */ + MT_DFP, /* DFPs are driven via TMDS */ + MT_CTV, /* CTV -> CTV */ + MT_STV, /* STV -> STV */ +}; + +const char *TMDSTypeName[3] = { + "NONE", + "Internal", + "External" +}; + +const char *DDCTypeName[5] = { + "NONE", + "MONID", + "DVI_DDC", + "VGA_DDC", + "CRT2_DDC" +}; + +const char *DACTypeName[3] = { + "Unknown", + "Primary", + "TVDAC/ExtDAC", +}; + +const char *ConnectorTypeName[8] = { + "None", + "Proprietary", + "VGA", + "DVI-I", + "DVI-D", + "CTV", + "STV", + "Unsupported" +}; + +const char *ConnectorTypeNameATOM[10] = { + "None", + "VGA", + "DVI-I", + "DVI-D", + "DVI-A", + "STV", + "CTV", + "LVDS", + "Digital", + "Unsupported" +}; + + +static const RADEONTMDSPll default_tmds_pll[CHIP_FAMILY_LAST][4] = +{ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_UNKNOW*/ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_LEGACY*/ + {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RADEON*/ + {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV100*/ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS100*/ + {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV200*/ + {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS200*/ + {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R200*/ + {{15500, 0x81b}, {0xffffffff, 0x83f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV250*/ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS300*/ + {{13000, 0x400f4}, {15000, 0x400f7}, {0xffffffff, 0x40111}, {0, 0}}, /*CHIP_FAMILY_RV280*/ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R300*/ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R350*/ + {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV350*/ + {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV380*/ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R420*/ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV410*/ /* FIXME: just values from r420 used... */ + {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS400*/ /* FIXME: just values from rv380 used... */ +}; + +static void RADEONI2CGetBits(I2CBusPtr b, int *Clock, int *data) +{ + ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned long val; + unsigned char *RADEONMMIO = info->MMIO; + + /* Get the result */ + val = INREG(info->DDCReg); + + *Clock = (val & RADEON_GPIO_Y_1) != 0; + *data = (val & RADEON_GPIO_Y_0) != 0; +} + +static void RADEONI2CPutBits(I2CBusPtr b, int Clock, int data) +{ + ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned long val; + unsigned char *RADEONMMIO = info->MMIO; + + val = INREG(info->DDCReg) & (CARD32)~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1); + val |= (Clock ? 0:RADEON_GPIO_EN_1); + val |= (data ? 0:RADEON_GPIO_EN_0); + OUTREG(info->DDCReg, val); + + /* read back to improve reliability on some cards. */ + val = INREG(info->DDCReg); +} + +Bool RADEONI2cInit(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + info->pI2CBus = xf86CreateI2CBusRec(); + if (!info->pI2CBus) return FALSE; + + info->pI2CBus->BusName = "DDC"; + info->pI2CBus->scrnIndex = pScrn->scrnIndex; + info->pI2CBus->I2CPutBits = RADEONI2CPutBits; + info->pI2CBus->I2CGetBits = RADEONI2CGetBits; + info->pI2CBus->AcknTimeout = 5; + + if (!xf86I2CBusInit(info->pI2CBus)) return FALSE; + return TRUE; +} + +void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) +{ + MonPtr mon = pScrn->monitor; + xf86MonPtr ddc = mon->DDC; + int i; + + if (flag) { /* HSync */ + for (i = 0; i < 4; i++) { + if (ddc->det_mon[i].type == DS_RANGES) { + mon->nHsync = 1; + mon->hsync[0].lo = ddc->det_mon[i].section.ranges.min_h; + mon->hsync[0].hi = ddc->det_mon[i].section.ranges.max_h; + return; + } + } + /* If no sync ranges detected in detailed timing table, let's + * try to derive them from supported VESA modes. Are we doing + * too much here!!!? */ + i = 0; + if (ddc->timings1.t1 & 0x02) { /* 800x600@56 */ + mon->hsync[i].lo = mon->hsync[i].hi = 35.2; + i++; + } + if (ddc->timings1.t1 & 0x04) { /* 640x480@75 */ + mon->hsync[i].lo = mon->hsync[i].hi = 37.5; + i++; + } + if ((ddc->timings1.t1 & 0x08) || (ddc->timings1.t1 & 0x01)) { + mon->hsync[i].lo = mon->hsync[i].hi = 37.9; + i++; + } + if (ddc->timings1.t2 & 0x40) { + mon->hsync[i].lo = mon->hsync[i].hi = 46.9; + i++; + } + if ((ddc->timings1.t2 & 0x80) || (ddc->timings1.t2 & 0x08)) { + mon->hsync[i].lo = mon->hsync[i].hi = 48.1; + i++; + } + if (ddc->timings1.t2 & 0x04) { + mon->hsync[i].lo = mon->hsync[i].hi = 56.5; + i++; + } + if (ddc->timings1.t2 & 0x02) { + mon->hsync[i].lo = mon->hsync[i].hi = 60.0; + i++; + } + if (ddc->timings1.t2 & 0x01) { + mon->hsync[i].lo = mon->hsync[i].hi = 64.0; + i++; + } + mon->nHsync = i; + } else { /* Vrefresh */ + for (i = 0; i < 4; i++) { + if (ddc->det_mon[i].type == DS_RANGES) { + mon->nVrefresh = 1; + mon->vrefresh[0].lo = ddc->det_mon[i].section.ranges.min_v; + mon->vrefresh[0].hi = ddc->det_mon[i].section.ranges.max_v; + return; + } + } + + i = 0; + if (ddc->timings1.t1 & 0x02) { /* 800x600@56 */ + mon->vrefresh[i].lo = mon->vrefresh[i].hi = 56; + i++; + } + if ((ddc->timings1.t1 & 0x01) || (ddc->timings1.t2 & 0x08)) { + mon->vrefresh[i].lo = mon->vrefresh[i].hi = 60; + i++; + } + if (ddc->timings1.t2 & 0x04) { + mon->vrefresh[i].lo = mon->vrefresh[i].hi = 70; + i++; + } + if ((ddc->timings1.t1 & 0x08) || (ddc->timings1.t2 & 0x80)) { + mon->vrefresh[i].lo = mon->vrefresh[i].hi = 72; + i++; + } + if ((ddc->timings1.t1 & 0x04) || (ddc->timings1.t2 & 0x40) || + (ddc->timings1.t2 & 0x02) || (ddc->timings1.t2 & 0x01)) { + mon->vrefresh[i].lo = mon->vrefresh[i].hi = 75; + i++; + } + mon->nVrefresh = i; + } +} + +static RADEONMonitorType +RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + int bConnected = 0; + + /* the monitor either wasn't connected or it is a non-DDC CRT. + * try to probe it + */ + if(IsCrtDac) { + unsigned long ulOrigVCLK_ECP_CNTL; + unsigned long ulOrigDAC_CNTL; + unsigned long ulOrigDAC_EXT_CNTL; + unsigned long ulOrigCRTC_EXT_CNTL; + unsigned long ulData; + unsigned long ulMask; + + ulOrigVCLK_ECP_CNTL = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); + + ulData = ulOrigVCLK_ECP_CNTL; + ulData &= ~(RADEON_PIXCLK_ALWAYS_ONb + | RADEON_PIXCLK_DAC_ALWAYS_ONb); + ulMask = ~(RADEON_PIXCLK_ALWAYS_ONb + |RADEON_PIXCLK_DAC_ALWAYS_ONb); + OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask); + + ulOrigCRTC_EXT_CNTL = INREG(RADEON_CRTC_EXT_CNTL); + ulData = ulOrigCRTC_EXT_CNTL; + ulData |= RADEON_CRTC_CRT_ON; + OUTREG(RADEON_CRTC_EXT_CNTL, ulData); + + ulOrigDAC_EXT_CNTL = INREG(RADEON_DAC_EXT_CNTL); + ulData = ulOrigDAC_EXT_CNTL; + ulData &= ~RADEON_DAC_FORCE_DATA_MASK; + ulData |= (RADEON_DAC_FORCE_BLANK_OFF_EN + |RADEON_DAC_FORCE_DATA_EN + |RADEON_DAC_FORCE_DATA_SEL_MASK); + if ((info->ChipFamily == CHIP_FAMILY_RV250) || + (info->ChipFamily == CHIP_FAMILY_RV280)) + ulData |= (0x01b6 << RADEON_DAC_FORCE_DATA_SHIFT); + else + ulData |= (0x01ac << RADEON_DAC_FORCE_DATA_SHIFT); + + OUTREG(RADEON_DAC_EXT_CNTL, ulData); + + ulOrigDAC_CNTL = INREG(RADEON_DAC_CNTL); + ulData = ulOrigDAC_CNTL; + ulData |= RADEON_DAC_CMP_EN; + ulData &= ~(RADEON_DAC_RANGE_CNTL_MASK + | RADEON_DAC_PDWN); + ulData |= 0x2; + OUTREG(RADEON_DAC_CNTL, ulData); + + usleep(10000); + + ulData = INREG(RADEON_DAC_CNTL); + bConnected = (RADEON_DAC_CMP_OUTPUT & ulData)?1:0; + + ulData = ulOrigVCLK_ECP_CNTL; + ulMask = 0xFFFFFFFFL; + OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask); + + OUTREG(RADEON_DAC_CNTL, ulOrigDAC_CNTL ); + OUTREG(RADEON_DAC_EXT_CNTL, ulOrigDAC_EXT_CNTL ); + OUTREG(RADEON_CRTC_EXT_CNTL, ulOrigCRTC_EXT_CNTL); + } else { /* TV DAC */ + + /* This doesn't seem to work reliably (maybe worse on some OEM cards), + for now we always return false. If one wants to connected a + non-DDC monitor on the DVI port when CRT port is also connected, + he will need to explicitly tell the driver in the config file + with Option MonitorLayout. + */ + bConnected = FALSE; + +#if 0 + if (info->ChipFamily == CHIP_FAMILY_R200) { + unsigned long ulOrigGPIO_MONID; + unsigned long ulOrigFP2_GEN_CNTL; + unsigned long ulOrigDISP_OUTPUT_CNTL; + unsigned long ulOrigCRTC2_GEN_CNTL; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_A; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_B; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_C; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_D; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_E; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_F; + unsigned long ulOrigCRTC2_H_TOTAL_DISP; + unsigned long ulOrigCRTC2_V_TOTAL_DISP; + unsigned long ulOrigCRTC2_H_SYNC_STRT_WID; + unsigned long ulOrigCRTC2_V_SYNC_STRT_WID; + unsigned long ulData, i; + + ulOrigGPIO_MONID = INREG(RADEON_GPIO_MONID); + ulOrigFP2_GEN_CNTL = INREG(RADEON_FP2_GEN_CNTL); + ulOrigDISP_OUTPUT_CNTL = INREG(RADEON_DISP_OUTPUT_CNTL); + ulOrigCRTC2_GEN_CNTL = INREG(RADEON_CRTC2_GEN_CNTL); + ulOrigDISP_LIN_TRANS_GRPH_A = INREG(RADEON_DISP_LIN_TRANS_GRPH_A); + ulOrigDISP_LIN_TRANS_GRPH_B = INREG(RADEON_DISP_LIN_TRANS_GRPH_B); + ulOrigDISP_LIN_TRANS_GRPH_C = INREG(RADEON_DISP_LIN_TRANS_GRPH_C); + ulOrigDISP_LIN_TRANS_GRPH_D = INREG(RADEON_DISP_LIN_TRANS_GRPH_D); + ulOrigDISP_LIN_TRANS_GRPH_E = INREG(RADEON_DISP_LIN_TRANS_GRPH_E); + ulOrigDISP_LIN_TRANS_GRPH_F = INREG(RADEON_DISP_LIN_TRANS_GRPH_F); + + ulOrigCRTC2_H_TOTAL_DISP = INREG(RADEON_CRTC2_H_TOTAL_DISP); + ulOrigCRTC2_V_TOTAL_DISP = INREG(RADEON_CRTC2_V_TOTAL_DISP); + ulOrigCRTC2_H_SYNC_STRT_WID = INREG(RADEON_CRTC2_H_SYNC_STRT_WID); + ulOrigCRTC2_V_SYNC_STRT_WID = INREG(RADEON_CRTC2_V_SYNC_STRT_WID); + + ulData = INREG(RADEON_GPIO_MONID); + ulData &= ~RADEON_GPIO_A_0; + OUTREG(RADEON_GPIO_MONID, ulData); + + OUTREG(RADEON_FP2_GEN_CNTL, 0x0a000c0c); + + OUTREG(RADEON_DISP_OUTPUT_CNTL, 0x00000012); + + OUTREG(RADEON_CRTC2_GEN_CNTL, 0x06000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); + OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); + OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); + OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); + OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); + + for (i = 0; i < 200; i++) { + ulData = INREG(RADEON_GPIO_MONID); + bConnected = (ulData & RADEON_GPIO_Y_0)?1:0; + if (!bConnected) break; + + usleep(1000); + } + + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, ulOrigDISP_LIN_TRANS_GRPH_A); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, ulOrigDISP_LIN_TRANS_GRPH_B); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, ulOrigDISP_LIN_TRANS_GRPH_C); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, ulOrigDISP_LIN_TRANS_GRPH_D); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, ulOrigDISP_LIN_TRANS_GRPH_E); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, ulOrigDISP_LIN_TRANS_GRPH_F); + OUTREG(RADEON_CRTC2_H_TOTAL_DISP, ulOrigCRTC2_H_TOTAL_DISP); + OUTREG(RADEON_CRTC2_V_TOTAL_DISP, ulOrigCRTC2_V_TOTAL_DISP); + OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, ulOrigCRTC2_H_SYNC_STRT_WID); + OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, ulOrigCRTC2_V_SYNC_STRT_WID); + OUTREG(RADEON_CRTC2_GEN_CNTL, ulOrigCRTC2_GEN_CNTL); + OUTREG(RADEON_DISP_OUTPUT_CNTL, ulOrigDISP_OUTPUT_CNTL); + OUTREG(RADEON_FP2_GEN_CNTL, ulOrigFP2_GEN_CNTL); + OUTREG(RADEON_GPIO_MONID, ulOrigGPIO_MONID); + } else { + unsigned long ulOrigPIXCLKSDATA; + unsigned long ulOrigTV_MASTER_CNTL; + unsigned long ulOrigTV_DAC_CNTL; + unsigned long ulOrigTV_PRE_DAC_MUX_CNTL; + unsigned long ulOrigDAC_CNTL2; + unsigned long ulData; + unsigned long ulMask; + + ulOrigPIXCLKSDATA = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + + ulData = ulOrigPIXCLKSDATA; + ulData &= ~(RADEON_PIX2CLK_ALWAYS_ONb + | RADEON_PIX2CLK_DAC_ALWAYS_ONb); + ulMask = ~(RADEON_PIX2CLK_ALWAYS_ONb + | RADEON_PIX2CLK_DAC_ALWAYS_ONb); + OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); + + ulOrigTV_MASTER_CNTL = INREG(RADEON_TV_MASTER_CNTL); + ulData = ulOrigTV_MASTER_CNTL; + ulData &= ~RADEON_TVCLK_ALWAYS_ONb; + OUTREG(RADEON_TV_MASTER_CNTL, ulData); + + ulOrigDAC_CNTL2 = INREG(RADEON_DAC_CNTL2); + ulData = ulOrigDAC_CNTL2; + ulData &= ~RADEON_DAC2_DAC2_CLK_SEL; + OUTREG(RADEON_DAC_CNTL2, ulData); + + ulOrigTV_DAC_CNTL = INREG(RADEON_TV_DAC_CNTL); + + ulData = 0x00880213; + OUTREG(RADEON_TV_DAC_CNTL, ulData); + + ulOrigTV_PRE_DAC_MUX_CNTL = INREG(RADEON_TV_PRE_DAC_MUX_CNTL); + + ulData = (RADEON_Y_RED_EN + | RADEON_C_GRN_EN + | RADEON_CMP_BLU_EN + | RADEON_RED_MX_FORCE_DAC_DATA + | RADEON_GRN_MX_FORCE_DAC_DATA + | RADEON_BLU_MX_FORCE_DAC_DATA); + if (IS_R300_VARIANT) + ulData |= 0x180 << RADEON_TV_FORCE_DAC_DATA_SHIFT; + else + ulData |= 0x1f5 << RADEON_TV_FORCE_DAC_DATA_SHIFT; + OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulData); + + usleep(10000); + + ulData = INREG(RADEON_TV_DAC_CNTL); + bConnected = (ulData & RADEON_TV_DAC_CMPOUT)?1:0; + + ulData = ulOrigPIXCLKSDATA; + ulMask = 0xFFFFFFFFL; + OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); + + OUTREG(RADEON_TV_MASTER_CNTL, ulOrigTV_MASTER_CNTL); + OUTREG(RADEON_DAC_CNTL2, ulOrigDAC_CNTL2); + OUTREG(RADEON_TV_DAC_CNTL, ulOrigTV_DAC_CNTL); + OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulOrigTV_PRE_DAC_MUX_CNTL); + } +#endif + } + + return(bConnected ? MT_CRT : MT_NONE); +} + + +static RADEONMonitorType RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, RADEONDDCType DDCType, RADEONConnector* port) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + unsigned long DDCReg; + RADEONMonitorType MonType = MT_NONE; + xf86MonPtr* MonInfo = &port->MonInfo; + int i, j; + + DDCReg = info->DDCReg; + switch(DDCType) + { + case DDC_MONID: + info->DDCReg = RADEON_GPIO_MONID; + break; + case DDC_DVI: + info->DDCReg = RADEON_GPIO_DVI_DDC; + break; + case DDC_VGA: + info->DDCReg = RADEON_GPIO_VGA_DDC; + break; + case DDC_CRT2: + info->DDCReg = RADEON_GPIO_CRT2_DDC; + break; + default: + info->DDCReg = DDCReg; + return MT_NONE; + } + + /* Read and output monitor info using DDC2 over I2C bus */ + if (info->pI2CBus && info->ddc2) { + OUTREG(info->DDCReg, INREG(info->DDCReg) & + (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1)); + + /* For some old monitors (like Compaq Presario FP500), we need + * following process to initialize/stop DDC + */ + OUTREG(info->DDCReg, INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1)); + for (j = 0; j < 3; j++) { + OUTREG(info->DDCReg, + INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0)); + usleep(13000); + + OUTREG(info->DDCReg, + INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1)); + for (i = 0; i < 10; i++) { + usleep(15000); + if (INREG(info->DDCReg) & RADEON_GPIO_Y_1) + break; + } + if (i == 10) continue; + + usleep(15000); + + OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0); + usleep(15000); + + OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1); + usleep(15000); + OUTREG(info->DDCReg, + INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0)); + usleep(15000); + *MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, info->pI2CBus); + + OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1); + OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0); + usleep(15000); + OUTREG(info->DDCReg, + INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1)); + for (i = 0; i < 5; i++) { + usleep(15000); + if (INREG(info->DDCReg) & RADEON_GPIO_Y_1) + break; + } + usleep(15000); + OUTREG(info->DDCReg, + INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0)); + usleep(15000); + + OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1); + OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0); + usleep(15000); + if(*MonInfo) break; + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DDC2/I2C is not properly initialized\n"); + MonType = MT_NONE; + } + + OUTREG(info->DDCReg, INREG(info->DDCReg) & + ~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1)); + + if (*MonInfo) { + if ((*MonInfo)->rawData[0x14] & 0x80) { + /* Note some laptops have a DVI output that uses internal TMDS, + * when its DVI is enabled by hotkey, LVDS panel is not used. + * In this case, the laptop is configured as DVI+VGA as a normal + * desktop card. + * Also for laptop, when X starts with lid closed (no DVI connection) + * both LDVS and TMDS are disable, we still need to treat it as a LVDS panel. + */ + if (port->TMDSType == TMDS_EXT) MonType = MT_DFP; + else { + if ((INREG(RADEON_FP_GEN_CNTL) & (1<<7)) || !info->IsMobility) + MonType = MT_DFP; + else + MonType = MT_LCD; + } + } else MonType = MT_CRT; + } else MonType = MT_NONE; + + info->DDCReg = DDCReg; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "DDC Type: %d, Detected Type: %d\n", DDCType, MonType); + + return MonType; +} + +static void RADEONGetPanelInfoFromReg (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 fp_vert_stretch = INREG(RADEON_FP_VERT_STRETCH); + CARD32 fp_horz_stretch = INREG(RADEON_FP_HORZ_STRETCH); + + info->PanelPwrDly = 200; + if (fp_vert_stretch & RADEON_VERT_STRETCH_ENABLE) { + info->PanelYRes = (fp_vert_stretch>>12) + 1; + } else { + info->PanelYRes = (INREG(RADEON_CRTC_V_TOTAL_DISP)>>16) + 1; + } + if (fp_horz_stretch & RADEON_HORZ_STRETCH_ENABLE) { + info->PanelXRes = ((fp_horz_stretch>>16) + 1) * 8; + } else { + info->PanelXRes = ((INREG(RADEON_CRTC_H_TOTAL_DISP)>>16) + 1) * 8; + } + + if ((info->PanelXRes < 640) || (info->PanelYRes < 480)) { + info->PanelXRes = 640; + info->PanelYRes = 480; + } + + if (xf86ReturnOptValBool(info->Options, OPTION_LVDS_PROBE_PLL, TRUE)) { + CARD32 ppll_div_sel, ppll_val; + + ppll_div_sel = INREG8(RADEON_CLOCK_CNTL_INDEX + 1) & 0x3; + RADEONPllErrataAfterIndex(info); + ppll_val = INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel); + if ((ppll_val & 0x000707ff) == 0x1bb) + goto noprobe; + info->FeedbackDivider = ppll_val & 0x7ff; + info->PostDivider = (ppll_val >> 16) & 0x7; + info->RefDivider = info->pll.reference_div; + info->UseBiosDividers = TRUE; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Existing panel PLL dividers will be used.\n"); + } + noprobe: + + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Panel size %dx%d is derived, this may not be correct.\n" + "If not, use PanelSize option to overwrite this setting\n", + info->PanelXRes, info->PanelYRes); +} + + +/* BIOS may not have right panel size, we search through all supported + * DDC modes looking for the maximum panel size. + */ +static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn) +{ + int j; + RADEONInfoPtr info = RADEONPTR (pScrn); + xf86MonPtr ddc = pScrn->monitor->DDC; + DisplayModePtr p; + + if ((info->UseBiosDividers && info->DotClock != 0) || (ddc == NULL)) + return; + + /* Go thru detailed timing table first */ + for (j = 0; j < 4; j++) { + if (ddc->det_mon[j].type == 0) { + struct detailed_timings *d_timings = + &ddc->det_mon[j].section.d_timings; + int match = 0; + + /* If we didn't get a panel clock or guessed one, try to match the + * mode with the panel size. We do that because we _need_ a panel + * clock, or ValidateFPModes will fail, even when UseBiosDividers + * is set. + */ + if (info->DotClock == 0 && + info->PanelXRes == d_timings->h_active && + info->PanelYRes == d_timings->v_active) + match = 1; + + /* If we don't have a BIOS provided panel data with fixed dividers, + * check for a larger panel size + */ + if (info->PanelXRes < d_timings->h_active && + info->PanelYRes < d_timings->v_active && + !info->UseBiosDividers) + match = 1; + + if (match) { + info->PanelXRes = d_timings->h_active; + info->PanelYRes = d_timings->v_active; + info->DotClock = d_timings->clock / 1000; + info->HOverPlus = d_timings->h_sync_off; + info->HSyncWidth = d_timings->h_sync_width; + info->HBlank = d_timings->h_blanking; + info->VOverPlus = d_timings->v_sync_off; + info->VSyncWidth = d_timings->v_sync_width; + info->VBlank = d_timings->v_blanking; + info->Flags = (d_timings->interlaced ? V_INTERLACE : 0); + if (d_timings->sync == 3) { + switch (d_timings->misc) { + case 0: info->Flags |= V_NHSYNC | V_NVSYNC; break; + case 1: info->Flags |= V_PHSYNC | V_NVSYNC; break; + case 2: info->Flags |= V_NHSYNC | V_PVSYNC; break; + case 3: info->Flags |= V_PHSYNC | V_PVSYNC; break; + } + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel infos found from DDC detailed: %dx%d\n", + info->PanelXRes, info->PanelYRes); + } + } + } + + if (info->UseBiosDividers && info->DotClock != 0) + return; + + /* Search thru standard VESA modes from EDID */ + for (j = 0; j < 8; j++) { + if ((info->PanelXRes < ddc->timings2[j].hsize) && + (info->PanelYRes < ddc->timings2[j].vsize)) { + for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { + if ((ddc->timings2[j].hsize == p->HDisplay) && + (ddc->timings2[j].vsize == p->VDisplay)) { + float refresh = + (float)p->Clock * 1000.0 / p->HTotal / p->VTotal; + + if (abs((float)ddc->timings2[j].refresh - refresh) < 1.0) { + /* Is this good enough? */ + info->PanelXRes = ddc->timings2[j].hsize; + info->PanelYRes = ddc->timings2[j].vsize; + info->HBlank = p->HTotal - p->HDisplay; + info->HOverPlus = p->HSyncStart - p->HDisplay; + info->HSyncWidth = p->HSyncEnd - p->HSyncStart; + info->VBlank = p->VTotal - p->VDisplay; + info->VOverPlus = p->VSyncStart - p->VDisplay; + info->VSyncWidth = p->VSyncEnd - p->VSyncStart; + info->DotClock = p->Clock; + info->Flags = p->Flags; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel infos found from DDC VESA/EDID: %dx%d\n", + info->PanelXRes, info->PanelYRes); + } + } + } + } + } +} + +static Bool RADEONGetLVDSInfo (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (!RADEONGetLVDSInfoFromBIOS(pScrn)) + RADEONGetPanelInfoFromReg(pScrn); + + /* The panel size we collected from BIOS may not be the + * maximum size supported by the panel. If not, we update + * it now. These will be used if no matching mode can be + * found from EDID data. + */ + RADEONUpdatePanelSize(pScrn); + + /* No timing information for the native mode, + * use whatever specified in the Modeline. + * If no Modeline specified, we'll just pick + * the VESA mode at 60Hz refresh rate which + * is likely to be the best for a flat panel. + */ + if (info->DotClock == 0) { + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + DisplayModePtr tmp_mode = NULL; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No valid timing info from BIOS.\n"); + tmp_mode = pScrn->monitor->Modes; + while(tmp_mode) { + if ((tmp_mode->HDisplay == info->PanelXRes) && + (tmp_mode->VDisplay == info->PanelYRes)) { + + float refresh = + (float)tmp_mode->Clock * 1000.0 / tmp_mode->HTotal / tmp_mode->VTotal; + if ((abs(60.0 - refresh) < 1.0) || + (tmp_mode->type == 0)) { + info->HBlank = tmp_mode->HTotal - tmp_mode->HDisplay; + info->HOverPlus = tmp_mode->HSyncStart - tmp_mode->HDisplay; + info->HSyncWidth = tmp_mode->HSyncEnd - tmp_mode->HSyncStart; + info->VBlank = tmp_mode->VTotal - tmp_mode->VDisplay; + info->VOverPlus = tmp_mode->VSyncStart - tmp_mode->VDisplay; + info->VSyncWidth = tmp_mode->VSyncEnd - tmp_mode->VSyncStart; + info->DotClock = tmp_mode->Clock; + info->Flags = 0; + break; + } + } + tmp_mode = tmp_mode->next; + } + if ((info->DotClock == 0) && !pRADEONEnt->PortInfo[0].MonInfo) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Panel size is not correctly detected.\n" + "Please try to use PanelSize option for correct settings.\n"); + return FALSE; + } + } + + return TRUE; +} + +static void RADEONGetTMDSInfo(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + int i; + + for (i=0; i<4; i++) { + info->tmds_pll[i].value = 0; + info->tmds_pll[i].freq = 0; + } + + if (RADEONGetTMDSInfoFromBIOS(pScrn)) return; + + for (i=0; i<4; i++) { + info->tmds_pll[i].value = default_tmds_pll[info->ChipFamily][i].value; + info->tmds_pll[i].freq = default_tmds_pll[info->ChipFamily][i].freq; + } +} + +void RADEONGetPanelInfo (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + char* s; + + if((s = xf86GetOptValString(info->Options, OPTION_PANEL_SIZE))) { + info->PanelPwrDly = 200; + if (sscanf (s, "%dx%d", &info->PanelXRes, &info->PanelYRes) != 2) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Invalid PanelSize option: %s\n", s); + RADEONGetPanelInfoFromReg(pScrn); + } + } else { + + if(info->DisplayType == MT_LCD) { + RADEONGetLVDSInfo(pScrn); + } else if ((info->DisplayType == MT_DFP) || (info->MergeType == MT_DFP)) { + RADEONGetTMDSInfo(pScrn); + if (!pScrn->monitor->DDC) + RADEONGetHardCodedEDIDFromBIOS(pScrn); + else if (!info->IsSecondary) + RADEONUpdatePanelSize(pScrn); + } + } +} + +BOOL RADEONQueryConnectedMonitors(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + const char *s; + Bool ignore_edid = FALSE; + int i = 0, second = 0, max_mt; + + + + max_mt = 5; + + if(info->IsSecondary) { + info->DisplayType = (RADEONMonitorType)pRADEONEnt->MonType2; + if(info->DisplayType == MT_NONE) return FALSE; + return TRUE; + } + + + /* We first get the information about all connectors from BIOS. + * This is how the card is phyiscally wired up. + * The information should be correct even on a OEM card. + * If not, we may have problem -- need to use MonitorLayout option. + */ + for (i = 0; i < 2; i++) { + pRADEONEnt->PortInfo[i].MonType = MT_UNKNOWN; + pRADEONEnt->PortInfo[i].MonInfo = NULL; + pRADEONEnt->PortInfo[i].DDCType = DDC_NONE_DETECTED; + pRADEONEnt->PortInfo[i].DACType = DAC_UNKNOWN; + pRADEONEnt->PortInfo[i].TMDSType = TMDS_UNKNOWN; + pRADEONEnt->PortInfo[i].ConnectorType = CONNECTOR_NONE; + } + + if (!RADEONGetConnectorInfoFromBIOS(pScrn)) { + /* Below is the most common setting, but may not be true */ + pRADEONEnt->PortInfo[0].MonType = MT_UNKNOWN; + pRADEONEnt->PortInfo[0].MonInfo = NULL; + pRADEONEnt->PortInfo[0].DDCType = DDC_DVI; + pRADEONEnt->PortInfo[0].DACType = DAC_TVDAC; + pRADEONEnt->PortInfo[0].TMDSType = TMDS_INT; + pRADEONEnt->PortInfo[0].ConnectorType = CONNECTOR_DVI_D; + + pRADEONEnt->PortInfo[1].MonType = MT_UNKNOWN; + pRADEONEnt->PortInfo[1].MonInfo = NULL; + pRADEONEnt->PortInfo[1].DDCType = DDC_VGA; + pRADEONEnt->PortInfo[1].DACType = DAC_PRIMARY; + pRADEONEnt->PortInfo[1].TMDSType = TMDS_EXT; + pRADEONEnt->PortInfo[1].ConnectorType = CONNECTOR_CRT; + + /* Some cards have the DDC lines swapped and we have no way to + * detect it yet (Mac cards) + */ + if (xf86ReturnOptValBool(info->Options, OPTION_REVERSE_DDC, FALSE)) { + pRADEONEnt->PortInfo[0].DDCType = DDC_VGA; + pRADEONEnt->PortInfo[1].DDCType = DDC_DVI; + } + } + + /* always make TMDS_INT port first*/ + if (pRADEONEnt->PortInfo[1].TMDSType == TMDS_INT) { + RADEONConnector connector; + connector = pRADEONEnt->PortInfo[0]; + pRADEONEnt->PortInfo[0] = pRADEONEnt->PortInfo[1]; + pRADEONEnt->PortInfo[1] = connector; + } else if ((pRADEONEnt->PortInfo[0].TMDSType != TMDS_INT && + pRADEONEnt->PortInfo[1].TMDSType != TMDS_INT)) { + /* no TMDS_INT port, make primary DAC port first */ + /* On my Inspiron 8600 both internal and external ports are + marked DAC_PRIMARY in BIOS. So be extra careful - only + swap when the first port is not DAC_PRIMARY */ + if ( (pRADEONEnt->PortInfo[1].DACType == DAC_PRIMARY) && + (pRADEONEnt->PortInfo[0].DACType != DAC_PRIMARY)) { + RADEONConnector connector; + connector = pRADEONEnt->PortInfo[0]; + pRADEONEnt->PortInfo[0] = pRADEONEnt->PortInfo[1]; + pRADEONEnt->PortInfo[1] = connector; + } + } + + if (info->HasSingleDAC) { + /* For RS300/RS350/RS400 chips, there is no primary DAC. Force VGA port to use TVDAC*/ + if (pRADEONEnt->PortInfo[0].ConnectorType == CONNECTOR_CRT) { + pRADEONEnt->PortInfo[0].DACType = DAC_TVDAC; + pRADEONEnt->PortInfo[1].DACType = DAC_PRIMARY; + } else { + pRADEONEnt->PortInfo[1].DACType = DAC_TVDAC; + pRADEONEnt->PortInfo[0].DACType = DAC_PRIMARY; + } + } else if (!info->HasCRTC2) { + pRADEONEnt->PortInfo[0].DACType = DAC_PRIMARY; + } + + /* IgnoreEDID option is different from the NoDDCxx options used by DDC module + * When IgnoreEDID is used, monitor detection will still use DDC + * detection, but all EDID data will not be used in mode validation. + * You can use this option when you have a DDC monitor but want specify your own + * monitor timing parameters by using HSync, VRefresh and Modeline, + */ + if (xf86GetOptValBool(info->Options, OPTION_IGNORE_EDID, &ignore_edid)) { + if (ignore_edid) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "IgnoreEDID is specified, EDID data will be ignored\n"); + } + + /* + * MonitorLayout option takes a string for two monitors connected in following format: + * Option "MonitorLayout" "primary-port-display, secondary-port-display" + * primary and secondary port displays can have one of following: + * NONE, CRT, LVDS, TMDS + * With this option, driver will bring up monitors as specified, + * not using auto-detection routines to probe monitors. + * + * This option can be used when the false monitor detection occurs. + * + * This option can also be used to disable one connected display. + * For example, if you have a laptop connected to an external CRT + * and you want to disable the internal LCD panel, you can specify + * Option "MonitorLayout" "NONE, CRT" + * + * This option can also used to disable Clone mode. One there is only + * one monitor is specified, clone mode will be turned off automatically + * even you have two monitors connected. + * + * Another usage of this option is you want to config the server + * to start up with a certain monitor arrangement even one monitor + * is not plugged in when server starts. + */ + if ((s = xf86GetOptValString(info->Options, OPTION_MONITOR_LAYOUT))) { + char s1[5], s2[5]; + i = 0; + /* When using user specified monitor types, we will not do DDC detection + * + */ + do { + switch(*s) { + case ',': + s1[i] = '\0'; + i = 0; + second = 1; + break; + case ' ': + case '\t': + case '\n': + case '\r': + break; + default: + if (second) + s2[i] = *s; + else + s1[i] = *s; + i++; + break; + } + if (i > 4) i = 4; + } while(*s++); + s2[i] = '\0'; + + for (i = 0; i < max_mt; i++) { + if (strcmp(s1, MonTypeName[i]) == 0) { + pRADEONEnt->PortInfo[0].MonType = MonTypeID[i]; + break; + } + } + for (i = 0; i < max_mt; i++) { + if (strcmp(s2, MonTypeName[i]) == 0) { + pRADEONEnt->PortInfo[1].MonType = MonTypeID[i]; + break; + } + } + + if (i == max_mt) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Invalid Monitor type specified for 2nd port \n"); + + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "MonitorLayout Option: \n\tMonitor1--Type %s, Monitor2--Type %s\n\n", s1, s2); +#if 0 + if (pRADEONEnt->PortInfo[1].MonType == MT_CRT) { + pRADEONEnt->PortInfo[1].DACType = DAC_PRIMARY; + pRADEONEnt->PortInfo[1].TMDSType = TMDS_UNKNOWN; + pRADEONEnt->PortInfo[1].DDCType = DDC_VGA; + pRADEONEnt->PortInfo[1].ConnectorType = CONNECTOR_CRT; + pRADEONEnt->PortInfo[0].DACType = DAC_TVDAC; + pRADEONEnt->PortInfo[0].TMDSType = TMDS_UNKNOWN; + pRADEONEnt->PortInfo[0].DDCType = DDC_NONE_DETECTED; + pRADEONEnt->PortInfo[0].ConnectorType = pRADEONEnt->PortInfo[0].MonType+1; + pRADEONEnt->PortInfo[0].MonInfo = NULL; + } +#endif + + if (!ignore_edid) { + if ((pRADEONEnt->PortInfo[0].MonType > MT_NONE) && + (pRADEONEnt->PortInfo[0].MonType < MT_STV)) + RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[0].DDCType, + &pRADEONEnt->PortInfo[0]); + if ((pRADEONEnt->PortInfo[1].MonType > MT_NONE) && + (pRADEONEnt->PortInfo[1].MonType < MT_STV)) + RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[1].DDCType, + &pRADEONEnt->PortInfo[1]); + } + + } + + if(((!info->HasCRTC2) || info->IsDellServer)) { + if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN) { + if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_DVI, &pRADEONEnt->PortInfo[0]))); + else if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_VGA, &pRADEONEnt->PortInfo[0]))); + else if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->PortInfo[0]))); + else + pRADEONEnt->PortInfo[0].MonType = MT_CRT; + } + + if (!ignore_edid) { + if (pRADEONEnt->PortInfo[0].MonInfo) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor1 EDID data ---------------------------\n"); + xf86PrintEDID(pRADEONEnt->PortInfo[0].MonInfo ); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor1 EDID data --------------------\n"); + } + } + + pRADEONEnt->MonType1 = pRADEONEnt->PortInfo[0].MonType; + pRADEONEnt->MonInfo1 = pRADEONEnt->PortInfo[0].MonInfo; + pRADEONEnt->MonType2 = MT_NONE; + pRADEONEnt->MonInfo2 = NULL; + info->MergeType = MT_NONE; + info->DisplayType = pRADEONEnt->MonType1; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Primary:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", + MonTypeName[pRADEONEnt->PortInfo[0].MonType+1], + info->IsAtomBios ? + ConnectorTypeNameATOM[pRADEONEnt->PortInfo[0].ConnectorType]: + ConnectorTypeName[pRADEONEnt->PortInfo[0].ConnectorType], + DACTypeName[pRADEONEnt->PortInfo[0].DACType+1], + TMDSTypeName[pRADEONEnt->PortInfo[0].TMDSType+1], + DDCTypeName[pRADEONEnt->PortInfo[0].DDCType]); + + return TRUE; + } + + if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN || pRADEONEnt->PortInfo[1].MonType == MT_UNKNOWN) { + + /* Primary Head (DVI or Laptop Int. panel)*/ + /* A ddc capable display connected on DVI port */ + if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN) { + if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[0].DDCType, &pRADEONEnt->PortInfo[0]))); + else if (info->IsMobility && + (INREG(RADEON_BIOS_4_SCRATCH) & 4)) { + /* non-DDC laptop panel connected on primary */ + pRADEONEnt->PortInfo[0].MonType = MT_LCD; + } else { + /* CRT on DVI, TODO: not reliable, make it always return false for now*/ + pRADEONEnt->PortInfo[0].MonType = RADEONCrtIsPhysicallyConnected(pScrn, !(pRADEONEnt->PortInfo[0].DACType)); + } + } + + /* Secondary Head (mostly VGA, can be DVI on some OEM boards)*/ + if (pRADEONEnt->PortInfo[1].MonType == MT_UNKNOWN) { + if((pRADEONEnt->PortInfo[1].MonType = + RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[1].DDCType, &pRADEONEnt->PortInfo[1]))); + else if (info->IsMobility && + (INREG(RADEON_FP2_GEN_CNTL) & RADEON_FP2_ON)) { + /* non-DDC TMDS panel connected through DVO */ + pRADEONEnt->PortInfo[1].MonType = MT_DFP; + } else + pRADEONEnt->PortInfo[1].MonType = RADEONCrtIsPhysicallyConnected(pScrn, !(pRADEONEnt->PortInfo[1].DACType)); + } + } + + if(ignore_edid) { + pRADEONEnt->PortInfo[0].MonInfo = NULL; + pRADEONEnt->PortInfo[1].MonInfo = NULL; + } else { + if (pRADEONEnt->PortInfo[0].MonInfo) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on port 1 ----------------------\n"); + xf86PrintEDID(pRADEONEnt->PortInfo[0].MonInfo ); + } + + if (pRADEONEnt->PortInfo[1].MonInfo) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on port 2-----------------------\n"); + xf86PrintEDID(pRADEONEnt->PortInfo[1].MonInfo ); + } + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\n"); + + pRADEONEnt->MonType1 = pRADEONEnt->PortInfo[0].MonType; + pRADEONEnt->MonInfo1 = pRADEONEnt->PortInfo[0].MonInfo; + pRADEONEnt->MonType2 = pRADEONEnt->PortInfo[1].MonType; + pRADEONEnt->MonInfo2 = pRADEONEnt->PortInfo[1].MonInfo; + if (pRADEONEnt->PortInfo[0].MonType == MT_NONE) { + if (pRADEONEnt->PortInfo[1].MonType == MT_NONE) { + pRADEONEnt->MonType1 = MT_CRT; + pRADEONEnt->MonInfo1 = NULL; + } else { + RADEONConnector tmp; + pRADEONEnt->MonType1 = pRADEONEnt->PortInfo[1].MonType; + pRADEONEnt->MonInfo1 = pRADEONEnt->PortInfo[1].MonInfo; + tmp = pRADEONEnt->PortInfo[0]; + pRADEONEnt->PortInfo[0] = pRADEONEnt->PortInfo[1]; + pRADEONEnt->PortInfo[1] = tmp; + } + pRADEONEnt->MonType2 = MT_NONE; + pRADEONEnt->MonInfo2 = NULL; + } + + info->DisplayType = pRADEONEnt->MonType1; + pRADEONEnt->ReversedDAC = FALSE; + info->OverlayOnCRTC2 = FALSE; + info->MergeType = MT_NONE; + if (pRADEONEnt->MonType2 != MT_NONE) { + if(!pRADEONEnt->HasSecondary) { + info->MergeType = pRADEONEnt->MonType2; + } + + if (pRADEONEnt->PortInfo[1].DACType == DAC_TVDAC) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reversed DAC decteced\n"); + pRADEONEnt->ReversedDAC = TRUE; + } + } else { + pRADEONEnt->HasSecondary = FALSE; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Primary:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", + MonTypeName[pRADEONEnt->PortInfo[0].MonType+1], + info->IsAtomBios ? + ConnectorTypeNameATOM[pRADEONEnt->PortInfo[0].ConnectorType]: + ConnectorTypeName[pRADEONEnt->PortInfo[0].ConnectorType], + DACTypeName[pRADEONEnt->PortInfo[0].DACType+1], + TMDSTypeName[pRADEONEnt->PortInfo[0].TMDSType+1], + DDCTypeName[pRADEONEnt->PortInfo[0].DDCType]); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Secondary:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", + MonTypeName[pRADEONEnt->PortInfo[1].MonType+1], + info->IsAtomBios ? + ConnectorTypeNameATOM[pRADEONEnt->PortInfo[1].ConnectorType]: + ConnectorTypeName[pRADEONEnt->PortInfo[1].ConnectorType], + DACTypeName[pRADEONEnt->PortInfo[1].DACType+1], + TMDSTypeName[pRADEONEnt->PortInfo[1].TMDSType+1], + DDCTypeName[pRADEONEnt->PortInfo[1].DDCType]); + + return TRUE; +} + + +/* + * Powering done DAC, needed for DPMS problem with ViewSonic P817 (or its variant). + * + * Note for current DAC mapping when calling this function: + * For most of cards: + * single CRT: Driver doesn't change the existing CRTC->DAC mapping, + * CRTC1 could be driving either DAC or both DACs. + * CRT+CRT: CRTC1->TV DAC, CRTC2->Primary DAC + * DFP/LCD+CRT: CRTC2->TV DAC, CRTC2->Primary DAC. + * Some boards have two DACs reversed or don't even have a primary DAC, + * this is reflected in pRADEONEnt->ReversedDAC. And radeon 7200 doesn't + * have a second DAC. + * It's kind of messy, we'll need to redo DAC mapping part some day. + */ +static void RADEONDacPowerSet(ScrnInfoPtr pScrn, Bool IsOn, Bool IsPrimaryDAC) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + if (IsPrimaryDAC) { + CARD32 dac_cntl; + CARD32 dac_macro_cntl = 0; + dac_cntl = INREG(RADEON_DAC_CNTL); + if ((!info->IsMobility) || (info->ChipFamily == CHIP_FAMILY_RV350)) + dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL); + if (IsOn) { + dac_cntl &= ~RADEON_DAC_PDWN; + dac_macro_cntl &= ~(RADEON_DAC_PDWN_R | + RADEON_DAC_PDWN_G | + RADEON_DAC_PDWN_B); + } else { + dac_cntl |= RADEON_DAC_PDWN; + dac_macro_cntl |= (RADEON_DAC_PDWN_R | + RADEON_DAC_PDWN_G | + RADEON_DAC_PDWN_B); + } + OUTREG(RADEON_DAC_CNTL, dac_cntl); + if ((!info->IsMobility) || (info->ChipFamily == CHIP_FAMILY_RV350)) + OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); + } else { + if (info->ChipFamily != CHIP_FAMILY_R200) { + CARD32 tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); + if (IsOn) { + tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD | + RADEON_TV_DAC_GDACPD | + RADEON_TV_DAC_BDACPD | + RADEON_TV_DAC_BGSLEEP); + } else { + tv_dac_cntl |= (RADEON_TV_DAC_RDACPD | + RADEON_TV_DAC_GDACPD | + RADEON_TV_DAC_BDACPD | + RADEON_TV_DAC_BGSLEEP); + } + OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl); + } else { + CARD32 fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL); + if (IsOn) { + fp2_gen_cntl |= RADEON_FP2_DVO_EN; + } else { + fp2_gen_cntl &= ~RADEON_FP2_DVO_EN; + } + OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); + } + } +} + +/* Calculate display buffer watermark to prevent buffer underflow */ +void RADEONInitDispBandwidth(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + RADEONInfoPtr info2 = NULL; + + DisplayModePtr mode1, mode2; + + CARD32 temp, data, mem_trcd, mem_trp, mem_tras, mem_trbs=0; + float mem_tcas; + int k1, c; + CARD32 MemTrcdExtMemCntl[4] = {1, 2, 3, 4}; + CARD32 MemTrpExtMemCntl[4] = {1, 2, 3, 4}; + CARD32 MemTrasExtMemCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + CARD32 MemTrcdMemTimingCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + CARD32 MemTrpMemTimingCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + CARD32 MemTrasMemTimingCntl[16] = {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + + float MemTcas[8] = {0, 1, 2, 3, 0, 1.5, 2.5, 0}; + float MemTcas2[8] = {0, 1, 2, 3, 4, 5, 6, 7}; + float MemTrbs[8] = {1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5}; + + float mem_bw, peak_disp_bw; + float min_mem_eff = 0.8; + float sclk_eff, sclk_delay; + float mc_latency_mclk, mc_latency_sclk, cur_latency_mclk, cur_latency_sclk; + float disp_latency, disp_latency_overhead, disp_drain_rate, disp_drain_rate2; + float pix_clk, pix_clk2; /* in MHz */ + int cur_size = 16; /* in octawords */ + int critical_point, critical_point2; + int stop_req, max_stop_req; + float read_return_rate, time_disp1_drop_priority; + + /* + * Set display0/1 priority up on r3/4xx in the memory controller for + * high res modes if the user specifies HIGH for displaypriority + * option. + */ + if ((info->DispPriority == 2) && IS_R300_VARIANT) { + CARD32 mc_init_misc_lat_timer = INREG(R300_MC_INIT_MISC_LAT_TIMER); + if (info->MergedFB || pRADEONEnt->HasSecondary) { + mc_init_misc_lat_timer |= 0x1100; /* display 0 and 1 */ + } else { + mc_init_misc_lat_timer |= 0x0100; /* display 0 only */ + } + OUTREG(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); + } + + + /* R420 and RV410 family not supported yet */ + if (info->ChipFamily == CHIP_FAMILY_R420 || info->ChipFamily == CHIP_FAMILY_RV410) return; + + if (pRADEONEnt->pSecondaryScrn) { + if (info->IsSecondary) return; + info2 = RADEONPTR(pRADEONEnt->pSecondaryScrn); + } else if (info->MergedFB) info2 = info; + + /* + * Determine if there is enough bandwidth for current display mode + */ + mem_bw = info->mclk * (info->RamWidth / 8) * (info->IsDDR ? 2 : 1); + + mode1 = info->CurrentLayout.mode; + if (info->MergedFB) { + mode1 = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT1; + mode2 = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2; + } else if ((pRADEONEnt->HasSecondary) && info2) { + mode2 = info2->CurrentLayout.mode; + } else { + mode2 = NULL; + } + + pix_clk = mode1->Clock/1000.0; + if (mode2) + pix_clk2 = mode2->Clock/1000.0; + else + pix_clk2 = 0; + + peak_disp_bw = (pix_clk * info->CurrentLayout.pixel_bytes); + if (info2) + peak_disp_bw += (pix_clk2 * info2->CurrentLayout.pixel_bytes); + + if (peak_disp_bw >= mem_bw * min_mem_eff) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "You may not have enough display bandwidth for current mode\n" + "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); + } + + /* CRTC1 + Set GRPH_BUFFER_CNTL register using h/w defined optimal values. + GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] + */ + stop_req = mode1->HDisplay * info->CurrentLayout.pixel_bytes / 16; + + /* setup Max GRPH_STOP_REQ default value */ + if (IS_RV100_VARIANT) + max_stop_req = 0x5c; + else + max_stop_req = 0x7c; + if (stop_req > max_stop_req) + stop_req = max_stop_req; + + /* Get values from the EXT_MEM_CNTL register...converting its contents. */ + temp = INREG(RADEON_MEM_TIMING_CNTL); + if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ + mem_trcd = MemTrcdExtMemCntl[(temp & 0x0c) >> 2]; + mem_trp = MemTrpExtMemCntl[ (temp & 0x03) >> 0]; + mem_tras = MemTrasExtMemCntl[(temp & 0x70) >> 4]; + } else { /* RV200 and later */ + mem_trcd = MemTrcdMemTimingCntl[(temp & 0x07) >> 0]; + mem_trp = MemTrpMemTimingCntl[ (temp & 0x700) >> 8]; + mem_tras = MemTrasMemTimingCntl[(temp & 0xf000) >> 12]; + } + + /* Get values from the MEM_SDRAM_MODE_REG register...converting its */ + temp = INREG(RADEON_MEM_SDRAM_MODE_REG); + data = (temp & (7<<20)) >> 20; + if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ + mem_tcas = MemTcas [data]; + } else { + mem_tcas = MemTcas2 [data]; + } + + if (IS_R300_VARIANT) { + + /* on the R300, Tcas is included in Trbs. + */ + temp = INREG(RADEON_MEM_CNTL); + data = (R300_MEM_NUM_CHANNELS_MASK & temp); + if (data == 1) { + if (R300_MEM_USE_CD_CH_ONLY & temp) { + temp = INREG(R300_MC_IND_INDEX); + temp &= ~R300_MC_IND_ADDR_MASK; + temp |= R300_MC_READ_CNTL_CD_mcind; + OUTREG(R300_MC_IND_INDEX, temp); + temp = INREG(R300_MC_IND_DATA); + data = (R300_MEM_RBS_POSITION_C_MASK & temp); + } else { + temp = INREG(R300_MC_READ_CNTL_AB); + data = (R300_MEM_RBS_POSITION_A_MASK & temp); + } + } else { + temp = INREG(R300_MC_READ_CNTL_AB); + data = (R300_MEM_RBS_POSITION_A_MASK & temp); + } + + mem_trbs = MemTrbs[data]; + mem_tcas += mem_trbs; + } + + if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ + /* DDR64 SCLK_EFF = SCLK for analysis */ + sclk_eff = info->sclk; + } else { +#ifdef XF86DRI + if (info->directRenderingEnabled) + sclk_eff = info->sclk - (info->agpMode * 50.0 / 3.0); + else +#endif + sclk_eff = info->sclk; + } + + /* Find the memory controller latency for the display client. + */ + if (IS_R300_VARIANT) { + /*not enough for R350 ???*/ + /* + if (!mode2) sclk_delay = 150; + else { + if (info->RamWidth == 256) sclk_delay = 87; + else sclk_delay = 97; + } + */ + sclk_delay = 250; + } else { + if ((info->ChipFamily == CHIP_FAMILY_RV100) || + info->IsIGP) { + if (info->IsDDR) sclk_delay = 41; + else sclk_delay = 33; + } else { + if (info->RamWidth == 128) sclk_delay = 57; + else sclk_delay = 41; + } + } + + mc_latency_sclk = sclk_delay / sclk_eff; + + if (info->IsDDR) { + if (info->RamWidth == 32) { + k1 = 40; + c = 3; + } else { + k1 = 20; + c = 1; + } + } else { + k1 = 40; + c = 3; + } + mc_latency_mclk = ((2.0*mem_trcd + mem_tcas*c + 4.0*mem_tras + 4.0*mem_trp + k1) / + info->mclk) + (4.0 / sclk_eff); + + /* + HW cursor time assuming worst case of full size colour cursor. + */ + cur_latency_mclk = (mem_trp + MAX(mem_tras, (mem_trcd + 2*(cur_size - (info->IsDDR+1))))) / info->mclk; + cur_latency_sclk = cur_size / sclk_eff; + + /* + Find the total latency for the display data. + */ + disp_latency_overhead = 8.0 / info->sclk; + mc_latency_mclk = mc_latency_mclk + disp_latency_overhead + cur_latency_mclk; + mc_latency_sclk = mc_latency_sclk + disp_latency_overhead + cur_latency_sclk; + disp_latency = MAX(mc_latency_mclk, mc_latency_sclk); + + /* + Find the drain rate of the display buffer. + */ + disp_drain_rate = pix_clk / (16.0/info->CurrentLayout.pixel_bytes); + if (info2) + disp_drain_rate2 = pix_clk2 / (16.0/info2->CurrentLayout.pixel_bytes); + else + disp_drain_rate2 = 0; + + /* + Find the critical point of the display buffer. + */ + critical_point= (CARD32)(disp_drain_rate * disp_latency + 0.5); + + /* ???? */ + /* + temp = (info->SavedReg.grph_buffer_cntl & RADEON_GRPH_CRITICAL_POINT_MASK) >> RADEON_GRPH_CRITICAL_POINT_SHIFT; + if (critical_point < temp) critical_point = temp; + */ + if (info->DispPriority == 2) { + critical_point = 0; + } + + /* + The critical point should never be above max_stop_req-4. Setting + GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. + */ + if (max_stop_req - critical_point < 4) critical_point = 0; + + if (critical_point == 0 && mode2 && info->ChipFamily == CHIP_FAMILY_R300) { + /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ + critical_point = 0x10; + } + + temp = info->SavedReg.grph_buffer_cntl; + temp &= ~(RADEON_GRPH_STOP_REQ_MASK); + temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); + temp &= ~(RADEON_GRPH_START_REQ_MASK); + if ((info->ChipFamily == CHIP_FAMILY_R350) && + (stop_req > 0x15)) { + stop_req -= 0x10; + } + temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); + + temp |= RADEON_GRPH_BUFFER_SIZE; + temp &= ~(RADEON_GRPH_CRITICAL_CNTL | + RADEON_GRPH_CRITICAL_AT_SOF | + RADEON_GRPH_STOP_CNTL); + /* + Write the result into the register. + */ + OUTREG(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | + (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); + + RADEONTRACE(("GRPH_BUFFER_CNTL from %x to %x\n", + (unsigned int)info->SavedReg.grph_buffer_cntl, INREG(RADEON_GRPH_BUFFER_CNTL))); + + if (mode2) { + stop_req = mode2->HDisplay * info2->CurrentLayout.pixel_bytes / 16; + + if (stop_req > max_stop_req) stop_req = max_stop_req; + + temp = info->SavedReg.grph2_buffer_cntl; + temp &= ~(RADEON_GRPH_STOP_REQ_MASK); + temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); + temp &= ~(RADEON_GRPH_START_REQ_MASK); + if ((info->ChipFamily == CHIP_FAMILY_R350) && + (stop_req > 0x15)) { + stop_req -= 0x10; + } + temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); + temp |= RADEON_GRPH_BUFFER_SIZE; + temp &= ~(RADEON_GRPH_CRITICAL_CNTL | + RADEON_GRPH_CRITICAL_AT_SOF | + RADEON_GRPH_STOP_CNTL); + + if ((info->ChipFamily == CHIP_FAMILY_RS100) || + (info->ChipFamily == CHIP_FAMILY_RS200)) + critical_point2 = 0; + else { + read_return_rate = MIN(info->sclk, info->mclk*(info->RamWidth*(info->IsDDR+1)/128)); + time_disp1_drop_priority = critical_point / (read_return_rate - disp_drain_rate); + + critical_point2 = (CARD32)((disp_latency + time_disp1_drop_priority + + disp_latency) * disp_drain_rate2 + 0.5); + + if (info->DispPriority == 2) { + critical_point2 = 0; + } + + if (max_stop_req - critical_point2 < 4) critical_point2 = 0; + + } + + if (critical_point2 == 0 && info->ChipFamily == CHIP_FAMILY_R300) { + /* some R300 cards have problem with this set to 0 */ + critical_point2 = 0x10; + } + + OUTREG(RADEON_GRPH2_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | + (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); + + RADEONTRACE(("GRPH2_BUFFER_CNTL from %x to %x\n", + (unsigned int)info->SavedReg.grph2_buffer_cntl, INREG(RADEON_GRPH2_BUFFER_CNTL))); + } +} + + +/* Blank screen */ +void RADEONBlank(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + if (!info->IsSecondary) { + switch(info->DisplayType) { + case MT_LCD: + case MT_CRT: + case MT_DFP: + OUTREGP(RADEON_CRTC_EXT_CNTL, + RADEON_CRTC_DISPLAY_DIS, + ~(RADEON_CRTC_DISPLAY_DIS)); + break; + + case MT_NONE: + default: + break; + } + if (info->MergedFB) + OUTREGP(RADEON_CRTC2_GEN_CNTL, + RADEON_CRTC2_DISP_DIS, + ~(RADEON_CRTC2_DISP_DIS)); + } else { + OUTREGP(RADEON_CRTC2_GEN_CNTL, + RADEON_CRTC2_DISP_DIS, + ~(RADEON_CRTC2_DISP_DIS)); + } +} + +/* Unblank screen */ +void RADEONUnblank(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + if (!info->IsSecondary) { + switch (info->DisplayType) { + case MT_LCD: + case MT_CRT: + case MT_DFP: + OUTREGP(RADEON_CRTC_EXT_CNTL, + RADEON_CRTC_CRT_ON, + ~(RADEON_CRTC_DISPLAY_DIS)); + break; + + case MT_NONE: + default: + break; + } + if (info->MergedFB) + OUTREGP(RADEON_CRTC2_GEN_CNTL, + 0, + ~(RADEON_CRTC2_DISP_DIS)); + } else { + switch (info->DisplayType) { + case MT_LCD: + case MT_DFP: + case MT_CRT: + OUTREGP(RADEON_CRTC2_GEN_CNTL, + 0, + ~(RADEON_CRTC2_DISP_DIS)); + break; + + case MT_NONE: + default: + break; + } + } +} + +/* Sets VESA Display Power Management Signaling (DPMS) Mode */ +void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, + int PowerManagementMode, + int flags) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + if (!pScrn->vtSema) return; + + RADEONTRACE(("RADEONDisplayPowerManagementSet(%d,0x%x)\n", PowerManagementMode, flags)); + +#ifdef XF86DRI + if (info->CPStarted) DRILock(pScrn->pScreen, 0); +#endif + + if (info->accelOn) + RADEON_SYNC(info, pScrn); + + if (info->FBDev) { + fbdevHWDPMSSet(pScrn, PowerManagementMode, flags); + } else { + int mask1 = (RADEON_CRTC_DISPLAY_DIS | + RADEON_CRTC_HSYNC_DIS | + RADEON_CRTC_VSYNC_DIS); + int mask2 = (RADEON_CRTC2_DISP_DIS | + RADEON_CRTC2_VSYNC_DIS | + RADEON_CRTC2_HSYNC_DIS); + + switch (PowerManagementMode) { + case DPMSModeOn: + /* Screen: On; HSync: On, VSync: On */ + if (info->IsSecondary) + OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask2); + else { + if (info->MergedFB) + OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask2); + OUTREGP(RADEON_CRTC_EXT_CNTL, 0, ~mask1); + } + break; + + case DPMSModeStandby: + /* Screen: Off; HSync: Off, VSync: On */ + if (info->IsSecondary) + OUTREGP(RADEON_CRTC2_GEN_CNTL, + (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), + ~mask2); + else { + if (info->MergedFB) + OUTREGP(RADEON_CRTC2_GEN_CNTL, + (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), + ~mask2); + OUTREGP(RADEON_CRTC_EXT_CNTL, + (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS), + ~mask1); + } + break; + + case DPMSModeSuspend: + /* Screen: Off; HSync: On, VSync: Off */ + if (info->IsSecondary) + OUTREGP(RADEON_CRTC2_GEN_CNTL, + (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), + ~mask2); + else { + if (info->MergedFB) + OUTREGP(RADEON_CRTC2_GEN_CNTL, + (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), + ~mask2); + OUTREGP(RADEON_CRTC_EXT_CNTL, + (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS), + ~mask1); + } + break; + + case DPMSModeOff: + /* Screen: Off; HSync: Off, VSync: Off */ + if (info->IsSecondary) + OUTREGP(RADEON_CRTC2_GEN_CNTL, mask2, ~mask2); + else { + if (info->MergedFB) + OUTREGP(RADEON_CRTC2_GEN_CNTL, mask2, ~mask2); + OUTREGP(RADEON_CRTC_EXT_CNTL, mask1, ~mask1); + } + break; + } + + if (PowerManagementMode == DPMSModeOn) { + if (info->IsSecondary) { + if (info->DisplayType == MT_DFP) { + OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); + OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_ON, ~RADEON_FP2_ON); + if (info->ChipFamily >= CHIP_FAMILY_R200) { + OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_DVO_EN, ~RADEON_FP2_DVO_EN); + } + } else if (info->DisplayType == MT_CRT) { + RADEONDacPowerSet(pScrn, TRUE, !pRADEONEnt->ReversedDAC); + } + } else { + if ((info->MergedFB) && (info->MergeType == MT_DFP)) { + OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); + OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_ON, ~RADEON_FP2_ON); + if (info->ChipFamily >= CHIP_FAMILY_R200) { + OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_DVO_EN, ~RADEON_FP2_DVO_EN); + } + } + if (info->DisplayType == MT_DFP) { + OUTREGP (RADEON_FP_GEN_CNTL, (RADEON_FP_FPON | RADEON_FP_TMDS_EN), + ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN)); + } else if (info->DisplayType == MT_LCD) { + + OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_BLON, ~RADEON_LVDS_BLON); + usleep (info->PanelPwrDly * 1000); + OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_ON, ~RADEON_LVDS_ON); + } else if (info->DisplayType == MT_CRT) { + if ((pRADEONEnt->HasSecondary) || info->MergedFB) { + RADEONDacPowerSet(pScrn, TRUE, pRADEONEnt->ReversedDAC); + } else { + RADEONDacPowerSet(pScrn, TRUE, TRUE); + if (info->HasCRTC2) + RADEONDacPowerSet(pScrn, TRUE, FALSE); + } + } + } + } else if ((PowerManagementMode == DPMSModeOff) || + (PowerManagementMode == DPMSModeSuspend) || + (PowerManagementMode == DPMSModeStandby)) { + if (info->IsSecondary) { + if (info->DisplayType == MT_DFP) { + OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); + OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_ON); + if (info->ChipFamily >= CHIP_FAMILY_R200) { + OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_DVO_EN); + } + } else if (info->DisplayType == MT_CRT) { + RADEONDacPowerSet(pScrn, FALSE, !pRADEONEnt->ReversedDAC); + } + } else { + if ((info->MergedFB) && (info->MergeType == MT_DFP)) { + OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); + OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_ON); + if (info->ChipFamily >= CHIP_FAMILY_R200) { + OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_DVO_EN); + } + } + if (info->DisplayType == MT_DFP) { + OUTREGP (RADEON_FP_GEN_CNTL, 0, ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN)); + } else if (info->DisplayType == MT_LCD) { + unsigned long tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + + if (info->IsMobility || info->IsIGP) { + /* Asic bug, when turning off LVDS_ON, we have to make sure + RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off + */ + OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); + } + + OUTREGP (RADEON_LVDS_GEN_CNTL, 0, + ~(RADEON_LVDS_BLON | RADEON_LVDS_ON)); + + if (info->IsMobility || info->IsIGP) { + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl); + } + } else if (info->DisplayType == MT_CRT) { + if ((pRADEONEnt->HasSecondary) || info->MergedFB) { + RADEONDacPowerSet(pScrn, FALSE, pRADEONEnt->ReversedDAC); + } else { + /* single CRT, turning both DACs off, we don't really know + * which DAC is actually connected. + */ + RADEONDacPowerSet(pScrn, FALSE, TRUE); + if (info->HasCRTC2) /* don't apply this to old radeon (singel CRTC) card */ + RADEONDacPowerSet(pScrn, FALSE, FALSE); + } + } + } + } + } + +#ifdef XF86DRI + if (info->CPStarted) DRIUnlock(pScrn->pScreen); +#endif +} diff --git a/src/radeon_driver.c b/src/radeon_driver.c index 4b79f28..0a6bbd9 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -112,12 +112,7 @@ #include "atipciids.h" #include "radeon_chipset.h" -#ifndef MAX -#define MAX(a,b) ((a)>(b)?(a):(b)) -#endif -#ifndef MIN -#define MIN(a,b) ((a)>(b)?(b):(a)) -#endif + /* Forward definitions for driver functions */ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen); @@ -125,10 +120,6 @@ static Bool RADEONSaveScreen(ScreenPtr pScreen, int mode); static void RADEONSave(ScrnInfoPtr pScrn); static void RADEONRestore(ScrnInfoPtr pScrn); static Bool RADEONModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); -static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, - int PowerManagementMode, - int flags); -static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn); static void RADEONGetMergedFBOptions(ScrnInfoPtr pScrn); static int RADEONValidateMergeModes(ScrnInfoPtr pScrn); @@ -457,27 +448,6 @@ static struct {720, 400, 70}, }; -static const RADEONTMDSPll default_tmds_pll[CHIP_FAMILY_LAST][4] = -{ - {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_UNKNOW*/ - {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_LEGACY*/ - {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RADEON*/ - {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV100*/ - {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS100*/ - {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV200*/ - {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS200*/ - {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R200*/ - {{15500, 0x81b}, {0xffffffff, 0x83f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV250*/ - {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS300*/ - {{13000, 0x400f4}, {15000, 0x400f7}, {0xffffffff, 0x40111}, {0, 0}}, /*CHIP_FAMILY_RV280*/ - {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R300*/ - {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R350*/ - {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV350*/ - {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV380*/ - {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R420*/ - {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV410*/ /* FIXME: just values from r420 used... */ - {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS400*/ /* FIXME: just values from rv380 used... */ -}; #ifdef XFree86LOADER static int getRADEONEntityIndex(void) @@ -862,77 +832,6 @@ void RADEONWaitForVerticalSync2(ScrnInfoPtr pScrn) } } -/* Blank screen */ -static void RADEONBlank(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - - if (!info->IsSecondary) { - switch(info->DisplayType) { - case MT_LCD: - case MT_CRT: - case MT_DFP: - OUTREGP(RADEON_CRTC_EXT_CNTL, - RADEON_CRTC_DISPLAY_DIS, - ~(RADEON_CRTC_DISPLAY_DIS)); - break; - - case MT_NONE: - default: - break; - } - if (info->MergedFB) - OUTREGP(RADEON_CRTC2_GEN_CNTL, - RADEON_CRTC2_DISP_DIS, - ~(RADEON_CRTC2_DISP_DIS)); - } else { - OUTREGP(RADEON_CRTC2_GEN_CNTL, - RADEON_CRTC2_DISP_DIS, - ~(RADEON_CRTC2_DISP_DIS)); - } -} - -/* Unblank screen */ -static void RADEONUnblank(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - - if (!info->IsSecondary) { - switch (info->DisplayType) { - case MT_LCD: - case MT_CRT: - case MT_DFP: - OUTREGP(RADEON_CRTC_EXT_CNTL, - RADEON_CRTC_CRT_ON, - ~(RADEON_CRTC_DISPLAY_DIS)); - break; - - case MT_NONE: - default: - break; - } - if (info->MergedFB) - OUTREGP(RADEON_CRTC2_GEN_CNTL, - 0, - ~(RADEON_CRTC2_DISP_DIS)); - } else { - switch (info->DisplayType) { - case MT_LCD: - case MT_DFP: - case MT_CRT: - OUTREGP(RADEON_CRTC2_GEN_CNTL, - 0, - ~(RADEON_CRTC2_DISP_DIS)); - break; - - case MT_NONE: - default: - break; - } - } -} /* Compute log base 2 of val */ int RADEONMinBits(int val) @@ -950,343 +849,7 @@ static int RADEONDiv(int n, int d) return (n + (d / 2)) / d; } -static RADEONMonitorType RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, RADEONDDCType DDCType, RADEONConnector* port) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - unsigned long DDCReg; - RADEONMonitorType MonType = MT_NONE; - xf86MonPtr* MonInfo = &port->MonInfo; - int i, j; - - DDCReg = info->DDCReg; - switch(DDCType) - { - case DDC_MONID: - info->DDCReg = RADEON_GPIO_MONID; - break; - case DDC_DVI: - info->DDCReg = RADEON_GPIO_DVI_DDC; - break; - case DDC_VGA: - info->DDCReg = RADEON_GPIO_VGA_DDC; - break; - case DDC_CRT2: - info->DDCReg = RADEON_GPIO_CRT2_DDC; - break; - default: - info->DDCReg = DDCReg; - return MT_NONE; - } - - /* Read and output monitor info using DDC2 over I2C bus */ - if (info->pI2CBus && info->ddc2) { - OUTREG(info->DDCReg, INREG(info->DDCReg) & - (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1)); - - /* For some old monitors (like Compaq Presario FP500), we need - * following process to initialize/stop DDC - */ - OUTREG(info->DDCReg, INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1)); - for (j = 0; j < 3; j++) { - OUTREG(info->DDCReg, - INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0)); - usleep(13000); - - OUTREG(info->DDCReg, - INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1)); - for (i = 0; i < 10; i++) { - usleep(15000); - if (INREG(info->DDCReg) & RADEON_GPIO_Y_1) - break; - } - if (i == 10) continue; - - usleep(15000); - - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0); - usleep(15000); - - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1); - usleep(15000); - OUTREG(info->DDCReg, - INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0)); - usleep(15000); - *MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, info->pI2CBus); - - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1); - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0); - usleep(15000); - OUTREG(info->DDCReg, - INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1)); - for (i = 0; i < 5; i++) { - usleep(15000); - if (INREG(info->DDCReg) & RADEON_GPIO_Y_1) - break; - } - usleep(15000); - OUTREG(info->DDCReg, - INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0)); - usleep(15000); - - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1); - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0); - usleep(15000); - if(*MonInfo) break; - } - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DDC2/I2C is not properly initialized\n"); - MonType = MT_NONE; - } - - OUTREG(info->DDCReg, INREG(info->DDCReg) & - ~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1)); - - if (*MonInfo) { - if ((*MonInfo)->rawData[0x14] & 0x80) { - /* Note some laptops have a DVI output that uses internal TMDS, - * when its DVI is enabled by hotkey, LVDS panel is not used. - * In this case, the laptop is configured as DVI+VGA as a normal - * desktop card. - * Also for laptop, when X starts with lid closed (no DVI connection) - * both LDVS and TMDS are disable, we still need to treat it as a LVDS panel. - */ - if (port->TMDSType == TMDS_EXT) MonType = MT_DFP; - else { - if ((INREG(RADEON_FP_GEN_CNTL) & (1<<7)) || !info->IsMobility) - MonType = MT_DFP; - else - MonType = MT_LCD; - } - } else MonType = MT_CRT; - } else MonType = MT_NONE; - - info->DDCReg = DDCReg; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "DDC Type: %d, Detected Type: %d\n", DDCType, MonType); - - return MonType; -} - -static RADEONMonitorType -RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - int bConnected = 0; - - /* the monitor either wasn't connected or it is a non-DDC CRT. - * try to probe it - */ - if(IsCrtDac) { - unsigned long ulOrigVCLK_ECP_CNTL; - unsigned long ulOrigDAC_CNTL; - unsigned long ulOrigDAC_EXT_CNTL; - unsigned long ulOrigCRTC_EXT_CNTL; - unsigned long ulData; - unsigned long ulMask; - - ulOrigVCLK_ECP_CNTL = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); - - ulData = ulOrigVCLK_ECP_CNTL; - ulData &= ~(RADEON_PIXCLK_ALWAYS_ONb - | RADEON_PIXCLK_DAC_ALWAYS_ONb); - ulMask = ~(RADEON_PIXCLK_ALWAYS_ONb - |RADEON_PIXCLK_DAC_ALWAYS_ONb); - OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask); - - ulOrigCRTC_EXT_CNTL = INREG(RADEON_CRTC_EXT_CNTL); - ulData = ulOrigCRTC_EXT_CNTL; - ulData |= RADEON_CRTC_CRT_ON; - OUTREG(RADEON_CRTC_EXT_CNTL, ulData); - - ulOrigDAC_EXT_CNTL = INREG(RADEON_DAC_EXT_CNTL); - ulData = ulOrigDAC_EXT_CNTL; - ulData &= ~RADEON_DAC_FORCE_DATA_MASK; - ulData |= (RADEON_DAC_FORCE_BLANK_OFF_EN - |RADEON_DAC_FORCE_DATA_EN - |RADEON_DAC_FORCE_DATA_SEL_MASK); - if ((info->ChipFamily == CHIP_FAMILY_RV250) || - (info->ChipFamily == CHIP_FAMILY_RV280)) - ulData |= (0x01b6 << RADEON_DAC_FORCE_DATA_SHIFT); - else - ulData |= (0x01ac << RADEON_DAC_FORCE_DATA_SHIFT); - - OUTREG(RADEON_DAC_EXT_CNTL, ulData); - - ulOrigDAC_CNTL = INREG(RADEON_DAC_CNTL); - ulData = ulOrigDAC_CNTL; - ulData |= RADEON_DAC_CMP_EN; - ulData &= ~(RADEON_DAC_RANGE_CNTL_MASK - | RADEON_DAC_PDWN); - ulData |= 0x2; - OUTREG(RADEON_DAC_CNTL, ulData); - - usleep(10000); - - ulData = INREG(RADEON_DAC_CNTL); - bConnected = (RADEON_DAC_CMP_OUTPUT & ulData)?1:0; - - ulData = ulOrigVCLK_ECP_CNTL; - ulMask = 0xFFFFFFFFL; - OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask); - - OUTREG(RADEON_DAC_CNTL, ulOrigDAC_CNTL ); - OUTREG(RADEON_DAC_EXT_CNTL, ulOrigDAC_EXT_CNTL ); - OUTREG(RADEON_CRTC_EXT_CNTL, ulOrigCRTC_EXT_CNTL); - } else { /* TV DAC */ - - /* This doesn't seem to work reliably (maybe worse on some OEM cards), - for now we always return false. If one wants to connected a - non-DDC monitor on the DVI port when CRT port is also connected, - he will need to explicitly tell the driver in the config file - with Option MonitorLayout. - */ - bConnected = FALSE; - -#if 0 - if (info->ChipFamily == CHIP_FAMILY_R200) { - unsigned long ulOrigGPIO_MONID; - unsigned long ulOrigFP2_GEN_CNTL; - unsigned long ulOrigDISP_OUTPUT_CNTL; - unsigned long ulOrigCRTC2_GEN_CNTL; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_A; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_B; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_C; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_D; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_E; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_F; - unsigned long ulOrigCRTC2_H_TOTAL_DISP; - unsigned long ulOrigCRTC2_V_TOTAL_DISP; - unsigned long ulOrigCRTC2_H_SYNC_STRT_WID; - unsigned long ulOrigCRTC2_V_SYNC_STRT_WID; - unsigned long ulData, i; - - ulOrigGPIO_MONID = INREG(RADEON_GPIO_MONID); - ulOrigFP2_GEN_CNTL = INREG(RADEON_FP2_GEN_CNTL); - ulOrigDISP_OUTPUT_CNTL = INREG(RADEON_DISP_OUTPUT_CNTL); - ulOrigCRTC2_GEN_CNTL = INREG(RADEON_CRTC2_GEN_CNTL); - ulOrigDISP_LIN_TRANS_GRPH_A = INREG(RADEON_DISP_LIN_TRANS_GRPH_A); - ulOrigDISP_LIN_TRANS_GRPH_B = INREG(RADEON_DISP_LIN_TRANS_GRPH_B); - ulOrigDISP_LIN_TRANS_GRPH_C = INREG(RADEON_DISP_LIN_TRANS_GRPH_C); - ulOrigDISP_LIN_TRANS_GRPH_D = INREG(RADEON_DISP_LIN_TRANS_GRPH_D); - ulOrigDISP_LIN_TRANS_GRPH_E = INREG(RADEON_DISP_LIN_TRANS_GRPH_E); - ulOrigDISP_LIN_TRANS_GRPH_F = INREG(RADEON_DISP_LIN_TRANS_GRPH_F); - - ulOrigCRTC2_H_TOTAL_DISP = INREG(RADEON_CRTC2_H_TOTAL_DISP); - ulOrigCRTC2_V_TOTAL_DISP = INREG(RADEON_CRTC2_V_TOTAL_DISP); - ulOrigCRTC2_H_SYNC_STRT_WID = INREG(RADEON_CRTC2_H_SYNC_STRT_WID); - ulOrigCRTC2_V_SYNC_STRT_WID = INREG(RADEON_CRTC2_V_SYNC_STRT_WID); - - ulData = INREG(RADEON_GPIO_MONID); - ulData &= ~RADEON_GPIO_A_0; - OUTREG(RADEON_GPIO_MONID, ulData); - - OUTREG(RADEON_FP2_GEN_CNTL, 0x0a000c0c); - - OUTREG(RADEON_DISP_OUTPUT_CNTL, 0x00000012); - - OUTREG(RADEON_CRTC2_GEN_CNTL, 0x06000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); - OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); - OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); - OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); - OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); - - for (i = 0; i < 200; i++) { - ulData = INREG(RADEON_GPIO_MONID); - bConnected = (ulData & RADEON_GPIO_Y_0)?1:0; - if (!bConnected) break; - - usleep(1000); - } - - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, ulOrigDISP_LIN_TRANS_GRPH_A); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, ulOrigDISP_LIN_TRANS_GRPH_B); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, ulOrigDISP_LIN_TRANS_GRPH_C); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, ulOrigDISP_LIN_TRANS_GRPH_D); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, ulOrigDISP_LIN_TRANS_GRPH_E); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, ulOrigDISP_LIN_TRANS_GRPH_F); - OUTREG(RADEON_CRTC2_H_TOTAL_DISP, ulOrigCRTC2_H_TOTAL_DISP); - OUTREG(RADEON_CRTC2_V_TOTAL_DISP, ulOrigCRTC2_V_TOTAL_DISP); - OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, ulOrigCRTC2_H_SYNC_STRT_WID); - OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, ulOrigCRTC2_V_SYNC_STRT_WID); - OUTREG(RADEON_CRTC2_GEN_CNTL, ulOrigCRTC2_GEN_CNTL); - OUTREG(RADEON_DISP_OUTPUT_CNTL, ulOrigDISP_OUTPUT_CNTL); - OUTREG(RADEON_FP2_GEN_CNTL, ulOrigFP2_GEN_CNTL); - OUTREG(RADEON_GPIO_MONID, ulOrigGPIO_MONID); - } else { - unsigned long ulOrigPIXCLKSDATA; - unsigned long ulOrigTV_MASTER_CNTL; - unsigned long ulOrigTV_DAC_CNTL; - unsigned long ulOrigTV_PRE_DAC_MUX_CNTL; - unsigned long ulOrigDAC_CNTL2; - unsigned long ulData; - unsigned long ulMask; - - ulOrigPIXCLKSDATA = INPLL(pScrn, RADEON_PIXCLKS_CNTL); - - ulData = ulOrigPIXCLKSDATA; - ulData &= ~(RADEON_PIX2CLK_ALWAYS_ONb - | RADEON_PIX2CLK_DAC_ALWAYS_ONb); - ulMask = ~(RADEON_PIX2CLK_ALWAYS_ONb - | RADEON_PIX2CLK_DAC_ALWAYS_ONb); - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); - - ulOrigTV_MASTER_CNTL = INREG(RADEON_TV_MASTER_CNTL); - ulData = ulOrigTV_MASTER_CNTL; - ulData &= ~RADEON_TVCLK_ALWAYS_ONb; - OUTREG(RADEON_TV_MASTER_CNTL, ulData); - - ulOrigDAC_CNTL2 = INREG(RADEON_DAC_CNTL2); - ulData = ulOrigDAC_CNTL2; - ulData &= ~RADEON_DAC2_DAC2_CLK_SEL; - OUTREG(RADEON_DAC_CNTL2, ulData); - - ulOrigTV_DAC_CNTL = INREG(RADEON_TV_DAC_CNTL); - - ulData = 0x00880213; - OUTREG(RADEON_TV_DAC_CNTL, ulData); - - ulOrigTV_PRE_DAC_MUX_CNTL = INREG(RADEON_TV_PRE_DAC_MUX_CNTL); - - ulData = (RADEON_Y_RED_EN - | RADEON_C_GRN_EN - | RADEON_CMP_BLU_EN - | RADEON_RED_MX_FORCE_DAC_DATA - | RADEON_GRN_MX_FORCE_DAC_DATA - | RADEON_BLU_MX_FORCE_DAC_DATA); - if (IS_R300_VARIANT) - ulData |= 0x180 << RADEON_TV_FORCE_DAC_DATA_SHIFT; - else - ulData |= 0x1f5 << RADEON_TV_FORCE_DAC_DATA_SHIFT; - OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulData); - - usleep(10000); - - ulData = INREG(RADEON_TV_DAC_CNTL); - bConnected = (ulData & RADEON_TV_DAC_CMPOUT)?1:0; - ulData = ulOrigPIXCLKSDATA; - ulMask = 0xFFFFFFFFL; - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); - - OUTREG(RADEON_TV_MASTER_CNTL, ulOrigTV_MASTER_CNTL); - OUTREG(RADEON_DAC_CNTL2, ulOrigDAC_CNTL2); - OUTREG(RADEON_TV_DAC_CNTL, ulOrigTV_DAC_CNTL); - OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulOrigTV_PRE_DAC_MUX_CNTL); - } -#endif - } - - return(bConnected ? MT_CRT : MT_NONE); -} static Bool RADEONProbePLLParameters(ScrnInfoPtr pScrn) { @@ -1490,155 +1053,6 @@ static Bool RADEONProbePLLParameters(ScrnInfoPtr pScrn) return TRUE; } -static void RADEONGetPanelInfoFromReg (ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - CARD32 fp_vert_stretch = INREG(RADEON_FP_VERT_STRETCH); - CARD32 fp_horz_stretch = INREG(RADEON_FP_HORZ_STRETCH); - - info->PanelPwrDly = 200; - if (fp_vert_stretch & RADEON_VERT_STRETCH_ENABLE) { - info->PanelYRes = (fp_vert_stretch>>12) + 1; - } else { - info->PanelYRes = (INREG(RADEON_CRTC_V_TOTAL_DISP)>>16) + 1; - } - if (fp_horz_stretch & RADEON_HORZ_STRETCH_ENABLE) { - info->PanelXRes = ((fp_horz_stretch>>16) + 1) * 8; - } else { - info->PanelXRes = ((INREG(RADEON_CRTC_H_TOTAL_DISP)>>16) + 1) * 8; - } - - if ((info->PanelXRes < 640) || (info->PanelYRes < 480)) { - info->PanelXRes = 640; - info->PanelYRes = 480; - } - - if (xf86ReturnOptValBool(info->Options, OPTION_LVDS_PROBE_PLL, TRUE)) { - CARD32 ppll_div_sel, ppll_val; - - ppll_div_sel = INREG8(RADEON_CLOCK_CNTL_INDEX + 1) & 0x3; - RADEONPllErrataAfterIndex(info); - ppll_val = INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel); - if ((ppll_val & 0x000707ff) == 0x1bb) - goto noprobe; - info->FeedbackDivider = ppll_val & 0x7ff; - info->PostDivider = (ppll_val >> 16) & 0x7; - info->RefDivider = info->pll.reference_div; - info->UseBiosDividers = TRUE; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Existing panel PLL dividers will be used.\n"); - } - noprobe: - - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Panel size %dx%d is derived, this may not be correct.\n" - "If not, use PanelSize option to overwrite this setting\n", - info->PanelXRes, info->PanelYRes); -} - -static Bool RADEONGetLVDSInfo (ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - - if (!RADEONGetLVDSInfoFromBIOS(pScrn)) - RADEONGetPanelInfoFromReg(pScrn); - - /* The panel size we collected from BIOS may not be the - * maximum size supported by the panel. If not, we update - * it now. These will be used if no matching mode can be - * found from EDID data. - */ - RADEONUpdatePanelSize(pScrn); - - /* No timing information for the native mode, - * use whatever specified in the Modeline. - * If no Modeline specified, we'll just pick - * the VESA mode at 60Hz refresh rate which - * is likely to be the best for a flat panel. - */ - if (info->DotClock == 0) { - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - DisplayModePtr tmp_mode = NULL; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "No valid timing info from BIOS.\n"); - tmp_mode = pScrn->monitor->Modes; - while(tmp_mode) { - if ((tmp_mode->HDisplay == info->PanelXRes) && - (tmp_mode->VDisplay == info->PanelYRes)) { - - float refresh = - (float)tmp_mode->Clock * 1000.0 / tmp_mode->HTotal / tmp_mode->VTotal; - if ((abs(60.0 - refresh) < 1.0) || - (tmp_mode->type == 0)) { - info->HBlank = tmp_mode->HTotal - tmp_mode->HDisplay; - info->HOverPlus = tmp_mode->HSyncStart - tmp_mode->HDisplay; - info->HSyncWidth = tmp_mode->HSyncEnd - tmp_mode->HSyncStart; - info->VBlank = tmp_mode->VTotal - tmp_mode->VDisplay; - info->VOverPlus = tmp_mode->VSyncStart - tmp_mode->VDisplay; - info->VSyncWidth = tmp_mode->VSyncEnd - tmp_mode->VSyncStart; - info->DotClock = tmp_mode->Clock; - info->Flags = 0; - break; - } - } - tmp_mode = tmp_mode->next; - } - if ((info->DotClock == 0) && !pRADEONEnt->PortInfo[0].MonInfo) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Panel size is not correctly detected.\n" - "Please try to use PanelSize option for correct settings.\n"); - return FALSE; - } - } - - return TRUE; -} - -static void RADEONGetTMDSInfo(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - int i; - - for (i=0; i<4; i++) { - info->tmds_pll[i].value = 0; - info->tmds_pll[i].freq = 0; - } - - if (RADEONGetTMDSInfoFromBIOS(pScrn)) return; - - for (i=0; i<4; i++) { - info->tmds_pll[i].value = default_tmds_pll[info->ChipFamily][i].value; - info->tmds_pll[i].freq = default_tmds_pll[info->ChipFamily][i].freq; - } -} - -static void RADEONGetPanelInfo (ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - char* s; - - if((s = xf86GetOptValString(info->Options, OPTION_PANEL_SIZE))) { - info->PanelPwrDly = 200; - if (sscanf (s, "%dx%d", &info->PanelXRes, &info->PanelYRes) != 2) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Invalid PanelSize option: %s\n", s); - RADEONGetPanelInfoFromReg(pScrn); - } - } else { - - if(info->DisplayType == MT_LCD) { - RADEONGetLVDSInfo(pScrn); - } else if ((info->DisplayType == MT_DFP) || (info->MergeType == MT_DFP)) { - RADEONGetTMDSInfo(pScrn); - if (!pScrn->monitor->DDC) - RADEONGetHardCodedEDIDFromBIOS(pScrn); - else if (!info->IsSecondary) - RADEONUpdatePanelSize(pScrn); - } - } -} - static void RADEONGetClockInfo(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR (pScrn); @@ -1727,421 +1141,6 @@ static void RADEONGetClockInfo(ScrnInfoPtr pScrn) } } -static BOOL RADEONQueryConnectedMonitors(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - const char *s; - Bool ignore_edid = FALSE; - int i = 0, second = 0, max_mt; - - const char *MonTypeName[7] = - { - "AUTO", - "NONE", - "CRT", - "LVDS", - "TMDS", - "CTV", - "STV" - }; - - const RADEONMonitorType MonTypeID[7] = - { - MT_UNKNOWN, /* this is just a dummy value for AUTO DETECTION */ - MT_NONE, /* NONE -> NONE */ - MT_CRT, /* CRT -> CRT */ - MT_LCD, /* Laptop LCDs are driven via LVDS port */ - MT_DFP, /* DFPs are driven via TMDS */ - MT_CTV, /* CTV -> CTV */ - MT_STV, /* STV -> STV */ - }; - - const char *TMDSTypeName[3] = - { - "NONE", - "Internal", - "External" - }; - - const char *DDCTypeName[5] = - { - "NONE", - "MONID", - "DVI_DDC", - "VGA_DDC", - "CRT2_DDC" - }; - - const char *DACTypeName[3] = - { - "Unknown", - "Primary", - "TVDAC/ExtDAC", - }; - - const char *ConnectorTypeName[8] = - { - "None", - "Proprietary", - "VGA", - "DVI-I", - "DVI-D", - "CTV", - "STV", - "Unsupported" - }; - - const char *ConnectorTypeNameATOM[10] = - { - "None", - "VGA", - "DVI-I", - "DVI-D", - "DVI-A", - "STV", - "CTV", - "LVDS", - "Digital", - "Unsupported" - }; - - max_mt = 5; - - if(info->IsSecondary) { - info->DisplayType = (RADEONMonitorType)pRADEONEnt->MonType2; - if(info->DisplayType == MT_NONE) return FALSE; - return TRUE; - } - - - /* We first get the information about all connectors from BIOS. - * This is how the card is phyiscally wired up. - * The information should be correct even on a OEM card. - * If not, we may have problem -- need to use MonitorLayout option. - */ - for (i = 0; i < 2; i++) { - pRADEONEnt->PortInfo[i].MonType = MT_UNKNOWN; - pRADEONEnt->PortInfo[i].MonInfo = NULL; - pRADEONEnt->PortInfo[i].DDCType = DDC_NONE_DETECTED; - pRADEONEnt->PortInfo[i].DACType = DAC_UNKNOWN; - pRADEONEnt->PortInfo[i].TMDSType = TMDS_UNKNOWN; - pRADEONEnt->PortInfo[i].ConnectorType = CONNECTOR_NONE; - } - - if (!RADEONGetConnectorInfoFromBIOS(pScrn)) { - /* Below is the most common setting, but may not be true */ - pRADEONEnt->PortInfo[0].MonType = MT_UNKNOWN; - pRADEONEnt->PortInfo[0].MonInfo = NULL; - pRADEONEnt->PortInfo[0].DDCType = DDC_DVI; - pRADEONEnt->PortInfo[0].DACType = DAC_TVDAC; - pRADEONEnt->PortInfo[0].TMDSType = TMDS_INT; - pRADEONEnt->PortInfo[0].ConnectorType = CONNECTOR_DVI_D; - - pRADEONEnt->PortInfo[1].MonType = MT_UNKNOWN; - pRADEONEnt->PortInfo[1].MonInfo = NULL; - pRADEONEnt->PortInfo[1].DDCType = DDC_VGA; - pRADEONEnt->PortInfo[1].DACType = DAC_PRIMARY; - pRADEONEnt->PortInfo[1].TMDSType = TMDS_EXT; - pRADEONEnt->PortInfo[1].ConnectorType = CONNECTOR_CRT; - - /* Some cards have the DDC lines swapped and we have no way to - * detect it yet (Mac cards) - */ - if (xf86ReturnOptValBool(info->Options, OPTION_REVERSE_DDC, FALSE)) { - pRADEONEnt->PortInfo[0].DDCType = DDC_VGA; - pRADEONEnt->PortInfo[1].DDCType = DDC_DVI; - } - } - - /* always make TMDS_INT port first*/ - if (pRADEONEnt->PortInfo[1].TMDSType == TMDS_INT) { - RADEONConnector connector; - connector = pRADEONEnt->PortInfo[0]; - pRADEONEnt->PortInfo[0] = pRADEONEnt->PortInfo[1]; - pRADEONEnt->PortInfo[1] = connector; - } else if ((pRADEONEnt->PortInfo[0].TMDSType != TMDS_INT && - pRADEONEnt->PortInfo[1].TMDSType != TMDS_INT)) { - /* no TMDS_INT port, make primary DAC port first */ - /* On my Inspiron 8600 both internal and external ports are - marked DAC_PRIMARY in BIOS. So be extra careful - only - swap when the first port is not DAC_PRIMARY */ - if ( (pRADEONEnt->PortInfo[1].DACType == DAC_PRIMARY) && - (pRADEONEnt->PortInfo[0].DACType != DAC_PRIMARY)) { - RADEONConnector connector; - connector = pRADEONEnt->PortInfo[0]; - pRADEONEnt->PortInfo[0] = pRADEONEnt->PortInfo[1]; - pRADEONEnt->PortInfo[1] = connector; - } - } - - if (info->HasSingleDAC) { - /* For RS300/RS350/RS400 chips, there is no primary DAC. Force VGA port to use TVDAC*/ - if (pRADEONEnt->PortInfo[0].ConnectorType == CONNECTOR_CRT) { - pRADEONEnt->PortInfo[0].DACType = DAC_TVDAC; - pRADEONEnt->PortInfo[1].DACType = DAC_PRIMARY; - } else { - pRADEONEnt->PortInfo[1].DACType = DAC_TVDAC; - pRADEONEnt->PortInfo[0].DACType = DAC_PRIMARY; - } - } else if (!info->HasCRTC2) { - pRADEONEnt->PortInfo[0].DACType = DAC_PRIMARY; - } - - /* IgnoreEDID option is different from the NoDDCxx options used by DDC module - * When IgnoreEDID is used, monitor detection will still use DDC - * detection, but all EDID data will not be used in mode validation. - * You can use this option when you have a DDC monitor but want specify your own - * monitor timing parameters by using HSync, VRefresh and Modeline, - */ - if (xf86GetOptValBool(info->Options, OPTION_IGNORE_EDID, &ignore_edid)) { - if (ignore_edid) - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "IgnoreEDID is specified, EDID data will be ignored\n"); - } - - /* - * MonitorLayout option takes a string for two monitors connected in following format: - * Option "MonitorLayout" "primary-port-display, secondary-port-display" - * primary and secondary port displays can have one of following: - * NONE, CRT, LVDS, TMDS - * With this option, driver will bring up monitors as specified, - * not using auto-detection routines to probe monitors. - * - * This option can be used when the false monitor detection occurs. - * - * This option can also be used to disable one connected display. - * For example, if you have a laptop connected to an external CRT - * and you want to disable the internal LCD panel, you can specify - * Option "MonitorLayout" "NONE, CRT" - * - * This option can also used to disable Clone mode. One there is only - * one monitor is specified, clone mode will be turned off automatically - * even you have two monitors connected. - * - * Another usage of this option is you want to config the server - * to start up with a certain monitor arrangement even one monitor - * is not plugged in when server starts. - */ - if ((s = xf86GetOptValString(info->Options, OPTION_MONITOR_LAYOUT))) { - char s1[5], s2[5]; - i = 0; - /* When using user specified monitor types, we will not do DDC detection - * - */ - do { - switch(*s) { - case ',': - s1[i] = '\0'; - i = 0; - second = 1; - break; - case ' ': - case '\t': - case '\n': - case '\r': - break; - default: - if (second) - s2[i] = *s; - else - s1[i] = *s; - i++; - break; - } - if (i > 4) i = 4; - } while(*s++); - s2[i] = '\0'; - - for (i = 0; i < max_mt; i++) { - if (strcmp(s1, MonTypeName[i]) == 0) { - pRADEONEnt->PortInfo[0].MonType = MonTypeID[i]; - break; - } - } - for (i = 0; i < max_mt; i++) { - if (strcmp(s2, MonTypeName[i]) == 0) { - pRADEONEnt->PortInfo[1].MonType = MonTypeID[i]; - break; - } - } - - if (i == max_mt) - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Invalid Monitor type specified for 2nd port \n"); - - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "MonitorLayout Option: \n\tMonitor1--Type %s, Monitor2--Type %s\n\n", s1, s2); -#if 0 - if (pRADEONEnt->PortInfo[1].MonType == MT_CRT) { - pRADEONEnt->PortInfo[1].DACType = DAC_PRIMARY; - pRADEONEnt->PortInfo[1].TMDSType = TMDS_UNKNOWN; - pRADEONEnt->PortInfo[1].DDCType = DDC_VGA; - pRADEONEnt->PortInfo[1].ConnectorType = CONNECTOR_CRT; - pRADEONEnt->PortInfo[0].DACType = DAC_TVDAC; - pRADEONEnt->PortInfo[0].TMDSType = TMDS_UNKNOWN; - pRADEONEnt->PortInfo[0].DDCType = DDC_NONE_DETECTED; - pRADEONEnt->PortInfo[0].ConnectorType = pRADEONEnt->PortInfo[0].MonType+1; - pRADEONEnt->PortInfo[0].MonInfo = NULL; - } -#endif - - if (!ignore_edid) { - if ((pRADEONEnt->PortInfo[0].MonType > MT_NONE) && - (pRADEONEnt->PortInfo[0].MonType < MT_STV)) - RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[0].DDCType, - &pRADEONEnt->PortInfo[0]); - if ((pRADEONEnt->PortInfo[1].MonType > MT_NONE) && - (pRADEONEnt->PortInfo[1].MonType < MT_STV)) - RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[1].DDCType, - &pRADEONEnt->PortInfo[1]); - } - - } - - if(((!info->HasCRTC2) || info->IsDellServer)) { - if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN) { - if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_DVI, &pRADEONEnt->PortInfo[0]))); - else if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_VGA, &pRADEONEnt->PortInfo[0]))); - else if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->PortInfo[0]))); - else - pRADEONEnt->PortInfo[0].MonType = MT_CRT; - } - - if (!ignore_edid) { - if (pRADEONEnt->PortInfo[0].MonInfo) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor1 EDID data ---------------------------\n"); - xf86PrintEDID(pRADEONEnt->PortInfo[0].MonInfo ); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor1 EDID data --------------------\n"); - } - } - - pRADEONEnt->MonType1 = pRADEONEnt->PortInfo[0].MonType; - pRADEONEnt->MonInfo1 = pRADEONEnt->PortInfo[0].MonInfo; - pRADEONEnt->MonType2 = MT_NONE; - pRADEONEnt->MonInfo2 = NULL; - info->MergeType = MT_NONE; - info->DisplayType = pRADEONEnt->MonType1; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Primary:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", - MonTypeName[pRADEONEnt->PortInfo[0].MonType+1], - info->IsAtomBios ? - ConnectorTypeNameATOM[pRADEONEnt->PortInfo[0].ConnectorType]: - ConnectorTypeName[pRADEONEnt->PortInfo[0].ConnectorType], - DACTypeName[pRADEONEnt->PortInfo[0].DACType+1], - TMDSTypeName[pRADEONEnt->PortInfo[0].TMDSType+1], - DDCTypeName[pRADEONEnt->PortInfo[0].DDCType]); - - return TRUE; - } - - if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN || pRADEONEnt->PortInfo[1].MonType == MT_UNKNOWN) { - - /* Primary Head (DVI or Laptop Int. panel)*/ - /* A ddc capable display connected on DVI port */ - if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN) { - if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[0].DDCType, &pRADEONEnt->PortInfo[0]))); - else if (info->IsMobility && - (INREG(RADEON_BIOS_4_SCRATCH) & 4)) { - /* non-DDC laptop panel connected on primary */ - pRADEONEnt->PortInfo[0].MonType = MT_LCD; - } else { - /* CRT on DVI, TODO: not reliable, make it always return false for now*/ - pRADEONEnt->PortInfo[0].MonType = RADEONCrtIsPhysicallyConnected(pScrn, !(pRADEONEnt->PortInfo[0].DACType)); - } - } - - /* Secondary Head (mostly VGA, can be DVI on some OEM boards)*/ - if (pRADEONEnt->PortInfo[1].MonType == MT_UNKNOWN) { - if((pRADEONEnt->PortInfo[1].MonType = - RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[1].DDCType, &pRADEONEnt->PortInfo[1]))); - else if (info->IsMobility && - (INREG(RADEON_FP2_GEN_CNTL) & RADEON_FP2_ON)) { - /* non-DDC TMDS panel connected through DVO */ - pRADEONEnt->PortInfo[1].MonType = MT_DFP; - } else - pRADEONEnt->PortInfo[1].MonType = RADEONCrtIsPhysicallyConnected(pScrn, !(pRADEONEnt->PortInfo[1].DACType)); - } - } - - if(ignore_edid) { - pRADEONEnt->PortInfo[0].MonInfo = NULL; - pRADEONEnt->PortInfo[1].MonInfo = NULL; - } else { - if (pRADEONEnt->PortInfo[0].MonInfo) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on port 1 ----------------------\n"); - xf86PrintEDID(pRADEONEnt->PortInfo[0].MonInfo ); - } - - if (pRADEONEnt->PortInfo[1].MonInfo) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on port 2-----------------------\n"); - xf86PrintEDID(pRADEONEnt->PortInfo[1].MonInfo ); - } - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\n"); - - pRADEONEnt->MonType1 = pRADEONEnt->PortInfo[0].MonType; - pRADEONEnt->MonInfo1 = pRADEONEnt->PortInfo[0].MonInfo; - pRADEONEnt->MonType2 = pRADEONEnt->PortInfo[1].MonType; - pRADEONEnt->MonInfo2 = pRADEONEnt->PortInfo[1].MonInfo; - if (pRADEONEnt->PortInfo[0].MonType == MT_NONE) { - if (pRADEONEnt->PortInfo[1].MonType == MT_NONE) { - pRADEONEnt->MonType1 = MT_CRT; - pRADEONEnt->MonInfo1 = NULL; - } else { - RADEONConnector tmp; - pRADEONEnt->MonType1 = pRADEONEnt->PortInfo[1].MonType; - pRADEONEnt->MonInfo1 = pRADEONEnt->PortInfo[1].MonInfo; - tmp = pRADEONEnt->PortInfo[0]; - pRADEONEnt->PortInfo[0] = pRADEONEnt->PortInfo[1]; - pRADEONEnt->PortInfo[1] = tmp; - } - pRADEONEnt->MonType2 = MT_NONE; - pRADEONEnt->MonInfo2 = NULL; - } - - info->DisplayType = pRADEONEnt->MonType1; - pRADEONEnt->ReversedDAC = FALSE; - info->OverlayOnCRTC2 = FALSE; - info->MergeType = MT_NONE; - if (pRADEONEnt->MonType2 != MT_NONE) { - if(!pRADEONEnt->HasSecondary) { - info->MergeType = pRADEONEnt->MonType2; - } - - if (pRADEONEnt->PortInfo[1].DACType == DAC_TVDAC) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reversed DAC decteced\n"); - pRADEONEnt->ReversedDAC = TRUE; - } - } else { - pRADEONEnt->HasSecondary = FALSE; - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Primary:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", - MonTypeName[pRADEONEnt->PortInfo[0].MonType+1], - info->IsAtomBios ? - ConnectorTypeNameATOM[pRADEONEnt->PortInfo[0].ConnectorType]: - ConnectorTypeName[pRADEONEnt->PortInfo[0].ConnectorType], - DACTypeName[pRADEONEnt->PortInfo[0].DACType+1], - TMDSTypeName[pRADEONEnt->PortInfo[0].TMDSType+1], - DDCTypeName[pRADEONEnt->PortInfo[0].DDCType]); - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Secondary:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", - MonTypeName[pRADEONEnt->PortInfo[1].MonType+1], - info->IsAtomBios ? - ConnectorTypeNameATOM[pRADEONEnt->PortInfo[1].ConnectorType]: - ConnectorTypeName[pRADEONEnt->PortInfo[1].ConnectorType], - DACTypeName[pRADEONEnt->PortInfo[1].DACType+1], - TMDSTypeName[pRADEONEnt->PortInfo[1].TMDSType+1], - DDCTypeName[pRADEONEnt->PortInfo[1].DDCType]); - - return TRUE; -} /* This is called by RADEONPreInit to set up the default visual */ @@ -2966,52 +1965,6 @@ static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn) return TRUE; } -static void RADEONI2CGetBits(I2CBusPtr b, int *Clock, int *data) -{ - ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned long val; - unsigned char *RADEONMMIO = info->MMIO; - - /* Get the result */ - val = INREG(info->DDCReg); - - *Clock = (val & RADEON_GPIO_Y_1) != 0; - *data = (val & RADEON_GPIO_Y_0) != 0; -} - -static void RADEONI2CPutBits(I2CBusPtr b, int Clock, int data) -{ - ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned long val; - unsigned char *RADEONMMIO = info->MMIO; - - val = INREG(info->DDCReg) & (CARD32)~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1); - val |= (Clock ? 0:RADEON_GPIO_EN_1); - val |= (data ? 0:RADEON_GPIO_EN_0); - OUTREG(info->DDCReg, val); - - /* read back to improve reliability on some cards. */ - val = INREG(info->DDCReg); -} - -static Bool RADEONI2cInit(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - - info->pI2CBus = xf86CreateI2CBusRec(); - if (!info->pI2CBus) return FALSE; - - info->pI2CBus->BusName = "DDC"; - info->pI2CBus->scrnIndex = pScrn->scrnIndex; - info->pI2CBus->I2CPutBits = RADEONI2CPutBits; - info->pI2CBus->I2CGetBits = RADEONI2CGetBits; - info->pI2CBus->AcknTimeout = 5; - - if (!xf86I2CBusInit(info->pI2CBus)) return FALSE; - return TRUE; -} static void RADEONPreInitDDC(ScrnInfoPtr pScrn) { @@ -3039,102 +1992,6 @@ static void RADEONPreInitDDC(ScrnInfoPtr pScrn) } -/* BIOS may not have right panel size, we search through all supported - * DDC modes looking for the maximum panel size. - */ -static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn) -{ - int j; - RADEONInfoPtr info = RADEONPTR (pScrn); - xf86MonPtr ddc = pScrn->monitor->DDC; - DisplayModePtr p; - - if ((info->UseBiosDividers && info->DotClock != 0) || (ddc == NULL)) - return; - - /* Go thru detailed timing table first */ - for (j = 0; j < 4; j++) { - if (ddc->det_mon[j].type == 0) { - struct detailed_timings *d_timings = - &ddc->det_mon[j].section.d_timings; - int match = 0; - - /* If we didn't get a panel clock or guessed one, try to match the - * mode with the panel size. We do that because we _need_ a panel - * clock, or ValidateFPModes will fail, even when UseBiosDividers - * is set. - */ - if (info->DotClock == 0 && - info->PanelXRes == d_timings->h_active && - info->PanelYRes == d_timings->v_active) - match = 1; - - /* If we don't have a BIOS provided panel data with fixed dividers, - * check for a larger panel size - */ - if (info->PanelXRes < d_timings->h_active && - info->PanelYRes < d_timings->v_active && - !info->UseBiosDividers) - match = 1; - - if (match) { - info->PanelXRes = d_timings->h_active; - info->PanelYRes = d_timings->v_active; - info->DotClock = d_timings->clock / 1000; - info->HOverPlus = d_timings->h_sync_off; - info->HSyncWidth = d_timings->h_sync_width; - info->HBlank = d_timings->h_blanking; - info->VOverPlus = d_timings->v_sync_off; - info->VSyncWidth = d_timings->v_sync_width; - info->VBlank = d_timings->v_blanking; - info->Flags = (d_timings->interlaced ? V_INTERLACE : 0); - if (d_timings->sync == 3) { - switch (d_timings->misc) { - case 0: info->Flags |= V_NHSYNC | V_NVSYNC; break; - case 1: info->Flags |= V_PHSYNC | V_NVSYNC; break; - case 2: info->Flags |= V_NHSYNC | V_PVSYNC; break; - case 3: info->Flags |= V_PHSYNC | V_PVSYNC; break; - } - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel infos found from DDC detailed: %dx%d\n", - info->PanelXRes, info->PanelYRes); - } - } - } - - if (info->UseBiosDividers && info->DotClock != 0) - return; - - /* Search thru standard VESA modes from EDID */ - for (j = 0; j < 8; j++) { - if ((info->PanelXRes < ddc->timings2[j].hsize) && - (info->PanelYRes < ddc->timings2[j].vsize)) { - for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { - if ((ddc->timings2[j].hsize == p->HDisplay) && - (ddc->timings2[j].vsize == p->VDisplay)) { - float refresh = - (float)p->Clock * 1000.0 / p->HTotal / p->VTotal; - - if (abs((float)ddc->timings2[j].refresh - refresh) < 1.0) { - /* Is this good enough? */ - info->PanelXRes = ddc->timings2[j].hsize; - info->PanelYRes = ddc->timings2[j].vsize; - info->HBlank = p->HTotal - p->HDisplay; - info->HOverPlus = p->HSyncStart - p->HDisplay; - info->HSyncWidth = p->HSyncEnd - p->HSyncStart; - info->VBlank = p->VTotal - p->VDisplay; - info->VOverPlus = p->VSyncStart - p->VDisplay; - info->VSyncWidth = p->VSyncEnd - p->VSyncStart; - info->DotClock = p->Clock; - info->Flags = p->Flags; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel infos found from DDC VESA/EDID: %dx%d\n", - info->PanelXRes, info->PanelYRes); - } - } - } - } - } -} /* This function will sort all modes according to their resolution. * Highest resolution first. @@ -3681,93 +2538,6 @@ static Bool RADEONPreInitGamma(ScrnInfoPtr pScrn) return TRUE; } -static void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) -{ - MonPtr mon = pScrn->monitor; - xf86MonPtr ddc = mon->DDC; - int i; - - if (flag) { /* HSync */ - for (i = 0; i < 4; i++) { - if (ddc->det_mon[i].type == DS_RANGES) { - mon->nHsync = 1; - mon->hsync[0].lo = ddc->det_mon[i].section.ranges.min_h; - mon->hsync[0].hi = ddc->det_mon[i].section.ranges.max_h; - return; - } - } - /* If no sync ranges detected in detailed timing table, let's - * try to derive them from supported VESA modes. Are we doing - * too much here!!!? */ - i = 0; - if (ddc->timings1.t1 & 0x02) { /* 800x600@56 */ - mon->hsync[i].lo = mon->hsync[i].hi = 35.2; - i++; - } - if (ddc->timings1.t1 & 0x04) { /* 640x480@75 */ - mon->hsync[i].lo = mon->hsync[i].hi = 37.5; - i++; - } - if ((ddc->timings1.t1 & 0x08) || (ddc->timings1.t1 & 0x01)) { - mon->hsync[i].lo = mon->hsync[i].hi = 37.9; - i++; - } - if (ddc->timings1.t2 & 0x40) { - mon->hsync[i].lo = mon->hsync[i].hi = 46.9; - i++; - } - if ((ddc->timings1.t2 & 0x80) || (ddc->timings1.t2 & 0x08)) { - mon->hsync[i].lo = mon->hsync[i].hi = 48.1; - i++; - } - if (ddc->timings1.t2 & 0x04) { - mon->hsync[i].lo = mon->hsync[i].hi = 56.5; - i++; - } - if (ddc->timings1.t2 & 0x02) { - mon->hsync[i].lo = mon->hsync[i].hi = 60.0; - i++; - } - if (ddc->timings1.t2 & 0x01) { - mon->hsync[i].lo = mon->hsync[i].hi = 64.0; - i++; - } - mon->nHsync = i; - } else { /* Vrefresh */ - for (i = 0; i < 4; i++) { - if (ddc->det_mon[i].type == DS_RANGES) { - mon->nVrefresh = 1; - mon->vrefresh[0].lo = ddc->det_mon[i].section.ranges.min_v; - mon->vrefresh[0].hi = ddc->det_mon[i].section.ranges.max_v; - return; - } - } - - i = 0; - if (ddc->timings1.t1 & 0x02) { /* 800x600@56 */ - mon->vrefresh[i].lo = mon->vrefresh[i].hi = 56; - i++; - } - if ((ddc->timings1.t1 & 0x01) || (ddc->timings1.t2 & 0x08)) { - mon->vrefresh[i].lo = mon->vrefresh[i].hi = 60; - i++; - } - if (ddc->timings1.t2 & 0x04) { - mon->vrefresh[i].lo = mon->vrefresh[i].hi = 70; - i++; - } - if ((ddc->timings1.t1 & 0x08) || (ddc->timings1.t2 & 0x80)) { - mon->vrefresh[i].lo = mon->vrefresh[i].hi = 72; - i++; - } - if ((ddc->timings1.t1 & 0x04) || (ddc->timings1.t2 & 0x40) || - (ddc->timings1.t2 & 0x02) || (ddc->timings1.t2 & 0x01)) { - mon->vrefresh[i].lo = mon->vrefresh[i].hi = 75; - i++; - } - mon->nVrefresh = i; - } -} static int RADEONValidateMergeModes(ScrnInfoPtr pScrn1) { @@ -7467,333 +6237,6 @@ static void RADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info) save->bus_cntl |= RADEON_BUS_RD_DISCARD_EN; } - -/* Calculate display buffer watermark to prevent buffer underflow */ -static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - RADEONInfoPtr info2 = NULL; - - DisplayModePtr mode1, mode2; - - CARD32 temp, data, mem_trcd, mem_trp, mem_tras, mem_trbs=0; - float mem_tcas; - int k1, c; - CARD32 MemTrcdExtMemCntl[4] = {1, 2, 3, 4}; - CARD32 MemTrpExtMemCntl[4] = {1, 2, 3, 4}; - CARD32 MemTrasExtMemCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; - - CARD32 MemTrcdMemTimingCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; - CARD32 MemTrpMemTimingCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; - CARD32 MemTrasMemTimingCntl[16] = {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; - - float MemTcas[8] = {0, 1, 2, 3, 0, 1.5, 2.5, 0}; - float MemTcas2[8] = {0, 1, 2, 3, 4, 5, 6, 7}; - float MemTrbs[8] = {1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5}; - - float mem_bw, peak_disp_bw; - float min_mem_eff = 0.8; - float sclk_eff, sclk_delay; - float mc_latency_mclk, mc_latency_sclk, cur_latency_mclk, cur_latency_sclk; - float disp_latency, disp_latency_overhead, disp_drain_rate, disp_drain_rate2; - float pix_clk, pix_clk2; /* in MHz */ - int cur_size = 16; /* in octawords */ - int critical_point, critical_point2; - int stop_req, max_stop_req; - float read_return_rate, time_disp1_drop_priority; - - /* - * Set display0/1 priority up on r3/4xx in the memory controller for - * high res modes if the user specifies HIGH for displaypriority - * option. - */ - if ((info->DispPriority == 2) && IS_R300_VARIANT) { - CARD32 mc_init_misc_lat_timer = INREG(R300_MC_INIT_MISC_LAT_TIMER); - if (info->MergedFB || pRADEONEnt->HasSecondary) { - mc_init_misc_lat_timer |= 0x1100; /* display 0 and 1 */ - } else { - mc_init_misc_lat_timer |= 0x0100; /* display 0 only */ - } - OUTREG(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); - } - - - /* R420 and RV410 family not supported yet */ - if (info->ChipFamily == CHIP_FAMILY_R420 || info->ChipFamily == CHIP_FAMILY_RV410) return; - - if (pRADEONEnt->pSecondaryScrn) { - if (info->IsSecondary) return; - info2 = RADEONPTR(pRADEONEnt->pSecondaryScrn); - } else if (info->MergedFB) info2 = info; - - /* - * Determine if there is enough bandwidth for current display mode - */ - mem_bw = info->mclk * (info->RamWidth / 8) * (info->IsDDR ? 2 : 1); - - mode1 = info->CurrentLayout.mode; - if (info->MergedFB) { - mode1 = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT1; - mode2 = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2; - } else if ((pRADEONEnt->HasSecondary) && info2) { - mode2 = info2->CurrentLayout.mode; - } else { - mode2 = NULL; - } - - pix_clk = mode1->Clock/1000.0; - if (mode2) - pix_clk2 = mode2->Clock/1000.0; - else - pix_clk2 = 0; - - peak_disp_bw = (pix_clk * info->CurrentLayout.pixel_bytes); - if (info2) - peak_disp_bw += (pix_clk2 * info2->CurrentLayout.pixel_bytes); - - if (peak_disp_bw >= mem_bw * min_mem_eff) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "You may not have enough display bandwidth for current mode\n" - "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); - } - - /* CRTC1 - Set GRPH_BUFFER_CNTL register using h/w defined optimal values. - GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] - */ - stop_req = mode1->HDisplay * info->CurrentLayout.pixel_bytes / 16; - - /* setup Max GRPH_STOP_REQ default value */ - if (IS_RV100_VARIANT) - max_stop_req = 0x5c; - else - max_stop_req = 0x7c; - if (stop_req > max_stop_req) - stop_req = max_stop_req; - - /* Get values from the EXT_MEM_CNTL register...converting its contents. */ - temp = INREG(RADEON_MEM_TIMING_CNTL); - if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ - mem_trcd = MemTrcdExtMemCntl[(temp & 0x0c) >> 2]; - mem_trp = MemTrpExtMemCntl[ (temp & 0x03) >> 0]; - mem_tras = MemTrasExtMemCntl[(temp & 0x70) >> 4]; - } else { /* RV200 and later */ - mem_trcd = MemTrcdMemTimingCntl[(temp & 0x07) >> 0]; - mem_trp = MemTrpMemTimingCntl[ (temp & 0x700) >> 8]; - mem_tras = MemTrasMemTimingCntl[(temp & 0xf000) >> 12]; - } - - /* Get values from the MEM_SDRAM_MODE_REG register...converting its */ - temp = INREG(RADEON_MEM_SDRAM_MODE_REG); - data = (temp & (7<<20)) >> 20; - if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ - mem_tcas = MemTcas [data]; - } else { - mem_tcas = MemTcas2 [data]; - } - - if (IS_R300_VARIANT) { - - /* on the R300, Tcas is included in Trbs. - */ - temp = INREG(RADEON_MEM_CNTL); - data = (R300_MEM_NUM_CHANNELS_MASK & temp); - if (data == 1) { - if (R300_MEM_USE_CD_CH_ONLY & temp) { - temp = INREG(R300_MC_IND_INDEX); - temp &= ~R300_MC_IND_ADDR_MASK; - temp |= R300_MC_READ_CNTL_CD_mcind; - OUTREG(R300_MC_IND_INDEX, temp); - temp = INREG(R300_MC_IND_DATA); - data = (R300_MEM_RBS_POSITION_C_MASK & temp); - } else { - temp = INREG(R300_MC_READ_CNTL_AB); - data = (R300_MEM_RBS_POSITION_A_MASK & temp); - } - } else { - temp = INREG(R300_MC_READ_CNTL_AB); - data = (R300_MEM_RBS_POSITION_A_MASK & temp); - } - - mem_trbs = MemTrbs[data]; - mem_tcas += mem_trbs; - } - - if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ - /* DDR64 SCLK_EFF = SCLK for analysis */ - sclk_eff = info->sclk; - } else { -#ifdef XF86DRI - if (info->directRenderingEnabled) - sclk_eff = info->sclk - (info->agpMode * 50.0 / 3.0); - else -#endif - sclk_eff = info->sclk; - } - - /* Find the memory controller latency for the display client. - */ - if (IS_R300_VARIANT) { - /*not enough for R350 ???*/ - /* - if (!mode2) sclk_delay = 150; - else { - if (info->RamWidth == 256) sclk_delay = 87; - else sclk_delay = 97; - } - */ - sclk_delay = 250; - } else { - if ((info->ChipFamily == CHIP_FAMILY_RV100) || - info->IsIGP) { - if (info->IsDDR) sclk_delay = 41; - else sclk_delay = 33; - } else { - if (info->RamWidth == 128) sclk_delay = 57; - else sclk_delay = 41; - } - } - - mc_latency_sclk = sclk_delay / sclk_eff; - - if (info->IsDDR) { - if (info->RamWidth == 32) { - k1 = 40; - c = 3; - } else { - k1 = 20; - c = 1; - } - } else { - k1 = 40; - c = 3; - } - mc_latency_mclk = ((2.0*mem_trcd + mem_tcas*c + 4.0*mem_tras + 4.0*mem_trp + k1) / - info->mclk) + (4.0 / sclk_eff); - - /* - HW cursor time assuming worst case of full size colour cursor. - */ - cur_latency_mclk = (mem_trp + MAX(mem_tras, (mem_trcd + 2*(cur_size - (info->IsDDR+1))))) / info->mclk; - cur_latency_sclk = cur_size / sclk_eff; - - /* - Find the total latency for the display data. - */ - disp_latency_overhead = 8.0 / info->sclk; - mc_latency_mclk = mc_latency_mclk + disp_latency_overhead + cur_latency_mclk; - mc_latency_sclk = mc_latency_sclk + disp_latency_overhead + cur_latency_sclk; - disp_latency = MAX(mc_latency_mclk, mc_latency_sclk); - - /* - Find the drain rate of the display buffer. - */ - disp_drain_rate = pix_clk / (16.0/info->CurrentLayout.pixel_bytes); - if (info2) - disp_drain_rate2 = pix_clk2 / (16.0/info2->CurrentLayout.pixel_bytes); - else - disp_drain_rate2 = 0; - - /* - Find the critical point of the display buffer. - */ - critical_point= (CARD32)(disp_drain_rate * disp_latency + 0.5); - - /* ???? */ - /* - temp = (info->SavedReg.grph_buffer_cntl & RADEON_GRPH_CRITICAL_POINT_MASK) >> RADEON_GRPH_CRITICAL_POINT_SHIFT; - if (critical_point < temp) critical_point = temp; - */ - if (info->DispPriority == 2) { - critical_point = 0; - } - - /* - The critical point should never be above max_stop_req-4. Setting - GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. - */ - if (max_stop_req - critical_point < 4) critical_point = 0; - - if (critical_point == 0 && mode2 && info->ChipFamily == CHIP_FAMILY_R300) { - /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ - critical_point = 0x10; - } - - temp = info->SavedReg.grph_buffer_cntl; - temp &= ~(RADEON_GRPH_STOP_REQ_MASK); - temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); - temp &= ~(RADEON_GRPH_START_REQ_MASK); - if ((info->ChipFamily == CHIP_FAMILY_R350) && - (stop_req > 0x15)) { - stop_req -= 0x10; - } - temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); - - temp |= RADEON_GRPH_BUFFER_SIZE; - temp &= ~(RADEON_GRPH_CRITICAL_CNTL | - RADEON_GRPH_CRITICAL_AT_SOF | - RADEON_GRPH_STOP_CNTL); - /* - Write the result into the register. - */ - OUTREG(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | - (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); - - RADEONTRACE(("GRPH_BUFFER_CNTL from %x to %x\n", - (unsigned int)info->SavedReg.grph_buffer_cntl, INREG(RADEON_GRPH_BUFFER_CNTL))); - - if (mode2) { - stop_req = mode2->HDisplay * info2->CurrentLayout.pixel_bytes / 16; - - if (stop_req > max_stop_req) stop_req = max_stop_req; - - temp = info->SavedReg.grph2_buffer_cntl; - temp &= ~(RADEON_GRPH_STOP_REQ_MASK); - temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); - temp &= ~(RADEON_GRPH_START_REQ_MASK); - if ((info->ChipFamily == CHIP_FAMILY_R350) && - (stop_req > 0x15)) { - stop_req -= 0x10; - } - temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); - temp |= RADEON_GRPH_BUFFER_SIZE; - temp &= ~(RADEON_GRPH_CRITICAL_CNTL | - RADEON_GRPH_CRITICAL_AT_SOF | - RADEON_GRPH_STOP_CNTL); - - if ((info->ChipFamily == CHIP_FAMILY_RS100) || - (info->ChipFamily == CHIP_FAMILY_RS200)) - critical_point2 = 0; - else { - read_return_rate = MIN(info->sclk, info->mclk*(info->RamWidth*(info->IsDDR+1)/128)); - time_disp1_drop_priority = critical_point / (read_return_rate - disp_drain_rate); - - critical_point2 = (CARD32)((disp_latency + time_disp1_drop_priority + - disp_latency) * disp_drain_rate2 + 0.5); - - if (info->DispPriority == 2) { - critical_point2 = 0; - } - - if (max_stop_req - critical_point2 < 4) critical_point2 = 0; - - } - - if (critical_point2 == 0 && info->ChipFamily == CHIP_FAMILY_R300) { - /* some R300 cards have problem with this set to 0 */ - critical_point2 = 0x10; - } - - OUTREG(RADEON_GRPH2_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | - (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); - - RADEONTRACE(("GRPH2_BUFFER_CNTL from %x to %x\n", - (unsigned int)info->SavedReg.grph2_buffer_cntl, INREG(RADEON_GRPH2_BUFFER_CNTL))); - } -} - /* Define CRTC registers for requested video mode */ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, DisplayModePtr mode, RADEONInfoPtr info) @@ -9245,257 +7688,6 @@ _X_EXPORT void RADEONFreeScreen(int scrnIndex, int flags) RADEONFreeRec(pScrn); } -/* - * Powering done DAC, needed for DPMS problem with ViewSonic P817 (or its variant). - * - * Note for current DAC mapping when calling this function: - * For most of cards: - * single CRT: Driver doesn't change the existing CRTC->DAC mapping, - * CRTC1 could be driving either DAC or both DACs. - * CRT+CRT: CRTC1->TV DAC, CRTC2->Primary DAC - * DFP/LCD+CRT: CRTC2->TV DAC, CRTC2->Primary DAC. - * Some boards have two DACs reversed or don't even have a primary DAC, - * this is reflected in pRADEONEnt->ReversedDAC. And radeon 7200 doesn't - * have a second DAC. - * It's kind of messy, we'll need to redo DAC mapping part some day. - */ -static void RADEONDacPowerSet(ScrnInfoPtr pScrn, Bool IsOn, Bool IsPrimaryDAC) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - - if (IsPrimaryDAC) { - CARD32 dac_cntl; - CARD32 dac_macro_cntl = 0; - dac_cntl = INREG(RADEON_DAC_CNTL); - if ((!info->IsMobility) || (info->ChipFamily == CHIP_FAMILY_RV350)) - dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL); - if (IsOn) { - dac_cntl &= ~RADEON_DAC_PDWN; - dac_macro_cntl &= ~(RADEON_DAC_PDWN_R | - RADEON_DAC_PDWN_G | - RADEON_DAC_PDWN_B); - } else { - dac_cntl |= RADEON_DAC_PDWN; - dac_macro_cntl |= (RADEON_DAC_PDWN_R | - RADEON_DAC_PDWN_G | - RADEON_DAC_PDWN_B); - } - OUTREG(RADEON_DAC_CNTL, dac_cntl); - if ((!info->IsMobility) || (info->ChipFamily == CHIP_FAMILY_RV350)) - OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); - } else { - if (info->ChipFamily != CHIP_FAMILY_R200) { - CARD32 tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); - if (IsOn) { - tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD | - RADEON_TV_DAC_GDACPD | - RADEON_TV_DAC_BDACPD | - RADEON_TV_DAC_BGSLEEP); - } else { - tv_dac_cntl |= (RADEON_TV_DAC_RDACPD | - RADEON_TV_DAC_GDACPD | - RADEON_TV_DAC_BDACPD | - RADEON_TV_DAC_BGSLEEP); - } - OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl); - } else { - CARD32 fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL); - if (IsOn) { - fp2_gen_cntl |= RADEON_FP2_DVO_EN; - } else { - fp2_gen_cntl &= ~RADEON_FP2_DVO_EN; - } - OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); - } - } -} - -/* Sets VESA Display Power Management Signaling (DPMS) Mode */ -static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, - int PowerManagementMode, - int flags) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - - if (!pScrn->vtSema) return; - - RADEONTRACE(("RADEONDisplayPowerManagementSet(%d,0x%x)\n", PowerManagementMode, flags)); - -#ifdef XF86DRI - if (info->CPStarted) DRILock(pScrn->pScreen, 0); -#endif - - if (info->accelOn) - RADEON_SYNC(info, pScrn); - - if (info->FBDev) { - fbdevHWDPMSSet(pScrn, PowerManagementMode, flags); - } else { - int mask1 = (RADEON_CRTC_DISPLAY_DIS | - RADEON_CRTC_HSYNC_DIS | - RADEON_CRTC_VSYNC_DIS); - int mask2 = (RADEON_CRTC2_DISP_DIS | - RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS); - - switch (PowerManagementMode) { - case DPMSModeOn: - /* Screen: On; HSync: On, VSync: On */ - if (info->IsSecondary) - OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask2); - else { - if (info->MergedFB) - OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask2); - OUTREGP(RADEON_CRTC_EXT_CNTL, 0, ~mask1); - } - break; - - case DPMSModeStandby: - /* Screen: Off; HSync: Off, VSync: On */ - if (info->IsSecondary) - OUTREGP(RADEON_CRTC2_GEN_CNTL, - (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), - ~mask2); - else { - if (info->MergedFB) - OUTREGP(RADEON_CRTC2_GEN_CNTL, - (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), - ~mask2); - OUTREGP(RADEON_CRTC_EXT_CNTL, - (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS), - ~mask1); - } - break; - - case DPMSModeSuspend: - /* Screen: Off; HSync: On, VSync: Off */ - if (info->IsSecondary) - OUTREGP(RADEON_CRTC2_GEN_CNTL, - (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), - ~mask2); - else { - if (info->MergedFB) - OUTREGP(RADEON_CRTC2_GEN_CNTL, - (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), - ~mask2); - OUTREGP(RADEON_CRTC_EXT_CNTL, - (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS), - ~mask1); - } - break; - - case DPMSModeOff: - /* Screen: Off; HSync: Off, VSync: Off */ - if (info->IsSecondary) - OUTREGP(RADEON_CRTC2_GEN_CNTL, mask2, ~mask2); - else { - if (info->MergedFB) - OUTREGP(RADEON_CRTC2_GEN_CNTL, mask2, ~mask2); - OUTREGP(RADEON_CRTC_EXT_CNTL, mask1, ~mask1); - } - break; - } - - if (PowerManagementMode == DPMSModeOn) { - if (info->IsSecondary) { - if (info->DisplayType == MT_DFP) { - OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); - OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_ON, ~RADEON_FP2_ON); - if (info->ChipFamily >= CHIP_FAMILY_R200) { - OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_DVO_EN, ~RADEON_FP2_DVO_EN); - } - } else if (info->DisplayType == MT_CRT) { - RADEONDacPowerSet(pScrn, TRUE, !pRADEONEnt->ReversedDAC); - } - } else { - if ((info->MergedFB) && (info->MergeType == MT_DFP)) { - OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); - OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_ON, ~RADEON_FP2_ON); - if (info->ChipFamily >= CHIP_FAMILY_R200) { - OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_DVO_EN, ~RADEON_FP2_DVO_EN); - } - } - if (info->DisplayType == MT_DFP) { - OUTREGP (RADEON_FP_GEN_CNTL, (RADEON_FP_FPON | RADEON_FP_TMDS_EN), - ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN)); - } else if (info->DisplayType == MT_LCD) { - - OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_BLON, ~RADEON_LVDS_BLON); - usleep (info->PanelPwrDly * 1000); - OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_ON, ~RADEON_LVDS_ON); - } else if (info->DisplayType == MT_CRT) { - if ((pRADEONEnt->HasSecondary) || info->MergedFB) { - RADEONDacPowerSet(pScrn, TRUE, pRADEONEnt->ReversedDAC); - } else { - RADEONDacPowerSet(pScrn, TRUE, TRUE); - if (info->HasCRTC2) - RADEONDacPowerSet(pScrn, TRUE, FALSE); - } - } - } - } else if ((PowerManagementMode == DPMSModeOff) || - (PowerManagementMode == DPMSModeSuspend) || - (PowerManagementMode == DPMSModeStandby)) { - if (info->IsSecondary) { - if (info->DisplayType == MT_DFP) { - OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); - OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_ON); - if (info->ChipFamily >= CHIP_FAMILY_R200) { - OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_DVO_EN); - } - } else if (info->DisplayType == MT_CRT) { - RADEONDacPowerSet(pScrn, FALSE, !pRADEONEnt->ReversedDAC); - } - } else { - if ((info->MergedFB) && (info->MergeType == MT_DFP)) { - OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); - OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_ON); - if (info->ChipFamily >= CHIP_FAMILY_R200) { - OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_DVO_EN); - } - } - if (info->DisplayType == MT_DFP) { - OUTREGP (RADEON_FP_GEN_CNTL, 0, ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN)); - } else if (info->DisplayType == MT_LCD) { - unsigned long tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); - - if (info->IsMobility || info->IsIGP) { - /* Asic bug, when turning off LVDS_ON, we have to make sure - RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off - */ - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); - } - - OUTREGP (RADEON_LVDS_GEN_CNTL, 0, - ~(RADEON_LVDS_BLON | RADEON_LVDS_ON)); - - if (info->IsMobility || info->IsIGP) { - OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl); - } - } else if (info->DisplayType == MT_CRT) { - if ((pRADEONEnt->HasSecondary) || info->MergedFB) { - RADEONDacPowerSet(pScrn, FALSE, pRADEONEnt->ReversedDAC); - } else { - /* single CRT, turning both DACs off, we don't really know - * which DAC is actually connected. - */ - RADEONDacPowerSet(pScrn, FALSE, TRUE); - if (info->HasCRTC2) /* don't apply this to old radeon (singel CRTC) card */ - RADEONDacPowerSet(pScrn, FALSE, FALSE); - } - } - } - } - } - -#ifdef XF86DRI - if (info->CPStarted) DRIUnlock(pScrn->pScreen); -#endif -} - static void RADEONGetMergedFBOptions(ScrnInfoPtr pScrn) { |