1706f2543Smrg/*
2706f2543Smrg * Copyright 1998 by Alan Hourihane, Wigan, England.
3706f2543Smrg *
4706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its
5706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that
6706f2543Smrg * the above copyright notice appear in all copies and that both that
7706f2543Smrg * copyright notice and this permission notice appear in supporting
8706f2543Smrg * documentation, and that the name of Alan Hourihane not be used in
9706f2543Smrg * advertising or publicity pertaining to distribution of the software without
10706f2543Smrg * specific, written prior permission.  Alan Hourihane makes no representations
11706f2543Smrg * about the suitability of this software for any purpose.  It is provided
12706f2543Smrg * "as is" without express or implied warranty.
13706f2543Smrg *
14706f2543Smrg * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16706f2543Smrg * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20706f2543Smrg * PERFORMANCE OF THIS SOFTWARE.
21706f2543Smrg *
22706f2543Smrg * Authors:  Alan Hourihane, <alanh@fairlite.demon.co.uk>
23706f2543Smrg *
24706f2543Smrg * IBM RAMDAC routines.
25706f2543Smrg */
26706f2543Smrg
27706f2543Smrg#ifdef HAVE_XORG_CONFIG_H
28706f2543Smrg#include <xorg-config.h>
29706f2543Smrg#endif
30706f2543Smrg
31706f2543Smrg#include "xf86.h"
32706f2543Smrg#include "xf86_OSproc.h"
33706f2543Smrg
34706f2543Smrg#include "xf86Cursor.h"
35706f2543Smrg
36706f2543Smrg#define INIT_IBM_RAMDAC_INFO
37706f2543Smrg#include "IBMPriv.h"
38706f2543Smrg#include "xf86RamDacPriv.h"
39706f2543Smrg
40706f2543Smrg#define INITIALFREQERR 100000
41706f2543Smrg
42706f2543Smrgunsigned long
43706f2543SmrgIBMramdac640CalculateMNPCForClock(
44706f2543Smrg    unsigned long RefClock,	/* In 100Hz units */
45706f2543Smrg    unsigned long ReqClock,	/* In 100Hz units */
46706f2543Smrg    char IsPixClock,	/* boolean, is this the pixel or the sys clock */
47706f2543Smrg    unsigned long MinClock,	/* Min VCO rating */
48706f2543Smrg    unsigned long MaxClock,	/* Max VCO rating */
49706f2543Smrg    unsigned long *rM,	/* M Out */
50706f2543Smrg    unsigned long *rN,	/* N Out */
51706f2543Smrg    unsigned long *rP,	/* Min P In, P Out */
52706f2543Smrg    unsigned long *rC	/* C Out */
53706f2543Smrg)
54706f2543Smrg{
55706f2543Smrg  unsigned long   M, N, P, iP = *rP;
56706f2543Smrg  unsigned long   IntRef, VCO, Clock;
57706f2543Smrg  long            freqErr, lowestFreqErr = INITIALFREQERR;
58706f2543Smrg  unsigned long   ActualClock = 0;
59706f2543Smrg
60706f2543Smrg  for (N = 0; N <= 63; N++)
61706f2543Smrg    {
62706f2543Smrg      IntRef = RefClock / (N + 1);
63706f2543Smrg      if (IntRef < 10000)
64706f2543Smrg	break;			/* IntRef needs to be >= 1MHz */
65706f2543Smrg      for (M = 2; M <= 127; M++)
66706f2543Smrg	{
67706f2543Smrg	  VCO = IntRef * (M + 1);
68706f2543Smrg	  if ((VCO < MinClock) || (VCO > MaxClock))
69706f2543Smrg	    continue;
70706f2543Smrg	  for (P = iP; P <= 4; P++)
71706f2543Smrg	    {
72706f2543Smrg	      if (P != 0)
73706f2543Smrg		Clock = (RefClock * (M + 1)) / ((N + 1) * 2 * P);
74706f2543Smrg	      else
75706f2543Smrg		Clock = (RefClock * (M + 1)) / (N + 1);
76706f2543Smrg
77706f2543Smrg	      freqErr = (Clock - ReqClock);
78706f2543Smrg
79706f2543Smrg	      if (freqErr < 0)
80706f2543Smrg		{
81706f2543Smrg		  /* PixelClock gets rounded up always so monitor reports
82706f2543Smrg		     correct frequency. */
83706f2543Smrg		  if (IsPixClock)
84706f2543Smrg		    continue;
85706f2543Smrg		  freqErr = -freqErr;
86706f2543Smrg		}
87706f2543Smrg
88706f2543Smrg	      if (freqErr < lowestFreqErr)
89706f2543Smrg		{
90706f2543Smrg		  *rM = M;
91706f2543Smrg		  *rN = N;
92706f2543Smrg		  *rP = P;
93706f2543Smrg		  *rC = (VCO <= 1280000 ? 1 : 2);
94706f2543Smrg		  ActualClock = Clock;
95706f2543Smrg
96706f2543Smrg		  lowestFreqErr = freqErr;
97706f2543Smrg		  /* Return if we found an exact match */
98706f2543Smrg		  if (freqErr == 0)
99706f2543Smrg		    return ActualClock;
100706f2543Smrg		}
101706f2543Smrg	    }
102706f2543Smrg	}
103706f2543Smrg    }
104706f2543Smrg
105706f2543Smrg  return ActualClock;
106706f2543Smrg}
107706f2543Smrg
108706f2543Smrgunsigned long
109706f2543SmrgIBMramdac526CalculateMNPCForClock(
110706f2543Smrg    unsigned long RefClock,	/* In 100Hz units */
111706f2543Smrg    unsigned long ReqClock,	/* In 100Hz units */
112706f2543Smrg    char IsPixClock,	/* boolean, is this the pixel or the sys clock */
113706f2543Smrg    unsigned long MinClock,	/* Min VCO rating */
114706f2543Smrg    unsigned long MaxClock,	/* Max VCO rating */
115706f2543Smrg    unsigned long *rM,	/* M Out */
116706f2543Smrg    unsigned long *rN,	/* N Out */
117706f2543Smrg    unsigned long *rP,	/* Min P In, P Out */
118706f2543Smrg    unsigned long *rC	/* C Out */
119706f2543Smrg)
120706f2543Smrg{
121706f2543Smrg  unsigned long   M, N, P, iP = *rP;
122706f2543Smrg  unsigned long   IntRef, VCO, Clock;
123706f2543Smrg  long            freqErr, lowestFreqErr = INITIALFREQERR;
124706f2543Smrg  unsigned long   ActualClock = 0;
125706f2543Smrg
126706f2543Smrg  for (N = 0; N <= 63; N++)
127706f2543Smrg    {
128706f2543Smrg      IntRef = RefClock / (N + 1);
129706f2543Smrg      if (IntRef < 10000)
130706f2543Smrg	break;			/* IntRef needs to be >= 1MHz */
131706f2543Smrg      for (M = 0; M <= 63; M++)
132706f2543Smrg	{
133706f2543Smrg	  VCO = IntRef * (M + 1);
134706f2543Smrg	  if ((VCO < MinClock) || (VCO > MaxClock))
135706f2543Smrg	    continue;
136706f2543Smrg	  for (P = iP; P <= 4; P++)
137706f2543Smrg	    {
138706f2543Smrg	      if (P)
139706f2543Smrg		Clock = (RefClock * (M + 1)) / ((N + 1) * 2 * P);
140706f2543Smrg	      else
141706f2543Smrg		Clock = VCO;
142706f2543Smrg
143706f2543Smrg	      freqErr = (Clock - ReqClock);
144706f2543Smrg
145706f2543Smrg	      if (freqErr < 0)
146706f2543Smrg		{
147706f2543Smrg		  /* PixelClock gets rounded up always so monitor reports
148706f2543Smrg		     correct frequency. */
149706f2543Smrg		  if (IsPixClock)
150706f2543Smrg		    continue;
151706f2543Smrg		  freqErr = -freqErr;
152706f2543Smrg		}
153706f2543Smrg
154706f2543Smrg	      if (freqErr < lowestFreqErr)
155706f2543Smrg		{
156706f2543Smrg		  *rM = M;
157706f2543Smrg		  *rN = N;
158706f2543Smrg		  *rP = P;
159706f2543Smrg		  *rC = (VCO <= 1280000 ? 1 : 2);
160706f2543Smrg		  ActualClock = Clock;
161706f2543Smrg
162706f2543Smrg		  lowestFreqErr = freqErr;
163706f2543Smrg		  /* Return if we found an exact match */
164706f2543Smrg		  if (freqErr == 0)
165706f2543Smrg		    return ActualClock;
166706f2543Smrg		}
167706f2543Smrg	    }
168706f2543Smrg	}
169706f2543Smrg    }
170706f2543Smrg
171706f2543Smrg  return ActualClock;
172706f2543Smrg}
173706f2543Smrg
174706f2543Smrgvoid
175706f2543SmrgIBMramdacRestore(ScrnInfoPtr pScrn, RamDacRecPtr ramdacPtr,
176706f2543Smrg				    RamDacRegRecPtr ramdacReg)
177706f2543Smrg{
178706f2543Smrg	int i, maxreg, dacreg;
179706f2543Smrg
180706f2543Smrg	switch (ramdacPtr->RamDacType) {
181706f2543Smrg	    case IBM640_RAMDAC:
182706f2543Smrg		maxreg = 0x300;
183706f2543Smrg		dacreg = 1024;
184706f2543Smrg		break;
185706f2543Smrg	    default:
186706f2543Smrg		maxreg = 0x100;
187706f2543Smrg		dacreg = 768;
188706f2543Smrg		break;
189706f2543Smrg	}
190706f2543Smrg
191706f2543Smrg	/* Here we pass a short, so that we can evaluate a mask too */
192706f2543Smrg	/* So that the mask is the high byte and the data the low byte */
193706f2543Smrg	for (i=0;i<maxreg;i++)
194706f2543Smrg	    (*ramdacPtr->WriteDAC)
195706f2543Smrg	        (pScrn, i, (ramdacReg->DacRegs[i] & 0xFF00) >> 8,
196706f2543Smrg						ramdacReg->DacRegs[i]);
197706f2543Smrg
198706f2543Smrg	(*ramdacPtr->WriteAddress)(pScrn, 0);
199706f2543Smrg	for (i=0;i<dacreg;i++)
200706f2543Smrg	    	(*ramdacPtr->WriteData)(pScrn, ramdacReg->DAC[i]);
201706f2543Smrg}
202706f2543Smrg
203706f2543Smrgvoid
204706f2543SmrgIBMramdacSave(ScrnInfoPtr pScrn, RamDacRecPtr ramdacPtr,
205706f2543Smrg				 RamDacRegRecPtr ramdacReg)
206706f2543Smrg{
207706f2543Smrg	int i, maxreg, dacreg;
208706f2543Smrg
209706f2543Smrg	switch (ramdacPtr->RamDacType) {
210706f2543Smrg	    case IBM640_RAMDAC:
211706f2543Smrg		maxreg = 0x300;
212706f2543Smrg		dacreg = 1024;
213706f2543Smrg		break;
214706f2543Smrg	    default:
215706f2543Smrg		maxreg = 0x100;
216706f2543Smrg		dacreg = 768;
217706f2543Smrg		break;
218706f2543Smrg	}
219706f2543Smrg
220706f2543Smrg	(*ramdacPtr->ReadAddress)(pScrn, 0);
221706f2543Smrg	for (i=0;i<dacreg;i++)
222706f2543Smrg	    ramdacReg->DAC[i] = (*ramdacPtr->ReadData)(pScrn);
223706f2543Smrg
224706f2543Smrg	for (i=0;i<maxreg;i++)
225706f2543Smrg	    ramdacReg->DacRegs[i] = (*ramdacPtr->ReadDAC)(pScrn, i);
226706f2543Smrg}
227706f2543Smrg
228706f2543SmrgRamDacHelperRecPtr
229706f2543SmrgIBMramdacProbe(ScrnInfoPtr pScrn, RamDacSupportedInfoRecPtr ramdacs/* , RamDacRecPtr ramdacPtr*/)
230706f2543Smrg{
231706f2543Smrg    RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
232706f2543Smrg    RamDacHelperRecPtr ramdacHelperPtr = NULL;
233706f2543Smrg    Bool RamDacIsSupported = FALSE;
234706f2543Smrg    int IBMramdac_ID = -1;
235706f2543Smrg    int i;
236706f2543Smrg    unsigned char id, rev, id2, rev2;
237706f2543Smrg
238706f2543Smrg    /* read ID and revision */
239706f2543Smrg    rev = (*ramdacPtr->ReadDAC)(pScrn, IBMRGB_rev);
240706f2543Smrg    id = (*ramdacPtr->ReadDAC)(pScrn, IBMRGB_id);
241706f2543Smrg
242706f2543Smrg    /* check if ID and revision are read only */
243706f2543Smrg    (*ramdacPtr->WriteDAC)(pScrn, ~rev, 0, IBMRGB_rev);
244706f2543Smrg    (*ramdacPtr->WriteDAC)(pScrn, ~id, 0, IBMRGB_id);
245706f2543Smrg    rev2 = (*ramdacPtr->ReadDAC)(pScrn, IBMRGB_rev);
246706f2543Smrg    id2 = (*ramdacPtr->ReadDAC)(pScrn, IBMRGB_id);
247706f2543Smrg
248706f2543Smrg    switch (id) {
249706f2543Smrg	case 0x30:
250706f2543Smrg		if (rev == 0xc0) IBMramdac_ID = IBM624_RAMDAC;
251706f2543Smrg		if (rev == 0x80) IBMramdac_ID = IBM624DB_RAMDAC;
252706f2543Smrg		break;
253706f2543Smrg	case 0x12:
254706f2543Smrg		if (rev == 0x1c) IBMramdac_ID = IBM640_RAMDAC;
255706f2543Smrg		break;
256706f2543Smrg	case 0x01:
257706f2543Smrg		IBMramdac_ID = IBM525_RAMDAC;
258706f2543Smrg		break;
259706f2543Smrg	case 0x02:
260706f2543Smrg		if (rev == 0xf0) IBMramdac_ID = IBM524_RAMDAC;
261706f2543Smrg		if (rev == 0xe0) IBMramdac_ID = IBM524A_RAMDAC;
262706f2543Smrg		if (rev == 0xc0) IBMramdac_ID = IBM526_RAMDAC;
263706f2543Smrg		if (rev == 0x80) IBMramdac_ID = IBM526DB_RAMDAC;
264706f2543Smrg		break;
265706f2543Smrg    }
266706f2543Smrg
267706f2543Smrg    if (id == 1 || id == 2) {
268706f2543Smrg        if (id == id2 && rev == rev2) {		/* IBM RGB52x found */
269706f2543Smrg	    /* check for 128bit VRAM -> RGB528 */
270706f2543Smrg	    if (((*ramdacPtr->ReadDAC)(pScrn, IBMRGB_misc1) & 0x03) == 0x03) {
271706f2543Smrg	        IBMramdac_ID = IBM528_RAMDAC;	/* 128bit DAC found */
272706f2543Smrg	        if (rev == 0xe0)
273706f2543Smrg		    IBMramdac_ID = IBM528A_RAMDAC;
274706f2543Smrg	    }
275706f2543Smrg        }
276706f2543Smrg    }
277706f2543Smrg
278706f2543Smrg    (*ramdacPtr->WriteDAC)(pScrn, rev, 0, IBMRGB_rev);
279706f2543Smrg    (*ramdacPtr->WriteDAC)(pScrn, id, 0, IBMRGB_id);
280706f2543Smrg
281706f2543Smrg    if (IBMramdac_ID == -1) {
282706f2543Smrg        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
283706f2543Smrg		"Cannot determine IBM RAMDAC type, aborting\n");
284706f2543Smrg	return NULL;
285706f2543Smrg    } else {
286706f2543Smrg        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
287706f2543Smrg		"Attached RAMDAC is %s\n", IBMramdacDeviceInfo[IBMramdac_ID&0xFFFF].DeviceName);
288706f2543Smrg    }
289706f2543Smrg
290706f2543Smrg    for (i=0;ramdacs[i].token != -1;i++) {
291706f2543Smrg	if (ramdacs[i].token == IBMramdac_ID)
292706f2543Smrg	    RamDacIsSupported = TRUE;
293706f2543Smrg    }
294706f2543Smrg
295706f2543Smrg    if (!RamDacIsSupported) {
296706f2543Smrg        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
297706f2543Smrg		"This IBM RAMDAC is NOT supported by this driver, aborting\n");
298706f2543Smrg	return NULL;
299706f2543Smrg    }
300706f2543Smrg
301706f2543Smrg    ramdacHelperPtr = RamDacHelperCreateInfoRec();
302706f2543Smrg    switch (IBMramdac_ID) {
303706f2543Smrg	case IBM526_RAMDAC:
304706f2543Smrg	case IBM526DB_RAMDAC:
305706f2543Smrg 	    ramdacHelperPtr->SetBpp = IBMramdac526SetBpp;
306706f2543Smrg    	    ramdacHelperPtr->HWCursorInit = IBMramdac526HWCursorInit;
307706f2543Smrg	    break;
308706f2543Smrg	case IBM640_RAMDAC:
309706f2543Smrg 	    ramdacHelperPtr->SetBpp = IBMramdac640SetBpp;
310706f2543Smrg    	    ramdacHelperPtr->HWCursorInit = IBMramdac640HWCursorInit;
311706f2543Smrg	    break;
312706f2543Smrg    }
313706f2543Smrg    ramdacPtr->RamDacType = IBMramdac_ID;
314706f2543Smrg    ramdacHelperPtr->RamDacType = IBMramdac_ID;
315706f2543Smrg    ramdacHelperPtr->Save = IBMramdacSave;
316706f2543Smrg    ramdacHelperPtr->Restore = IBMramdacRestore;
317706f2543Smrg
318706f2543Smrg    return ramdacHelperPtr;
319706f2543Smrg}
320706f2543Smrg
321706f2543Smrgvoid
322706f2543SmrgIBMramdac526SetBpp(ScrnInfoPtr pScrn, RamDacRegRecPtr ramdacReg)
323706f2543Smrg{
324706f2543Smrg    ramdacReg->DacRegs[IBMRGB_key_control] = 0x00; /* Disable Chroma Key */
325706f2543Smrg
326706f2543Smrg    switch (pScrn->bitsPerPixel) {
327706f2543Smrg	case 32:
328706f2543Smrg	    ramdacReg->DacRegs[IBMRGB_pix_fmt] = PIXEL_FORMAT_32BPP;
329706f2543Smrg	    ramdacReg->DacRegs[IBMRGB_32bpp] = B32_DCOL_DIRECT;
330706f2543Smrg	    ramdacReg->DacRegs[IBMRGB_24bpp] = 0;
331706f2543Smrg	    ramdacReg->DacRegs[IBMRGB_16bpp] = 0;
332706f2543Smrg	    ramdacReg->DacRegs[IBMRGB_8bpp] = 0;
333706f2543Smrg	    if (pScrn->overlayFlags & OVERLAY_8_32_PLANAR) {
334706f2543Smrg		ramdacReg->DacRegs[IBMRGB_key_control] = 0x01; /* Enable Key */
335706f2543Smrg		ramdacReg->DacRegs[IBMRGB_key] = 0xFF;
336706f2543Smrg		ramdacReg->DacRegs[IBMRGB_key_mask] = 0xFF;
337706f2543Smrg	    }
338706f2543Smrg	    break;
339706f2543Smrg	case 24:
340706f2543Smrg	    ramdacReg->DacRegs[IBMRGB_pix_fmt] = PIXEL_FORMAT_24BPP;
341706f2543Smrg	    ramdacReg->DacRegs[IBMRGB_32bpp] = 0;
342706f2543Smrg	    ramdacReg->DacRegs[IBMRGB_24bpp] = B24_DCOL_DIRECT;
343706f2543Smrg	    ramdacReg->DacRegs[IBMRGB_16bpp] = 0;
344706f2543Smrg	    ramdacReg->DacRegs[IBMRGB_8bpp] = 0;
345706f2543Smrg	    break;
346706f2543Smrg	case 16:
347706f2543Smrg	    if (pScrn->depth == 16) {
348706f2543Smrg	        ramdacReg->DacRegs[IBMRGB_pix_fmt] = PIXEL_FORMAT_16BPP;
349706f2543Smrg	        ramdacReg->DacRegs[IBMRGB_32bpp] = 0;
350706f2543Smrg	        ramdacReg->DacRegs[IBMRGB_24bpp] = 0;
351706f2543Smrg	        ramdacReg->DacRegs[IBMRGB_16bpp] = B16_DCOL_DIRECT|B16_LINEAR |
352706f2543Smrg					           B16_CONTIGUOUS | B16_565;
353706f2543Smrg	        ramdacReg->DacRegs[IBMRGB_8bpp] = 0;
354706f2543Smrg	    } else {
355706f2543Smrg	        ramdacReg->DacRegs[IBMRGB_pix_fmt] = PIXEL_FORMAT_16BPP;
356706f2543Smrg	        ramdacReg->DacRegs[IBMRGB_32bpp] = 0;
357706f2543Smrg	        ramdacReg->DacRegs[IBMRGB_24bpp] = 0;
358706f2543Smrg	        ramdacReg->DacRegs[IBMRGB_16bpp] = B16_DCOL_DIRECT|B16_LINEAR |
359706f2543Smrg					           B16_CONTIGUOUS | B16_555;
360706f2543Smrg	        ramdacReg->DacRegs[IBMRGB_8bpp] = 0;
361706f2543Smrg	    }
362706f2543Smrg	    break;
363706f2543Smrg	case 8:
364706f2543Smrg	    ramdacReg->DacRegs[IBMRGB_pix_fmt] = PIXEL_FORMAT_8BPP;
365706f2543Smrg	    ramdacReg->DacRegs[IBMRGB_32bpp] = 0;
366706f2543Smrg	    ramdacReg->DacRegs[IBMRGB_24bpp] = 0;
367706f2543Smrg	    ramdacReg->DacRegs[IBMRGB_16bpp] = 0;
368706f2543Smrg	    ramdacReg->DacRegs[IBMRGB_8bpp] = B8_DCOL_INDIRECT;
369706f2543Smrg	    break;
370706f2543Smrg	case 4:
371706f2543Smrg	    ramdacReg->DacRegs[IBMRGB_pix_fmt] = PIXEL_FORMAT_4BPP;
372706f2543Smrg	    ramdacReg->DacRegs[IBMRGB_32bpp] = 0;
373706f2543Smrg	    ramdacReg->DacRegs[IBMRGB_24bpp] = 0;
374706f2543Smrg	    ramdacReg->DacRegs[IBMRGB_16bpp] = 0;
375706f2543Smrg	    ramdacReg->DacRegs[IBMRGB_8bpp] = 0;
376706f2543Smrg    }
377706f2543Smrg}
378706f2543Smrg
379706f2543SmrgIBMramdac526SetBppProc *IBMramdac526SetBppWeak(void) {
380706f2543Smrg    return IBMramdac526SetBpp;
381706f2543Smrg}
382706f2543Smrg
383706f2543Smrgvoid
384706f2543SmrgIBMramdac640SetBpp(ScrnInfoPtr pScrn, RamDacRegRecPtr ramdacReg)
385706f2543Smrg{
386706f2543Smrg    unsigned char bpp = 0x00;
387706f2543Smrg    unsigned char overlaybpp = 0x00;
388706f2543Smrg    unsigned char offset = 0x00;
389706f2543Smrg    unsigned char dispcont = 0x44;
390706f2543Smrg
391706f2543Smrg    ramdacReg->DacRegs[RGB640_SER_WID_03_00] = 0x00;
392706f2543Smrg    ramdacReg->DacRegs[RGB640_SER_WID_07_04] = 0x00;
393706f2543Smrg    ramdacReg->DacRegs[RGB640_DIAGS] = 0x07;
394706f2543Smrg
395706f2543Smrg    switch (pScrn->depth) {
396706f2543Smrg	case 8:
397706f2543Smrg	    ramdacReg->DacRegs[RGB640_SER_07_00] = 0x00;
398706f2543Smrg	    ramdacReg->DacRegs[RGB640_SER_15_08] = 0x00;
399706f2543Smrg	    ramdacReg->DacRegs[RGB640_SER_23_16] = 0x00;
400706f2543Smrg	    ramdacReg->DacRegs[RGB640_SER_31_24] = 0x00;
401706f2543Smrg    	    ramdacReg->DacRegs[RGB640_SER_MODE] = IBM640_SER_16_1; /*16:1 Mux*/
402706f2543Smrg    	    ramdacReg->DacRegs[RGB640_MISC_CONF] = IBM640_PCLK_8; /* pll / 8 */
403706f2543Smrg	    bpp = 0x03;
404706f2543Smrg	    break;
405706f2543Smrg	case 15:
406706f2543Smrg	    ramdacReg->DacRegs[RGB640_SER_07_00] = 0x10;
407706f2543Smrg	    ramdacReg->DacRegs[RGB640_SER_15_08] = 0x11;
408706f2543Smrg	    ramdacReg->DacRegs[RGB640_SER_23_16] = 0x00;
409706f2543Smrg	    ramdacReg->DacRegs[RGB640_SER_31_24] = 0x00;
410706f2543Smrg    	    ramdacReg->DacRegs[RGB640_SER_MODE] = IBM640_SER_8_1; /* 8:1 Mux*/
411706f2543Smrg    	    ramdacReg->DacRegs[RGB640_MISC_CONF] = IBM640_PCLK_8; /* pll / 8 */
412706f2543Smrg	    bpp = 0x0E;
413706f2543Smrg	    break;
414706f2543Smrg	case 16:
415706f2543Smrg	    ramdacReg->DacRegs[RGB640_SER_07_00] = 0x10;
416706f2543Smrg	    ramdacReg->DacRegs[RGB640_SER_15_08] = 0x11;
417706f2543Smrg	    ramdacReg->DacRegs[RGB640_SER_23_16] = 0x00;
418706f2543Smrg	    ramdacReg->DacRegs[RGB640_SER_31_24] = 0x00;
419706f2543Smrg    	    ramdacReg->DacRegs[RGB640_SER_MODE] = IBM640_SER_8_1; /* 8:1 Mux*/
420706f2543Smrg    	    ramdacReg->DacRegs[RGB640_MISC_CONF] = IBM640_PCLK_8; /* pll / 8 */
421706f2543Smrg	    bpp = 0x05;
422706f2543Smrg	    break;
423706f2543Smrg	case 24:
424706f2543Smrg	    ramdacReg->DacRegs[RGB640_SER_07_00] = 0x30;
425706f2543Smrg	    ramdacReg->DacRegs[RGB640_SER_15_08] = 0x31;
426706f2543Smrg	    ramdacReg->DacRegs[RGB640_SER_23_16] = 0x32;
427706f2543Smrg	    ramdacReg->DacRegs[RGB640_SER_31_24] = 0x33;
428706f2543Smrg    	    ramdacReg->DacRegs[RGB640_SER_MODE] = IBM640_SER_4_1; /* 4:1 Mux*/
429706f2543Smrg    	    ramdacReg->DacRegs[RGB640_MISC_CONF] = IBM640_PCLK_8; /* pll / 8 */
430706f2543Smrg	    bpp = 0x09;
431706f2543Smrg	    if (pScrn->overlayFlags & OVERLAY_8_32_PLANAR) {
432706f2543Smrg		ramdacReg->DacRegs[RGB640_SER_WID_07_04] = 0x04;
433706f2543Smrg		ramdacReg->DacRegs[RGB640_CHROMA_KEY0] = 0xFF;
434706f2543Smrg		ramdacReg->DacRegs[RGB640_CHROMA_MASK0] = 0xFF;
435706f2543Smrg		offset = 0x04;
436706f2543Smrg		overlaybpp = 0x04;
437706f2543Smrg		dispcont = 0x48;
438706f2543Smrg	    }
439706f2543Smrg	    break;
440706f2543Smrg	case 30: /* 10 bit dac */
441706f2543Smrg	    ramdacReg->DacRegs[RGB640_SER_07_00] = 0x30;
442706f2543Smrg	    ramdacReg->DacRegs[RGB640_SER_15_08] = 0x31;
443706f2543Smrg	    ramdacReg->DacRegs[RGB640_SER_23_16] = 0x32;
444706f2543Smrg	    ramdacReg->DacRegs[RGB640_SER_31_24] = 0x33;
445706f2543Smrg    	    ramdacReg->DacRegs[RGB640_SER_MODE] = IBM640_SER_4_1; /* 4:1 Mux*/
446706f2543Smrg    	    ramdacReg->DacRegs[RGB640_MISC_CONF] = IBM640_PSIZE10 |
447706f2543Smrg						   IBM640_PCLK_8; /* pll / 8 */
448706f2543Smrg	    bpp = 0x0D;
449706f2543Smrg	    break;
450706f2543Smrg    }
451706f2543Smrg
452706f2543Smrg    {
453706f2543Smrg	int i;
454706f2543Smrg    	for (i=0x100;i<0x140;i+=4) {
455706f2543Smrg	    /* Initialize FrameBuffer Window Attribute Table */
456706f2543Smrg	    ramdacReg->DacRegs[i+0] = bpp;
457706f2543Smrg	    ramdacReg->DacRegs[i+1] = offset;
458706f2543Smrg	    ramdacReg->DacRegs[i+2] = 0x00;
459706f2543Smrg	    ramdacReg->DacRegs[i+3] = 0x00;
460706f2543Smrg	    /* Initialize Overlay Window Attribute Table */
461706f2543Smrg	    ramdacReg->DacRegs[i+0x100] = overlaybpp;
462706f2543Smrg	    ramdacReg->DacRegs[i+0x101] = 0x00;
463706f2543Smrg	    ramdacReg->DacRegs[i+0x102] = 0x00;
464706f2543Smrg	    ramdacReg->DacRegs[i+0x103] = dispcont;
465706f2543Smrg        }
466706f2543Smrg    }
467706f2543Smrg}
468706f2543Smrg
469706f2543Smrgstatic void
470706f2543SmrgIBMramdac526ShowCursor(ScrnInfoPtr pScrn)
471706f2543Smrg{
472706f2543Smrg   RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
473706f2543Smrg
474706f2543Smrg   /* Enable cursor - X11 mode */
475706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs, 0x00, 0x07);
476706f2543Smrg}
477706f2543Smrg
478706f2543Smrgstatic void
479706f2543SmrgIBMramdac640ShowCursor(ScrnInfoPtr pScrn)
480706f2543Smrg{
481706f2543Smrg   RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
482706f2543Smrg
483706f2543Smrg   /* Enable cursor - mode2 (x11 mode) */
484706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURSOR_CONTROL, 0x00, 0x0B);
485706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, RGB640_CROSSHAIR_CONTROL, 0x00, 0x00);
486706f2543Smrg}
487706f2543Smrg
488706f2543Smrgstatic void
489706f2543SmrgIBMramdac526HideCursor(ScrnInfoPtr pScrn)
490706f2543Smrg{
491706f2543Smrg   RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
492706f2543Smrg
493706f2543Smrg   /* Disable cursor - X11 mode */
494706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs, 0x00, 0x24);
495706f2543Smrg}
496706f2543Smrg
497706f2543Smrgstatic void
498706f2543SmrgIBMramdac640HideCursor(ScrnInfoPtr pScrn)
499706f2543Smrg{
500706f2543Smrg   RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
501706f2543Smrg
502706f2543Smrg   /* Disable cursor - mode2 (x11 mode) */
503706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURSOR_CONTROL, 0x00, 0x08);
504706f2543Smrg}
505706f2543Smrg
506706f2543Smrgstatic void
507706f2543SmrgIBMramdac526SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
508706f2543Smrg{
509706f2543Smrg   RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
510706f2543Smrg
511706f2543Smrg   x += 64;
512706f2543Smrg   y += 64;
513706f2543Smrg
514706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_hot_x, 0x00, 0x3f);
515706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_hot_y, 0x00, 0x3f);
516706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_xl, 0x00, x & 0xff);
517706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_xh, 0x00, (x>>8) & 0xf);
518706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_yl, 0x00, y & 0xff);
519706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_yh, 0x00, (y>>8) & 0xf);
520706f2543Smrg}
521706f2543Smrg
522706f2543Smrgstatic void
523706f2543SmrgIBMramdac640SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
524706f2543Smrg{
525706f2543Smrg   RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
526706f2543Smrg
527706f2543Smrg   x += 64;
528706f2543Smrg   y += 64;
529706f2543Smrg
530706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_OFFSETX, 0x00, 0x3f);
531706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_OFFSETY, 0x00, 0x3f);
532706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_X_LOW, 0x00, x & 0xff);
533706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_X_HIGH, 0x00, (x>>8) & 0xf);
534706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_Y_LOW, 0x00, y & 0xff);
535706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_Y_HIGH, 0x00, (y>>8) & 0xf);
536706f2543Smrg}
537706f2543Smrg
538706f2543Smrgstatic void
539706f2543SmrgIBMramdac526SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
540706f2543Smrg{
541706f2543Smrg   RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
542706f2543Smrg
543706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_col1_r, 0x00, bg >> 16);
544706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_col1_g, 0x00, bg >> 8);
545706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_col1_b, 0x00, bg);
546706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_col2_r, 0x00, fg >> 16);
547706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_col2_g, 0x00, fg >> 8);
548706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_col2_b, 0x00, fg);
549706f2543Smrg}
550706f2543Smrg
551706f2543Smrgstatic void
552706f2543SmrgIBMramdac640SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
553706f2543Smrg{
554706f2543Smrg   RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
555706f2543Smrg
556706f2543Smrg   (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_COL0, 0x00, 0);
557706f2543Smrg   (*ramdacPtr->WriteData)(pScrn, fg>>16);
558706f2543Smrg   (*ramdacPtr->WriteData)(pScrn, fg>>8);
559706f2543Smrg   (*ramdacPtr->WriteData)(pScrn, fg);
560706f2543Smrg   (*ramdacPtr->WriteData)(pScrn, bg>>16);
561706f2543Smrg   (*ramdacPtr->WriteData)(pScrn, bg>>8);
562706f2543Smrg   (*ramdacPtr->WriteData)(pScrn, bg);
563706f2543Smrg   (*ramdacPtr->WriteData)(pScrn, fg>>16);
564706f2543Smrg   (*ramdacPtr->WriteData)(pScrn, fg>>8);
565706f2543Smrg   (*ramdacPtr->WriteData)(pScrn, fg);
566706f2543Smrg   (*ramdacPtr->WriteData)(pScrn, bg>>16);
567706f2543Smrg   (*ramdacPtr->WriteData)(pScrn, bg>>8);
568706f2543Smrg   (*ramdacPtr->WriteData)(pScrn, bg);
569706f2543Smrg}
570706f2543Smrg
571706f2543Smrgstatic void
572706f2543SmrgIBMramdac526LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
573706f2543Smrg{
574706f2543Smrg   RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
575706f2543Smrg   int i;
576706f2543Smrg   /*
577706f2543Smrg    * Output the cursor data.  The realize function has put the planes into
578706f2543Smrg    * their correct order, so we can just blast this out.
579706f2543Smrg    */
580706f2543Smrg   for (i = 0; i < 1024; i++)
581706f2543Smrg      (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_array + i, 0x00, (*src++));
582706f2543Smrg}
583706f2543Smrg
584706f2543Smrgstatic void
585706f2543SmrgIBMramdac640LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
586706f2543Smrg{
587706f2543Smrg   RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
588706f2543Smrg   int i;
589706f2543Smrg   /*
590706f2543Smrg    * Output the cursor data.  The realize function has put the planes into
591706f2543Smrg    * their correct order, so we can just blast this out.
592706f2543Smrg    */
593706f2543Smrg   for (i = 0; i < 1024; i++)
594706f2543Smrg      (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_WRITE + i, 0x00, (*src++));
595706f2543Smrg}
596706f2543Smrg
597706f2543Smrgstatic Bool
598706f2543SmrgIBMramdac526UseHWCursor(ScreenPtr pScr, CursorPtr pCurs)
599706f2543Smrg{
600706f2543Smrg    return TRUE;
601706f2543Smrg}
602706f2543Smrg
603706f2543Smrgstatic Bool
604706f2543SmrgIBMramdac640UseHWCursor(ScreenPtr pScr, CursorPtr pCurs)
605706f2543Smrg{
606706f2543Smrg    return TRUE;
607706f2543Smrg}
608706f2543Smrg
609706f2543Smrgvoid
610706f2543SmrgIBMramdac526HWCursorInit(xf86CursorInfoPtr infoPtr)
611706f2543Smrg{
612706f2543Smrg    infoPtr->MaxWidth = 64;
613706f2543Smrg    infoPtr->MaxHeight = 64;
614706f2543Smrg    infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
615706f2543Smrg		     HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
616706f2543Smrg		     HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1;
617706f2543Smrg    infoPtr->SetCursorColors = IBMramdac526SetCursorColors;
618706f2543Smrg    infoPtr->SetCursorPosition = IBMramdac526SetCursorPosition;
619706f2543Smrg    infoPtr->LoadCursorImage = IBMramdac526LoadCursorImage;
620706f2543Smrg    infoPtr->HideCursor = IBMramdac526HideCursor;
621706f2543Smrg    infoPtr->ShowCursor = IBMramdac526ShowCursor;
622706f2543Smrg    infoPtr->UseHWCursor = IBMramdac526UseHWCursor;
623706f2543Smrg}
624706f2543Smrg
625706f2543Smrgvoid
626706f2543SmrgIBMramdac640HWCursorInit(xf86CursorInfoPtr infoPtr)
627706f2543Smrg{
628706f2543Smrg    infoPtr->MaxWidth = 64;
629706f2543Smrg    infoPtr->MaxHeight = 64;
630706f2543Smrg    infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
631706f2543Smrg		     HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
632706f2543Smrg		     HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1;
633706f2543Smrg    infoPtr->SetCursorColors = IBMramdac640SetCursorColors;
634706f2543Smrg    infoPtr->SetCursorPosition = IBMramdac640SetCursorPosition;
635706f2543Smrg    infoPtr->LoadCursorImage = IBMramdac640LoadCursorImage;
636706f2543Smrg    infoPtr->HideCursor = IBMramdac640HideCursor;
637706f2543Smrg    infoPtr->ShowCursor = IBMramdac640ShowCursor;
638706f2543Smrg    infoPtr->UseHWCursor = IBMramdac640UseHWCursor;
639706f2543Smrg}
640