1dfe64dd3Smacallan/* 2dfe64dd3Smacallan * Mode setup and basic video bridge detection 3dfe64dd3Smacallan * 4dfe64dd3Smacallan * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria. 5dfe64dd3Smacallan * 6dfe64dd3Smacallan * Redistribution and use in source and binary forms, with or without 7dfe64dd3Smacallan * modification, are permitted provided that the following conditions 8dfe64dd3Smacallan * are met: 9dfe64dd3Smacallan * 1) Redistributions of source code must retain the above copyright 10dfe64dd3Smacallan * notice, this list of conditions and the following disclaimer. 11dfe64dd3Smacallan * 2) Redistributions in binary form must reproduce the above copyright 12dfe64dd3Smacallan * notice, this list of conditions and the following disclaimer in the 13dfe64dd3Smacallan * documentation and/or other materials provided with the distribution. 14dfe64dd3Smacallan * 3) The name of the author may not be used to endorse or promote products 15dfe64dd3Smacallan * derived from this software without specific prior written permission. 16dfe64dd3Smacallan * 17dfe64dd3Smacallan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR 18dfe64dd3Smacallan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19dfe64dd3Smacallan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20dfe64dd3Smacallan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21dfe64dd3Smacallan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22dfe64dd3Smacallan * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23dfe64dd3Smacallan * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24dfe64dd3Smacallan * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25dfe64dd3Smacallan * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26dfe64dd3Smacallan * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27dfe64dd3Smacallan * 28dfe64dd3Smacallan * Author: Thomas Winischhofer <thomas@winischhofer.net> 29dfe64dd3Smacallan * 30dfe64dd3Smacallan * Init() function for old series (except for TV and FIFO calculation) 31dfe64dd3Smacallan * previously based on code which is Copyright (C) 1998,1999 by Alan 32dfe64dd3Smacallan * Hourihane, Wigan, England 33dfe64dd3Smacallan */ 34dfe64dd3Smacallan 35dfe64dd3Smacallan#ifdef HAVE_CONFIG_H 36dfe64dd3Smacallan#include "config.h" 37dfe64dd3Smacallan#endif 38dfe64dd3Smacallan 39dfe64dd3Smacallan#include "xf86.h" 40dfe64dd3Smacallan#include "xf86_OSproc.h" 41dfe64dd3Smacallan#include "xorgVersion.h" 42dfe64dd3Smacallan#include "xf86PciInfo.h" 43dfe64dd3Smacallan#include "xf86Pci.h" 44dfe64dd3Smacallan 45dfe64dd3Smacallan#include "xgi.h" 46dfe64dd3Smacallan#include "xgi_regs.h" 47dfe64dd3Smacallan#include "xgi_dac.h" 48dfe64dd3Smacallan 49dfe64dd3Smacallan#include "vb_def.h" 50dfe64dd3Smacallan 51dfe64dd3SmacallanBool XG40Init(ScrnInfoPtr pScrn, DisplayModePtr mode); 52dfe64dd3Smacallan 53dfe64dd3Smacallan/* Jong 01/07/2008; force to disable 2D */ 54dfe64dd3Smacallanextern Bool ForceToDisable2DEngine(ScrnInfoPtr pScrn); 55dfe64dd3Smacallan 56dfe64dd3Smacallan#define Midx 0 57dfe64dd3Smacallan#define Nidx 1 58dfe64dd3Smacallan#define VLDidx 2 59dfe64dd3Smacallan#define Pidx 3 60dfe64dd3Smacallan 61dfe64dd3SmacallanBool 62dfe64dd3SmacallanXG40Init(ScrnInfoPtr pScrn, DisplayModePtr mode) 63dfe64dd3Smacallan{ 64dfe64dd3Smacallan XGIPtr pXGI = XGIPTR(pScrn); 65dfe64dd3Smacallan XGIRegPtr pReg = &pXGI->ModeReg; 66dfe64dd3Smacallan vgaRegPtr vgaReg = &VGAHWPTR(pScrn)->ModeReg; 67dfe64dd3Smacallan int vgaIOBase; 68dfe64dd3Smacallan unsigned short temp; 69dfe64dd3Smacallan int offset; 70dfe64dd3Smacallan int clock = mode->Clock; 71dfe64dd3Smacallan unsigned int vclk[5]; 72dfe64dd3Smacallan 73dfe64dd3Smacallan int num, denum, div, sbit, scale; 74dfe64dd3Smacallan unsigned short Threshold_Low, Threshold_High; 75dfe64dd3Smacallan 76dfe64dd3SmacallanPDEBUG(ErrorF("XG40Init()\n")); 77dfe64dd3Smacallan 78dfe64dd3Smacallan xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, "XG40Init()\n"); 79dfe64dd3Smacallan xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, 80dfe64dd3Smacallan "virtualX = %d depth = %d Logical width = %d\n", 81dfe64dd3Smacallan pScrn->virtualX, pScrn->bitsPerPixel, 82dfe64dd3Smacallan pScrn->virtualX * pScrn->bitsPerPixel/8); 83dfe64dd3Smacallan 84dfe64dd3Smacallan vgaHWGetIOBase(VGAHWPTR(pScrn)); 85dfe64dd3Smacallan vgaIOBase = VGAHWPTR(pScrn)->IOBase; 86dfe64dd3Smacallan 87dfe64dd3Smacallan (*pXGI->XGISave)(pScrn, pReg); 88dfe64dd3Smacallan 89dfe64dd3Smacallan#if !defined(__arm__) 90dfe64dd3Smacallan outw(VGA_SEQ_INDEX, 0x8605); 91dfe64dd3Smacallan#else 92dfe64dd3Smacallan moutl(XGISR, 0x8605); 93dfe64dd3Smacallan#endif 94dfe64dd3Smacallan 95dfe64dd3Smacallan pReg->xgiRegs3C4[6] &= ~GENMASK(4:2); 96dfe64dd3Smacallan 97dfe64dd3Smacallan switch (pScrn->bitsPerPixel) { 98dfe64dd3Smacallan case 8: 99dfe64dd3Smacallan pXGI->DstColor = 0 ; 100dfe64dd3Smacallan pReg->xgiRegs3C4[6] |= 0x03; 101dfe64dd3Smacallan PDEBUG(ErrorF("8: pXGI->DstColor = %08lX\n",pXGI->DstColor)) ; 102dfe64dd3Smacallan break; 103dfe64dd3Smacallan case 16: 104dfe64dd3Smacallan pXGI->DstColor = 1 << 16 ; 105dfe64dd3Smacallan PDEBUG(ErrorF("16: pXGI->DstColor = %08lX\n",pXGI->DstColor)) ; 106dfe64dd3Smacallan if (pScrn->depth==15) { 107dfe64dd3Smacallan pReg->xgiRegs3C4[6] |= ((1 << 2) | 0x03); 108dfe64dd3Smacallan } else { 109dfe64dd3Smacallan pReg->xgiRegs3C4[6] |= ((2 << 2) | 0x03); 110dfe64dd3Smacallan } 111dfe64dd3Smacallan break; 112dfe64dd3Smacallan case 24: 113dfe64dd3Smacallan pReg->xgiRegs3C4[6] |= ((3 << 2) | 0x03); 114dfe64dd3Smacallan break; 115dfe64dd3Smacallan case 32: 116dfe64dd3Smacallan PDEBUG(ErrorF("32: pXGI->DstColor = %08lX\n",pXGI->DstColor)) ; 117dfe64dd3Smacallan pXGI->DstColor = 2 << 16 ; 118dfe64dd3Smacallan pReg->xgiRegs3C4[6] |= ((4 << 2) | 0x03); 119dfe64dd3Smacallan break; 120dfe64dd3Smacallan } 121dfe64dd3Smacallan 122dfe64dd3Smacallan pXGI->scrnOffset = pScrn->displayWidth * ((pScrn->bitsPerPixel+7)/8); 123dfe64dd3Smacallan pXGI->scrnOffset += 15 ; 124dfe64dd3Smacallan pXGI->scrnOffset >>= 4 ; 125dfe64dd3Smacallan pXGI->scrnOffset <<= 4 ; 126dfe64dd3Smacallan 127dfe64dd3Smacallan PDEBUG(ErrorF("XG40Init: pScrn->displayWidth = %ld\n",pScrn->displayWidth )) ; 128dfe64dd3Smacallan PDEBUG(ErrorF("XG40Init: pScrn->bitsPerPixel = %ld\n",pScrn->bitsPerPixel )) ; 129dfe64dd3Smacallan PDEBUG(ErrorF("XG40Init: pXGI->scrnOffset = %ld\n",pXGI->scrnOffset )) ; 130dfe64dd3Smacallan 131dfe64dd3Smacallan pReg->xgiRegs3D4[0x19] = 0; 132dfe64dd3Smacallan pReg->xgiRegs3D4[0x1A] &= 0xFC; 133dfe64dd3Smacallan 134dfe64dd3Smacallan if (mode->Flags & V_INTERLACE) { 135dfe64dd3Smacallan offset = pXGI->scrnOffset >> 2; 136dfe64dd3Smacallan pReg->xgiRegs3C4[0x06] |= 0x20; 137dfe64dd3Smacallan 138dfe64dd3Smacallan temp = (mode->CrtcHSyncStart >> 3) - 139dfe64dd3Smacallan (mode->CrtcHTotal >> 3)/2; 140dfe64dd3Smacallan pReg->xgiRegs3D4[0x19] = GETVAR8(temp); 141dfe64dd3Smacallan pReg->xgiRegs3D4[0x1A] |= GETBITS(temp, 9:8); 142dfe64dd3Smacallan } else { 143dfe64dd3Smacallan offset = pXGI->scrnOffset >> 3; 144dfe64dd3Smacallan pReg->xgiRegs3C4[0x06] &= ~0x20; 145dfe64dd3Smacallan } 146dfe64dd3Smacallan 147dfe64dd3Smacallan pReg->xgiRegs3C4[0x07] |= 0x10; /* enable High Speed DAC */ 148dfe64dd3Smacallan pReg->xgiRegs3C4[0x07] &= 0xFC; 149dfe64dd3Smacallan if (clock < 100000) 150dfe64dd3Smacallan pReg->xgiRegs3C4[0x07] |= 0x03; 151dfe64dd3Smacallan else if (clock < 200000) 152dfe64dd3Smacallan pReg->xgiRegs3C4[0x07] |= 0x02; 153dfe64dd3Smacallan else if (clock < 250000) 154dfe64dd3Smacallan pReg->xgiRegs3C4[0x07] |= 0x01; 155dfe64dd3Smacallan 156dfe64dd3Smacallan /* Extended Vertical Overflow */ 157dfe64dd3Smacallan pReg->xgiRegs3C4[0x0A] = 158dfe64dd3Smacallan GETBITSTR(mode->CrtcVTotal -2, 10:10, 0:0) | 159dfe64dd3Smacallan GETBITSTR(mode->CrtcVDisplay -1, 10:10, 1:1) | 160dfe64dd3Smacallan GETBITSTR(mode->CrtcVBlankStart , 10:10, 2:2) | 161dfe64dd3Smacallan GETBITSTR(mode->CrtcVSyncStart , 10:10, 3:3) | 162dfe64dd3Smacallan GETBITSTR(mode->CrtcVBlankEnd , 8:8, 4:4) | 163dfe64dd3Smacallan GETBITSTR(mode->CrtcVSyncEnd , 4:4, 5:5) ; 164dfe64dd3Smacallan 165dfe64dd3Smacallan /* Extended Horizontal Overflow */ 166dfe64dd3Smacallan pReg->xgiRegs3C4[0x0B] = 167dfe64dd3Smacallan GETBITSTR((mode->CrtcHTotal >> 3) - 5, 9:8, 1:0) | 168dfe64dd3Smacallan GETBITSTR((mode->CrtcHDisplay >> 3) - 1, 9:8, 3:2) | 169dfe64dd3Smacallan GETBITSTR((mode->CrtcHBlankStart >> 3) , 9:8, 5:4) | 170dfe64dd3Smacallan GETBITSTR((mode->CrtcHSyncStart >> 3) , 9:8, 7:6) ; 171dfe64dd3Smacallan 172dfe64dd3Smacallan pReg->xgiRegs3C4[0x0C] &= 0xF8; 173dfe64dd3Smacallan pReg->xgiRegs3C4[0x0C] |= 174dfe64dd3Smacallan GETBITSTR(mode->CrtcHBlankEnd >> 3, 7:6, 1:0) | 175dfe64dd3Smacallan GETBITSTR(mode->CrtcHSyncEnd >> 3, 5:5, 2:2) ; 176dfe64dd3Smacallan 177dfe64dd3Smacallan /* Screen Offset */ 178dfe64dd3Smacallan vgaReg->CRTC[0x13] = GETVAR8(offset); 179dfe64dd3Smacallan pReg->xgiRegs3C4[0x0E] &= 0xF0; 180dfe64dd3Smacallan pReg->xgiRegs3C4[0x0E] |= GETBITS(offset, 11:8); 181dfe64dd3Smacallan 182dfe64dd3Smacallan /* line compare */ 183dfe64dd3Smacallan if (mode->CrtcHDisplay > 0) 184dfe64dd3Smacallan pReg->xgiRegs3C4[0x0F] |= 0x08; 185dfe64dd3Smacallan else 186dfe64dd3Smacallan pReg->xgiRegs3C4[0x0F] &= 0xF7; 187dfe64dd3Smacallan 188dfe64dd3Smacallan pReg->xgiRegs3C4[0x10] = 189dfe64dd3Smacallan ((mode->CrtcHDisplay *((pScrn->bitsPerPixel+7)/8) + 63) >> 6)+1; 190dfe64dd3Smacallan 191dfe64dd3Smacallan /* Enable Linear */ 192dfe64dd3Smacallan pReg->xgiRegs3C4[0x20] |= 0x81; 193dfe64dd3Smacallan 194dfe64dd3Smacallan 195dfe64dd3Smacallan /* Set vclk */ 196dfe64dd3Smacallan if (compute_vclk(clock, &num, &denum, &div, &sbit, &scale)) { 197dfe64dd3Smacallan pReg->xgiRegs3C4[0x2B] = (num -1) & 0x7f; 198dfe64dd3Smacallan if (div == 2) 199dfe64dd3Smacallan pReg->xgiRegs3C4[0x2B] |= 0x80; 200dfe64dd3Smacallan pReg->xgiRegs3C4[0x2C] = ((denum -1) & 0x1f); 201dfe64dd3Smacallan pReg->xgiRegs3C4[0x2C] |= (((scale-1)&3) << 5); 202dfe64dd3Smacallan if (sbit) 203dfe64dd3Smacallan pReg->xgiRegs3C4[0x2C] |= 0x80; 204dfe64dd3Smacallan pReg->xgiRegs3C4[0x2D] = 0x80; 205dfe64dd3Smacallan } 206dfe64dd3Smacallan else { 207dfe64dd3Smacallan /* if compute_vclk cannot handle the request clock try XGICalcClock! */ 208dfe64dd3Smacallan XGICalcClock(pScrn, clock, 2, vclk); 209dfe64dd3Smacallan pReg->xgiRegs3C4[0x2B] = (vclk[Midx] - 1) & 0x7f ; 210dfe64dd3Smacallan pReg->xgiRegs3C4[0x2B] |= ((vclk[VLDidx] == 2 ) ? 1 : 0 ) << 7 ; 211dfe64dd3Smacallan 212dfe64dd3Smacallan /* bits [4:0] contain denumerator -MC */ 213dfe64dd3Smacallan pReg->xgiRegs3C4[0x2C] = (vclk[Nidx] -1) & 0x1f ; 214dfe64dd3Smacallan 215dfe64dd3Smacallan if (vclk[Pidx] <= 4) { 216dfe64dd3Smacallan /* postscale 1,2,3,4 */ 217dfe64dd3Smacallan pReg->xgiRegs3C4[0x2C] |= (vclk[Pidx] -1 ) << 5 ; 218dfe64dd3Smacallan pReg->xgiRegs3C4[0x2C] &= 0x7F; 219dfe64dd3Smacallan } else { 220dfe64dd3Smacallan /* postscale 6,8 */ 221dfe64dd3Smacallan pReg->xgiRegs3C4[0x2C] |= ((vclk[Pidx] / 2) -1 ) << 5 ; 222dfe64dd3Smacallan pReg->xgiRegs3C4[0x2C] |= 0x80; 223dfe64dd3Smacallan } 224dfe64dd3Smacallan pReg->xgiRegs3C4[0x2D] = 0x80; 225dfe64dd3Smacallan } /* end of set vclk */ 226dfe64dd3Smacallan 227dfe64dd3Smacallan if ( (pXGI->Chipset == PCI_CHIP_XGIXG40) && (clock > 150000) ) { /* enable two-pixel mode */ 228dfe64dd3Smacallan pReg->xgiRegs3C4[0x07] |= 0x80; 229dfe64dd3Smacallan pReg->xgiRegs3C4[0x32] |= 0x08; 230dfe64dd3Smacallan } else { 231dfe64dd3Smacallan pReg->xgiRegs3C4[0x07] &= 0x7F; 232dfe64dd3Smacallan pReg->xgiRegs3C4[0x32] &= 0xF7; 233dfe64dd3Smacallan } 234dfe64dd3Smacallan 235dfe64dd3Smacallan /*pReg->xgiRegs3C2 = inb(0x3CC) | 0x0C;*/ /* Programmable Clock */ 236dfe64dd3Smacallan pReg->xgiRegs3C2 = inb(pXGI->RelIO+0x4c) | 0x0C; /*Programmable Clock*/ 237dfe64dd3Smacallan 238dfe64dd3Smacallan if (!pXGI->NoAccel) { 239dfe64dd3Smacallan /* Enable 2D accelerator. 240dfe64dd3Smacallan */ 241dfe64dd3Smacallan /* Jong 01/07/2008; disable 2D engine depend on SR3A[6]:1-> force to siable 2D */ 242dfe64dd3Smacallan if(pXGI->Chipset != PCI_CHIP_XGIXG21) 243dfe64dd3Smacallan pReg->xgiRegs3C4[0x1E] |= 0x42; 244dfe64dd3Smacallan else 245dfe64dd3Smacallan { 246dfe64dd3Smacallan if(ForceToDisable2DEngine(pScrn)) 247dfe64dd3Smacallan pReg->xgiRegs3C4[0x1E] |= 0x02; 248dfe64dd3Smacallan } 249dfe64dd3Smacallan 250dfe64dd3Smacallan } 251dfe64dd3Smacallan 252dfe64dd3Smacallan /* set threshold value */ 253dfe64dd3Smacallan (*pXGI->SetThreshold)(pScrn, mode, &Threshold_Low, &Threshold_High); 254dfe64dd3Smacallan pReg->xgiRegs3C4[0x08] = GETBITSTR(Threshold_Low, 3:0, 7:4) | 0xF; 255dfe64dd3Smacallan pReg->xgiRegs3C4[0x0F] &= ~GENMASK(5:5); 256dfe64dd3Smacallan pReg->xgiRegs3C4[0x0F] |= GETBITSTR(Threshold_Low, 4:4, 5:5); 257dfe64dd3Smacallan pReg->xgiRegs3C4[0x09] &= ~GENMASK(3:0); 258dfe64dd3Smacallan pReg->xgiRegs3C4[0x09] |= GETBITS(Threshold_High, 3:0); 259dfe64dd3Smacallan 260dfe64dd3Smacallan return(TRUE); 261dfe64dd3Smacallan} 262dfe64dd3Smacallan 263dfe64dd3Smacallan/* Detect video bridge and set VBFlags accordingly */ 264dfe64dd3Smacallanvoid XGIVGAPreInit(ScrnInfoPtr pScrn) 265dfe64dd3Smacallan{ 266dfe64dd3Smacallan XGIPtr pXGI = XGIPTR(pScrn); 267dfe64dd3Smacallan 268dfe64dd3Smacallan switch (pXGI->Chipset) { 269dfe64dd3Smacallan case PCI_CHIP_XGIXG40: 270dfe64dd3Smacallan case PCI_CHIP_XGIXG20: 271dfe64dd3Smacallan case PCI_CHIP_XGIXG21: 272dfe64dd3Smacallan case PCI_CHIP_XGIXG27: 273dfe64dd3Smacallan default: 274dfe64dd3Smacallan pXGI->ModeInit = XG40Init; 275dfe64dd3Smacallan break; 276dfe64dd3Smacallan } 277dfe64dd3Smacallan 278dfe64dd3Smacallan 279dfe64dd3Smacallan} 280dfe64dd3Smacallan 281