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