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