Commit | Line | Data |
---|---|---|
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 | ||
45 | unsigned long | |
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=%d m=%d p=%d\n", | |
118 | ActualClock, VCO, *rN, *rM, *rP); | |
119 | ||
120 | return ActualClock; | |
121 | } | |
122 | ||
123 | void | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 void | |
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 | } | |
661 | ||
662 | static Bool | |
663 | TIramdacUseHWCursor(ScreenPtr pScr, CursorPtr pCurs) | |
664 | { | |
665 | return TRUE; | |
666 | } | |
667 | ||
668 | void | |
669 | TIramdacHWCursorInit(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 | ||
684 | void | |
685 | TIramdacLoadPalette(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 | ||
721 | TIramdacLoadPaletteProc * | |
722 | TIramdacLoadPaletteWeak(void) | |
723 | { | |
724 | return TIramdacLoadPalette; | |
725 | } |