Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / ramdac / TI.c
CommitLineData
a09e091a
JB
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(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=%d m=%d p=%d\n",
118 ActualClock, VCO, *rN, *rM, *rP);
119
120 return ActualClock;
121}
122
123void
124TIramdacRestore(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
225void
226TIramdacSave(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
280RamDacHelperRecPtr
281TIramdacProbe(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
355void
356TIramdac3026SetBpp(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
473void
474TIramdac3030SetBpp(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
591static void
592TIramdacShowCursor(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
600static void
601TIramdacHideCursor(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
609static void
610TIramdacSetCursorPosition(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
623static void
624TIramdacSetCursorColors(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
645static void
646TIramdacLoadCursorImage(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}
661
662static Bool
663TIramdacUseHWCursor(ScreenPtr pScr, CursorPtr pCurs)
664{
665 return TRUE;
666}
667
668void
669TIramdacHWCursorInit(xf86CursorInfoPtr infoPtr)
670{
671 infoPtr->MaxWidth = 64;
672 infoPtr->MaxHeight = 64;
673 infoPtr->Flags = HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
674 HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
675 HARDWARE_CURSOR_SOURCE_MASK_NOT_INTERLEAVED;
676 infoPtr->SetCursorColors = TIramdacSetCursorColors;
677 infoPtr->SetCursorPosition = TIramdacSetCursorPosition;
678 infoPtr->LoadCursorImage = TIramdacLoadCursorImage;
679 infoPtr->HideCursor = TIramdacHideCursor;
680 infoPtr->ShowCursor = TIramdacShowCursor;
681 infoPtr->UseHWCursor = TIramdacUseHWCursor;
682}
683
684void
685TIramdacLoadPalette(ScrnInfoPtr pScrn,
686 int numColors,
687 int *indices, LOCO * colors, VisualPtr pVisual)
688{
689 RamDacRecPtr hwp = RAMDACSCRPTR(pScrn);
690 int i, index, shift;
691
692 if (pScrn->depth == 16) {
693 for (i = 0; i < numColors; i++) {
694 index = indices[i];
695 (*hwp->WriteAddress) (pScrn, index << 2);
696 (*hwp->WriteData) (pScrn, colors[index >> 1].red);
697 (*hwp->WriteData) (pScrn, colors[index].green);
698 (*hwp->WriteData) (pScrn, colors[index >> 1].blue);
699
700 if (index <= 31) {
701 (*hwp->WriteAddress) (pScrn, index << 3);
702 (*hwp->WriteData) (pScrn, colors[index].red);
703 (*hwp->WriteData) (pScrn, colors[(index << 1) + 1].green);
704 (*hwp->WriteData) (pScrn, colors[index].blue);
705 }
706 }
707 }
708 else {
709 shift = (pScrn->depth == 15) ? 3 : 0;
710
711 for (i = 0; i < numColors; i++) {
712 index = indices[i];
713 (*hwp->WriteAddress) (pScrn, index << shift);
714 (*hwp->WriteData) (pScrn, colors[index].red);
715 (*hwp->WriteData) (pScrn, colors[index].green);
716 (*hwp->WriteData) (pScrn, colors[index].blue);
717 }
718 }
719}
720
721TIramdacLoadPaletteProc *
722TIramdacLoadPaletteWeak(void)
723{
724 return TIramdacLoadPalette;
725}