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