pm2v_dac.c revision c35d236e
1c35d236eSmrg/*
2c35d236eSmrg * Copyright 1997-2001 by Alan Hourihane <alanh@fairlite.demon.co.uk>
3c35d236eSmrg *
4c35d236eSmrg * Permission to use, copy, modify, distribute, and sell this software and its
5c35d236eSmrg * documentation for any purpose is hereby granted without fee, provided that
6c35d236eSmrg * the above copyright notice appear in all copies and that both that
7c35d236eSmrg * copyright notice and this permission notice appear in supporting
8c35d236eSmrg * documentation, and that the name of Alan Hourihane not be used in
9c35d236eSmrg * advertising or publicity pertaining to distribution of the software without
10c35d236eSmrg * specific, written prior permission.  Alan Hourihane makes no representations
11c35d236eSmrg * about the suitability of this software for any purpose.  It is provided
12c35d236eSmrg * "as is" without express or implied warranty.
13c35d236eSmrg *
14c35d236eSmrg * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15c35d236eSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16c35d236eSmrg * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17c35d236eSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18c35d236eSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19c35d236eSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20c35d236eSmrg * PERFORMANCE OF THIS SOFTWARE.
21c35d236eSmrg *
22c35d236eSmrg * Authors:  Alan Hourihane, <alanh@fairlite.demon.co.uk>
23c35d236eSmrg *           Dirk Hohndel,   <hohndel@suse.de>
24c35d236eSmrg *	     Stefan Dirsch,  <sndirsch@suse.de>
25c35d236eSmrg *	     Helmut Fahrion, <hf@suse.de>
26c35d236eSmrg *
27c35d236eSmrg * this work is sponsored by S.u.S.E. GmbH, Fuerth, Elsa GmbH, Aachen and
28c35d236eSmrg * Siemens Nixdorf Informationssysteme
29c35d236eSmrg */
30c35d236eSmrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/glint/pm2v_dac.c,v 1.29tsi Exp $ */
31c35d236eSmrg
32c35d236eSmrg#ifdef HAVE_CONFIG_H
33c35d236eSmrg#include "config.h"
34c35d236eSmrg#endif
35c35d236eSmrg
36c35d236eSmrg#include "xf86.h"
37c35d236eSmrg#include "xf86_OSproc.h"
38c35d236eSmrg
39c35d236eSmrg#include "xf86PciInfo.h"
40c35d236eSmrg#include "xf86Pci.h"
41c35d236eSmrg
42c35d236eSmrg#include "glint_regs.h"
43c35d236eSmrg#include "glint.h"
44c35d236eSmrg
45c35d236eSmrgstatic unsigned long
46c35d236eSmrgPM2VDAC_CalculateClock
47c35d236eSmrg(
48c35d236eSmrg unsigned long reqclock,		/* In kHz units */
49c35d236eSmrg unsigned long refclock,		/* In kHz units */
50c35d236eSmrg unsigned char *prescale,		/* ClkPreScale */
51c35d236eSmrg unsigned char *feedback, 		/* ClkFeedBackScale */
52c35d236eSmrg unsigned char *postscale		/* ClkPostScale */
53c35d236eSmrg )
54c35d236eSmrg{
55c35d236eSmrg    int			f, pre, post;
56c35d236eSmrg    unsigned long	freq;
57c35d236eSmrg    long		freqerr = 1000;
58c35d236eSmrg    unsigned long  	actualclock = 0;
59c35d236eSmrg    unsigned char	divide[5] = { 1, 2, 4, 8, 16 };
60c35d236eSmrg
61c35d236eSmrg    for (f=1;f<256;f++) {
62c35d236eSmrg	for (pre=1;pre<256;pre++) {
63c35d236eSmrg	    for (post=0;post<2;post++) {
64c35d236eSmrg	    	freq = ((refclock * f) / (pre * (1 << divide[post])));
65c35d236eSmrg		if ((reqclock > freq - freqerr)&&(reqclock < freq + freqerr)){
66c35d236eSmrg		    freqerr = (reqclock > freq) ?
67c35d236eSmrg					reqclock - freq : freq - reqclock;
68c35d236eSmrg		    *feedback = f;
69c35d236eSmrg		    *prescale = pre;
70c35d236eSmrg		    *postscale = post;
71c35d236eSmrg		    actualclock = freq;
72c35d236eSmrg		}
73c35d236eSmrg	    }
74c35d236eSmrg	}
75c35d236eSmrg    }
76c35d236eSmrg
77c35d236eSmrg    return(actualclock);
78c35d236eSmrg}
79c35d236eSmrg
80c35d236eSmrgstatic void
81c35d236eSmrgPermedia2VPreInitSecondary(ScrnInfoPtr pScrn)
82c35d236eSmrg{
83c35d236eSmrg    GLINTPtr pGlint = GLINTPTR(pScrn);
84c35d236eSmrg
85c35d236eSmrg    /* disable MCLK */
86c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDMClkControl, 0x00, 0);
87c35d236eSmrg
88c35d236eSmrg    /* boot new mclk values */
89c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDMClkPreScale, 0x00, 0x09);
90c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDMClkFeedbackScale, 0x00, 0x58);
91c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDMClkPostScale, 0x00, 0x01);
92c35d236eSmrg
93c35d236eSmrg    /* re-enable MCLK */
94c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDMClkControl, 0x00, 1);
95c35d236eSmrg
96c35d236eSmrg    /* spin until locked MCLK */
97c35d236eSmrg    while ( (Permedia2vInIndReg(pScrn, PM2VDACRDMClkControl) & 0x2) == 0);
98c35d236eSmrg
99c35d236eSmrg    /* Now re-boot the SGRAM's */
100c35d236eSmrg    GLINT_SLOW_WRITE_REG(0xe6002021,PMMemConfig);
101c35d236eSmrg    GLINT_SLOW_WRITE_REG(0x00000020,PMBootAddress);
102c35d236eSmrg}
103c35d236eSmrg
104c35d236eSmrgvoid
105c35d236eSmrgPermedia2VPreInit(ScrnInfoPtr pScrn)
106c35d236eSmrg{
107c35d236eSmrg    GLINTPtr pGlint = GLINTPTR(pScrn);
108c35d236eSmrg
109c35d236eSmrg    if (IS_JPRO) {
110c35d236eSmrg	/* Appian Jeronimo Pro 4x8mb (pm2v version) */
111c35d236eSmrg	/* BIOS doesn't initialize the secondary heads, so we need to */
112c35d236eSmrg
113c35d236eSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
114c35d236eSmrg	    "Appian Jeronimo Pro 4x8mb board detected and initialized.\n");
115c35d236eSmrg
116c35d236eSmrg	Permedia2VPreInitSecondary(pScrn);
117c35d236eSmrg    }
118c35d236eSmrg
119c35d236eSmrg#if defined(__alpha__)
120c35d236eSmrg    /*
121c35d236eSmrg     * On Alpha, we have to init secondary PM2V cards, since
122c35d236eSmrg     * int10 cannot be run on the OEMed cards with VGA disable
123c35d236eSmrg     * jumpers.
124c35d236eSmrg     */
125c35d236eSmrg    if (!xf86IsPrimaryPci(pGlint->PciInfo)) {
126c35d236eSmrg	if ( IS_QPM2V ) {
127c35d236eSmrg
128c35d236eSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
129c35d236eSmrg		       "PM2V secondary: initializing\n");
130c35d236eSmrg	    Permedia2VPreInitSecondary(pScrn);
131c35d236eSmrg	}
132c35d236eSmrg    }
133c35d236eSmrg#endif /* __alpha__ */
134c35d236eSmrg}
135c35d236eSmrg
136c35d236eSmrgBool
137c35d236eSmrgPermedia2VInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
138c35d236eSmrg{
139c35d236eSmrg    GLINTPtr pGlint = GLINTPTR(pScrn);
140c35d236eSmrg    GLINTRegPtr pReg = &pGlint->ModeReg[0];
141c35d236eSmrg    CARD32 temp1, temp2, temp3, temp4;
142c35d236eSmrg
143c35d236eSmrg    temp1 = 0;
144c35d236eSmrg    temp2 = 0;
145c35d236eSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN
146c35d236eSmrg    switch (pGlint->HwBpp) {
147c35d236eSmrg    case 8:
148c35d236eSmrg    case 24:
149c35d236eSmrg	    temp1 = 0x00;
150c35d236eSmrg	    temp2 = 0x00;
151c35d236eSmrg	    break;
152c35d236eSmrg
153c35d236eSmrg    case 15:
154c35d236eSmrg    case 16:
155c35d236eSmrg	    temp1 = 0x02;
156c35d236eSmrg	    temp2 = 0x02;
157c35d236eSmrg	    break;
158c35d236eSmrg
159c35d236eSmrg    case 32:
160c35d236eSmrg	    temp1 = 0x01;
161c35d236eSmrg	    temp2 = 0x01;
162c35d236eSmrg	    break;
163c35d236eSmrg    default:
164c35d236eSmrg	    break;
165c35d236eSmrg    };
166c35d236eSmrg#endif /* BIG_ENDIAN */
167c35d236eSmrg
168c35d236eSmrg    pReg->glintRegs[Aperture0 >> 3] = temp1;
169c35d236eSmrg    pReg->glintRegs[Aperture1 >> 3] = temp2;
170c35d236eSmrg
171c35d236eSmrg    pReg->glintRegs[PMFramebufferWriteMask >> 3] = 0xFFFFFFFF;
172c35d236eSmrg    pReg->glintRegs[PMBypassWriteMask >> 3] = 0xFFFFFFFF;
173c35d236eSmrg
174c35d236eSmrg    pReg->glintRegs[DFIFODis >> 3] = 0;
175c35d236eSmrg    pReg->glintRegs[FIFODis >> 3] = 1;
176c35d236eSmrg
177c35d236eSmrg    if (pGlint->UseBlockWrite)
178c35d236eSmrg	pReg->glintRegs[PMMemConfig >> 3] = GLINT_READ_REG(PMMemConfig) | 1<<21;
179c35d236eSmrg
180c35d236eSmrg    temp1 = mode->CrtcHSyncStart - mode->CrtcHDisplay;
181c35d236eSmrg    temp2 = mode->CrtcVSyncStart - mode->CrtcVDisplay;
182c35d236eSmrg    temp3 = mode->CrtcHSyncEnd - mode->CrtcHSyncStart;
183c35d236eSmrg    temp4 = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
184c35d236eSmrg
185c35d236eSmrg    pReg->glintRegs[PMHTotal >> 3] = Shiftbpp(pScrn,mode->CrtcHTotal);
186c35d236eSmrg    pReg->glintRegs[PMHsEnd >> 3] = Shiftbpp(pScrn, temp1 + temp3);
187c35d236eSmrg    pReg->glintRegs[PMHsStart >> 3] = Shiftbpp(pScrn, temp1);
188c35d236eSmrg    pReg->glintRegs[PMHbEnd >> 3] =
189c35d236eSmrg			Shiftbpp(pScrn,mode->CrtcHTotal-mode->CrtcHDisplay);
190c35d236eSmrg    pReg->glintRegs[PMScreenStride >> 3] =
191c35d236eSmrg					Shiftbpp(pScrn,pScrn->displayWidth>>1);
192c35d236eSmrg
193c35d236eSmrg    pReg->glintRegs[PMVTotal >> 3] = mode->CrtcVTotal;
194c35d236eSmrg    pReg->glintRegs[PMVsEnd >> 3] = temp2 + temp4;
195c35d236eSmrg    pReg->glintRegs[PMVsStart >> 3] = temp2;
196c35d236eSmrg    pReg->glintRegs[PMVbEnd >> 3] = mode->CrtcVTotal - mode->CrtcVDisplay;
197c35d236eSmrg
198c35d236eSmrg    /* The hw cursor needs /VSYNC to recognize vert retrace. We'll stick
199c35d236eSmrg       both sync lines to active low here and if needed invert them
200c35d236eSmrg       using the RAMDAC's RDSyncControl below. */
201c35d236eSmrg    pReg->glintRegs[PMVideoControl >> 3] =
202c35d236eSmrg	(1 << 5) | (1 << 3) | 1;
203c35d236eSmrg
204c35d236eSmrg    /* We stick the RAMDAC into 64bit mode */
205c35d236eSmrg    /* And reduce the horizontal timings and clock by half */
206c35d236eSmrg    pReg->glintRegs[PMVideoControl >> 3] |= 1<<16;
207c35d236eSmrg    pReg->glintRegs[PMHTotal >> 3] >>= 1;
208c35d236eSmrg    pReg->glintRegs[PMHsEnd >> 3] >>= 1;
209c35d236eSmrg    pReg->glintRegs[PMHsStart >> 3] >>= 1;
210c35d236eSmrg    pReg->glintRegs[PMHbEnd >> 3] >>= 1;
211c35d236eSmrg
212c35d236eSmrg    pReg->glintRegs[VClkCtl >> 3] = (GLINT_READ_REG(VClkCtl) & 0xFFFFFFFC);
213c35d236eSmrg    pReg->glintRegs[PMScreenBase >> 3] = 0;
214c35d236eSmrg    pReg->glintRegs[PMHTotal >> 3] -= 1;
215c35d236eSmrg    pReg->glintRegs[PMHsStart >> 3] -= 1; /* PMHsStart */
216c35d236eSmrg    pReg->glintRegs[PMVTotal >> 3] -= 1; /* PMVTotal */
217c35d236eSmrg
218c35d236eSmrg    pReg->glintRegs[ChipConfig >> 3] = GLINT_READ_REG(ChipConfig) & 0xFFFFFFDD;
219c35d236eSmrg    pReg->DacRegs[PM2VDACRDDACControl] = 0x00;
220c35d236eSmrg
221c35d236eSmrg    {
222c35d236eSmrg	/* Get the programmable clock values */
223c35d236eSmrg    	unsigned char m,n,p;
224c35d236eSmrg
225c35d236eSmrg	(void) PM2VDAC_CalculateClock(mode->Clock/2,pGlint->RefClock,
226c35d236eSmrg								&m,&n,&p);
227c35d236eSmrg	pReg->DacRegs[PM2VDACRDDClk0PreScale] = m;
228c35d236eSmrg	pReg->DacRegs[PM2VDACRDDClk0FeedbackScale] = n;
229c35d236eSmrg	pReg->DacRegs[PM2VDACRDDClk0PostScale] = p;
230c35d236eSmrg    }
231c35d236eSmrg
232c35d236eSmrg    pReg->glintRegs[PM2VDACRDIndexControl >> 3] = 0x00;
233c35d236eSmrg
234c35d236eSmrg    if (pScrn->rgbBits == 8)
235c35d236eSmrg        pReg->DacRegs[PM2VDACRDMiscControl] = 0x01; /* 8bit DAC */
236c35d236eSmrg    else
237c35d236eSmrg	pReg->DacRegs[PM2VDACRDMiscControl] = 0x00; /* 6bit DAC */
238c35d236eSmrg
239c35d236eSmrg    pReg->DacRegs[PM2VDACRDSyncControl] = 0x00;
240c35d236eSmrg    if (mode->Flags & V_PHSYNC)
241c35d236eSmrg        pReg->DacRegs[PM2VDACRDSyncControl] |= 0x01; /* invert hsync */
242c35d236eSmrg    if (mode->Flags & V_PVSYNC)
243c35d236eSmrg        pReg->DacRegs[PM2VDACRDSyncControl] |= 0x08; /* invert vsync */
244c35d236eSmrg
245c35d236eSmrg    switch (pScrn->bitsPerPixel)
246c35d236eSmrg    {
247c35d236eSmrg    case 8:
248c35d236eSmrg	pReg->DacRegs[PM2VDACRDPixelSize] = 0x00;
249c35d236eSmrg	pReg->DacRegs[PM2VDACRDColorFormat] = 0x2E;
250c35d236eSmrg    	break;
251c35d236eSmrg    case 16:
252c35d236eSmrg        pReg->DacRegs[PM2VDACRDMiscControl] |= 0x08;
253c35d236eSmrg	pReg->DacRegs[PM2VDACRDPixelSize] = 0x01;
254c35d236eSmrg	if (pScrn->depth == 15)
255c35d236eSmrg	    pReg->DacRegs[PM2VDACRDColorFormat] = 0x61;
256c35d236eSmrg	else
257c35d236eSmrg	    pReg->DacRegs[PM2VDACRDColorFormat] = 0x70;
258c35d236eSmrg    	break;
259c35d236eSmrg    case 24:
260c35d236eSmrg        pReg->DacRegs[PM2VDACRDMiscControl] |= 0x08;
261c35d236eSmrg	pReg->DacRegs[PM2VDACRDPixelSize] = 0x04;
262c35d236eSmrg	pReg->DacRegs[PM2VDACRDColorFormat] = 0x60;
263c35d236eSmrg    	break;
264c35d236eSmrg    case 32:
265c35d236eSmrg        pReg->DacRegs[PM2VDACRDMiscControl] |= 0x08;
266c35d236eSmrg	pReg->DacRegs[PM2VDACRDPixelSize] = 0x02;
267c35d236eSmrg	pReg->DacRegs[PM2VDACRDColorFormat] = 0x20;
268c35d236eSmrg	if (pScrn->overlayFlags & OVERLAY_8_32_PLANAR) {
269c35d236eSmrg	    pReg->DacRegs[PM2VDACRDMiscControl] |= 0x18;
270c35d236eSmrg	    pReg->DacRegs[PM2VDACRDOverlayKey] = pScrn->colorKey;
271c35d236eSmrg	}
272c35d236eSmrg    	break;
273c35d236eSmrg    }
274c35d236eSmrg
275c35d236eSmrg    return(TRUE);
276c35d236eSmrg}
277c35d236eSmrg
278c35d236eSmrgvoid
279c35d236eSmrgPermedia2VSave(ScrnInfoPtr pScrn, GLINTRegPtr glintReg)
280c35d236eSmrg{
281c35d236eSmrg    GLINTPtr pGlint = GLINTPTR(pScrn);
282c35d236eSmrg    int i;
283c35d236eSmrg
284c35d236eSmrg    /* We can't rely on the vgahw layer copying the font information
285c35d236eSmrg     * back properly, due to problems with MMIO access to VGA space
286c35d236eSmrg     * so we memcpy the information */
287c35d236eSmrg    memcpy((CARD8*)pGlint->VGAdata,(CARD8*)pGlint->FbBase, 65536);
288c35d236eSmrg
289c35d236eSmrg    glintReg->glintRegs[ChipConfig >> 3] = GLINT_READ_REG(ChipConfig);
290c35d236eSmrg    glintReg->glintRegs[Aperture0 >> 3]  = GLINT_READ_REG(Aperture0);
291c35d236eSmrg    glintReg->glintRegs[Aperture1 >> 3]  = GLINT_READ_REG(Aperture1);
292c35d236eSmrg    glintReg->glintRegs[PMFramebufferWriteMask >> 3] =
293c35d236eSmrg					GLINT_READ_REG(PMFramebufferWriteMask);
294c35d236eSmrg    glintReg->glintRegs[PMBypassWriteMask >> 3] =
295c35d236eSmrg					GLINT_READ_REG(PMBypassWriteMask);
296c35d236eSmrg    glintReg->glintRegs[DFIFODis >> 3]  = GLINT_READ_REG(DFIFODis);
297c35d236eSmrg    glintReg->glintRegs[FIFODis >> 3]  = GLINT_READ_REG(FIFODis);
298c35d236eSmrg    /* We only muck about with PMMemConfig, if user wants to */
299c35d236eSmrg    if (pGlint->UseBlockWrite)
300c35d236eSmrg	glintReg->glintRegs[PMMemConfig >> 3] = GLINT_READ_REG(PMMemConfig);
301c35d236eSmrg    glintReg->glintRegs[PMHTotal >> 3] = GLINT_READ_REG(PMHTotal);
302c35d236eSmrg    glintReg->glintRegs[PMHbEnd >> 3] = GLINT_READ_REG(PMHbEnd);
303c35d236eSmrg    glintReg->glintRegs[PMHbEnd >> 3] = GLINT_READ_REG(PMHgEnd);
304c35d236eSmrg    glintReg->glintRegs[PMScreenStride >> 3] = GLINT_READ_REG(PMScreenStride);
305c35d236eSmrg    glintReg->glintRegs[PMHsStart >> 3] = GLINT_READ_REG(PMHsStart);
306c35d236eSmrg    glintReg->glintRegs[PMHsEnd >> 3] = GLINT_READ_REG(PMHsEnd);
307c35d236eSmrg    glintReg->glintRegs[PMVTotal >> 3] = GLINT_READ_REG(PMVTotal);
308c35d236eSmrg    glintReg->glintRegs[PMVbEnd >> 3] = GLINT_READ_REG(PMVbEnd);
309c35d236eSmrg    glintReg->glintRegs[PMVsStart >> 3] = GLINT_READ_REG(PMVsStart);
310c35d236eSmrg    glintReg->glintRegs[PMVsEnd >> 3] = GLINT_READ_REG(PMVsEnd);
311c35d236eSmrg    glintReg->glintRegs[PMScreenBase >> 3] = GLINT_READ_REG(PMScreenBase);
312c35d236eSmrg    glintReg->glintRegs[PMVideoControl >> 3] = GLINT_READ_REG(PMVideoControl);
313c35d236eSmrg    glintReg->glintRegs[VClkCtl >> 3] = GLINT_READ_REG(VClkCtl);
314c35d236eSmrg
315c35d236eSmrg    for (i=0;i<768;i++) {
316c35d236eSmrg    	Permedia2ReadAddress(pScrn, i);
317c35d236eSmrg	glintReg->cmap[i] = Permedia2ReadData(pScrn);
318c35d236eSmrg    }
319c35d236eSmrg
320c35d236eSmrg    glintReg->glintRegs[PM2VDACRDIndexControl >> 3] =
321c35d236eSmrg				GLINT_READ_REG(PM2VDACRDIndexControl);
322c35d236eSmrg    glintReg->DacRegs[PM2VDACRDOverlayKey] =
323c35d236eSmrg				Permedia2vInIndReg(pScrn, PM2VDACRDOverlayKey);
324c35d236eSmrg    glintReg->DacRegs[PM2VDACRDSyncControl] =
325c35d236eSmrg				Permedia2vInIndReg(pScrn, PM2VDACRDSyncControl);
326c35d236eSmrg    glintReg->DacRegs[PM2VDACRDMiscControl] =
327c35d236eSmrg				Permedia2vInIndReg(pScrn, PM2VDACRDMiscControl);
328c35d236eSmrg    glintReg->DacRegs[PM2VDACRDDACControl] =
329c35d236eSmrg				Permedia2vInIndReg(pScrn, PM2VDACRDDACControl);
330c35d236eSmrg    glintReg->DacRegs[PM2VDACRDPixelSize] =
331c35d236eSmrg				Permedia2vInIndReg(pScrn, PM2VDACRDPixelSize);
332c35d236eSmrg    glintReg->DacRegs[PM2VDACRDColorFormat] =
333c35d236eSmrg				Permedia2vInIndReg(pScrn, PM2VDACRDColorFormat);
334c35d236eSmrg
335c35d236eSmrg    glintReg->DacRegs[PM2VDACRDDClk0PreScale] = Permedia2vInIndReg(pScrn, PM2VDACRDDClk0PreScale);
336c35d236eSmrg    glintReg->DacRegs[PM2VDACRDDClk0FeedbackScale] = Permedia2vInIndReg(pScrn, PM2VDACRDDClk0FeedbackScale);
337c35d236eSmrg    glintReg->DacRegs[PM2VDACRDDClk0PostScale] = Permedia2vInIndReg(pScrn, PM2VDACRDDClk0PostScale);
338c35d236eSmrg}
339c35d236eSmrg
340c35d236eSmrgvoid
341c35d236eSmrgPermedia2VRestore(ScrnInfoPtr pScrn, GLINTRegPtr glintReg)
342c35d236eSmrg{
343c35d236eSmrg    GLINTPtr pGlint = GLINTPTR(pScrn);
344c35d236eSmrg    CARD32 temp;
345c35d236eSmrg    int i;
346c35d236eSmrg
347c35d236eSmrg    /* We can't rely on the vgahw layer copying the font information
348c35d236eSmrg     * back properly, due to problems with MMIO access to VGA space
349c35d236eSmrg     * so we memcpy the information */
350c35d236eSmrg    if (pGlint->STATE)
351c35d236eSmrg    	memcpy((CARD8*)pGlint->FbBase,(CARD8*)pGlint->VGAdata, 65536);
352c35d236eSmrg
353c35d236eSmrg    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[ChipConfig >> 3], ChipConfig);
354c35d236eSmrg    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[Aperture0 >> 3], Aperture0);
355c35d236eSmrg    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[Aperture1 >> 3], Aperture1);
356c35d236eSmrg    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMFramebufferWriteMask >> 3],
357c35d236eSmrg							PMFramebufferWriteMask);
358c35d236eSmrg    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMBypassWriteMask >> 3],
359c35d236eSmrg							PMBypassWriteMask);
360c35d236eSmrg    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[DFIFODis >> 3], DFIFODis);
361c35d236eSmrg    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[FIFODis >> 3], FIFODis);
362c35d236eSmrg    /* We only muck about with PMMemConfig, if user wants to */
363c35d236eSmrg    if (pGlint->UseBlockWrite)
364c35d236eSmrg    	GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMMemConfig >> 3],PMMemConfig);
365c35d236eSmrg    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMVideoControl >> 3],
366c35d236eSmrg								PMVideoControl);
367c35d236eSmrg    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMHbEnd >> 3], PMHgEnd);
368c35d236eSmrg    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMScreenBase >> 3], PMScreenBase);
369c35d236eSmrg    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[VClkCtl >> 3], VClkCtl);
370c35d236eSmrg    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMScreenStride >> 3],
371c35d236eSmrg								PMScreenStride);
372c35d236eSmrg    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMHTotal >> 3], PMHTotal);
373c35d236eSmrg    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMHbEnd >> 3], PMHbEnd);
374c35d236eSmrg    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMHsStart >> 3], PMHsStart);
375c35d236eSmrg    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMHsEnd >> 3], PMHsEnd);
376c35d236eSmrg    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMVTotal >> 3], PMVTotal);
377c35d236eSmrg    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMVbEnd >> 3], PMVbEnd);
378c35d236eSmrg    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMVsStart >> 3], PMVsStart);
379c35d236eSmrg    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMVsEnd >> 3], PMVsEnd);
380c35d236eSmrg
381c35d236eSmrg    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PM2VDACRDIndexControl >> 3],
382c35d236eSmrg				PM2VDACRDIndexControl);
383c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDOverlayKey, 0x00,
384c35d236eSmrg				glintReg->DacRegs[PM2VDACRDOverlayKey]);
385c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDSyncControl, 0x00,
386c35d236eSmrg				glintReg->DacRegs[PM2VDACRDSyncControl]);
387c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDMiscControl, 0x00,
388c35d236eSmrg				glintReg->DacRegs[PM2VDACRDMiscControl]);
389c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDDACControl, 0x00,
390c35d236eSmrg				glintReg->DacRegs[PM2VDACRDDACControl]);
391c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDPixelSize, 0x00,
392c35d236eSmrg				glintReg->DacRegs[PM2VDACRDPixelSize]);
393c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDColorFormat, 0x00,
394c35d236eSmrg				glintReg->DacRegs[PM2VDACRDColorFormat]);
395c35d236eSmrg
396c35d236eSmrg    for (i=0;i<768;i++) {
397c35d236eSmrg    	Permedia2WriteAddress(pScrn, i);
398c35d236eSmrg	Permedia2WriteData(pScrn, glintReg->cmap[i]);
399c35d236eSmrg    }
400c35d236eSmrg
401c35d236eSmrg    temp = Permedia2vInIndReg(pScrn, PM2VDACIndexClockControl) & 0xFC;
402c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDDClk0PreScale, 0x00,
403c35d236eSmrg				glintReg->DacRegs[PM2VDACRDDClk0PreScale]);
404c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDDClk0FeedbackScale, 0x00,
405c35d236eSmrg				glintReg->DacRegs[PM2VDACRDDClk0FeedbackScale]);
406c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDDClk0PostScale, 0x00,
407c35d236eSmrg				glintReg->DacRegs[PM2VDACRDDClk0PostScale]);
408c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACIndexClockControl, 0x00, temp|0x03);
409c35d236eSmrg}
410c35d236eSmrg
411c35d236eSmrgstatic void
412c35d236eSmrgPermedia2vShowCursor(ScrnInfoPtr pScrn)
413c35d236eSmrg{
414c35d236eSmrg    /* Enable cursor - X11 mode */
415c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDCursorMode, 0x00, 0x11);
416c35d236eSmrg}
417c35d236eSmrg
418c35d236eSmrgstatic void Permedia2vLoadCursorCallback(ScrnInfoPtr pScrn);
419c35d236eSmrg
420c35d236eSmrgstatic void
421c35d236eSmrgPermedia2vHideCursor(ScrnInfoPtr pScrn)
422c35d236eSmrg{
423c35d236eSmrg    GLINTPtr pGlint = GLINTPTR(pScrn);
424c35d236eSmrg
425c35d236eSmrg    /* Disable cursor - X11 mode */
426c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDCursorMode, 0x00, 0x10);
427c35d236eSmrg
428c35d236eSmrg    /*
429c35d236eSmrg     * For some reason, we need to clear the image as well as disable
430c35d236eSmrg     * the cursor on PM2V, but not on PM3. The problem is noticeable
431c35d236eSmrg     * only when running multi-head, as you can see the cursor get
432c35d236eSmrg     * "left behind" on the screen it is leaving...
433c35d236eSmrg     */
434c35d236eSmrg    if (pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_PERMEDIA2V) {
435c35d236eSmrg        memset(pGlint->HardwareCursorPattern, 0, 1024);
436c35d236eSmrg	pGlint->LoadCursorCallback = Permedia2vLoadCursorCallback;
437c35d236eSmrg    }
438c35d236eSmrg}
439c35d236eSmrg
440c35d236eSmrgstatic void
441c35d236eSmrgPermedia2vLoadCursorCallback(
442c35d236eSmrg    ScrnInfoPtr pScrn
443c35d236eSmrg)
444c35d236eSmrg{
445c35d236eSmrg    GLINTPtr pGlint = GLINTPTR(pScrn);
446c35d236eSmrg    int i;
447c35d236eSmrg
448c35d236eSmrg    for (i=0; i<1024; i++)
449c35d236eSmrg    	Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPattern+i, 0x00,
450c35d236eSmrg					pGlint->HardwareCursorPattern[i]);
451c35d236eSmrg
452c35d236eSmrg    pGlint->LoadCursorCallback = NULL;
453c35d236eSmrg}
454c35d236eSmrg
455c35d236eSmrgstatic void
456c35d236eSmrgPermedia2vLoadCursorImage(
457c35d236eSmrg    ScrnInfoPtr pScrn,
458c35d236eSmrg    unsigned char *src
459c35d236eSmrg)
460c35d236eSmrg{
461c35d236eSmrg    GLINTPtr pGlint = GLINTPTR(pScrn);
462c35d236eSmrg    int i;
463c35d236eSmrg
464c35d236eSmrg    for (i=0; i<1024; i++)
465c35d236eSmrg	pGlint->HardwareCursorPattern[i] = *(src++);
466c35d236eSmrg
467c35d236eSmrg    pGlint->LoadCursorCallback = Permedia2vLoadCursorCallback;
468c35d236eSmrg}
469c35d236eSmrg
470c35d236eSmrgstatic void
471c35d236eSmrgPermedia2vSetCursorPosition(
472c35d236eSmrg   ScrnInfoPtr pScrn,
473c35d236eSmrg   int x, int y
474c35d236eSmrg)
475c35d236eSmrg{
476c35d236eSmrg    x += 64;
477c35d236eSmrg    y += 64;
478c35d236eSmrg    /* Output position - "only" 11 bits of location documented */
479c35d236eSmrg
480c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDCursorHotSpotX, 0x00, 0x3f);
481c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDCursorHotSpotY, 0x00, 0x3f);
482c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDCursorXLow, 0x00, x & 0xFF);
483c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDCursorXHigh, 0x00, (x>>8) & 0x0F);
484c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDCursorYLow, 0x00, y & 0xFF);
485c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDCursorYHigh, 0x00, (y>>8) & 0x0F);
486c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2DACCursorControl, 0x00, 0x00);
487c35d236eSmrg}
488c35d236eSmrg
489c35d236eSmrgstatic void
490c35d236eSmrgPermedia2vCursorColorCallback(
491c35d236eSmrg   ScrnInfoPtr pScrn
492c35d236eSmrg)
493c35d236eSmrg{
494c35d236eSmrg    GLINTPtr pGlint = GLINTPTR(pScrn);
495c35d236eSmrg    int fg = pGlint->FGCursor;
496c35d236eSmrg    int bg = pGlint->BGCursor;
497c35d236eSmrg
498c35d236eSmrg    if ((pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_PERMEDIA3) ||
499c35d236eSmrg	((pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_GAMMA) &&
500c35d236eSmrg	 (pGlint->MultiChip == PCI_CHIP_PERMEDIA3)) ) {
501c35d236eSmrg    /* PM3 uses last 2 indexes into hardware cursor palette fg first...*/
502c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+39, 0x00, (fg>>16)&0xff);
503c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+40, 0x00, (fg>>8)&0xff);
504c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+41, 0x00, fg & 0xff);
505c35d236eSmrg
506c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+42, 0x00, (bg>>16)&0xff);
507c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+43, 0x00, (bg>>8)&0xff);
508c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+44, 0x00, bg & 0xff);
509c35d236eSmrg    } else {
510c35d236eSmrg    /* PM2v uses first 2 indexes into hardware cursor palette bg first...*/
511c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+0, 0x00, (bg>>16)&0xff);
512c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+1, 0x00, (bg>>8)&0xff);
513c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+2, 0x00, bg & 0xff);
514c35d236eSmrg
515c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+3, 0x00, (fg>>16)&0xff);
516c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+4, 0x00, (fg>>8)&0xff);
517c35d236eSmrg    Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+5, 0x00, fg & 0xff);
518c35d236eSmrg    }
519c35d236eSmrg    pGlint->CursorColorCallback = NULL;
520c35d236eSmrg}
521c35d236eSmrg
522c35d236eSmrgstatic void
523c35d236eSmrgPermedia2vSetCursorColors(
524c35d236eSmrg   ScrnInfoPtr pScrn,
525c35d236eSmrg   int bg, int fg
526c35d236eSmrg)
527c35d236eSmrg{
528c35d236eSmrg    GLINTPtr pGlint = GLINTPTR(pScrn);
529c35d236eSmrg
530c35d236eSmrg    pGlint->FGCursor = fg;
531c35d236eSmrg    pGlint->BGCursor = bg;
532c35d236eSmrg
533c35d236eSmrg    pGlint->CursorColorCallback = Permedia2vCursorColorCallback;
534c35d236eSmrg}
535c35d236eSmrg
536c35d236eSmrgstatic Bool
537c35d236eSmrgPermedia2vUseHWCursor(ScreenPtr pScr, CursorPtr pCurs)
538c35d236eSmrg{
539c35d236eSmrg    return TRUE;
540c35d236eSmrg}
541c35d236eSmrg
542c35d236eSmrgBool
543c35d236eSmrgPermedia2vHWCursorInit(ScreenPtr pScreen)
544c35d236eSmrg{
545c35d236eSmrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
546c35d236eSmrg    GLINTPtr pGlint = GLINTPTR(pScrn);
547c35d236eSmrg    xf86CursorInfoPtr infoPtr;
548c35d236eSmrg
549c35d236eSmrg    infoPtr = xf86CreateCursorInfoRec();
550c35d236eSmrg    if(!infoPtr) return FALSE;
551c35d236eSmrg
552c35d236eSmrg    pGlint->CursorInfoRec = infoPtr;
553c35d236eSmrg
554c35d236eSmrg    infoPtr->MaxWidth = 64;
555c35d236eSmrg    infoPtr->MaxHeight = 64;
556c35d236eSmrg    infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
557c35d236eSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN
558c35d236eSmrg		HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
559c35d236eSmrg#endif
560c35d236eSmrg		HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1;
561c35d236eSmrg    infoPtr->SetCursorColors = Permedia2vSetCursorColors;
562c35d236eSmrg    infoPtr->SetCursorPosition = Permedia2vSetCursorPosition;
563c35d236eSmrg    infoPtr->LoadCursorImage = Permedia2vLoadCursorImage;
564c35d236eSmrg    infoPtr->HideCursor = Permedia2vHideCursor;
565c35d236eSmrg    infoPtr->ShowCursor = Permedia2vShowCursor;
566c35d236eSmrg    infoPtr->UseHWCursor = Permedia2vUseHWCursor;
567c35d236eSmrg
568c35d236eSmrg    return(xf86InitCursor(pScreen, infoPtr));
569c35d236eSmrg}
570