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