pm2_dac.c revision 933f9f8f
1/*
2 * Copyright 1997-2001 by Alan Hourihane <alanh@fairlite.demon.co.uk>
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Alan Hourihane not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission.  Alan Hourihane makes no representations
11 * about the suitability of this software for any purpose.  It is provided
12 * "as is" without express or implied warranty.
13 *
14 * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 *
22 * Authors:  Alan Hourihane, <alanh@fairlite.demon.co.uk>
23 *           Dirk Hohndel,   <hohndel@suse.de>
24 *	     Stefan Dirsch,  <sndirsch@suse.de>
25 *	     Helmut Fahrion, <hf@suse.de>
26 *	     Michel Dänzer,  <michdaen@iiic.ethz.ch>
27 *
28 * this work is sponsored by S.u.S.E. GmbH, Fuerth, Elsa GmbH, Aachen and
29 * Siemens Nixdorf Informationssysteme
30 */
31/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/glint/pm2_dac.c,v 1.26tsi Exp $ */
32
33#ifdef HAVE_CONFIG_H
34#include "config.h"
35#endif
36
37#include <X11/Xarch.h>
38#include "xf86.h"
39#include "xf86_OSproc.h"
40
41#include "xf86PciInfo.h"
42#include "xf86Pci.h"
43
44#include "glint_regs.h"
45#include "glint.h"
46
47#define INITIALFREQERR 100000
48#define MINCLK 110000		/* VCO frequency range */
49#define MAXCLK 250000
50
51static unsigned long
52PM2DAC_CalculateMNPCForClock
53(
54 unsigned long reqclock,		/* In kHz units */
55 unsigned long refclock,		/* In kHz units */
56 unsigned char *rm, 			/* M Out */
57 unsigned char *rn, 			/* N Out */
58 unsigned char *rp			/* P Out */
59 )
60{
61    unsigned char	m, n, p;
62    unsigned long	f;
63    long		freqerr, lowestfreqerr = INITIALFREQERR;
64    unsigned long  	clock,actualclock = 0;
65
66    for (n = 2; n <= 14; n++) {
67        for (m = 2; m != 0; m++) { /* this is a char, so this counts to 255 */
68	    f = refclock * m / n;
69	    if ( (f < MINCLK) || (f > MAXCLK) )
70	    	continue;
71	    for (p = 0; p <= 4; p++) {
72	    	clock = f >> p;
73		freqerr = reqclock - clock;
74		if (freqerr < 0)
75		    freqerr = -freqerr;
76		if (freqerr < lowestfreqerr) {
77		    *rn = n;
78		    *rm = m;
79		    *rp = p;
80		    lowestfreqerr = freqerr;
81		    actualclock = clock;
82#ifdef DEBUG
83	ErrorF("Best %ld diff %ld\n",actualclock,freqerr);
84#endif
85		}
86	    }
87	}
88    }
89
90    return(actualclock);
91}
92
93Bool
94Permedia2Init(ScrnInfoPtr pScrn, DisplayModePtr mode)
95{
96    GLINTPtr pGlint = GLINTPTR(pScrn);
97    GLINTRegPtr pReg = &pGlint->ModeReg[0];
98    CARD32 temp1, temp2, temp3, temp4;
99
100    pReg->glintRegs[Aperture0 >> 3] = 0;
101    pReg->glintRegs[Aperture1 >> 3] = 0;
102    pReg->glintRegs[PMFramebufferWriteMask >> 3] = 0xFFFFFFFF;
103    pReg->glintRegs[PMBypassWriteMask >> 3] = 0xFFFFFFFF;
104
105    pReg->glintRegs[DFIFODis >> 3] = 0;
106    pReg->glintRegs[FIFODis >> 3] = 1;
107
108    if (pGlint->UseBlockWrite)
109	pReg->glintRegs[PMMemConfig >> 3] = GLINT_READ_REG(PMMemConfig) | 1<<21;
110
111
112    temp1 = mode->CrtcHSyncStart - mode->CrtcHDisplay;
113    temp2 = mode->CrtcVSyncStart - mode->CrtcVDisplay;
114    temp3 = mode->CrtcHSyncEnd - mode->CrtcHSyncStart;
115    temp4 = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
116
117    pReg->glintRegs[PMHTotal >> 3] = Shiftbpp(pScrn,mode->CrtcHTotal);
118    pReg->glintRegs[PMHsEnd >> 3] = Shiftbpp(pScrn, temp1 + temp3);
119    pReg->glintRegs[PMHsStart >> 3] = Shiftbpp(pScrn, temp1);
120    pReg->glintRegs[PMHbEnd >> 3] =
121			Shiftbpp(pScrn,mode->CrtcHTotal-mode->CrtcHDisplay);
122    pReg->glintRegs[PMScreenStride >> 3] =
123			Shiftbpp(pScrn,pScrn->displayWidth>>1);
124
125    pReg->glintRegs[PMVTotal >> 3] = mode->CrtcVTotal;
126    pReg->glintRegs[PMVsEnd >> 3] = temp2 + temp4;
127    pReg->glintRegs[PMVsStart >> 3] = temp2;
128    pReg->glintRegs[PMVbEnd >> 3] = mode->CrtcVTotal - mode->CrtcVDisplay;
129
130    /* The hw cursor needs /VSYNC to recognize vert retrace. We'll stick
131       both sync lines to active high here and if needed invert them
132       using the RAMDAC's MCR below. */
133    pReg->glintRegs[PMVideoControl >> 3] =
134	(1 << 5) | (1 << 3) | 1;
135
136    if (pScrn->bitsPerPixel > 8) {
137	/* When != 8bpp then we stick the RAMDAC into 64bit mode */
138	/* And reduce the horizontal timings by half */
139	pReg->glintRegs[PMVideoControl >> 3] |= 1<<16;
140    	pReg->glintRegs[PMHTotal >> 3] >>= 1;
141	pReg->glintRegs[PMHsEnd >> 3] >>= 1;
142	pReg->glintRegs[PMHsStart >> 3] >>= 1;
143	pReg->glintRegs[PMHbEnd >> 3] >>= 1;
144    }
145
146    pReg->glintRegs[VClkCtl >> 3] = (GLINT_READ_REG(VClkCtl) & 0xFFFFFFFC);
147    pReg->glintRegs[PMScreenBase >> 3] = 0;
148    pReg->glintRegs[PMHTotal >> 3] -= 1;
149    pReg->glintRegs[PMHsStart >> 3] -= 1;
150    pReg->glintRegs[PMVTotal >> 3] -= 1;
151
152    pReg->glintRegs[ChipConfig >> 3] = GLINT_READ_REG(ChipConfig) & 0xFFFFFFDD;
153
154    pReg->DacRegs[PM2DACIndexMDCR] = 0x00; /* Disable Overlay */
155
156    {
157	/* Get the programmable clock values */
158    	unsigned char m,n,p;
159
160	(void) PM2DAC_CalculateMNPCForClock(mode->Clock,pGlint->RefClock,
161								&m,&n,&p);
162	pReg->DacRegs[PM2DACIndexClockAM] = m;
163	pReg->DacRegs[PM2DACIndexClockAN] = n;
164	pReg->DacRegs[PM2DACIndexClockAP] = p|0x08;
165    }
166
167    if (pScrn->rgbBits == 8)
168	pReg->DacRegs[PM2DACIndexMCR] = 0x02; /* 8bit DAC */
169    else
170        pReg->DacRegs[PM2DACIndexMCR] = 0x00; /* 6bit DAC */
171
172    if (!(mode->Flags & V_PHSYNC))
173        pReg->DacRegs[PM2DACIndexMCR] |= 0x04; /* invert hsync */
174    if (!(mode->Flags & V_PVSYNC))
175        pReg->DacRegs[PM2DACIndexMCR] |= 0x08; /* invert vsync */
176
177    switch (pScrn->bitsPerPixel)
178    {
179    case 8:
180	pReg->DacRegs[PM2DACIndexCMR] = PM2DAC_RGB | PM2DAC_GRAPHICS |
181					PM2DAC_CI8;
182    	break;
183    case 16:
184	if (pScrn->depth == 15) {
185	      pReg->DacRegs[PM2DACIndexCMR] = PM2DAC_RGB | PM2DAC_TRUECOLOR|
186				        PM2DAC_GRAPHICS | PM2DAC_5551;
187	} else {
188	    pReg->DacRegs[PM2DACIndexCMR] = PM2DAC_RGB | PM2DAC_TRUECOLOR|
189				 	PM2DAC_GRAPHICS | PM2DAC_565;
190	}
191    	break;
192    case 24:
193	pReg->DacRegs[PM2DACIndexCMR] = PM2DAC_RGB | PM2DAC_TRUECOLOR|
194				 	PM2DAC_GRAPHICS | PM2DAC_PACKED;
195    	break;
196    case 32:
197	pReg->DacRegs[PM2DACIndexCMR] = PM2DAC_RGB |
198				 	PM2DAC_GRAPHICS | PM2DAC_8888;
199	if (pScrn->overlayFlags & OVERLAY_8_32_PLANAR) {
200	    pReg->DacRegs[PM2DACIndexColorKeyControl] = 0x11;
201	    pReg->DacRegs[PM2DACIndexColorKeyOverlay] = pScrn->colorKey;
202	} else
203	    pReg->DacRegs[PM2DACIndexCMR] |= PM2DAC_TRUECOLOR;
204    	break;
205    }
206
207    return(TRUE);
208}
209
210void
211Permedia2Save(ScrnInfoPtr pScrn, GLINTRegPtr glintReg)
212{
213    GLINTPtr pGlint = GLINTPTR(pScrn);
214    int i;
215
216    /* We can't rely on the vgahw layer copying the font information
217     * back properly, due to problems with MMIO access to VGA space
218     * so we memcpy the information using the slow routines */
219    xf86SlowBcopy((CARD8*)pGlint->FbBase, (CARD8*)pGlint->VGAdata, 65536);
220
221    glintReg->glintRegs[Aperture0 >> 3] = GLINT_READ_REG(Aperture0);
222    glintReg->glintRegs[Aperture1 >> 3] = GLINT_READ_REG(Aperture1);
223    glintReg->glintRegs[PMFramebufferWriteMask >> 3] =
224					GLINT_READ_REG(PMFramebufferWriteMask);
225    glintReg->glintRegs[PMBypassWriteMask >> 3]  = GLINT_READ_REG(PMBypassWriteMask);
226    glintReg->glintRegs[DFIFODis >> 3]  = GLINT_READ_REG(DFIFODis);
227    glintReg->glintRegs[FIFODis >> 3]  = GLINT_READ_REG(FIFODis);
228    /* We only muck about with PMMemConfig, if user wants to */
229    if (pGlint->UseBlockWrite)
230	glintReg->glintRegs[PMMemConfig >> 3] = GLINT_READ_REG(PMMemConfig);
231    glintReg->glintRegs[PMHTotal >> 3] = GLINT_READ_REG(PMHTotal);
232    glintReg->glintRegs[PMHbEnd >> 3] = GLINT_READ_REG(PMHbEnd);
233    glintReg->glintRegs[PMHbEnd >> 3] = GLINT_READ_REG(PMHgEnd);
234    glintReg->glintRegs[PMScreenStride >> 3] = GLINT_READ_REG(PMScreenStride);
235    glintReg->glintRegs[PMHsStart >> 3] = GLINT_READ_REG(PMHsStart);
236    glintReg->glintRegs[PMHsEnd >> 3] = GLINT_READ_REG(PMHsEnd);
237    glintReg->glintRegs[PMVTotal >> 3] = GLINT_READ_REG(PMVTotal);
238    glintReg->glintRegs[PMVbEnd >> 3] = GLINT_READ_REG(PMVbEnd);
239    glintReg->glintRegs[PMVsStart >> 3] = GLINT_READ_REG(PMVsStart);
240    glintReg->glintRegs[PMVsEnd >> 3] = GLINT_READ_REG(PMVsEnd);
241    glintReg->glintRegs[PMScreenBase >> 3] = GLINT_READ_REG(PMScreenBase);
242    glintReg->glintRegs[PMVideoControl >> 3] = GLINT_READ_REG(PMVideoControl);
243    glintReg->glintRegs[VClkCtl >> 3] = GLINT_READ_REG(VClkCtl);
244    glintReg->glintRegs[ChipConfig >> 3] = GLINT_READ_REG(ChipConfig);
245
246    for (i=0;i<768;i++) {
247    	Permedia2ReadAddress(pScrn, i);
248	glintReg->cmap[i] = Permedia2ReadData(pScrn);
249    }
250
251    glintReg->DacRegs[PM2DACIndexColorKeyOverlay] =
252				Permedia2InIndReg(pScrn, PM2DACIndexColorKeyOverlay);
253    glintReg->DacRegs[PM2DACIndexColorKeyControl] =
254				Permedia2InIndReg(pScrn, PM2DACIndexColorKeyControl);
255    glintReg->DacRegs[PM2DACIndexMCR] =
256				Permedia2InIndReg(pScrn, PM2DACIndexMCR);
257    glintReg->DacRegs[PM2DACIndexMDCR] =
258				Permedia2InIndReg(pScrn, PM2DACIndexMDCR);
259    glintReg->DacRegs[PM2DACIndexCMR] =
260				Permedia2InIndReg(pScrn, PM2DACIndexCMR);
261
262    glintReg->DacRegs[PM2DACIndexClockAM] =
263				Permedia2InIndReg(pScrn, PM2DACIndexClockAM);
264    glintReg->DacRegs[PM2DACIndexClockAN] =
265				Permedia2InIndReg(pScrn, PM2DACIndexClockAN);
266    glintReg->DacRegs[PM2DACIndexClockAP] =
267				Permedia2InIndReg(pScrn, PM2DACIndexClockAP);
268}
269
270void
271Permedia2Restore(ScrnInfoPtr pScrn, GLINTRegPtr glintReg)
272{
273    GLINTPtr pGlint = GLINTPTR(pScrn);
274    int i;
275
276    /* We can't rely on the vgahw layer copying the font information
277     * back properly, due to problems with MMIO access to VGA space
278     * so we memcpy the information using the slow routines */
279    if (pGlint->STATE)
280	xf86SlowBcopy((CARD8*)pGlint->VGAdata, (CARD8*)pGlint->FbBase, 65536);
281
282#if 0
283    GLINT_SLOW_WRITE_REG(0, ResetStatus);
284    while(GLINT_READ_REG(ResetStatus) != 0) {
285	xf86MsgVerb(X_INFO, 2, "Resetting Engine - Please Wait.\n");
286    };
287#endif
288
289    GLINT_SLOW_WRITE_REG(0xFF, PM2DACReadMask);
290
291    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[Aperture0 >> 3], Aperture0);
292    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[Aperture1 >> 3], Aperture1);
293    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMFramebufferWriteMask >> 3],
294							PMFramebufferWriteMask);
295    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMBypassWriteMask >> 3],
296							PMBypassWriteMask);
297    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[DFIFODis >> 3], DFIFODis);
298    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[FIFODis >> 3], FIFODis);
299    /* We only muck about with PMMemConfig, if user wants to */
300    if (pGlint->UseBlockWrite)
301    	GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMMemConfig >> 3],PMMemConfig);
302    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMVideoControl >> 3],
303								PMVideoControl);
304    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMHbEnd >> 3], PMHgEnd);
305    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMScreenBase >> 3], PMScreenBase);
306    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[VClkCtl >> 3], VClkCtl);
307    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMScreenStride >> 3],
308								PMScreenStride);
309    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMHTotal >> 3], PMHTotal);
310    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMHbEnd >> 3], PMHbEnd);
311    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMHsStart >> 3], PMHsStart);
312    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMHsEnd >> 3], PMHsEnd);
313    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMVTotal >> 3], PMVTotal);
314    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMVbEnd >> 3], PMVbEnd);
315    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMVsStart >> 3], PMVsStart);
316    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMVsEnd >> 3], PMVsEnd);
317    GLINT_SLOW_WRITE_REG(glintReg->glintRegs[ChipConfig >> 3], ChipConfig);
318
319    Permedia2OutIndReg(pScrn, PM2DACIndexColorKeyOverlay, 0x00,
320					glintReg->DacRegs[PM2DACIndexColorKeyOverlay]);
321    Permedia2OutIndReg(pScrn, PM2DACIndexColorKeyControl, 0x00,
322					glintReg->DacRegs[PM2DACIndexColorKeyControl]);
323    Permedia2OutIndReg(pScrn, PM2DACIndexMCR, 0x00,
324					glintReg->DacRegs[PM2DACIndexMCR]);
325    Permedia2OutIndReg(pScrn, PM2DACIndexMDCR, 0x00,
326					glintReg->DacRegs[PM2DACIndexMDCR]);
327    Permedia2OutIndReg(pScrn, PM2DACIndexCMR, 0x00,
328					glintReg->DacRegs[PM2DACIndexCMR]);
329
330    Permedia2OutIndReg(pScrn, PM2DACIndexClockAM, 0x00,
331					glintReg->DacRegs[PM2DACIndexClockAM]);
332    Permedia2OutIndReg(pScrn, PM2DACIndexClockAN, 0x00,
333					glintReg->DacRegs[PM2DACIndexClockAN]);
334    Permedia2OutIndReg(pScrn, PM2DACIndexClockAP, 0x00,
335					glintReg->DacRegs[PM2DACIndexClockAP]);
336
337    for (i=0;i<768;i++) {
338    	Permedia2WriteAddress(pScrn, i);
339        Permedia2WriteData(pScrn, glintReg->cmap[i]);
340    }
341}
342
343static void
344Permedia2ShowCursor(ScrnInfoPtr pScrn)
345{
346    /* Enable cursor - X11 mode */
347    Permedia2OutIndReg(pScrn, PM2DACCursorControl, 0x00, 0x43);
348}
349
350static void
351Permedia2HideCursor(ScrnInfoPtr pScrn)
352{
353    /* Disable cursor */
354    Permedia2OutIndReg(pScrn, PM2DACCursorControl, 0x00, 0x00);
355}
356
357static void
358Permedia2LoadCursorImage(
359    ScrnInfoPtr pScrn,
360    unsigned char *src
361)
362{
363    GLINTPtr pGlint = GLINTPTR(pScrn);
364    int i;
365
366    GLINT_SLOW_WRITE_REG(0x00, PM2DACWriteAddress);
367    for (i=0; i<1024; i++) {
368	GLINT_SLOW_WRITE_REG(*(src++), PM2DACCursorData);
369    }
370}
371
372static void
373Permedia2SetCursorPosition(
374   ScrnInfoPtr pScrn,
375   int x, int y
376)
377{
378    GLINTPtr pGlint = GLINTPTR(pScrn);
379
380    x += 64;
381    y += 64;
382
383    /* Output position - "only" 11 bits of location documented */
384
385    GLINT_WRITE_REG(x & 0xFF,	   PM2DACCursorXLsb);
386    GLINT_WRITE_REG((x>>8) & 0x07, PM2DACCursorXMsb);
387    GLINT_WRITE_REG(y & 0xFF,	   PM2DACCursorYLsb);
388    GLINT_WRITE_REG((y>>8) & 0x07, PM2DACCursorYMsb);
389}
390
391static void
392Permedia2SetCursorColors(
393   ScrnInfoPtr pScrn,
394   int bg, int fg
395)
396{
397    GLINTPtr pGlint = GLINTPTR(pScrn);
398    /* The Permedia2 cursor is always 8 bits so shift 8, not 10 */
399
400    GLINT_SLOW_WRITE_REG(1, PM2DACCursorColorAddress);
401    /* Background color */
402    GLINT_SLOW_WRITE_REG(bg >> 0, PM2DACCursorColorData);
403    GLINT_SLOW_WRITE_REG(bg >> 8, PM2DACCursorColorData);
404    GLINT_SLOW_WRITE_REG(bg >> 16, PM2DACCursorColorData);
405
406    /* Foreground color */
407    GLINT_SLOW_WRITE_REG(fg >> 0, PM2DACCursorColorData);
408    GLINT_SLOW_WRITE_REG(fg >> 8, PM2DACCursorColorData);
409    GLINT_SLOW_WRITE_REG(fg >> 16, PM2DACCursorColorData);
410}
411
412static Bool
413Permedia2UseHWCursor(ScreenPtr pScr, CursorPtr pCurs)
414{
415    return TRUE;
416}
417
418Bool
419Permedia2HWCursorInit(ScreenPtr pScreen)
420{
421    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
422    GLINTPtr pGlint = GLINTPTR(pScrn);
423    xf86CursorInfoPtr infoPtr;
424
425    infoPtr = xf86CreateCursorInfoRec();
426    if(!infoPtr) return FALSE;
427
428    pGlint->CursorInfoRec = infoPtr;
429
430    infoPtr->MaxWidth = 64;
431    infoPtr->MaxHeight = 64;
432    infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
433#if X_BYTE_ORDER == X_LITTLE_ENDIAN
434		HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
435#endif
436		HARDWARE_CURSOR_SOURCE_MASK_NOT_INTERLEAVED;
437    infoPtr->SetCursorColors = Permedia2SetCursorColors;
438    infoPtr->SetCursorPosition = Permedia2SetCursorPosition;
439    infoPtr->LoadCursorImage = Permedia2LoadCursorImage;
440    infoPtr->HideCursor = Permedia2HideCursor;
441    infoPtr->ShowCursor = Permedia2ShowCursor;
442    infoPtr->UseHWCursor = Permedia2UseHWCursor;
443
444    return(xf86InitCursor(pScreen, infoPtr));
445}
446
447/* I2C Functions */
448
449void
450Permedia2I2CUDelay(I2CBusPtr b, int usec)
451{
452    GLINTPtr pGlint = (GLINTPtr) b->DriverPrivate.ptr;
453    CARD32 ct1 = GLINT_READ_REG(PMCount);
454    CARD32 ct2 = usec * 100;
455
456    if (GLINT_READ_REG(PMCount) != ct1)
457	while ((GLINT_READ_REG(PMCount) - ct1) < ct2);
458}
459
460void
461Permedia2I2CPutBits(I2CBusPtr b, int scl, int sda)
462{
463    GLINTPtr pGlint = (GLINTPtr) b->DriverPrivate.ptr;
464    int r = (pGlint->DDCBus == b) ? PMDDCData : VSSerialBusControl;
465/*
466    This is bogus.
467    All this line does is to preserve the USE_MONID bit if set which prevents
468    the i2c bits from doing anything
469    CARD32 v = GLINT_READ_REG(r) & ~(ClkOut | DataOut);
470*/
471    CARD32 v = 0;
472
473    if (scl > 0) v |= ClkOut;
474    if (sda > 0) v |= DataOut;
475
476    GLINT_WRITE_REG(v, r);
477}
478
479void
480Permedia2I2CGetBits(I2CBusPtr b, int *scl, int *sda)
481{
482    GLINTPtr pGlint = (GLINTPtr) b->DriverPrivate.ptr;
483    CARD32 v = GLINT_READ_REG((pGlint->DDCBus == b) ?
484	    PMDDCData : VSSerialBusControl);
485
486    *scl = (v & ClkIn) > 0;
487    *sda = (v & DataIn) > 0;
488}
489
490void
491Permedia2PreInit(ScrnInfoPtr pScrn)
492{
493#if defined(__alpha__)
494    GLINTPtr pGlint = GLINTPTR(pScrn);
495
496    /*
497     * On Alpha, we have to init secondary PM2 cards, since
498     * int10 cannot be run on the OEMed cards with VGA disable
499     * jumpers.
500     */
501    if (!xf86IsPrimaryPci(pGlint->PciInfo)) {
502	if ( IS_GLORIASYNERGY ) {
503
504	    /* PM2DAC_CalculateMNPCForClock(80000, 14318, &m, &n, &p); */
505	    Permedia2OutIndReg(pScrn, PM2DACIndexMemClockM, 0x00, 0x7b);
506	    Permedia2OutIndReg(pScrn, PM2DACIndexMemClockN, 0x00, 0x0b);
507	    Permedia2OutIndReg(pScrn, PM2DACIndexMemClockP, 0x00, 0x09);
508
509	    GLINT_SLOW_WRITE_REG( 0x20, PMBootAddress);
510	    GLINT_SLOW_WRITE_REG( 0xe6002021, PMMemConfig);
511	}
512    }
513#endif /* __alpha__ */
514}
515