--- xc/programs/Xserver/hw/xfree86/common/xf86PciInfo.h.new_chips 2004-04-22 14:25:07.000000000 -0400 +++ xc/programs/Xserver/hw/xfree86/common/xf86PciInfo.h 2004-04-22 14:25:04.000000000 -0400 @@ -133,6 +133,18 @@ #define PCI_CHIP_QV1280 0x3033 /* ATI */ +#define PCI_CHIP_RV380_3150 0x3150 +#define PCI_CHIP_RV380_3151 0x3151 +#define PCI_CHIP_RV380_3152 0x3152 +#define PCI_CHIP_RV380_3153 0x3153 +#define PCI_CHIP_RV380_3154 0x3154 +#define PCI_CHIP_RV380_3156 0x3156 +#define PCI_CHIP_RV380_3E50 0x3E50 +#define PCI_CHIP_RV380_3E51 0x3E51 +#define PCI_CHIP_RV380_3E52 0x3E52 +#define PCI_CHIP_RV380_3E53 0x3E53 +#define PCI_CHIP_RV380_3E54 0x3E54 +#define PCI_CHIP_RV380_3E56 0x3E56 #define PCI_CHIP_RS100_4136 0x4136 #define PCI_CHIP_RS200_4137 0x4137 #define PCI_CHIP_R300_AD 0x4144 @@ -181,6 +193,14 @@ #define PCI_CHIP_RV250_Ie 0x4965 #define PCI_CHIP_RV250_If 0x4966 #define PCI_CHIP_RV250_Ig 0x4967 +#define PCI_CHIP_R420_JH 0x4A48 +#define PCI_CHIP_R420_JI 0x4A49 +#define PCI_CHIP_R420_JJ 0x4A4A +#define PCI_CHIP_R420_JK 0x4A4B +#define PCI_CHIP_R420_JL 0x4A4C +#define PCI_CHIP_R420_JM 0x4A4D +#define PCI_CHIP_R420_JN 0x4A4E +#define PCI_CHIP_R420_JP 0x4A50 #define PCI_CHIP_MACH64LB 0x4C42 #define PCI_CHIP_MACH64LD 0x4C44 #define PCI_CHIP_RAGE128LE 0x4C45 @@ -277,6 +297,22 @@ #define PCI_CHIP_RAGE128TS 0x5453 #define PCI_CHIP_RAGE128TT 0x5454 #define PCI_CHIP_RAGE128TU 0x5455 +#define PCI_CHIP_RV370_5460 0x5460 +#define PCI_CHIP_RV370_5461 0x5461 +#define PCI_CHIP_RV370_5462 0x5462 +#define PCI_CHIP_RV370_5463 0x5463 +#define PCI_CHIP_RV370_5464 0x5464 +#define PCI_CHIP_RV370_5465 0x5465 +#define PCI_CHIP_RV370_5466 0x5466 +#define PCI_CHIP_RV370_5467 0x5467 +#define PCI_CHIP_R423_UH 0x5548 +#define PCI_CHIP_R423_UI 0x5549 +#define PCI_CHIP_R423_UJ 0x554A +#define PCI_CHIP_R423_UK 0x554B +#define PCI_CHIP_R423_UQ 0x5551 +#define PCI_CHIP_R423_UR 0x5552 +#define PCI_CHIP_R423_UT 0x5554 +#define PCI_CHIP_R423_5D57 0x5D57 #define PCI_CHIP_MACH64VT 0x5654 #define PCI_CHIP_MACH64VU 0x5655 #define PCI_CHIP_MACH64VV 0x5656 @@ -284,12 +320,22 @@ #define PCI_CHIP_RS300_5835 0x5835 #define PCI_CHIP_RS300_5836 0x5836 #define PCI_CHIP_RS300_5837 0x5837 +#define PCI_CHIP_RV370_5B60 0x5B60 +#define PCI_CHIP_RV370_5B61 0x5B61 +#define PCI_CHIP_RV370_5B62 0x5B62 +#define PCI_CHIP_RV370_5B63 0x5B63 +#define PCI_CHIP_RV370_5B64 0x5B64 +#define PCI_CHIP_RV370_5B65 0x5B65 +#define PCI_CHIP_RV370_5B66 0x5B66 +#define PCI_CHIP_RV370_5B67 0x5B67 #define PCI_CHIP_RV280_5960 0x5960 #define PCI_CHIP_RV280_5961 0x5961 #define PCI_CHIP_RV280_5962 0x5962 #define PCI_CHIP_RV280_5964 0x5964 #define PCI_CHIP_RV280_5C61 0x5C61 #define PCI_CHIP_RV280_5C63 0x5C63 +#define PCI_CHIP_RS350_7834 0x7834 +#define PCI_CHIP_RS350_7835 0x7835 /* Avance Logic */ #define PCI_CHIP_ALG2064 0x2064 --- xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.h.new_chips 2004-05-10 09:42:44.000000000 -0400 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.h 2004-05-13 10:28:41.000000000 -0400 @@ -45,26 +45,93 @@ #define _XF86MISC_SERVER_ #include "xf86misc.h" +typedef enum +{ + DDC_NONE_DETECTED, + DDC_MONID, + DDC_DVI, + DDC_VGA, + DDC_CRT2 +} RADEONDDCType; + +typedef enum +{ + MT_UNKNOWN = -1, + MT_NONE = 0, + MT_CRT = 1, + MT_LCD = 2, + MT_DFP = 3, + MT_CTV = 4, + MT_STV = 5 +} RADEONMonitorType; + +typedef enum +{ + CONNECTOR_NONE, + CONNECTOR_PROPRIETARY, + CONNECTOR_CRT, + CONNECTOR_DVI_I, + CONNECTOR_DVI_D, + CONNECTOR_CTV, + CONNECTOR_STV, + CONNECTOR_UNSUPPORTED +} RADEONConnectorType; + +typedef enum +{ + CONNECTOR_NONE_ATOM, + CONNECTOR_VGA_ATOM, + CONNECTOR_DVI_I_ATOM, + CONNECTOR_DVI_D_ATOM, + CONNECTOR_DVI_A_ATOM, + CONNECTOR_STV_ATOM, + CONNECTOR_CTV_ATOM, + CONNECTOR_LVDS_ATOM, + CONNECTOR_DIGITAL_ATOM, + CONNECTOR_UNSUPPORTED_ATOM +} RADEONConnectorTypeATOM; + +typedef enum +{ + DAC_UNKNOWN = -1, + DAC_PRIMARY = 0, + DAC_TVDAC = 1 +} RADEONDacType; + +typedef enum +{ + TMDS_UNKNOWN = -1, + TMDS_INT = 0, + TMDS_EXT = 1 +} RADEONTmdsType; + typedef struct { - Bool HasSecondary; + RADEONDDCType DDCType; + RADEONDacType DACType; + RADEONTmdsType TMDSType; + RADEONConnectorType ConnectorType; + RADEONMonitorType MonType; + xf86MonPtr MonInfo; +} RADEONConnector; + +typedef struct +{ + Bool IsUsed; + Bool IsActive; + DisplayModePtr pCurMode; + RADEONConnector* pPort; +} RADEONController; - /* - * The next two are used to make sure CRTC2 is restored before CRTC_EXT, - * otherwise it could lead to blank screens. - */ - Bool IsSecondaryRestored; - Bool RestorePrimary; +typedef struct +{ + Bool HasSecondary; ScrnInfoPtr pSecondaryScrn; ScrnInfoPtr pPrimaryScrn; - int MonType1; - int MonType2; - xf86MonPtr MonInfo1; - xf86MonPtr MonInfo2; - Bool ReversedDAC; /* TVDAC used as primary dac */ - Bool ReversedTMDS; /* DDC_DVI is used for external TMDS */ + RADEONConnector PortInfo[2]; + RADEONController Controller[2]; } RADEONEntRec, *RADEONEntPtr; /* radeon_probe.c */ @@ -76,6 +143,7 @@ FunctionPrototype((DriverPtr, int)); extern SymTabRec RADEONChipsets[]; + extern PciChipsets RADEONPciChipsets[]; /* radeon_driver.c */ --- xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_display.c.new_chips 2004-05-10 09:42:44.000000000 -0400 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_display.c 2004-05-19 14:36:56.000000000 -0400 @@ -0,0 +1,2213 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c,v 1.120tsi 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. + */ + +#include "xf86.h" +#include "xf86_OSproc.h" + +#include "fbdevhw.h" +#include "vgaHW.h" + +#include "radeon.h" +#include "radeon_macros.h" +#include "radeon_probe.h" +#include "radeon_reg.h" + +extern int gRADEONEntityIndex; + +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, 0x400f7/*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*/ +}; + +static const CARD32 default_tvdac_adj [CHIP_FAMILY_LAST] = +{ + 0x00000000, /* unknown */ + 0x00000000, /* legacy */ + 0x00000000, /* r100 */ + 0x00280000, /* rv100 */ + 0x00000000, /* rs100 */ + 0x00880000, /* rv200 */ + 0x00000000, /* rs200 */ + 0x00000000, /* r200 */ + 0x00770000, /* rv250 */ + 0x00290000, /* rs300 */ + 0x00560000, /* rv280 */ + 0x00780000, /* r300 */ + 0x00770000, /* r350 */ + 0x00780000, /* rv350 */ + 0x00780000, /* rv380 */ + 0x01080000, /* r420 */ +}; + +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 IsPrimaryDac) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + int bConnected = 0; + + /* the monitor either wasn't connected or it is a non-DDC monitor. + we need to try to detect connectedness another way.... + */ + if(IsPrimaryDac) + { + unsigned long ulOrigVCLK_ECP_CNTL; + unsigned long ulOrigDAC_CNTL; + unsigned long ulOrigDAC_EXT_CNTL; + unsigned long ulOrigCRTC_EXT_CNTL; + unsigned long ulOrigDAC_CNTL2; + unsigned long ulData; + unsigned long ulMask; + + ulOrigDAC_CNTL2 = INREG(RADEON_DAC_CNTL2); + OUTREG(RADEON_DAC_CNTL2, 2); + + 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(1000); + + 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); + OUTREG(RADEON_DAC_CNTL2, ulOrigDAC_CNTL2); + } + else + { + if (info->ChipFamily == CHIP_FAMILY_R200) + { +#if 0 + 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; +#endif + +/* This doesn't work on some cards, we always return false + for now, If one wants to connected a non-DDC monitor on + the DVI port, he has to specify it explicitly in + the config file with Option MonitorLayout. +*/ + return MT_NONE; /* **** code ends here ***** */ + +#if 0 + 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); +#endif + } + 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 ulOrigCRTC2_GEN_CNTL; + unsigned long ulOrigDISP_OUTPUT_CNTL; + unsigned long ulOrigDAC_EXT_CNTL; + unsigned long ulData; + unsigned long ulMask; + int i; + + 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); + + ulOrigDISP_OUTPUT_CNTL = INREG(RADEON_DISP_OUTPUT_CNTL); + ulData = ulOrigDISP_OUTPUT_CNTL & ~0xc; + OUTREG(RADEON_DISP_OUTPUT_CNTL, ulData); + + ulOrigCRTC2_GEN_CNTL = INREG(RADEON_CRTC2_GEN_CNTL); + ulData = ulOrigCRTC2_GEN_CNTL | RADEON_CRTC2_CRT2_ON; + OUTREG(RADEON_CRTC2_GEN_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); + + ulOrigTV_DAC_CNTL = INREG(RADEON_TV_DAC_CNTL); + + ulData = 0x00880213; + OUTREG(RADEON_TV_DAC_CNTL, ulData); + usleep(50000); + + ulOrigDAC_EXT_CNTL = INREG(RADEON_DAC_EXT_CNTL); + ulData = ulOrigDAC_EXT_CNTL; + ulData &= ~RADEON_DAC_FORCE_DATA_MASK; + ulData |= (3 | 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); + + usleep(1000); + + ulData = INREG(RADEON_TV_DAC_CNTL); + bConnected = (ulData & RADEON_TV_DAC_CMPOUT) ? 1:0; +#if 1 + for (i = 0; i < 4; i++) { + ulData = 0x00880203; + OUTREG(RADEON_TV_DAC_CNTL, ulData); + while(INREG(RADEON_TV_DAC_CNTL) & (1<<5)); + ulData = 0x00880213; + OUTREG(RADEON_TV_DAC_CNTL, ulData); + usleep(5000); + ulData = INREG(RADEON_TV_DAC_CNTL); + bConnected = (ulData & RADEON_TV_DAC_CMPOUT) ? 1:0; + if (!bConnected) break; + } +#endif + 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_DAC_EXT_CNTL, ulOrigDAC_EXT_CNTL); + OUTREG(RADEON_DISP_OUTPUT_CNTL, ulOrigDISP_OUTPUT_CNTL); + OUTREG(RADEON_TV_DAC_CNTL, ulOrigTV_DAC_CNTL); + OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulOrigTV_PRE_DAC_MUX_CNTL); + } + } + + 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: + if ((info->ChipFamily == CHIP_FAMILY_R200) || + IS_R300_VARIANT) return MT_NONE; + 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 == 3) 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; + } + + if (*MonInfo) { + if ((*MonInfo)->rawData[0x14] & 0x80) { + 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_vert_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; + } + + 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); + + if (info->DotClock == 0) { + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + DisplayModePtr tmp_mode = NULL; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No valid timing info from BIOS.\n"); + /* 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. + */ + 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->CloneType == MT_DFP)) { + RADEONGetTMDSInfo(pScrn); + if (!pScrn->monitor->DDC) + RADEONGetHardCodedEDIDFromBIOS(pScrn); + } + } +} + +/* BIOS may not have right panel size, we search through all supported + * DDC modes looking for the maximum panel size. + */ +void RADEONUpdatePanelSize(ScrnInfoPtr pScrn) +{ + int j; + RADEONInfoPtr info = RADEONPTR (pScrn); + xf86MonPtr ddc = pScrn->monitor->DDC; + DisplayModePtr p; + + /* 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; + if (info->PanelXRes < d_timings->h_active && + info->PanelYRes < d_timings->v_active) { + + 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; + } + } + } + + /* 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 = + (ddc->det_mon[j].section.d_timings.interlaced + ? V_INTERLACE + : 0); + if (ddc->det_mon[j].section.d_timings.sync == 3) { + switch (ddc->det_mon[j].section.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 size found from DDC: %dx%d\n", + info->PanelXRes, info->PanelYRes); +} + +void RADEONGetTVDacAdjInfo(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + /* Todo: get this setting from BIOS */ + info->tv_dac_adj = default_tvdac_adj[info->ChipFamily]; + if (info->IsMobility) { /* some mobility chips may different */ + if (info->ChipFamily == CHIP_FAMILY_RV250) + info->tv_dac_adj = 0x00880000; + } +} + +static void RADEONQueryConnectedDisplays(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + DevUnion* pPriv; + RADEONEntPtr pRADEONEnt; + unsigned char *RADEONMMIO = info->MMIO; + const char *s; + Bool ignore_edid = FALSE; + int i = 0, second = 0, max_mt; + + pPriv = xf86GetEntityPrivate(pScrn->entityList[0], gRADEONEntityIndex); + pRADEONEnt = pPriv->ptr; + max_mt = 5; + + /* 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; + } + pRADEONEnt->Controller[0].IsUsed = FALSE; + pRADEONEnt->Controller[1].IsUsed = FALSE; + pRADEONEnt->Controller[0].IsActive = FALSE; + pRADEONEnt->Controller[1].IsActive = FALSE; + + 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; + } + + /* 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 */ + if (pRADEONEnt->PortInfo[1].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. + * For example, you can config your laptop with + * Option "MonitorLayout" "LVDS, CRT" + * Option "CloneHSync" "40-150" + * Option "CloneVRefresh" "60-120" + * With these options, you can connect in your CRT monitor later + * after the X server has started. + */ + 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; + } + } + if (i == max_mt) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Invalid Monitor type specified for 1st port \n"); + + 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 (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; + } + + 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 (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN || pRADEONEnt->PortInfo[1].MonType == MT_UNKNOWN) { + + if((!info->HasCRTC2) && (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->PortInfo[1].MonType = MT_NONE; + pRADEONEnt->PortInfo[1].MonInfo = NULL; + pRADEONEnt->PortInfo[1].DDCType = DDC_NONE_DETECTED; + pRADEONEnt->PortInfo[1].DACType = DAC_UNKNOWN; + pRADEONEnt->PortInfo[1].TMDSType = TMDS_UNKNOWN; + pRADEONEnt->PortInfo[1].ConnectorType = CONNECTOR_NONE; + + pRADEONEnt->Controller[0].pPort = &pRADEONEnt->PortInfo[0]; + pRADEONEnt->Controller[1].pPort = &pRADEONEnt->PortInfo[1]; + return; + } + + /* 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 1st port ----------------------\n"); + xf86PrintEDID( pRADEONEnt->PortInfo[0].MonInfo ); + } + + if (pRADEONEnt->PortInfo[1].MonInfo) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on 2nd port -----------------------\n"); + xf86PrintEDID( pRADEONEnt->PortInfo[1].MonInfo ); + } + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\n"); + +} + +Bool RADEONMapControllers(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + Bool head_reversed = FALSE; + + info->Clone = FALSE; + info->CloneType = MT_NONE; + + if (!info->IsSecondary) { + RADEONQueryConnectedDisplays(pScrn); + + pRADEONEnt->Controller[0].pPort = &(pRADEONEnt->PortInfo[0]); + pRADEONEnt->Controller[1].pPort = &(pRADEONEnt->PortInfo[1]); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Port1:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", + MonTypeName[pRADEONEnt->Controller[0].pPort->MonType+1], + info->IsAtomBios ? + ConnectorTypeNameATOM[pRADEONEnt->Controller[0].pPort->ConnectorType]: + ConnectorTypeName[pRADEONEnt->Controller[0].pPort->ConnectorType], + DACTypeName[pRADEONEnt->Controller[0].pPort->DACType+1], + TMDSTypeName[pRADEONEnt->Controller[0].pPort->TMDSType+1], + DDCTypeName[pRADEONEnt->Controller[0].pPort->DDCType]); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Port2:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", + MonTypeName[pRADEONEnt->Controller[1].pPort->MonType+1], + info->IsAtomBios ? + ConnectorTypeNameATOM[pRADEONEnt->Controller[1].pPort->ConnectorType]: + ConnectorTypeName[pRADEONEnt->Controller[1].pPort->ConnectorType], + DACTypeName[pRADEONEnt->Controller[1].pPort->DACType+1], + TMDSTypeName[pRADEONEnt->Controller[1].pPort->TMDSType+1], + DDCTypeName[pRADEONEnt->Controller[1].pPort->DDCType]); + + /* no display detected on primary port*/ + if (pRADEONEnt->Controller[0].pPort->MonType == MT_NONE) { + if (pRADEONEnt->Controller[1].pPort->MonType != MT_NONE) { + /* Only one detected on secondary, let it to be primary */ + pRADEONEnt->Controller[0].pPort = &(pRADEONEnt->PortInfo[1]); + pRADEONEnt->Controller[1].pPort = &(pRADEONEnt->PortInfo[0]); + head_reversed = TRUE; + } else { + /* None detected, Default to a CRT connected */ + pRADEONEnt->Controller[0].pPort->MonType = MT_CRT; + } + } + + if ((pRADEONEnt->Controller[0].pPort->MonType == MT_LCD) && + (pRADEONEnt->Controller[1].pPort->MonType == MT_CRT)) { + if (!(INREG(RADEON_LVDS_GEN_CNTL) & RADEON_LVDS_ON)) { + /* LCD is switched off, don't turn it on, otherwise it may casue lockup due to SS issue. */ + pRADEONEnt->Controller[0].pPort = &(pRADEONEnt->PortInfo[1]); + pRADEONEnt->Controller[1].pPort = &(pRADEONEnt->PortInfo[0]); + pRADEONEnt->Controller[1].pPort->MonType = MT_NONE; + head_reversed = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "LCD is switched off, only CRT will be used\n"); + } + } + + if ((pRADEONEnt->Controller[0].pPort->MonType != MT_NONE) && + (pRADEONEnt->Controller[1].pPort->MonType != MT_NONE)) { + if (xf86ReturnOptValBool(info->Options, OPTION_REVERSE_DISPLAY, FALSE)) { + if (info->IsMobility) { + /* Don't reverse display for mobility chips, as only CRTC1 path has RMX which + will be required by many LCD panels + */ + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Reverse Display cannot be used for mobility chip\n"); + } else { + pRADEONEnt->Controller[0].pPort = &(pRADEONEnt->PortInfo[1]); + pRADEONEnt->Controller[1].pPort = &(pRADEONEnt->PortInfo[0]); + head_reversed = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Primary and Secondary mapping is reversed\n"); + } + } + } + + if (pRADEONEnt->HasSecondary && pRADEONEnt->Controller[1].pPort->MonType == MT_NONE) { + pRADEONEnt->HasSecondary = FALSE; + } + } + + if(info->HasCRTC2) { + if(info->IsSecondary) { + info->DisplayType = pRADEONEnt->Controller[1].pPort->MonType; + pScrn->monitor->DDC = pRADEONEnt->Controller[1].pPort->MonInfo; + } else { + info->DisplayType = pRADEONEnt->Controller[0].pPort->MonType; + pScrn->monitor->DDC = pRADEONEnt->Controller[0].pPort->MonInfo; + } + + if(!pRADEONEnt->HasSecondary) { + if ((info->CloneType = pRADEONEnt->Controller[1].pPort->MonType)) + info->Clone = TRUE; + } + } else { + if (pRADEONEnt->Controller[0].pPort->MonType == MT_NONE) + pRADEONEnt->Controller[0].pPort->MonType = MT_CRT; + info->DisplayType = pRADEONEnt->Controller[0].pPort->MonType; + pScrn->monitor->DDC = pRADEONEnt->Controller[0].pPort->MonInfo; + pRADEONEnt->Controller[1].pPort->MonType = MT_NONE; + } + + if (!info->IsSecondary) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "---- Primary Head: Port%d ---- \n", head_reversed?2:1); + if (pRADEONEnt->Controller[1].pPort->MonType != MT_NONE) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "---- Secondary Head: Port%d ----\n", head_reversed?1:2); + else + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "---- Secondary Head: Not used ----\n"); + } + + info->HBlank = 0; + info->HOverPlus = 0; + info->HSyncWidth = 0; + info->VBlank = 0; + info->VOverPlus = 0; + info->VSyncWidth = 0; + info->DotClock = 0; + info->UseBiosDividers = FALSE; + + /* This option is used to place video overlay to CRTC2 when in clone mode. + * Default is on CRTC1. + */ + info->OverlayOnCRTC2 = FALSE; + if (xf86ReturnOptValBool(info->Options, OPTION_CRTC2_OVERLAY, FALSE)) + info->OverlayOnCRTC2 = TRUE; + + return TRUE; +} + +/* + * Powering done DAC, needed for DPMS problem with ViewSonic P817 (or its variant). + * + */ +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 { + CARD32 tv_dac_cntl; + CARD32 fp2_gen_cntl; + + switch(info->ChipFamily) + { + case CHIP_FAMILY_R420: + tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); + if (IsOn) { + tv_dac_cntl &= ~(R420_TV_DAC_RDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_BDACPD | + RADEON_TV_DAC_BGSLEEP); + } else { + tv_dac_cntl |= (R420_TV_DAC_RDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_BDACPD | + RADEON_TV_DAC_BGSLEEP); + } + OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl); + break; + + case CHIP_FAMILY_R200: + 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); + break; + + default: + 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); + break; + } + } +} + +/* This is to be used enable/disable displays dynamically, + not currently used +*/ +void RADEONEnableDisplay(ScrnInfoPtr pScrn, RADEONController* pCRTC, BOOL bEnable) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONSavePtr save = &info->ModeReg; + unsigned char * RADEONMMIO = info->MMIO; + unsigned long tmp; + + if (bEnable) { + if (pCRTC->pPort->MonType == MT_CRT) { + if (pCRTC->pPort->DACType == DAC_PRIMARY) { + tmp = INREG(RADEON_CRTC_EXT_CNTL); + tmp |= RADEON_CRTC_CRT_ON; + OUTREG(RADEON_CRTC_EXT_CNTL, tmp); + save->crtc_ext_cntl |= RADEON_CRTC_CRT_ON; + } else if (pCRTC->pPort->DACType == DAC_TVDAC) { + if (info->ChipFamily == CHIP_FAMILY_R200) { + tmp = INREG(RADEON_CRTC2_GEN_CNTL); + tmp |= RADEON_CRTC2_CRT2_ON; + OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); + save->crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON; + } else { + tmp = INREG(RADEON_FP2_GEN_CNTL); + tmp |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); + OUTREG(RADEON_FP2_GEN_CNTL, tmp); + save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); + } + } + RADEONDacPowerSet(pScrn, bEnable, (pCRTC->pPort->DACType == DAC_PRIMARY)); + } else if (pCRTC->pPort->MonType == MT_DFP) { + if (pCRTC->pPort->TMDSType == TMDS_INT) { + tmp = INREG(RADEON_FP_GEN_CNTL); + tmp |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); + OUTREG(RADEON_FP_GEN_CNTL, tmp); + save->fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); + } else if (pCRTC->pPort->TMDSType == TMDS_EXT) { + tmp = INREG(RADEON_FP2_GEN_CNTL); + tmp |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); + OUTREG(RADEON_FP2_GEN_CNTL, tmp); + save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); + } + } else if (pCRTC->pPort->MonType == MT_LCD) { + tmp = INREG(RADEON_LVDS_GEN_CNTL); + tmp |= (RADEON_LVDS_ON | RADEON_LVDS_BLON); + tmp &= ~(RADEON_LVDS_DISPLAY_DIS); + OUTREG(RADEON_LVDS_GEN_CNTL, tmp); + save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON); + save->lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS); + } + } else { + if (pCRTC->pPort->MonType == MT_CRT || pCRTC->pPort->MonType == NONE) { + if (pCRTC->pPort->DACType == DAC_PRIMARY) { + tmp = INREG(RADEON_CRTC_EXT_CNTL); + tmp &= ~RADEON_CRTC_CRT_ON; + OUTREG(RADEON_CRTC_EXT_CNTL, tmp); + save->crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON; + } else if (pCRTC->pPort->DACType == DAC_TVDAC) { + if (info->ChipFamily == CHIP_FAMILY_R200) { + tmp = INREG(RADEON_FP2_GEN_CNTL); + tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); + OUTREG(RADEON_FP2_GEN_CNTL, tmp); + save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); + } else { + tmp = INREG(RADEON_CRTC2_GEN_CNTL); + tmp &= ~RADEON_CRTC2_CRT2_ON; + OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); + save->crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON; + } + } + RADEONDacPowerSet(pScrn, bEnable, (pCRTC->pPort->DACType == DAC_PRIMARY)); + } + + if (pCRTC->pPort->MonType == MT_DFP || pCRTC->pPort->MonType == NONE) { + if (pCRTC->pPort->TMDSType == TMDS_INT) { + tmp = INREG(RADEON_FP_GEN_CNTL); + tmp &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); + OUTREG(RADEON_FP_GEN_CNTL, tmp); + save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); + } else if (pCRTC->pPort->TMDSType == TMDS_EXT) { + tmp = INREG(RADEON_FP2_GEN_CNTL); + tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); + OUTREG(RADEON_FP2_GEN_CNTL, tmp); + save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); + } + } + + if (pCRTC->pPort->MonType == MT_LCD || + (pCRTC->pPort->MonType == NONE && pCRTC->pPort->ConnectorType == CONNECTOR_PROPRIETARY)) { + tmp = INREG(RADEON_LVDS_GEN_CNTL); + tmp |= (RADEON_LVDS_ON | RADEON_LVDS_DISPLAY_DIS); + tmp &= ~(RADEON_LVDS_BLON); + OUTREG(RADEON_LVDS_GEN_CNTL, tmp); + save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_DISPLAY_DIS); + save->lvds_gen_cntl &= ~(RADEON_LVDS_BLON); + } + } + pCRTC->IsActive = bEnable; +} + +/* 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; + + if (pRADEONEnt->pSecondaryScrn) { + if (info->IsSecondary) return; + info2 = RADEONPTR(pRADEONEnt->pSecondaryScrn); + } else if (info->Clone) 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->Clone) + mode2 = info->CurCloneMode; + 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 ((info->ChipFamily == CHIP_FAMILY_RV100) || + (info->ChipFamily == CHIP_FAMILY_RV200) || + (info->ChipFamily == CHIP_FAMILY_RV250) || + (info->ChipFamily == CHIP_FAMILY_RV280) || + (info->ChipFamily == CHIP_FAMILY_RS100) || + (info->ChipFamily == CHIP_FAMILY_RS200) || + (info->ChipFamily == CHIP_FAMILY_RS300)) + 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 == 2) { + 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) { + if (mode2) { + /*??some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ + if (info->ChipFamily == CHIP_FAMILY_R300) + critical_point += 0x10; + else + critical_point = 0; + } + else + 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; + + 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", + 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) { + if (info->ChipFamily == CHIP_FAMILY_R300) + critical_point2 += 0x10; + else + critical_point2 = 0; + } + + if (max_stop_req - critical_point2 < 4) critical_point2 = 0; + + } + + 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", + 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; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + static int ScreenCount = 0; + ScreenCount++; + + if (ScreenCount == 2) { + ScreenCount = 0; + return; + } + + if (!pRADEONEnt->HasSecondary || + (pRADEONEnt->HasSecondary && !info->IsSwitching) || + (info->IsSwitching && (!info->IsSecondary))) { + + if (!pRADEONEnt->HasSecondary || info->IsSwitching) ScreenCount = 0; + + switch (pRADEONEnt->Controller[0].pPort->MonType) { + case MT_LCD: + OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_DISPLAY_DIS, + ~RADEON_LVDS_DISPLAY_DIS); + break; + + case MT_CRT: + if ((info->ChipFamily == CHIP_FAMILY_R200) && + (pRADEONEnt->Controller[0].pPort->DACType == DAC_TVDAC)) + OUTREGP(RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); + + break; + case MT_DFP: + if (pRADEONEnt->Controller[0].pPort->TMDSType == TMDS_EXT) + OUTREGP(RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); + else + OUTREGP(RADEON_FP_GEN_CNTL, RADEON_FP_BLANK_EN, ~RADEON_FP_BLANK_EN); + + break; + case MT_NONE: + default: + break; + } + + OUTREGP (RADEON_CRTC_EXT_CNTL, + RADEON_CRTC_DISPLAY_DIS | + RADEON_CRTC_VSYNC_DIS | + RADEON_CRTC_HSYNC_DIS, + ~(RADEON_CRTC_DISPLAY_DIS | + RADEON_CRTC_VSYNC_DIS | + RADEON_CRTC_HSYNC_DIS)); + + if (!info->HasCRTC2) return; + + if (info->Clone) { + switch (pRADEONEnt->Controller[1].pPort->MonType) { + case MT_LCD: + OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_DISPLAY_DIS, + ~RADEON_LVDS_DISPLAY_DIS); + break; + + case MT_CRT: + if ((info->ChipFamily == CHIP_FAMILY_R200) && + (pRADEONEnt->Controller[1].pPort->DACType == DAC_TVDAC)) + OUTREGP(RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); + break; + + case MT_DFP: + if (pRADEONEnt->Controller[1].pPort->TMDSType == TMDS_EXT) + OUTREGP(RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); + else + OUTREGP(RADEON_FP_GEN_CNTL, RADEON_FP_BLANK_EN, ~RADEON_FP_BLANK_EN); + break; + + case MT_NONE: + default: + break; + } + OUTREGP (RADEON_CRTC2_GEN_CNTL, + RADEON_CRTC2_DISP_DIS | + RADEON_CRTC2_VSYNC_DIS | + RADEON_CRTC2_HSYNC_DIS, + ~(RADEON_CRTC2_DISP_DIS | + RADEON_CRTC2_VSYNC_DIS | + RADEON_CRTC2_HSYNC_DIS)); + } + } + + if ((pRADEONEnt->HasSecondary && !info->IsSwitching) || + (info->IsSwitching && info->IsSecondary)) { + + if (info->IsSwitching) ScreenCount = 0; + + switch (pRADEONEnt->Controller[1].pPort->MonType) { + case MT_LCD: + OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_DISPLAY_DIS, + ~RADEON_LVDS_DISPLAY_DIS); + break; + + case MT_CRT: + if ((info->ChipFamily == CHIP_FAMILY_R200) && + (pRADEONEnt->Controller[1].pPort->DACType == DAC_TVDAC)) + OUTREGP(RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); + + break; + case MT_DFP: + if (pRADEONEnt->Controller[1].pPort->TMDSType == TMDS_EXT) + OUTREGP(RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); + else + OUTREGP(RADEON_FP_GEN_CNTL, RADEON_FP_BLANK_EN, ~RADEON_FP_BLANK_EN); + + break; + case MT_NONE: + default: + break; + } + + OUTREGP (RADEON_CRTC2_GEN_CNTL, + RADEON_CRTC2_DISP_DIS | + RADEON_CRTC2_VSYNC_DIS | + RADEON_CRTC2_HSYNC_DIS, + ~(RADEON_CRTC2_DISP_DIS | + RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS)); + } +} + +/* Unblank screen. */ +void RADEONUnblank (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + unsigned char *RADEONMMIO = info->MMIO; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + static int ScreenCount = 0; + ScreenCount++; + + /*__asm__ __volatile__ ("int $3");*/ + + if (!pRADEONEnt->HasSecondary || + ScreenCount == 2 || + (info->IsSwitching && !info->IsSecondary)) { + + if (ScreenCount == 1) ScreenCount = 0; + + switch (pRADEONEnt->Controller[0].pPort->MonType) { + case MT_LCD: + OUTREGP (RADEON_LVDS_GEN_CNTL, 0, ~RADEON_LVDS_DISPLAY_DIS); + break; + + case MT_CRT: + if ((info->ChipFamily == CHIP_FAMILY_R200) && + (pRADEONEnt->Controller[0].pPort->DACType == DAC_TVDAC)) + OUTREGP(RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); + break; + + case MT_DFP: + if (pRADEONEnt->Controller[0].pPort->TMDSType == TMDS_EXT) + OUTREGP(RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); + else + OUTREGP(RADEON_FP_GEN_CNTL, 0, ~RADEON_FP_BLANK_EN); + break; + + case MT_NONE: + default: + break; + } + + OUTREGP (RADEON_CRTC_EXT_CNTL, + 0, + ~(RADEON_CRTC_DISPLAY_DIS | + RADEON_CRTC_VSYNC_DIS | + RADEON_CRTC_HSYNC_DIS)); + + if (!info->HasCRTC2) return; + + if (info->Clone) { + switch (pRADEONEnt->Controller[1].pPort->MonType) { + case MT_LCD: + OUTREGP (RADEON_LVDS_GEN_CNTL, 0, ~RADEON_LVDS_DISPLAY_DIS); + break; + + case MT_CRT: + if ((info->ChipFamily == CHIP_FAMILY_R200) && + (pRADEONEnt->Controller[1].pPort->DACType == DAC_TVDAC)) + OUTREGP(RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); + break; + + case MT_DFP: + if (pRADEONEnt->Controller[1].pPort->TMDSType == TMDS_EXT) + OUTREGP(RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); + else + OUTREGP(RADEON_FP_GEN_CNTL, 0, ~RADEON_FP_BLANK_EN); + break; + + case MT_NONE: + default: + break; + } + + OUTREGP (RADEON_CRTC2_GEN_CNTL, 0, + ~(RADEON_CRTC2_DISP_DIS | + RADEON_CRTC2_VSYNC_DIS | + RADEON_CRTC2_HSYNC_DIS)); + } + } + + if (ScreenCount == 2 || + (info->IsSwitching && info->IsSecondary)) { + + ScreenCount = 0; + + switch (pRADEONEnt->Controller[1].pPort->MonType) { + case MT_LCD: + OUTREGP (RADEON_LVDS_GEN_CNTL, 0, ~RADEON_LVDS_DISPLAY_DIS); + break; + + case MT_CRT: + if ((info->ChipFamily == CHIP_FAMILY_R200) && + (pRADEONEnt->Controller[1].pPort->DACType == DAC_TVDAC)) + OUTREGP(RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); + break; + + case MT_DFP: + if (pRADEONEnt->Controller[1].pPort->TMDSType == TMDS_EXT) + OUTREGP(RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); + else + OUTREGP(RADEON_FP_GEN_CNTL, 0, ~RADEON_FP_BLANK_EN); + + break; + case MT_NONE: + default: + break; + } + + OUTREGP (RADEON_CRTC2_GEN_CNTL, + 0, + ~(RADEON_CRTC2_DISP_DIS | + RADEON_CRTC2_VSYNC_DIS | + RADEON_CRTC2_HSYNC_DIS)); + + } +} + +/* 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; + +#ifdef XF86DRI + if (info->CPStarted) DRILock(pScrn->pScreen, 0); +#endif + + if (info->accelOn) info->accel->Sync(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->Clone) + 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->Clone) + 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->Clone) + 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->Clone) + 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->Controller[1].pPort->DACType == DAC_PRIMARY)); + } + } else { + if (info->Clone) { + if (info->CloneType == 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->CloneType == MT_CRT) { + RADEONDacPowerSet(pScrn, TRUE, (pRADEONEnt->Controller[1].pPort->DACType == DAC_PRIMARY)); + } + } + 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->Clone) { + RADEONDacPowerSet(pScrn, TRUE, (pRADEONEnt->Controller[0].pPort->DACType == DAC_PRIMARY)); + } 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->Controller[1].pPort->DACType == DAC_PRIMARY)); + } + } else { + if (info->Clone) { + if(info->CloneType == 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->CloneType == MT_CRT) { + RADEONDacPowerSet(pScrn, FALSE, (pRADEONEnt->Controller[1].pPort->DACType == DAC_PRIMARY)); + } + } + 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(RADEON_PIXCLKS_CNTL, tmpPixclksCntl); + } + } else if (info->DisplayType == MT_CRT) { + if ((pRADEONEnt->HasSecondary) || info->Clone) { + RADEONDacPowerSet(pScrn, FALSE, (pRADEONEnt->Controller[0].pPort->DACType == DAC_PRIMARY)); + } 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 +} --- xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h.new_chips 2004-05-10 09:42:44.000000000 -0400 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h 2004-05-15 22:09:30.000000000 -0400 @@ -406,11 +406,21 @@ # define RADEON_DAC_PDWN_G (1 << 17) # define RADEON_DAC_PDWN_B (1 << 18) #define RADEON_TV_DAC_CNTL 0x088c +# define RADEON_TV_DAC_NBLANK (1 << 0) +# define RADEON_TV_DAC_NHOLD (1 << 1) # define RADEON_TV_DAC_STD_MASK 0x0300 +# define RADEON_TV_DAC_STD_PS2 0x0200 # define RADEON_TV_DAC_BGSLEEP (1 << 6) +# define RADEON_TV_DAC_BGADJ_MASK (0xf << 16) +# define RADEON_TV_DAC_DACADJ_MASK (0xf << 20) # define RADEON_TV_DAC_RDACPD (1 << 24) # define RADEON_TV_DAC_GDACPD (1 << 25) # define RADEON_TV_DAC_BDACPD (1 << 26) +# define R420_TV_DAC_DACADJ_MASK (0x1f << 20) +# define R420_TV_DAC_RDACPD (1 << 25) +# define R420_TV_DAC_GDACPD (1 << 26) +# define R420_TV_DAC_BDACPD (1 << 27) +# define R420_TV_DAC_TVENABLE (1 << 28) #define RADEON_DISP_HW_DEBUG 0x0d14 # define RADEON_CRT2_DISP1_SEL (1 << 5) #define RADEON_DISP_OUTPUT_CNTL 0x0d64 @@ -418,6 +428,9 @@ # define RADEON_DISP_DAC2_SOURCE_MASK 0x0c # define RADEON_DISP_DAC_SOURCE_CRTC2 0x01 # define RADEON_DISP_DAC2_SOURCE_CRTC2 0x04 +# define RADEON_DISP_TVDAC_SOURCE_MASK (0x03<<2) +# define RADEON_DISP_TVDAC_SOURCE_CRTC 0x0 +# define RADEON_DISP_TVDAC_SOURCE_CRTC2 (0x01<<2) #define RADEON_DAC_CRC_SIG 0x02cc #define RADEON_DAC_DATA 0x03c9 /* VGA */ #define RADEON_DAC_MASK 0x03c6 /* VGA */ @@ -623,10 +636,17 @@ # define RADEON_FP_V_SYNC_WID_SHIFT 0x00000010 #define RADEON_FP_GEN_CNTL 0x0284 # define RADEON_FP_FPON (1 << 0) +# define RADEON_FP_BLANK_EN (1 << 1) # define RADEON_FP_TMDS_EN (1 << 2) # define RADEON_FP_PANEL_FORMAT (1 << 3) # define RADEON_FP_EN_TMDS (1 << 7) # define RADEON_FP_DETECT_SENSE (1 << 8) +# define R200_FP_SOURCE_SEL_MASK (3 << 10) +# define R200_FP_SOURCE_SEL_CRTC1 (0 << 10) +# define R200_FP_SOURCE_SEL_CRTC2 (1 << 10) +# define R200_FP_SOURCE_SEL_RMX (2 << 10) +# define R200_FP_SOURCE_SEL_TRANS (3 << 10) +# define RADEON_FP_SEL_CRTC1 (0 << 13) # define RADEON_FP_SEL_CRTC2 (1 << 13) # define RADEON_FP_CRTC_DONT_SHADOW_HPAR (1 << 15) # define RADEON_FP_CRTC_DONT_SHADOW_VPAR (1 << 16) @@ -642,8 +662,10 @@ # define RADEON_FP2_BLANK_EN (1 << 1) # define RADEON_FP2_ON (1 << 2) # define RADEON_FP2_PANEL_FORMAT (1 << 3) -# define RADEON_FP2_SOURCE_SEL_MASK (3 << 10) -# define RADEON_FP2_SOURCE_SEL_CRTC2 (1 << 10) +# define R200_FP2_SOURCE_SEL_MASK (3 << 10) +# define R200_FP2_SOURCE_SEL_CRTC1 (0 << 10) +# define R200_FP2_SOURCE_SEL_CRTC2 (1 << 10) +# define R200_FP2_SOURCE_SEL_RMX (2 << 10) # define RADEON_FP2_SRC_SEL_MASK (3 << 13) # define RADEON_FP2_SRC_SEL_CRTC2 (1 << 13) # define RADEON_FP2_FP_POL (1 << 16) --- xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c.new_chips 2004-05-10 09:42:44.000000000 -0400 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c 2004-05-18 07:12:06.000000000 -0400 @@ -90,57 +90,12 @@ #include "fbdevhw.h" #include "vgaHW.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); 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); - -typedef enum { - OPTION_NOACCEL, - OPTION_SW_CURSOR, - OPTION_DAC_6BIT, - OPTION_DAC_8BIT, -#ifdef XF86DRI - OPTION_IS_PCI, - OPTION_BUS_TYPE, - OPTION_CP_PIO, - OPTION_USEC_TIMEOUT, - OPTION_AGP_MODE, - OPTION_AGP_FW, - OPTION_GART_SIZE, - OPTION_RING_SIZE, - OPTION_BUFFER_SIZE, - OPTION_DEPTH_MOVE, - OPTION_PAGE_FLIP, - OPTION_NO_BACKBUFFER, -#endif - OPTION_PANEL_OFF, - OPTION_DDC_MODE, - OPTION_MONITOR_LAYOUT, - OPTION_IGNORE_EDID, - OPTION_CRTC2_OVERLAY, - OPTION_CLONE_MODE, - OPTION_CLONE_HSYNC, - OPTION_CLONE_VREFRESH, - OPTION_FBDEV, - OPTION_VIDEO_KEY, - OPTION_DISP_PRIORITY, - OPTION_PANEL_SIZE, - OPTION_MIN_DOTCLOCK -} RADEONOpts; const OptionInfoRec RADEONOptions[] = { { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, @@ -175,6 +130,9 @@ { OPTION_DISP_PRIORITY, "DisplayPriority", OPTV_ANYSTR, {0}, FALSE }, { OPTION_PANEL_SIZE, "PanelSize", OPTV_ANYSTR, {0}, FALSE }, { OPTION_MIN_DOTCLOCK, "ForceMinDotClock", OPTV_FREQ, {0}, FALSE }, + { OPTION_REVERSE_DISPLAY,"ReverseDisplay", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_NOBIOS, "NoBIOS", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_REF_CLOCK, "RefClock", OPTV_INTEGER, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; @@ -388,24 +346,6 @@ {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, 0x400f7/*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*/ -}; - extern int gRADEONEntityIndex; struct RADEONInt10Save { @@ -417,7 +357,7 @@ static Bool RADEONMapMMIO(ScrnInfoPtr pScrn); static Bool RADEONUnmapMMIO(ScrnInfoPtr pScrn); -static RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn) +RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn) { DevUnion *pPriv; RADEONInfoPtr info = RADEONPTR(pScrn); @@ -679,78 +619,6 @@ } } -/* 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->Clone) - 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->Clone) - 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) { @@ -767,850 +635,10 @@ return (n + (d / 2)) / d; } -static RADEONMonitorType RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, RADEONDDCType DDCType, xf86MonPtr* MonInfo) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - unsigned long DDCReg; - RADEONMonitorType MonType = MT_NONE; - 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; - } - - 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 ((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(1000); - - 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 ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350)) - 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(1000); - - 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 void RADEONQueryConnectedDisplays(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - const char *s; - Bool ignore_edid = FALSE, ddc_crt2_used = FALSE; - -#define RADEON_BIOS8(v) (info->VBIOS[v]) -#define RADEON_BIOS16(v) (info->VBIOS[v] | \ - (info->VBIOS[(v) + 1] << 8)) -#define RADEON_BIOS32(v) (info->VBIOS[v] | \ - (info->VBIOS[(v) + 1] << 8) | \ - (info->VBIOS[(v) + 2] << 16) | \ - (info->VBIOS[(v) + 3] << 24)) - - pRADEONEnt->MonType1 = MT_NONE; - pRADEONEnt->MonType2 = MT_NONE; - pRADEONEnt->MonInfo1 = NULL; - pRADEONEnt->MonInfo2 = NULL; - pRADEONEnt->ReversedDAC = FALSE; - pRADEONEnt->ReversedTMDS = FALSE; - - /* IgnoreEDID option is different from NoDDC 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. - */ - 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. - */ - - /* current monitor mapping scheme: - * Two displays connected: - * Primary Port: - * CRTC1 -> FP/TMDS -> DVI port -> TMDS panel --> Primary or - * CRTC1 -> FP/LVDS -> Int. LCD -> LVDS panel --> Primary or - * CRTC1 -> TV DAC -> DVI port -> CRT monitor --> Primary - * - * Secondary Port - * CRTC2 -> CRT DAC -> VGA port -> CRT monitor --> Secondary or - * CRTC2 -> FP2/Ext. -> DVI port -> TMDS panel --> Secondary - * - * Only DVI (or Int. LDC) conneced: - * CRTC1 -> FP/TMDS -> DVI port -> TMDS panel --> Primary or - * CRTC1 -> FP/LVDS -> Int. LCD -> LVDS panel --> Primary or - * CRTC1 -> TV DAC -> DVI port -> CRT monitor --> Primary - * - * Only VGA (can be DVI on some dual-DVI boards) connected: - * CRTC1 -> CRT DAC -> VGA port -> CRT monitor --> Primary or - * CRTC1 -> FP2/Ext. -> DVI port -> TMDS panel --> Primary (not supported) - * - * Note, this is different from Windows scheme where - * if a digital panel is connected to DVI port, DVI will be the 1st port - * otherwise, VGA port will be treated as 1st port - * - * Here we always treat DVI port as primary if both ports are connected. - * When only one port is connected, it will be treated as - * primary regardless which port or what type of display is involved. - */ - - if ((s = xf86GetOptValString(info->Options, OPTION_MONITOR_LAYOUT))) { - char s1[5], s2[5]; - int i = 0, second = 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++; - if (i == 4) break; - } - } while(*s++); - s2[i] = '\0'; - - if (strcmp(s1, "NONE") == 0) - pRADEONEnt->MonType1 = MT_NONE; - else if (strcmp(s1, "CRT") == 0) - pRADEONEnt->MonType1 = MT_CRT; - else if (strcmp(s1, "TMDS") == 0) - pRADEONEnt->MonType1 = MT_DFP; - else if (strcmp(s1, "LVDS") == 0) - pRADEONEnt->MonType1 = MT_LCD; - else - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Invalid Monitor type specified for 1st port \n"); - if (strcmp(s2, "NONE") == 0) - pRADEONEnt->MonType2 = MT_NONE; - else if (strcmp(s2, "CRT") == 0) - pRADEONEnt->MonType2 = MT_CRT; - else if (strcmp(s2, "TMDS") == 0) - pRADEONEnt->MonType2 = MT_DFP; - else if (strcmp(s2, "LVDS") == 0) - pRADEONEnt->MonType2 = MT_LCD; - else - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Invalid Monitor type specified for 2nd port \n"); - - if (!ignore_edid) { - if (pRADEONEnt->MonType1) /* assuming the first port using DDC_DVI */ - if(!RADEONDisplayDDCConnected(pScrn, DDC_DVI, &pRADEONEnt->MonInfo1)) { - RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->MonInfo1); - ddc_crt2_used = TRUE; - } - if (pRADEONEnt->MonType2) { /* assuming the second port using DDC_VGA/DDC_CRT2 */ - if(!RADEONDisplayDDCConnected(pScrn, DDC_VGA, &pRADEONEnt->MonInfo2)) - if (!ddc_crt2_used) - RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->MonInfo2); - } - } - - if (!pRADEONEnt->MonType1) { - if (pRADEONEnt->MonType2) { - pRADEONEnt->MonType1 = pRADEONEnt->MonType2; - pRADEONEnt->MonInfo1 = pRADEONEnt->MonInfo2; - } else { - pRADEONEnt->MonType1 = MT_CRT; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "No valid monitor specified, force to CRT on 1st port\n"); - } - pRADEONEnt->MonType2 = MT_NONE; - pRADEONEnt->MonInfo2 = NULL; - } - } else { - /* Auto detection */ - int i; - CARD32 tmp; - - /* Old single head radeon cards */ - if(!info->HasCRTC2) { - if((pRADEONEnt->MonType1 = RADEONDisplayDDCConnected(pScrn, DDC_DVI, &pRADEONEnt->MonInfo1))); - else if((pRADEONEnt->MonType1 = RADEONDisplayDDCConnected(pScrn, DDC_VGA, &pRADEONEnt->MonInfo1))); - else if((pRADEONEnt->MonType1 = RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->MonInfo1))); - else if (pInt10) { - if (xf86LoadSubModule(pScrn, "vbe")) { - vbeInfoPtr pVbe; - pVbe = VBEInit(pInt10, info->pEnt->index); - if (pVbe) { - for (i = 0; i < 5; i++) { - pRADEONEnt->MonInfo1 = vbeDoEDID(pVbe, NULL); - } - if (pRADEONEnt->MonInfo1->rawData[0x14] & 0x80) - pRADEONEnt->MonType1 = MT_DFP; - else pRADEONEnt->MonType1 = MT_CRT; - } - } - } else - pRADEONEnt->MonType1 = MT_CRT; - - pRADEONEnt->HasSecondary = FALSE; - if (!ignore_edid) { - if (pRADEONEnt->MonInfo1) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor1 EDID data ---------------------------\n"); - xf86PrintEDID( pRADEONEnt->MonInfo1 ); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor1 EDID data --------------------\n"); - } - } - return; - } - - /* Normally the port uses DDC_DVI connected with TVDAC, - * But this is not true for OEM cards which have TVDAC and CRT DAC reversed. - * If that's the case, we need also reverse the port arrangement. - * BIOS settings are supposed report this correctly, work fine for all cards tested. - * But there may be some exceptions, in that case, user can reverse their monitor - * definition in config file to correct the problem. - */ - if (info->VBIOS && (tmp = RADEON_BIOS16(info->FPBIOSstart + 0x50))) { - for (i = 1; i < 4; i++) { - unsigned int tmp0; - if (!RADEON_BIOS8(tmp + i*2) && i > 1) break; - tmp0 = RADEON_BIOS16(tmp + i*2); - if ((!(tmp0 & 0x01)) && (((tmp0 >> 8) & 0xf) == DDC_DVI)) { - pRADEONEnt->ReversedDAC = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reversed DACs detected\n"); - } - if ((((tmp0 >> 8) & 0x0f) == DDC_DVI ) && ((tmp0 >> 4) & 0x1)) { - pRADEONEnt->ReversedTMDS = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reversed TMDS detected\n"); - } - } - } - - /* Primary Head (DVI or Laptop Int. panel)*/ - /* A ddc capable display connected on DVI port */ - if((pRADEONEnt->MonType1 = RADEONDisplayDDCConnected(pScrn, DDC_DVI, &pRADEONEnt->MonInfo1))); - else if((pRADEONEnt->MonType1 = - RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->MonInfo1))) { - ddc_crt2_used = TRUE; - } else if ((info->IsMobility) && - (info->VBIOS && (INREG(RADEON_BIOS_4_SCRATCH) & 4))) { - /* non-DDC laptop panel connected on primary */ - pRADEONEnt->MonType1 = MT_LCD; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Non-DDC laptop panel detected\n"); - } else { - /* CRT on DVI, TODO: not reliable, make it always return false for now*/ - pRADEONEnt->MonType1 = RADEONCrtIsPhysicallyConnected(pScrn, pRADEONEnt->ReversedDAC); - } - - /* Secondary Head (mostly VGA, can be DVI on some OEM boards)*/ - if((pRADEONEnt->MonType2 = - RADEONDisplayDDCConnected(pScrn, DDC_VGA, &pRADEONEnt->MonInfo2))); - else if(!ddc_crt2_used) - pRADEONEnt->MonType2 = - RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->MonInfo2); - if (!pRADEONEnt->MonType2) - pRADEONEnt->MonType2 = RADEONCrtIsPhysicallyConnected(pScrn, !pRADEONEnt->ReversedDAC); - - if(pRADEONEnt->ReversedTMDS) { - /* always keep internal TMDS as primary head */ - if (pRADEONEnt->MonType1 == MT_DFP || - pRADEONEnt->MonType2 == MT_DFP) { - int tmp1 = pRADEONEnt->MonType1; - xf86MonPtr MonInfo = pRADEONEnt->MonInfo1; - pRADEONEnt->MonInfo1 = pRADEONEnt->MonInfo2; - pRADEONEnt->MonInfo2 = MonInfo; - pRADEONEnt->MonType1 = pRADEONEnt->MonType2; - pRADEONEnt->MonType2 = tmp1; - if ((pRADEONEnt->MonType1 == MT_CRT) || - (pRADEONEnt->MonType2 == MT_CRT)) { - pRADEONEnt->ReversedDAC ^= 1; - } - } - } - - /* no display detected on DVI port*/ - if (pRADEONEnt->MonType1 == MT_NONE) { - if (pRADEONEnt->MonType2 != MT_NONE) { - /* Only one detected on VGA, let it to be primary */ - pRADEONEnt->MonType1 = pRADEONEnt->MonType2; - pRADEONEnt->MonInfo1 = pRADEONEnt->MonInfo2; - pRADEONEnt->MonType2 = MT_NONE; - pRADEONEnt->MonInfo2 = NULL; - } else { - /* Non detected, Default to a CRT connected */ - pRADEONEnt->MonType1 = MT_CRT; - } - } - } - - if(s) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Displays Configured by MonitorLayout: \n\tMonitor1--Type %d, Monitor2--Type %d\n\n", - pRADEONEnt->MonType1, pRADEONEnt->MonType2); - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Displays Detected: Monitor1--Type %d, Monitor2--Type %d\n\n", - pRADEONEnt->MonType1, pRADEONEnt->MonType2); - } - - if(ignore_edid) { - pRADEONEnt->MonInfo1 = NULL; - pRADEONEnt->MonInfo2 = NULL; - } - - if (!ignore_edid) { - if (pRADEONEnt->MonInfo1) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor1 EDID data ---------------------------\n"); - xf86PrintEDID( pRADEONEnt->MonInfo1 ); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor1 EDID data --------------------\n"); - } - if (pRADEONEnt->MonInfo2) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor2 EDID data ---------------------------\n"); - xf86PrintEDID( pRADEONEnt->MonInfo2 ); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor2 EDID data --------------------\n"); - } - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\n"); - - info->OverlayOnCRTC2 = FALSE; - if (xf86ReturnOptValBool(info->Options, OPTION_CRTC2_OVERLAY, FALSE)) { - info->OverlayOnCRTC2 = TRUE; - } - - if (pRADEONEnt->MonType2 == MT_NONE) - pRADEONEnt->HasSecondary = FALSE; -} - - -/* Read the Video BIOS block and the FP registers (if applicable). */ -static Bool RADEONGetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned long tmp, i; - - if (!(info->VBIOS = xalloc(RADEON_VBIOS_SIZE))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Cannot allocate space for hold Video BIOS!\n"); - return FALSE; - } - - if (pInt10) { - info->BIOSAddr = pInt10->BIOSseg << 4; - (void)memcpy(info->VBIOS, xf86int10Addr(pInt10, info->BIOSAddr), - RADEON_VBIOS_SIZE); - } else { - xf86ReadPciBIOS(0, info->PciTag, 0, info->VBIOS, RADEON_VBIOS_SIZE); - if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Video BIOS not detected in PCI space!\n"); - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Attempting to read Video BIOS from " - "legacy ISA space!\n"); - info->BIOSAddr = 0x000c0000; - xf86ReadDomainMemory(info->PciTag, info->BIOSAddr, - RADEON_VBIOS_SIZE, info->VBIOS); - } - } - - if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) { - xfree(info->VBIOS); - info->FPBIOSstart = 0; - info->VBIOS = NULL; - info->BIOSAddr = 0x00000000; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Video BIOS not found!\n"); - } else - info->FPBIOSstart = RADEON_BIOS16(0x48); - info->OverlayOnCRTC2 = FALSE; - - if (!info->IsSecondary) - RADEONQueryConnectedDisplays(pScrn, pInt10); - - { - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - - info->Clone = FALSE; - info->CloneType = MT_NONE; - - if(info->HasCRTC2) { - if(info->IsSecondary) { - info->DisplayType = (RADEONMonitorType)pRADEONEnt->MonType2; - if(info->DisplayType == MT_NONE) return FALSE; - } else { - info->DisplayType = (RADEONMonitorType)pRADEONEnt->MonType1; - - if(!pRADEONEnt->HasSecondary) { - info->CloneType = (RADEONMonitorType)pRADEONEnt->MonType2; - if (info->CloneType != MT_NONE) - info->Clone = TRUE; - } - } - } else { - info->DisplayType = (RADEONMonitorType)pRADEONEnt->MonType1; - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s Display == Type %d\n", - (info->IsSecondary ? "Secondary" : "Primary"), - info->DisplayType); - - if (info->Clone) - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clone Display == Type %d\n", - info->CloneType); - - info->HBlank = 0; - info->HOverPlus = 0; - info->HSyncWidth = 0; - info->VBlank = 0; - info->VOverPlus = 0; - info->VSyncWidth = 0; - info->DotClock = 0; - info->UseBiosDividers = FALSE; - - if (info->DisplayType == MT_LCD && info->VBIOS && - !(xf86GetOptValString(info->Options, OPTION_PANEL_SIZE))) { - tmp = RADEON_BIOS16(info->FPBIOSstart + 0x40); - if (!tmp) { - info->PanelPwrDly = 200; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No Panel Info Table found in BIOS!\n"); - } else { - char stmp[30]; - int tmp0; - - for (i = 0; i < 24; i++) - stmp[i] = RADEON_BIOS8(tmp+i+1); - stmp[24] = 0; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Panel ID string: %s\n", stmp); - - info->PanelXRes = RADEON_BIOS16(tmp+25); - info->PanelYRes = RADEON_BIOS16(tmp+27); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel Size from BIOS: %dx%d\n", - info->PanelXRes, info->PanelYRes); - - info->PanelPwrDly = RADEON_BIOS16(tmp+44); - if (info->PanelPwrDly > 2000 || info->PanelPwrDly < 0) - info->PanelPwrDly = 2000; - - /* some panels only work well with certain divider combinations. - */ - info->RefDivider = RADEON_BIOS16(tmp+46); - info->PostDivider = RADEON_BIOS8(tmp+48); - info->FeedbackDivider = RADEON_BIOS16(tmp+49); - if ((info->RefDivider != 0) && - (info->FeedbackDivider > 3)) { - info->UseBiosDividers = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "BIOS provided dividers will be used.\n"); - } - - /* We don't use a while loop here just in case we have a corrupted BIOS image. - The max number of table entries is 23 at present, but may grow in future. - To ensure it works with future revisions we loop it to 32. - */ - for (i = 0; i < 32; i++) { - tmp0 = RADEON_BIOS16(tmp+64+i*2); - if (tmp0 == 0) break; - if ((RADEON_BIOS16(tmp0) == info->PanelXRes) && - (RADEON_BIOS16(tmp0+2) == info->PanelYRes)) { - info->HBlank = (RADEON_BIOS16(tmp0+17) - - RADEON_BIOS16(tmp0+19)) * 8; - info->HOverPlus = (RADEON_BIOS16(tmp0+21) - - RADEON_BIOS16(tmp0+19) - 1) * 8; - info->HSyncWidth = RADEON_BIOS8(tmp0+23) * 8; - info->VBlank = (RADEON_BIOS16(tmp0+24) - - RADEON_BIOS16(tmp0+26)); - info->VOverPlus = ((RADEON_BIOS16(tmp0+28) & 0x7ff) - - RADEON_BIOS16(tmp0+26)); - info->VSyncWidth = ((RADEON_BIOS16(tmp0+28) & 0xf800) >> 11); - info->DotClock = RADEON_BIOS16(tmp0+9) * 10; - info->Flags = 0; - } - } - - if (info->DotClock == 0) { - DisplayModePtr tmp_mode = NULL; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "No valid timing info from BIOS.\n"); - /* 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. - */ - 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->MonInfo1) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Panel size is not correctly detected.\n" - "Please try to use PanelSize option for correct settings.\n"); - return FALSE; - } - } - } - } - } - - if (info->VBIOS) { - tmp = RADEON_BIOS16(info->FPBIOSstart + 0x30); - info->sclk = RADEON_BIOS16(tmp + 8) / 100.0; - info->mclk = RADEON_BIOS16(tmp + 10) / 100.0; - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No valid info for SCLK/MCLK for display bandwidth calculation.\n"); - info->sclk = 200.00; - info->mclk = 200.00; - } - - return TRUE; -} - +/* This is intended to be used when there is no BIOS info available for PLLs + * Doesn't seem to work well with normal PC cards, keep it to powerpc for now. + */ +#if defined(__powerpc__) static Bool RADEONProbePLLParameters(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); @@ -1722,121 +750,62 @@ return TRUE; } +#endif -static void RADEONGetTMDSInfo(ScrnInfoPtr pScrn) +static void RADEONGetClockInfo(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); - CARD32 tmp; - int i, n; - - for (i=0; i<4; i++) { - info->tmds_pll[i].value = 0; - info->tmds_pll[i].freq = 0; - } - - if (info->VBIOS) { - tmp = RADEON_BIOS16(info->FPBIOSstart + 0x34); - if (tmp) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "DFP table revision: %d\n", RADEON_BIOS8(tmp)); - if (RADEON_BIOS8(tmp) == 3) { - n = RADEON_BIOS8(tmp + 5) + 1; - if (n > 4) n = 4; - for (i=0; itmds_pll[i].value = RADEON_BIOS32(tmp+i*10+0x08); - info->tmds_pll[i].freq = RADEON_BIOS16(tmp+i*10+0x10); - } - return; + RADEONInfoPtr info = RADEONPTR (pScrn); + RADEONPLLPtr pll = &info->pll; + double min_dotclock; + + if (RADEONGetClockInfoFromBIOS(pScrn)) { + if (pll->reference_div < 2) { + /* retrive it from register setting for fitting into current PLL algorithm. + We'll probably need a new routine to calculate the best ref_div from BIOS + provided min_input_pll and max_input_pll + */ + CARD32 tmp; + tmp = INPLL(pScrn, RADEON_PPLL_REF_DIV); + if (IS_R300_VARIANT || + (info->ChipFamily == CHIP_FAMILY_RS300)) { + pll->reference_div = (tmp & R300_PPLL_REF_DIV_ACC_MASK) >> R300_PPLL_REF_DIV_ACC_SHIFT; + } else { + pll->reference_div = tmp & RADEON_PPLL_REF_DIV_MASK; } - /* revision 4 has some problem as it appears in RV280, - comment it off for new, use default instead */ - /* - else if (RADEON_BIOS8(tmp) == 4) { - int stride = 0; - n = RADEON_BIOS8(tmp + 5) + 1; - if (n > 4) n = 4; - for (i=0; itmds_pll[i].value = RADEON_BIOS32(tmp+stride+0x08); - info->tmds_pll[i].freq = RADEON_BIOS16(tmp+stride+0x10); - if (i == 0) stride += 10; - else stride += 6; - } - return; - } - */ + if (pll->reference_div < 2) pll->reference_div = 12; } - } - - 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; - } -} - -/* Read PLL parameters from BIOS block. Default to typical values if - * there is no BIOS. - */ -static Bool RADEONGetPLLParameters(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONPLLPtr pll = &info->pll; - CARD16 bios_header; - CARD16 pll_info_block; - double min_dotclock; - - if (!info->VBIOS) { - - pll->min_pll_freq = 12500; - pll->max_pll_freq = 35000; + + } else { + xf86DrvMsg (pScrn->scrnIndex, X_WARNING, + "Video BIOS not detected, using default clock settings!\n"); + if (!xf86GetOptValInteger (info->Options, OPTION_REF_CLOCK, + (int *) &(pll->reference_freq))) { +#if defined(__powerpc__) + if (RADEONProbePLLParameters(pScrn)) return; +#endif + if (info->IsIGP) + pll->reference_freq = 1432; + else + pll->reference_freq = 2700; + } - if (!RADEONProbePLLParameters(pScrn)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Video BIOS not detected, using default PLL parameters!\n"); + pll->reference_div = 12; + pll->min_pll_freq = 12500; + pll->max_pll_freq = 35000; + pll->xclk = 10300; - switch (info->Chipset) { - case PCI_CHIP_R200_QL: - case PCI_CHIP_R200_QN: - case PCI_CHIP_R200_QO: - case PCI_CHIP_R200_BB: - pll->reference_freq = 2700; - pll->reference_div = 12; - pll->xclk = 27500; - break; - case PCI_CHIP_RV250_Id: - case PCI_CHIP_RV250_Ie: - case PCI_CHIP_RV250_If: - case PCI_CHIP_RV250_Ig: - pll->reference_freq = 2700; - pll->reference_div = 12; - pll->xclk = 24975; - break; - case PCI_CHIP_RV200_QW: - pll->reference_freq = 2700; - pll->reference_div = 12; - pll->xclk = 23000; - break; - default: - pll->reference_freq = 2700; - pll->reference_div = 67; - pll->xclk = 16615; - break; - } - } - } else { - bios_header = RADEON_BIOS16(0x48); - pll_info_block = RADEON_BIOS16(bios_header + 0x30); - RADEONTRACE(("Header at 0x%04x; PLL Information at 0x%04x\n", - bios_header, pll_info_block)); - - pll->reference_freq = RADEON_BIOS16(pll_info_block + 0x0e); - pll->reference_div = RADEON_BIOS16(pll_info_block + 0x10); - pll->min_pll_freq = RADEON_BIOS32(pll_info_block + 0x12); - pll->max_pll_freq = RADEON_BIOS32(pll_info_block + 0x16); - pll->xclk = RADEON_BIOS16(pll_info_block + 0x08); + info->sclk = 200.00; + info->mclk = 200.00; } + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "PLL parameters: rf=%d rd=%d min=%ld max=%ld; xclk=%d\n", + pll->reference_freq, + pll->reference_div, + pll->min_pll_freq, pll->max_pll_freq, pll->xclk); + /* (Some?) Radeon BIOSes seem too lie about their minimum dot * clocks. Allow users to override the detected minimum dot clock * value (e.g., and allow it to be suitable for TV sets). @@ -1856,10 +825,9 @@ pll->min_pll_freq = min_dotclock * 1000; } } - - return TRUE; } + /* This is called by RADEONPreInit to set up the default visual */ static Bool RADEONPreInitVisual(ScrnInfoPtr pScrn) { @@ -1962,9 +930,7 @@ info->IsDDR = FALSE; tmp = INREG(RADEON_MEM_CNTL); - if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350)) { + if (IS_R300_VARIANT) { tmp &= R300_MEM_NUM_CHANNELS_MASK; switch (tmp) { case 0: info->RamWidth = 64; break; @@ -2035,6 +1001,8 @@ info->HasCRTC2 = TRUE; info->IsMobility = FALSE; info->IsIGP = FALSE; + info->BusType = -1; + info->HasSingleDAC = FALSE; switch (info->Chipset) { case PCI_CHIP_RADEON_LY: case PCI_CHIP_RADEON_LZ: @@ -2094,9 +1062,12 @@ break; case PCI_CHIP_RS300_5835: + case PCI_CHIP_RS350_7835: info->IsMobility = TRUE; case PCI_CHIP_RS300_5834: + case PCI_CHIP_RS350_7834: info->ChipFamily = CHIP_FAMILY_RS300; + info->HasSingleDAC = TRUE; info->IsIGP = TRUE; break; @@ -2148,6 +1119,49 @@ info->ChipFamily = CHIP_FAMILY_R350; break; + case PCI_CHIP_RV380_3150: + case PCI_CHIP_RV380_3154: + info->IsMobility = TRUE; + case PCI_CHIP_RV380_3E50: + case PCI_CHIP_RV380_3E54: + info->ChipFamily = CHIP_FAMILY_RV380; + info->BusType = BUS_TYPE_PCIE; + break; + + case PCI_CHIP_RV370_5460: + case PCI_CHIP_RV370_5464: + info->IsMobility = TRUE; + case PCI_CHIP_RV370_5B60: + case PCI_CHIP_RV370_5B64: + case PCI_CHIP_RV370_5B65: + info->ChipFamily = CHIP_FAMILY_RV380; + info->BusType = BUS_TYPE_PCIE; + break; + + case PCI_CHIP_R420_JN: + info->IsMobility = TRUE; + case PCI_CHIP_R420_JH: + case PCI_CHIP_R420_JI: + case PCI_CHIP_R420_JJ: + case PCI_CHIP_R420_JK: + case PCI_CHIP_R420_JL: + case PCI_CHIP_R420_JM: + case PCI_CHIP_R420_JP: + info->ChipFamily = CHIP_FAMILY_R420; + break; + + case PCI_CHIP_R423_UH: + case PCI_CHIP_R423_UI: + case PCI_CHIP_R423_UJ: + case PCI_CHIP_R423_UK: + case PCI_CHIP_R423_UQ: + case PCI_CHIP_R423_UR: + case PCI_CHIP_R423_UT: + case PCI_CHIP_R423_5D57: + info->ChipFamily = CHIP_FAMILY_R420; + info->BusType = BUS_TYPE_PCIE; + break; + default: /* Original Radeon/7200 */ info->ChipFamily = CHIP_FAMILY_RADEON; @@ -2194,34 +1208,19 @@ from = X_PROBED; if (info->FBDev) pScrn->videoRam = fbdevHWGetVidmem(pScrn) / 1024; - else if ((info->ChipFamily == CHIP_FAMILY_RS100) || - (info->ChipFamily == CHIP_FAMILY_RS200) || - (info->ChipFamily == CHIP_FAMILY_RS300)) { + else if (info->IsIGP) { CARD32 tom = INREG(RADEON_NB_TOM); pScrn->videoRam = (((tom >> 16) - (tom & 0xffff) + 1) << 6); - OUTREG(RADEON_MC_FB_LOCATION, tom); - OUTREG(RADEON_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16); - OUTREG(RADEON_DISPLAY2_BASE_ADDR, (tom & 0xffff) << 16); - OUTREG(RADEON_OV0_BASE_ADDR, (tom & 0xffff) << 16); - - /* This is supposed to fix the crtc2 noise problem. - */ - OUTREG(RADEON_GRPH2_BUFFER_CNTL, - INREG(RADEON_GRPH2_BUFFER_CNTL) & ~0x7f0000); - - if ((info->ChipFamily == CHIP_FAMILY_RS100) || - (info->ChipFamily == CHIP_FAMILY_RS200)) { - /* This is to workaround the asic bug for RMX, some versions - of BIOS dosen't have this register initialized correctly. - */ - OUTREGP(RADEON_CRTC_MORE_CNTL, RADEON_CRTC_H_CUTOFF_ACTIVE_EN, - ~RADEON_CRTC_H_CUTOFF_ACTIVE_EN); - } - - } - else + } else { + /* There are different HDP mapping schemes depending on single/multi funciton setting, + * chip family, HDP mode, and generation of HDP mapping scheme. + * To make things simple, we only allow maximum 128M addressable FB. Anything more than + * 128M is configured as invisible FB to CPU that can only be accessed from chip side. + */ pScrn->videoRam = INREG(RADEON_CONFIG_MEMSIZE) / 1024; + if (pScrn->videoRam > 128*1024) pScrn->videoRam = 128*1024; + } /* Some production boards of m6 will return 0 if it's 8 MB */ if (pScrn->videoRam == 0) pScrn->videoRam = 8192; @@ -2262,8 +1261,14 @@ } pScrn->videoRam &= ~1023; info->FbMapSize = pScrn->videoRam * 1024; - xf86DrvMsg(pScrn->scrnIndex, from, - "VideoRAM: %d kByte (%d bit %s SDRAM)\n", pScrn->videoRam, info->RamWidth, info->IsDDR?"DDR":"SDR"); + if (info->IsSecondary) + xf86DrvMsg(pScrn->scrnIndex, from, + "VideoRAM used for second head: %d kByte\n", + pScrn->videoRam); + else + xf86DrvMsg(pScrn->scrnIndex, from, + "Addressable VideoRAM: %d kByte (%ld kByte total, %d-bit %s)\n", + pScrn->videoRam, INREG(RADEON_CONFIG_MEMSIZE)/1024, info->RamWidth, info->IsDDR?"DDR":"SDR"); #ifdef XF86DRI /* AGP/PCI */ @@ -2275,194 +1280,56 @@ * calling drmAgpEnable on a PCI card can cause some strange lockup * when the server restarts next time. */ - - agpCommand = pciReadLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG); - pciWriteLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG, - agpCommand | RADEON_AGP_ENABLE); - if (pciReadLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG) - & RADEON_AGP_ENABLE) { - info->IsPCI = FALSE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "AGP card detected\n"); + if (info->BusType == BUS_TYPE_PCIE) { + /* All PCIE cards use RV350 core or up, DRI is not supported for + * these cards, we don't need to worry about it here. + * For now, set IsPCI=TRUE for backward compatibility. + * NOTE: all current PCIE cards don't work with the existing AGP or PCI GART + * and shouldn't be force into AGP or PCI type if we ever want to enable DRI + */ + info->IsPCI = TRUE; } else { - info->IsPCI = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PCI card detected\n"); - } - pciWriteLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG, agpCommand); + agpCommand = pciReadLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG); + pciWriteLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG, + agpCommand | RADEON_AGP_ENABLE); + if (pciReadLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG) + & RADEON_AGP_ENABLE) { + info->IsPCI = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "AGP card detected\n"); + } else { + info->IsPCI = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PCI card detected\n"); + } + pciWriteLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG, agpCommand); - if ((s = xf86GetOptValString(info->Options, OPTION_BUS_TYPE))) { - if (strcmp(s, "AGP") == 0) { - info->IsPCI = FALSE; - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into AGP mode\n"); - } else if (strcmp(s, "PCI") == 0) { + if ((s = xf86GetOptValString(info->Options, OPTION_BUS_TYPE))) { + if (strcmp(s, "AGP") == 0) { + info->IsPCI = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into AGP mode\n"); + } else if (strcmp(s, "PCI") == 0) { + info->IsPCI = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI mode\n"); + } else if (strcmp(s, "PCIE") == 0) { + info->IsPCI = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "PCI Express not supported yet, using PCI mode\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Invalid BusType option, using detected type\n"); + } + } else if (xf86ReturnOptValBool(info->Options, OPTION_IS_PCI, FALSE)) { info->IsPCI = TRUE; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI mode\n"); - } else if (strcmp(s, "PCIE") == 0) { - info->IsPCI = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "PCI Express not supported yet, using PCI mode\n"); - } else { - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "Invalid BusType option, using detected type\n"); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "ForcePCIMode is deprecated -- " + "use BusType option instead\n"); } - } else if (xf86ReturnOptValBool(info->Options, OPTION_IS_PCI, FALSE)) { - info->IsPCI = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI mode\n"); - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "ForcePCIMode is deprecated -- " - "use BusType option instead\n"); } #endif 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) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - /* vbeInfoPtr pVbe; */ - - info->ddc1 = FALSE; - info->ddc_bios = FALSE; - if (!xf86LoadSubModule(pScrn, "ddc")) { - info->ddc2 = FALSE; - } else { - xf86LoaderReqSymLists(ddcSymbols, NULL); - info->ddc2 = TRUE; - } - - /* DDC can use I2C bus */ - /* Load I2C if we have the code to use it */ - if (info->ddc2) { - if (xf86LoadSubModule(pScrn, "i2c")) { - xf86LoaderReqSymLists(i2cSymbols,NULL); - info->ddc2 = RADEONI2cInit(pScrn); - } - else info->ddc2 = FALSE; - } -} - - -/* 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; - - /* 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; - if (info->PanelXRes < d_timings->h_active && - info->PanelYRes < d_timings->v_active) { - - 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; - } - } - } - - /* 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 = - (ddc->det_mon[j].section.d_timings.interlaced - ? V_INTERLACE - : 0); - if (ddc->det_mon[j].section.d_timings.sync == 3) { - switch (ddc->det_mon[j].section.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 size found from DDC: %dx%d\n", - info->PanelXRes, info->PanelYRes); -} - /* This function will sort all modes according to their resolution. * Highest resolution first. */ @@ -2670,7 +1537,7 @@ int maxVirtX = pScrn->virtualX; int maxVirtY = pScrn->virtualY; - if ((DisplayType != MT_CRT) && !info->IsSecondary) { + if (DisplayType != MT_CRT && !info->IsSecondary) { /* 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 @@ -2682,31 +1549,31 @@ /* Collect all of the DDC modes */ first = last = ddcModes = RADEONDDCModes(pScrn); - for (p = ddcModes; p; p = p->next) { + + for (p = ddcModes; p; p = p->next) { - /* If primary head is a flat panel, use RMX by default */ - if ((!info->IsSecondary && DisplayType != MT_CRT) && - !info->ddc_mode) { - /* These values are effective values after expansion. - * They are not really used to set CRTC registers. - */ - p->HTotal = info->PanelXRes + info->HBlank; - p->HSyncStart = info->PanelXRes + info->HOverPlus; - p->HSyncEnd = p->HSyncStart + info->HSyncWidth; - p->VTotal = info->PanelYRes + info->VBlank; - p->VSyncStart = info->PanelYRes + info->VOverPlus; - p->VSyncEnd = p->VSyncStart + info->VSyncWidth; - p->Clock = info->DotClock; + /* If primary head is a flat panel, use RMX by default */ + if ((DisplayType != MT_CRT) && (!info->ddc_mode) && !info->IsSecondary) { + /* These values are effective values after expansion. + * They are not really used to set CRTC registers. + */ + p->HTotal = info->PanelXRes + info->HBlank; + p->HSyncStart = info->PanelXRes + info->HOverPlus; + p->HSyncEnd = p->HSyncStart + info->HSyncWidth; + p->VTotal = info->PanelYRes + info->VBlank; + p->VSyncStart = info->PanelYRes + info->VOverPlus; + p->VSyncEnd = p->VSyncStart + info->VSyncWidth; + p->Clock = info->DotClock; - p->Flags |= RADEON_USE_RMX; - } + p->Flags |= RADEON_USE_RMX; + } - maxVirtX = MAX(maxVirtX, p->HDisplay); - maxVirtY = MAX(maxVirtY, p->VDisplay); - count++; + maxVirtX = MAX(maxVirtX, p->HDisplay); + maxVirtY = MAX(maxVirtY, p->VDisplay); + count++; - last = p; - } + last = p; + } /* Match up modes that are specified in the XF86Config file */ if (ppModeName[0]) { @@ -2989,6 +1856,31 @@ return count; } +static void RADEONPreInitDDC(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + /* vbeInfoPtr pVbe; */ + + info->ddc1 = FALSE; + info->ddc_bios = FALSE; + if (!xf86LoadSubModule(pScrn, "ddc")) { + info->ddc2 = FALSE; + } else { + xf86LoaderReqSymLists(ddcSymbols, NULL); + info->ddc2 = TRUE; + } + + /* DDC can use I2C bus */ + /* Load I2C if we have the code to use it */ + if (info->ddc2) { + if (xf86LoadSubModule(pScrn, "i2c")) { + xf86LoaderReqSymLists(i2cSymbols,NULL); + info->ddc2 = RADEONI2cInit(pScrn); + } + else info->ddc2 = FALSE; + } +} + /* This is called by RADEONPreInit to initialize gamma correction */ static Bool RADEONPreInitGamma(ScrnInfoPtr pScrn) { @@ -2998,94 +1890,6 @@ 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 RADEONValidateCloneModes(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); @@ -3183,10 +1987,10 @@ } } - pScrn->monitor->DDC = pRADEONEnt->MonInfo2; + pScrn->monitor->DDC = pRADEONEnt->Controller[1].pPort->MonInfo; if (pScrn->monitor->DDC) { if ((pScrn->monitor->nVrefresh == 0) || (pScrn->monitor->nHsync == 0)) { - if (pScrn->monitor->nHsync == 0) + if (pScrn->monitor->nHsync == 0) RADEONSetSyncRangeFromEdid(pScrn, 1); if (pScrn->monitor->nVrefresh == 0) RADEONSetSyncRangeFromEdid(pScrn, 0); @@ -3277,6 +2081,8 @@ pScrn->modes = pScrn->modes->next; } + pScrn->monitor->DDC = pRADEONEnt->Controller[0].pPort->MonInfo; + /* no longer needed, free it */ pScrn->modes = save_mode; while (pScrn->modes) @@ -3326,13 +2132,12 @@ /* This is called by RADEONPreInit to validate modes and compute * parameters for all of the valid modes. */ -static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) +static Bool RADEONPreInitModes(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); ClockRangePtr clockRanges; int modesFound; RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - char *s; /* This option has two purposes: * @@ -3364,10 +2169,6 @@ info->ddc_mode = xf86ReturnOptValBool(info->Options, OPTION_DDC_MODE, FALSE); - /* don't use RMX if we have a dual-tdms panels */ - if (pRADEONEnt->MonType2 == MT_DFP) - info->ddc_mode = TRUE; - /* Here is a hack for cloning first display on the second head. If * we don't do this, when both heads are connected, the same CRTC * will be used to drive them according to the capability of the @@ -3407,70 +2208,12 @@ "Validating modes on %s head ---------\n", info->IsSecondary ? "Secondary" : "Primary"); - if (info->IsSecondary) - pScrn->monitor->DDC = pRADEONEnt->MonInfo2; - else - pScrn->monitor->DDC = pRADEONEnt->MonInfo1; - if (!pScrn->monitor->DDC && info->ddc_mode) { info->ddc_mode = FALSE; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No DDC data available, DDCMode option is dismissed\n"); } - if ((info->DisplayType == MT_DFP) || - (info->DisplayType == MT_LCD)) { - if ((s = xf86GetOptValString(info->Options, OPTION_PANEL_SIZE))) { - int PanelX, PanelY; - DisplayModePtr tmp_mode = NULL; - if (sscanf(s, "%dx%d", &PanelX, &PanelY) == 2) { - info->PanelXRes = PanelX; - info->PanelYRes = PanelY; - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "Panel size is forced to: %s\n", s); - - /* We can't trust BIOS or DDC timings anymore, - 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. - */ - info->ddc_mode = FALSE; - pScrn->monitor->DDC = NULL; - tmp_mode = pScrn->monitor->Modes; - while(tmp_mode) { - if ((tmp_mode->HDisplay == PanelX) && - (tmp_mode->VDisplay == PanelY)) { - - 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) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "No valid timing info for specified panel size.\n" - "Please specify the Modeline for this panel\n"); - return FALSE; - } - } else { - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "Invalid PanelSize value: %s\n", s); - } - } - } - if (pScrn->monitor->DDC) { /* If we still don't know sync range yet, let's try EDID. * @@ -3569,7 +2312,7 @@ * mode using xf86ValidateModes routine * This can happen when DDC is disabled. */ - if (info->PanelXRes < 320 || info->PanelYRes < 200) + if ((info->PanelXRes < 320 || info->PanelYRes < 200) && (user_modes_found < 1)) modesFound = xf86ValidateModes(pScrn, pScrn->monitor->Modes, @@ -3691,7 +2434,7 @@ return TRUE; } -static Bool RADEONPreInitInt10(ScrnInfoPtr pScrn, xf86Int10InfoPtr *ppInt10) +static Bool RADEONPreInitInt10(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); @@ -3699,7 +2442,7 @@ if (xf86LoadSubModule(pScrn, "int10")) { xf86LoaderReqSymLists(int10Symbols, NULL); xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n"); - *ppInt10 = xf86InitInt10(info->pEnt->index); + info->pInt10 = xf86InitInt10(info->pEnt->index); } #endif return TRUE; @@ -3847,11 +2590,23 @@ } #endif +static Bool RADEONPreInitControllers(ScrnInfoPtr pScrn) +{ + RADEONGetBIOSInfo(pScrn); + + RADEONMapControllers(pScrn); + + RADEONGetClockInfo(pScrn); + RADEONGetPanelInfo(pScrn); + RADEONGetTVDacAdjInfo(pScrn); + + return TRUE; +} + static void RADEONProbeDDC(ScrnInfoPtr pScrn, int indx) { vbeInfoPtr pVbe; - if (xf86LoadSubModule(pScrn, "vbe")) { pVbe = VBEInit(NULL,indx); ConfiguredMonitor = vbeDoEDID(pVbe, NULL); @@ -3862,9 +2617,9 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) { RADEONInfoPtr info; - xf86Int10InfoPtr pInt10 = NULL; void *int10_save = NULL; const char *s; + RADEONEntPtr pRADEONEnt; RADEONTRACE(("RADEONPreInit\n")); if (pScrn->numEntities != 1) return FALSE; @@ -3919,11 +2674,9 @@ RADEONPreInt10Save(pScrn, &int10_save); #endif + pRADEONEnt = RADEONEntPriv(pScrn); if (xf86IsEntityShared(info->pEnt->index)) { if (xf86IsPrimInitDone(info->pEnt->index)) { - - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - info->IsSecondary = TRUE; if (!pRADEONEnt->HasSecondary) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, @@ -3933,14 +2686,12 @@ } pRADEONEnt->pSecondaryScrn = pScrn; } else { - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - xf86SetPrimInitDone(info->pEnt->index); pRADEONEnt->pPrimaryScrn = pScrn; - pRADEONEnt->RestorePrimary = FALSE; - pRADEONEnt->IsSecondaryRestored = FALSE; } + } else { + pRADEONEnt->pPrimaryScrn = pScrn; } if (flags & PROBE_DETECT) { @@ -4030,8 +2781,9 @@ } } + info->pInt10 = NULL; if (!info->FBDev) - if (!RADEONPreInitInt10(pScrn, &pInt10)) + if (!RADEONPreInitInt10(pScrn)) goto fail; RADEONPostInt10Check(pScrn, int10_save); @@ -4041,17 +2793,11 @@ RADEONPreInitDDC(pScrn); - if (!RADEONGetBIOSParameters(pScrn, pInt10)) - goto fail; - - if (info->DisplayType == MT_DFP) - RADEONGetTMDSInfo(pScrn); + if (!RADEONPreInitControllers (pScrn)) goto fail; + + if (!RADEONPreInitGamma(pScrn)) goto fail; - if (!RADEONGetPLLParameters(pScrn)) goto fail; - - if (!RADEONPreInitGamma(pScrn)) goto fail; - - if (!RADEONPreInitModes(pScrn, pInt10)) goto fail; + if (!RADEONPreInitModes(pScrn)) goto fail; if (!RADEONPreInitCursor(pScrn)) goto fail; @@ -4068,8 +2814,8 @@ } /* Free int10 info */ - if (pInt10) - xf86FreeInt10(pInt10); + if (info->pInt10) + xf86FreeInt10(info->pInt10); if(info->MMIO) RADEONUnmapMMIO(pScrn); info->MMIO = NULL; @@ -4093,8 +2839,8 @@ } /* Free int10 info */ - if (pInt10) - xf86FreeInt10(pInt10); + if (info->pInt10) + xf86FreeInt10(info->pInt10); vgaHWFreeHWRec(pScrn); @@ -4231,6 +2977,8 @@ } } + OUTREG(RADEON_DAC_CNTL2, INREG(RADEON_DAC_CNTL2) & ~RADEON_DAC2_PALETTE_ACC_CTL); + #ifdef XF86DRI if (info->CPStarted) DRIUnlock(pScrn->pScreen); #endif @@ -4283,9 +3031,10 @@ info->fbY = 0; #endif - info->PaletteSavedOnVT = FALSE; - RADEONSave(pScrn); + pScrn->vtSema = TRUE; + RADEONSaveScreen(pScreen, SCREEN_SAVER_ON); + if (info->FBDev) { unsigned char *RADEONMMIO = info->MMIO; @@ -4295,8 +3044,6 @@ if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE; } - RADEONSaveScreen(pScreen, SCREEN_SAVER_ON); - pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); if (info->CurCloneMode) { @@ -4348,9 +3095,7 @@ xf86DrvMsg(scrnIndex, X_WARNING, "Direct rendering not yet supported on " "IGP320/330/340/350, 7000, 9000 integrated chips\n"); - } else if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350)) { + } else if (IS_R300_VARIANT) { info->directRenderingEnabled = FALSE; xf86DrvMsg(scrnIndex, X_WARNING, "Direct rendering not yet supported on " @@ -4770,10 +3515,40 @@ info->BlockHandler = pScreen->BlockHandler; pScreen->BlockHandler = RADEONBlockHandler; - return TRUE; } +/* Write palette data */ +static void RADEONRestorePalette(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + int i; + CARD32 tmp = 0; + + if (info->HasCRTC2) { + tmp = INPLL (pScrn, RADEON_PIXCLKS_CNTL); + OUTPLLP (pScrn, RADEON_PIXCLKS_CNTL, + RADEON_PIX2CLK_SRC_SEL_CPUCLK, + ~(RADEON_PIX2CLK_SRC_SEL_MASK)); + + PAL_SELECT(1); + OUTPAL_START(0); + for (i = 0; i < 256; i++) { + OUTPAL_NEXT_CARD32(restore->palette2[i]); + } + } + + PAL_SELECT(0); + OUTPAL_START(0); + for (i = 0; i < 256; i++) { + OUTPAL_NEXT_CARD32(restore->palette[i]); + } + + if (info->HasCRTC2) + OUTREG(RADEON_PIXCLKS_CNTL, tmp); +} + /* Write common registers (initialized to 0) */ static void RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) @@ -4781,6 +3556,10 @@ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; + OUTREG(RADEON_RBBM_SOFT_RESET, restore->rbbm_soft_reset); + OUTREG(RADEON_DP_DATATYPE, restore->dp_datatype); + OUTREG(RADEON_CLOCK_CNTL_INDEX, restore->clock_cntl_index); + OUTREG(RADEON_OVR_CLR, restore->ovr_clr); OUTREG(RADEON_OVR_WID_LEFT_RIGHT, restore->ovr_wid_left_right); OUTREG(RADEON_OVR_WID_TOP_BOTTOM, restore->ovr_wid_top_bottom); @@ -4794,16 +3573,30 @@ OUTREG(RADEON_BUS_CNTL, restore->bus_cntl); OUTREG(RADEON_SURFACE_CNTL, restore->surface_cntl); + OUTREG(RADEON_GRPH_BUFFER_CNTL, restore->grph_buffer_cntl); + OUTREG(RADEON_GRPH2_BUFFER_CNTL, restore->grph2_buffer_cntl); + + /* we don't save/restore AGP_LOCATION here, it should + be taken care of by kernel driver. Writing to + MC_AGP_LOCATION with a incorrect value before AGPGART + is properly set up can cause problem, even if it's just + the saved value (same as the exiting value in the register). + */ + OUTREG(RADEON_MC_FB_LOCATION, restore->mc_fb_location); + OUTREG(RADEON_DISPLAY_BASE_ADDR, restore->disp1_base_addr); + OUTREG(RADEON_DISPLAY2_BASE_ADDR, restore->disp2_base_addr); + OUTREG(RADEON_OV0_BASE_ADDR, restore->ov0_base_addr); + OUTREG(RADEON_HOST_PATH_CNTL, restore->host_path_cntl); + OUTREG(RADEON_DEFAULT_OFFSET, restore->default_offset); + /* Workaround for the VT switching problem in dual-head mode. This * problem only occurs on RV style chips, typically when a FP and - * CRT are connected. + * CRT are connected. ???Do we still need this??? */ if (info->HasCRTC2 && !info->IsSwitching && - info->ChipFamily != CHIP_FAMILY_R200 && - info->ChipFamily != CHIP_FAMILY_R300 && - info->ChipFamily != CHIP_FAMILY_R350 && - info->ChipFamily != CHIP_FAMILY_RV350) { + (info->ChipFamily != CHIP_FAMILY_R200) && + (!IS_R300_VARIANT)) { CARD32 tmp; RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); @@ -4846,29 +3639,47 @@ { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - OUTREG(RADEON_CRTC_GEN_CNTL, restore->crtc_gen_cntl); + OUTREG(RADEON_CRTC_H_TOTAL_DISP, restore->crtc_h_total_disp); + OUTREG(RADEON_CRTC_H_SYNC_STRT_WID, restore->crtc_h_sync_strt_wid); + OUTREG(RADEON_CRTC_V_TOTAL_DISP, restore->crtc_v_total_disp); + OUTREG(RADEON_CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid); + OUTREG(RADEON_FP_H_SYNC_STRT_WID, restore->fp_h_sync_strt_wid); + OUTREG(RADEON_FP_V_SYNC_STRT_WID, restore->fp_v_sync_strt_wid); + OUTREG(RADEON_CRTC_PITCH, restore->crtc_pitch); + if (info->IsSwitching) return; - OUTREGP(RADEON_CRTC_EXT_CNTL, - restore->crtc_ext_cntl, - RADEON_CRTC_VSYNC_DIS | - RADEON_CRTC_HSYNC_DIS | - RADEON_CRTC_DISPLAY_DIS); + OUTREG(RADEON_CRTC_GEN_CNTL, restore->crtc_gen_cntl); + OUTREG(RADEON_CRTC_EXT_CNTL, restore->crtc_ext_cntl); OUTREGP(RADEON_DAC_CNTL, restore->dac_cntl, RADEON_DAC_RANGE_CNTL | RADEON_DAC_BLANKING); - OUTREG(RADEON_CRTC_H_TOTAL_DISP, restore->crtc_h_total_disp); - OUTREG(RADEON_CRTC_H_SYNC_STRT_WID, restore->crtc_h_sync_strt_wid); - OUTREG(RADEON_CRTC_V_TOTAL_DISP, restore->crtc_v_total_disp); - OUTREG(RADEON_CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid); OUTREG(RADEON_CRTC_OFFSET, restore->crtc_offset); OUTREG(RADEON_CRTC_OFFSET_CNTL, restore->crtc_offset_cntl); - OUTREG(RADEON_CRTC_PITCH, restore->crtc_pitch); OUTREG(RADEON_DISP_MERGE_CNTL, restore->disp_merge_cntl); OUTREG(RADEON_CRTC_MORE_CNTL, restore->crtc_more_cntl); + + /* when there is only single head, we need to make sure + * it's using first CRTC, no matter what type of display + */ + if (!pRADEONEnt->Controller[1].IsUsed) { + + if ((info->ChipFamily != CHIP_FAMILY_RADEON) && + (info->ChipFamily != CHIP_FAMILY_R200)) + OUTREG (RADEON_TV_DAC_CNTL, restore->tv_dac_cntl); + + OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl); + OUTREG(RADEON_DISP_OUTPUT_CNTL, restore->disp_output_cntl); + + if(IS_RV100_VARIANT) { + OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug); + } + OUTREG(RADEON_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl); + } } /* Write CRTC2 registers */ @@ -4878,43 +3689,34 @@ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - OUTREGP(RADEON_CRTC2_GEN_CNTL, - restore->crtc2_gen_cntl, - RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS | - RADEON_CRTC2_DISP_DIS); + OUTREG(RADEON_CRTC2_H_TOTAL_DISP, restore->crtc2_h_total_disp); + OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, restore->crtc2_h_sync_strt_wid); + OUTREG(RADEON_CRTC2_V_TOTAL_DISP, restore->crtc2_v_total_disp); + OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, restore->crtc2_v_sync_strt_wid); + OUTREG(RADEON_CRTC2_PITCH, restore->crtc2_pitch); + OUTREG(RADEON_FP_H2_SYNC_STRT_WID, restore->fp_h2_sync_strt_wid); + OUTREG(RADEON_FP_V2_SYNC_STRT_WID, restore->fp_v2_sync_strt_wid); + if (info->IsSwitching) return; + OUTREG(RADEON_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl); OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl); - OUTREG(RADEON_TV_DAC_CNTL, 0x00280203); - if ((info->ChipFamily == CHIP_FAMILY_R200) || - (info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350)) { + if ((info->ChipFamily != CHIP_FAMILY_RADEON) && + (info->ChipFamily != CHIP_FAMILY_R200)) + OUTREG (RADEON_TV_DAC_CNTL, restore->tv_dac_cntl); + + if (IS_R300_VARIANT) { + OUTREG(RADEON_DISP_OUTPUT_CNTL, restore->disp_output_cntl); + } else if (info->ChipFamily == CHIP_FAMILY_R200) { OUTREG(RADEON_DISP_OUTPUT_CNTL, restore->disp_output_cntl); + OUTREG(RADEON_FP2_GEN_CNTL, restore->fp2_gen_cntl); } else { OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug); } - OUTREG(RADEON_CRTC2_H_TOTAL_DISP, restore->crtc2_h_total_disp); - OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, restore->crtc2_h_sync_strt_wid); - OUTREG(RADEON_CRTC2_V_TOTAL_DISP, restore->crtc2_v_total_disp); - OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, restore->crtc2_v_sync_strt_wid); OUTREG(RADEON_CRTC2_OFFSET, restore->crtc2_offset); OUTREG(RADEON_CRTC2_OFFSET_CNTL, restore->crtc2_offset_cntl); - OUTREG(RADEON_CRTC2_PITCH, restore->crtc2_pitch); OUTREG(RADEON_DISP2_MERGE_CNTL, restore->disp2_merge_cntl); - - if ((info->DisplayType == MT_DFP && info->IsSecondary) || - info->CloneType == MT_DFP) { - OUTREG(RADEON_FP_H2_SYNC_STRT_WID, restore->fp2_h_sync_strt_wid); - OUTREG(RADEON_FP_V2_SYNC_STRT_WID, restore->fp2_v_sync_strt_wid); - OUTREG(RADEON_FP2_GEN_CNTL, restore->fp2_gen_cntl); - } -#if 0 - /* Hack for restoring text mode -- fixed elsewhere */ - usleep(100000); -#endif } /* Write flat panel registers */ @@ -4924,22 +3726,17 @@ unsigned char *RADEONMMIO = info->MMIO; unsigned long tmp; - OUTREG(RADEON_FP_CRTC_H_TOTAL_DISP, restore->fp_crtc_h_total_disp); - OUTREG(RADEON_FP_CRTC_V_TOTAL_DISP, restore->fp_crtc_v_total_disp); - OUTREG(RADEON_FP_H_SYNC_STRT_WID, restore->fp_h_sync_strt_wid); - OUTREG(RADEON_FP_V_SYNC_STRT_WID, restore->fp_v_sync_strt_wid); + OUTREG(RADEON_TMDS_PLL_CNTL, restore->tmds_pll_cntl); OUTREG(RADEON_TMDS_TRANSMITTER_CNTL,restore->tmds_transmitter_cntl); OUTREG(RADEON_FP_HORZ_STRETCH, restore->fp_horz_stretch); OUTREG(RADEON_FP_VERT_STRETCH, restore->fp_vert_stretch); + + if (info->IsSwitching) return; OUTREG(RADEON_FP_GEN_CNTL, restore->fp_gen_cntl); - /* old AIW Radeon has some BIOS initialization problem - * with display buffer underflow, only occurs to DFP - */ - if (!info->HasCRTC2) - OUTREG(RADEON_GRPH_BUFFER_CNTL, - INREG(RADEON_GRPH_BUFFER_CNTL) & ~0x7f0000); + if (!info->HasCRTC2) return; + OUTREG(RADEON_FP2_GEN_CNTL, restore->fp2_gen_cntl); if (info->IsMobility) { OUTREG(RADEON_BIOS_4_SCRATCH, restore->bios_4_scratch); @@ -4949,7 +3746,6 @@ if (info->DisplayType != MT_DFP) { unsigned long tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); - OUTREG(RADEON_BIOS_5_SCRATCH, restore->bios_5_scratch); if (info->IsMobility || info->IsIGP) { /* Asic bug, when turning off LVDS_ON, we have to make sure @@ -5002,8 +3798,13 @@ { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; + int i = 0; - while (INPLL(pScrn, RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R); + /*while (INPLL(pScrn, RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R);*/ + for (i = 0; + (i < 10000 && + INPLL(pScrn, RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R); + i++); OUTPLLP(pScrn, RADEON_PPLL_REF_DIV, RADEON_PPLL_ATOMIC_UPDATE_W, @@ -5028,8 +3829,13 @@ { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; + int i = 0; - while (INPLL(pScrn, RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R); + /*while (INPLL(pScrn, RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R);*/ + for (i = 0; + (i < 10000 && + INPLL(pScrn, RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R); + i++); OUTPLLP(pScrn, RADEON_P2PLL_REF_DIV, RADEON_P2PLL_ATOMIC_UPDATE_W, @@ -5072,28 +3878,7 @@ RADEON_PLL_DIV_SEL, ~(RADEON_PLL_DIV_SEL)); - if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_RS300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350)) { - if (restore->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) { - /* When restoring console mode, use saved PPLL_REF_DIV - * setting. - */ - OUTPLLP(pScrn, RADEON_PPLL_REF_DIV, - restore->ppll_ref_div, - 0); - } else { - /* R300 uses ref_div_acc field as real ref divider */ - OUTPLLP(pScrn, RADEON_PPLL_REF_DIV, - (restore->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT), - ~R300_PPLL_REF_DIV_ACC_MASK); - } - } else { - OUTPLLP(pScrn, RADEON_PPLL_REF_DIV, - restore->ppll_ref_div, - ~RADEON_PPLL_REF_DIV_MASK); - } + OUTPLL(RADEON_PPLL_REF_DIV, restore->ppll_ref_div); OUTPLLP(pScrn, RADEON_PPLL_DIV_3, restore->ppll_div_3, @@ -5127,10 +3912,8 @@ usleep(5000); /* Let the clock to lock */ - OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, - RADEON_VCLK_SRC_SEL_PPLLCLK, - ~(RADEON_VCLK_SRC_SEL_MASK)); -} + OUTPLLP (pScrn, RADEON_VCLK_ECP_CNTL, restore->vclk_cntl, 0); + } /* Write PLL2 registers */ @@ -5189,33 +3972,7 @@ usleep(5000); /* Let the clock to lock */ - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, - RADEON_PIX2CLK_SRC_SEL_P2PLLCLK, - ~(RADEON_PIX2CLK_SRC_SEL_MASK)); -} - -/* Write palette data */ -static void RADEONRestorePalette(ScrnInfoPtr pScrn, RADEONSavePtr restore) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - int i; - - if (!restore->palette_valid) return; - - PAL_SELECT(1); - OUTPAL_START(0); - for (i = 0; i < 256; i++) { - RADEONWaitForFifo(pScrn, 32); /* delay */ - OUTPAL_NEXT_CARD32(restore->palette2[i]); - } - - PAL_SELECT(0); - OUTPAL_START(0); - for (i = 0; i < 256; i++) { - RADEONWaitForFifo(pScrn, 32); /* delay */ - OUTPAL_NEXT_CARD32(restore->palette[i]); - } + OUTPLLP (pScrn, RADEON_PIXCLKS_CNTL, restore->pixclks_cntl, 0); } /* Write out state to define a new video mode */ @@ -5223,69 +3980,34 @@ { RADEONInfoPtr info = RADEONPTR(pScrn); RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - static RADEONSaveRec restore0; - - /* For Non-dual head card, we don't have private field in the Entity */ - if (!info->HasCRTC2) { - RADEONRestoreCommonRegisters(pScrn, restore); - RADEONRestoreCrtcRegisters(pScrn, restore); - RADEONRestoreFPRegisters(pScrn, restore); - RADEONRestorePLLRegisters(pScrn, restore); - return; - } + + if (info->IsSwitching) { + if (info->IsSecondary) { + RADEONRestoreCrtc2Registers(pScrn, restore); + RADEONRestorePLL2Registers(pScrn, restore); + RADEONRestoreFPRegisters(pScrn, restore); + } else { - RADEONTRACE(("RADEONRestoreMode(%p)\n", restore)); + if (info->Clone) { + RADEONRestoreCrtc2Registers(pScrn, restore); + RADEONRestorePLL2Registers(pScrn, restore); + } - /* When changing mode with Dual-head card, care must be taken for - * the special order in setting registers. CRTC2 has to be set - * before changing CRTC_EXT register. In the dual-head setup, X - * server calls this routine twice with primary and secondary pScrn - * pointers respectively. The calls can come with different - * order. Regardless the order of X server issuing the calls, we - * have to ensure we set registers in the right order!!! Otherwise - * we may get a blank screen. - */ - if (info->IsSecondary) { - if (!pRADEONEnt->RestorePrimary && !info->IsSwitching) - RADEONRestoreCommonRegisters(pScrn, restore); - RADEONRestoreCrtc2Registers(pScrn, restore); - RADEONRestorePLL2Registers(pScrn, restore); - - if(info->IsSwitching) return; - - pRADEONEnt->IsSecondaryRestored = TRUE; - - if (pRADEONEnt->RestorePrimary) { - pRADEONEnt->RestorePrimary = FALSE; - - RADEONRestoreCrtcRegisters(pScrn, &restore0); - RADEONRestoreFPRegisters(pScrn, &restore0); - RADEONRestorePLLRegisters(pScrn, &restore0); - pRADEONEnt->IsSecondaryRestored = FALSE; + RADEONRestoreCrtcRegisters(pScrn, restore); + RADEONRestorePLLRegisters(pScrn, restore); + RADEONRestoreFPRegisters(pScrn, restore); } } else { - if (!pRADEONEnt->IsSecondaryRestored) - RADEONRestoreCommonRegisters(pScrn, restore); - if (info->Clone) { + if ((info->Clone) || pRADEONEnt->HasSecondary) { RADEONRestoreCrtc2Registers(pScrn, restore); RADEONRestorePLL2Registers(pScrn, restore); } - if (!pRADEONEnt->HasSecondary || pRADEONEnt->IsSecondaryRestored || - info->IsSwitching) { - pRADEONEnt->IsSecondaryRestored = FALSE; - - RADEONRestoreCrtcRegisters(pScrn, restore); - RADEONRestoreFPRegisters(pScrn, restore); - RADEONRestorePLLRegisters(pScrn, restore); - } else { - memcpy(&restore0, restore, sizeof(restore0)); - pRADEONEnt->RestorePrimary = TRUE; - } + RADEONRestoreCrtcRegisters(pScrn, restore); + RADEONRestorePLLRegisters(pScrn, restore); + RADEONRestoreFPRegisters(pScrn, restore); } - - RADEONRestorePalette(pScrn, &info->SavedReg); } /* Read common registers */ @@ -5294,6 +4016,11 @@ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; + save->dp_datatype = INREG(RADEON_DP_DATATYPE); + save->rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET); + save->clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX); + if (info->R300CGWorkaround) R300CGWorkaround(pScrn); + save->ovr_clr = INREG(RADEON_OVR_CLR); save->ovr_wid_left_right = INREG(RADEON_OVR_WID_LEFT_RIGHT); save->ovr_wid_top_bottom = INREG(RADEON_OVR_WID_TOP_BOTTOM); @@ -5308,6 +4035,13 @@ save->surface_cntl = INREG(RADEON_SURFACE_CNTL); save->grph_buffer_cntl = INREG(RADEON_GRPH_BUFFER_CNTL); save->grph2_buffer_cntl = INREG(RADEON_GRPH2_BUFFER_CNTL); + + save->mc_fb_location = INREG(RADEON_MC_FB_LOCATION); + save->disp1_base_addr = INREG(RADEON_DISPLAY_BASE_ADDR); + save->disp2_base_addr = INREG(RADEON_DISPLAY2_BASE_ADDR); + save->ov0_base_addr = INREG(RADEON_OV0_BASE_ADDR); + save->host_path_cntl = INREG(RADEON_HOST_PATH_CNTL); + save->default_offset = INREG(RADEON_DEFAULT_OFFSET); } /* Read miscellaneous registers which might be destroyed by an fbdevHW call */ @@ -5341,6 +4075,7 @@ save->crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL); save->crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL); save->dac_cntl = INREG(RADEON_DAC_CNTL); + save->tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); save->crtc_h_total_disp = INREG(RADEON_CRTC_H_TOTAL_DISP); save->crtc_h_sync_strt_wid = INREG(RADEON_CRTC_H_SYNC_STRT_WID); save->crtc_v_total_disp = INREG(RADEON_CRTC_V_TOTAL_DISP); @@ -5386,8 +4121,11 @@ unsigned char *RADEONMMIO = info->MMIO; save->dac2_cntl = INREG(RADEON_DAC_CNTL2); - save->disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL); - save->disp_hw_debug = INREG (RADEON_DISP_HW_DEBUG); + if (IS_RV100_VARIANT) { + save->disp_hw_debug = INREG (RADEON_DISP_HW_DEBUG); + } else { + save->disp_output_cntl = INREG (RADEON_DISP_OUTPUT_CNTL); + } save->crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); save->crtc2_h_total_disp = INREG(RADEON_CRTC2_H_TOTAL_DISP); @@ -5398,8 +4136,8 @@ save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL); save->crtc2_pitch = INREG(RADEON_CRTC2_PITCH); - save->fp2_h_sync_strt_wid = INREG (RADEON_FP_H2_SYNC_STRT_WID); - save->fp2_v_sync_strt_wid = INREG (RADEON_FP_V2_SYNC_STRT_WID); + save->fp_h2_sync_strt_wid = INREG (RADEON_FP_H2_SYNC_STRT_WID); + save->fp_v2_sync_strt_wid = INREG (RADEON_FP_V2_SYNC_STRT_WID); save->fp2_gen_cntl = INREG (RADEON_FP2_GEN_CNTL); save->disp2_merge_cntl = INREG(RADEON_DISP2_MERGE_CNTL); } @@ -5410,6 +4148,7 @@ save->ppll_ref_div = INPLL(pScrn, RADEON_PPLL_REF_DIV); save->ppll_div_3 = INPLL(pScrn, RADEON_PPLL_DIV_3); save->htotal_cntl = INPLL(pScrn, RADEON_HTOTAL_CNTL); + save->vclk_cntl = INPLL (pScrn, RADEON_VCLK_ECP_CNTL); RADEONTRACE(("Read: 0x%08x 0x%08x 0x%08x\n", save->ppll_ref_div, @@ -5427,7 +4166,8 @@ save->p2pll_ref_div = INPLL(pScrn, RADEON_P2PLL_REF_DIV); save->p2pll_div_0 = INPLL(pScrn, RADEON_P2PLL_DIV_0); save->htotal_cntl2 = INPLL(pScrn, RADEON_HTOTAL2_CNTL); - + save->pixclks_cntl = INPLL (pScrn, RADEON_PIXCLKS_CNTL); + RADEONTRACE(("Read: 0x%08x 0x%08x 0x%08x\n", save->p2pll_ref_div, save->p2pll_div_0, @@ -5444,18 +4184,25 @@ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; int i; + CARD32 tmp = 0; + + if (info->HasCRTC2) { + tmp = INPLL (pScrn, RADEON_PIXCLKS_CNTL); + OUTPLLP (pScrn, RADEON_PIXCLKS_CNTL, + RADEON_PIX2CLK_SRC_SEL_CPUCLK, + ~(RADEON_PIX2CLK_SRC_SEL_MASK)); + + PAL_SELECT(1); + INPAL_START(0); + for (i = 0; i < 256; i++) save->palette2[i] = INPAL_NEXT(); + } -#ifdef ENABLE_FLAT_PANEL - /* Select palette 0 (main CRTC) if using FP-enabled chip */ - /* if (info->Port1 == MT_DFP) PAL_SELECT(1); */ -#endif - PAL_SELECT(1); - INPAL_START(0); - for (i = 0; i < 256; i++) save->palette2[i] = INPAL_NEXT(); PAL_SELECT(0); INPAL_START(0); for (i = 0; i < 256; i++) save->palette[i] = INPAL_NEXT(); - save->palette_valid = TRUE; + + if (info->HasCRTC2) + OUTPLL(RADEON_PIXCLKS_CNTL, tmp); } /* Save state that defines current video mode */ @@ -5464,20 +4211,19 @@ RADEONInfoPtr info = RADEONPTR(pScrn); RADEONTRACE(("RADEONSaveMode(%p)\n", save)); - RADEONSaveCommonRegisters(pScrn, save); if (info->IsSecondary) { - RADEONSaveCrtc2Registers(pScrn, save); - RADEONSavePLL2Registers(pScrn, save); - } else { - RADEONSavePLLRegisters(pScrn, save); - RADEONSaveCrtcRegisters(pScrn, save); - RADEONSaveFPRegisters(pScrn, save); - - if (info->Clone) { - RADEONSaveCrtc2Registers(pScrn, save); - RADEONSavePLL2Registers(pScrn, save); - } + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RADEONInfoPtr info0 = RADEONPTR(pRADEONEnt->pPrimaryScrn); + memcpy(&info->SavedReg, &info0->SavedReg, sizeof(RADEONSaveRec)); + } else { + RADEONSavePLLRegisters (pScrn, save); + RADEONSaveCommonRegisters (pScrn, save); + RADEONSaveCrtcRegisters (pScrn, save); + RADEONSaveFPRegisters (pScrn, save); + RADEONSaveCrtc2Registers (pScrn, save); + RADEONSavePLL2Registers (pScrn, save); RADEONSavePalette(pScrn, save); + memcpy(&info->ModeReg, &info->SavedReg, sizeof(RADEONSaveRec)); } RADEONTRACE(("RADEONSaveMode returns %p\n", save)); @@ -5487,7 +4233,6 @@ static void RADEONSave(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; RADEONSavePtr save = &info->SavedReg; vgaHWPtr hwp = VGAHWPTR(pScrn); @@ -5511,10 +4256,6 @@ */ #endif vgaHWLock(hwp); - save->dp_datatype = INREG(RADEON_DP_DATATYPE); - save->rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET); - save->clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX); - if (info->R300CGWorkaround) R300CGWorkaround(pScrn); } RADEONSaveMode(pScrn, save); @@ -5524,9 +4265,11 @@ static void RADEONRestore(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; RADEONSavePtr restore = &info->SavedReg; - vgaHWPtr hwp = VGAHWPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + vgaHWPtr hwp = VGAHWPTR(pRADEONEnt->pPrimaryScrn); + static int ScreenCount = 0; + ScreenCount++; RADEONTRACE(("RADEONRestore\n")); @@ -5536,37 +4279,23 @@ #endif if (info->FBDev) { + RADEONRestorePalette(pScrn, restore); fbdevHWRestore(pScrn); return; } - RADEONBlank(pScrn); - OUTREG(RADEON_CLOCK_CNTL_INDEX, restore->clock_cntl_index); - if (info->R300CGWorkaround) R300CGWorkaround(pScrn); - OUTREG(RADEON_RBBM_SOFT_RESET, restore->rbbm_soft_reset); - OUTREG(RADEON_DP_DATATYPE, restore->dp_datatype); - OUTREG(RADEON_GRPH_BUFFER_CNTL, restore->grph_buffer_cntl); - OUTREG(RADEON_GRPH2_BUFFER_CNTL, restore->grph2_buffer_cntl); + RADEONBlank(pScrn); -#if 0 - /* M6 card has trouble restoring text mode for its CRT. - * This is fixed elsewhere and will be removed in the future. - */ - if ((xf86IsEntityShared(info->pEnt->index) || info->Clone) - && info->IsM6) - OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl); -#endif + if (ScreenCount == 1) { + if (!pRADEONEnt->HasSecondary) ScreenCount = 0; - RADEONRestoreMode(pScrn, restore); + RADEONRestoreMode(pScrn, restore); + RADEONRestoreCommonRegisters(pScrn, restore); -#if 0 - /* Temp fix to "solve" VT switch problems. When switching VTs on - * some systems, the console can either hang or the fonts can be - * corrupted. This hack solves the problem 99% of the time. A - * correct fix is being worked on. - */ - usleep(100000); -#endif + RADEONRestorePalette(pScrn, restore); + } else { + ScreenCount = 0; + } if (!info->IsSecondary) { vgaHWUnlock(hwp); @@ -5579,27 +4308,20 @@ vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS ); #endif vgaHWLock(hwp); - } else { - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - ScrnInfoPtr pScrn0; - vgaHWPtr hwp0; - - pScrn0 = pRADEONEnt->pPrimaryScrn; - hwp0 = VGAHWPTR(pScrn0); - vgaHWUnlock(hwp0); - vgaHWRestore(pScrn0, &hwp0->SavedReg, VGA_SR_MODE | VGA_SR_FONTS ); - vgaHWLock(hwp0); } - RADEONUnblank(pScrn); - -#if 0 - RADEONWaitForVerticalSync(pScrn); -#endif + /* We don't really need unblank here, saved text mode state should + * restore the controller to old state. + */ + /* + RADEONUnblank(pScrn); + */ } /* Define common registers for requested video mode */ static void RADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info) { + unsigned char *RADEONMMIO = info->MMIO; + save->ovr_clr = 0; save->ovr_wid_left_right = 0; save->ovr_wid_top_bottom = 0; @@ -5611,874 +4333,575 @@ save->cap0_trig_cntl = 0; save->cap1_trig_cntl = 0; save->bus_cntl = info->BusCntl; + /* * If bursts are enabled, turn on discards * Radeon doesn't have write bursts */ if (save->bus_cntl & (RADEON_BUS_READ_BURST)) 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; - - if (pRADEONEnt->pSecondaryScrn) { - if (info->IsSecondary) return; - info2 = RADEONPTR(pRADEONEnt->pSecondaryScrn); - } else if (info->Clone) info2 = info; - - /* - * Determine if there is enough bandwidth for current display mode + /* old AIW Radeon has some BIOS initialization problem + * with display buffer underflow, only occurs to DFP */ - mem_bw = info->mclk * (info->RamWidth / 8) * (info->IsDDR ? 2 : 1); - - mode1 = info->CurrentLayout.mode; - if (info->Clone) - mode2 = info->CurCloneMode; - 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; + if ((!info->HasCRTC2) && info->DisplayType == MT_DFP) + save->grph_buffer_cntl &= ~0x7f0000; - /* setup Max GRPH_STOP_REQ default value */ - if ((info->ChipFamily == CHIP_FAMILY_RV100) || - (info->ChipFamily == CHIP_FAMILY_RV200) || - (info->ChipFamily == CHIP_FAMILY_RV250) || - (info->ChipFamily == CHIP_FAMILY_RV280) || - (info->ChipFamily == CHIP_FAMILY_RS100) || - (info->ChipFamily == CHIP_FAMILY_RS200) || - (info->ChipFamily == CHIP_FAMILY_RS300)) - 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 ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350)) { + if (info->IsIGP) { + CARD32 tom = INREG(RADEON_NB_TOM); + save->mc_fb_location = tom; + save->disp1_base_addr = (tom & 0xffff) << 16; + save->disp2_base_addr = (tom & 0xffff) << 16; + save->ov0_base_addr = (tom & 0xffff) << 16; - /* on the R300, Tcas is included in Trbs. + /* This is supposed to fix the crtc2 noise problem. */ - temp = INREG(RADEON_MEM_CNTL); - data = (R300_MEM_NUM_CHANNELS_MASK & temp); - if (data == 2) { - 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; - } + save->grph2_buffer_cntl &= ~0x7f0000; - 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 ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350)) { - /*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; + save->mc_fb_location = (INREG(RADEON_CONFIG_MEMSIZE)-1) & 0xffff0000; + if ((info->ChipFamily == CHIP_FAMILY_RV350) || + (info->ChipFamily == CHIP_FAMILY_RV380) || + (info->ChipFamily == CHIP_FAMILY_R420)) { + save->host_path_cntl |= (1<<23); } - } else { - k1 = 40; - c = 3; + save->disp1_base_addr = 0; + save->disp2_base_addr = 0; + save->ov0_base_addr = 0; } - 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) { - if (mode2) { - /*??some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ - if (info->ChipFamily == CHIP_FAMILY_R300) - critical_point += 0x10; - else - critical_point = 0; - } - else - 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; - - 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", - 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) { - if (info->ChipFamily == CHIP_FAMILY_R300) - critical_point2 += 0x10; - else - critical_point2 = 0; - } - - if (max_stop_req - critical_point2 < 4) critical_point2 = 0; - - } - - 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", - 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) -{ - unsigned char *RADEONMMIO = info->MMIO; - - int format; - int hsync_start; - int hsync_wid; - int vsync_wid; - - switch (info->CurrentLayout.pixel_code) { - case 4: format = 1; break; - case 8: format = 2; break; - case 15: format = 3; break; /* 555 */ - case 16: format = 4; break; /* 565 */ - case 24: format = 5; break; /* RGB */ - case 32: format = 6; break; /* xRGB */ - default: - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Unsupported pixel depth (%d)\n", - info->CurrentLayout.bitsPerPixel); - return FALSE; - } - - if ((info->DisplayType == MT_DFP) || - (info->DisplayType == MT_LCD)) { - if (mode->Flags & RADEON_USE_RMX) { -#if 0 - mode->CrtcHDisplay = info->PanelXRes; - mode->CrtcVDisplay = info->PanelYRes; -#endif - mode->CrtcHTotal = mode->CrtcHDisplay + info->HBlank; - mode->CrtcHSyncStart = mode->CrtcHDisplay + info->HOverPlus; - mode->CrtcHSyncEnd = mode->CrtcHSyncStart + info->HSyncWidth; - mode->CrtcVTotal = mode->CrtcVDisplay + info->VBlank; - mode->CrtcVSyncStart = mode->CrtcVDisplay + info->VOverPlus; - mode->CrtcVSyncEnd = mode->CrtcVSyncStart + info->VSyncWidth; - mode->Clock = info->DotClock; - mode->Flags = info->Flags | RADEON_USE_RMX; - } - } - - save->crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN - | RADEON_CRTC_EN - | (format << 8) - | ((mode->Flags & V_DBLSCAN) - ? RADEON_CRTC_DBL_SCAN_EN - : 0) - | ((mode->Flags & V_CSYNC) - ? RADEON_CRTC_CSYNC_EN - : 0) - | ((mode->Flags & V_INTERLACE) - ? RADEON_CRTC_INTERLACE_EN - : 0)); - - if ((info->DisplayType == MT_DFP) || - (info->DisplayType == MT_LCD)) { - save->crtc_ext_cntl = RADEON_VGA_ATI_LINEAR | RADEON_XCRT_CNT_EN; - save->crtc_gen_cntl &= ~(RADEON_CRTC_DBL_SCAN_EN | - RADEON_CRTC_CSYNC_EN | - RADEON_CRTC_INTERLACE_EN); - } else { - save->crtc_ext_cntl = (RADEON_VGA_ATI_LINEAR | - RADEON_XCRT_CNT_EN | - RADEON_CRTC_CRT_ON); - } - - save->dac_cntl = (RADEON_DAC_MASK_ALL - | RADEON_DAC_VGA_ADR_EN - | (info->dac6bits ? 0 : RADEON_DAC_8BIT_EN)); - - save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) - | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) - << 16)); - - hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; - if (!hsync_wid) hsync_wid = 1; - hsync_start = mode->CrtcHSyncStart - 8; - - save->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) - | ((hsync_wid & 0x3f) << 16) - | ((mode->Flags & V_NHSYNC) - ? RADEON_CRTC_H_SYNC_POL - : 0)); - -#if 1 - /* This works for double scan mode. */ - save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) - | ((mode->CrtcVDisplay - 1) << 16)); -#else - /* This is what cce/nbmode.c example code - * does -- is this correct? - */ - save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) - | ((mode->CrtcVDisplay - * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1) - << 16)); -#endif - - vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; - if (!vsync_wid) vsync_wid = 1; - - save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) - | ((vsync_wid & 0x1f) << 16) - | ((mode->Flags & V_NVSYNC) - ? RADEON_CRTC_V_SYNC_POL - : 0)); - - save->crtc_offset = 0; - save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL); - - save->crtc_pitch = (((pScrn->displayWidth * pScrn->bitsPerPixel) + - ((pScrn->bitsPerPixel * 8) -1)) / - (pScrn->bitsPerPixel * 8)); - save->crtc_pitch |= save->crtc_pitch << 16; - - /* Some versions of BIOS setup CRTC_MORE_CNTL for a DFP, if we - have a CRT here, it should be cleared to avoild a blank screen. - */ - if (info->DisplayType == MT_CRT) - save->crtc_more_cntl = (info->SavedReg.crtc_more_cntl & - ~(RADEON_CRTC_H_CUTOFF_ACTIVE_EN | - RADEON_CRTC_V_CUTOFF_ACTIVE_EN)); - else - save->crtc_more_cntl = info->SavedReg.crtc_more_cntl; - - save->surface_cntl = 0; - save->disp_merge_cntl = info->SavedReg.disp_merge_cntl; - save->disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; - -#if X_BYTE_ORDER == X_BIG_ENDIAN - /* Alhought we current onlu use aperture 0, also setting aperture 1 should not harm -ReneR */ - switch (pScrn->bitsPerPixel) { - case 16: - save->surface_cntl |= RADEON_NONSURF_AP0_SWP_16BPP; - save->surface_cntl |= RADEON_NONSURF_AP1_SWP_16BPP; - break; - - case 32: - save->surface_cntl |= RADEON_NONSURF_AP0_SWP_32BPP; - save->surface_cntl |= RADEON_NONSURF_AP1_SWP_32BPP; - break; - } -#endif - - RADEONTRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n", - save->crtc_pitch, pScrn->virtualX, - info->CurrentLayout.displayWidth)); - return TRUE; -} - -/* Define CRTC2 registers for requested video mode */ -static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, - DisplayModePtr mode, RADEONInfoPtr info) -{ - unsigned char *RADEONMMIO = info->MMIO; - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - - int format; - int hsync_start; - int hsync_wid; - int vsync_wid; - - switch (info->CurrentLayout.pixel_code) { - case 4: format = 1; break; - case 8: format = 2; break; - case 15: format = 3; break; /* 555 */ - case 16: format = 4; break; /* 565 */ - case 24: format = 5; break; /* RGB */ - case 32: format = 6; break; /* xRGB */ - default: - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Unsupported pixel depth (%d)\n", - info->CurrentLayout.bitsPerPixel); - return FALSE; - } - - save->crtc2_gen_cntl = (RADEON_CRTC2_EN - | RADEON_CRTC2_CRT2_ON - | (format << 8) - | ((mode->Flags & V_DBLSCAN) - ? RADEON_CRTC2_DBL_SCAN_EN - : 0) - | ((mode->Flags & V_CSYNC) - ? RADEON_CRTC2_CSYNC_EN - : 0) - | ((mode->Flags & V_INTERLACE) - ? RADEON_CRTC2_INTERLACE_EN - : 0)); - - /* Turn CRT on in case the first head is a DFP */ - save->crtc_ext_cntl |= RADEON_CRTC_CRT_ON; - save->dac2_cntl = info->SavedReg.dac2_cntl; - /* always let TVDAC drive CRT2, we don't support tvout yet */ - save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; - save->disp_output_cntl = info->SavedReg.disp_output_cntl; - if (info->ChipFamily == CHIP_FAMILY_R200 || - info->ChipFamily == CHIP_FAMILY_R300 || - info->ChipFamily == CHIP_FAMILY_R350 || - info->ChipFamily == CHIP_FAMILY_RV350) { - save->disp_output_cntl &= ~(RADEON_DISP_DAC_SOURCE_MASK | - RADEON_DISP_DAC2_SOURCE_MASK); - if (pRADEONEnt->MonType1 != MT_CRT) { - save->disp_output_cntl |= (RADEON_DISP_DAC_SOURCE_CRTC2 | - RADEON_DISP_DAC2_SOURCE_CRTC2); - } else { - if (pRADEONEnt->ReversedDAC) { - save->disp_output_cntl |= RADEON_DISP_DAC2_SOURCE_CRTC2; - } else { - save->disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2; - } - } - } else { - save->disp_hw_debug = info->SavedReg.disp_hw_debug; - /* Turn on 2nd CRT */ - if (pRADEONEnt->MonType1 != MT_CRT) { - /* This is for some sample boards with the VGA port - connected to the TVDAC, but BIOS doesn't reflect this. - Here we configure both DACs to use CRTC2. - Not sure if this happens in any retail board. - */ - save->disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL; - save->dac2_cntl |= RADEON_DAC2_DAC_CLK_SEL; - } else { - if (pRADEONEnt->ReversedDAC) { - save->disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL; - save->dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL; - } else { - save->disp_hw_debug |= RADEON_CRT2_DISP1_SEL; - save->dac2_cntl |= RADEON_DAC2_DAC_CLK_SEL; - } - } - } - - save->crtc2_h_total_disp = - ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) - | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) << 16)); - - hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; - if (!hsync_wid) hsync_wid = 1; - hsync_start = mode->CrtcHSyncStart - 8; - - save->crtc2_h_sync_strt_wid = ((hsync_start & 0x1fff) - | ((hsync_wid & 0x3f) << 16) - | ((mode->Flags & V_NHSYNC) - ? RADEON_CRTC_H_SYNC_POL - : 0)); - -#if 1 - /* This works for double scan mode. */ - save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) - | ((mode->CrtcVDisplay - 1) << 16)); -#else - /* This is what cce/nbmode.c example code - * does -- is this correct? - */ - save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) - | ((mode->CrtcVDisplay - * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1) - << 16)); -#endif - - vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; - if (!vsync_wid) vsync_wid = 1; - - save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) - | ((vsync_wid & 0x1f) << 16) - | ((mode->Flags & V_NVSYNC) - ? RADEON_CRTC2_V_SYNC_POL - : 0)); - - save->crtc2_offset = 0; - save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL); - - save->crtc2_pitch = (((pScrn->displayWidth * pScrn->bitsPerPixel) + - ((pScrn->bitsPerPixel * 8) -1)) / - (pScrn->bitsPerPixel * 8)); - save->crtc2_pitch |= save->crtc2_pitch << 16; - save->disp2_merge_cntl = info->SavedReg.disp2_merge_cntl; - save->disp2_merge_cntl &= ~(RADEON_DISP2_RGB_OFFSET_EN); - - if ((info->DisplayType == MT_DFP && info->IsSecondary) || - info->CloneType == MT_DFP) { - save->crtc2_gen_cntl = (RADEON_CRTC2_EN | (format << 8)); - save->fp2_h_sync_strt_wid = save->crtc2_h_sync_strt_wid; - save->fp2_v_sync_strt_wid = save->crtc2_v_sync_strt_wid; - save->fp2_gen_cntl = (RADEON_FP2_PANEL_FORMAT | - RADEON_FP2_ON); - if (info->ChipFamily >= CHIP_FAMILY_R200) { - save->fp2_gen_cntl |= RADEON_FP2_DVO_EN; - } - - if (info->ChipFamily == CHIP_FAMILY_R200 || - info->ChipFamily == CHIP_FAMILY_R300 || - info->ChipFamily == CHIP_FAMILY_R350 || - info->ChipFamily == CHIP_FAMILY_RV350) { - save->fp2_gen_cntl &= ~RADEON_FP2_SOURCE_SEL_MASK; - save->fp2_gen_cntl |= RADEON_FP2_SOURCE_SEL_CRTC2; - } else { - save->fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_MASK; - save->fp2_gen_cntl |= RADEON_FP2_SRC_SEL_CRTC2; - } - - if (pScrn->rgbBits == 8) - save->fp2_gen_cntl |= RADEON_FP2_PANEL_FORMAT; /* 24 bit format */ - else - save->fp2_gen_cntl &= ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format */ - - /* FIXME: When there are two DFPs, the 2nd DFP is driven by the - * external TMDS transmitter. It may have a problem at - * high dot clock for certain panels. - */ - - /* If BIOS has not turned it on, we'll keep it on so that we'll - * have a valid VGA screen even after X quits or VT is switched - * to the console mode. - */ - info->SavedReg.fp2_gen_cntl = RADEON_FP2_ON; - } - - RADEONTRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n", - save->crtc2_pitch, pScrn->virtualX, - info->CurrentLayout.displayWidth)); - return TRUE; } -/* Define CRTC registers for requested video mode */ -static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig, - RADEONSavePtr save, DisplayModePtr mode, - RADEONInfoPtr info) +static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, DisplayModePtr mode, BOOL IsPrimary) { + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RADEONInfoPtr info = RADEONPTR(pScrn); int xres = mode->HDisplay; int yres = mode->VDisplay; float Hratio, Vratio; - - /* If the FP registers have been initialized before for a panel, - * but the primary port is a CRT, we need to reinitialize - * FP registers in order for CRT to work properly - */ - - if ((info->DisplayType != MT_DFP) && (info->DisplayType != MT_LCD)) { - save->fp_crtc_h_total_disp = orig->fp_crtc_h_total_disp; - save->fp_crtc_v_total_disp = orig->fp_crtc_v_total_disp; - save->fp_gen_cntl = 0; - save->fp_h_sync_strt_wid = orig->fp_h_sync_strt_wid; - save->fp_horz_stretch = 0; - save->fp_v_sync_strt_wid = orig->fp_v_sync_strt_wid; - save->fp_vert_stretch = 0; - save->lvds_gen_cntl = orig->lvds_gen_cntl; - save->lvds_pll_cntl = orig->lvds_pll_cntl; - save->tmds_pll_cntl = orig->tmds_pll_cntl; - save->tmds_transmitter_cntl= orig->tmds_transmitter_cntl; - - save->lvds_gen_cntl |= ( RADEON_LVDS_DISPLAY_DIS | (1 << 23)); - save->lvds_gen_cntl &= ~(RADEON_LVDS_BLON | RADEON_LVDS_ON); - save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); - - return; - } - - if (info->PanelXRes == 0 || info->PanelYRes == 0) { - Hratio = 1.0; - Vratio = 1.0; - } else { - if (xres > info->PanelXRes) xres = info->PanelXRes; - if (yres > info->PanelYRes) yres = info->PanelYRes; - - Hratio = (float)xres/(float)info->PanelXRes; - Vratio = (float)yres/(float)info->PanelYRes; + RADEONMonitorType MonType; + RADEONTmdsType TmdsType; + + if (IsPrimary) { + MonType = pRADEONEnt->Controller[0].pPort->MonType; + TmdsType = pRADEONEnt->Controller[0].pPort->TMDSType; + } else { + MonType = pRADEONEnt->Controller[1].pPort->MonType; + TmdsType = pRADEONEnt->Controller[1].pPort->TMDSType; } - if (Hratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) { - save->fp_horz_stretch = orig->fp_horz_stretch; - save->fp_horz_stretch &= ~(RADEON_HORZ_STRETCH_BLEND | - RADEON_HORZ_STRETCH_ENABLE); - save->fp_horz_stretch &= ~(RADEON_HORZ_AUTO_RATIO | - RADEON_HORZ_PANEL_SIZE); - save->fp_horz_stretch |= ((xres/8-1)<<16); + if (IsPrimary) { + if (info->PanelXRes == 0 || info->PanelYRes == 0) { + Hratio = 1.0; + Vratio = 1.0; + } else { + if (xres > info->PanelXRes) xres = info->PanelXRes; + if (yres > info->PanelYRes) yres = info->PanelYRes; - } else { - save->fp_horz_stretch = - ((((unsigned long)(Hratio * RADEON_HORZ_STRETCH_RATIO_MAX + - 0.5)) & RADEON_HORZ_STRETCH_RATIO_MASK)) | - (orig->fp_horz_stretch & (RADEON_HORZ_PANEL_SIZE | - RADEON_HORZ_FP_LOOP_STRETCH | - RADEON_HORZ_AUTO_RATIO_INC)); - save->fp_horz_stretch |= (RADEON_HORZ_STRETCH_BLEND | - RADEON_HORZ_STRETCH_ENABLE); - - save->fp_horz_stretch &= ~(RADEON_HORZ_AUTO_RATIO | - RADEON_HORZ_PANEL_SIZE); - save->fp_horz_stretch |= ((info->PanelXRes / 8 - 1) << 16); + Hratio = (float)xres/(float)info->PanelXRes; + Vratio = (float)yres/(float)info->PanelYRes; + } - } + save->fp_vert_stretch &= RADEON_VERT_STRETCH_RESERVED; + save->fp_horz_stretch &= (RADEON_HORZ_FP_LOOP_STRETCH | + RADEON_HORZ_AUTO_RATIO_INC); - if (Vratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) { - save->fp_vert_stretch = orig->fp_vert_stretch; - save->fp_vert_stretch &= ~(RADEON_VERT_STRETCH_ENABLE| - RADEON_VERT_STRETCH_BLEND); - save->fp_vert_stretch &= ~(RADEON_VERT_AUTO_RATIO_EN | - RADEON_VERT_PANEL_SIZE); - save->fp_vert_stretch |= ((yres-1) << 12); - } else { - save->fp_vert_stretch = - (((((unsigned long)(Vratio * RADEON_VERT_STRETCH_RATIO_MAX + - 0.5)) & RADEON_VERT_STRETCH_RATIO_MASK)) | - (orig->fp_vert_stretch & (RADEON_VERT_PANEL_SIZE | - RADEON_VERT_STRETCH_RESERVED))); - save->fp_vert_stretch |= (RADEON_VERT_STRETCH_ENABLE | - RADEON_VERT_STRETCH_BLEND); - - save->fp_vert_stretch &= ~(RADEON_VERT_AUTO_RATIO_EN | - RADEON_VERT_PANEL_SIZE); - save->fp_vert_stretch |= ((info->PanelYRes-1) << 12); + if (Hratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) { + save->fp_horz_stretch |= ((xres/8-1)<<16); + } else { + save->fp_horz_stretch |= ((((unsigned long)(Hratio * RADEON_HORZ_STRETCH_RATIO_MAX + + 0.5)) & RADEON_HORZ_STRETCH_RATIO_MASK) | + RADEON_HORZ_STRETCH_BLEND | + RADEON_HORZ_STRETCH_ENABLE | + ((info->PanelXRes/8-1)<<16)); + } - } + if (Vratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) { + save->fp_vert_stretch |= ((yres-1)<<12); + } else { + save->fp_vert_stretch |= ((((unsigned long)(Vratio * RADEON_VERT_STRETCH_RATIO_MAX + + 0.5)) & RADEON_VERT_STRETCH_RATIO_MASK) | + RADEON_VERT_STRETCH_ENABLE | + RADEON_VERT_STRETCH_BLEND | + ((info->PanelYRes-1)<<12)); + } + } - save->fp_gen_cntl = (orig->fp_gen_cntl & (CARD32) - ~(RADEON_FP_SEL_CRTC2 | - RADEON_FP_RMX_HVSYNC_CONTROL_EN | - RADEON_FP_DFP_SYNC_SEL | - RADEON_FP_CRT_SYNC_SEL | - RADEON_FP_CRTC_LOCK_8DOT | - RADEON_FP_USE_SHADOW_EN | - RADEON_FP_CRTC_USE_SHADOW_VEND | - RADEON_FP_CRT_SYNC_ALT)); save->fp_gen_cntl |= (RADEON_FP_CRTC_DONT_SHADOW_VPAR | RADEON_FP_CRTC_DONT_SHADOW_HEND ); - if (pScrn->rgbBits == 8) - save->fp_gen_cntl |= RADEON_FP_PANEL_FORMAT; /* 24 bit format */ + if (pScrn->rgbBits == 8) + save->fp_gen_cntl |= RADEON_FP_PANEL_FORMAT; /* 24 bit format, */ else - save->fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */ - - save->lvds_gen_cntl = orig->lvds_gen_cntl; - save->lvds_pll_cntl = orig->lvds_pll_cntl; + save->fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT; /* 18 bit format, */ info->PanelOff = FALSE; - /* This option is used to force the ONLY DEVICE in XFConfig to use - * CRT port, instead of default DVI port. - */ - if (xf86ReturnOptValBool(info->Options, OPTION_PANEL_OFF, FALSE)) { + /*This option is used to force the ONLY DEVICE in XFConfig to + use CRT port, instead of default DVI port */ + if (xf86ReturnOptValBool (info->Options, OPTION_PANEL_OFF, FALSE)) { info->PanelOff = TRUE; } - save->tmds_pll_cntl = orig->tmds_pll_cntl; - save->tmds_transmitter_cntl= orig->tmds_transmitter_cntl; if (info->PanelOff && info->Clone) { info->OverlayOnCRTC2 = TRUE; - if (info->DisplayType == MT_LCD) { + if (MonType == MT_LCD) { /* Turning off LVDS_ON seems to make panel white blooming. * For now we just turn off display data ??? */ save->lvds_gen_cntl |= (RADEON_LVDS_DISPLAY_DIS); save->lvds_gen_cntl &= ~(RADEON_LVDS_BLON | RADEON_LVDS_ON); - } else if (info->DisplayType == MT_DFP) + } else if (MonType == MT_DFP) save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); } else { - if (info->DisplayType == MT_LCD) { + if (MonType == MT_LCD) { save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON); save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); - } else if (info->DisplayType == MT_DFP) { + } else if ((MonType == MT_DFP) && (TmdsType == TMDS_INT)) { int i; - CARD32 tmp = orig->tmds_pll_cntl & 0xfffff; + CARD32 tmp = save->tmds_pll_cntl & 0xfffff; for (i=0; i<4; i++) { if (info->tmds_pll[i].freq == 0) break; - if (save->dot_clock_freq < info->tmds_pll[i].freq) { + if ((CARD32)(mode->Clock/10) < info->tmds_pll[i].freq) { tmp = info->tmds_pll[i].value ; break; } } - if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350) || + if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_RV280)) { if (tmp & 0xfff00000) save->tmds_pll_cntl = tmp; - else - save->tmds_pll_cntl = (orig->tmds_pll_cntl & 0xfff00000) | tmp; + else { + save->tmds_pll_cntl &= 0xfff00000; + save->tmds_pll_cntl |= tmp; + } } else save->tmds_pll_cntl = tmp; - RADEONTRACE(("TMDS_PLL from %x to %x\n", - orig->tmds_pll_cntl, - save->tmds_pll_cntl)); - save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLRST); - if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350) || + if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_R200) || !info->HasCRTC2) save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN); else /* weird, RV chips got this bit reversed? */ save->tmds_transmitter_cntl |= (RADEON_TMDS_TRANSMITTER_PLLEN); - save->fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); + save->fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); } } if (info->IsMobility) { - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - /* To work correctly with laptop hotkeys. - * Since there is no machnism for accessing ACPI evnets - * and the driver currently doesn't know how to validate - * a mode dynamically, we have to tell BIOS don't do - * display switching after X has started. - * If LCD is on, lid close/open should still work - * with below settings + * Since there is no machnism of handling ACPI evnets, + * we have to tell BIOS don't do display switching after X has started. + * If LCD is on, lid close/open should still work with below settings */ if (info->DisplayType == MT_LCD) { - if (pRADEONEnt->MonType2 == MT_CRT) + if (pRADEONEnt->Controller[1].pPort->MonType == MT_CRT) save->bios_5_scratch = 0x0201; - else if (pRADEONEnt->MonType2 == MT_DFP) + else if (pRADEONEnt->Controller[1].pPort->MonType == MT_DFP) save->bios_5_scratch = 0x0801; - else - save->bios_5_scratch = orig->bios_5_scratch; } else { - if (pRADEONEnt->MonType2 == MT_CRT) + if (pRADEONEnt->Controller[1].pPort->MonType == MT_CRT) save->bios_5_scratch = 0x0200; - else if (pRADEONEnt->MonType2 == MT_DFP) + else if (pRADEONEnt->Controller[1].pPort->MonType == MT_DFP) save->bios_5_scratch = 0x0800; else save->bios_5_scratch = 0x0; } save->bios_4_scratch = 0x4; - save->bios_6_scratch = orig->bios_6_scratch | 0x40000000; + save->bios_6_scratch |= 0x40000000; + } +} + +static void RADEONInitTvDacCntl(ScrnInfoPtr pScrn, RADEONSavePtr save) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + if (info->ChipFamily == CHIP_FAMILY_R420) { + save->tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK | + RADEON_TV_DAC_BGADJ_MASK | + R420_TV_DAC_DACADJ_MASK | + R420_TV_DAC_RDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_TVENABLE); + } else { + save->tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK | + RADEON_TV_DAC_BGADJ_MASK | + RADEON_TV_DAC_DACADJ_MASK | + RADEON_TV_DAC_RDACPD | + RADEON_TV_DAC_GDACPD | + RADEON_TV_DAC_GDACPD); + } + save->tv_dac_cntl = (RADEON_TV_DAC_NBLANK | + RADEON_TV_DAC_NHOLD | + RADEON_TV_DAC_STD_PS2 | + info->tv_dac_adj); +} + +/* Define CRTC registers for requested video mode. */ +Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, RADEONInfoPtr info) +{ + int format; + int hsync_start; + int hsync_wid; + int vsync_wid; + + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + + pRADEONEnt->Controller[0].IsUsed = TRUE; + pRADEONEnt->Controller[0].IsActive = TRUE; + pRADEONEnt->Controller[0].pCurMode = mode; + + switch (info->CurrentLayout.pixel_code) { + case 4: format = 1; break; + case 8: format = 2; break; + case 15: format = 3; break; /* 555 */ + case 16: format = 4; break; /* 565 */ + case 24: format = 5; break; /* RGB */ + case 32: format = 6; break; /* xRGB */ + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Unsupported pixel depth (%d)\n", info->CurrentLayout.bitsPerPixel); + return FALSE; + } + + save->crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN + | RADEON_CRTC_EN + | (format << 8) + | ((mode->Flags & V_DBLSCAN) + ? RADEON_CRTC_DBL_SCAN_EN + : 0) + | ((mode->Flags & V_INTERLACE) + ? RADEON_CRTC_INTERLACE_EN + : 0)); + + save->crtc_ext_cntl |= (RADEON_CRTC_CRT_ON | + RADEON_CRTC_VSYNC_DIS | + RADEON_CRTC_HSYNC_DIS | + RADEON_CRTC_DISPLAY_DIS); + + save->disp_merge_cntl &= ~(1 << 8); + save->crtc_more_cntl = 0; + if ((info->ChipFamily == CHIP_FAMILY_RS100) || + (info->ChipFamily == CHIP_FAMILY_RS200)) { + /* This is to workaround the asic bug for RMX, some versions + of BIOS dosen't have this register initialized correctly. + */ + save->crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN; + } + + if (mode->Flags & RADEON_USE_RMX) { + mode->CrtcHTotal = mode->CrtcHDisplay + info->HBlank; + mode->CrtcHSyncStart = mode->CrtcHDisplay + info->HOverPlus; + mode->CrtcHSyncEnd = mode->CrtcHSyncStart + info->HSyncWidth; + mode->CrtcVTotal = mode->CrtcVDisplay + info->VBlank; + mode->CrtcVSyncStart = mode->CrtcVDisplay + info->VOverPlus; + mode->CrtcVSyncEnd = mode->CrtcVSyncStart + info->VSyncWidth; + mode->Clock = info->DotClock; + mode->Flags = info->Flags | RADEON_USE_RMX; + } + + save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) + | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) << 16)); + + hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; + if (!hsync_wid) hsync_wid = 1; + if (hsync_wid > 0x3f) hsync_wid = 0x3f; + hsync_start = mode->CrtcHSyncStart - 8; + + save->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) + | (hsync_wid << 16) + | ((mode->Flags & V_NHSYNC) + ? RADEON_CRTC_H_SYNC_POL + : RADEON_CRTC_H_SYNC_POL)); + + /* This works for double scan mode. */ + save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) + | ((mode->CrtcVDisplay - 1) << 16)); + + vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; + if (!vsync_wid) vsync_wid = 1; + if (vsync_wid > 0x1f) vsync_wid = 0x1f; + + save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) + | (vsync_wid << 16) + | ((mode->Flags & V_NVSYNC) + ? RADEON_CRTC_V_SYNC_POL + : RADEON_CRTC_V_SYNC_POL)); + + save->crtc_offset = 0; + save->crtc_offset_cntl = 0; + + save->crtc_pitch = ((pScrn->displayWidth * pScrn->bitsPerPixel) + + ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8); + save->crtc_pitch |= save->crtc_pitch << 16; + + save->vclk_cntl = (info->SavedReg.vclk_cntl & + ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK; + + /* Set following registers for all cases first, if a DFP/LCD is connected on + internal TMDS/LVDS port, they will be set by RADEONInitFPRegister + */ + if (!info->IsSwitching) { + save->fp_gen_cntl = 0; + save->fp_vert_stretch &= RADEON_VERT_STRETCH_RESERVED; + save->fp_horz_stretch &= (RADEON_HORZ_FP_LOOP_STRETCH | + RADEON_HORZ_AUTO_RATIO_INC); + } + + if (pRADEONEnt->Controller[0].pPort->MonType == MT_CRT) { + if (pRADEONEnt->Controller[0].pPort->DACType == DAC_PRIMARY) { + if((info->ChipFamily == CHIP_FAMILY_R200) || + IS_R300_VARIANT) { + save->disp_output_cntl &= ~RADEON_DISP_DAC_SOURCE_MASK; + } else { + save->dac2_cntl &= ~(RADEON_DAC2_DAC_CLK_SEL); + } + save->dac_cntl = (RADEON_DAC_MASK_ALL + | RADEON_DAC_VGA_ADR_EN + | (info->dac6bits ? 0 : RADEON_DAC_8BIT_EN)); + } else { + /*0x0028023;*/ + RADEONInitTvDacCntl(pScrn, save); + save->crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON; + save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; + if(IS_R300_VARIANT) { + save->disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK; + save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC; + } else if (info->ChipFamily == CHIP_FAMILY_R200) { + save->fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_RATE_SEL_SDR); + save->fp2_gen_cntl |= (RADEON_FP2_ON | + RADEON_FP2_BLANK_EN | + RADEON_FP2_DVO_EN); + } else { + save->disp_hw_debug |= RADEON_CRT2_DISP1_SEL; + } + } + } else if ((pRADEONEnt->Controller[0].pPort->MonType == MT_DFP) || + (pRADEONEnt->Controller[0].pPort->MonType == MT_LCD)) { + + save->fp_h_sync_strt_wid = save->crtc_h_sync_strt_wid; + save->fp_v_sync_strt_wid = save->crtc_v_sync_strt_wid; + + RADEONInitFPRegisters(pScrn, save, mode, TRUE); + + if ((pRADEONEnt->Controller[0].pPort->TMDSType == TMDS_INT) || + (pRADEONEnt->Controller[0].pPort->MonType == MT_LCD)) { + + if ((IS_R300_VARIANT) || + (info->ChipFamily == CHIP_FAMILY_R200)) { + save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; + if (mode->Flags & RADEON_USE_RMX) + save->fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX; + else + save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1; + } else + save->fp_gen_cntl |= RADEON_FP_SEL_CRTC1; + + } else { + + if((info->ChipFamily == CHIP_FAMILY_R200) || + IS_R300_VARIANT) { + save->fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_EN | + RADEON_FP2_DVO_RATE_SEL_SDR); + if (mode->Flags & RADEON_USE_RMX) + save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX; + } else { + save->fp2_gen_cntl &= ~(RADEON_FP2_SRC_SEL_CRTC2 | + RADEON_FP2_DVO_RATE_SEL_SDR); + } + save->fp2_gen_cntl |= ( RADEON_FP2_ON | + RADEON_FP2_BLANK_EN | + RADEON_FP2_DVO_EN); + if (pScrn->rgbBits == 8) + save->fp2_gen_cntl |= RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */ + else + save->fp2_gen_cntl &= ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */ + } + } + + return TRUE; +} + +/* Define CRTC2 registers for requested video mode. */ +Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, RADEONInfoPtr info) +{ + int format; + int hsync_start; + int hsync_wid; + int vsync_wid; + + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RADEONInfoPtr info0 = NULL; + if (info->IsSecondary) + info0 = RADEONPTR(pRADEONEnt->pPrimaryScrn); + + pRADEONEnt->Controller[1].IsUsed = TRUE; + pRADEONEnt->Controller[1].IsActive = TRUE; + pRADEONEnt->Controller[1].pCurMode = mode; + + switch (info->CurrentLayout.pixel_code) { + case 4: format = 1; + break; + case 8: format = 2; + break; + case 15: format = 3; + break; /* 555 */ + case 16: format = 4; + break; /* 565 */ + case 24: format = 5; + break; /* RGB */ + case 32: format = 6; + break; /* xRGB */ + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Unsupported pixel depth (%d)\n", info->CurrentLayout.bitsPerPixel); + return FALSE; } - save->fp_crtc_h_total_disp = save->crtc_h_total_disp; - save->fp_crtc_v_total_disp = save->crtc_v_total_disp; - save->fp_h_sync_strt_wid = save->crtc_h_sync_strt_wid; - save->fp_v_sync_strt_wid = save->crtc_v_sync_strt_wid; + save->crtc2_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) + | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) << 16)); + + hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; + if (!hsync_wid) hsync_wid = 1; + if (hsync_wid > 0x3f) hsync_wid = 0x3f; + hsync_start = mode->CrtcHSyncStart - 8; + + save->crtc2_h_sync_strt_wid = ((hsync_start & 0x1fff) + | (hsync_wid << 16) + | ((mode->Flags & V_NHSYNC) + ? RADEON_CRTC_H_SYNC_POL + : RADEON_CRTC_H_SYNC_POL)); + + /* This works for double scan mode. */ + save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) + | ((mode->CrtcVDisplay - 1) << 16)); + + vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; + if (!vsync_wid) vsync_wid = 1; + if (vsync_wid > 0x1f) vsync_wid = 0x1f; + + save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) + | (vsync_wid << 16) + | ((mode->Flags & V_NVSYNC) + ? RADEON_CRTC2_V_SYNC_POL + : RADEON_CRTC2_V_SYNC_POL)); + + save->crtc2_offset = 0; + save->crtc2_offset_cntl = 0; + + save->crtc2_pitch = ((pScrn->displayWidth * pScrn->bitsPerPixel) + + ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8); + save->crtc2_pitch |= save->crtc2_pitch << 16; + + save->crtc2_gen_cntl = (RADEON_CRTC2_EN + | RADEON_CRTC2_CRT2_ON + | (format << 8) + | RADEON_CRTC2_VSYNC_DIS + | RADEON_CRTC2_HSYNC_DIS + | RADEON_CRTC2_DISP_DIS + | ((mode->Flags & V_DBLSCAN) + ? RADEON_CRTC2_DBL_SCAN_EN + : 0) + | ((mode->Flags & V_INTERLACE) + ? RADEON_CRTC2_INTERLACE_EN + : 0)); + + save->disp2_merge_cntl &= ~(1 << 8); + + if (pRADEONEnt->Controller[1].pPort->MonType == MT_CRT) { + if (pRADEONEnt->Controller[1].pPort->DACType == DAC_PRIMARY) { + if((info->ChipFamily == CHIP_FAMILY_R200) || + IS_R300_VARIANT) { + save->disp_output_cntl &= ~RADEON_DISP_DAC_SOURCE_MASK; + save->disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2; + } else { + save->dac2_cntl |= RADEON_DAC2_DAC_CLK_SEL; + } + } else { + /*save->tv_dac_cntl = 0x0028023;*/ + RADEONInitTvDacCntl(pScrn, save); + if(IS_R300_VARIANT) { + save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; + save->disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK; + save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2; + } else if (info->ChipFamily == CHIP_FAMILY_R200) { + save->fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_RATE_SEL_SDR); + save->fp2_gen_cntl |= (R200_FP2_SOURCE_SEL_CRTC2 | + RADEON_FP2_BLANK_EN | + RADEON_FP2_ON | + RADEON_FP2_DVO_EN); + save->fp_h2_sync_strt_wid = save->crtc2_h_sync_strt_wid; + save->fp_v2_sync_strt_wid = save->crtc2_v_sync_strt_wid; + } else { + save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; + save->disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL; + } + } + } else if ((pRADEONEnt->Controller[1].pPort->MonType == MT_DFP) || + (pRADEONEnt->Controller[1].pPort->MonType == MT_LCD)) { + + save->fp_h2_sync_strt_wid = save->crtc2_h_sync_strt_wid; + save->fp_v2_sync_strt_wid = save->crtc2_v_sync_strt_wid; + + if ((pRADEONEnt->Controller[1].pPort->TMDSType == TMDS_INT) || + (pRADEONEnt->Controller[1].pPort->MonType == MT_LCD)) { + + RADEONInitFPRegisters(pScrn, save, mode, FALSE); + + if ((IS_R300_VARIANT) || + (info->ChipFamily == CHIP_FAMILY_R200)) { + save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; + save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC2; + } else + save->fp_gen_cntl |= RADEON_FP_SEL_CRTC2; + } else { + if((info->ChipFamily == CHIP_FAMILY_R200) || + IS_R300_VARIANT) { + save->fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_RATE_SEL_SDR); + save->fp2_gen_cntl |= (R200_FP2_SOURCE_SEL_CRTC2 | + RADEON_FP2_PANEL_FORMAT | + RADEON_FP2_BLANK_EN | + RADEON_FP2_ON | + RADEON_FP2_DVO_EN); + } else { + save->fp2_gen_cntl &= ~(RADEON_FP2_DVO_RATE_SEL_SDR); + save->fp2_gen_cntl |= (RADEON_FP2_SRC_SEL_CRTC2 | + RADEON_FP2_PANEL_FORMAT | + RADEON_FP2_BLANK_EN | + RADEON_FP2_ON | + RADEON_FP2_DVO_EN); + } + if (pScrn->rgbBits == 8) + save->fp2_gen_cntl |= RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */ + else + save->fp2_gen_cntl &= ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */ + } + } + + save->pixclks_cntl = ((info->SavedReg.pixclks_cntl & + ~(RADEON_PIX2CLK_SRC_SEL_MASK)) | + RADEON_PIX2CLK_SRC_SEL_P2PLLCLK); + + return TRUE; } + /* Define PLL registers for requested video mode */ -static void RADEONInitPLLRegisters(RADEONSavePtr save, RADEONPLLPtr pll, +static void RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, RADEONPLLPtr pll, double dot_clock) { unsigned long freq = dot_clock * 100; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RADEONInfoPtr info = RADEONPTR(pScrn); struct { int divider; @@ -6504,8 +4927,14 @@ if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12; for (post_div = &post_divs[0]; post_div->divider; ++post_div) { + + if ((pRADEONEnt->Controller[0].pPort->MonType == MT_DFP) && + (pRADEONEnt->Controller[0].pPort->TMDSType == TMDS_EXT)) { + /* DVO doesn't work well with odd divides */ + if ((post_div->divider == 1) || (post_div->divider == 3)) continue; + } + save->pll_output_freq = post_div->divider * freq; - if (save->pll_output_freq >= pll->min_pll_freq && save->pll_output_freq <= pll->max_pll_freq) break; } @@ -6527,16 +4956,31 @@ save->feedback_div, save->post_div)); - save->ppll_ref_div = pll->reference_div; save->ppll_div_3 = (save->feedback_div | (post_div->bitvalue << 16)); save->htotal_cntl = 0; + + if (IS_R300_VARIANT || + (info->ChipFamily == CHIP_FAMILY_RS300)) { + save->ppll_ref_div &= ~R300_PPLL_REF_DIV_ACC_MASK; + save->ppll_ref_div |= (pll->reference_div << R300_PPLL_REF_DIV_ACC_SHIFT); + } else { + save->ppll_ref_div &= ~RADEON_PPLL_REF_DIV_MASK; + save->ppll_ref_div |= pll->reference_div; + } + + /* select secondary reference source. */ + if (info->IsIGP) { + save->ppll_ref_div &= ~(3<<16); + save->ppll_ref_div |= (3<<16); + } } /* Define PLL2 registers for requested video mode */ -static void RADEONInitPLL2Registers(RADEONSavePtr save, RADEONPLLPtr pll, +static void RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, RADEONPLLPtr pll, double dot_clock) { unsigned long freq = dot_clock * 100; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); struct { int divider; @@ -6561,6 +5005,13 @@ if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12; for (post_div = &post_divs[0]; post_div->divider; ++post_div) { + + if ((pRADEONEnt->Controller[1].pPort->MonType == MT_DFP) && + (pRADEONEnt->Controller[1].pPort->TMDSType == TMDS_EXT)) { + /* DVO doesn't work well with odd divides */ + if ((post_div->divider == 1) || (post_div->divider == 3)) continue; + } + save->pll_output_freq_2 = post_div->divider * freq; if (save->pll_output_freq_2 >= pll->min_pll_freq && save->pll_output_freq_2 <= pll->max_pll_freq) break; @@ -6589,19 +5040,14 @@ save->htotal_cntl2 = 0; } -/* Define initial palette for requested video mode. This doesn't do - * anything for XFree86 4.0. - */ -static void RADEONInitPalette(RADEONSavePtr save) -{ - save->palette_valid = FALSE; -} - /* Define registers for a requested video mode */ static Bool RADEONInit(ScrnInfoPtr pScrn, DisplayModePtr mode, RADEONSavePtr save) { RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RADEONInfoPtr info0 = NULL; + ScrnInfoPtr pScrn0 = NULL; double dot_clock = mode->Clock/1000.0; #if RADEON_DEBUG @@ -6657,9 +5103,12 @@ RADEONInitCommonRegisters(save, info); if (info->IsSecondary) { - if (!RADEONInitCrtc2Registers(pScrn, save, mode, info)) - return FALSE; - RADEONInitPLL2Registers(save, &info->pll, dot_clock); + pScrn0 = pRADEONEnt->pPrimaryScrn; + info0 = RADEONPTR(pScrn0); + RADEONInitCrtc2Registers(pScrn, save, mode, info); + RADEONInitPLL2Registers(pScrn, save, &info->pll, dot_clock); + /* Make sure primary has the same copy */ + memcpy(&info0->ModeReg, save, sizeof(RADEONSaveRec)); } else { if (!RADEONInitCrtcRegisters(pScrn, save, mode, info)) return FALSE; @@ -6671,23 +5120,25 @@ save->htotal_cntl = 0; } else - RADEONInitPLLRegisters(save, &info->pll, dot_clock); + RADEONInitPLLRegisters(pScrn, save, &info->pll, dot_clock); } else { save->ppll_ref_div = info->SavedReg.ppll_ref_div; save->ppll_div_3 = info->SavedReg.ppll_div_3; save->htotal_cntl = info->SavedReg.htotal_cntl; } - if (info->Clone && info->CurCloneMode) { + if (pRADEONEnt->HasSecondary) { + pScrn0 = pRADEONEnt->pSecondaryScrn; + info0 = RADEONPTR(pScrn0); + /* carry over to secondary screen */ + memcpy(&info0->ModeReg, save, sizeof(RADEONSaveRec)); + } else if (info->Clone && info->CurCloneMode) { RADEONInitCrtc2Registers(pScrn, save, info->CurCloneMode, info); dot_clock = info->CurCloneMode->Clock / 1000.0; - RADEONInitPLL2Registers(save, &info->pll, dot_clock); + RADEONInitPLL2Registers(pScrn, save, &info->pll, dot_clock); } - if (!info->PaletteSavedOnVT) RADEONInitPalette(save); } - RADEONInitFPRegisters(pScrn, &info->SavedReg, save, mode, info); - RADEONTRACE(("RADEONInit returns %p\n", save)); return TRUE; } @@ -6696,13 +5147,21 @@ static Bool RADEONModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) { RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + static int ScreenCount = 0; + ScreenCount++; if (!RADEONInit(pScrn, mode, &info->ModeReg)) return FALSE; - pScrn->vtSema = TRUE; - RADEONBlank(pScrn); - RADEONRestoreMode(pScrn, &info->ModeReg); - RADEONUnblank(pScrn); + /* Make sure all restore routines are only called once + after everything is initialized + */ + if ((!pRADEONEnt->HasSecondary) || info->IsSwitching || (ScreenCount == 2)) { + ScreenCount = 0; + if (!info->IsSwitching) + RADEONRestoreCommonRegisters(pScrn, &info->ModeReg); + RADEONRestoreMode(pScrn, &info->ModeReg); + } info->CurrentLayout.mode = mode; @@ -6743,6 +5202,10 @@ if (info->accelOn) info->accel->Sync(pScrn); + /*__asm__ __volatile__ ("int $3");*/ + + info->IsSwitching = TRUE; + RADEONBlank(pScrn); if (info->FBDev) { RADEONSaveFBDevRegisters(pScrn, &info->ModeReg); @@ -6750,7 +5213,6 @@ RADEONRestoreFBDevRegisters(pScrn, &info->ModeReg); } else { - info->IsSwitching = TRUE; if (info->Clone && info->CloneModes) { DisplayModePtr clone_mode = info->CloneModes; @@ -6780,6 +5242,7 @@ clone_mode = clone_mode->next; } } + ret = RADEONModeInit(xf86Screens[scrnIndex], mode); if (info->CurCloneMode) { @@ -6800,8 +5263,6 @@ RADEONDoAdjustFrame(pScrn, info->CloneFrameX0, info->CloneFrameY0, TRUE); } - - info->IsSwitching = FALSE; } if (info->accelOn) { @@ -6815,6 +5276,8 @@ DRIUnlock(pScrn->pScreen); } #endif + RADEONUnblank(pScrn); + info->IsSwitching = FALSE; return ret; } @@ -6920,19 +5383,27 @@ { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + static int ScreenCount = 0; RADEONTRACE(("RADEONEnterVT\n")); + ScreenCount++; + if ((!pRADEONEnt->HasSecondary) || (ScreenCount == 2)) { + RADEONRestorePalette(pScrn, &info->ModeReg); + ScreenCount = 0; + } + + RADEONSaveScreen(pScrn->pScreen, SCREEN_SAVER_ON); if (info->FBDev) { unsigned char *RADEONMMIO = info->MMIO; if (!fbdevHWEnterVT(scrnIndex,flags)) return FALSE; - info->PaletteSavedOnVT = FALSE; info->ModeReg.surface_cntl = INREG(RADEON_SURFACE_CNTL); RADEONRestoreFBDevRegisters(pScrn, &info->ModeReg); - } else + } else { if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE; - + } #ifdef XF86DRI if (info->directRenderingEnabled) { /* get the Radeon back into shape after resume */ @@ -6943,7 +5414,7 @@ during server startup (hence the info->adaptor if). */ if (info->adaptor) RADEONResetVideo(pScrn); - + if (info->accelOn) RADEONEngineRestore(pScrn); @@ -6969,9 +5440,21 @@ { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONSavePtr save = &info->ModeReg; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RADEONInfoPtr info0 = NULL; + ScrnInfoPtr pScrn0 = NULL; + static int ScreenCount = 0; RADEONTRACE(("RADEONLeaveVT\n")); + + ScreenCount++; + + if (pRADEONEnt->HasSecondary) { + if (info->IsSecondary) pScrn0 = pRADEONEnt->pPrimaryScrn; + else pScrn0 = pRADEONEnt->pSecondaryScrn; + info0 = RADEONPTR(pScrn0); + } + #ifdef XF86DRI if (RADEONPTR(pScrn)->directRenderingEnabled) { DRILock(pScrn->pScreen, 0); @@ -6979,12 +5462,21 @@ } #endif - if (info->FBDev) { - RADEONSavePalette(pScrn, save); - info->PaletteSavedOnVT = TRUE; + /* save current palette for VT switching back */ + if (ScreenCount == 1) { + if (!pRADEONEnt->HasSecondary) ScreenCount = 0; + RADEONSavePalette(pScrn, &info->ModeReg); + if (info0) { /* copy to other screen with the same saved palette */ + memcpy ((char*)info0->ModeReg.palette, + (char*)info->ModeReg.palette, + sizeof(info->ModeReg.palette)*2); + } + } else { + ScreenCount = 0; + } + if (info->FBDev) { RADEONSaveFBDevRegisters(pScrn, &info->ModeReg); - fbdevHWLeaveVT(scrnIndex,flags); } @@ -7046,257 +5538,3 @@ vgaHWFreeHWRec(pScrn); 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; - -#ifdef XF86DRI - if (info->CPStarted) DRILock(pScrn->pScreen, 0); -#endif - - if (info->accelOn) info->accel->Sync(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->Clone) - 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->Clone) - 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->Clone) - 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->Clone) - 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->Clone) { - if (info->CloneType == 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->CloneType == MT_CRT) { - RADEONDacPowerSet(pScrn, TRUE, !pRADEONEnt->ReversedDAC); - } - } - 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->Clone) { - 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->Clone) { - if(info->CloneType == 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->CloneType == MT_CRT) { - RADEONDacPowerSet(pScrn, FALSE, !pRADEONEnt->ReversedDAC); - } - } - 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(RADEON_PIXCLKS_CNTL, tmpPixclksCntl); - } - } else if (info->DisplayType == MT_CRT) { - if ((pRADEONEnt->HasSecondary) || info->Clone) { - 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 -} --- xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.c.new_chips 2004-05-10 09:42:45.000000000 -0400 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.c 2004-05-13 10:29:09.000000000 -0400 @@ -113,6 +113,8 @@ { PCI_CHIP_RV250_Lg, "ATI Radeon Mobility 9000 (M9) Lg (AGP)" }, { PCI_CHIP_RS300_5834, "ATI Radeon 9100 IGP (A5) 5834" }, { PCI_CHIP_RS300_5835, "ATI Radeon Mobility 9100 IGP (U3) 5835" }, + { PCI_CHIP_RS350_7834, "ATI Radeon 9100 PRO IGP 7834" }, + { PCI_CHIP_RS350_7835, "ATI Radeon Mobility 9200 IGP 7835" }, { PCI_CHIP_RV280_5960, "ATI Radeon 9200PRO 5960 (AGP)" }, { PCI_CHIP_RV280_5961, "ATI Radeon 9200 5961 (AGP)" }, { PCI_CHIP_RV280_5962, "ATI Radeon 9200 5962 (AGP)" }, @@ -147,6 +149,62 @@ { PCI_CHIP_R350_NI, "ATI Radeon 9800 NI (AGP)" }, { PCI_CHIP_R350_NK, "ATI FireGL X2 NK (AGP)" }, { PCI_CHIP_R360_NJ, "ATI Radeon 9800XT NJ (AGP)" }, + { PCI_CHIP_RV380_3E50, "ATI Radeon X600 (RV380) 3E50 (PCIE)" }, + { PCI_CHIP_RV380_3E54, "ATI Radeon X600 (RV380) 3E54 (PCIE)" }, + { PCI_CHIP_RV380_3150, "ATI Radeon Mobility X600 (M24) 3150 (PCIE)" }, + { PCI_CHIP_RV380_3154, "ATI Radeon Mobility X600 (M24) 3154 (PCIE)" }, + { PCI_CHIP_RV370_5B60, "ATI Radeon X300 (RV370) 5B60 (PCIE)" }, + { PCI_CHIP_RV370_5B62, "ATI Radeon X600 (RV370) 5B62 (PCIE)" }, + { PCI_CHIP_RV370_5B64, "ATI Radeon X300 (RV370) 5B64 (PCIE)" }, + { PCI_CHIP_RV370_5B65, "ATI Radeon X300 (RV370) 5B65 (PCIE)" }, + { PCI_CHIP_RV370_5460, "ATI Radeon Mobility X300 (M22) 5460 (PCIE)" }, + { PCI_CHIP_RV370_5464, "ATI Radeon Mobility X300 (M22) 5464 (PCIE)" }, + { PCI_CHIP_R420_JH, "ATI Radeon X800 (R420) JH (AGP)" }, + { PCI_CHIP_R420_JI, "ATI Radeon X800 (R420) JI (AGP)" }, + { PCI_CHIP_R420_JJ, "ATI Radeon X800 (R420) JJ (AGP)" }, + { PCI_CHIP_R420_JK, "ATI Radeon X800 (R420) JK (AGP)" }, + { PCI_CHIP_R420_JL, "ATI Radeon X800 (R420) JL (AGP)" }, + { PCI_CHIP_R420_JM, "ATI Radeon X800 (R420) JM (AGP)" }, + { PCI_CHIP_R420_JN, "ATI Radeon Mobility M18 JN (AGP)" }, + { PCI_CHIP_R420_JP, "ATI Radeon X800 (R420) JP (AGP)" }, + { PCI_CHIP_R423_UH, "ATI Radeon X800 (R423) UH (PCIE)" }, + { PCI_CHIP_R423_UI, "ATI Radeon X800 (R423) UI (PCIE)" }, + { PCI_CHIP_R423_UJ, "ATI Radeon X800 (R423) UJ (PCIE)" }, + { PCI_CHIP_R423_UK, "ATI Radeon X800 (R423) UK (PCIE)" }, + { PCI_CHIP_R423_UQ, "ATI FireGL X800 (R423) UQ (PCIE)" }, + { PCI_CHIP_R423_UR, "ATI FireGL X800 (R423) UR (PCIE)" }, + { PCI_CHIP_R423_UT, "ATI FireGL X800 (R423) UT (PCIE)" }, + { PCI_CHIP_R423_5D57, "ATI Radeon X800 (R423) 5D57 (PCIE)" }, + +/* + { PCI_CHIP_RV380_3E50, "ATI Radeon X600 (RV380) 3E50 (PCIE)" }, + { PCI_CHIP_RV380_3E54, "ATI FireGL V3200 (RV380) 3E54 (PCIE)" }, + { PCI_CHIP_RV380_3150, "ATI Radeon Mobility X600 (M24) 3150 (PCIE)" }, + { PCI_CHIP_RV380_3154, "ATI FireGL M24 GL 3154 (PCIE)" }, + { PCI_CHIP_RV370_5B60, "ATI Radeon X300 (RV370) 5B60 (PCIE)" }, + { PCI_CHIP_RV370_5B62, "ATI Radeon X600 (RV370) 5B62 (PCIE)" }, + { PCI_CHIP_RV370_5B64, "ATI FireGL V3100 (RV370) 5B64 (PCIE)" }, + { PCI_CHIP_RV370_5B65, "ATI FireGL D1100 (RV370) 5B65 (PCIE)" }, + { PCI_CHIP_RV370_5460, "ATI Radeon Mobility M300 (M22) 5460 (PCIE)" }, + { PCI_CHIP_RV370_5464, "ATI FireGL M22 GL 5464 (PCIE)" }, + { PCI_CHIP_R420_JH, "ATI Radeon X800 (R420) JH (AGP)" }, + { PCI_CHIP_R420_JI, "ATI Radeon X800PRO (R420) JI (AGP)" }, + { PCI_CHIP_R420_JJ, "ATI Radeon X800SE (R420) JJ (AGP)" }, + { PCI_CHIP_R420_JK, "ATI Radeon X800 (R420) JK (AGP)" }, + { PCI_CHIP_R420_JL, "ATI Radeon X800 (R420) JL (AGP)" }, + { PCI_CHIP_R420_JM, "ATI FireGL X3 (R420) JM (AGP)" }, + { PCI_CHIP_R420_JN, "ATI Radeon Mobility 9800 (M18) JN (AGP)" }, + { PCI_CHIP_R420_JP, "ATI Radeon X800XT (R420) JP (AGP)" }, + { PCI_CHIP_R423_UH, "ATI Radeon X800 (R423) UH (PCIE)" }, + { PCI_CHIP_R423_UI, "ATI Radeon X800PRO (R423) UI (PCIE)" }, + { PCI_CHIP_R423_UJ, "ATI Radeon X800LE (R423) UJ (PCIE)" }, + { PCI_CHIP_R423_UK, "ATI Radeon X800SE (R423) UK (PCIE)" }, + { PCI_CHIP_R423_UQ, "ATI FireGL V7200 (R423) UQ (PCIE)" }, + { PCI_CHIP_R423_UR, "ATI FireGL V5100 (R423) UR (PCIE)" }, + { PCI_CHIP_R423_UT, "ATI FireGL V7100 (R423) UT (PCIE)" }, + { PCI_CHIP_R423_5D57, "ATI Radeon X800XT (R423) 5D57 (PCIE)" }, +*/ + { -1, NULL } }; @@ -181,6 +239,8 @@ { PCI_CHIP_RV250_Lg, PCI_CHIP_RV250_Lg, RES_SHARED_VGA }, { PCI_CHIP_RS300_5834, PCI_CHIP_RS300_5834, RES_SHARED_VGA }, { PCI_CHIP_RS300_5835, PCI_CHIP_RS300_5835, RES_SHARED_VGA }, + { PCI_CHIP_RS350_7834, PCI_CHIP_RS350_7834, RES_SHARED_VGA }, + { PCI_CHIP_RS350_7835, PCI_CHIP_RS350_7835, RES_SHARED_VGA }, { PCI_CHIP_RV280_5960, PCI_CHIP_RV280_5960, RES_SHARED_VGA }, { PCI_CHIP_RV280_5961, PCI_CHIP_RV280_5961, RES_SHARED_VGA }, { PCI_CHIP_RV280_5962, PCI_CHIP_RV280_5962, RES_SHARED_VGA }, @@ -215,6 +275,33 @@ { PCI_CHIP_R350_NI, PCI_CHIP_R350_NI, RES_SHARED_VGA }, { PCI_CHIP_R350_NK, PCI_CHIP_R350_NK, RES_SHARED_VGA }, { PCI_CHIP_R360_NJ, PCI_CHIP_R360_NJ, RES_SHARED_VGA }, + { PCI_CHIP_RV380_3E50, PCI_CHIP_RV380_3E50, RES_SHARED_VGA }, + { PCI_CHIP_RV380_3E54, PCI_CHIP_RV380_3E54, RES_SHARED_VGA }, + { PCI_CHIP_RV380_3150, PCI_CHIP_RV380_3150, RES_SHARED_VGA }, + { PCI_CHIP_RV380_3154, PCI_CHIP_RV380_3154, RES_SHARED_VGA }, + { PCI_CHIP_RV370_5B60, PCI_CHIP_RV370_5B60, RES_SHARED_VGA }, + { PCI_CHIP_RV370_5B62, PCI_CHIP_RV370_5B62, RES_SHARED_VGA }, + { PCI_CHIP_RV370_5B64, PCI_CHIP_RV370_5B64, RES_SHARED_VGA }, + { PCI_CHIP_RV370_5B65, PCI_CHIP_RV370_5B65, RES_SHARED_VGA }, + { PCI_CHIP_RV370_5460, PCI_CHIP_RV370_5460, RES_SHARED_VGA }, + { PCI_CHIP_RV370_5464, PCI_CHIP_RV370_5464, RES_SHARED_VGA }, + { PCI_CHIP_R420_JH, PCI_CHIP_R420_JH, RES_SHARED_VGA }, + { PCI_CHIP_R420_JI, PCI_CHIP_R420_JI, RES_SHARED_VGA }, + { PCI_CHIP_R420_JJ, PCI_CHIP_R420_JJ, RES_SHARED_VGA }, + { PCI_CHIP_R420_JK, PCI_CHIP_R420_JK, RES_SHARED_VGA }, + { PCI_CHIP_R420_JL, PCI_CHIP_R420_JL, RES_SHARED_VGA }, + { PCI_CHIP_R420_JM, PCI_CHIP_R420_JM, RES_SHARED_VGA }, + { PCI_CHIP_R420_JN, PCI_CHIP_R420_JN, RES_SHARED_VGA }, + { PCI_CHIP_R420_JP, PCI_CHIP_R420_JP, RES_SHARED_VGA }, + { PCI_CHIP_R423_UH, PCI_CHIP_R423_UH, RES_SHARED_VGA }, + { PCI_CHIP_R423_UI, PCI_CHIP_R423_UI, RES_SHARED_VGA }, + { PCI_CHIP_R423_UJ, PCI_CHIP_R423_UJ, RES_SHARED_VGA }, + { PCI_CHIP_R423_UK, PCI_CHIP_R423_UK, RES_SHARED_VGA }, + { PCI_CHIP_R423_UQ, PCI_CHIP_R423_UQ, RES_SHARED_VGA }, + { PCI_CHIP_R423_UR, PCI_CHIP_R423_UR, RES_SHARED_VGA }, + { PCI_CHIP_R423_UT, PCI_CHIP_R423_UT, RES_SHARED_VGA }, + { PCI_CHIP_R423_5D57, PCI_CHIP_R423_5D57, RES_SHARED_VGA }, + { -1, -1, RES_UNDEFINED } }; @@ -363,7 +450,6 @@ pPriv->ptr = xnfcalloc(sizeof(RADEONEntRec), 1); pRADEONEnt = pPriv->ptr; pRADEONEnt->HasSecondary = FALSE; - pRADEONEnt->IsSecondaryRestored = FALSE; } else { pRADEONEnt = pPriv->ptr; pRADEONEnt->HasSecondary = TRUE; --- xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c.new_chips 2004-05-10 09:42:45.000000000 -0400 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c 2004-05-10 09:42:44.000000000 -0400 @@ -207,14 +207,11 @@ host_path_cntl = INREG(RADEON_HOST_PATH_CNTL); rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET); - if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350)) { + if (IS_R300_VARIANT) { CARD32 tmp; OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset | RADEON_SOFT_RESET_CP | - RADEON_SOFT_RESET_HI | RADEON_SOFT_RESET_E2)); INREG(RADEON_RBBM_SOFT_RESET); OUTREG(RADEON_RBBM_SOFT_RESET, 0); @@ -223,7 +220,6 @@ } else { OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset | RADEON_SOFT_RESET_CP | - RADEON_SOFT_RESET_HI | RADEON_SOFT_RESET_SE | RADEON_SOFT_RESET_RE | RADEON_SOFT_RESET_PP | @@ -232,7 +228,6 @@ INREG(RADEON_RBBM_SOFT_RESET); OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset & (CARD32) ~(RADEON_SOFT_RESET_CP | - RADEON_SOFT_RESET_HI | RADEON_SOFT_RESET_SE | RADEON_SOFT_RESET_RE | RADEON_SOFT_RESET_PP | @@ -245,9 +240,7 @@ INREG(RADEON_HOST_PATH_CNTL); OUTREG(RADEON_HOST_PATH_CNTL, host_path_cntl); - if ((info->ChipFamily != CHIP_FAMILY_R300) && - (info->ChipFamily != CHIP_FAMILY_R350) && - (info->ChipFamily != CHIP_FAMILY_RV350)) + if (!IS_R300_VARIANT) OUTREG(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset); OUTREG(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index); @@ -275,9 +268,7 @@ */ /* Turn of all automatic flushing - we'll do it all */ - if ((info->ChipFamily != CHIP_FAMILY_R300) && - (info->ChipFamily != CHIP_FAMILY_R350) && - (info->ChipFamily != CHIP_FAMILY_RV350)) + if (!IS_R300_VARIANT) OUTREG(RADEON_RB2D_DSTCACHE_MODE, 0); pitch64 = ((pScrn->displayWidth * (pScrn->bitsPerPixel / 8) + 0x3f)) >> 6; --- xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h.new_chips 2004-05-10 09:42:45.000000000 -0400 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h 2004-05-15 20:16:58.000000000 -0400 @@ -52,7 +52,8 @@ /* Xv support */ #include "xf86xv.h" - +#include "vbe.h" +#include "radeon_probe.h" /* DRI support */ #ifdef XF86DRI #define _XF86DRI_SERVER_ @@ -93,6 +94,43 @@ #define RADEON_ALIGN(x,bytes) (((x) + ((bytes) - 1)) & ~((bytes) - 1)) #define RADEONPTR(pScrn) ((RADEONInfoPtr)(pScrn)->driverPrivate) +typedef enum { + OPTION_NOACCEL, + OPTION_SW_CURSOR, + OPTION_DAC_6BIT, + OPTION_DAC_8BIT, +#ifdef XF86DRI + OPTION_IS_PCI, + OPTION_BUS_TYPE, + OPTION_CP_PIO, + OPTION_USEC_TIMEOUT, + OPTION_AGP_MODE, + OPTION_AGP_FW, + OPTION_GART_SIZE, + OPTION_RING_SIZE, + OPTION_BUFFER_SIZE, + OPTION_DEPTH_MOVE, + OPTION_PAGE_FLIP, + OPTION_NO_BACKBUFFER, +#endif + OPTION_PANEL_OFF, + OPTION_DDC_MODE, + OPTION_MONITOR_LAYOUT, + OPTION_IGNORE_EDID, + OPTION_CRTC2_OVERLAY, + OPTION_CLONE_MODE, + OPTION_CLONE_HSYNC, + OPTION_CLONE_VREFRESH, + OPTION_FBDEV, + OPTION_VIDEO_KEY, + OPTION_DISP_PRIORITY, + OPTION_PANEL_SIZE, + OPTION_MIN_DOTCLOCK, + OPTION_REVERSE_DISPLAY, + OPTION_NOBIOS, + OPTION_REF_CLOCK +} RADEONOpts; + typedef struct { /* Common registers */ CARD32 ovr_clr; @@ -112,6 +150,14 @@ CARD32 bios_4_scratch; CARD32 bios_5_scratch; CARD32 bios_6_scratch; + + CARD32 disp1_base_addr; + CARD32 disp2_base_addr; + CARD32 ov0_base_addr; + CARD32 mc_fb_location; + CARD32 host_path_cntl; + CARD32 default_offset; + /* Other registers to save for VT switches */ CARD32 dp_datatype; CARD32 rbbm_soft_reset; @@ -155,16 +201,17 @@ CARD32 fp_gen_cntl; CARD32 fp2_gen_cntl; CARD32 fp_h_sync_strt_wid; - CARD32 fp2_h_sync_strt_wid; + CARD32 fp_h2_sync_strt_wid; CARD32 fp_horz_stretch; CARD32 fp_panel_cntl; CARD32 fp_v_sync_strt_wid; - CARD32 fp2_v_sync_strt_wid; + CARD32 fp_v2_sync_strt_wid; CARD32 fp_vert_stretch; CARD32 lvds_gen_cntl; CARD32 lvds_pll_cntl; CARD32 tmds_pll_cntl; CARD32 tmds_transmitter_cntl; + CARD32 tv_dac_cntl; /* Computed values for PLL */ CARD32 dot_clock_freq; @@ -187,9 +234,10 @@ CARD32 p2pll_ref_div; CARD32 p2pll_div_0; CARD32 htotal_cntl2; + CARD32 pixclks_cntl; + CARD32 vclk_cntl; /* Pallet */ - Bool palette_valid; CARD32 palette[256]; CARD32 palette2[256]; } RADEONSaveRec, *RADEONSavePtr; @@ -211,30 +259,12 @@ DisplayModePtr mode; } RADEONFBLayout; -typedef enum { - MT_NONE, - MT_CRT, - MT_LCD, - MT_DFP, - MT_CTV, - MT_STV -} RADEONMonitorType; - -typedef enum { - DDC_NONE_DETECTED, - DDC_MONID, - DDC_DVI, - DDC_VGA, - DDC_CRT2 -} RADEONDDCType; - -typedef enum { - CONNECTOR_NONE, - CONNECTOR_PROPRIETARY, - CONNECTOR_CRT, - CONNECTOR_DVI_I, - CONNECTOR_DVI_D -} RADEONConnectorType; +typedef enum +{ + BUS_TYPE_AGP, + BUS_TYPE_PCI, + BUS_TYPE_PCIE +} RadeonBusType; typedef enum { CHIP_FAMILY_UNKNOW, @@ -251,9 +281,26 @@ CHIP_FAMILY_R300, CHIP_FAMILY_R350, CHIP_FAMILY_RV350, + CHIP_FAMILY_RV380, + CHIP_FAMILY_R420, CHIP_FAMILY_LAST } RADEONChipFamily; +#define IS_RV100_VARIANT ((info->ChipFamily == CHIP_FAMILY_RV100) || \ + (info->ChipFamily == CHIP_FAMILY_RV200) || \ + (info->ChipFamily == CHIP_FAMILY_RS100) || \ + (info->ChipFamily == CHIP_FAMILY_RS200) || \ + (info->ChipFamily == CHIP_FAMILY_RV250) || \ + (info->ChipFamily == CHIP_FAMILY_RV280) || \ + (info->ChipFamily == CHIP_FAMILY_RS300)) + + +#define IS_R300_VARIANT ((info->ChipFamily == CHIP_FAMILY_R300) || \ + (info->ChipFamily == CHIP_FAMILY_RV350) || \ + (info->ChipFamily == CHIP_FAMILY_R350) || \ + (info->ChipFamily == CHIP_FAMILY_RV380) || \ + (info->ChipFamily == CHIP_FAMILY_R420)) + typedef struct { CARD32 freq; CARD32 value; @@ -271,10 +318,12 @@ unsigned long LinearAddr; /* Frame buffer physical address */ unsigned long MMIOAddr; /* MMIO region physical address */ unsigned long BIOSAddr; /* BIOS physical address */ + Bool IsAtomBios; unsigned char *MMIO; /* Map of MMIO region */ unsigned char *FB; /* Map of frame buffer */ CARD8 *VBIOS; /* Video BIOS pointer */ + xf86Int10InfoPtr pInt10; CARD32 MemCntl; CARD32 BusCntl; @@ -283,11 +332,10 @@ /* VE/M6 support */ RADEONMonitorType DisplayType; /* Monitor connected on */ - RADEONDDCType DDCType; - RADEONConnectorType ConnectorType; Bool HasCRTC2; /* All cards except original Radeon */ Bool IsMobility; /* Mobile chips for laptops */ Bool IsIGP; /* IGP chips */ + Bool HasSingleDAC; /* 2 CRTCs but single interal DAC */ Bool IsSecondary; /* Second Screen */ Bool IsSwitching; /* Flag for switching mode */ Bool Clone; /* Force second head to clone primary*/ @@ -299,7 +347,8 @@ int CloneFrameY0; Bool OverlayOnCRTC2; Bool PanelOff; /* Force panel (LCD/DFP) off */ - int FPBIOSstart; /* Start of the flat panel info */ + int ROMHeaderStart; /* Start of the ROM Info Table */ + int MasterDataStart; /* Offset for Master Data Table for ATOM BIOS */ Bool ddc_mode; /* Validate mode by matching exactly * the modes supported in DDC data */ @@ -320,6 +369,7 @@ int FeedbackDivider; int PostDivider; Bool UseBiosDividers; + /* EDID data using DDC interface */ Bool ddc_bios; Bool ddc1; @@ -329,6 +379,7 @@ RADEONPLLRec pll; RADEONTMDSPll tmds_pll[4]; + CARD32 tv_dac_adj; int RamWidth; float sclk; /* in MHz */ float mclk; /* in MHz */ @@ -341,8 +392,6 @@ void (*BlockHandler)(int, pointer, pointer, pointer); - Bool PaletteSavedOnVT; /* Palette saved on last VT switch */ - XAAInfoRecPtr accel; Bool accelOn; xf86CursorInfoPtr cursor; @@ -423,6 +472,8 @@ drmSize pciSize; drmHandle pciMemHandle; unsigned char *PCI; /* Map */ + int BusType; /* bus type, for future PCIE DRI support */ + Bool depthMoves; /* Enable depth moves -- slow! */ Bool allowPageFlip; /* Enable 3d page flipping */ @@ -577,6 +628,28 @@ extern void RADEONInitVideo(ScreenPtr pScreen); extern void RADEONResetVideo(ScrnInfoPtr pScrn); extern void R300CGWorkaround(ScrnInfoPtr pScrn); +extern RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn); + +extern void RADEONUpdatePanelSize(ScrnInfoPtr pScrn); +extern void RADEONInitDispBandwidth(ScrnInfoPtr pScrn); +extern Bool RADEONI2cInit(ScrnInfoPtr pScrn); +extern void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag); +extern Bool RADEONMapControllers(ScrnInfoPtr pScrn); +extern void RADEONEnableDisplay(ScrnInfoPtr pScrn, RADEONController* pCRTC, BOOL bEnable); +extern void RADEONGetPanelInfo (ScrnInfoPtr pScrn); +extern void RADEONGetTVDacAdjInfo(ScrnInfoPtr pScrn); +extern void RADEONUnblank (ScrnInfoPtr pScrn); +extern void RADEONBlank (ScrnInfoPtr pScrn); +extern void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, + int PowerManagementMode, + int flags); + +extern Bool RADEONGetBIOSInfo(ScrnInfoPtr pScrn); +extern Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn); +extern Bool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn); +extern Bool RADEONGetLVDSInfoFromBIOS (ScrnInfoPtr pScrn); +extern Bool RADEONGetTMDSInfoFromBIOS (ScrnInfoPtr pScrn); +extern Bool RADEONGetHardCodedEDIDFromBIOS (ScrnInfoPtr pScrn); #ifdef XF86DRI extern Bool RADEONDRIScreenInit(ScreenPtr pScreen); --- xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_video.c.new_chips 2004-05-10 09:42:45.000000000 -0400 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_video.c 2004-05-19 15:33:22.000000000 -0400 @@ -391,9 +391,7 @@ OUTREG(RADEON_CAP0_TRIG_CNTL, 0); RADEONSetColorKey(pScrn, pPriv->colorKey); - if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350) || + if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_R200) || (info->ChipFamily == CHIP_FAMILY_RADEON)) { int i; @@ -478,9 +476,7 @@ OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & 0xfffffCff) | (pPriv->ecp_div << 8)); - if ((info->ChipFamily == CHIP_FAMILY_RS100) || - (info->ChipFamily == CHIP_FAMILY_RS200) || - (info->ChipFamily == CHIP_FAMILY_RS300)) { + if (info->IsIGP) { /* Force the overlay clock on for integrated chips */ OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) | (1<<18))); @@ -922,9 +918,7 @@ y_mult = 2; x_off = 8; - if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350) || + if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_R200)) x_off = 0; --- xc/programs/Xserver/hw/xfree86/drivers/ati/atichip.h.new_chips 2004-05-10 09:42:45.000000000 -0400 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/atichip.h 2004-05-10 09:42:44.000000000 -0400 @@ -97,13 +97,18 @@ ATI_CHIP_R200, /* R200 */ ATI_CHIP_RV250, /* RV250 */ ATI_CHIP_RADEONMOBILITY9, /* Radeon M9 */ - ATI_CHIP_RS300, /* Radoen 9000 IGP */ + ATI_CHIP_RS300, /* Radoen 9100 IGP */ + ATI_CHIP_RS350, /* Radoen 9200 IGP */ ATI_CHIP_RV280, /* RV250 */ ATI_CHIP_RADEONMOBILITY9PLUS, /* Radeon M9+ */ ATI_CHIP_R300, /* R300 */ - ATI_CHIP_RV350, /* RV350 */ + ATI_CHIP_RV350, /* RV350/M10/M11 */ ATI_CHIP_R350, /* R350 */ ATI_CHIP_R360, /* R360 */ + ATI_CHIP_RV370, /* RV370/M22 */ + ATI_CHIP_RV380, /* RV380/M24 */ + ATI_CHIP_R420, /* R420/M18 */ + ATI_CHIP_R423, /* R423 */ ATI_CHIP_Radeon, /* Last among Radeon's */ ATI_CHIP_HDTV /* HDTV */ } ATIChipType; --- xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_bios.c.new_chips 2004-05-10 09:42:45.000000000 -0400 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_bios.c 2004-05-10 09:42:44.000000000 -0400 @@ -0,0 +1,522 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c,v 1.120tsi 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. + */ + +#include "xf86.h" +#include "xf86_OSproc.h" + +#include "radeon.h" +#include "radeon_macros.h" +#include "radeon_probe.h" +#include "radeon_reg.h" +#include "vbe.h" + +/* Read the Video BIOS block and the FP registers (if applicable). */ +Bool RADEONGetBIOSInfo(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + int tmp; + + if (!xf86ReturnOptValBool (info->Options, OPTION_NOBIOS, FALSE)) { + if (!(info->VBIOS = xalloc(RADEON_VBIOS_SIZE))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Cannot allocate space for hold Video BIOS!\n"); + return FALSE; + } else { + if (info->pInt10) { + info->BIOSAddr = info->pInt10->BIOSseg << 4; + (void)memcpy(info->VBIOS, xf86int10Addr(info->pInt10, info->BIOSAddr), + RADEON_VBIOS_SIZE); + } else { + xf86ReadPciBIOS(0, info->PciTag, 0, info->VBIOS, RADEON_VBIOS_SIZE); + if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Video BIOS not detected in PCI space!\n"); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Attempting to read Video BIOS from " + "legacy ISA space!\n"); + info->BIOSAddr = 0x000c0000; + xf86ReadDomainMemory(info->PciTag, info->BIOSAddr, + RADEON_VBIOS_SIZE, info->VBIOS); + } + } + } + } else { + info->VBIOS = NULL; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "NoBIOS option is configured, all info from video BIOS will not be used\n"); + return FALSE; + } + + if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Unrecognized BIOS signature, BIOS data will not be used\n"); + xfree (info->VBIOS); + info->VBIOS = NULL; + return FALSE; + } + + if (info->VBIOS) info->ROMHeaderStart = RADEON_BIOS16(0x48); + + if(!info->ROMHeaderStart) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Invalid ROM pointer, BIOS data will not be used\n"); + xfree (info->VBIOS); + info->VBIOS = NULL; + return FALSE; + } + + tmp = info->ROMHeaderStart + 4; + if ((RADEON_BIOS8(tmp) == 'A' && + RADEON_BIOS8(tmp+1) == 'T' && + RADEON_BIOS8(tmp+2) == 'O' && + RADEON_BIOS8(tmp+3) == 'M') || + (RADEON_BIOS8(tmp) == 'M' && + RADEON_BIOS8(tmp+1) == 'O' && + RADEON_BIOS8(tmp+2) == 'T' && + RADEON_BIOS8(tmp+3) == 'A')) + info->IsAtomBios = TRUE; + else + info->IsAtomBios = FALSE; + + if (info->IsAtomBios) + info->MasterDataStart = RADEON_BIOS16 (info->ROMHeaderStart + 32); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s BIOS detected\n", + info->IsAtomBios ? "ATOM":"Legacy"); + + return TRUE; +} + +Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + int i = 0, j, tmp, tmp0=0, tmp1=0; + + if(!info->VBIOS) return FALSE; + + if (info->IsAtomBios) { + if((tmp = RADEON_BIOS16 (info->MasterDataStart + 22))) { + int crtc = 0, id[2]; + tmp1 = RADEON_BIOS16 (tmp + 4); + for (i=0; i<8; i++) { + if(tmp1 & (1<>8) & 0xf) == id[0]) { + if (i == 3) + pRADEONEnt->PortInfo[0].TMDSType = TMDS_INT; + else if (i == 7) + pRADEONEnt->PortInfo[0].TMDSType = TMDS_EXT; + + if (pRADEONEnt->PortInfo[0].DACType == DAC_UNKNOWN) + pRADEONEnt->PortInfo[0].DACType = (portinfo & 0xf) - 1; + continue; + } + } + + id[crtc] = (portinfo>>8) & 0xf; + pRADEONEnt->PortInfo[crtc].DACType = (portinfo & 0xf) - 1; + pRADEONEnt->PortInfo[crtc].ConnectorType = (portinfo>>4) & 0xf; + if (i == 3) + pRADEONEnt->PortInfo[crtc].TMDSType = TMDS_INT; + else if (i == 7) + pRADEONEnt->PortInfo[crtc].TMDSType = TMDS_EXT; + + if((tmp0 = RADEON_BIOS16 (info->MasterDataStart + 24)) && id[crtc]) { + switch (RADEON_BIOS16 (tmp0 + 4 + 27 * id[crtc]) * 4) + { + case RADEON_GPIO_MONID: + pRADEONEnt->PortInfo[crtc].DDCType = DDC_MONID; + break; + case RADEON_GPIO_DVI_DDC: + pRADEONEnt->PortInfo[crtc].DDCType = DDC_DVI; + break; + case RADEON_GPIO_VGA_DDC: + pRADEONEnt->PortInfo[crtc].DDCType = DDC_VGA; + break; + case RADEON_GPIO_CRT2_DDC: + pRADEONEnt->PortInfo[crtc].DDCType = DDC_CRT2; + break; + default: + pRADEONEnt->PortInfo[crtc].DDCType = DDC_NONE; + break; + } + + } else { + pRADEONEnt->PortInfo[crtc].DDCType = DDC_NONE; + } + crtc++; + } else { + /* we have already had two CRTCs assigned. the rest may share the same + * port with the existing connector, fill in them accordingly. + */ + for (j=0; j<2; j++) { + if (((portinfo>>8) & 0xf) == id[j]) { + if (i == 3) + pRADEONEnt->PortInfo[j].TMDSType = TMDS_INT; + else if (i == 7) + pRADEONEnt->PortInfo[j].TMDSType = TMDS_EXT; + + if (pRADEONEnt->PortInfo[j].DACType == DAC_UNKNOWN) + pRADEONEnt->PortInfo[j].DACType = (portinfo & 0xf) - 1; + } + } + } + } + } + + for (i=0; i<2; i++) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Port%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", + i, pRADEONEnt->PortInfo[i].DDCType, pRADEONEnt->PortInfo[i].DACType, + pRADEONEnt->PortInfo[i].TMDSType, pRADEONEnt->PortInfo[i].ConnectorType); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Device Info Table found!\n"); + return FALSE; + } + } else { + if ((tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x50))) { + for (i = 1; i < 4; i++) { + + if (!RADEON_BIOS8(tmp + i*2) && i > 1) break; /* end of table */ + + tmp0 = RADEON_BIOS16(tmp + i*2); + if (((tmp0 >> 12) & 0x1f) == 0) continue; /* no connector */ + + /* internal DDC_DVI port will get assigned to PortInfo[0], or if there is no DDC_DVI (like in some IGPs). */ + tmp1 = ((((tmp0 >> 8) & 0xf) == DDC_DVI) || (tmp1 == 1)) ? 0 : 1; /* determine port info index */ + + pRADEONEnt->PortInfo[tmp1].DDCType = (tmp0 >> 8) & 0x0f; + if (pRADEONEnt->PortInfo[tmp1].DDCType > DDC_CRT2) pRADEONEnt->PortInfo[tmp1].DDCType = DDC_NONE_DETECTED; + pRADEONEnt->PortInfo[tmp1].DACType = (tmp0 & 0x01) ? DAC_TVDAC : DAC_PRIMARY; + pRADEONEnt->PortInfo[tmp1].ConnectorType = (tmp0 >> 12) & 0x0f; + if (pRADEONEnt->PortInfo[tmp1].ConnectorType > CONNECTOR_UNSUPPORTED) pRADEONEnt->PortInfo[tmp1].ConnectorType = CONNECTOR_UNSUPPORTED; + pRADEONEnt->PortInfo[tmp1].TMDSType = ((tmp0 >> 4) & 0x01) ? TMDS_EXT : TMDS_INT; + + /* some sanity checks */ + if (((pRADEONEnt->PortInfo[tmp1].ConnectorType != CONNECTOR_DVI_D) && + (pRADEONEnt->PortInfo[tmp1].ConnectorType != CONNECTOR_DVI_I)) && + pRADEONEnt->PortInfo[tmp1].TMDSType == TMDS_INT) + pRADEONEnt->PortInfo[tmp1].TMDSType = TMDS_UNKNOWN; + + xf86DrvMsg(0, X_INFO, "Connector%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", + tmp1, pRADEONEnt->PortInfo[tmp1].DDCType, pRADEONEnt->PortInfo[tmp1].DACType, + pRADEONEnt->PortInfo[tmp1].TMDSType, pRADEONEnt->PortInfo[tmp1].ConnectorType); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Connector Info Table found!\n"); + return FALSE; + } + + if (info->IsMobility) { + if ((tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x42))) { + if ((tmp0 = RADEON_BIOS16(tmp + 0x15))) { + if ((tmp1 = RADEON_BIOS8(tmp0+2) & 0x07)) { + pRADEONEnt->PortInfo[0].DDCType = tmp1; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "LCD DDC Info Table found!\n"); + } + } + } + } + +#if 0 +/* External TMDS Table, not used now */ + if ((tmp0 = RADEON_BIOS16(info->ROMHeaderStart + 0x58))) { + + //pRADEONEnt->PortInfo[1].DDCType = (RADEON_BIOS8(tmp0 + 7) & 0x07); + //pRADEONEnt->PortInfo[1].ConnectorType = CONNECTOR_DVI_I; + //pRADEONEnt->PortInfo[1].TMDSType = TMDS_EXT; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "External TMDS found.\n"); + + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NO External TMDS Info found\n"); + + } +#endif + + } + return TRUE; +} + +/* Read PLL parameters from BIOS block. Default to typical values if there + is no BIOS. */ +Bool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + RADEONPLLPtr pll = &info->pll; + CARD16 pll_info_block; + + if (!info->VBIOS) { + return FALSE; + } else { + if (info->IsAtomBios) { + pll_info_block = RADEON_BIOS16 (info->MasterDataStart + 12); + + pll->reference_freq = RADEON_BIOS16 (pll_info_block + 82); + pll->reference_div = 0; /* Need to derive from existing setting + or use a new algorithm to calculate + from min_input and max_input + */ + pll->min_pll_freq = RADEON_BIOS16 (pll_info_block + 78); + pll->max_pll_freq = RADEON_BIOS32 (pll_info_block + 32); + pll->xclk = RADEON_BIOS16 (pll_info_block + 72); + + info->sclk = RADEON_BIOS32(pll_info_block + 8) / 100.0; + info->mclk = RADEON_BIOS32(pll_info_block + 12) / 100.0; + if (info->sclk == 0) info->sclk = 200; + if (info->mclk == 0) info->mclk = 200; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ref_freq: %d, min_pll: %ld, max_pll: %ld, xclk: %d, sclk: %f, mclk: %f\n", + pll->reference_freq, pll->min_pll_freq, pll->max_pll_freq, pll->xclk, info->sclk, info->mclk); + + } else { + pll_info_block = RADEON_BIOS16 (info->ROMHeaderStart + 0x30); + + pll->reference_freq = RADEON_BIOS16 (pll_info_block + 0x0e); + pll->reference_div = RADEON_BIOS16 (pll_info_block + 0x10); + pll->min_pll_freq = RADEON_BIOS32 (pll_info_block + 0x12); + pll->max_pll_freq = RADEON_BIOS32 (pll_info_block + 0x16); + pll->xclk = RADEON_BIOS16 (pll_info_block + 0x08); + + info->sclk = RADEON_BIOS16(pll_info_block + 8) / 100.0; + info->mclk = RADEON_BIOS16(pll_info_block + 10) / 100.0; + } + } + + return TRUE; +} + +Bool RADEONGetLVDSInfoFromBIOS (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned long tmp, i; + + if (!info->VBIOS) return FALSE; + + if (info->IsAtomBios) { + if((tmp = RADEON_BIOS16 (info->MasterDataStart + 16))) { + + info->PanelXRes = RADEON_BIOS16(tmp+6); + info->PanelYRes = RADEON_BIOS16(tmp+10); + info->DotClock = RADEON_BIOS16(tmp+4)*10; + info->HBlank = RADEON_BIOS16(tmp+8); + info->HOverPlus = RADEON_BIOS16(tmp+14); + info->HSyncWidth = RADEON_BIOS16(tmp+16); + info->VBlank = RADEON_BIOS16(tmp+12); + info->VOverPlus = RADEON_BIOS16(tmp+18); + info->VSyncWidth = RADEON_BIOS16(tmp+20); + info->PanelPwrDly = RADEON_BIOS16(tmp+40); + + info->Flags = 0; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "LVDS Info: Is this right?\n" + "XRes: %d, YRes: %d, DotClock: %d\n" + "HBlank: %d, HOverPlus: %d, HSyncWidth: %d\n" + "VBlank: %d, VOverPlus: %d, VSyncWidth: %d\n", + info->PanelXRes, info->PanelYRes, info->DotClock, + info->HBlank,info->HOverPlus, info->HSyncWidth, + info->VBlank, info->VOverPlus, info->VSyncWidth); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No LVDS Info Table found in BIOS!\n"); + return FALSE; + } + } else { + + tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x40); + + if (!tmp) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No Panel Info Table found in BIOS!\n"); + return FALSE; + } else { + char stmp[30]; + int tmp0; + + for (i = 0; i < 24; i++) + stmp[i] = RADEON_BIOS8(tmp+i+1); + stmp[24] = 0; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Panel ID string: %s\n", stmp); + + info->PanelXRes = RADEON_BIOS16(tmp+25); + info->PanelYRes = RADEON_BIOS16(tmp+27); + xf86DrvMsg(0, X_INFO, "Panel Size from BIOS: %dx%d\n", + info->PanelXRes, info->PanelYRes); + + info->PanelPwrDly = RADEON_BIOS16(tmp+44); + if (info->PanelPwrDly > 2000 || info->PanelPwrDly < 0) + info->PanelPwrDly = 2000; + + /* some panels only work well with certain divider combinations. + */ + info->RefDivider = RADEON_BIOS16(tmp+46); + info->PostDivider = RADEON_BIOS8(tmp+48); + info->FeedbackDivider = RADEON_BIOS16(tmp+49); + if ((info->RefDivider != 0) && + (info->FeedbackDivider > 3)) { + info->UseBiosDividers = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "BIOS provided dividers will be used.\n"); + } + + /* We don't use a while loop here just in case we have a corrupted BIOS image. + The max number of table entries is 23 at present, but may grow in future. + To ensure it works with future revisions we loop it to 32. + */ + for (i = 0; i < 32; i++) { + tmp0 = RADEON_BIOS16(tmp+64+i*2); + if (tmp0 == 0) break; + if ((RADEON_BIOS16(tmp0) == info->PanelXRes) && + (RADEON_BIOS16(tmp0+2) == info->PanelYRes)) { + info->HBlank = (RADEON_BIOS16(tmp0+17) - + RADEON_BIOS16(tmp0+19)) * 8; + info->HOverPlus = (RADEON_BIOS16(tmp0+21) - + RADEON_BIOS16(tmp0+19) - 1) * 8; + info->HSyncWidth = RADEON_BIOS8(tmp0+23) * 8; + info->VBlank = (RADEON_BIOS16(tmp0+24) - + RADEON_BIOS16(tmp0+26)); + info->VOverPlus = ((RADEON_BIOS16(tmp0+28) & 0x7ff) - + RADEON_BIOS16(tmp0+26)); + info->VSyncWidth = ((RADEON_BIOS16(tmp0+28) & 0xf800) >> 11); + info->DotClock = RADEON_BIOS16(tmp0+9) * 10; + info->Flags = 0; + } + } + } + } + return TRUE; +} + +Bool RADEONGetHardCodedEDIDFromBIOS (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned long tmp; + char EDID[256]; + + if (!info->VBIOS) return FALSE; + + if (info->IsAtomBios) { + /* Not yet */ + return FALSE; + } else { + if (!(tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x4c))) { + return FALSE; + } + + memcpy(EDID, (char*)(info->VBIOS + tmp), 256); + + info->DotClock = (*(CARD16*)(EDID+54)) * 10; + info->PanelXRes = (*(CARD8*)(EDID+56)) + ((*(CARD8*)(EDID+58))>>4)*256; + info->HBlank = (*(CARD8*)(EDID+57)) + ((*(CARD8*)(EDID+58)) & 0xf)*256; + info->HOverPlus = (*(CARD8*)(EDID+62)) + ((*(CARD8*)(EDID+65)>>6)*256); + info->HSyncWidth = (*(CARD8*)(EDID+63)) + (((*(CARD8*)(EDID+65)>>4) & 3)*256); + info->PanelYRes = (*(CARD8*)(EDID+59)) + ((*(CARD8*)(EDID+61))>>4)*256; + info->VBlank = ((*(CARD8*)(EDID+60)) + ((*(CARD8*)(EDID+61)) & 0xf)*256); + info->VOverPlus = (((*(CARD8*)(EDID+64))>>4) + (((*(CARD8*)(EDID+65)>>2) & 3)*16)); + info->VSyncWidth = (((*(CARD8*)(EDID+64)) & 0xf) + ((*(CARD8*)(EDID+65)) & 3)*256); + info->Flags = V_NHSYNC | V_NVSYNC; /**(CARD8*)(EDID+71);*/ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Hardcoded EDID data will be used for TMDS panel\n"); + } + return TRUE; +} + +Bool RADEONGetTMDSInfoFromBIOS (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + CARD32 tmp, maxfreq; + int i, n; + + if (!info->VBIOS) return FALSE; + + if (info->IsAtomBios) { + if((tmp = RADEON_BIOS16 (info->MasterDataStart + 18))) { + + maxfreq = RADEON_BIOS16(tmp+4); + + for (i=0; i<4; i++) { + info->tmds_pll[i].freq = RADEON_BIOS16(tmp+i*6+6); + /* This assumes each field in TMDS_PLL has 6 bit as in R300/R420 */ + info->tmds_pll[i].value = ((RADEON_BIOS8(tmp+i*6+8) & 0x3f) | + ((RADEON_BIOS8(tmp+i*6+10) & 0x3f)<<6) | + ((RADEON_BIOS8(tmp+i*6+9) & 0xf)<<12) | + ((RADEON_BIOS8(tmp+i*6+11) & 0xf)<<16)); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "TMDS PLL from BIOS: %ld %lx\n", + info->tmds_pll[i].freq, info->tmds_pll[i].value); + + if (maxfreq == info->tmds_pll[i].freq) { + info->tmds_pll[i].freq = 0xffffffff; + break; + } + } + return TRUE; + } + } else { + + tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x34); + if (tmp) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "DFP table revision: %d\n", RADEON_BIOS8(tmp)); + if (RADEON_BIOS8(tmp) == 3) { + n = RADEON_BIOS8(tmp + 5) + 1; + if (n > 4) n = 4; + for (i=0; itmds_pll[i].value = RADEON_BIOS32(tmp+i*10+0x08); + info->tmds_pll[i].freq = RADEON_BIOS16(tmp+i*10+0x10); + } + return TRUE; + } + + /* revision 4 has some problem as it appears in RV280, + comment it off for now, use default instead */ + /* + else if (RADEON_BIOS8(tmp) == 4) { + int stride = 0; + n = RADEON_BIOS8(tmp + 5) + 1; + if (n > 4) n = 4; + for (i=0; itmds_pll[i].value = RADEON_BIOS32(tmp+stride+0x08); + info->tmds_pll[i].freq = RADEON_BIOS16(tmp+stride+0x10); + if (i == 0) stride += 10; + else stride += 6; + } + return TRUE; + } + */ + } + } + return FALSE; +} --- xc/programs/Xserver/hw/xfree86/drivers/ati/Imakefile.new_chips 2004-05-10 09:42:45.000000000 -0400 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/Imakefile 2004-05-10 09:42:44.000000000 -0400 @@ -156,7 +156,7 @@ SRCS3 = r128_accel.c r128_cursor.c r128_dga.c r128_driver.c \ r128_video.c $(DRISRCS3) $(MODSRCS3) SRCS4 = radeon_accel.c radeon_cursor.c radeon_dga.c radeon_driver.c \ - radeon_video.c $(DRISRCS4) $(MODSRCS4) + radeon_video.c radeon_display.c radeon_bios.c $(DRISRCS4) $(MODSRCS4) OBJS1 = ati.o atiadapter.o atibus.o atichip.o atiident.o atioption.o \ atiprobe.o atividmem.o $(CPIOOBJS1) $(MODOBJS1) \ @@ -170,7 +170,7 @@ OBJS3 = r128_accel.o r128_cursor.o r128_dga.o r128_driver.o \ r128_video.o $(DRIOBJS3) $(MODOBJS3) OBJS4 = radeon_accel.o radeon_cursor.o radeon_dga.o radeon_driver.o \ - radeon_video.o $(DRIOBJS4) $(MODOBJS4) + radeon_video.o radeon_display.o radeon_bios.o $(DRIOBJS4) $(MODOBJS4) SRCS = $(SRCS1) $(SRCS2) $(SRCS3) $(SRCS4) OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $(OBJS4) @@ -349,6 +349,8 @@ InstallDriverSDKNonExecFile(radeon_sarea.h,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(radeon_version.h,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(radeon_video.c,$(DRIVERSDKDIR)/drivers/ati) +InstallDriverSDKNonExecFile(radeon_display.c,$(DRIVERSDKDIR)/drivers/ati) +InstallDriverSDKNonExecFile(radeon_bios.c,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(radeon_common.h,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(radeon_accelfuncs.c,$(DRIVERSDKDIR)/drivers/ati) --- xc/programs/Xserver/hw/xfree86/drivers/ati/atichip.c.new_chips 2004-05-10 09:42:45.000000000 -0400 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/atichip.c 2004-05-10 09:42:44.000000000 -0400 @@ -95,13 +95,18 @@ "ATI Radeon 8500/9100", "ATI Radeon 9000", "ATI Radeon Mobility M9", - "ATI Radeon 9000 IGP", + "ATI Radeon 9100 IGP", + "ATI Radeon 9200 IGP", "ATI Radeon 9200", "ATI Radeon Mobility M9+", "ATI Radeon 9700/9500", "ATI Radeon 9600", "ATI Radeon 9800", "ATI Radeon 9800XT", + "ATI Radeon X300/M22", + "ATI Radeon X600/M24", + "ATI Radeon X800/M18", + "ATI Radeon X800 PCIE", "ATI unknown Radeon", "ATI Rage HDTV" }; @@ -688,6 +693,10 @@ case NewChipID('X', '5'): return ATI_CHIP_RS300; + case NewChipID('x', '4'): + case NewChipID('x', '5'): + return ATI_CHIP_RS350; + case NewChipID('Y', '\''): case NewChipID('Y', 'a'): case NewChipID('Y', 'b'): @@ -734,6 +743,40 @@ case NewChipID('N', 'J'): return ATI_CHIP_R360; + case NewChipID('[', '\''): + case NewChipID('[', 'b'): + case NewChipID('[', 'd'): + case NewChipID('[', 'e'): + case NewChipID('T', '\''): + case NewChipID('T', 'd'): + return ATI_CHIP_RV370; + + case NewChipID('>', 'P'): + case NewChipID('>', 'T'): + case NewChipID('1', 'P'): + case NewChipID('1', 'T'): + return ATI_CHIP_RV380; + + case NewChipID('J', 'H'): + case NewChipID('J', 'I'): + case NewChipID('J', 'J'): + case NewChipID('J', 'K'): + case NewChipID('J', 'L'): + case NewChipID('J', 'M'): + case NewChipID('J', 'N'): + case NewChipID('J', 'P'): + return ATI_CHIP_R420; + + case NewChipID('U', 'H'): + case NewChipID('U', 'I'): + case NewChipID('U', 'J'): + case NewChipID('U', 'K'): + case NewChipID('U', 'Q'): + case NewChipID('U', 'R'): + case NewChipID('U', 'T'): + case NewChipID(']', 'W'): + return ATI_CHIP_R423; + case NewChipID('H', 'D'): return ATI_CHIP_HDTV; --- xc/programs/Xserver/hw/xfree86/etc/pci.ids.new_chips 2004-02-15 19:48:36.000000000 -0500 +++ xc/programs/Xserver/hw/xfree86/etc/pci.ids 2004-05-04 09:34:18.000000000 -0400 @@ -172,6 +172,12 @@ 0017 PROTO-3 PCI Prototyping board 9100 INI-9100/9100W SCSI Host 1002 ATI Technologies Inc + 3150 Radeon RV380 [Radeon Mobility X600 M24] + 3154 Radeon RV380 [Radeon Mobility X600 M24] + 3e50 Radeon RV380 [Radeon X600] + 3e54 Radeon RV380 [Radeon X600] + 3e70 Radeon RV380 [Radeon X600 Secondary] + 3e74 Radeon RV380 [Radeon X600 Secondary] 4136 Radeon IGP 320 M 4144 Radeon R300 AD [Radeon 9500 Pro] # New PCI ID provided by ATI developer relations (correction to above) @@ -208,8 +214,24 @@ 1002 02aa Radeon 8500 AIW DV Edition 4336 Radeon Mobility U1 4337 Radeon IGP 340M + 4341 SB200 AC97 Audio Controller + 4342 SB200 PCI to PCI Bridge + 4345 SB200 USB Controller (EHCI) + 4347 SB200 USB Controller (OHCI) + 4348 SB200 USB Controller (OHCI) + 4349 SB200 IDE Controller + 434c SB200 PCI to LPC Bridge + 4353 SB200 SMBus Controller 4354 215CT [Mach64 CT] 4358 210888CX [Mach64 CX] + 4361 SB300 Audio Controller + 4362 SB300 PCI to PCI Bridge + 4363 SB300 SMBus Controller + 4365 SB300 USB Controller (EHCI) + 4367 SB300 USB Controller (OHCI) + 4368 SB300 USB Controller (OHCI) + 4369 SB300 IDE Controller + 436c SB300 PCI to LPC Bridge 4554 210888ET [Mach64 ET] 4654 Mach64 VT 4742 3D Rage Pro AGP 1X/2X @@ -291,6 +313,22 @@ 17af 2006 RV250 If [Excalibur Radeon 9000] 4967 Radeon RV250 Ig [Radeon 9000] 496e Radeon RV250 [Radeon 9000] (Secondary) + 4a48 Radeon R420 [Radeon X800] + 4a49 Radeon R420 [Radeon X800] + 4a4a Radeon R420 [Radeon X800] + 4a4b Radeon R420 [Radeon X800] + 4a4c Radeon R420 [Radeon X800] + 4a4d Radeon R420 [Radeon X800] + 4a4e Radeon R420 [Radeon Mobility X800 M18] + 4a50 Radeon R420 [Radeon X800] + 4a68 Radeon R420 [Radeon X800 Secondary] + 4a69 Radeon R420 [Radeon X800 Secondary] + 4a6a Radeon R420 [Radeon X800 Secondary] + 4a6b Radeon R420 [Radeon X800 Secondary] + 4a6c Radeon R420 [Radeon X800 Secondary] + 4a6d Radeon R420 [Radeon X800 Secondary] + 4a6e Radeon R420 [Radeon Mobility X800 M18 Secondary] + 4a70 Radeon R420 [Radeon X800 Secondary] 4c42 3D Rage LT Pro AGP-133 0e11 b0e8 Rage 3D LT Pro 0e11 b10e 3D Rage LT Pro (Compaq Armada 1750) @@ -441,8 +479,8 @@ 174b 7161 Radeon RV200 QW [Radeon 7500 LE] 17af 0202 RV200 QW [Excalibur Radeon 7500LE] 5158 Radeon RV200 QX [Radeon 7500] - 5159 Radeon RV100 QY [Radeon 7000/VE] - 1002 000a Radeon 7000/Radeon VE + 5159 Radeon RV100 QY [Radeon 7000/7000M/VE] + 1002 000a Radeon 7000/Radeon 7000M/Radeon VE 1002 000b Radeon 7000 1002 0038 Radeon 7000/Radeon VE 1002 003a Radeon 7000/Radeon VE @@ -506,13 +544,47 @@ 5453 Rage 128 Pro Ultra TS 5454 Rage 128 Pro Ultra TT 5455 Rage 128 Pro Ultra TU + 5460 Radeon RV370 [Radeon Mobility X300 M22] + 5464 Radeon RV370 [Radeon Mobility X300 M22] + 5548 Radeon R423 [Radeon X800 PCIE] + 5549 Radeon R423 [Radeon X800 PCIE] + 554a Radeon R423 [Radeon X800 PCIE] + 554b Radeon R423 [Radeon X800 PCIE] + 5551 Radeon R423 [Radeon X800 PCIE] + 5552 Radeon R423 [Radeon X800 PCIE] + 5554 Radeon R423 [Radeon X800 PCIE] + 5568 Radeon R423 [Radeon X800 PCIE Secondary] + 5569 Radeon R423 [Radeon X800 PCIE Secondary] + 556a Radeon R423 [Radeon X800 PCIE Secondary] + 556b Radeon R423 [Radeon X800 PCIE Secondary] + 5571 Radeon R423 [Radeon X800 PCIE Secondary] + 5572 Radeon R423 [Radeon X800 PCIE Secondary] + 5574 Radeon R423 [Radeon X800 PCIE Secondary] 5654 264VT [Mach64 VT] 1002 5654 Mach64VT Reference 5655 264VT3 [Mach64 VT3] 5656 264VT4 [Mach64 VT4] - 5961 Radeon RV280 [Radeon 9200] + 5833 Radeon RS300 Host Bridge + 5834 Radeon RS300 [Radeon IGP 9100] + 5835 Radeon RS300 [Radeon IGP Mobility 9100] + 5838 Radeon RS300 PCI to PCI Bridge + 5b60 Radeon RV370 [Radeon X300] + 5b62 Radeon RV370 [Radeon X600] + 5b64 Radeon RV370 [Radeon X300] + 5b65 Radeon RV370 [Radeon X300] + 5b70 Radeon RV370 [Radeon X300 Secondary] + 5b72 Radeon RV370 [Radeon X600 Secondary] + 5b74 Radeon RV370 [Radeon X300 Secondary] + 5b75 Radeon RV370 [Radeon X300 Secondary] + 5961 Radeon RV280 [Radeon 9200 Secondary] + 5d57 Radeon R423 [Radeon X800 PCIE] + 5d77 Radeon R423 [Radeon X800 PCIE Secondary] 700f PCI Bridge [IGP 320M] 7010 PCI Bridge [IGP 340M] + 7833 Radeon RS350 Host Bridge + 7834 Radeon RS350 [Radeon IGP 9100 PRO] + 7835 Radeon RS350 [Radeon IGP Mobility 9200] + 7838 Radeon RS350 PCI to PCI Bridge cab0 AGP Bridge [IGP 320M] cab2 RS200/RS200M AGP Bridge [IGP 340M] 1003 ULSI Systems --- xc/programs/Xserver/hw/xfree86/scanpci/xf86PciStdIds.h.new_chips 2004-04-30 12:29:43.000000000 -0400 +++ xc/programs/Xserver/hw/xfree86/scanpci/xf86PciStdIds.h 2004-04-30 14:49:59.000000000 -0400 @@ -317,6 +317,10 @@ static const char pci_device_1001_9100[] = "INI-9100/9100W SCSI Host"; #endif static const char pci_vendor_1002[] = "ATI Technologies Inc"; +static const char pci_device_1002_3150[] = "Radeon RV380 [Radeon Mobility X600 M24]"; +static const char pci_device_1002_3154[] = "Radeon RV380 [Radeon Mobility X600 M24]"; +static const char pci_device_1002_3e50[] = "Radeon RV380 [Radeon X600]"; +static const char pci_device_1002_3e54[] = "Radeon RV380 [Radeon X600]"; static const char pci_device_1002_4136[] = "Radeon IGP 320 M"; static const char pci_device_1002_4144[] = "Radeon R300 AD [Radeon 9500 Pro]"; static const char pci_device_1002_4145[] = "R300 AE [Radeon 9700 Pro]"; @@ -531,6 +535,14 @@ #endif static const char pci_device_1002_4967[] = "Radeon RV250 Ig [Radeon 9000]"; static const char pci_device_1002_496e[] = "Radeon RV250 [Radeon 9000] (Secondary)"; +static const char pci_device_1002_4a48[] = "Radeon R420 [Radeon X800]"; +static const char pci_device_1002_4a49[] = "Radeon R420 [Radeon X800]"; +static const char pci_device_1002_4a4a[] = "Radeon R420 [Radeon X800]"; +static const char pci_device_1002_4a4b[] = "Radeon R420 [Radeon X800]"; +static const char pci_device_1002_4a4c[] = "Radeon R420 [Radeon X800]"; +static const char pci_device_1002_4a4d[] = "Radeon R420 [Radeon X800]"; +static const char pci_device_1002_4a4e[] = "Radeon R420 [Radeon Mobility X800 M18]"; +static const char pci_device_1002_4a50[] = "Radeon R420 [Radeon X800]"; static const char pci_device_1002_4c42[] = "3D Rage LT Pro AGP-133"; #ifdef INIT_SUBSYS_INFO static const char pci_subsys_1002_4c42_0e11_b0e8[] = "Rage 3D LT Pro"; @@ -946,15 +958,32 @@ static const char pci_device_1002_5453[] = "Rage 128 Pro Ultra TS"; static const char pci_device_1002_5454[] = "Rage 128 Pro Ultra TT"; static const char pci_device_1002_5455[] = "Rage 128 Pro Ultra TU"; +static const char pci_device_1002_5460[] = "Radeon RV370 [Radeon Mobility X300 M22]"; +static const char pci_device_1002_5464[] = "Radeon RV370 [Radeon Mobility X300 M22]"; +static const char pci_device_1002_5548[] = "Radeon R423 [Radeon X800 PCIE]"; +static const char pci_device_1002_5549[] = "Radeon R423 [Radeon X800 PCIE]"; +static const char pci_device_1002_554a[] = "Radeon R423 [Radeon X800 PCIE]"; +static const char pci_device_1002_554b[] = "Radeon R423 [Radeon X800 PCIE]"; +static const char pci_device_1002_5551[] = "Radeon R423 [Radeon X800 PCIE]"; +static const char pci_device_1002_5552[] = "Radeon R423 [Radeon X800 PCIE]"; +static const char pci_device_1002_5554[] = "Radeon R423 [Radeon X800 PCIE]"; static const char pci_device_1002_5654[] = "264VT [Mach64 VT]"; #ifdef INIT_SUBSYS_INFO static const char pci_subsys_1002_5654_1002_5654[] = "Mach64VT Reference"; #endif static const char pci_device_1002_5655[] = "264VT3 [Mach64 VT3]"; static const char pci_device_1002_5656[] = "264VT4 [Mach64 VT4]"; +static const char pci_device_1002_5834[] = "Radeon RS300 [Radeon IGP 9100]"; +static const char pci_device_1002_5835[] = "Radeon RS300 [Radeon Mobility IGP 9100]"; static const char pci_device_1002_5961[] = "Radeon RV280 [Radeon 9200]"; +static const char pci_device_1002_5b60[] = "Radeon RV370 [Radeon X300]"; +static const char pci_device_1002_5b64[] = "Radeon RV370 [Radeon X300]"; +static const char pci_device_1002_5b65[] = "Radeon RV370 [Radeon X300]"; +static const char pci_device_1002_5d57[] = "Radeon R423 [Radeon X800 PCIE]"; static const char pci_device_1002_700f[] = "PCI Bridge [IGP 320M]"; static const char pci_device_1002_7010[] = "PCI Bridge [IGP 340M]"; +static const char pci_device_1002_7834[] = "Radeon RS350 [Radeon IGP 9100 XT]"; +static const char pci_device_1002_7835[] = "Radeon RS350 [Radeon Mobility IGP 9200]"; static const char pci_device_1002_cab0[] = "AGP Bridge [IGP 320M]"; static const char pci_device_1002_cab2[] = "RS200/RS200M AGP Bridge [IGP 340M]"; #ifdef VENDOR_INCLUDE_NONVIDEO