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