atipreinit.c revision b7306217
132b578d3Smrg/* 232b578d3Smrg * Copyright 1999 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org 332b578d3Smrg * 432b578d3Smrg * Permission to use, copy, modify, distribute, and sell this software and its 532b578d3Smrg * documentation for any purpose is hereby granted without fee, provided that 632b578d3Smrg * the above copyright notice appear in all copies and that both that copyright 732b578d3Smrg * notice and this permission notice appear in supporting documentation, and 832b578d3Smrg * that the name of Marc Aurele La France not be used in advertising or 932b578d3Smrg * publicity pertaining to distribution of the software without specific, 1032b578d3Smrg * written prior permission. Marc Aurele La France makes no representations 1132b578d3Smrg * about the suitability of this software for any purpose. It is provided 1232b578d3Smrg * "as-is" without express or implied warranty. 1332b578d3Smrg * 1432b578d3Smrg * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1532b578d3Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO 1632b578d3Smrg * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1732b578d3Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1832b578d3Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 1932b578d3Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2032b578d3Smrg * PERFORMANCE OF THIS SOFTWARE. 2132b578d3Smrg */ 2232b578d3Smrg 2332b578d3Smrg#ifdef HAVE_CONFIG_H 2432b578d3Smrg#include "config.h" 2532b578d3Smrg#endif 2632b578d3Smrg 2732b578d3Smrg#include <string.h> 2832b578d3Smrg#include <stdio.h> 2932b578d3Smrg 3007f4e327Smacallan#ifdef __NetBSD__ 3107f4e327Smacallan#include <sys/time.h> 3207f4e327Smacallan#include <sys/ioctl.h> 3307f4e327Smacallan#include <errno.h> 3407f4e327Smacallan#include <dev/wscons/wsconsio.h> 3507f4e327Smacallan#endif 3607f4e327Smacallan 3732b578d3Smrg#include "ati.h" 3832b578d3Smrg#include "atiadjust.h" 3932b578d3Smrg#include "atiaudio.h" 4032b578d3Smrg#include "atibus.h" 4132b578d3Smrg#include "atichip.h" 4232b578d3Smrg#include "aticursor.h" 4332b578d3Smrg#include "atidac.h" 4432b578d3Smrg#include "atidsp.h" 4532b578d3Smrg#include "atii2c.h" 4632b578d3Smrg#include "atiload.h" 4732b578d3Smrg#include "atilock.h" 4832b578d3Smrg#include "atimach64.h" 4932b578d3Smrg#include "atimach64accel.h" 5032b578d3Smrg#include "atimach64io.h" 5132b578d3Smrg#include "atimach64probe.h" 5232b578d3Smrg#include "atimode.h" 5332b578d3Smrg#include "atioption.h" 5432b578d3Smrg#include "atipreinit.h" 5532b578d3Smrg#include "atiprint.h" 5632b578d3Smrg#include "atiprobe.h" 5732b578d3Smrg#include "atividmem.h" 5832b578d3Smrg#include "atiwonderio.h" 5932b578d3Smrg#include "atixv.h" 6032b578d3Smrg 6132b578d3Smrg#include "vbe.h" 622a51b5beSmrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 6332b578d3Smrg#include "xf86RAC.h" 642a51b5beSmrg#endif 6532b578d3Smrg 6607f4e327Smacallan#include "xf86Priv.h" 6707f4e327Smacallan 6832b578d3Smrg/* 6932b578d3Smrg * FreeScreen handles the clean-up. 7032b578d3Smrg */ 7132b578d3Smrgstatic Bool 7232b578d3SmrgMach64GetRec(ScrnInfoPtr pScrn) 7332b578d3Smrg{ 7432b578d3Smrg if (!pScrn->driverPrivate) { 7532b578d3Smrg pScrn->driverPrivate = xnfcalloc(sizeof(ATIRec), 1); 7632b578d3Smrg memset(pScrn->driverPrivate, 0, sizeof(ATIRec)); 7732b578d3Smrg } 7832b578d3Smrg 7932b578d3Smrg return TRUE; 8032b578d3Smrg} 8132b578d3Smrg 8232b578d3Smrg/* 8332b578d3Smrg * ATIReportMemory -- 8432b578d3Smrg * 8532b578d3Smrg * This function reports on the amount and type of video memory found. 8632b578d3Smrg */ 8732b578d3Smrgstatic void 8832b578d3SmrgATIReportMemory 8932b578d3Smrg( 9032b578d3Smrg ScrnInfoPtr pScreenInfo, 9132b578d3Smrg ATIPtr pATI, 9232b578d3Smrg const char *MemoryTypeName 9332b578d3Smrg) 9432b578d3Smrg{ 9532b578d3Smrg char Buffer[128], *Message; 9632b578d3Smrg 9732b578d3Smrg Message = Buffer + 9832b578d3Smrg snprintf(Buffer, SizeOf(Buffer), "%d kB of %s detected", 9932b578d3Smrg pATI->VideoRAM, MemoryTypeName); 10032b578d3Smrg 10132b578d3Smrg if (pATI->VideoRAM > pScreenInfo->videoRam) 10232b578d3Smrg { 10332b578d3Smrg Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message, 10432b578d3Smrg " (using %d kB)", pScreenInfo->videoRam); 10532b578d3Smrg } 10632b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, "%s.\n", Buffer); 10732b578d3Smrg} 10832b578d3Smrg 10932b578d3Smrgstatic const int videoRamSizes[] = 11032b578d3Smrg {512, 1024, 2*1024, 4*1024, 6*1024, 8*1024, 12*1024, 16*1024}; 11132b578d3Smrgstatic const rgb defaultWeight = {0, 0, 0}; 11232b578d3Smrgstatic const Gamma defaultGamma = {0.0, 0.0, 0.0}; 11332b578d3Smrg 11432b578d3Smrg/* 11532b578d3Smrg * ATIPrintNoiseIfRequested -- 11632b578d3Smrg * 11732b578d3Smrg * This function formats debugging information on the server's stderr when 11832b578d3Smrg * requested by the user through the server's verbosity setting. 11932b578d3Smrg */ 12032b578d3Smrgstatic void 12132b578d3SmrgATIPrintNoiseIfRequested 12232b578d3Smrg( 12332b578d3Smrg ATIPtr pATI, 12432b578d3Smrg CARD8 *BIOS, 12532b578d3Smrg unsigned int BIOSSize 12632b578d3Smrg) 12732b578d3Smrg{ 12832b578d3Smrg if (xf86GetVerbosity() <= 3) 12932b578d3Smrg return; 13032b578d3Smrg 13132b578d3Smrg if (BIOSSize > 0) 13232b578d3Smrg ATIPrintBIOS(BIOS, BIOSSize); 13332b578d3Smrg xf86ErrorFVerb(4, "\n On server entry:\n"); 13432b578d3Smrg ATIPrintRegisters(pATI); 13532b578d3Smrg} 13632b578d3Smrg 13732b578d3Smrg#define BIOS_SIZE 0x00010000U /* 64kB */ 13832b578d3Smrg#define BIOSByte(_n) ((CARD8)(BIOS[_n])) 13932b578d3Smrg#define BIOSWord(_n) ((CARD16)(BIOS[_n] | \ 14032b578d3Smrg (BIOS[(_n) + 1] << 8))) 14132b578d3Smrg 14232b578d3Smrg/* 14332b578d3Smrg * For Mach64 adapters, pick up, from the BIOS, the type of programmable 14432b578d3Smrg * clock generator (if any), and various information about it. 14532b578d3Smrg */ 14632b578d3Smrgstatic void 14732b578d3Smrgati_bios_clock 14832b578d3Smrg( 14932b578d3Smrg ScrnInfoPtr pScreenInfo, 15032b578d3Smrg ATIPtr pATI, 15132b578d3Smrg CARD8 *BIOS, 15232b578d3Smrg unsigned int ClockTable, 15332b578d3Smrg GDevPtr pGDev 15432b578d3Smrg) 15532b578d3Smrg{ 15632b578d3Smrg CARD16 ClockDac; 15732b578d3Smrg 15832b578d3Smrg if (ClockTable > 0) 15932b578d3Smrg { 16032b578d3Smrg pATI->ProgrammableClock = BIOSByte(ClockTable); 16132b578d3Smrg pATI->ClockNumberToProgramme = BIOSByte(ClockTable + 0x06U); 16232b578d3Smrg pATI->refclk = BIOSWord(ClockTable + 0x08U); 16332b578d3Smrg pATI->refclk *= 10000; 16432b578d3Smrg } 16532b578d3Smrg else 16632b578d3Smrg { 16732b578d3Smrg /* 16832b578d3Smrg * Compensate for BIOS absence. Note that the reference 16932b578d3Smrg * frequency has already been set by option processing. 17032b578d3Smrg */ 17132b578d3Smrg if ((pATI->DAC & ~0x0FU) == ATI_DAC_INTERNAL) 17232b578d3Smrg { 17332b578d3Smrg pATI->ProgrammableClock = ATI_CLOCK_INTERNAL; 17432b578d3Smrg } 17532b578d3Smrg else switch (pATI->DAC) 17632b578d3Smrg { 17732b578d3Smrg case ATI_DAC_STG1703: 17832b578d3Smrg pATI->ProgrammableClock = ATI_CLOCK_STG1703; 17932b578d3Smrg break; 18032b578d3Smrg 18132b578d3Smrg case ATI_DAC_CH8398: 18232b578d3Smrg pATI->ProgrammableClock = ATI_CLOCK_CH8398; 18332b578d3Smrg break; 18432b578d3Smrg 18532b578d3Smrg case ATI_DAC_ATT20C408: 18632b578d3Smrg pATI->ProgrammableClock = ATI_CLOCK_ATT20C408; 18732b578d3Smrg break; 18832b578d3Smrg 18932b578d3Smrg case ATI_DAC_IBMRGB514: 19032b578d3Smrg pATI->ProgrammableClock = ATI_CLOCK_IBMRGB514; 19132b578d3Smrg break; 19232b578d3Smrg 19332b578d3Smrg default: /* Provisional */ 19432b578d3Smrg pATI->ProgrammableClock = ATI_CLOCK_ICS2595; 19532b578d3Smrg break; 19632b578d3Smrg } 19732b578d3Smrg 19832b578d3Smrg /* This should be safe for all generators except IBM's RGB514 */ 19932b578d3Smrg pATI->ClockNumberToProgramme = 3; 20032b578d3Smrg } 20132b578d3Smrg 20232b578d3Smrg pATI->ClockDescriptor = ATIClockDescriptors[ATI_CLOCK_FIXED]; 20332b578d3Smrg 20432b578d3Smrg if ((pATI->ProgrammableClock > ATI_CLOCK_FIXED) && 20532b578d3Smrg (pATI->ProgrammableClock < ATI_CLOCK_MAX)) 20632b578d3Smrg { 20732b578d3Smrg /* 20832b578d3Smrg * Graphics PRO TURBO 1600's are unusual in that an ICS2595 is used 20932b578d3Smrg * to generate clocks for VGA modes, and an IBM RGB514 is used for 21032b578d3Smrg * accelerator modes. 21132b578d3Smrg */ 21232b578d3Smrg if ((pATI->ProgrammableClock == ATI_CLOCK_ICS2595) && 21332b578d3Smrg (pATI->DAC == ATI_DAC_IBMRGB514)) 21432b578d3Smrg pATI->ProgrammableClock = ATI_CLOCK_IBMRGB514; 21532b578d3Smrg 21632b578d3Smrg pATI->ClockDescriptor = ATIClockDescriptors[pATI->ProgrammableClock]; 21732b578d3Smrg } 21832b578d3Smrg 21932b578d3Smrg ClockDac = pATI->DAC; 22032b578d3Smrg switch (pATI->ProgrammableClock) 22132b578d3Smrg { 22232b578d3Smrg case ATI_CLOCK_ICS2595: 22332b578d3Smrg /* 22432b578d3Smrg * Pick up reference divider (43 or 46) appropriate to the chip 22532b578d3Smrg * revision level. 22632b578d3Smrg */ 22732b578d3Smrg if (ClockTable > 0) 22832b578d3Smrg pATI->ClockDescriptor.MinM = 22932b578d3Smrg pATI->ClockDescriptor.MaxM = BIOSWord(ClockTable + 0x0AU); 23032b578d3Smrg else if (!xf86NameCmp(pGDev->clockchip, "ATI 18818-0")) 23132b578d3Smrg pATI->ClockDescriptor.MinM = 23232b578d3Smrg pATI->ClockDescriptor.MaxM = 43; 23332b578d3Smrg else if (!xf86NameCmp(pGDev->clockchip, "ATI 18818-1")) 23432b578d3Smrg pATI->ClockDescriptor.MinM = 23532b578d3Smrg pATI->ClockDescriptor.MaxM = 46; 23632b578d3Smrg else 23732b578d3Smrg pATI->ProgrammableClock = ATI_CLOCK_UNKNOWN; 23832b578d3Smrg break; 23932b578d3Smrg 24032b578d3Smrg case ATI_CLOCK_STG1703: 24132b578d3Smrg /* This one's also a RAMDAC */ 24232b578d3Smrg ClockDac = ATI_DAC_STG1703; 24332b578d3Smrg break; 24432b578d3Smrg 24532b578d3Smrg case ATI_CLOCK_CH8398: 24632b578d3Smrg /* This one's also a RAMDAC */ 24732b578d3Smrg ClockDac = ATI_DAC_CH8398; 24832b578d3Smrg break; 24932b578d3Smrg 25032b578d3Smrg case ATI_CLOCK_INTERNAL: 25132b578d3Smrg /* 25232b578d3Smrg * The reference divider has already been programmed by BIOS 25332b578d3Smrg * initialisation. Because, there is only one reference 25432b578d3Smrg * divider for all generated frequencies (including MCLK), it 25532b578d3Smrg * cannot be changed without reprogramming all clocks every 25632b578d3Smrg * time one of them needs a different reference divider. 25732b578d3Smrg * 25832b578d3Smrg * Besides, it's not a good idea to change the reference 25932b578d3Smrg * divider. BIOS initialisation sets it to a value that 26032b578d3Smrg * effectively prevents generating frequencies beyond the 26132b578d3Smrg * graphics controller's tolerance. 26232b578d3Smrg */ 26332b578d3Smrg pATI->ClockDescriptor.MinM = 26432b578d3Smrg pATI->ClockDescriptor.MaxM = ATIMach64GetPLLReg(PLL_REF_DIV); 26532b578d3Smrg 26632b578d3Smrg /* The DAC is also integrated */ 26732b578d3Smrg if ((pATI->DAC & ~0x0FU) != ATI_DAC_INTERNAL) 26832b578d3Smrg ClockDac = ATI_DAC_INTERNAL; 26932b578d3Smrg 27032b578d3Smrg break; 27132b578d3Smrg 27232b578d3Smrg case ATI_CLOCK_ATT20C408: 27332b578d3Smrg /* This one's also a RAMDAC */ 27432b578d3Smrg ClockDac = ATI_DAC_ATT20C408; 27532b578d3Smrg break; 27632b578d3Smrg 27732b578d3Smrg case ATI_CLOCK_IBMRGB514: 27832b578d3Smrg /* This one's also a RAMDAC */ 27932b578d3Smrg ClockDac = ATI_DAC_IBMRGB514; 28032b578d3Smrg pATI->ClockNumberToProgramme = 7; 28132b578d3Smrg break; 28232b578d3Smrg 28332b578d3Smrg default: 28432b578d3Smrg break; 28532b578d3Smrg } 28632b578d3Smrg 28732b578d3Smrg /* 28832b578d3Smrg * We now have up to two indications of what RAMDAC the adapter uses. 28932b578d3Smrg * They should be the same. The following test and corresponding 29032b578d3Smrg * action are under construction. 29132b578d3Smrg */ 29232b578d3Smrg if (pATI->DAC != ClockDac) 29332b578d3Smrg { 29432b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, 29532b578d3Smrg "Mach64 RAMDAC probe discrepancy detected:\n" 29632b578d3Smrg " DAC=0x%02X; ClockDac=0x%02X.\n", 29732b578d3Smrg pATI->DAC, ClockDac); 29832b578d3Smrg 29932b578d3Smrg if (pATI->DAC == ATI_DAC_IBMRGB514) 30032b578d3Smrg { 30132b578d3Smrg pATI->ProgrammableClock = ATI_CLOCK_IBMRGB514; 30232b578d3Smrg pATI->ClockDescriptor = ATIClockDescriptors[ATI_CLOCK_IBMRGB514]; 30332b578d3Smrg pATI->ClockNumberToProgramme = 7; 30432b578d3Smrg } 30532b578d3Smrg else 30632b578d3Smrg { 30732b578d3Smrg pATI->DAC = ClockDac; /* For now */ 30832b578d3Smrg } 30932b578d3Smrg } 31032b578d3Smrg 31132b578d3Smrg switch (pATI->refclk / 100000) 31232b578d3Smrg { 31332b578d3Smrg case 143: 31432b578d3Smrg pATI->ReferenceNumerator = 157500; 31532b578d3Smrg pATI->ReferenceDenominator = 11; 31632b578d3Smrg break; 31732b578d3Smrg 31832b578d3Smrg case 286: 31932b578d3Smrg pATI->ReferenceNumerator = 315000; 32032b578d3Smrg pATI->ReferenceDenominator = 11; 32132b578d3Smrg break; 32232b578d3Smrg 32332b578d3Smrg default: 32432b578d3Smrg pATI->ReferenceNumerator = pATI->refclk / 1000; 32532b578d3Smrg pATI->ReferenceDenominator = 1; 32632b578d3Smrg break; 32732b578d3Smrg } 32832b578d3Smrg} 32932b578d3Smrg 33032b578d3Smrg/* 33132b578d3Smrg * Pick up multimedia information, which will be at different 33232b578d3Smrg * displacements depending on table revision. 33332b578d3Smrg */ 33432b578d3Smrgstatic void 33532b578d3Smrgati_bios_mmedia 33632b578d3Smrg( 33732b578d3Smrg ScrnInfoPtr pScreenInfo, 33832b578d3Smrg ATIPtr pATI, 33932b578d3Smrg CARD8 *BIOS, 34032b578d3Smrg unsigned int VideoTable, 34132b578d3Smrg unsigned int HardwareTable 34232b578d3Smrg) 34332b578d3Smrg{ 34432b578d3Smrg pATI->Audio = ATI_AUDIO_NONE; 34532b578d3Smrg 34632b578d3Smrg if (VideoTable > 0) 34732b578d3Smrg { 34832b578d3Smrg switch (BIOSByte(VideoTable - 0x02U)) 34932b578d3Smrg { 35032b578d3Smrg case 0x00U: 35132b578d3Smrg pATI->Tuner = BIOSByte(VideoTable) & 0x1FU; 35232b578d3Smrg 35332b578d3Smrg /* 35432b578d3Smrg * XXX The VideoTable[1] byte is known to have been 35532b578d3Smrg * omitted in LTPro and Mobility BIOS'es. Any others? 35632b578d3Smrg */ 35732b578d3Smrg switch (pATI->Chip) 35832b578d3Smrg { 35932b578d3Smrg case ATI_CHIP_264LTPRO: 36032b578d3Smrg case ATI_CHIP_MOBILITY: 36132b578d3Smrg pATI->Decoder = BIOSByte(VideoTable + 0x01U) & 0x07U; 36232b578d3Smrg pATI->Audio = BIOSByte(VideoTable + 0x02U) & 0x0FU; 36332b578d3Smrg break; 36432b578d3Smrg 36532b578d3Smrg default: 36632b578d3Smrg pATI->Decoder = BIOSByte(VideoTable + 0x02U) & 0x07U; 36732b578d3Smrg pATI->Audio = BIOSByte(VideoTable + 0x03U) & 0x0FU; 36832b578d3Smrg break; 36932b578d3Smrg } 37032b578d3Smrg 37132b578d3Smrg break; 37232b578d3Smrg 37332b578d3Smrg case 0x01U: 37432b578d3Smrg pATI->Tuner = BIOSByte(VideoTable) & 0x1FU; 37532b578d3Smrg pATI->Audio = BIOSByte(VideoTable + 0x01U) & 0x0FU; 37632b578d3Smrg pATI->Decoder = BIOSByte(VideoTable + 0x05U) & 0x0FU; 37732b578d3Smrg break; 37832b578d3Smrg 37932b578d3Smrg default: 38032b578d3Smrg break; 38132b578d3Smrg } 38232b578d3Smrg } 38332b578d3Smrg 38432b578d3Smrg if (HardwareTable > 0) 38532b578d3Smrg { 38632b578d3Smrg pATI->I2CType = BIOSByte(HardwareTable + 0x06U) & 0x0FU; 38732b578d3Smrg } 38832b578d3Smrg} 38932b578d3Smrg 39032b578d3Smrg/* 39132b578d3Smrg * Determine panel dimensions and model. 39232b578d3Smrg */ 39332b578d3Smrgstatic void 39432b578d3Smrgati_bios_panel_info 39532b578d3Smrg( 39632b578d3Smrg ScrnInfoPtr pScreenInfo, 39732b578d3Smrg ATIPtr pATI, 39832b578d3Smrg CARD8 *BIOS, 39932b578d3Smrg unsigned int BIOSSize, 40032b578d3Smrg unsigned int LCDTable 40132b578d3Smrg) 40232b578d3Smrg{ 40332b578d3Smrg unsigned int LCDPanelInfo = 0; 40432b578d3Smrg char Buffer[128]; 40532b578d3Smrg int i, j; 40632b578d3Smrg 40732b578d3Smrg if (LCDTable > 0) 40832b578d3Smrg { 40932b578d3Smrg LCDPanelInfo = BIOSWord(LCDTable + 0x0AU); 41032b578d3Smrg if (((LCDPanelInfo + 0x1DU) > BIOSSize) || 41132b578d3Smrg ((BIOSByte(LCDPanelInfo) != pATI->LCDPanelID) && 41232b578d3Smrg (pATI->LCDPanelID || (BIOSByte(LCDPanelInfo) > 0x1FU) || 41332b578d3Smrg (pATI->Chip <= ATI_CHIP_264LTPRO)))) 41432b578d3Smrg LCDPanelInfo = 0; 41532b578d3Smrg } 41632b578d3Smrg 41732b578d3Smrg if (!LCDPanelInfo) 41832b578d3Smrg { 41932b578d3Smrg /* 42032b578d3Smrg * Scan BIOS for panel info table. 42132b578d3Smrg */ 42232b578d3Smrg for (i = 0; i <= (int)(BIOSSize - 0x1DU); i++) 42332b578d3Smrg { 42432b578d3Smrg /* Look for panel ID ... */ 42532b578d3Smrg if ((BIOSByte(i) != pATI->LCDPanelID) && 42632b578d3Smrg (pATI->LCDPanelID || (BIOSByte(i) > 0x1FU) || 42732b578d3Smrg (pATI->Chip <= ATI_CHIP_264LTPRO))) 42832b578d3Smrg continue; 42932b578d3Smrg 43032b578d3Smrg /* ... followed by 24-byte panel model name ... */ 43132b578d3Smrg for (j = 0; j < 24; j++) 43232b578d3Smrg { 43332b578d3Smrg if ((CARD8)(BIOSByte(i + j + 1) - 0x20U) > 0x5FU) 43432b578d3Smrg { 43532b578d3Smrg i += j; 43632b578d3Smrg goto NextBIOSByte; 43732b578d3Smrg } 43832b578d3Smrg } 43932b578d3Smrg 44032b578d3Smrg /* ... verify panel width ... */ 44132b578d3Smrg if (pATI->LCDHorizontal && 44232b578d3Smrg (pATI->LCDHorizontal != BIOSWord(i + 0x19U))) 44332b578d3Smrg continue; 44432b578d3Smrg 44532b578d3Smrg /* ... and verify panel height */ 44632b578d3Smrg if (pATI->LCDVertical && 44732b578d3Smrg (pATI->LCDVertical != BIOSWord(i + 0x1BU))) 44832b578d3Smrg continue; 44932b578d3Smrg 45032b578d3Smrg if (LCDPanelInfo) 45132b578d3Smrg { 45232b578d3Smrg /* 45332b578d3Smrg * More than one possibility, but don't care if all 45432b578d3Smrg * tables describe panels of the same size. 45532b578d3Smrg */ 45632b578d3Smrg if ((BIOSByte(LCDPanelInfo + 0x19U) == 45732b578d3Smrg BIOSByte(i + 0x19U)) && 45832b578d3Smrg (BIOSByte(LCDPanelInfo + 0x1AU) == 45932b578d3Smrg BIOSByte(i + 0x1AU)) && 46032b578d3Smrg (BIOSByte(LCDPanelInfo + 0x1BU) == 46132b578d3Smrg BIOSByte(i + 0x1BU)) && 46232b578d3Smrg (BIOSByte(LCDPanelInfo + 0x1CU) == 46332b578d3Smrg BIOSByte(i + 0x1CU))) 46432b578d3Smrg continue; 46532b578d3Smrg 46632b578d3Smrg LCDPanelInfo = 0; 46732b578d3Smrg break; 46832b578d3Smrg } 46932b578d3Smrg 47032b578d3Smrg LCDPanelInfo = i; 47132b578d3Smrg 47232b578d3Smrg NextBIOSByte: ; 47332b578d3Smrg } 47432b578d3Smrg } 47532b578d3Smrg 47632b578d3Smrg if (LCDPanelInfo > 0) 47732b578d3Smrg { 47832b578d3Smrg pATI->LCDPanelID = BIOSByte(LCDPanelInfo); 47932b578d3Smrg pATI->LCDHorizontal = BIOSWord(LCDPanelInfo + 0x19U); 48032b578d3Smrg pATI->LCDVertical = BIOSWord(LCDPanelInfo + 0x1BU); 48132b578d3Smrg } 48232b578d3Smrg 48332b578d3Smrg if (LCDPanelInfo) 48432b578d3Smrg { 48532b578d3Smrg for (i = 0; i < 24; i++) 48632b578d3Smrg Buffer[i] = BIOSByte(LCDPanelInfo + 1 + i); 48732b578d3Smrg for (; --i >= 0; ) 48832b578d3Smrg if (Buffer[i] && Buffer[i] != ' ') 48932b578d3Smrg { 49032b578d3Smrg Buffer[i + 1] = '\0'; 49132b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, 49232b578d3Smrg "Panel model %s.\n", Buffer); 49332b578d3Smrg break; 49432b578d3Smrg } 49532b578d3Smrg } 49632b578d3Smrg} 49732b578d3Smrg 49832b578d3Smrg/* 49932b578d3Smrg * ATIPreInit -- 50032b578d3Smrg * 50132b578d3Smrg * This function is only called once per screen at the start of the first 50232b578d3Smrg * server generation. 50332b578d3Smrg */ 50432b578d3SmrgBool 50532b578d3SmrgATIPreInit 50632b578d3Smrg( 50732b578d3Smrg ScrnInfoPtr pScreenInfo, 50832b578d3Smrg int flags 50932b578d3Smrg) 51032b578d3Smrg{ 51132b578d3Smrg CARD8 BIOS[BIOS_SIZE]; 51232b578d3Smrg unsigned int BIOSSize = 0; 51332b578d3Smrg unsigned int ROMTable = 0, ClockTable = 0, FrequencyTable = 0; 51432b578d3Smrg unsigned int LCDTable = 0, VideoTable = 0; 51532b578d3Smrg unsigned int HardwareTable = 0; 51632b578d3Smrg 51732b578d3Smrg char Buffer[128], *Message; 51832b578d3Smrg ATIPtr pATI; 51932b578d3Smrg GDevPtr pGDev; 52032b578d3Smrg EntityInfoPtr pEntity; 5212a51b5beSmrg#ifndef XSERVER_LIBPCIACCESS 52232b578d3Smrg resPtr pResources; 5232a51b5beSmrg#endif 52432b578d3Smrg pciVideoPtr pVideo; 52532b578d3Smrg DisplayModePtr pMode; 52632b578d3Smrg CARD32 IOValue; 52732b578d3Smrg int i, j; 52832b578d3Smrg int Numerator, Denominator; 52932b578d3Smrg int MinX, MinY; 53032b578d3Smrg ClockRange ATIClockRange = {NULL, 0, 80000, -1, TRUE, TRUE, 1, 1, 0}; 53132b578d3Smrg int DefaultmaxClock = 0; 53232b578d3Smrg int minPitch, maxPitch = 0xFFU, pitchInc, maxHeight = 0; 53332b578d3Smrg int ApertureSize = 0x00010000U; 53432b578d3Smrg int ModeType = M_T_BUILTIN; 53532b578d3Smrg LookupModeFlags Strategy = LOOKUP_CLOSEST_CLOCK; 53632b578d3Smrg int DefaultDepth; 53732b578d3Smrg Bool PreInitSuccess = FALSE; 53832b578d3Smrg 53932b578d3Smrg# define pATIHW (&pATI->OldHW) 54032b578d3Smrg 54107f4e327Smacallan#ifndef AVOID_CPIO_ 54232b578d3Smrg 54332b578d3Smrg xf86Int10InfoPtr pInt10Info = NULL; 54432b578d3Smrg vbeInfoPtr pVBE = NULL; 54532b578d3Smrg pointer pInt10Module, pDDCModule = NULL, pVBEModule = NULL; 54632b578d3Smrg 54732b578d3Smrg#endif /* AVOID_CPIO */ 54832b578d3Smrg 54932b578d3Smrg if (pScreenInfo->numEntities != 1) 55032b578d3Smrg { 55132b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 55232b578d3Smrg "Logic error: Number of attached entities not 1.\n"); 55332b578d3Smrg return FALSE; 55432b578d3Smrg } 55532b578d3Smrg 55632b578d3Smrg if (!Mach64GetRec(pScreenInfo)) 55732b578d3Smrg return FALSE; 55832b578d3Smrg 55932b578d3Smrg pATI = ATIPTR(pScreenInfo); 56032b578d3Smrg 56132b578d3Smrg /* Register resources */ 56232b578d3Smrg pEntity = xf86GetEntityInfo(pScreenInfo->entityList[0]); 56332b578d3Smrg pGDev = pEntity->device; 5642a51b5beSmrg#ifndef XSERVER_LIBPCIACCESS 56532b578d3Smrg pResources = pEntity->resources; 5662a51b5beSmrg#endif 56732b578d3Smrg 56832b578d3Smrg pATI->iEntity = pEntity->index; 56932b578d3Smrg pATI->Chip = pEntity->chipset; 57032b578d3Smrg pVideo = xf86GetPciInfoForEntity(pATI->iEntity); 57132b578d3Smrg 5721b12faf6Smrg free(pEntity); 57332b578d3Smrg 5742a51b5beSmrg#ifndef XSERVER_LIBPCIACCESS 57532b578d3Smrg if (!pResources) 57632b578d3Smrg pResources = xf86RegisterResources(pATI->iEntity, NULL, ResShared); 57732b578d3Smrg if (pResources) 57832b578d3Smrg { 57932b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 580d31dbc53Smrg "Unable to register bus resources\n"); 58132b578d3Smrg xf86FreeResList(pResources); 58232b578d3Smrg return FALSE; 58332b578d3Smrg } 5842a51b5beSmrg#endif 58532b578d3Smrg ConfiguredMonitor = NULL; 58632b578d3Smrg (void)memset(BIOS, 0, SizeOf(BIOS)); 58732b578d3Smrg 58832b578d3Smrg if (!(flags & PROBE_DETECT)) 58932b578d3Smrg { 59032b578d3Smrg /* Set monitor */ 59132b578d3Smrg pScreenInfo->monitor = pScreenInfo->confScreen->monitor; 59232b578d3Smrg 59332b578d3Smrg /* Set depth, bpp, etc. */ 59432b578d3Smrg if ((pATI->Chip < ATI_CHIP_264CT)) 59532b578d3Smrg { 59632b578d3Smrg i = NoDepth24Support; /* No support for >8bpp either */ 59732b578d3Smrg DefaultDepth = 8; 59832b578d3Smrg } 59932b578d3Smrg else 60032b578d3Smrg { 60132b578d3Smrg i = Support24bppFb | Support32bppFb; 60232b578d3Smrg DefaultDepth = 0; 60332b578d3Smrg } 60432b578d3Smrg 60532b578d3Smrg if (!xf86SetDepthBpp(pScreenInfo, DefaultDepth, 0, 0, i)) 60632b578d3Smrg return FALSE; 60732b578d3Smrg 60832b578d3Smrg for (j = 0; ; j++) 60932b578d3Smrg { 61032b578d3Smrg static const CARD8 AllowedDepthBpp[][2] = 61132b578d3Smrg { 61232b578d3Smrg { 8, 8}, 61332b578d3Smrg {15, 16}, 61432b578d3Smrg {16, 16}, 61532b578d3Smrg {24, 24}, 61632b578d3Smrg {24, 32} 61732b578d3Smrg }; 61832b578d3Smrg 61932b578d3Smrg if (j < NumberOf(AllowedDepthBpp)) 62032b578d3Smrg { 62132b578d3Smrg if (pScreenInfo->depth > AllowedDepthBpp[j][0]) 62232b578d3Smrg continue; 62332b578d3Smrg 62432b578d3Smrg if (pScreenInfo->depth == AllowedDepthBpp[j][0]) 62532b578d3Smrg { 62632b578d3Smrg if (pScreenInfo->bitsPerPixel > AllowedDepthBpp[j][1]) 62732b578d3Smrg continue; 62832b578d3Smrg 62932b578d3Smrg if (pScreenInfo->bitsPerPixel == AllowedDepthBpp[j][1]) 63032b578d3Smrg break; 63132b578d3Smrg } 63232b578d3Smrg } 63332b578d3Smrg 63432b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 63532b578d3Smrg "Driver does not support depth %d at fbbpp %d.\n", 63632b578d3Smrg pScreenInfo->depth, pScreenInfo->bitsPerPixel); 63732b578d3Smrg return FALSE; 63832b578d3Smrg } 63932b578d3Smrg 64032b578d3Smrg xf86PrintDepthBpp(pScreenInfo); 64132b578d3Smrg 64232b578d3Smrg if ((i == NoDepth24Support) && (pScreenInfo->depth > 8)) 64332b578d3Smrg { 64432b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 64532b578d3Smrg "Depth %d is not supported through this adapter.\n", 64632b578d3Smrg pScreenInfo->depth); 64732b578d3Smrg return FALSE; 64832b578d3Smrg } 64932b578d3Smrg 65032b578d3Smrg /* Pick up XF86Config options */ 65132b578d3Smrg ATIProcessOptions(pScreenInfo, pATI); 65232b578d3Smrg } 65332b578d3Smrg 65432b578d3Smrg if (!ATIMach64ProbeIO(pVideo, pATI)) 65532b578d3Smrg return FALSE; 65632b578d3Smrg 65732b578d3Smrg ATIClaimBusSlot(pGDev->active, pATI); 65832b578d3Smrg 65932b578d3Smrg#ifndef AVOID_CPIO 66032b578d3Smrg#ifdef TV_OUT 66132b578d3Smrg 66232b578d3Smrg pATI->pVBE = NULL; 66332b578d3Smrg pATI->pInt10 = NULL; 66432b578d3Smrg 66532b578d3Smrg#endif /* TV_OUT */ 66632b578d3Smrg 66732b578d3Smrg /* 66832b578d3Smrg * If there is an ix86-style BIOS, ensure its initialisation entry point 66932b578d3Smrg * has been executed, and retrieve DDC and VBE information from it. 67032b578d3Smrg */ 67132b578d3Smrg if (!(pInt10Module = xf86LoadSubModule(pScreenInfo, "int10"))) 67232b578d3Smrg { 67332b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, 67432b578d3Smrg "Unable to load int10 module.\n"); 67532b578d3Smrg } 67632b578d3Smrg else if (!(pInt10Info = xf86InitInt10(pATI->iEntity))) 67732b578d3Smrg { 67832b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, 67932b578d3Smrg "Unable to initialise int10 interface.\n"); 68032b578d3Smrg } 68132b578d3Smrg else 68232b578d3Smrg { 68332b578d3Smrg if (!(pDDCModule = xf86LoadSubModule(pScreenInfo, "ddc"))) 68432b578d3Smrg { 68532b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, 68632b578d3Smrg "Unable to load ddc module.\n"); 68732b578d3Smrg } 68832b578d3Smrg else 68932b578d3Smrg if (!(pVBEModule = xf86LoadSubModule(pScreenInfo, "vbe"))) 69032b578d3Smrg { 69132b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, 69232b578d3Smrg "Unable to load vbe module.\n"); 69332b578d3Smrg } 69432b578d3Smrg else 69532b578d3Smrg { 69632b578d3Smrg if ((pVBE = VBEInit(pInt10Info, pATI->iEntity))) 69732b578d3Smrg { 69832b578d3Smrg ConfiguredMonitor = vbeDoEDID(pVBE, pDDCModule); 69932b578d3Smrg } 70032b578d3Smrg } 70132b578d3Smrg 70232b578d3Smrg if (!(flags & PROBE_DETECT)) 70332b578d3Smrg { 70432b578d3Smrg /* Validate, then make a private copy of, the initialised BIOS */ 70532b578d3Smrg CARD8 *pBIOS = xf86int10Addr(pInt10Info, pInt10Info->BIOSseg << 4); 70632b578d3Smrg 70732b578d3Smrg if ((pBIOS[0] != 0x55U) || (pBIOS[1] != 0xAAU) || !pBIOS[2]) 70832b578d3Smrg { 70932b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, 71032b578d3Smrg "Unable to correctly retrieve adapter BIOS.\n"); 71132b578d3Smrg } 71232b578d3Smrg else 71332b578d3Smrg { 71432b578d3Smrg BIOSSize = pBIOS[2] << 9; 71532b578d3Smrg if (BIOSSize > BIOS_SIZE) 71632b578d3Smrg BIOSSize = BIOS_SIZE; 71732b578d3Smrg (void)memcpy(BIOS, pBIOS, BIOSSize); 71832b578d3Smrg } 71932b578d3Smrg } 72032b578d3Smrg } 72132b578d3Smrg 72232b578d3Smrg#ifndef TV_OUT 72332b578d3Smrg /* De-activate VBE */ 72432b578d3Smrg vbeFree(pVBE); 72532b578d3Smrg xf86UnloadSubModule(pVBEModule); 72632b578d3Smrg 72732b578d3Smrg /* De-activate int10 */ 72832b578d3Smrg xf86FreeInt10(pInt10Info); 72932b578d3Smrg xf86UnloadSubModule(pInt10Module); 73032b578d3Smrg#else 73132b578d3Smrg pATI->pInt10 = pInt10Info; 73232b578d3Smrg pATI->pVBE = pVBE; 73332b578d3Smrg pVBE = NULL; 73432b578d3Smrg pInt10Info = NULL; 73532b578d3Smrg#endif /* TV_OUT */ 73607f4e327Smacallan#endif /* AVOID_CPIO */ 73707f4e327Smacallan#ifdef __NetBSD__ 73807f4e327Smacallan if (ConfiguredMonitor == NULL) { 73907f4e327Smacallan struct wsdisplayio_edid_info ei; 74007f4e327Smacallan char buffer[1024]; 74107f4e327Smacallan int i, j; 74207f4e327Smacallan 74307f4e327Smacallan ei.edid_data = buffer; 74407f4e327Smacallan ei.buffer_size = 1024; 74507f4e327Smacallan if (ioctl(xf86Info.screenFd, WSDISPLAYIO_GET_EDID, &ei) != -1) { 74607f4e327Smacallan xf86Msg(X_INFO, "got %d bytes worth of EDID from wsdisplay\n", ei.data_size); 74707f4e327Smacallan ConfiguredMonitor = xf86InterpretEDID(pScreenInfo->scrnIndex, buffer); 74807f4e327Smacallan } else 74907f4e327Smacallan xf86Msg(X_INFO, "ioctl failed %d\n", errno); 75007f4e327Smacallan } 75107f4e327Smacallan#endif 75207f4e327Smacallan 75332b578d3Smrg 75432b578d3Smrg if (ConfiguredMonitor && !(flags & PROBE_DETECT)) 75532b578d3Smrg { 75632b578d3Smrg xf86PrintEDID(ConfiguredMonitor); 75732b578d3Smrg xf86SetDDCproperties(pScreenInfo, ConfiguredMonitor); 75832b578d3Smrg } 75932b578d3Smrg 76007f4e327Smacallan#ifndef AVOID_CPIO 76132b578d3Smrg /* DDC module is no longer needed at this point */ 76232b578d3Smrg xf86UnloadSubModule(pDDCModule); 76307f4e327Smacallan#endif 76432b578d3Smrg 76532b578d3Smrg if (flags & PROBE_DETECT) 76632b578d3Smrg { 76732b578d3Smrg return TRUE; 76832b578d3Smrg } 76932b578d3Smrg 77032b578d3Smrg#ifndef AVOID_CPIO 77132b578d3Smrg 77232b578d3Smrg /* I/O bases might no longer be valid after BIOS initialisation */ 77332b578d3Smrg { 77432b578d3Smrg if (pATI->CPIODecoding == BLOCK_IO) 77532b578d3Smrg pATI->CPIOBase = PCI_REGION_BASE(pVideo, 1, REGION_IO); 77632b578d3Smrg 77732b578d3Smrg pATI->MMIOInLinear = FALSE; 77832b578d3Smrg 77932b578d3Smrg /* Set MMIO address from PCI configuration space, if available */ 78032b578d3Smrg if ((pATI->Block0Base = PCI_REGION_BASE(pVideo, 2, REGION_MEM))) 78132b578d3Smrg { 78232b578d3Smrg pATI->Block0Base += 0x0400U; 78332b578d3Smrg } 78432b578d3Smrg } 78532b578d3Smrg 78632b578d3Smrg#endif /* AVOID_CPIO */ 78732b578d3Smrg 7882a51b5beSmrg#ifndef XSERVER_LIBPCIACCESS 78932b578d3Smrg#ifdef AVOID_CPIO 79032b578d3Smrg 79132b578d3Smrg pScreenInfo->racMemFlags = 79232b578d3Smrg RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR; 79332b578d3Smrg 79432b578d3Smrg#else /* AVOID_CPIO */ 79532b578d3Smrg 79632b578d3Smrg pScreenInfo->racIoFlags = 79732b578d3Smrg RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR; 79832b578d3Smrg pScreenInfo->racMemFlags = RAC_FB | RAC_CURSOR; 79932b578d3Smrg 80032b578d3Smrg#endif /* AVOID_CPIO */ 8012a51b5beSmrg#endif 80232b578d3Smrg /* Finish private area initialisation */ 80332b578d3Smrg pATI->nFIFOEntries = 16; /* For now */ 80432b578d3Smrg 80532b578d3Smrg /* Finish probing the adapter */ 80632b578d3Smrg { 80732b578d3Smrg /* 80832b578d3Smrg * For MMIO register access, the MMIO address is computed when probing 80932b578d3Smrg * and there are no BIOS calls. This mapping should always succeed. 81032b578d3Smrg * 81132b578d3Smrg * For CPIO register access, the MMIO address is computed above in the 81232b578d3Smrg * presence of an auxiliary aperture. Otherwise, it is set to zero and 81332b578d3Smrg * gets computed when we read the linear aperture configuration. This 81432b578d3Smrg * mapping is either irrelevant or a no-op. 81532b578d3Smrg */ 81632b578d3Smrg if (!ATIMapApertures(pScreenInfo->scrnIndex, pATI)) 81732b578d3Smrg return FALSE; 81832b578d3Smrg 81932b578d3Smrg#ifdef AVOID_CPIO 82032b578d3Smrg 82132b578d3Smrg if (!pATI->pBlock[0]) 82232b578d3Smrg { 82332b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 82432b578d3Smrg "Unable to mmap() adapter registers.\n"); 82532b578d3Smrg return FALSE; 82632b578d3Smrg } 82732b578d3Smrg 82832b578d3Smrg#endif /* AVOID_CPIO */ 82932b578d3Smrg 83032b578d3Smrg /* 83132b578d3Smrg * Verify register access by comparing against the CONFIG_CHIP_ID 83232b578d3Smrg * value saved by adapter detection. 83332b578d3Smrg */ 83432b578d3Smrg if (pATI->config_chip_id != inr(CONFIG_CHIP_ID)) 83532b578d3Smrg { 83632b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 83732b578d3Smrg "Adapter registers not mapped correctly.\n"); 83832b578d3Smrg ATIUnmapApertures(pScreenInfo->scrnIndex, pATI); 83932b578d3Smrg return FALSE; 84032b578d3Smrg } 84132b578d3Smrg 84232b578d3Smrg pATIHW->crtc_gen_cntl = inr(CRTC_GEN_CNTL); 84332b578d3Smrg if (!(pATIHW->crtc_gen_cntl & CRTC_EN) && 84432b578d3Smrg (pATI->Chip >= ATI_CHIP_264CT)) 84532b578d3Smrg { 84632b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 84732b578d3Smrg "Adapter has not been initialised.\n"); 84832b578d3Smrg goto bail_locked; 84932b578d3Smrg } 85032b578d3Smrg 85132b578d3Smrg#ifdef AVOID_CPIO 85232b578d3Smrg 85332b578d3Smrg if (!(pATIHW->crtc_gen_cntl & CRTC_EXT_DISP_EN)) 85432b578d3Smrg { 85532b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 85632b578d3Smrg "Adapters found to be in VGA mode on server entry are not" 85732b578d3Smrg " supported by the MMIO-only version of this driver.\n"); 85832b578d3Smrg goto bail_locked; 85932b578d3Smrg } 86032b578d3Smrg 86132b578d3Smrg#endif /* AVOID_CPIO */ 86232b578d3Smrg 86332b578d3Smrg pATIHW->mem_cntl = inr(MEM_CNTL); 86432b578d3Smrg if (pATI->Chip < ATI_CHIP_264VTB) 86532b578d3Smrg { 86632b578d3Smrg IOValue = GetBits(pATIHW->mem_cntl, CTL_MEM_SIZE); 86732b578d3Smrg pATI->VideoRAM = videoRamSizes[IOValue]; 86832b578d3Smrg } 86932b578d3Smrg else 87032b578d3Smrg { 87132b578d3Smrg pATI->nFIFOEntries = /* Don't care */ 87232b578d3Smrg (unsigned int)(-1) >> 1; 87332b578d3Smrg 87432b578d3Smrg IOValue = GetBits(pATIHW->mem_cntl, CTL_MEM_SIZEB); 87532b578d3Smrg if (IOValue < 8) 87632b578d3Smrg pATI->VideoRAM = (IOValue + 1) * 512; 87732b578d3Smrg else if (IOValue < 12) 87832b578d3Smrg pATI->VideoRAM = (IOValue - 3) * 1024; 87932b578d3Smrg else 88032b578d3Smrg pATI->VideoRAM = (IOValue - 7) * 2048; 88132b578d3Smrg } 88232b578d3Smrg 88332b578d3Smrg IOValue = inr(CONFIG_STATUS64_0); 88432b578d3Smrg if (pATI->Chip >= ATI_CHIP_264CT) 88532b578d3Smrg { 88632b578d3Smrg pATI->MemoryType = GetBits(IOValue, CFG_MEM_TYPE_T); 88732b578d3Smrg } 88832b578d3Smrg else 88932b578d3Smrg { 89032b578d3Smrg pATI->MemoryType = GetBits(IOValue, CFG_MEM_TYPE); 89132b578d3Smrg } 89232b578d3Smrg 89332b578d3Smrg pATI->LCDPanelID = -1; 89432b578d3Smrg 89532b578d3Smrg if (pATI->Chip >= ATI_CHIP_264CT) 89632b578d3Smrg { 89732b578d3Smrg /* Get LCD panel id */ 89832b578d3Smrg if (pATI->Chip == ATI_CHIP_264LT) 89932b578d3Smrg { 90032b578d3Smrg pATI->LCDPanelID = GetBits(IOValue, CFG_PANEL_ID); 90132b578d3Smrg 90232b578d3Smrg pATIHW->horz_stretching = inr(HORZ_STRETCHING); 90332b578d3Smrg pATIHW->vert_stretching = inr(VERT_STRETCHING); 90432b578d3Smrg pATIHW->lcd_gen_ctrl = inr(LCD_GEN_CTRL); 90532b578d3Smrg } 90632b578d3Smrg else if ((pATI->Chip == ATI_CHIP_264LTPRO) || 90732b578d3Smrg (pATI->Chip == ATI_CHIP_264XL) || 90832b578d3Smrg (pATI->Chip == ATI_CHIP_MOBILITY)) 90932b578d3Smrg { 91032b578d3Smrg pATI->LCDPanelID = GetBits(IOValue, CFG_PANEL_ID); 91132b578d3Smrg 91232b578d3Smrg pATIHW->lcd_index = inr(LCD_INDEX); 91332b578d3Smrg pATIHW->horz_stretching = 91432b578d3Smrg ATIMach64GetLCDReg(LCD_HORZ_STRETCHING); 91532b578d3Smrg pATI->LCDHorizontal = 91632b578d3Smrg GetBits(pATIHW->horz_stretching, HORZ_PANEL_SIZE); 91732b578d3Smrg if (pATI->LCDHorizontal) 91832b578d3Smrg { 91932b578d3Smrg if (pATI->LCDHorizontal == MaxBits(HORZ_PANEL_SIZE)) 92032b578d3Smrg pATI->LCDHorizontal = 0; 92132b578d3Smrg else 92232b578d3Smrg pATI->LCDHorizontal = 92332b578d3Smrg (pATI->LCDHorizontal + 1) << 3; 92432b578d3Smrg } 92532b578d3Smrg pATIHW->ext_vert_stretch = 92632b578d3Smrg ATIMach64GetLCDReg(LCD_EXT_VERT_STRETCH); 92732b578d3Smrg pATI->LCDVertical = 92832b578d3Smrg GetBits(pATIHW->ext_vert_stretch, VERT_PANEL_SIZE); 92932b578d3Smrg if (pATI->LCDVertical) 93032b578d3Smrg { 93132b578d3Smrg if (pATI->LCDVertical == MaxBits(VERT_PANEL_SIZE)) 93232b578d3Smrg pATI->LCDVertical = 0; 93332b578d3Smrg else 93432b578d3Smrg pATI->LCDVertical++; 93532b578d3Smrg } 93632b578d3Smrg pATIHW->vert_stretching = 93732b578d3Smrg ATIMach64GetLCDReg(LCD_VERT_STRETCHING); 93832b578d3Smrg pATIHW->lcd_gen_ctrl = ATIMach64GetLCDReg(LCD_GEN_CNTL); 93932b578d3Smrg outr(LCD_INDEX, pATIHW->lcd_index); 94032b578d3Smrg } 94132b578d3Smrg 94232b578d3Smrg /* 94332b578d3Smrg * Don't bother with panel support if it hasn't been previously 94432b578d3Smrg * enabled. 94532b578d3Smrg */ 94632b578d3Smrg if ((pATI->LCDPanelID >= 0) && 94732b578d3Smrg !(pATIHW->horz_stretching & HORZ_STRETCH_EN) && 94832b578d3Smrg !(pATIHW->vert_stretching & VERT_STRETCH_EN) && 94932b578d3Smrg !(pATIHW->lcd_gen_ctrl & LCD_ON)) 95032b578d3Smrg { 95132b578d3Smrg /* 95232b578d3Smrg * At this point, if an XL or Mobility BIOS hasn't set 95332b578d3Smrg * panel dimensions, then there is no panel. Otherwise, 95432b578d3Smrg * keep any panel disabled to allow for modes greater than 95532b578d3Smrg * the panel's dimensions. 95632b578d3Smrg */ 95732b578d3Smrg if ((pATI->Chip >= ATI_CHIP_264XL) && 95832b578d3Smrg (!pATI->LCDHorizontal || !pATI->LCDVertical)) 95932b578d3Smrg pATI->LCDPanelID = -1; 96032b578d3Smrg else 96132b578d3Smrg pATI->OptionPanelDisplay = FALSE; 96232b578d3Smrg } 96332b578d3Smrg } 96432b578d3Smrg 96532b578d3Smrg /* Get DAC type */ 96632b578d3Smrg pATI->DAC = GetBits(inr(DAC_CNTL), DAC_TYPE); 96732b578d3Smrg 96832b578d3Smrg if (pATI->Chip < ATI_CHIP_264CT) 96932b578d3Smrg { 97032b578d3Smrg /* Factor in what the BIOS says the DAC is */ 97132b578d3Smrg pATI->DAC = ATI_DAC(pATI->DAC, 97232b578d3Smrg GetBits(inr(SCRATCH_REG1), BIOS_INIT_DAC_SUBTYPE)); 97332b578d3Smrg } 97432b578d3Smrg 97532b578d3Smrg /* 97632b578d3Smrg * RAMDAC types 0 & 1 for Mach64's are different than those for 97732b578d3Smrg * Mach32's. 97832b578d3Smrg */ 97932b578d3Smrg if (pATI->DAC < ATI_DAC_ATI68875) 98032b578d3Smrg pATI->DAC += ATI_DAC_INTERNAL; 98132b578d3Smrg } 98232b578d3Smrg 98332b578d3Smrg { 98432b578d3Smrg ROMTable = BIOSWord(0x48U); 98532b578d3Smrg if ((ROMTable < 0x0002U) || 98632b578d3Smrg (BIOSWord(ROMTable - 0x02U) < 0x0012U) || 98732b578d3Smrg ((ROMTable + BIOSWord(ROMTable - 0x02U)) > BIOSSize)) 98832b578d3Smrg ROMTable = 0; 98932b578d3Smrg 99032b578d3Smrg if (ROMTable > 0) 99132b578d3Smrg { 99232b578d3Smrg ClockTable = BIOSWord(ROMTable + 0x10U); 99332b578d3Smrg if ((ClockTable + 0x20U) > BIOSSize) 99432b578d3Smrg ClockTable = 0; 99532b578d3Smrg 99632b578d3Smrg if (BIOSWord(ROMTable - 0x02U) >= 0x0048U) 99732b578d3Smrg { 99832b578d3Smrg VideoTable = BIOSWord(ROMTable + 0x46U); 99932b578d3Smrg if ((VideoTable < 0x08U) || 100032b578d3Smrg (BIOSByte(VideoTable - 0x01U) < 0x08U) || 100132b578d3Smrg (BIOSByte(VideoTable - 0x02U) > 0x01U) || 100232b578d3Smrg ((VideoTable + BIOSByte(VideoTable - 0x01U)) > BIOSSize)) 100332b578d3Smrg VideoTable = 0; 100432b578d3Smrg } 100532b578d3Smrg 100632b578d3Smrg if (BIOSWord(ROMTable - 0x02U) >= 0x004AU) 100732b578d3Smrg { 100832b578d3Smrg HardwareTable = BIOSWord(ROMTable + 0x48U); 100932b578d3Smrg if (((HardwareTable + 0x08U) > BIOSSize) || 101032b578d3Smrg (memcmp(BIOS + HardwareTable, "$ATI", 4) != 0)) 101132b578d3Smrg HardwareTable = 0; 101232b578d3Smrg } 101332b578d3Smrg } 101432b578d3Smrg 1015b7306217Smacallan#if defined(__sparc__) 1016b7306217Smacallan /* make PGX64 work by default */ 1017b7306217Smacallan if (pATI->Chip == ATI_CHIP_264XL) 1018b7306217Smacallan pATI->refclk = 29498000; 1019b7306217Smacallan#endif 102032b578d3Smrg 1021b7306217Smacallan ati_bios_clock(pScreenInfo, pATI, BIOS, ClockTable, pGDev); 102232b578d3Smrg ati_bios_mmedia(pScreenInfo, pATI, BIOS, VideoTable, HardwareTable); 102332b578d3Smrg 102432b578d3Smrg if (pATI->LCDPanelID >= 0) 102532b578d3Smrg { 102632b578d3Smrg LCDTable = BIOSWord(0x78U); 102732b578d3Smrg if ((LCDTable + BIOSByte(LCDTable + 5)) > BIOSSize) 102832b578d3Smrg LCDTable = 0; 102932b578d3Smrg 103032b578d3Smrg ati_bios_panel_info(pScreenInfo, pATI, BIOS, BIOSSize, LCDTable); 103132b578d3Smrg } 103232b578d3Smrg 103332b578d3Smrg xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3, 103432b578d3Smrg "BIOS Data: BIOSSize=0x%04X, ROMTable=0x%04X.\n", 103532b578d3Smrg BIOSSize, ROMTable); 103632b578d3Smrg xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3, 103732b578d3Smrg "BIOS Data: ClockTable=0x%04X, FrequencyTable=0x%04X.\n", 103832b578d3Smrg ClockTable, FrequencyTable); 103932b578d3Smrg xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3, 104032b578d3Smrg "BIOS Data: LCDTable=0x%04X.\n", 104132b578d3Smrg LCDTable); 104232b578d3Smrg xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3, 104332b578d3Smrg "BIOS Data: VideoTable=0x%04X, HardwareTable=0x%04X.\n", 104432b578d3Smrg VideoTable, HardwareTable); 104532b578d3Smrg xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3, 104632b578d3Smrg "BIOS Data: I2CType=0x%02X, Tuner=0x%02X, Decoder=0x%02X," 104732b578d3Smrg " Audio=0x%02X.\n", 104832b578d3Smrg pATI->I2CType, pATI->Tuner, pATI->Decoder, pATI->Audio); 104932b578d3Smrg } 105032b578d3Smrg 105132b578d3Smrg ATIUnlock(pATI); /* Unlock registers */ 105232b578d3Smrg 105332b578d3Smrg /* Report what was found */ 105432b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, 105532b578d3Smrg "%s graphics controller detected.\n", 105632b578d3Smrg xf86TokenToString(Mach64Chipsets, pATI->Chip)); 105732b578d3Smrg 105832b578d3Smrg { 105932b578d3Smrg Message = Buffer + snprintf(Buffer, SizeOf(Buffer), "Chip type %04X", 106032b578d3Smrg pATI->ChipType); 106132b578d3Smrg if (!(pATI->ChipType & ~(CHIP_CODE_0 | CHIP_CODE_1))) 106232b578d3Smrg Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message, 106332b578d3Smrg " (%c%c)", 106432b578d3Smrg GetBits(pATI->ChipType, CHIP_CODE_1) + 0x41U, 106532b578d3Smrg GetBits(pATI->ChipType, CHIP_CODE_0) + 0x41U); 106632b578d3Smrg else if ((pATI->ChipType & 0x4040U) == 0x4040U) 106732b578d3Smrg Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message, 106832b578d3Smrg " \"%c%c\"", 106932b578d3Smrg GetByte(pATI->ChipType, 1), GetByte(pATI->ChipType, 0)); 107032b578d3Smrg if ((pATI->Chip >= ATI_CHIP_264CT) && (pATI->Chip != ATI_CHIP_Mach64)) 107132b578d3Smrg Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message, 107232b578d3Smrg ", version %d, foundry %s", 107332b578d3Smrg pATI->ChipVersion, ATIFoundryNames[pATI->ChipFoundry]); 107432b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, 107532b578d3Smrg "%s, class %d, revision 0x%02X.\n", 107632b578d3Smrg Buffer, pATI->ChipClass, pATI->ChipRevision); 107732b578d3Smrg } 107832b578d3Smrg 107932b578d3Smrg { 108032b578d3Smrg Message = Buffer + snprintf(Buffer, SizeOf(Buffer), 108132b578d3Smrg "%s bus interface detected", ATIBusNames[pATI->BusType]); 108232b578d3Smrg 108332b578d3Smrg#ifndef AVOID_CPIO 108432b578d3Smrg 108532b578d3Smrg { 108632b578d3Smrg Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message, 108732b578d3Smrg "; %s I/O base is 0x%04lX", 108832b578d3Smrg (pATI->CPIODecoding == SPARSE_IO) ? "sparse" : "block", 108932b578d3Smrg pATI->CPIOBase); 109032b578d3Smrg } 109132b578d3Smrg 109232b578d3Smrg#endif /* AVOID_CPIO */ 109332b578d3Smrg 109432b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, "%s.\n", Buffer); 109532b578d3Smrg } 109632b578d3Smrg 10972a51b5beSmrg#ifndef XSERVER_LIBPCIACCESS 109832b578d3Smrg#ifndef AVOID_CPIO 109932b578d3Smrg 110032b578d3Smrg if (pATI->CPIO_VGAWonder) 110132b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, 110232b578d3Smrg "VGA Wonder registers at I/O port 0x%04lX.\n", 110332b578d3Smrg pATI->CPIO_VGAWonder); 110432b578d3Smrg 110532b578d3Smrg#endif /* AVOID_CPIO */ 11062a51b5beSmrg#endif 110732b578d3Smrg 110832b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, 110932b578d3Smrg "ATI Mach64 adapter detected.\n"); 111032b578d3Smrg 111132b578d3Smrg if (pATI->Chip >= ATI_CHIP_264GT) 111232b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE, 111332b578d3Smrg "For information on using the multimedia capabilities\n\tof this" 111432b578d3Smrg " adapter, please see http://gatos.sf.net.\n"); 111532b578d3Smrg 111632b578d3Smrg if ((pATI->DAC & ~0x0FU) == ATI_DAC_INTERNAL) 111732b578d3Smrg { 111832b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, 111932b578d3Smrg "Internal RAMDAC (subtype %d) detected.\n", pATI->DAC & 0x0FU); 112032b578d3Smrg } 112132b578d3Smrg else 112232b578d3Smrg { 112332b578d3Smrg const SymTabRec *DAC; 112432b578d3Smrg 112532b578d3Smrg for (DAC = ATIDACDescriptors; ; DAC++) 112632b578d3Smrg { 112732b578d3Smrg if (pATI->DAC == DAC->token) 112832b578d3Smrg { 112932b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, 113032b578d3Smrg "%s RAMDAC detected.\n", DAC->name); 113132b578d3Smrg break; 113232b578d3Smrg } 113332b578d3Smrg 113432b578d3Smrg if (pATI->DAC < DAC->token) 113532b578d3Smrg { 113632b578d3Smrg xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 0, 113732b578d3Smrg "Unknown RAMDAC type 0x%02X detected.\n", pATI->DAC); 113832b578d3Smrg break; 113932b578d3Smrg } 114032b578d3Smrg } 114132b578d3Smrg } 114232b578d3Smrg 114332b578d3Smrg if (!xf86LinearVidMem()) 114432b578d3Smrg { 114532b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 114632b578d3Smrg "A linear aperture is not available.\n"); 114732b578d3Smrg goto bail; 114832b578d3Smrg } 114932b578d3Smrg 115032b578d3Smrg /* 115132b578d3Smrg * Set colour weights. 115232b578d3Smrg */ 115332b578d3Smrg 115432b578d3Smrg if (pATI->Chip < ATI_CHIP_264CT) 115532b578d3Smrg pScreenInfo->rgbBits = 6; 115632b578d3Smrg else 115732b578d3Smrg pScreenInfo->rgbBits = 8; 115832b578d3Smrg pATI->rgbBits = pScreenInfo->rgbBits; 115932b578d3Smrg if (!xf86SetWeight(pScreenInfo, defaultWeight, defaultWeight)) 116032b578d3Smrg goto bail; 116132b578d3Smrg 116232b578d3Smrg if ((pScreenInfo->depth > 8) && 116332b578d3Smrg ((pScreenInfo->weight.red != pScreenInfo->weight.blue) || 116432b578d3Smrg (pScreenInfo->weight.red != (CARD32)(pScreenInfo->depth / 3)) || 116532b578d3Smrg ((CARD32)pScreenInfo->depth != (pScreenInfo->weight.red + 116632b578d3Smrg pScreenInfo->weight.green + 116732b578d3Smrg pScreenInfo->weight.blue)))) 116832b578d3Smrg { 116932b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 117032b578d3Smrg "Driver does not support weight %d%d%d for depth %d.\n", 117132b578d3Smrg (int)pScreenInfo->weight.red, (int)pScreenInfo->weight.green, 117232b578d3Smrg (int)pScreenInfo->weight.blue, pScreenInfo->depth); 117332b578d3Smrg goto bail; 117432b578d3Smrg } 117532b578d3Smrg 117632b578d3Smrg /* 117732b578d3Smrg * Set default visual. 117832b578d3Smrg */ 117932b578d3Smrg 118032b578d3Smrg if (!xf86SetDefaultVisual(pScreenInfo, -1)) 118132b578d3Smrg goto bail; 118232b578d3Smrg 118332b578d3Smrg if ((pScreenInfo->depth > 8) && 118432b578d3Smrg (((pScreenInfo->defaultVisual | DynamicClass) != DirectColor) || 118532b578d3Smrg ((pScreenInfo->defaultVisual == DirectColor) && 118632b578d3Smrg (pATI->DAC == ATI_DAC_INTERNAL)))) 118732b578d3Smrg { 118832b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 118932b578d3Smrg "Driver does not support default visual %s for depth %d.\n", 119032b578d3Smrg xf86GetVisualName(pScreenInfo->defaultVisual), 119132b578d3Smrg pScreenInfo->depth); 119232b578d3Smrg goto bail; 119332b578d3Smrg } 119432b578d3Smrg 119532b578d3Smrg /* 119632b578d3Smrg * Set colour gamma. 119732b578d3Smrg */ 119832b578d3Smrg 119932b578d3Smrg if (!xf86SetGamma(pScreenInfo, defaultGamma)) 120032b578d3Smrg goto bail; 120132b578d3Smrg 120232b578d3Smrg pATI->depth = pScreenInfo->depth; 120332b578d3Smrg pATI->bitsPerPixel = pScreenInfo->bitsPerPixel; 120432b578d3Smrg pATI->weight = pScreenInfo->weight; 120532b578d3Smrg pATI->XModifier = pATI->bitsPerPixel / UnitOf(pATI->bitsPerPixel); 120632b578d3Smrg 120732b578d3Smrg /* 120832b578d3Smrg * Determine which CRT controller to use for video modes. 120932b578d3Smrg */ 121032b578d3Smrg 121132b578d3Smrg { 121232b578d3Smrg pATI->NewHW.crtc = ATI_CRTC_MACH64; 121332b578d3Smrg 121432b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, 121532b578d3Smrg "Using Mach64 accelerator CRTC.\n"); 121632b578d3Smrg 12172a51b5beSmrg#ifndef XSERVER_LIBPCIACCESS 121832b578d3Smrg#ifndef AVOID_CPIO 121932b578d3Smrg 122032b578d3Smrg if (pATI->VGAAdapter) 122132b578d3Smrg { 122232b578d3Smrg /* 122332b578d3Smrg * No need for VGA I/O resources during operating state (but they 122432b578d3Smrg * are still decoded). 122532b578d3Smrg */ 122632b578d3Smrg pResources = 122732b578d3Smrg xf86SetOperatingState(resVgaIo, pATI->iEntity, ResUnusedOpr); 122832b578d3Smrg if (pResources) 122932b578d3Smrg { 123032b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, 123132b578d3Smrg "Logic error setting operating state for VGA I/O.\n"); 123232b578d3Smrg xf86FreeResList(pResources); 123332b578d3Smrg } 123432b578d3Smrg 123532b578d3Smrg if (pATI->CPIO_VGAWonder) 123632b578d3Smrg { 123732b578d3Smrg pResources = xf86SetOperatingState(pATI->VGAWonderResources, 123832b578d3Smrg pATI->iEntity, ResUnusedOpr); 123932b578d3Smrg if (pResources) 124032b578d3Smrg { 124132b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, 124232b578d3Smrg "Logic error setting operating state for" 124332b578d3Smrg " VGAWonder I/O.\n"); 124432b578d3Smrg xf86FreeResList(pResources); 124532b578d3Smrg } 124632b578d3Smrg } 124732b578d3Smrg } 124832b578d3Smrg 124932b578d3Smrg#endif /* AVOID_CPIO */ 12502a51b5beSmrg#endif 125132b578d3Smrg 125232b578d3Smrg } 125332b578d3Smrg 125432b578d3Smrg /* 125532b578d3Smrg * Decide between the CRT and the panel. 125632b578d3Smrg */ 125732b578d3Smrg if (pATI->LCDPanelID >= 0) 125832b578d3Smrg { 125932b578d3Smrg if (!pATI->OptionPanelDisplay) 126032b578d3Smrg { 126132b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_CONFIG, 126232b578d3Smrg "Using CRT interface and disabling digital flat panel.\n"); 126332b578d3Smrg } 126432b578d3Smrg else 126532b578d3Smrg { 126632b578d3Smrg unsigned HDisplay, VDisplay; 126732b578d3Smrg CARD8 ClockMask, PostMask; 126832b578d3Smrg 126932b578d3Smrg /* 127032b578d3Smrg * Determine porch data. This groks the mode on entry to extract 127132b578d3Smrg * the width and position of its sync and blanking pulses, and 127232b578d3Smrg * considers any overscan as part of the displayed area, given that 127332b578d3Smrg * the overscan is also stretched. 127432b578d3Smrg * 127532b578d3Smrg * This also attempts to determine panel dimensions but cannot do 127632b578d3Smrg * so for one that is "auto-stretched". 127732b578d3Smrg */ 127832b578d3Smrg 127932b578d3Smrg if (pATI->Chip == ATI_CHIP_264LT) 128032b578d3Smrg { 128132b578d3Smrg pATIHW->lcd_gen_ctrl = inr(LCD_GEN_CTRL); 128232b578d3Smrg 128332b578d3Smrg /* Set up to read non-shadow registers */ 128432b578d3Smrg if (pATIHW->lcd_gen_ctrl & SHADOW_RW_EN) 128532b578d3Smrg outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl & ~SHADOW_RW_EN); 128632b578d3Smrg } 128732b578d3Smrg else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || 128832b578d3Smrg (pATI->Chip == ATI_CHIP_264XL) || 128932b578d3Smrg (pATI->Chip == ATI_CHIP_MOBILITY)) */ 129032b578d3Smrg { 129132b578d3Smrg pATIHW->lcd_index = inr(LCD_INDEX); 129232b578d3Smrg pATIHW->config_panel = ATIMach64GetLCDReg(LCD_CONFIG_PANEL); 129332b578d3Smrg pATIHW->lcd_gen_ctrl = ATIMach64GetLCDReg(LCD_GEN_CNTL); 129432b578d3Smrg 129532b578d3Smrg /* Set up to read non-shadow registers */ 129632b578d3Smrg if (pATIHW->lcd_gen_ctrl & SHADOW_RW_EN) 129732b578d3Smrg ATIMach64PutLCDReg(LCD_GEN_CNTL, 129832b578d3Smrg pATIHW->lcd_gen_ctrl & ~SHADOW_RW_EN); 129932b578d3Smrg } 130032b578d3Smrg 130132b578d3Smrg#ifndef AVOID_CPIO 130232b578d3Smrg 130332b578d3Smrg if (!(pATIHW->crtc_gen_cntl & CRTC_EXT_DISP_EN)) 130432b578d3Smrg { 130532b578d3Smrg unsigned HBlankStart, HSyncStart, HSyncEnd, HBlankEnd, HTotal; 130632b578d3Smrg unsigned VBlankStart, VSyncStart, VSyncEnd, VBlankEnd, VTotal; 130732b578d3Smrg 130832b578d3Smrg pATIHW->clock = (inb(R_GENMO) & 0x0CU) >> 2; 130932b578d3Smrg 131032b578d3Smrg pATIHW->crt[2] = GetReg(CRTX(pATI->CPIO_VGABase), 0x02U); 131132b578d3Smrg pATIHW->crt[3] = GetReg(CRTX(pATI->CPIO_VGABase), 0x03U); 131232b578d3Smrg pATIHW->crt[5] = GetReg(CRTX(pATI->CPIO_VGABase), 0x05U); 131332b578d3Smrg pATIHW->crt[7] = GetReg(CRTX(pATI->CPIO_VGABase), 0x07U); 131432b578d3Smrg pATIHW->crt[9] = GetReg(CRTX(pATI->CPIO_VGABase), 0x09U); 131532b578d3Smrg pATIHW->crt[21] = GetReg(CRTX(pATI->CPIO_VGABase), 0x15U); 131632b578d3Smrg pATIHW->crt[22] = GetReg(CRTX(pATI->CPIO_VGABase), 0x16U); 131732b578d3Smrg 131832b578d3Smrg pATIHW->crtc_h_total_disp = inr(CRTC_H_TOTAL_DISP); 131932b578d3Smrg pATIHW->crtc_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID); 132032b578d3Smrg pATIHW->crtc_v_total_disp = inr(CRTC_V_TOTAL_DISP); 132132b578d3Smrg pATIHW->crtc_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID); 132232b578d3Smrg 132332b578d3Smrg /* Switch to shadow registers */ 132432b578d3Smrg if (pATI->Chip == ATI_CHIP_264LT) 132532b578d3Smrg outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl | SHADOW_RW_EN); 132632b578d3Smrg else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || 132732b578d3Smrg (pATI->Chip == ATI_CHIP_264XL) || 132832b578d3Smrg (pATI->Chip == ATI_CHIP_MOBILITY)) */ 132932b578d3Smrg ATIMach64PutLCDReg(LCD_GEN_CNTL, 133032b578d3Smrg pATIHW->lcd_gen_ctrl | SHADOW_RW_EN); 133132b578d3Smrg 133232b578d3Smrg pATIHW->shadow_vga[2] = 133332b578d3Smrg GetReg(CRTX(pATI->CPIO_VGABase), 0x02U); 133432b578d3Smrg pATIHW->shadow_vga[3] = 133532b578d3Smrg GetReg(CRTX(pATI->CPIO_VGABase), 0x03U); 133632b578d3Smrg pATIHW->shadow_vga[5] = 133732b578d3Smrg GetReg(CRTX(pATI->CPIO_VGABase), 0x05U); 133832b578d3Smrg pATIHW->shadow_vga[7] = 133932b578d3Smrg GetReg(CRTX(pATI->CPIO_VGABase), 0x07U); 134032b578d3Smrg pATIHW->shadow_vga[9] = 134132b578d3Smrg GetReg(CRTX(pATI->CPIO_VGABase), 0x09U); 134232b578d3Smrg pATIHW->shadow_vga[21] = 134332b578d3Smrg GetReg(CRTX(pATI->CPIO_VGABase), 0x15U); 134432b578d3Smrg pATIHW->shadow_vga[22] = 134532b578d3Smrg GetReg(CRTX(pATI->CPIO_VGABase), 0x16U); 134632b578d3Smrg 134732b578d3Smrg pATIHW->shadow_h_total_disp = inr(CRTC_H_TOTAL_DISP); 134832b578d3Smrg pATIHW->shadow_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID); 134932b578d3Smrg pATIHW->shadow_v_total_disp = inr(CRTC_V_TOTAL_DISP); 135032b578d3Smrg pATIHW->shadow_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID); 135132b578d3Smrg 135232b578d3Smrg /* 135332b578d3Smrg * HSyncStart and HSyncEnd should equal their shadow 135432b578d3Smrg * counterparts. Otherwise, due to a chip bug, the panel might 135532b578d3Smrg * not sync, regardless of which register set is used to drive 135632b578d3Smrg * the panel. There are certain combinations of register 135732b578d3Smrg * values where the panel does in fact sync, but it remains 135832b578d3Smrg * impossible to accurately determine the horizontal sync pulse 135932b578d3Smrg * timing actually seen by the panel. 136032b578d3Smrg * 136132b578d3Smrg * Note that this hardware bug does not affect the CRT output. 136232b578d3Smrg */ 136332b578d3Smrg if (((pATIHW->crtc_h_sync_strt_wid ^ 136432b578d3Smrg pATIHW->shadow_h_sync_strt_wid) & 136532b578d3Smrg (CRTC_H_SYNC_STRT | CRTC_H_SYNC_STRT_HI | 136632b578d3Smrg CRTC_H_SYNC_WID))) 136732b578d3Smrg { 136832b578d3Smrg xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_NOTICE, 0, 136932b578d3Smrg "Invalid horizontal sync pulse timing detected in mode" 137032b578d3Smrg " on server entry.\n"); 137132b578d3Smrg 137232b578d3Smrg /* Don't trust input timing */ 137332b578d3Smrg pATI->OptionLCDSync = TRUE; 137432b578d3Smrg ModeType = 0; 137532b578d3Smrg } 137632b578d3Smrg 137732b578d3Smrg /* Merge in shadow registers as appropriate */ 137832b578d3Smrg if (pATIHW->lcd_gen_ctrl & SHADOW_EN) 137932b578d3Smrg { 138032b578d3Smrg pATIHW->crt[2] = pATIHW->shadow_vga[2]; 138132b578d3Smrg pATIHW->crt[3] = pATIHW->shadow_vga[3]; 138232b578d3Smrg pATIHW->crt[5] = pATIHW->shadow_vga[5]; 138332b578d3Smrg 138432b578d3Smrg /* XXX Does this apply to VGA? If so, what about the LT? */ 138532b578d3Smrg if ((pATI->Chip < ATI_CHIP_264LTPRO) || 138632b578d3Smrg !(pATIHW->config_panel & DONT_SHADOW_HEND)) 138732b578d3Smrg { 138832b578d3Smrg pATIHW->crtc_h_total_disp &= ~CRTC_H_DISP; 138932b578d3Smrg pATIHW->crtc_h_total_disp |= 139032b578d3Smrg pATIHW->shadow_h_total_disp & CRTC_H_DISP; 139132b578d3Smrg } 139232b578d3Smrg 139332b578d3Smrg pATIHW->crtc_h_total_disp &= ~CRTC_H_TOTAL; 139432b578d3Smrg pATIHW->crtc_h_total_disp |= 139532b578d3Smrg pATIHW->shadow_h_total_disp & CRTC_H_TOTAL; 139632b578d3Smrg pATIHW->crtc_h_sync_strt_wid = 139732b578d3Smrg pATIHW->shadow_h_sync_strt_wid; 139832b578d3Smrg 139932b578d3Smrg /* XXX Does this apply to VGA? */ 140032b578d3Smrg if (pATIHW->lcd_gen_ctrl & USE_SHADOWED_VEND) 140132b578d3Smrg { 140232b578d3Smrg pATIHW->crtc_v_total_disp &= ~CRTC_V_DISP; 140332b578d3Smrg pATIHW->crtc_v_total_disp |= 140432b578d3Smrg pATIHW->shadow_v_total_disp & CRTC_V_DISP; 140532b578d3Smrg } 140632b578d3Smrg 140732b578d3Smrg if (!(pATIHW->lcd_gen_ctrl & DONT_SHADOW_VPAR)) 140832b578d3Smrg { 140932b578d3Smrg pATIHW->crt[7] = pATIHW->shadow_vga[7]; 141032b578d3Smrg pATIHW->crt[9] = pATIHW->shadow_vga[9]; 141132b578d3Smrg pATIHW->crt[21] = pATIHW->shadow_vga[21]; 141232b578d3Smrg pATIHW->crt[22] = pATIHW->shadow_vga[22]; 141332b578d3Smrg 141432b578d3Smrg pATIHW->crtc_v_total_disp &= ~CRTC_V_TOTAL; 141532b578d3Smrg pATIHW->crtc_v_total_disp |= 141632b578d3Smrg pATIHW->shadow_v_total_disp & CRTC_V_TOTAL; 141732b578d3Smrg } 141832b578d3Smrg } 141932b578d3Smrg 142032b578d3Smrg if (!(pATIHW->lcd_gen_ctrl & DONT_SHADOW_VPAR)) 142132b578d3Smrg pATIHW->crtc_v_sync_strt_wid = 142232b578d3Smrg pATIHW->shadow_v_sync_strt_wid; 142332b578d3Smrg 142432b578d3Smrg /* 142532b578d3Smrg * Decipher input timing. This is complicated by the fact that 142632b578d3Smrg * the full width of all timing parameters, except for the 142732b578d3Smrg * blanking pulses, is only available through the accelerator 142832b578d3Smrg * registers, not the VGA ones. Blanking pulse boundaries must 142932b578d3Smrg * then be interpolated. 143032b578d3Smrg * 143132b578d3Smrg * Note that, in VGA mode, the accelerator's sync width fields 143232b578d3Smrg * are actually end positions, not widths. 143332b578d3Smrg */ 143432b578d3Smrg HDisplay = GetBits(pATIHW->crtc_h_total_disp, CRTC_H_DISP); 143532b578d3Smrg HSyncStart = 143632b578d3Smrg (GetBits(pATIHW->crtc_h_sync_strt_wid, 143732b578d3Smrg CRTC_H_SYNC_STRT_HI) * 143832b578d3Smrg (MaxBits(CRTC_H_SYNC_STRT) + 1)) | 143932b578d3Smrg GetBits(pATIHW->crtc_h_sync_strt_wid, CRTC_H_SYNC_STRT); 144032b578d3Smrg HSyncEnd = (HSyncStart & ~MaxBits(CRTC_H_SYNC_WID)) | 144132b578d3Smrg GetBits(pATIHW->crtc_h_sync_strt_wid, CRTC_H_SYNC_WID); 144232b578d3Smrg if (HSyncStart >= HSyncEnd) 144332b578d3Smrg HSyncEnd += MaxBits(CRTC_H_SYNC_WID) + 1; 144432b578d3Smrg HTotal = GetBits(pATIHW->crtc_h_total_disp, CRTC_H_TOTAL); 144532b578d3Smrg 144632b578d3Smrg HBlankStart = (HDisplay & ~0xFFU) | pATIHW->crt[2]; 144732b578d3Smrg if (HDisplay > HBlankStart) 144832b578d3Smrg HBlankStart += 0x0100U; 144932b578d3Smrg HBlankEnd = (HSyncEnd & ~0x3FU) | 145032b578d3Smrg ((pATIHW->crt[5] >> 2) & 0x20U) | 145132b578d3Smrg (pATIHW->crt[3] & 0x1FU); 145232b578d3Smrg if (HSyncEnd > (HBlankEnd + 1)) 145332b578d3Smrg HBlankEnd += 0x40U; 145432b578d3Smrg 145532b578d3Smrg VDisplay = GetBits(pATIHW->crtc_v_total_disp, CRTC_V_DISP); 145632b578d3Smrg VSyncStart = 145732b578d3Smrg GetBits(pATIHW->crtc_v_sync_strt_wid, CRTC_V_SYNC_STRT); 145832b578d3Smrg VSyncEnd = (VSyncStart & ~MaxBits(CRTC_V_SYNC_END_VGA)) | 145932b578d3Smrg GetBits(pATIHW->crtc_v_sync_strt_wid, CRTC_V_SYNC_END_VGA); 146032b578d3Smrg if (VSyncStart > VSyncEnd) 146132b578d3Smrg VSyncEnd += MaxBits(CRTC_V_SYNC_END_VGA) + 1; 146232b578d3Smrg VTotal = GetBits(pATIHW->crtc_v_total_disp, CRTC_V_TOTAL); 146332b578d3Smrg 146432b578d3Smrg VBlankStart = (VDisplay & ~0x03FFU) | 146532b578d3Smrg ((pATIHW->crt[9] << 4) & 0x0200U) | 146632b578d3Smrg ((pATIHW->crt[7] << 5) & 0x0100U) | pATIHW->crt[21]; 146732b578d3Smrg if (VDisplay > VBlankStart) 146832b578d3Smrg VBlankStart += 0x0400U; 146932b578d3Smrg VBlankEnd = (VSyncEnd & ~0x00FFU) | pATIHW->crt[22]; 147032b578d3Smrg if (VSyncEnd > (VBlankEnd + 1)) 147132b578d3Smrg VBlankEnd += 0x0100U; 147232b578d3Smrg 147332b578d3Smrg pATI->LCDHBlankWidth = HBlankEnd - HBlankStart; 147432b578d3Smrg pATI->LCDHSyncStart = HSyncStart - HBlankStart; 147532b578d3Smrg pATI->LCDHSyncWidth = HSyncEnd - HSyncStart; 147632b578d3Smrg 147732b578d3Smrg pATI->LCDVBlankWidth = VBlankEnd - VBlankStart; 147832b578d3Smrg pATI->LCDVSyncStart = VSyncStart - VBlankStart; 147932b578d3Smrg pATI->LCDVSyncWidth = VSyncEnd - VSyncStart; 148032b578d3Smrg 148132b578d3Smrg HDisplay = HTotal + 5 - pATI->LCDHBlankWidth; 148232b578d3Smrg VDisplay = VTotal + 2 - pATI->LCDVBlankWidth; 148332b578d3Smrg } 148432b578d3Smrg else 148532b578d3Smrg 148632b578d3Smrg#endif /* AVOID_CPIO */ 148732b578d3Smrg 148832b578d3Smrg { 148932b578d3Smrg pATIHW->clock = inr(CLOCK_CNTL) & 0x03U; 149032b578d3Smrg 149132b578d3Smrg pATIHW->crtc_h_total_disp = inr(CRTC_H_TOTAL_DISP); 149232b578d3Smrg pATIHW->crtc_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID); 149332b578d3Smrg pATIHW->crtc_v_total_disp = inr(CRTC_V_TOTAL_DISP); 149432b578d3Smrg pATIHW->crtc_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID); 149532b578d3Smrg pATIHW->ovr_wid_left_right = inr(OVR_WID_LEFT_RIGHT); 149632b578d3Smrg pATIHW->ovr_wid_top_bottom = inr(OVR_WID_TOP_BOTTOM); 149732b578d3Smrg 149832b578d3Smrg /* Switch to shadow registers */ 149932b578d3Smrg if (pATI->Chip == ATI_CHIP_264LT) 150032b578d3Smrg outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl | SHADOW_RW_EN); 150132b578d3Smrg else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || 150232b578d3Smrg (pATI->Chip == ATI_CHIP_264XL) || 150332b578d3Smrg (pATI->Chip == ATI_CHIP_MOBILITY)) */ 150432b578d3Smrg ATIMach64PutLCDReg(LCD_GEN_CNTL, 150532b578d3Smrg pATIHW->lcd_gen_ctrl | SHADOW_RW_EN); 150632b578d3Smrg 150732b578d3Smrg /* Oddly enough, there are no shadow overscan registers */ 150832b578d3Smrg pATIHW->shadow_h_total_disp = inr(CRTC_H_TOTAL_DISP); 150932b578d3Smrg pATIHW->shadow_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID); 151032b578d3Smrg pATIHW->shadow_v_total_disp = inr(CRTC_V_TOTAL_DISP); 151132b578d3Smrg pATIHW->shadow_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID); 151232b578d3Smrg 151332b578d3Smrg /* 151432b578d3Smrg * HSyncStart and HSyncEnd should equal their shadow 151532b578d3Smrg * counterparts. Otherwise, due to a chip bug, the panel might 151632b578d3Smrg * not sync, regardless of which register set is used to drive 151732b578d3Smrg * the panel. There are certain combinations of register 151832b578d3Smrg * values where the panel does in fact sync, but it remains 151932b578d3Smrg * impossible to accurately determine the horizontal sync pulse 152032b578d3Smrg * timing actually seen by the panel. 152132b578d3Smrg * 152232b578d3Smrg * Note that this hardware bug does not affect the CRT output. 152332b578d3Smrg */ 152432b578d3Smrg if (((pATIHW->crtc_h_sync_strt_wid ^ 152532b578d3Smrg pATIHW->shadow_h_sync_strt_wid) & 152632b578d3Smrg (CRTC_H_SYNC_STRT | CRTC_H_SYNC_STRT_HI | 152732b578d3Smrg CRTC_H_SYNC_WID))) 152832b578d3Smrg { 152932b578d3Smrg xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_NOTICE, 0, 153032b578d3Smrg "Invalid horizontal sync pulse timing detected in mode" 153132b578d3Smrg " on server entry.\n"); 153232b578d3Smrg 153332b578d3Smrg /* Don't trust input timing */ 153432b578d3Smrg pATI->OptionLCDSync = TRUE; 153532b578d3Smrg ModeType = 0; 153632b578d3Smrg } 153732b578d3Smrg 153832b578d3Smrg /* Merge in shadow registers as appropriate */ 153932b578d3Smrg if (pATIHW->lcd_gen_ctrl & SHADOW_EN) 154032b578d3Smrg { 154132b578d3Smrg /* XXX What about the LT? */ 154232b578d3Smrg if ((pATI->Chip < ATI_CHIP_264LTPRO) || 154332b578d3Smrg !(pATIHW->config_panel & DONT_SHADOW_HEND)) 154432b578d3Smrg { 154532b578d3Smrg pATIHW->crtc_h_total_disp &= ~CRTC_H_DISP; 154632b578d3Smrg pATIHW->crtc_h_total_disp |= 154732b578d3Smrg pATIHW->shadow_h_total_disp & CRTC_H_DISP; 154832b578d3Smrg } 154932b578d3Smrg 155032b578d3Smrg pATIHW->crtc_h_total_disp &= ~CRTC_H_TOTAL; 155132b578d3Smrg pATIHW->crtc_h_total_disp |= 155232b578d3Smrg pATIHW->shadow_h_total_disp & CRTC_H_TOTAL; 155332b578d3Smrg pATIHW->crtc_h_sync_strt_wid = 155432b578d3Smrg pATIHW->shadow_h_sync_strt_wid; 155532b578d3Smrg 155632b578d3Smrg if (pATIHW->lcd_gen_ctrl & USE_SHADOWED_VEND) 155732b578d3Smrg { 155832b578d3Smrg pATIHW->crtc_v_total_disp &= ~CRTC_V_DISP; 155932b578d3Smrg pATIHW->crtc_v_total_disp |= 156032b578d3Smrg pATIHW->shadow_v_total_disp & CRTC_V_DISP; 156132b578d3Smrg } 156232b578d3Smrg 156332b578d3Smrg if (!(pATIHW->lcd_gen_ctrl & DONT_SHADOW_VPAR)) 156432b578d3Smrg { 156532b578d3Smrg pATIHW->crtc_v_total_disp &= ~CRTC_V_TOTAL; 156632b578d3Smrg pATIHW->crtc_v_total_disp |= 156732b578d3Smrg pATIHW->shadow_v_total_disp & CRTC_V_TOTAL; 156832b578d3Smrg } 156932b578d3Smrg } 157032b578d3Smrg 157132b578d3Smrg if (!(pATIHW->lcd_gen_ctrl & DONT_SHADOW_VPAR)) 157232b578d3Smrg pATIHW->crtc_v_sync_strt_wid = 157332b578d3Smrg pATIHW->shadow_v_sync_strt_wid; 157432b578d3Smrg 157532b578d3Smrg /* Decipher input timing */ 157632b578d3Smrg HDisplay = GetBits(pATIHW->crtc_h_total_disp, CRTC_H_DISP) + 157732b578d3Smrg GetBits(pATIHW->ovr_wid_left_right, OVR_WID_LEFT) + 157832b578d3Smrg GetBits(pATIHW->ovr_wid_left_right, OVR_WID_RIGHT); 157932b578d3Smrg VDisplay = GetBits(pATIHW->crtc_v_total_disp, CRTC_V_DISP) + 158032b578d3Smrg GetBits(pATIHW->ovr_wid_top_bottom, OVR_WID_TOP) + 158132b578d3Smrg GetBits(pATIHW->ovr_wid_top_bottom, OVR_WID_BOTTOM); 158232b578d3Smrg 158332b578d3Smrg pATI->LCDHSyncStart = 158432b578d3Smrg (GetBits(pATIHW->crtc_h_sync_strt_wid, 158532b578d3Smrg CRTC_H_SYNC_STRT_HI) * 158632b578d3Smrg (MaxBits(CRTC_H_SYNC_STRT) + 1)) + 158732b578d3Smrg GetBits(pATIHW->crtc_h_sync_strt_wid, CRTC_H_SYNC_STRT) - 158832b578d3Smrg HDisplay; 158932b578d3Smrg pATI->LCDHSyncWidth = 159032b578d3Smrg GetBits(pATIHW->crtc_h_sync_strt_wid, CRTC_H_SYNC_WID); 159132b578d3Smrg pATI->LCDHBlankWidth = 159232b578d3Smrg GetBits(pATIHW->crtc_h_total_disp, CRTC_H_TOTAL) - 159332b578d3Smrg HDisplay; 159432b578d3Smrg pATI->LCDVSyncStart = 159532b578d3Smrg GetBits(pATIHW->crtc_v_sync_strt_wid, CRTC_V_SYNC_STRT) - 159632b578d3Smrg VDisplay; 159732b578d3Smrg pATI->LCDVSyncWidth = 159832b578d3Smrg GetBits(pATIHW->crtc_v_sync_strt_wid, CRTC_V_SYNC_WID); 159932b578d3Smrg pATI->LCDVBlankWidth = 160032b578d3Smrg GetBits(pATIHW->crtc_v_total_disp, CRTC_V_TOTAL) - 160132b578d3Smrg VDisplay; 160232b578d3Smrg 160332b578d3Smrg HDisplay++; 160432b578d3Smrg VDisplay++; 160532b578d3Smrg } 160632b578d3Smrg 160732b578d3Smrg /* Restore LCD registers */ 160832b578d3Smrg if (pATI->Chip == ATI_CHIP_264LT) 160932b578d3Smrg { 161032b578d3Smrg outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl); 161132b578d3Smrg } 161232b578d3Smrg else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || 161332b578d3Smrg (pATI->Chip == ATI_CHIP_264XL) || 161432b578d3Smrg (pATI->Chip == ATI_CHIP_MOBILITY)) */ 161532b578d3Smrg { 161632b578d3Smrg ATIMach64PutLCDReg(LCD_GEN_CNTL, pATIHW->lcd_gen_ctrl); 161732b578d3Smrg outr(LCD_INDEX, pATIHW->lcd_index); 161832b578d3Smrg } 161932b578d3Smrg 162032b578d3Smrg HDisplay <<= 3; 162132b578d3Smrg pATI->LCDHSyncStart <<= 3; 162232b578d3Smrg pATI->LCDHSyncWidth <<= 3; 162332b578d3Smrg pATI->LCDHBlankWidth <<= 3; 162432b578d3Smrg 162532b578d3Smrg /* Calculate panel dimensions implied by the input timing */ 162632b578d3Smrg if ((pATIHW->horz_stretching & 162732b578d3Smrg (HORZ_STRETCH_EN | AUTO_HORZ_RATIO)) == 162832b578d3Smrg HORZ_STRETCH_EN) 162932b578d3Smrg { 163032b578d3Smrg if (pATIHW->horz_stretching & HORZ_STRETCH_MODE) 163132b578d3Smrg { 163232b578d3Smrg if (pATIHW->horz_stretching & HORZ_STRETCH_BLEND) 163332b578d3Smrg { 163432b578d3Smrg HDisplay = 163532b578d3Smrg (HDisplay * (MaxBits(HORZ_STRETCH_BLEND) + 1)) / 163632b578d3Smrg GetBits(pATIHW->horz_stretching, 163732b578d3Smrg HORZ_STRETCH_BLEND); 163832b578d3Smrg } 163932b578d3Smrg } 164032b578d3Smrg else if (((pATIHW->horz_stretching & HORZ_STRETCH_LOOP) > 164132b578d3Smrg HORZ_STRETCH_LOOP15) || 164232b578d3Smrg (pATIHW->horz_stretching & 164332b578d3Smrg SetBits(1, HORZ_STRETCH_RATIO))) 164432b578d3Smrg { 164532b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, 164632b578d3Smrg "Ignoring invalid horizontal stretch ratio in mode on" 164732b578d3Smrg " server entry.\n"); 164832b578d3Smrg } 164932b578d3Smrg else 165032b578d3Smrg { 165132b578d3Smrg IOValue = 165232b578d3Smrg GetBits(pATIHW->horz_stretching, HORZ_STRETCH_RATIO); 165332b578d3Smrg 165432b578d3Smrg switch (GetBits(pATIHW->horz_stretching, 165532b578d3Smrg HORZ_STRETCH_LOOP)) 165632b578d3Smrg { 165732b578d3Smrg case GetBits(HORZ_STRETCH_LOOP09, HORZ_STRETCH_LOOP): 165832b578d3Smrg i = 9; 165932b578d3Smrg IOValue &= (1 << 9) - 1; 166032b578d3Smrg break; 166132b578d3Smrg 166232b578d3Smrg case GetBits(HORZ_STRETCH_LOOP11, HORZ_STRETCH_LOOP): 166332b578d3Smrg i = 11; 166432b578d3Smrg IOValue &= (1 << 11) - 1; 166532b578d3Smrg break; 166632b578d3Smrg 166732b578d3Smrg case GetBits(HORZ_STRETCH_LOOP12, HORZ_STRETCH_LOOP): 166832b578d3Smrg i = 12; 166932b578d3Smrg IOValue &= (1 << 12) - 1; 167032b578d3Smrg break; 167132b578d3Smrg 167232b578d3Smrg case GetBits(HORZ_STRETCH_LOOP14, HORZ_STRETCH_LOOP): 167332b578d3Smrg i = 14; 167432b578d3Smrg IOValue &= (1 << 14) - 1; 167532b578d3Smrg break; 167632b578d3Smrg 167732b578d3Smrg case GetBits(HORZ_STRETCH_LOOP15, HORZ_STRETCH_LOOP): 167832b578d3Smrg default: /* Muffle compiler */ 167932b578d3Smrg i = 15; 168032b578d3Smrg IOValue &= (1 << 15) - 1; 168132b578d3Smrg break; 168232b578d3Smrg } 168332b578d3Smrg 168432b578d3Smrg if (IOValue) 168532b578d3Smrg { 168632b578d3Smrg /* Count the number of bits in IOValue */ 168732b578d3Smrg j = (IOValue >> 1) & 0x36DBU; 168832b578d3Smrg j = IOValue - j - ((j >> 1) & 0x36DBU); 168932b578d3Smrg j = ((j + (j >> 3)) & 0x71C7U) % 0x3FU; 169032b578d3Smrg 169132b578d3Smrg HDisplay = (HDisplay * i) / j; 169232b578d3Smrg } 169332b578d3Smrg } 169432b578d3Smrg } 169532b578d3Smrg 169632b578d3Smrg if ((pATIHW->vert_stretching & VERT_STRETCH_EN) && 169732b578d3Smrg !(pATIHW->ext_vert_stretch & AUTO_VERT_RATIO)) 169832b578d3Smrg { 169932b578d3Smrg if ((pATIHW->vert_stretching & VERT_STRETCH_USE0) || 170032b578d3Smrg (VDisplay <= 350)) 170132b578d3Smrg IOValue = 170232b578d3Smrg GetBits(pATIHW->vert_stretching, VERT_STRETCH_RATIO0); 170332b578d3Smrg else if (VDisplay <= 400) 170432b578d3Smrg IOValue = 170532b578d3Smrg GetBits(pATIHW->vert_stretching, VERT_STRETCH_RATIO1); 170632b578d3Smrg else if ((VDisplay <= 480) || 170732b578d3Smrg !(pATIHW->ext_vert_stretch & VERT_STRETCH_RATIO3)) 170832b578d3Smrg IOValue = 170932b578d3Smrg GetBits(pATIHW->vert_stretching, VERT_STRETCH_RATIO2); 171032b578d3Smrg else 171132b578d3Smrg IOValue = 171232b578d3Smrg GetBits(pATIHW->ext_vert_stretch, VERT_STRETCH_RATIO3); 171332b578d3Smrg 171432b578d3Smrg if (IOValue) 171532b578d3Smrg VDisplay = 171632b578d3Smrg (VDisplay * (MaxBits(VERT_STRETCH_RATIO0) + 1)) / 171732b578d3Smrg IOValue; 171832b578d3Smrg } 171932b578d3Smrg 172032b578d3Smrg /* Match calculated dimensions to probed dimensions */ 172132b578d3Smrg if (!pATI->LCDHorizontal) 172232b578d3Smrg { 172332b578d3Smrg if ((pATIHW->horz_stretching & 172432b578d3Smrg (HORZ_STRETCH_EN | AUTO_HORZ_RATIO)) != 172532b578d3Smrg (HORZ_STRETCH_EN | AUTO_HORZ_RATIO)) 172632b578d3Smrg pATI->LCDHorizontal = HDisplay; 172732b578d3Smrg } 172832b578d3Smrg else if (pATI->LCDHorizontal != (int)HDisplay) 172932b578d3Smrg { 173032b578d3Smrg if ((pATIHW->horz_stretching & 173132b578d3Smrg (HORZ_STRETCH_EN | AUTO_HORZ_RATIO)) != 173232b578d3Smrg (HORZ_STRETCH_EN | AUTO_HORZ_RATIO)) 173332b578d3Smrg xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 4, 173432b578d3Smrg "Inconsistent panel horizontal dimension:" 173532b578d3Smrg " %d and %d.\n", pATI->LCDHorizontal, HDisplay); 173632b578d3Smrg HDisplay = pATI->LCDHorizontal; 173732b578d3Smrg } 173832b578d3Smrg 173932b578d3Smrg if (!pATI->LCDVertical) 174032b578d3Smrg { 174132b578d3Smrg if (!(pATIHW->vert_stretching & VERT_STRETCH_EN) || 174232b578d3Smrg !(pATIHW->ext_vert_stretch & AUTO_VERT_RATIO)) 174332b578d3Smrg pATI->LCDVertical = VDisplay; 174432b578d3Smrg } 174532b578d3Smrg else if (pATI->LCDVertical != (int)VDisplay) 174632b578d3Smrg { 174732b578d3Smrg if (!(pATIHW->vert_stretching & VERT_STRETCH_EN) || 174832b578d3Smrg !(pATIHW->ext_vert_stretch & AUTO_VERT_RATIO)) 174932b578d3Smrg xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 4, 175032b578d3Smrg "Inconsistent panel vertical dimension: %d and %d.\n", 175132b578d3Smrg pATI->LCDVertical, VDisplay); 175232b578d3Smrg VDisplay = pATI->LCDVertical; 175332b578d3Smrg } 175432b578d3Smrg 175532b578d3Smrg if (!pATI->LCDHorizontal || !pATI->LCDVertical) 175632b578d3Smrg { 175732b578d3Smrg if (pATI->LCDPanelID || (pATI->Chip <= ATI_CHIP_264LTPRO)) 175832b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 175932b578d3Smrg "Unable to determine dimensions of panel (ID %d).\n", 176032b578d3Smrg pATI->LCDPanelID); 176132b578d3Smrg else 176232b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 176332b578d3Smrg "Unable to determine dimensions of panel.\n"); 176432b578d3Smrg 176532b578d3Smrg goto bail; 176632b578d3Smrg } 176732b578d3Smrg 176832b578d3Smrg /* If the mode on entry wasn't stretched, adjust timings */ 176932b578d3Smrg if (!(pATIHW->horz_stretching & HORZ_STRETCH_EN) && 177032b578d3Smrg (pATI->LCDHorizontal > (int)HDisplay)) 177132b578d3Smrg { 177232b578d3Smrg HDisplay = pATI->LCDHorizontal - HDisplay; 177332b578d3Smrg if (pATI->LCDHSyncStart >= HDisplay) 177432b578d3Smrg pATI->LCDHSyncStart -= HDisplay; 177532b578d3Smrg else 177632b578d3Smrg pATI->LCDHSyncStart = 0; 177732b578d3Smrg pATI->LCDHBlankWidth -= HDisplay; 177832b578d3Smrg HDisplay = pATI->LCDHSyncStart + pATI->LCDHSyncWidth; 177932b578d3Smrg if (pATI->LCDHBlankWidth < HDisplay) 178032b578d3Smrg pATI->LCDHBlankWidth = HDisplay; 178132b578d3Smrg } 178232b578d3Smrg 178332b578d3Smrg if (!(pATIHW->vert_stretching & VERT_STRETCH_EN) && 178432b578d3Smrg (pATI->LCDVertical > (int)VDisplay)) 178532b578d3Smrg { 178632b578d3Smrg VDisplay = pATI->LCDVertical - VDisplay; 178732b578d3Smrg if (pATI->LCDVSyncStart >= VDisplay) 178832b578d3Smrg pATI->LCDVSyncStart -= VDisplay; 178932b578d3Smrg else 179032b578d3Smrg pATI->LCDVSyncStart = 0; 179132b578d3Smrg pATI->LCDVBlankWidth -= VDisplay; 179232b578d3Smrg VDisplay = pATI->LCDVSyncStart + pATI->LCDVSyncWidth; 179332b578d3Smrg if (pATI->LCDVBlankWidth < VDisplay) 179432b578d3Smrg pATI->LCDVBlankWidth = VDisplay; 179532b578d3Smrg } 179632b578d3Smrg 179732b578d3Smrg if (pATI->LCDPanelID || (pATI->Chip <= ATI_CHIP_264LTPRO)) 179832b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, 179932b578d3Smrg "%dx%d panel (ID %d) detected.\n", 180032b578d3Smrg pATI->LCDHorizontal, pATI->LCDVertical, pATI->LCDPanelID); 180132b578d3Smrg else 180232b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, 180332b578d3Smrg "%dx%d panel detected.\n", 180432b578d3Smrg pATI->LCDHorizontal, pATI->LCDVertical); 180532b578d3Smrg 180632b578d3Smrg /* 180732b578d3Smrg * Determine panel clock. This must be done after option 180832b578d3Smrg * processing so that the adapter's reference frequency is always 180932b578d3Smrg * available. 181032b578d3Smrg * 181132b578d3Smrg * Get post divider. A GCC bug has caused the following expression 181232b578d3Smrg * to be broken down into its individual components. 181332b578d3Smrg */ 181432b578d3Smrg ClockMask = PLL_VCLK0_XDIV << pATIHW->clock; 181532b578d3Smrg PostMask = PLL_VCLK0_POST_DIV << (pATIHW->clock * 2); 181632b578d3Smrg i = GetBits(ATIMach64GetPLLReg(PLL_XCLK_CNTL), ClockMask); 181732b578d3Smrg i *= MaxBits(PLL_VCLK0_POST_DIV) + 1; 181832b578d3Smrg i |= GetBits(ATIMach64GetPLLReg(PLL_VCLK_POST_DIV), PostMask); 181932b578d3Smrg 182032b578d3Smrg /* Calculate clock of mode on entry */ 182132b578d3Smrg Numerator = ATIMach64GetPLLReg(PLL_VCLK0_FB_DIV + pATIHW->clock) * 182232b578d3Smrg pATI->ReferenceNumerator; 182332b578d3Smrg Denominator = pATI->ClockDescriptor.MinM * 182432b578d3Smrg pATI->ReferenceDenominator * 182532b578d3Smrg pATI->ClockDescriptor.PostDividers[i]; 182632b578d3Smrg pATI->LCDClock = ATIDivide(Numerator, Denominator, 1, 0); 182732b578d3Smrg 182832b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, 182932b578d3Smrg "Panel clock is %.3f MHz.\n", 183032b578d3Smrg (double)(pATI->LCDClock) / 1000.0); 183132b578d3Smrg 183232b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, 183332b578d3Smrg "Using digital flat panel interface%s.\n", 183432b578d3Smrg pATI->OptionCRTDisplay ? 183532b578d3Smrg " to display on both CRT and panel" : ""); 183632b578d3Smrg } 183732b578d3Smrg } 183832b578d3Smrg 183932b578d3Smrg /* 184032b578d3Smrg * Finish detecting video RAM size. 184132b578d3Smrg */ 184232b578d3Smrg pScreenInfo->videoRam = pATI->VideoRAM; 184332b578d3Smrg 184432b578d3Smrg { 184532b578d3Smrg { 184632b578d3Smrg /* Get adapter's linear aperture configuration */ 184732b578d3Smrg pATIHW->config_cntl = inr(CONFIG_CNTL); 184832b578d3Smrg pATI->LinearBase = 184932b578d3Smrg GetBits(pATIHW->config_cntl, CFG_MEM_AP_LOC) << 22; 185032b578d3Smrg if ((pATIHW->config_cntl & CFG_MEM_AP_SIZE) != CFG_MEM_AP_SIZE) 185132b578d3Smrg { 185232b578d3Smrg pATI->LinearSize = 185332b578d3Smrg GetBits(pATIHW->config_cntl, CFG_MEM_AP_SIZE) << 22; 185432b578d3Smrg 185532b578d3Smrg /* 185632b578d3Smrg * Linear aperture could have been disabled (but still 185732b578d3Smrg * assigned) by BIOS initialisation. 185832b578d3Smrg */ 185932b578d3Smrg if (pATI->LinearBase && !pATI->LinearSize) 186032b578d3Smrg { 186132b578d3Smrg if ((pATI->Chip <= ATI_CHIP_88800GXD) && 186232b578d3Smrg (pATI->VideoRAM < 4096)) 186332b578d3Smrg pATI->LinearSize = 4 * 1024 * 1024; 186432b578d3Smrg else 186532b578d3Smrg pATI->LinearSize = 8 * 1024 * 1024; 186632b578d3Smrg } 186732b578d3Smrg } 186832b578d3Smrg 186932b578d3Smrg if (pATI->LinearBase && pATI->LinearSize) 187032b578d3Smrg { 187132b578d3Smrg int AcceleratorVideoRAM = 0, ServerVideoRAM; 187232b578d3Smrg 187332b578d3Smrg#ifndef AVOID_CPIO 187432b578d3Smrg 187532b578d3Smrg /* 187632b578d3Smrg * Unless specified in PCI configuration space, set MMIO 187732b578d3Smrg * address to tail end of linear aperture. 187832b578d3Smrg */ 187932b578d3Smrg if (!pATI->Block0Base) 188032b578d3Smrg { 188132b578d3Smrg pATI->Block0Base = 188232b578d3Smrg pATI->LinearBase + pATI->LinearSize - 0x00000400U; 188332b578d3Smrg pATI->MMIOInLinear = TRUE; 188432b578d3Smrg } 188532b578d3Smrg 188632b578d3Smrg#endif /* AVOID_CPIO */ 188732b578d3Smrg 188832b578d3Smrg AcceleratorVideoRAM = pATI->LinearSize >> 10; 188932b578d3Smrg 189032b578d3Smrg /* 189132b578d3Smrg * Account for MMIO area at the tail end of the linear 189232b578d3Smrg * aperture, if it is needed or if it cannot be disabled. 189332b578d3Smrg */ 189432b578d3Smrg if (pATI->MMIOInLinear || (pATI->Chip < ATI_CHIP_264VTB)) 189532b578d3Smrg AcceleratorVideoRAM -= 2; 189632b578d3Smrg 189732b578d3Smrg ServerVideoRAM = pATI->VideoRAM; 189832b578d3Smrg 189932b578d3Smrg if (pATI->Cursor > ATI_CURSOR_SOFTWARE) 190032b578d3Smrg { 190132b578d3Smrg /* 190232b578d3Smrg * Allocate a 1 kB cursor image area at the top of the 190332b578d3Smrg * little-endian aperture, just before any MMIO area that 190432b578d3Smrg * might also be there. 190532b578d3Smrg */ 190632b578d3Smrg if (ServerVideoRAM > AcceleratorVideoRAM) 190732b578d3Smrg ServerVideoRAM = AcceleratorVideoRAM; 190832b578d3Smrg 190932b578d3Smrg ServerVideoRAM--; 191032b578d3Smrg pATI->CursorOffset = ServerVideoRAM << 10; 191132b578d3Smrg pATI->CursorBase = pATI->LinearBase + pATI->CursorOffset; 191232b578d3Smrg 191332b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, 191432b578d3Smrg "Storing hardware cursor image at 0x%08lX.\n", 191532b578d3Smrg pATI->CursorBase); 191632b578d3Smrg } 191732b578d3Smrg 191832b578d3Smrg { 191932b578d3Smrg CARD32 PageSize = getpagesize() >> 10; 192032b578d3Smrg 192132b578d3Smrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN 192232b578d3Smrg 192332b578d3Smrg /* 192432b578d3Smrg * MMIO areas must be mmap()'ed separately to avoid write 192532b578d3Smrg * combining them. Thus, they might not end up still 192632b578d3Smrg * adjacent with the little-endian linear aperture after 192732b578d3Smrg * mmap()'ing. So, round down the linear aperture size to 192832b578d3Smrg * avoid an overlap. Any hardware cursor image area might 192932b578d3Smrg * not end up being write combined, but this seems 193032b578d3Smrg * preferable to further reducing the video memory size 193132b578d3Smrg * advertised to the server. 193232b578d3Smrg * 193332b578d3Smrg * XXX Ideally this should be dealt with in the os-support 193432b578d3Smrg * layer, i.e., it should be possible to reset a 193532b578d3Smrg * subarea's write combining after it has been 193632b578d3Smrg * mmap()'ed, but doing so currently causes the removal 193732b578d3Smrg * of write combining for the entire aperture. 193832b578d3Smrg */ 193932b578d3Smrg if (pATI->MMIOInLinear) 194032b578d3Smrg AcceleratorVideoRAM -= AcceleratorVideoRAM % PageSize; 194132b578d3Smrg 194232b578d3Smrg#else /* if X_BYTE_ORDER != X_LITTLE_ENDIAN */ 194332b578d3Smrg 194432b578d3Smrg /* 194532b578d3Smrg * Big-endian apertures are 8 MB higher and don't contain 194632b578d3Smrg * an MMIO area. 194732b578d3Smrg */ 194832b578d3Smrg pATI->LinearBase += 0x00800000U; 194932b578d3Smrg AcceleratorVideoRAM = pATI->LinearSize >> 10; 195032b578d3Smrg 195132b578d3Smrg#endif /* X_BYTE_ORDER */ 195232b578d3Smrg 195332b578d3Smrg if (ServerVideoRAM > AcceleratorVideoRAM) 195432b578d3Smrg ServerVideoRAM = AcceleratorVideoRAM; 195532b578d3Smrg else if (AcceleratorVideoRAM > pATI->VideoRAM) 195632b578d3Smrg AcceleratorVideoRAM = pATI->VideoRAM; 195732b578d3Smrg 195832b578d3Smrg PageSize--; 195932b578d3Smrg AcceleratorVideoRAM = 196032b578d3Smrg (AcceleratorVideoRAM + PageSize) & ~PageSize; 196132b578d3Smrg 196232b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, 196332b578d3Smrg "Using %d MB linear aperture at 0x%08lX.\n", 196432b578d3Smrg pATI->LinearSize >> 20, pATI->LinearBase); 196532b578d3Smrg 196632b578d3Smrg /* Only mmap what is needed */ 196732b578d3Smrg ApertureSize = pATI->LinearSize = 196832b578d3Smrg AcceleratorVideoRAM << 10; 196932b578d3Smrg } 197032b578d3Smrg 197132b578d3Smrg if (ServerVideoRAM < pATI->VideoRAM) 197232b578d3Smrg { 197332b578d3Smrg pScreenInfo->videoRam = ServerVideoRAM; 197432b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE, 197532b578d3Smrg "Virtual resolutions will be limited to %d kB\n due to" 197632b578d3Smrg " linear aperture size and/or placement of hardware" 197732b578d3Smrg " cursor image area.\n", 197832b578d3Smrg ServerVideoRAM); 197932b578d3Smrg } 198032b578d3Smrg } 198132b578d3Smrg } 198232b578d3Smrg 198332b578d3Smrg if (!pATI->LinearBase || !pATI->LinearSize) 198432b578d3Smrg { 198532b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 198632b578d3Smrg "Linear aperture not available.\n"); 198732b578d3Smrg goto bail; 198832b578d3Smrg } 198932b578d3Smrg 199032b578d3Smrg if (pATI->Block0Base) 199132b578d3Smrg { 199232b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, 199332b578d3Smrg "Using Block 0 MMIO aperture at 0x%08lX.\n", pATI->Block0Base); 199432b578d3Smrg 199532b578d3Smrg /* Set Block1 MMIO address if supported */ 199632b578d3Smrg if (pATI->Chip >= ATI_CHIP_264VT) 199732b578d3Smrg { 199832b578d3Smrg pATI->Block1Base = pATI->Block0Base - 0x00000400U; 199932b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, 200032b578d3Smrg "Using Block 1 MMIO aperture at 0x%08lX.\n", 200132b578d3Smrg pATI->Block1Base); 200232b578d3Smrg } 200332b578d3Smrg } 200432b578d3Smrg } 200532b578d3Smrg 20062a51b5beSmrg#ifndef XSERVER_LIBPCIACCESS 200732b578d3Smrg#ifndef AVOID_CPIO 200832b578d3Smrg 200932b578d3Smrg if (pATI->VGAAdapter) 201032b578d3Smrg { 201132b578d3Smrg /* 201232b578d3Smrg * Free VGA memory aperture during operating state (but it is still 201332b578d3Smrg * decoded). 201432b578d3Smrg */ 201532b578d3Smrg pResources = xf86SetOperatingState(resVgaMem, pATI->iEntity, 201632b578d3Smrg ResUnusedOpr); 201732b578d3Smrg if (pResources) 201832b578d3Smrg { 201932b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, 202032b578d3Smrg "Logic error setting operating state for VGA memory" 202132b578d3Smrg " aperture.\n"); 202232b578d3Smrg xf86FreeResList(pResources); 202332b578d3Smrg } 202432b578d3Smrg } 202532b578d3Smrg 202632b578d3Smrg#endif /* AVOID_CPIO */ 20272a51b5beSmrg#endif 202832b578d3Smrg 202932b578d3Smrg /* 203032b578d3Smrg * Remap apertures. Must lock and re-unlock around this in case the 203132b578d3Smrg * remapping fails. 203232b578d3Smrg */ 203332b578d3Smrg ATILock(pATI); 203432b578d3Smrg ATIUnmapApertures(pScreenInfo->scrnIndex, pATI); 203532b578d3Smrg if (!ATIMapApertures(pScreenInfo->scrnIndex, pATI)) 203632b578d3Smrg return FALSE; 203732b578d3Smrg 203832b578d3Smrg ATIUnlock(pATI); 203932b578d3Smrg 204032b578d3Smrg if (pATI->OptionAccel) 204132b578d3Smrg { 204232b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, 204332b578d3Smrg "MMIO write caching %sabled.\n", 204432b578d3Smrg pATI->OptionMMIOCache ? "en" : "dis"); 204532b578d3Smrg } 204632b578d3Smrg 204732b578d3Smrg { 204832b578d3Smrg if (pATI->Chip >= ATI_CHIP_264CT) 204932b578d3Smrg ATIReportMemory(pScreenInfo, pATI, 205032b578d3Smrg ATIMemoryTypeNames_264xT[pATI->MemoryType]); 205132b578d3Smrg else if (pATI->Chip == ATI_CHIP_88800CX) 205232b578d3Smrg ATIReportMemory(pScreenInfo, pATI, 205332b578d3Smrg ATIMemoryTypeNames_88800CX[pATI->MemoryType]); 205432b578d3Smrg else 205532b578d3Smrg ATIReportMemory(pScreenInfo, pATI, 205632b578d3Smrg ATIMemoryTypeNames_Mach[pATI->MemoryType]); 205732b578d3Smrg } 205832b578d3Smrg 205932b578d3Smrg /* 206032b578d3Smrg * Finish banking setup. This needs to be fixed to not assume the mode on 206132b578d3Smrg * entry is a VGA mode. XXX 206232b578d3Smrg */ 206332b578d3Smrg 206432b578d3Smrg#ifndef AVOID_CPIO 206532b578d3Smrg 206632b578d3Smrg if (!pATI->VGAAdapter) 206732b578d3Smrg { 206832b578d3Smrg pATI->NewHW.SetBank = ATIx8800SetBank; 206932b578d3Smrg pATI->NewHW.nPlane = 0; 207032b578d3Smrg 207132b578d3Smrg pATIHW->crtc = pATI->NewHW.crtc; 207232b578d3Smrg 207332b578d3Smrg pATIHW->SetBank = (ATIBankProcPtr)NoopDDA; 207432b578d3Smrg } 207532b578d3Smrg else 207632b578d3Smrg { 207732b578d3Smrg Bool ext_disp_en = (pATI->LockData.crtc_gen_cntl & CRTC_EXT_DISP_EN); 207832b578d3Smrg Bool vga_ap_en = (pATI->LockData.config_cntl & CFG_MEM_VGA_AP_EN); 207932b578d3Smrg Bool vga_color_256 = (GetReg(SEQX, 0x04U) & 0x08U); 208032b578d3Smrg 208132b578d3Smrg pATI->NewHW.SetBank = ATIMach64SetBankPacked; 208232b578d3Smrg pATI->NewHW.nPlane = 1; 208332b578d3Smrg 208432b578d3Smrg pATIHW->crtc = ATI_CRTC_VGA; 208532b578d3Smrg 208632b578d3Smrg if (ext_disp_en) 208732b578d3Smrg pATIHW->crtc = ATI_CRTC_MACH64; 208832b578d3Smrg 208932b578d3Smrg if ((pATIHW->crtc != ATI_CRTC_VGA) || vga_color_256) 209032b578d3Smrg pATIHW->nPlane = 1; 209132b578d3Smrg else 209232b578d3Smrg pATIHW->nPlane = 4; 209332b578d3Smrg 209432b578d3Smrg /* VideoRAM is a multiple of 512kB and BankSize is 64kB */ 209532b578d3Smrg pATIHW->nBank = pATI->VideoRAM / (pATIHW->nPlane * 0x40U); 209632b578d3Smrg 209732b578d3Smrg if ((pATIHW->crtc == ATI_CRTC_VGA) && !vga_ap_en) 209832b578d3Smrg { 209932b578d3Smrg pATIHW->SetBank = (ATIBankProcPtr)NoopDDA; 210032b578d3Smrg pATIHW->nBank = 1; 210132b578d3Smrg } 210232b578d3Smrg else if (pATIHW->nPlane == 1) 210332b578d3Smrg { 210432b578d3Smrg pATIHW->SetBank = ATIMach64SetBankPacked; 210532b578d3Smrg } 210632b578d3Smrg else 210732b578d3Smrg { 210832b578d3Smrg pATIHW->SetBank = ATIMach64SetBankPlanar; 210932b578d3Smrg } 211032b578d3Smrg } 211132b578d3Smrg 211232b578d3Smrg#else /* AVOID_CPIO */ 211332b578d3Smrg 211432b578d3Smrg { 211532b578d3Smrg pATIHW->crtc = pATI->NewHW.crtc; 211632b578d3Smrg } 211732b578d3Smrg 211832b578d3Smrg#endif /* AVOID_CPIO */ 211932b578d3Smrg 212032b578d3Smrg if (pATI->OptionShadowFB) 212132b578d3Smrg { 212232b578d3Smrg /* Until ShadowFB becomes a true screen wrapper, if it ever does... */ 212332b578d3Smrg 212432b578d3Smrg if (pATI->OptionAccel) 212532b578d3Smrg { 212632b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, 212732b578d3Smrg "Cannot shadow an accelerated frame buffer.\n"); 212832b578d3Smrg pATI->OptionShadowFB = FALSE; 212932b578d3Smrg } 213032b578d3Smrg else 213132b578d3Smrg { 213232b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, 213332b578d3Smrg "Using shadow frame buffer.\n"); 213432b578d3Smrg } 213532b578d3Smrg } 213632b578d3Smrg 213732b578d3Smrg /* 264VT-B's and later have DSP registers */ 213832b578d3Smrg if ((pATI->Chip >= ATI_CHIP_264VTB) && 213932b578d3Smrg !ATIDSPPreInit(pScreenInfo->scrnIndex, pATI)) 214032b578d3Smrg goto bail; 214132b578d3Smrg 214232b578d3Smrg /* 214332b578d3Smrg * Determine minClock and maxClock. For adapters with supported 214432b578d3Smrg * programmable clock generators, start with an absolute maximum. 214532b578d3Smrg */ 214632b578d3Smrg if (pATI->ClockDescriptor.MaxN > 0) 214732b578d3Smrg { 214832b578d3Smrg Numerator = pATI->ClockDescriptor.MaxN * pATI->ReferenceNumerator; 214932b578d3Smrg Denominator = pATI->ClockDescriptor.MinM * pATI->ReferenceDenominator * 215032b578d3Smrg pATI->ClockDescriptor.PostDividers[0]; 215132b578d3Smrg 215232b578d3Smrg /* 215332b578d3Smrg * An integrated PLL behaves as though the reference frequency were 215432b578d3Smrg * doubled. It also does not appear to care about the colour depth. 215532b578d3Smrg */ 215632b578d3Smrg if (pATI->ProgrammableClock == ATI_CLOCK_INTERNAL) 215732b578d3Smrg Numerator <<= 1; 215832b578d3Smrg 215932b578d3Smrg ATIClockRange.maxClock = (Numerator / (Denominator * 1000)) * 1000; 216032b578d3Smrg 216132b578d3Smrg Numerator = pATI->ClockDescriptor.MinN * pATI->ReferenceNumerator; 216232b578d3Smrg Denominator = pATI->ClockDescriptor.MaxM * pATI->ReferenceDenominator * 216332b578d3Smrg pATI->ClockDescriptor.PostDividers[pATI->ClockDescriptor.NumD - 1]; 216432b578d3Smrg 216532b578d3Smrg if (pATI->ProgrammableClock == ATI_CLOCK_INTERNAL) 216632b578d3Smrg Numerator <<= 1; 216732b578d3Smrg 216832b578d3Smrg ATIClockRange.minClock = (Numerator / (Denominator * 1000)) * 1000; 216932b578d3Smrg 217032b578d3Smrg if (pATI->XCLKFeedbackDivider) 217132b578d3Smrg { 217232b578d3Smrg /* Possibly reduce maxClock due to memory bandwidth */ 217332b578d3Smrg Numerator = pATI->XCLKFeedbackDivider * 2 * 217432b578d3Smrg pATI->ReferenceNumerator; 217532b578d3Smrg Denominator = pATI->ClockDescriptor.MinM * 217632b578d3Smrg pATI->XCLKReferenceDivider * pATI->ReferenceDenominator; 217732b578d3Smrg 217832b578d3Smrg { 217932b578d3Smrg Denominator *= pATI->bitsPerPixel / 4; 218032b578d3Smrg } 218132b578d3Smrg 218232b578d3Smrg i = (6 - 2) - pATI->XCLKPostDivider; 218332b578d3Smrg 218432b578d3Smrg i = (ATIDivide(Numerator, Denominator, i, -1) / 1000) * 1000; 218532b578d3Smrg if (i < ATIClockRange.maxClock) 218632b578d3Smrg ATIClockRange.maxClock = i; 218732b578d3Smrg } 218832b578d3Smrg } 218932b578d3Smrg 219032b578d3Smrg /* 219132b578d3Smrg * Assume an internal DAC can handle whatever frequency the internal PLL 219232b578d3Smrg * can produce (with the reference divider set by BIOS initialisation), but 219332b578d3Smrg * default maxClock to a lower chip-specific default. 219432b578d3Smrg */ 219532b578d3Smrg if ((pATI->DAC & ~0x0FU) == ATI_DAC_INTERNAL) 219632b578d3Smrg { 219732b578d3Smrg int DacSpeed; 219832b578d3Smrg switch (pATI->bitsPerPixel) 219932b578d3Smrg { 220032b578d3Smrg case 15: 220132b578d3Smrg case 16: 220232b578d3Smrg DacSpeed = pGDev->dacSpeeds[DAC_BPP16]; 220332b578d3Smrg break; 220432b578d3Smrg 220532b578d3Smrg case 24: 220632b578d3Smrg DacSpeed = pGDev->dacSpeeds[DAC_BPP24]; 220732b578d3Smrg break; 220832b578d3Smrg 220932b578d3Smrg case 32: 221032b578d3Smrg DacSpeed = pGDev->dacSpeeds[DAC_BPP32]; 221132b578d3Smrg break; 221232b578d3Smrg 221332b578d3Smrg default: 221432b578d3Smrg DacSpeed = 0; 221532b578d3Smrg break; 221632b578d3Smrg } 221732b578d3Smrg if (!DacSpeed) 221832b578d3Smrg DacSpeed = pGDev->dacSpeeds[DAC_BPP8]; 221932b578d3Smrg if (DacSpeed < ATIClockRange.maxClock) 222032b578d3Smrg { 222132b578d3Smrg DefaultmaxClock = 135000; 222232b578d3Smrg 222332b578d3Smrg if (pATI->depth > 8) 222432b578d3Smrg DefaultmaxClock = 80000; 222532b578d3Smrg 222632b578d3Smrg if ((pATI->Chip >= ATI_CHIP_264VTB) && 222732b578d3Smrg (pATI->Chip != ATI_CHIP_Mach64)) 222832b578d3Smrg { 222932b578d3Smrg if ((pATI->Chip >= ATI_CHIP_264VT4) && 223032b578d3Smrg (pATI->Chip != ATI_CHIP_264LTPRO)) 223132b578d3Smrg DefaultmaxClock = 230000; 223232b578d3Smrg else if (pATI->Chip >= ATI_CHIP_264VT3) 223332b578d3Smrg DefaultmaxClock = 200000; 223432b578d3Smrg else 223532b578d3Smrg DefaultmaxClock = 170000; 223632b578d3Smrg } 223732b578d3Smrg if (DacSpeed > DefaultmaxClock) 223832b578d3Smrg ATIClockRange.maxClock = DacSpeed; 223932b578d3Smrg else if (DefaultmaxClock < ATIClockRange.maxClock) 224032b578d3Smrg ATIClockRange.maxClock = DefaultmaxClock; 224132b578d3Smrg } 224232b578d3Smrg } 224332b578d3Smrg else 224432b578d3Smrg { 224532b578d3Smrg switch(pATI->DAC) 224632b578d3Smrg { 224732b578d3Smrg case ATI_DAC_STG1700: 224832b578d3Smrg case ATI_DAC_STG1702: 224932b578d3Smrg case ATI_DAC_STG1703: 225032b578d3Smrg DefaultmaxClock = 110000; 225132b578d3Smrg break; 225232b578d3Smrg 225332b578d3Smrg case ATI_DAC_IBMRGB514: 225432b578d3Smrg pATI->maxClock = 220000; 225532b578d3Smrg { 225632b578d3Smrg DefaultmaxClock = 220000; 225732b578d3Smrg } 225832b578d3Smrg break; 225932b578d3Smrg 226032b578d3Smrg default: 226132b578d3Smrg 226232b578d3Smrg#ifndef AVOID_CPIO 226332b578d3Smrg 226432b578d3Smrg if (pATI->CPIO_VGAWonder && (pATI->VideoRAM < 1024)) 226532b578d3Smrg { 226632b578d3Smrg DefaultmaxClock = 226732b578d3Smrg (GetBits(BIOSByte(0x44U), 0x04U) * 5000) + 40000; 226832b578d3Smrg } 226932b578d3Smrg else 227032b578d3Smrg 227132b578d3Smrg#endif /* AVOID_CPIO */ 227232b578d3Smrg 227332b578d3Smrg { 227432b578d3Smrg DefaultmaxClock = 80000; 227532b578d3Smrg } 227632b578d3Smrg 227732b578d3Smrg break; 227832b578d3Smrg } 227932b578d3Smrg 228032b578d3Smrg if (DefaultmaxClock < ATIClockRange.maxClock) 228132b578d3Smrg ATIClockRange.maxClock = DefaultmaxClock; 228232b578d3Smrg } 228332b578d3Smrg 228432b578d3Smrg /* 228532b578d3Smrg * Determine available pixel clock frequencies. 228632b578d3Smrg */ 228732b578d3Smrg 228832b578d3Smrg if ((pATI->ProgrammableClock <= ATI_CLOCK_FIXED) || 228932b578d3Smrg (pATI->ProgrammableClock >= ATI_CLOCK_MAX)) 229032b578d3Smrg { 229132b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 229232b578d3Smrg "Unsupported or non-programmable clock generator.\n"); 229332b578d3Smrg goto bail; 229432b578d3Smrg } 229532b578d3Smrg 229632b578d3Smrg ATIClockPreInit(pScreenInfo, pATI); 229732b578d3Smrg Strategy = LOOKUP_BEST_REFRESH; 229832b578d3Smrg 229932b578d3Smrg /* 230032b578d3Smrg * Mode validation. 230132b578d3Smrg */ 230232b578d3Smrg 230332b578d3Smrg if (pATI->Chip >= ATI_CHIP_264CT) 230432b578d3Smrg { 230532b578d3Smrg minPitch = 8; 230632b578d3Smrg } 230732b578d3Smrg else 230832b578d3Smrg { 230932b578d3Smrg minPitch = 16; 231032b578d3Smrg } 231132b578d3Smrg 231232b578d3Smrg pitchInc = minPitch * pATI->bitsPerPixel; 231332b578d3Smrg 231432b578d3Smrg pScreenInfo->maxHValue = (MaxBits(CRTC_H_TOTAL) + 1) << 3; 231532b578d3Smrg 231632b578d3Smrg if (pATI->Chip < ATI_CHIP_264VT) 231732b578d3Smrg { 231832b578d3Smrg /* 231932b578d3Smrg * ATI finally fixed accelerated doublescanning in the 264VT 232032b578d3Smrg * and later. On 88800's, the bit is documented to exist, but 232132b578d3Smrg * only doubles the vertical timings. On the 264CT and 264ET, 232232b578d3Smrg * the bit is ignored. 232332b578d3Smrg */ 232432b578d3Smrg ATIClockRange.doubleScanAllowed = FALSE; 232532b578d3Smrg 232632b578d3Smrg /* CRTC_H_TOTAL is one bit narrower */ 232732b578d3Smrg pScreenInfo->maxHValue >>= 1; 232832b578d3Smrg } 232932b578d3Smrg 233032b578d3Smrg pScreenInfo->maxVValue = MaxBits(CRTC_V_TOTAL) + 1; 233132b578d3Smrg 233232b578d3Smrg maxPitch = minPitch * MaxBits(CRTC_PITCH); 233332b578d3Smrg 233432b578d3Smrg if (pATI->OptionAccel) 233532b578d3Smrg { 233632b578d3Smrg /* 233732b578d3Smrg * Set engine restrictions on coordinate space. Use maxPitch for the 233832b578d3Smrg * horizontal and maxHeight for the vertical. 233932b578d3Smrg */ 234032b578d3Smrg if (maxPitch > (ATIMach64MaxX / pATI->XModifier)) 234132b578d3Smrg maxPitch = ATIMach64MaxX / pATI->XModifier; 234232b578d3Smrg 234332b578d3Smrg maxHeight = ATIMach64MaxY; 234432b578d3Smrg 234532b578d3Smrg /* 234632b578d3Smrg * For SGRAM & WRAM adapters, the display engine limits the pitch to 234732b578d3Smrg * multiples of 64 bytes. 234832b578d3Smrg */ 234932b578d3Smrg if ((pATI->Chip >= ATI_CHIP_264CT) && 235032b578d3Smrg ((pATI->Chip >= ATI_CHIP_264VTB) || 235132b578d3Smrg (pATI->MemoryType >= MEM_264_SGRAM))) 235232b578d3Smrg pitchInc = pATI->XModifier * (64 * 8); 235332b578d3Smrg } 235432b578d3Smrg 235532b578d3Smrg if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0)) 235632b578d3Smrg { 235732b578d3Smrg /* 235832b578d3Smrg * Given LCD modes are more tightly controlled than CRT modes, allow 235932b578d3Smrg * the user the option of not specifying a panel's horizontal sync 236032b578d3Smrg * and/or vertical refresh tolerances. 236132b578d3Smrg */ 236232b578d3Smrg Strategy |= LOOKUP_OPTIONAL_TOLERANCES; 236332b578d3Smrg 236432b578d3Smrg if (ModeType == M_T_BUILTIN) 236532b578d3Smrg { 236632b578d3Smrg /* 236732b578d3Smrg * Add a mode to the end of the monitor's list for the panel's 236832b578d3Smrg * native resolution. 236932b578d3Smrg */ 237032b578d3Smrg pMode = (DisplayModePtr)xnfcalloc(1, SizeOf(DisplayModeRec)); 237132b578d3Smrg pMode->name = "Native panel mode"; 237232b578d3Smrg pMode->type = M_T_BUILTIN; 237332b578d3Smrg pMode->Clock = pATI->LCDClock; 237432b578d3Smrg pMode->HDisplay = pATI->LCDHorizontal; 237532b578d3Smrg pMode->VDisplay = pATI->LCDVertical; 237632b578d3Smrg 237732b578d3Smrg /* 237832b578d3Smrg * These timings are bogus, but enough to survive sync tolerance 237932b578d3Smrg * checks. 238032b578d3Smrg */ 238132b578d3Smrg pMode->HSyncStart = pMode->HDisplay; 238232b578d3Smrg pMode->HSyncEnd = pMode->HSyncStart + minPitch; 238332b578d3Smrg pMode->HTotal = pMode->HSyncEnd + minPitch; 238432b578d3Smrg pMode->VSyncStart = pMode->VDisplay; 238532b578d3Smrg pMode->VSyncEnd = pMode->VSyncStart + 1; 238632b578d3Smrg pMode->VTotal = pMode->VSyncEnd + 1; 238732b578d3Smrg 238832b578d3Smrg pMode->CrtcHDisplay = pMode->HDisplay; 238932b578d3Smrg pMode->CrtcHBlankStart = pMode->HDisplay; 239032b578d3Smrg pMode->CrtcHSyncStart = pMode->HSyncStart; 239132b578d3Smrg pMode->CrtcHSyncEnd = pMode->HSyncEnd; 239232b578d3Smrg pMode->CrtcHBlankEnd = pMode->HTotal; 239332b578d3Smrg pMode->CrtcHTotal = pMode->HTotal; 239432b578d3Smrg 239532b578d3Smrg pMode->CrtcVDisplay = pMode->VDisplay; 239632b578d3Smrg pMode->CrtcVBlankStart = pMode->VDisplay; 239732b578d3Smrg pMode->CrtcVSyncStart = pMode->VSyncStart; 239832b578d3Smrg pMode->CrtcVSyncEnd = pMode->VSyncEnd; 239932b578d3Smrg pMode->CrtcVBlankEnd = pMode->VTotal; 240032b578d3Smrg pMode->CrtcVTotal = pMode->VTotal; 240132b578d3Smrg 240232b578d3Smrg if (!pScreenInfo->monitor->Modes) 240332b578d3Smrg { 240432b578d3Smrg pScreenInfo->monitor->Modes = pMode; 240532b578d3Smrg } 240632b578d3Smrg else 240732b578d3Smrg { 240832b578d3Smrg pScreenInfo->monitor->Last->next = pMode; 240932b578d3Smrg pMode->prev = pScreenInfo->monitor->Last; 241032b578d3Smrg } 241132b578d3Smrg 241232b578d3Smrg pScreenInfo->monitor->Last = pMode; 241332b578d3Smrg } 241432b578d3Smrg 241532b578d3Smrg /* 241632b578d3Smrg * Defeat Xconfigurator brain damage. Ignore all HorizSync and 241732b578d3Smrg * VertRefresh specifications. For now, this does not take 241832b578d3Smrg * SYNC_TOLERANCE into account. 241932b578d3Smrg */ 242032b578d3Smrg if (pScreenInfo->monitor->nHsync > 0) 242132b578d3Smrg { 242232b578d3Smrg double hsync = (double)pATI->LCDClock / 242332b578d3Smrg (pATI->LCDHorizontal + pATI->LCDHBlankWidth); 242432b578d3Smrg 242532b578d3Smrg for (i = 0; ; i++) 242632b578d3Smrg { 242732b578d3Smrg if (i >= pScreenInfo->monitor->nHsync) 242832b578d3Smrg { 242932b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE, 243032b578d3Smrg "Conflicting XF86Config HorizSync specification(s)" 243132b578d3Smrg " ignored.\n"); 243232b578d3Smrg break; 243332b578d3Smrg } 243432b578d3Smrg 243532b578d3Smrg if ((hsync >= pScreenInfo->monitor->hsync[i].lo) && 243632b578d3Smrg (hsync <= pScreenInfo->monitor->hsync[i].hi)) 243732b578d3Smrg { 243832b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, 243932b578d3Smrg "Extraneous XF86Config HorizSync specification(s)" 244032b578d3Smrg " ignored.\n"); 244132b578d3Smrg break; 244232b578d3Smrg } 244332b578d3Smrg } 244432b578d3Smrg 244532b578d3Smrg pScreenInfo->monitor->nHsync = 0; 244632b578d3Smrg } 244732b578d3Smrg 244832b578d3Smrg if (pScreenInfo->monitor->nVrefresh > 0) 244932b578d3Smrg { 245032b578d3Smrg double vrefresh = ((double)pATI->LCDClock * 1000.0) / 245132b578d3Smrg ((pATI->LCDHorizontal + pATI->LCDHBlankWidth) * 245232b578d3Smrg (pATI->LCDVertical + pATI->LCDVBlankWidth)); 245332b578d3Smrg 245432b578d3Smrg for (i = 0; ; i++) 245532b578d3Smrg { 245632b578d3Smrg if (i >= pScreenInfo->monitor->nVrefresh) 245732b578d3Smrg { 245832b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE, 245932b578d3Smrg "Conflicting XF86Config VertRefresh specification(s)" 246032b578d3Smrg " ignored.\n"); 246132b578d3Smrg break; 246232b578d3Smrg } 246332b578d3Smrg 246432b578d3Smrg if ((vrefresh >= pScreenInfo->monitor->vrefresh[i].lo) && 246532b578d3Smrg (vrefresh <= pScreenInfo->monitor->vrefresh[i].hi)) 246632b578d3Smrg { 246732b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, 246832b578d3Smrg "Extraneous XF86Config VertRefresh specification(s)" 246932b578d3Smrg " ignored.\n"); 247032b578d3Smrg break; 247132b578d3Smrg } 247232b578d3Smrg } 247332b578d3Smrg 247432b578d3Smrg pScreenInfo->monitor->nVrefresh = 0; 247532b578d3Smrg } 247632b578d3Smrg } 247732b578d3Smrg 247832b578d3Smrg i = xf86ValidateModes(pScreenInfo, 247932b578d3Smrg pScreenInfo->monitor->Modes, pScreenInfo->display->modes, 248032b578d3Smrg &ATIClockRange, NULL, minPitch, maxPitch, 248132b578d3Smrg pitchInc, 0, maxHeight, 248232b578d3Smrg pScreenInfo->display->virtualX, pScreenInfo->display->virtualY, 248332b578d3Smrg ApertureSize, Strategy); 248432b578d3Smrg if (i <= 0) 248532b578d3Smrg goto bail; 248632b578d3Smrg 248732b578d3Smrg /* Remove invalid modes */ 248832b578d3Smrg xf86PruneDriverModes(pScreenInfo); 248932b578d3Smrg 249032b578d3Smrg /* Set current mode to the first in the list */ 249132b578d3Smrg pScreenInfo->currentMode = pScreenInfo->modes; 249232b578d3Smrg 249332b578d3Smrg /* Print mode list */ 249432b578d3Smrg xf86PrintModes(pScreenInfo); 249532b578d3Smrg 249632b578d3Smrg /* Set display resolution */ 249732b578d3Smrg xf86SetDpi(pScreenInfo, 0, 0); 249832b578d3Smrg 249932b578d3Smrg /* Load required modules */ 250032b578d3Smrg if (!ATILoadModules(pScreenInfo, pATI)) 250132b578d3Smrg goto bail; 250232b578d3Smrg 250332b578d3Smrg pATI->displayWidth = pScreenInfo->displayWidth; 250432b578d3Smrg 250532b578d3Smrg /* Initialise for panning */ 250632b578d3Smrg ATIAdjustPreInit(pATI); 250732b578d3Smrg 250832b578d3Smrg /* 250932b578d3Smrg * Warn about modes that are too small, or not aligned, to scroll to the 251032b578d3Smrg * bottom right corner of the virtual screen. 251132b578d3Smrg */ 251232b578d3Smrg MinX = pScreenInfo->virtualX - pATI->AdjustMaxX; 251332b578d3Smrg MinY = pScreenInfo->virtualY - pATI->AdjustMaxY; 251432b578d3Smrg 251532b578d3Smrg pMode = pScreenInfo->modes; 251632b578d3Smrg do 251732b578d3Smrg { 251832b578d3Smrg if ((pMode->VDisplay <= MinY) && 251932b578d3Smrg ((pMode->VDisplay < MinY) || (pMode->HDisplay < MinX))) 252032b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, 252132b578d3Smrg "Mode \"%s\" too small to scroll to bottom right corner of" 252232b578d3Smrg " virtual resolution.\n", pMode->name); 252332b578d3Smrg else if ((pMode->HDisplay & ~pATI->AdjustMask) / pScreenInfo->xInc) 252432b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, 252532b578d3Smrg "Mode \"%s\" cannot scroll to bottom right corner of virtual" 252632b578d3Smrg " resolution.\n Horizontal dimension not a multiple of %ld.\n", 252732b578d3Smrg pMode->name, ~pATI->AdjustMask + 1); 252832b578d3Smrg } while ((pMode = pMode->next) != pScreenInfo->modes); 252932b578d3Smrg 253032b578d3Smrg /* Initialise XVideo extension support */ 253132b578d3Smrg ATIXVPreInit(pATI); 253232b578d3Smrg 253332b578d3Smrg /* Initialise CRTC code */ 253432b578d3Smrg ATIModePreInit(pScreenInfo, pATI, &pATI->NewHW); 253532b578d3Smrg 253632b578d3Smrg /* Set up for I2C */ 253732b578d3Smrg ATII2CPreInit(pScreenInfo, pATI); 253832b578d3Smrg 253932b578d3Smrg if (!pScreenInfo->chipset || !*pScreenInfo->chipset) 254032b578d3Smrg pScreenInfo->chipset = "mach64"; 254132b578d3Smrg 254232b578d3Smrg PreInitSuccess = TRUE; 254332b578d3Smrg 254432b578d3Smrgbail: 254532b578d3Smrg ATILock(pATI); 254632b578d3Smrg 254732b578d3Smrgbail_locked: 254832b578d3Smrg ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize); 254932b578d3Smrg ATIUnmapApertures(pScreenInfo->scrnIndex, pATI); 255032b578d3Smrg 255132b578d3Smrg return PreInitSuccess; 255232b578d3Smrg} 2553