1/*
2 * Copyright 1998 by Alan Hourihane, Wigan, England.
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 *
24 * IBM RAMDAC routines.
25 */
26
27#ifdef HAVE_XORG_CONFIG_H
28#include <xorg-config.h>
29#endif
30
31#include "xf86.h"
32#include "xf86_OSproc.h"
33
34#include "xf86Cursor.h"
35
36#define INIT_IBM_RAMDAC_INFO
37#include "IBMPriv.h"
38#include "xf86RamDacPriv.h"
39
40#define INITIALFREQERR 100000
41
42unsigned long
43IBMramdac640CalculateMNPCForClock(
44    unsigned long RefClock,	/* In 100Hz units */
45    unsigned long ReqClock,	/* In 100Hz units */
46    char IsPixClock,	/* boolean, is this the pixel or the sys clock */
47    unsigned long MinClock,	/* Min VCO rating */
48    unsigned long MaxClock,	/* Max VCO rating */
49    unsigned long *rM,	/* M Out */
50    unsigned long *rN,	/* N Out */
51    unsigned long *rP,	/* Min P In, P Out */
52    unsigned long *rC	/* C Out */
53)
54{
55  unsigned long   M, N, P, iP = *rP;
56  unsigned long   IntRef, VCO, Clock;
57  long            freqErr, lowestFreqErr = INITIALFREQERR;
58  unsigned long   ActualClock = 0;
59
60  for (N = 0; N <= 63; N++)
61    {
62      IntRef = RefClock / (N + 1);
63      if (IntRef < 10000)
64	break;			/* IntRef needs to be >= 1MHz */
65      for (M = 2; M <= 127; M++)
66	{
67	  VCO = IntRef * (M + 1);
68	  if ((VCO < MinClock) || (VCO > MaxClock))
69	    continue;
70	  for (P = iP; P <= 4; P++)
71	    {
72	      if (P != 0)
73		Clock = (RefClock * (M + 1)) / ((N + 1) * 2 * P);
74	      else
75		Clock = (RefClock * (M + 1)) / (N + 1);
76
77	      freqErr = (Clock - ReqClock);
78
79	      if (freqErr < 0)
80		{
81		  /* PixelClock gets rounded up always so monitor reports
82		     correct frequency. */
83		  if (IsPixClock)
84		    continue;
85		  freqErr = -freqErr;
86		}
87
88	      if (freqErr < lowestFreqErr)
89		{
90		  *rM = M;
91		  *rN = N;
92		  *rP = P;
93		  *rC = (VCO <= 1280000 ? 1 : 2);
94		  ActualClock = Clock;
95
96		  lowestFreqErr = freqErr;
97		  /* Return if we found an exact match */
98		  if (freqErr == 0)
99		    return ActualClock;
100		}
101	    }
102	}
103    }
104
105  return ActualClock;
106}
107
108unsigned long
109IBMramdac526CalculateMNPCForClock(
110    unsigned long RefClock,	/* In 100Hz units */
111    unsigned long ReqClock,	/* In 100Hz units */
112    char IsPixClock,	/* boolean, is this the pixel or the sys clock */
113    unsigned long MinClock,	/* Min VCO rating */
114    unsigned long MaxClock,	/* Max VCO rating */
115    unsigned long *rM,	/* M Out */
116    unsigned long *rN,	/* N Out */
117    unsigned long *rP,	/* Min P In, P Out */
118    unsigned long *rC	/* C Out */
119)
120{
121  unsigned long   M, N, P, iP = *rP;
122  unsigned long   IntRef, VCO, Clock;
123  long            freqErr, lowestFreqErr = INITIALFREQERR;
124  unsigned long   ActualClock = 0;
125
126  for (N = 0; N <= 63; N++)
127    {
128      IntRef = RefClock / (N + 1);
129      if (IntRef < 10000)
130	break;			/* IntRef needs to be >= 1MHz */
131      for (M = 0; M <= 63; M++)
132	{
133	  VCO = IntRef * (M + 1);
134	  if ((VCO < MinClock) || (VCO > MaxClock))
135	    continue;
136	  for (P = iP; P <= 4; P++)
137	    {
138	      if (P)
139		Clock = (RefClock * (M + 1)) / ((N + 1) * 2 * P);
140	      else
141		Clock = VCO;
142
143	      freqErr = (Clock - ReqClock);
144
145	      if (freqErr < 0)
146		{
147		  /* PixelClock gets rounded up always so monitor reports
148		     correct frequency. */
149		  if (IsPixClock)
150		    continue;
151		  freqErr = -freqErr;
152		}
153
154	      if (freqErr < lowestFreqErr)
155		{
156		  *rM = M;
157		  *rN = N;
158		  *rP = P;
159		  *rC = (VCO <= 1280000 ? 1 : 2);
160		  ActualClock = Clock;
161
162		  lowestFreqErr = freqErr;
163		  /* Return if we found an exact match */
164		  if (freqErr == 0)
165		    return ActualClock;
166		}
167	    }
168	}
169    }
170
171  return ActualClock;
172}
173
174void
175IBMramdacRestore(ScrnInfoPtr pScrn, RamDacRecPtr ramdacPtr,
176				    RamDacRegRecPtr ramdacReg)
177{
178	int i, maxreg, dacreg;
179
180	switch (ramdacPtr->RamDacType) {
181	    case IBM640_RAMDAC:
182		maxreg = 0x300;
183		dacreg = 1024;
184		break;
185	    default:
186		maxreg = 0x100;
187		dacreg = 768;
188		break;
189	}
190
191	/* Here we pass a short, so that we can evaluate a mask too */
192	/* So that the mask is the high byte and the data the low byte */
193	for (i=0;i<maxreg;i++)
194	    (*ramdacPtr->WriteDAC)
195	        (pScrn, i, (ramdacReg->DacRegs[i] & 0xFF00) >> 8,
196						ramdacReg->DacRegs[i]);
197
198	(*ramdacPtr->WriteAddress)(pScrn, 0);
199	for (i=0;i<dacreg;i++)
200	    	(*ramdacPtr->WriteData)(pScrn, ramdacReg->DAC[i]);
201}
202
203void
204IBMramdacSave(ScrnInfoPtr pScrn, RamDacRecPtr ramdacPtr,
205				 RamDacRegRecPtr ramdacReg)
206{
207	int i, maxreg, dacreg;
208
209	switch (ramdacPtr->RamDacType) {
210	    case IBM640_RAMDAC:
211		maxreg = 0x300;
212		dacreg = 1024;
213		break;
214	    default:
215		maxreg = 0x100;
216		dacreg = 768;
217		break;
218	}
219
220	(*ramdacPtr->ReadAddress)(pScrn, 0);
221	for (i=0;i<dacreg;i++)
222	    ramdacReg->DAC[i] = (*ramdacPtr->ReadData)(pScrn);
223
224	for (i=0;i<maxreg;i++)
225	    ramdacReg->DacRegs[i] = (*ramdacPtr->ReadDAC)(pScrn, i);
226}
227
228RamDacHelperRecPtr
229IBMramdacProbe(ScrnInfoPtr pScrn, RamDacSupportedInfoRecPtr ramdacs/* , RamDacRecPtr ramdacPtr*/)
230{
231    RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
232    RamDacHelperRecPtr ramdacHelperPtr = NULL;
233    Bool RamDacIsSupported = FALSE;
234    int IBMramdac_ID = -1;
235    int i;
236    unsigned char id, rev, id2, rev2;
237
238    /* read ID and revision */
239    rev = (*ramdacPtr->ReadDAC)(pScrn, IBMRGB_rev);
240    id = (*ramdacPtr->ReadDAC)(pScrn, IBMRGB_id);
241
242    /* check if ID and revision are read only */
243    (*ramdacPtr->WriteDAC)(pScrn, ~rev, 0, IBMRGB_rev);
244    (*ramdacPtr->WriteDAC)(pScrn, ~id, 0, IBMRGB_id);
245    rev2 = (*ramdacPtr->ReadDAC)(pScrn, IBMRGB_rev);
246    id2 = (*ramdacPtr->ReadDAC)(pScrn, IBMRGB_id);
247
248    switch (id) {
249	case 0x30:
250		if (rev == 0xc0) IBMramdac_ID = IBM624_RAMDAC;
251		if (rev == 0x80) IBMramdac_ID = IBM624DB_RAMDAC;
252		break;
253	case 0x12:
254		if (rev == 0x1c) IBMramdac_ID = IBM640_RAMDAC;
255		break;
256	case 0x01:
257		IBMramdac_ID = IBM525_RAMDAC;
258		break;
259	case 0x02:
260		if (rev == 0xf0) IBMramdac_ID = IBM524_RAMDAC;
261		if (rev == 0xe0) IBMramdac_ID = IBM524A_RAMDAC;
262		if (rev == 0xc0) IBMramdac_ID = IBM526_RAMDAC;
263		if (rev == 0x80) IBMramdac_ID = IBM526DB_RAMDAC;
264		break;
265    }
266
267    if (id == 1 || id == 2) {
268        if (id == id2 && rev == rev2) {		/* IBM RGB52x found */
269	    /* check for 128bit VRAM -> RGB528 */
270	    if (((*ramdacPtr->ReadDAC)(pScrn, IBMRGB_misc1) & 0x03) == 0x03) {
271	        IBMramdac_ID = IBM528_RAMDAC;	/* 128bit DAC found */
272	        if (rev == 0xe0)
273		    IBMramdac_ID = IBM528A_RAMDAC;
274	    }
275        }
276    }
277
278    (*ramdacPtr->WriteDAC)(pScrn, rev, 0, IBMRGB_rev);
279    (*ramdacPtr->WriteDAC)(pScrn, id, 0, IBMRGB_id);
280
281    if (IBMramdac_ID == -1) {
282        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
283		"Cannot determine IBM RAMDAC type, aborting\n");
284	return NULL;
285    } else {
286        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
287		"Attached RAMDAC is %s\n", IBMramdacDeviceInfo[IBMramdac_ID&0xFFFF].DeviceName);
288    }
289
290    for (i=0;ramdacs[i].token != -1;i++) {
291	if (ramdacs[i].token == IBMramdac_ID)
292	    RamDacIsSupported = TRUE;
293    }
294
295    if (!RamDacIsSupported) {
296        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
297		"This IBM RAMDAC is NOT supported by this driver, aborting\n");
298	return NULL;
299    }
300
301    ramdacHelperPtr = RamDacHelperCreateInfoRec();
302    switch (IBMramdac_ID) {
303	case IBM526_RAMDAC:
304	case IBM526DB_RAMDAC:
305 	    ramdacHelperPtr->SetBpp = IBMramdac526SetBpp;
306    	    ramdacHelperPtr->HWCursorInit = IBMramdac526HWCursorInit;
307	    break;
308	case IBM640_RAMDAC:
309 	    ramdacHelperPtr->SetBpp = IBMramdac640SetBpp;
310    	    ramdacHelperPtr->HWCursorInit = IBMramdac640HWCursorInit;
311	    break;
312    }
313    ramdacPtr->RamDacType = IBMramdac_ID;
314    ramdacHelperPtr->RamDacType = IBMramdac_ID;
315    ramdacHelperPtr->Save = IBMramdacSave;
316    ramdacHelperPtr->Restore = IBMramdacRestore;
317
318    return ramdacHelperPtr;
319}
320
321void
322IBMramdac526SetBpp(ScrnInfoPtr pScrn, RamDacRegRecPtr ramdacReg)
323{
324    ramdacReg->DacRegs[IBMRGB_key_control] = 0x00; /* Disable Chroma Key */
325
326    switch (pScrn->bitsPerPixel) {
327	case 32:
328	    ramdacReg->DacRegs[IBMRGB_pix_fmt] = PIXEL_FORMAT_32BPP;
329	    ramdacReg->DacRegs[IBMRGB_32bpp] = B32_DCOL_DIRECT;
330	    ramdacReg->DacRegs[IBMRGB_24bpp] = 0;
331	    ramdacReg->DacRegs[IBMRGB_16bpp] = 0;
332	    ramdacReg->DacRegs[IBMRGB_8bpp] = 0;
333	    if (pScrn->overlayFlags & OVERLAY_8_32_PLANAR) {
334		ramdacReg->DacRegs[IBMRGB_key_control] = 0x01; /* Enable Key */
335		ramdacReg->DacRegs[IBMRGB_key] = 0xFF;
336		ramdacReg->DacRegs[IBMRGB_key_mask] = 0xFF;
337	    }
338	    break;
339	case 24:
340	    ramdacReg->DacRegs[IBMRGB_pix_fmt] = PIXEL_FORMAT_24BPP;
341	    ramdacReg->DacRegs[IBMRGB_32bpp] = 0;
342	    ramdacReg->DacRegs[IBMRGB_24bpp] = B24_DCOL_DIRECT;
343	    ramdacReg->DacRegs[IBMRGB_16bpp] = 0;
344	    ramdacReg->DacRegs[IBMRGB_8bpp] = 0;
345	    break;
346	case 16:
347	    if (pScrn->depth == 16) {
348	        ramdacReg->DacRegs[IBMRGB_pix_fmt] = PIXEL_FORMAT_16BPP;
349	        ramdacReg->DacRegs[IBMRGB_32bpp] = 0;
350	        ramdacReg->DacRegs[IBMRGB_24bpp] = 0;
351	        ramdacReg->DacRegs[IBMRGB_16bpp] = B16_DCOL_DIRECT|B16_LINEAR |
352					           B16_CONTIGUOUS | B16_565;
353	        ramdacReg->DacRegs[IBMRGB_8bpp] = 0;
354	    } else {
355	        ramdacReg->DacRegs[IBMRGB_pix_fmt] = PIXEL_FORMAT_16BPP;
356	        ramdacReg->DacRegs[IBMRGB_32bpp] = 0;
357	        ramdacReg->DacRegs[IBMRGB_24bpp] = 0;
358	        ramdacReg->DacRegs[IBMRGB_16bpp] = B16_DCOL_DIRECT|B16_LINEAR |
359					           B16_CONTIGUOUS | B16_555;
360	        ramdacReg->DacRegs[IBMRGB_8bpp] = 0;
361	    }
362	    break;
363	case 8:
364	    ramdacReg->DacRegs[IBMRGB_pix_fmt] = PIXEL_FORMAT_8BPP;
365	    ramdacReg->DacRegs[IBMRGB_32bpp] = 0;
366	    ramdacReg->DacRegs[IBMRGB_24bpp] = 0;
367	    ramdacReg->DacRegs[IBMRGB_16bpp] = 0;
368	    ramdacReg->DacRegs[IBMRGB_8bpp] = B8_DCOL_INDIRECT;
369	    break;
370	case 4:
371	    ramdacReg->DacRegs[IBMRGB_pix_fmt] = PIXEL_FORMAT_4BPP;
372	    ramdacReg->DacRegs[IBMRGB_32bpp] = 0;
373	    ramdacReg->DacRegs[IBMRGB_24bpp] = 0;
374	    ramdacReg->DacRegs[IBMRGB_16bpp] = 0;
375	    ramdacReg->DacRegs[IBMRGB_8bpp] = 0;
376    }
377}
378
379IBMramdac526SetBppProc *IBMramdac526SetBppWeak(void) {
380    return IBMramdac526SetBpp;
381}
382
383void
384IBMramdac640SetBpp(ScrnInfoPtr pScrn, RamDacRegRecPtr ramdacReg)
385{
386    unsigned char bpp = 0x00;
387    unsigned char overlaybpp = 0x00;
388    unsigned char offset = 0x00;
389    unsigned char dispcont = 0x44;
390
391    ramdacReg->DacRegs[RGB640_SER_WID_03_00] = 0x00;
392    ramdacReg->DacRegs[RGB640_SER_WID_07_04] = 0x00;
393    ramdacReg->DacRegs[RGB640_DIAGS] = 0x07;
394
395    switch (pScrn->depth) {
396	case 8:
397	    ramdacReg->DacRegs[RGB640_SER_07_00] = 0x00;
398	    ramdacReg->DacRegs[RGB640_SER_15_08] = 0x00;
399	    ramdacReg->DacRegs[RGB640_SER_23_16] = 0x00;
400	    ramdacReg->DacRegs[RGB640_SER_31_24] = 0x00;
401    	    ramdacReg->DacRegs[RGB640_SER_MODE] = IBM640_SER_16_1; /*16:1 Mux*/
402    	    ramdacReg->DacRegs[RGB640_MISC_CONF] = IBM640_PCLK_8; /* pll / 8 */
403	    bpp = 0x03;
404	    break;
405	case 15:
406	    ramdacReg->DacRegs[RGB640_SER_07_00] = 0x10;
407	    ramdacReg->DacRegs[RGB640_SER_15_08] = 0x11;
408	    ramdacReg->DacRegs[RGB640_SER_23_16] = 0x00;
409	    ramdacReg->DacRegs[RGB640_SER_31_24] = 0x00;
410    	    ramdacReg->DacRegs[RGB640_SER_MODE] = IBM640_SER_8_1; /* 8:1 Mux*/
411    	    ramdacReg->DacRegs[RGB640_MISC_CONF] = IBM640_PCLK_8; /* pll / 8 */
412	    bpp = 0x0E;
413	    break;
414	case 16:
415	    ramdacReg->DacRegs[RGB640_SER_07_00] = 0x10;
416	    ramdacReg->DacRegs[RGB640_SER_15_08] = 0x11;
417	    ramdacReg->DacRegs[RGB640_SER_23_16] = 0x00;
418	    ramdacReg->DacRegs[RGB640_SER_31_24] = 0x00;
419    	    ramdacReg->DacRegs[RGB640_SER_MODE] = IBM640_SER_8_1; /* 8:1 Mux*/
420    	    ramdacReg->DacRegs[RGB640_MISC_CONF] = IBM640_PCLK_8; /* pll / 8 */
421	    bpp = 0x05;
422	    break;
423	case 24:
424	    ramdacReg->DacRegs[RGB640_SER_07_00] = 0x30;
425	    ramdacReg->DacRegs[RGB640_SER_15_08] = 0x31;
426	    ramdacReg->DacRegs[RGB640_SER_23_16] = 0x32;
427	    ramdacReg->DacRegs[RGB640_SER_31_24] = 0x33;
428    	    ramdacReg->DacRegs[RGB640_SER_MODE] = IBM640_SER_4_1; /* 4:1 Mux*/
429    	    ramdacReg->DacRegs[RGB640_MISC_CONF] = IBM640_PCLK_8; /* pll / 8 */
430	    bpp = 0x09;
431	    if (pScrn->overlayFlags & OVERLAY_8_32_PLANAR) {
432		ramdacReg->DacRegs[RGB640_SER_WID_07_04] = 0x04;
433		ramdacReg->DacRegs[RGB640_CHROMA_KEY0] = 0xFF;
434		ramdacReg->DacRegs[RGB640_CHROMA_MASK0] = 0xFF;
435		offset = 0x04;
436		overlaybpp = 0x04;
437		dispcont = 0x48;
438	    }
439	    break;
440	case 30: /* 10 bit dac */
441	    ramdacReg->DacRegs[RGB640_SER_07_00] = 0x30;
442	    ramdacReg->DacRegs[RGB640_SER_15_08] = 0x31;
443	    ramdacReg->DacRegs[RGB640_SER_23_16] = 0x32;
444	    ramdacReg->DacRegs[RGB640_SER_31_24] = 0x33;
445    	    ramdacReg->DacRegs[RGB640_SER_MODE] = IBM640_SER_4_1; /* 4:1 Mux*/
446    	    ramdacReg->DacRegs[RGB640_MISC_CONF] = IBM640_PSIZE10 |
447						   IBM640_PCLK_8; /* pll / 8 */
448	    bpp = 0x0D;
449	    break;
450    }
451
452    {
453	int i;
454    	for (i=0x100;i<0x140;i+=4) {
455	    /* Initialize FrameBuffer Window Attribute Table */
456	    ramdacReg->DacRegs[i+0] = bpp;
457	    ramdacReg->DacRegs[i+1] = offset;
458	    ramdacReg->DacRegs[i+2] = 0x00;
459	    ramdacReg->DacRegs[i+3] = 0x00;
460	    /* Initialize Overlay Window Attribute Table */
461	    ramdacReg->DacRegs[i+0x100] = overlaybpp;
462	    ramdacReg->DacRegs[i+0x101] = 0x00;
463	    ramdacReg->DacRegs[i+0x102] = 0x00;
464	    ramdacReg->DacRegs[i+0x103] = dispcont;
465        }
466    }
467}
468
469static void
470IBMramdac526ShowCursor(ScrnInfoPtr pScrn)
471{
472   RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
473
474   /* Enable cursor - X11 mode */
475   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs, 0x00, 0x07);
476}
477
478static void
479IBMramdac640ShowCursor(ScrnInfoPtr pScrn)
480{
481   RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
482
483   /* Enable cursor - mode2 (x11 mode) */
484   (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURSOR_CONTROL, 0x00, 0x0B);
485   (*ramdacPtr->WriteDAC)(pScrn, RGB640_CROSSHAIR_CONTROL, 0x00, 0x00);
486}
487
488static void
489IBMramdac526HideCursor(ScrnInfoPtr pScrn)
490{
491   RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
492
493   /* Disable cursor - X11 mode */
494   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs, 0x00, 0x24);
495}
496
497static void
498IBMramdac640HideCursor(ScrnInfoPtr pScrn)
499{
500   RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
501
502   /* Disable cursor - mode2 (x11 mode) */
503   (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURSOR_CONTROL, 0x00, 0x08);
504}
505
506static void
507IBMramdac526SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
508{
509   RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
510
511   x += 64;
512   y += 64;
513
514   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_hot_x, 0x00, 0x3f);
515   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_hot_y, 0x00, 0x3f);
516   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_xl, 0x00, x & 0xff);
517   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_xh, 0x00, (x>>8) & 0xf);
518   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_yl, 0x00, y & 0xff);
519   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_yh, 0x00, (y>>8) & 0xf);
520}
521
522static void
523IBMramdac640SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
524{
525   RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
526
527   x += 64;
528   y += 64;
529
530   (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_OFFSETX, 0x00, 0x3f);
531   (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_OFFSETY, 0x00, 0x3f);
532   (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_X_LOW, 0x00, x & 0xff);
533   (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_X_HIGH, 0x00, (x>>8) & 0xf);
534   (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_Y_LOW, 0x00, y & 0xff);
535   (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_Y_HIGH, 0x00, (y>>8) & 0xf);
536}
537
538static void
539IBMramdac526SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
540{
541   RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
542
543   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_col1_r, 0x00, bg >> 16);
544   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_col1_g, 0x00, bg >> 8);
545   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_col1_b, 0x00, bg);
546   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_col2_r, 0x00, fg >> 16);
547   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_col2_g, 0x00, fg >> 8);
548   (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_col2_b, 0x00, fg);
549}
550
551static void
552IBMramdac640SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
553{
554   RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
555
556   (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_COL0, 0x00, 0);
557   (*ramdacPtr->WriteData)(pScrn, fg>>16);
558   (*ramdacPtr->WriteData)(pScrn, fg>>8);
559   (*ramdacPtr->WriteData)(pScrn, fg);
560   (*ramdacPtr->WriteData)(pScrn, bg>>16);
561   (*ramdacPtr->WriteData)(pScrn, bg>>8);
562   (*ramdacPtr->WriteData)(pScrn, bg);
563   (*ramdacPtr->WriteData)(pScrn, fg>>16);
564   (*ramdacPtr->WriteData)(pScrn, fg>>8);
565   (*ramdacPtr->WriteData)(pScrn, fg);
566   (*ramdacPtr->WriteData)(pScrn, bg>>16);
567   (*ramdacPtr->WriteData)(pScrn, bg>>8);
568   (*ramdacPtr->WriteData)(pScrn, bg);
569}
570
571static void
572IBMramdac526LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
573{
574   RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
575   int i;
576   /*
577    * Output the cursor data.  The realize function has put the planes into
578    * their correct order, so we can just blast this out.
579    */
580   for (i = 0; i < 1024; i++)
581      (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_array + i, 0x00, (*src++));
582}
583
584static void
585IBMramdac640LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
586{
587   RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
588   int i;
589   /*
590    * Output the cursor data.  The realize function has put the planes into
591    * their correct order, so we can just blast this out.
592    */
593   for (i = 0; i < 1024; i++)
594      (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_WRITE + i, 0x00, (*src++));
595}
596
597static Bool
598IBMramdac526UseHWCursor(ScreenPtr pScr, CursorPtr pCurs)
599{
600    return TRUE;
601}
602
603static Bool
604IBMramdac640UseHWCursor(ScreenPtr pScr, CursorPtr pCurs)
605{
606    return TRUE;
607}
608
609void
610IBMramdac526HWCursorInit(xf86CursorInfoPtr infoPtr)
611{
612    infoPtr->MaxWidth = 64;
613    infoPtr->MaxHeight = 64;
614    infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
615		     HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
616		     HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1;
617    infoPtr->SetCursorColors = IBMramdac526SetCursorColors;
618    infoPtr->SetCursorPosition = IBMramdac526SetCursorPosition;
619    infoPtr->LoadCursorImage = IBMramdac526LoadCursorImage;
620    infoPtr->HideCursor = IBMramdac526HideCursor;
621    infoPtr->ShowCursor = IBMramdac526ShowCursor;
622    infoPtr->UseHWCursor = IBMramdac526UseHWCursor;
623}
624
625void
626IBMramdac640HWCursorInit(xf86CursorInfoPtr infoPtr)
627{
628    infoPtr->MaxWidth = 64;
629    infoPtr->MaxHeight = 64;
630    infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
631		     HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
632		     HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1;
633    infoPtr->SetCursorColors = IBMramdac640SetCursorColors;
634    infoPtr->SetCursorPosition = IBMramdac640SetCursorPosition;
635    infoPtr->LoadCursorImage = IBMramdac640LoadCursorImage;
636    infoPtr->HideCursor = IBMramdac640HideCursor;
637    infoPtr->ShowCursor = IBMramdac640ShowCursor;
638    infoPtr->UseHWCursor = IBMramdac640UseHWCursor;
639}
640