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