xref: /OK3568_Linux_fs/external/xserver/hw/xfree86/ramdac/TI.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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  * Modified from IBM.c to support TI RAMDAC routines
25  *   by Jens Owen, <jens@tungstengraphics.com>.
26  */
27 
28 #ifdef HAVE_XORG_CONFIG_H
29 #include <xorg-config.h>
30 #endif
31 
32 #include "xf86.h"
33 #include "xf86_OSproc.h"
34 
35 #include "xf86Cursor.h"
36 
37 #define INIT_TI_RAMDAC_INFO
38 #include "TIPriv.h"
39 #include "xf86RamDacPriv.h"
40 
41 /* The following values are in kHz */
42 #define TI_MIN_VCO_FREQ  110000
43 #define TI_MAX_VCO_FREQ  220000
44 
45 unsigned long
TIramdacCalculateMNPForClock(unsigned long RefClock,unsigned long ReqClock,char IsPixClock,unsigned long MinClock,unsigned long MaxClock,unsigned long * rM,unsigned long * rN,unsigned long * rP)46 TIramdacCalculateMNPForClock(unsigned long RefClock,    /* In 100Hz units */
47                              unsigned long ReqClock,    /* In 100Hz units */
48                              char IsPixClock,   /* boolean, is this the pixel or the sys clock */
49                              unsigned long MinClock,    /* Min VCO rating */
50                              unsigned long MaxClock,    /* Max VCO rating */
51                              unsigned long *rM, /* M Out */
52                              unsigned long *rN, /* N Out */
53                              unsigned long *rP  /* Min P In, P Out */
54     )
55 {
56     unsigned long n, p;
57     unsigned long best_m = 0, best_n = 0;
58     double VCO, IntRef = (double) RefClock;
59     double m_err, inc_m, calc_m;
60     unsigned long ActualClock;
61 
62     /* Make sure that MinClock <= ReqClock <= MaxClock */
63     if (ReqClock < MinClock)
64         ReqClock = MinClock;
65     if (ReqClock > MaxClock)
66         ReqClock = MaxClock;
67 
68     /*
69      * ActualClock = VCO / 2 ^ p
70      * Choose p so that TI_MIN_VCO_FREQ <= VCO <= TI_MAX_VCO_FREQ
71      * Note that since TI_MAX_VCO_FREQ = 2 * TI_MIN_VCO_FREQ
72      * we don't have to bother checking for this maximum limit.
73      */
74     VCO = (double) ReqClock;
75     for (p = 0; p < 3 && VCO < TI_MIN_VCO_FREQ; (p)++)
76         VCO *= 2.0;
77 
78     /*
79      * We avoid doing multiplications by ( 65 - n ),
80      * and add an increment instead - this keeps any error small.
81      */
82     inc_m = VCO / (IntRef * 8.0);
83 
84     /* Initial value of calc_m for the loop */
85     calc_m = inc_m + inc_m + inc_m;
86 
87     /* Initial amount of error for an integer - impossibly large */
88     m_err = 2.0;
89 
90     /* Search for the closest INTEGER value of ( 65 - m ) */
91     for (n = 3; n <= 25; (n)++, calc_m += inc_m) {
92 
93         /* Ignore values of ( 65 - m ) which we can't use */
94         if (calc_m < 3.0 || calc_m > 64.0)
95             continue;
96 
97         /*
98          * Pick the closest INTEGER (has smallest fractional part).
99          * The optimizer should clean this up for us.
100          */
101         if ((calc_m - (int) calc_m) < m_err) {
102             m_err = calc_m - (int) calc_m;
103             best_m = (int) calc_m;
104             best_n = n;
105         }
106     }
107 
108     /* 65 - ( 65 - x ) = x */
109     *rM = 65 - best_m;
110     *rN = 65 - best_n;
111     *rP = p;
112 
113     /* Now all the calculations can be completed */
114     VCO = 8.0 * IntRef * best_m / best_n;
115     ActualClock = VCO / (1 << p);
116 
117     DebugF("f_out=%ld f_vco=%.1f n=%lu m=%lu p=%lu\n",
118            ActualClock, VCO, *rN, *rM, *rP);
119 
120     return ActualClock;
121 }
122 
123 void
TIramdacRestore(ScrnInfoPtr pScrn,RamDacRecPtr ramdacPtr,RamDacRegRecPtr ramdacReg)124 TIramdacRestore(ScrnInfoPtr pScrn, RamDacRecPtr ramdacPtr,
125                 RamDacRegRecPtr ramdacReg)
126 {
127     int i;
128     unsigned long status;
129 
130     /* Here we pass a short, so that we can evaluate a mask too
131      * So that the mask is the high byte and the data the low byte
132      * Order is important
133      */
134     TIRESTORE(TIDAC_latch_ctrl);
135     TIRESTORE(TIDAC_true_color_ctrl);
136     TIRESTORE(TIDAC_multiplex_ctrl);
137     TIRESTORE(TIDAC_clock_select);
138     TIRESTORE(TIDAC_palette_page);
139     TIRESTORE(TIDAC_general_ctrl);
140     TIRESTORE(TIDAC_misc_ctrl);
141     /* 0x2A & 0x2B are reserved */
142     TIRESTORE(TIDAC_key_over_low);
143     TIRESTORE(TIDAC_key_over_high);
144     TIRESTORE(TIDAC_key_red_low);
145     TIRESTORE(TIDAC_key_red_high);
146     TIRESTORE(TIDAC_key_green_low);
147     TIRESTORE(TIDAC_key_green_high);
148     TIRESTORE(TIDAC_key_blue_low);
149     TIRESTORE(TIDAC_key_blue_high);
150     TIRESTORE(TIDAC_key_ctrl);
151     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_clock_ctrl, 0, 0x30);
152     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_clock_ctrl, 0, 0x38);
153     TIRESTORE(TIDAC_clock_ctrl);
154     TIRESTORE(TIDAC_sense_test);
155     TIRESTORE(TIDAC_ind_curs_ctrl);
156 
157     /* only restore clocks if they were valid to begin with */
158 
159     if (ramdacReg->DacRegs[TIDAC_PIXEL_VALID]) {
160         /* Reset pixel clock */
161         (*ramdacPtr->WriteDAC) (pScrn, TIDAC_pll_addr, 0, 0x22);
162         (*ramdacPtr->WriteDAC) (pScrn, TIDAC_pll_pixel_data, 0, 0x3c);
163 
164         /* Restore N, M & P values for pixel clocks */
165         (*ramdacPtr->WriteDAC) (pScrn, TIDAC_pll_addr, 0, 0);
166         (*ramdacPtr->WriteDAC) (pScrn, TIDAC_pll_pixel_data, 0,
167                                 ramdacReg->DacRegs[TIDAC_PIXEL_N]);
168         (*ramdacPtr->WriteDAC) (pScrn, TIDAC_pll_pixel_data, 0,
169                                 ramdacReg->DacRegs[TIDAC_PIXEL_M]);
170         (*ramdacPtr->WriteDAC) (pScrn, TIDAC_pll_pixel_data, 0,
171                                 ramdacReg->DacRegs[TIDAC_PIXEL_P]);
172 
173         /* wait for pixel clock to lock */
174         i = 1000000;
175         do {
176             status = (*ramdacPtr->ReadDAC) (pScrn, TIDAC_pll_pixel_data);
177         } while ((!(status & 0x40)) && (--i));
178         if (!(status & 0x40)) {
179             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
180                        "Pixel clock setup timed out\n");
181             return;
182         }
183     }
184 
185     if (ramdacReg->DacRegs[TIDAC_LOOP_VALID]) {
186         /* Reset loop clock */
187         (*ramdacPtr->WriteDAC) (pScrn, TIDAC_pll_addr, 0, 0x22);
188         (*ramdacPtr->WriteDAC) (pScrn, TIDAC_pll_loop_data, 0, 0x70);
189 
190         /* Restore N, M & P values for pixel clocks */
191         (*ramdacPtr->WriteDAC) (pScrn, TIDAC_pll_addr, 0, 0);
192         (*ramdacPtr->WriteDAC) (pScrn, TIDAC_pll_loop_data, 0,
193                                 ramdacReg->DacRegs[TIDAC_LOOP_N]);
194         (*ramdacPtr->WriteDAC) (pScrn, TIDAC_pll_loop_data, 0,
195                                 ramdacReg->DacRegs[TIDAC_LOOP_M]);
196         (*ramdacPtr->WriteDAC) (pScrn, TIDAC_pll_loop_data, 0,
197                                 ramdacReg->DacRegs[TIDAC_LOOP_P]);
198 
199         /* wait for loop clock to lock */
200         i = 1000000;
201         do {
202             status = (*ramdacPtr->ReadDAC) (pScrn, TIDAC_pll_loop_data);
203         } while ((!(status & 0x40)) && (--i));
204         if (!(status & 0x40)) {
205             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
206                        "Loop clock setup timed out\n");
207             return;
208         }
209     }
210 
211     /* restore palette */
212     (*ramdacPtr->WriteAddress) (pScrn, 0);
213 #ifndef NOT_DONE
214     for (i = 0; i < 768; i++)
215         (*ramdacPtr->WriteData) (pScrn, ramdacReg->DAC[i]);
216 #else
217     (*ramdacPtr->WriteData) (pScrn, 0);
218     (*ramdacPtr->WriteData) (pScrn, 0);
219     (*ramdacPtr->WriteData) (pScrn, 0);
220     for (i = 0; i < 765; i++)
221         (*ramdacPtr->WriteData) (pScrn, 0xff);
222 #endif
223 }
224 
225 void
TIramdacSave(ScrnInfoPtr pScrn,RamDacRecPtr ramdacPtr,RamDacRegRecPtr ramdacReg)226 TIramdacSave(ScrnInfoPtr pScrn, RamDacRecPtr ramdacPtr,
227              RamDacRegRecPtr ramdacReg)
228 {
229     int i;
230 
231     (*ramdacPtr->ReadAddress) (pScrn, 0);
232     for (i = 0; i < 768; i++)
233         ramdacReg->DAC[i] = (*ramdacPtr->ReadData) (pScrn);
234 
235     /* Read back N,M and P values for pixel clock */
236     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_pll_addr, 0, 0);
237     ramdacReg->DacRegs[TIDAC_PIXEL_N] =
238         (*ramdacPtr->ReadDAC) (pScrn, TIDAC_pll_pixel_data);
239     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_pll_addr, 0, 0x11);
240     ramdacReg->DacRegs[TIDAC_PIXEL_M] =
241         (*ramdacPtr->ReadDAC) (pScrn, TIDAC_pll_pixel_data);
242     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_pll_addr, 0, 0x22);
243     ramdacReg->DacRegs[TIDAC_PIXEL_P] =
244         (*ramdacPtr->ReadDAC) (pScrn, TIDAC_pll_pixel_data);
245 
246     /* Read back N,M and P values for loop clock */
247     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_pll_addr, 0, 0);
248     ramdacReg->DacRegs[TIDAC_LOOP_N] =
249         (*ramdacPtr->ReadDAC) (pScrn, TIDAC_pll_loop_data);
250     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_pll_addr, 0, 0x11);
251     ramdacReg->DacRegs[TIDAC_LOOP_M] =
252         (*ramdacPtr->ReadDAC) (pScrn, TIDAC_pll_loop_data);
253     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_pll_addr, 0, 0x22);
254     ramdacReg->DacRegs[TIDAC_LOOP_P] =
255         (*ramdacPtr->ReadDAC) (pScrn, TIDAC_pll_loop_data);
256 
257     /* Order is important */
258     TISAVE(TIDAC_latch_ctrl);
259     TISAVE(TIDAC_true_color_ctrl);
260     TISAVE(TIDAC_multiplex_ctrl);
261     TISAVE(TIDAC_clock_select);
262     TISAVE(TIDAC_palette_page);
263     TISAVE(TIDAC_general_ctrl);
264     TISAVE(TIDAC_misc_ctrl);
265     /* 0x2A & 0x2B are reserved */
266     TISAVE(TIDAC_key_over_low);
267     TISAVE(TIDAC_key_over_high);
268     TISAVE(TIDAC_key_red_low);
269     TISAVE(TIDAC_key_red_high);
270     TISAVE(TIDAC_key_green_low);
271     TISAVE(TIDAC_key_green_high);
272     TISAVE(TIDAC_key_blue_low);
273     TISAVE(TIDAC_key_blue_high);
274     TISAVE(TIDAC_key_ctrl);
275     TISAVE(TIDAC_clock_ctrl);
276     TISAVE(TIDAC_sense_test);
277     TISAVE(TIDAC_ind_curs_ctrl);
278 }
279 
280 RamDacHelperRecPtr
TIramdacProbe(ScrnInfoPtr pScrn,RamDacSupportedInfoRecPtr ramdacs)281 TIramdacProbe(ScrnInfoPtr pScrn, RamDacSupportedInfoRecPtr ramdacs)
282 {
283     RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
284     RamDacHelperRecPtr ramdacHelperPtr = NULL;
285     Bool RamDacIsSupported = FALSE;
286     int TIramdac_ID = -1;
287     int i;
288     unsigned char id, rev, rev2, id2;
289 
290     /* read ID and revision */
291     rev = (*ramdacPtr->ReadDAC) (pScrn, TIDAC_rev);
292     id = (*ramdacPtr->ReadDAC) (pScrn, TIDAC_id);
293 
294     /* check if ID and revision are read only */
295     (*ramdacPtr->WriteDAC) (pScrn, ~rev, 0, TIDAC_rev);
296     (*ramdacPtr->WriteDAC) (pScrn, ~id, 0, TIDAC_id);
297     rev2 = (*ramdacPtr->ReadDAC) (pScrn, TIDAC_rev);
298     id2 = (*ramdacPtr->ReadDAC) (pScrn, TIDAC_id);
299 
300     switch (id) {
301     case TIDAC_TVP_3030_ID:
302         if (id == id2 && rev == rev2)   /* check for READ ONLY */
303             TIramdac_ID = TI3030_RAMDAC;
304         break;
305     case TIDAC_TVP_3026_ID:
306         if (id == id2 && rev == rev2)   /* check for READ ONLY */
307             TIramdac_ID = TI3026_RAMDAC;
308         break;
309     }
310 
311     (*ramdacPtr->WriteDAC) (pScrn, rev, 0, TIDAC_rev);
312     (*ramdacPtr->WriteDAC) (pScrn, id, 0, TIDAC_id);
313 
314     if (TIramdac_ID == -1) {
315         xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
316                    "Cannot determine TI RAMDAC type, aborting\n");
317         return NULL;
318     }
319     else {
320         xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
321                    "Attached RAMDAC is %s\n",
322                    TIramdacDeviceInfo[TIramdac_ID & 0xFFFF].DeviceName);
323     }
324 
325     for (i = 0; ramdacs[i].token != -1; i++) {
326         if (ramdacs[i].token == TIramdac_ID)
327             RamDacIsSupported = TRUE;
328     }
329 
330     if (!RamDacIsSupported) {
331         xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
332                    "This TI RAMDAC is NOT supported by this driver, aborting\n");
333         return NULL;
334     }
335 
336     ramdacHelperPtr = RamDacHelperCreateInfoRec();
337     switch (TIramdac_ID) {
338     case TI3030_RAMDAC:
339         ramdacHelperPtr->SetBpp = TIramdac3030SetBpp;
340         ramdacHelperPtr->HWCursorInit = TIramdacHWCursorInit;
341         break;
342     case TI3026_RAMDAC:
343         ramdacHelperPtr->SetBpp = TIramdac3026SetBpp;
344         ramdacHelperPtr->HWCursorInit = TIramdacHWCursorInit;
345         break;
346     }
347     ramdacPtr->RamDacType = TIramdac_ID;
348     ramdacHelperPtr->RamDacType = TIramdac_ID;
349     ramdacHelperPtr->Save = TIramdacSave;
350     ramdacHelperPtr->Restore = TIramdacRestore;
351 
352     return ramdacHelperPtr;
353 }
354 
355 void
TIramdac3026SetBpp(ScrnInfoPtr pScrn,RamDacRegRecPtr ramdacReg)356 TIramdac3026SetBpp(ScrnInfoPtr pScrn, RamDacRegRecPtr ramdacReg)
357 {
358     switch (pScrn->bitsPerPixel) {
359     case 32:
360         /* order is important */
361         ramdacReg->DacRegs[TIDAC_latch_ctrl] = 0x06;
362         ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x46;
363         ramdacReg->DacRegs[TIDAC_multiplex_ctrl] = 0x5c;
364         ramdacReg->DacRegs[TIDAC_clock_select] = 0x05;
365         ramdacReg->DacRegs[TIDAC_palette_page] = 0x00;
366         ramdacReg->DacRegs[TIDAC_general_ctrl] = 0x10;
367         ramdacReg->DacRegs[TIDAC_misc_ctrl] = 0x3C;
368         /* 0x2A & 0x2B are reserved */
369         ramdacReg->DacRegs[TIDAC_key_over_low] = 0xFF;
370         ramdacReg->DacRegs[TIDAC_key_over_high] = 0xFF;
371         ramdacReg->DacRegs[TIDAC_key_red_low] = 0xFF;
372         ramdacReg->DacRegs[TIDAC_key_red_high] = 0xFF;
373         ramdacReg->DacRegs[TIDAC_key_green_low] = 0xFF;
374         ramdacReg->DacRegs[TIDAC_key_green_high] = 0xFF;
375         ramdacReg->DacRegs[TIDAC_key_blue_low] = 0xFF;
376         ramdacReg->DacRegs[TIDAC_key_blue_high] = 0x00;
377         ramdacReg->DacRegs[TIDAC_key_ctrl] = 0x10;
378         ramdacReg->DacRegs[TIDAC_sense_test] = 0x00;
379         if (pScrn->overlayFlags & OVERLAY_8_32_PLANAR) {
380             ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x06;
381             ramdacReg->DacRegs[TIDAC_misc_ctrl] = 0x3C;
382             ramdacReg->DacRegs[TIDAC_key_ctrl] = 0x01;
383         }
384         ramdacReg->DacRegs[TIDAC_ind_curs_ctrl] = 0x00;
385         break;
386     case 24:
387         /* order is important */
388         ramdacReg->DacRegs[TIDAC_latch_ctrl] = 0x06;
389         ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x56;
390         ramdacReg->DacRegs[TIDAC_multiplex_ctrl] = 0x58;
391         ramdacReg->DacRegs[TIDAC_clock_select] = 0x25;
392         ramdacReg->DacRegs[TIDAC_palette_page] = 0x00;
393         ramdacReg->DacRegs[TIDAC_general_ctrl] = 0x00;
394         ramdacReg->DacRegs[TIDAC_misc_ctrl] = 0x2C;
395         /* 0x2A & 0x2B are reserved */
396         ramdacReg->DacRegs[TIDAC_key_over_low] = 0xFF;
397         ramdacReg->DacRegs[TIDAC_key_over_high] = 0xFF;
398         ramdacReg->DacRegs[TIDAC_key_red_low] = 0xFF;
399         ramdacReg->DacRegs[TIDAC_key_red_high] = 0xFF;
400         ramdacReg->DacRegs[TIDAC_key_green_low] = 0xFF;
401         ramdacReg->DacRegs[TIDAC_key_green_high] = 0xFF;
402         ramdacReg->DacRegs[TIDAC_key_blue_low] = 0xFF;
403         ramdacReg->DacRegs[TIDAC_key_blue_high] = 0x00;
404         ramdacReg->DacRegs[TIDAC_key_ctrl] = 0x10;
405         ramdacReg->DacRegs[TIDAC_sense_test] = 0x00;
406         ramdacReg->DacRegs[TIDAC_ind_curs_ctrl] = 0x00;
407         break;
408     case 16:
409         /* order is important */
410 #if 0
411         /* Matrox driver uses this */
412         ramdacReg->DacRegs[TIDAC_latch_ctrl] = 0x07;
413 #else
414         ramdacReg->DacRegs[TIDAC_latch_ctrl] = 0x06;
415 #endif
416         if (pScrn->depth == 16) {
417             ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x45;
418         }
419         else {
420             ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x44;
421         }
422 #if 0
423         /* Matrox driver uses this */
424         ramdacReg->DacRegs[TIDAC_multiplex_ctrl] = 0x50;
425         ramdacReg->DacRegs[TIDAC_clock_select] = 0x15;
426         ramdacReg->DacRegs[TIDAC_palette_page] = 0x00;
427         ramdacReg->DacRegs[TIDAC_general_ctrl] = 0x00;
428 #else
429         ramdacReg->DacRegs[TIDAC_multiplex_ctrl] = 0x54;
430         ramdacReg->DacRegs[TIDAC_clock_select] = 0x05;
431         ramdacReg->DacRegs[TIDAC_palette_page] = 0x00;
432         ramdacReg->DacRegs[TIDAC_general_ctrl] = 0x10;
433 #endif
434         ramdacReg->DacRegs[TIDAC_misc_ctrl] = 0x2C;
435         /* 0x2A & 0x2B are reserved */
436         ramdacReg->DacRegs[TIDAC_key_over_low] = 0xFF;
437         ramdacReg->DacRegs[TIDAC_key_over_high] = 0xFF;
438         ramdacReg->DacRegs[TIDAC_key_red_low] = 0xFF;
439         ramdacReg->DacRegs[TIDAC_key_red_high] = 0xFF;
440         ramdacReg->DacRegs[TIDAC_key_green_low] = 0xFF;
441         ramdacReg->DacRegs[TIDAC_key_green_high] = 0xFF;
442         ramdacReg->DacRegs[TIDAC_key_blue_low] = 0xFF;
443         ramdacReg->DacRegs[TIDAC_key_blue_high] = 0x00;
444         ramdacReg->DacRegs[TIDAC_key_ctrl] = 0x10;
445         ramdacReg->DacRegs[TIDAC_sense_test] = 0x00;
446         ramdacReg->DacRegs[TIDAC_ind_curs_ctrl] = 0x00;
447         break;
448     case 8:
449         /* order is important */
450         ramdacReg->DacRegs[TIDAC_latch_ctrl] = 0x06;
451         ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x80;
452         ramdacReg->DacRegs[TIDAC_multiplex_ctrl] = 0x4c;
453         ramdacReg->DacRegs[TIDAC_clock_select] = 0x05;
454         ramdacReg->DacRegs[TIDAC_palette_page] = 0x00;
455         ramdacReg->DacRegs[TIDAC_general_ctrl] = 0x10;
456         ramdacReg->DacRegs[TIDAC_misc_ctrl] = 0x1C;
457         /* 0x2A & 0x2B are reserved */
458         ramdacReg->DacRegs[TIDAC_key_over_low] = 0xFF;
459         ramdacReg->DacRegs[TIDAC_key_over_high] = 0xFF;
460         ramdacReg->DacRegs[TIDAC_key_red_low] = 0xFF;
461         ramdacReg->DacRegs[TIDAC_key_red_high] = 0xFF;
462         ramdacReg->DacRegs[TIDAC_key_green_low] = 0xFF;
463         ramdacReg->DacRegs[TIDAC_key_green_high] = 0xFF;
464         ramdacReg->DacRegs[TIDAC_key_blue_low] = 0x00;
465         ramdacReg->DacRegs[TIDAC_key_blue_high] = 0x00;
466         ramdacReg->DacRegs[TIDAC_key_ctrl] = 0x00;
467         ramdacReg->DacRegs[TIDAC_sense_test] = 0x00;
468         ramdacReg->DacRegs[TIDAC_ind_curs_ctrl] = 0x00;
469         break;
470     }
471 }
472 
473 void
TIramdac3030SetBpp(ScrnInfoPtr pScrn,RamDacRegRecPtr ramdacReg)474 TIramdac3030SetBpp(ScrnInfoPtr pScrn, RamDacRegRecPtr ramdacReg)
475 {
476     switch (pScrn->bitsPerPixel) {
477     case 32:
478         /* order is important */
479         ramdacReg->DacRegs[TIDAC_latch_ctrl] = 0x06;
480         ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x46;
481         ramdacReg->DacRegs[TIDAC_multiplex_ctrl] = 0x5D;
482         ramdacReg->DacRegs[TIDAC_clock_select] = 0x05;
483         ramdacReg->DacRegs[TIDAC_palette_page] = 0x00;
484         ramdacReg->DacRegs[TIDAC_general_ctrl] = 0x10;
485         ramdacReg->DacRegs[TIDAC_misc_ctrl] = 0x3C;
486         /* 0x2A & 0x2B are reserved */
487         ramdacReg->DacRegs[TIDAC_key_over_low] = 0xFF;
488         ramdacReg->DacRegs[TIDAC_key_over_high] = 0xFF;
489         ramdacReg->DacRegs[TIDAC_key_red_low] = 0xFF;
490         ramdacReg->DacRegs[TIDAC_key_red_high] = 0xFF;
491         ramdacReg->DacRegs[TIDAC_key_green_low] = 0xFF;
492         ramdacReg->DacRegs[TIDAC_key_green_high] = 0xFF;
493         ramdacReg->DacRegs[TIDAC_key_blue_low] = 0xFF;
494         ramdacReg->DacRegs[TIDAC_key_blue_high] = 0x00;
495         ramdacReg->DacRegs[TIDAC_key_ctrl] = 0x10;
496         ramdacReg->DacRegs[TIDAC_sense_test] = 0x00;
497         if (pScrn->overlayFlags & OVERLAY_8_32_PLANAR) {
498             ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x06;
499             ramdacReg->DacRegs[TIDAC_misc_ctrl] = 0x3C;
500             ramdacReg->DacRegs[TIDAC_key_ctrl] = 0x01;
501         }
502         ramdacReg->DacRegs[TIDAC_ind_curs_ctrl] = 0x00;
503         break;
504     case 24:
505         /* order is important */
506         ramdacReg->DacRegs[TIDAC_latch_ctrl] = 0x06;
507         ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x56;
508         ramdacReg->DacRegs[TIDAC_multiplex_ctrl] = 0x58;
509         ramdacReg->DacRegs[TIDAC_clock_select] = 0x25;
510         ramdacReg->DacRegs[TIDAC_palette_page] = 0x00;
511         ramdacReg->DacRegs[TIDAC_general_ctrl] = 0x00;
512         ramdacReg->DacRegs[TIDAC_misc_ctrl] = 0x2C;
513         /* 0x2A & 0x2B are reserved */
514         ramdacReg->DacRegs[TIDAC_key_over_low] = 0xFF;
515         ramdacReg->DacRegs[TIDAC_key_over_high] = 0xFF;
516         ramdacReg->DacRegs[TIDAC_key_red_low] = 0xFF;
517         ramdacReg->DacRegs[TIDAC_key_red_high] = 0xFF;
518         ramdacReg->DacRegs[TIDAC_key_green_low] = 0xFF;
519         ramdacReg->DacRegs[TIDAC_key_green_high] = 0xFF;
520         ramdacReg->DacRegs[TIDAC_key_blue_low] = 0xFF;
521         ramdacReg->DacRegs[TIDAC_key_blue_high] = 0x00;
522         ramdacReg->DacRegs[TIDAC_key_ctrl] = 0x10;
523         ramdacReg->DacRegs[TIDAC_sense_test] = 0x00;
524         ramdacReg->DacRegs[TIDAC_ind_curs_ctrl] = 0x00;
525         break;
526     case 16:
527         /* order is important */
528 #if 0
529         /* Matrox driver uses this */
530         ramdacReg->DacRegs[TIDAC_latch_ctrl] = 0x07;
531 #else
532         ramdacReg->DacRegs[TIDAC_latch_ctrl] = 0x06;
533 #endif
534         if (pScrn->depth == 16) {
535             ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x45;
536         }
537         else {
538             ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x44;
539         }
540 #if 0
541         /* Matrox driver uses this */
542         ramdacReg->DacRegs[TIDAC_multiplex_ctrl] = 0x50;
543         ramdacReg->DacRegs[TIDAC_clock_select] = 0x15;
544         ramdacReg->DacRegs[TIDAC_palette_page] = 0x00;
545         ramdacReg->DacRegs[TIDAC_general_ctrl] = 0x00;
546 #else
547         ramdacReg->DacRegs[TIDAC_multiplex_ctrl] = 0x55;
548         ramdacReg->DacRegs[TIDAC_clock_select] = 0x85;
549         ramdacReg->DacRegs[TIDAC_palette_page] = 0x00;
550         ramdacReg->DacRegs[TIDAC_general_ctrl] = 0x10;
551 #endif
552         ramdacReg->DacRegs[TIDAC_misc_ctrl] = 0x2C;
553         /* 0x2A & 0x2B are reserved */
554         ramdacReg->DacRegs[TIDAC_key_over_low] = 0xFF;
555         ramdacReg->DacRegs[TIDAC_key_over_high] = 0xFF;
556         ramdacReg->DacRegs[TIDAC_key_red_low] = 0xFF;
557         ramdacReg->DacRegs[TIDAC_key_red_high] = 0xFF;
558         ramdacReg->DacRegs[TIDAC_key_green_low] = 0xFF;
559         ramdacReg->DacRegs[TIDAC_key_green_high] = 0xFF;
560         ramdacReg->DacRegs[TIDAC_key_blue_low] = 0xFF;
561         ramdacReg->DacRegs[TIDAC_key_blue_high] = 0x00;
562         ramdacReg->DacRegs[TIDAC_key_ctrl] = 0x10;
563         ramdacReg->DacRegs[TIDAC_sense_test] = 0x00;
564         ramdacReg->DacRegs[TIDAC_ind_curs_ctrl] = 0x00;
565         break;
566     case 8:
567         /* order is important */
568         ramdacReg->DacRegs[TIDAC_latch_ctrl] = 0x06;
569         ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x80;
570         ramdacReg->DacRegs[TIDAC_multiplex_ctrl] = 0x4d;
571         ramdacReg->DacRegs[TIDAC_clock_select] = 0x05;
572         ramdacReg->DacRegs[TIDAC_palette_page] = 0x00;
573         ramdacReg->DacRegs[TIDAC_general_ctrl] = 0x10;
574         ramdacReg->DacRegs[TIDAC_misc_ctrl] = 0x1C;
575         /* 0x2A & 0x2B are reserved */
576         ramdacReg->DacRegs[TIDAC_key_over_low] = 0xFF;
577         ramdacReg->DacRegs[TIDAC_key_over_high] = 0xFF;
578         ramdacReg->DacRegs[TIDAC_key_red_low] = 0xFF;
579         ramdacReg->DacRegs[TIDAC_key_red_high] = 0xFF;
580         ramdacReg->DacRegs[TIDAC_key_green_low] = 0xFF;
581         ramdacReg->DacRegs[TIDAC_key_green_high] = 0xFF;
582         ramdacReg->DacRegs[TIDAC_key_blue_low] = 0x00;
583         ramdacReg->DacRegs[TIDAC_key_blue_high] = 0x00;
584         ramdacReg->DacRegs[TIDAC_key_ctrl] = 0x00;
585         ramdacReg->DacRegs[TIDAC_sense_test] = 0x00;
586         ramdacReg->DacRegs[TIDAC_ind_curs_ctrl] = 0x00;
587         break;
588     }
589 }
590 
591 static void
TIramdacShowCursor(ScrnInfoPtr pScrn)592 TIramdacShowCursor(ScrnInfoPtr pScrn)
593 {
594     RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
595 
596     /* Enable cursor - X11 mode */
597     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_ind_curs_ctrl, 0, 0x03);
598 }
599 
600 static void
TIramdacHideCursor(ScrnInfoPtr pScrn)601 TIramdacHideCursor(ScrnInfoPtr pScrn)
602 {
603     RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
604 
605     /* Disable cursor - X11 mode */
606     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_ind_curs_ctrl, 0, 0x00);
607 }
608 
609 static void
TIramdacSetCursorPosition(ScrnInfoPtr pScrn,int x,int y)610 TIramdacSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
611 {
612     RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
613 
614     x += 64;
615     y += 64;
616 
617     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_CURS_XLOW, 0, x & 0xff);
618     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_CURS_XHIGH, 0, (x >> 8) & 0x0f);
619     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_CURS_YLOW, 0, y & 0xff);
620     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_CURS_YHIGH, 0, (y >> 8) & 0x0f);
621 }
622 
623 static void
TIramdacSetCursorColors(ScrnInfoPtr pScrn,int bg,int fg)624 TIramdacSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
625 {
626     RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
627 
628     /* Background color */
629     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_CURS_WRITE_ADDR, 0, 1);
630     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_CURS_COLOR, 0,
631                             ((bg & 0x00ff0000) >> 16));
632     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_CURS_COLOR, 0,
633                             ((bg & 0x0000ff00) >> 8));
634     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_CURS_COLOR, 0, (bg & 0x000000ff));
635 
636     /* Foreground color */
637     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_CURS_WRITE_ADDR, 0, 2);
638     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_CURS_COLOR, 0,
639                             ((fg & 0x00ff0000) >> 16));
640     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_CURS_COLOR, 0,
641                             ((fg & 0x0000ff00) >> 8));
642     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_CURS_COLOR, 0, (fg & 0x000000ff));
643 }
644 
645 static Bool
TIramdacLoadCursorImage(ScrnInfoPtr pScrn,unsigned char * src)646 TIramdacLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
647 {
648     RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
649     int i = 1024;
650 
651     /* reset A9,A8 */
652     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_ind_curs_ctrl, 0, 0x00);
653     /* reset cursor RAM load address A7..A0 */
654     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_INDEX, 0x00, 0x00);
655 
656     while (i--) {
657         /* NOT_DONE: might need a delay here */
658         (*ramdacPtr->WriteDAC) (pScrn, TIDAC_CURS_RAM_DATA, 0, *(src++));
659     }
660     return TRUE;
661 }
662 
663 static Bool
TIramdacUseHWCursor(ScreenPtr pScr,CursorPtr pCurs)664 TIramdacUseHWCursor(ScreenPtr pScr, CursorPtr pCurs)
665 {
666     return TRUE;
667 }
668 
669 void
TIramdacHWCursorInit(xf86CursorInfoPtr infoPtr)670 TIramdacHWCursorInit(xf86CursorInfoPtr infoPtr)
671 {
672     infoPtr->MaxWidth = 64;
673     infoPtr->MaxHeight = 64;
674     infoPtr->Flags = HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
675         HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
676         HARDWARE_CURSOR_SOURCE_MASK_NOT_INTERLEAVED;
677     infoPtr->SetCursorColors = TIramdacSetCursorColors;
678     infoPtr->SetCursorPosition = TIramdacSetCursorPosition;
679     infoPtr->LoadCursorImageCheck = TIramdacLoadCursorImage;
680     infoPtr->HideCursor = TIramdacHideCursor;
681     infoPtr->ShowCursor = TIramdacShowCursor;
682     infoPtr->UseHWCursor = TIramdacUseHWCursor;
683 }
684 
685 void
TIramdacLoadPalette(ScrnInfoPtr pScrn,int numColors,int * indices,LOCO * colors,VisualPtr pVisual)686 TIramdacLoadPalette(ScrnInfoPtr pScrn,
687                     int numColors,
688                     int *indices, LOCO * colors, VisualPtr pVisual)
689 {
690     RamDacRecPtr hwp = RAMDACSCRPTR(pScrn);
691     int i, index, shift;
692 
693     if (pScrn->depth == 16) {
694         for (i = 0; i < numColors; i++) {
695             index = indices[i];
696             (*hwp->WriteAddress) (pScrn, index << 2);
697             (*hwp->WriteData) (pScrn, colors[index >> 1].red);
698             (*hwp->WriteData) (pScrn, colors[index].green);
699             (*hwp->WriteData) (pScrn, colors[index >> 1].blue);
700 
701             if (index <= 31) {
702                 (*hwp->WriteAddress) (pScrn, index << 3);
703                 (*hwp->WriteData) (pScrn, colors[index].red);
704                 (*hwp->WriteData) (pScrn, colors[(index << 1) + 1].green);
705                 (*hwp->WriteData) (pScrn, colors[index].blue);
706             }
707         }
708     }
709     else {
710         shift = (pScrn->depth == 15) ? 3 : 0;
711 
712         for (i = 0; i < numColors; i++) {
713             index = indices[i];
714             (*hwp->WriteAddress) (pScrn, index << shift);
715             (*hwp->WriteData) (pScrn, colors[index].red);
716             (*hwp->WriteData) (pScrn, colors[index].green);
717             (*hwp->WriteData) (pScrn, colors[index].blue);
718         }
719     }
720 }
721 
722 TIramdacLoadPaletteProc *
TIramdacLoadPaletteWeak(void)723 TIramdacLoadPaletteWeak(void)
724 {
725     return TIramdacLoadPalette;
726 }
727