1
2 /*
3 * ATI Mach64 GX Support
4 */
5
6 #include <linux/delay.h>
7 #include <linux/fb.h>
8
9 #include <asm/io.h>
10
11 #include <video/fbcon.h>
12
13 #include "mach64.h"
14 #include "atyfb.h"
15
16 /* Definitions for the ICS 2595 == ATI 18818_1 Clockchip */
17
18 #define REF_FREQ_2595 1432 /* 14.33 MHz (exact 14.31818) */
19 #define REF_DIV_2595 46 /* really 43 on ICS 2595 !!! */
20 /* ohne Prescaler */
21 #define MAX_FREQ_2595 15938 /* 159.38 MHz (really 170.486) */
22 #define MIN_FREQ_2595 8000 /* 80.00 MHz ( 85.565) */
23 /* mit Prescaler 2, 4, 8 */
24 #define ABS_MIN_FREQ_2595 1000 /* 10.00 MHz (really 10.697) */
25 #define N_ADJ_2595 257
26
27 #define STOP_BITS_2595 0x1800
28
29
30 #define MIN_N_408 2
31
32 #define MIN_N_1703 6
33
34 #define MIN_M 2
35 #define MAX_M 30
36 #define MIN_N 35
37 #define MAX_N 255-8
38
dummy(void)39 static int dummy(void)
40 {
41 return 0;
42 }
43
44
45 /*
46 * Support Functions
47 */
48
aty_dac_waste4(const struct fb_info_aty * info)49 static void aty_dac_waste4(const struct fb_info_aty *info)
50 {
51 (void)aty_ld_8(DAC_REGS, info);
52
53 (void)aty_ld_8(DAC_REGS + 2, info);
54 (void)aty_ld_8(DAC_REGS + 2, info);
55 (void)aty_ld_8(DAC_REGS + 2, info);
56 (void)aty_ld_8(DAC_REGS + 2, info);
57 }
58
aty_StrobeClock(const struct fb_info_aty * info)59 static void aty_StrobeClock(const struct fb_info_aty *info)
60 {
61 u8 tmp;
62
63 udelay(26);
64
65 tmp = aty_ld_8(CLOCK_CNTL, info);
66 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, tmp | CLOCK_STROBE, info);
67
68 return;
69 }
70
71
72 /*
73 * IBM RGB514 DAC and Clock Chip
74 */
75
aty_st_514(int offset,u8 val,const struct fb_info_aty * info)76 static void aty_st_514(int offset, u8 val, const struct fb_info_aty *info)
77 {
78 aty_st_8(DAC_CNTL, 1, info);
79 /* right addr byte */
80 aty_st_8(DAC_W_INDEX, offset & 0xff, info);
81 /* left addr byte */
82 aty_st_8(DAC_DATA, (offset >> 8) & 0xff, info);
83 aty_st_8(DAC_MASK, val, info);
84 aty_st_8(DAC_CNTL, 0, info);
85 }
86
aty_set_dac_514(const struct fb_info_aty * info,const union aty_pll * pll,u32 bpp,u32 accel)87 static int aty_set_dac_514(const struct fb_info_aty *info,
88 const union aty_pll *pll, u32 bpp, u32 accel)
89 {
90 static struct {
91 u8 pixel_dly;
92 u8 misc2_cntl;
93 u8 pixel_rep;
94 u8 pixel_cntl_index;
95 u8 pixel_cntl_v1;
96 } tab[3] = {
97 { 0, 0x41, 0x03, 0x71, 0x45 }, /* 8 bpp */
98 { 0, 0x45, 0x04, 0x0c, 0x01 }, /* 555 */
99 { 0, 0x45, 0x06, 0x0e, 0x00 }, /* XRGB */
100 };
101 int i;
102
103 switch (bpp) {
104 case 8:
105 default:
106 i = 0;
107 break;
108 case 16:
109 i = 1;
110 break;
111 case 32:
112 i = 2;
113 break;
114 }
115 aty_st_514(0x90, 0x00, info); /* VRAM Mask Low */
116 aty_st_514(0x04, tab[i].pixel_dly, info); /* Horizontal Sync Control */
117 aty_st_514(0x05, 0x00, info); /* Power Management */
118 aty_st_514(0x02, 0x01, info); /* Misc Clock Control */
119 aty_st_514(0x71, tab[i].misc2_cntl, info); /* Misc Control 2 */
120 aty_st_514(0x0a, tab[i].pixel_rep, info); /* Pixel Format */
121 aty_st_514(tab[i].pixel_cntl_index, tab[i].pixel_cntl_v1, info);
122 /* Misc Control 2 / 16 BPP Control / 32 BPP Control */
123 return 0;
124 }
125
aty_var_to_pll_514(const struct fb_info_aty * info,u32 vclk_per,u8 bpp,u32 xres,union aty_pll * pll)126 static int aty_var_to_pll_514(const struct fb_info_aty *info, u32 vclk_per,
127 u8 bpp, u32 xres, union aty_pll *pll)
128 {
129 /*
130 * FIXME: use real calculations instead of using fixed values from the old
131 * driver
132 */
133 static struct {
134 u32 limit; /* pixlock rounding limit (arbitrary) */
135 u8 m; /* (df<<6) | vco_div_count */
136 u8 n; /* ref_div_count */
137 } RGB514_clocks[7] = {
138 { 8000, (3<<6) | 20, 9 }, /* 7395 ps / 135.2273 MHz */
139 { 10000, (1<<6) | 19, 3 }, /* 9977 ps / 100.2273 MHz */
140 { 13000, (1<<6) | 2, 3 }, /* 12509 ps / 79.9432 MHz */
141 { 14000, (2<<6) | 8, 7 }, /* 13394 ps / 74.6591 MHz */
142 { 16000, (1<<6) | 44, 6 }, /* 15378 ps / 65.0284 MHz */
143 { 25000, (1<<6) | 15, 5 }, /* 17460 ps / 57.2727 MHz */
144 { 50000, (0<<6) | 53, 7 }, /* 33145 ps / 30.1705 MHz */
145 };
146 int i;
147
148 for (i = 0; i < sizeof(RGB514_clocks)/sizeof(*RGB514_clocks); i++)
149 if (vclk_per <= RGB514_clocks[i].limit) {
150 pll->ibm514.m = RGB514_clocks[i].m;
151 pll->ibm514.n = RGB514_clocks[i].n;
152 return 0;
153 }
154 return -EINVAL;
155 }
156
aty_pll_514_to_var(const struct fb_info_aty * info,const union aty_pll * pll)157 static u32 aty_pll_514_to_var(const struct fb_info_aty *info,
158 const union aty_pll *pll)
159 {
160 u8 df, vco_div_count, ref_div_count;
161
162 df = pll->ibm514.m >> 6;
163 vco_div_count = pll->ibm514.m & 0x3f;
164 ref_div_count = pll->ibm514.n;
165
166 return ((info->ref_clk_per*ref_div_count)<<(3-df))/(vco_div_count+65);
167 }
168
aty_set_pll_514(const struct fb_info_aty * info,const union aty_pll * pll)169 static void aty_set_pll_514(const struct fb_info_aty *info,
170 const union aty_pll *pll)
171 {
172 aty_st_514(0x06, 0x02, info); /* DAC Operation */
173 aty_st_514(0x10, 0x01, info); /* PLL Control 1 */
174 aty_st_514(0x70, 0x01, info); /* Misc Control 1 */
175 aty_st_514(0x8f, 0x1f, info); /* PLL Ref. Divider Input */
176 aty_st_514(0x03, 0x00, info); /* Sync Control */
177 aty_st_514(0x05, 0x00, info); /* Power Management */
178 aty_st_514(0x20, pll->ibm514.m, info); /* F0 / M0 */
179 aty_st_514(0x21, pll->ibm514.n, info); /* F1 / N0 */
180 }
181
182 const struct aty_dac_ops aty_dac_ibm514 = {
183 set_dac: aty_set_dac_514,
184 };
185
186 const struct aty_pll_ops aty_pll_ibm514 = {
187 var_to_pll: aty_var_to_pll_514,
188 pll_to_var: aty_pll_514_to_var,
189 set_pll: aty_set_pll_514,
190 init_pll: (void *)dummy
191 };
192
193
194 /*
195 * ATI 68860-B DAC
196 */
197
aty_set_dac_ATI68860_B(const struct fb_info_aty * info,const union aty_pll * pll,u32 bpp,u32 accel)198 static int aty_set_dac_ATI68860_B(const struct fb_info_aty *info,
199 const union aty_pll *pll, u32 bpp, u32 accel)
200 {
201 u32 gModeReg, devSetupRegA, temp, mask;
202
203 gModeReg = 0;
204 devSetupRegA = 0;
205
206 switch (bpp) {
207 case 8:
208 gModeReg = 0x83;
209 devSetupRegA = 0x60 | 0x00 /*(info->mach64DAC8Bit ? 0x00 : 0x01) */;
210 break;
211 case 15:
212 gModeReg = 0xA0;
213 devSetupRegA = 0x60;
214 break;
215 case 16:
216 gModeReg = 0xA1;
217 devSetupRegA = 0x60;
218 break;
219 case 24:
220 gModeReg = 0xC0;
221 devSetupRegA = 0x60;
222 break;
223 case 32:
224 gModeReg = 0xE3;
225 devSetupRegA = 0x60;
226 break;
227 }
228
229 if (!accel) {
230 gModeReg = 0x80;
231 devSetupRegA = 0x61;
232 }
233
234 temp = aty_ld_8(DAC_CNTL, info);
235 aty_st_8(DAC_CNTL, (temp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3, info);
236
237 aty_st_8(DAC_REGS + 2, 0x1D, info);
238 aty_st_8(DAC_REGS + 3, gModeReg, info);
239 aty_st_8(DAC_REGS, 0x02, info);
240
241 temp = aty_ld_8(DAC_CNTL, info);
242 aty_st_8(DAC_CNTL, temp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, info);
243
244 if (info->total_vram < MEM_SIZE_1M)
245 mask = 0x04;
246 else if (info->total_vram == MEM_SIZE_1M)
247 mask = 0x08;
248 else
249 mask = 0x0C;
250
251 /* The following assumes that the BIOS has correctly set R7 of the
252 * Device Setup Register A at boot time.
253 */
254 #define A860_DELAY_L 0x80
255
256 temp = aty_ld_8(DAC_REGS, info);
257 aty_st_8(DAC_REGS, (devSetupRegA | mask) | (temp & A860_DELAY_L), info);
258 temp = aty_ld_8(DAC_CNTL, info);
259 aty_st_8(DAC_CNTL, (temp & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3)), info);
260
261 aty_st_le32(BUS_CNTL, 0x890e20f1, info);
262 aty_st_le32(DAC_CNTL, 0x47052100, info);
263
264 return 0;
265 }
266
267 const struct aty_dac_ops aty_dac_ati68860b = {
268 set_dac: aty_set_dac_ATI68860_B,
269 };
270
271
272 /*
273 * AT&T 21C498 DAC
274 */
275
aty_set_dac_ATT21C498(const struct fb_info_aty * info,const union aty_pll * pll,u32 bpp,u32 accel)276 static int aty_set_dac_ATT21C498(const struct fb_info_aty *info,
277 const union aty_pll *pll, u32 bpp, u32 accel)
278 {
279 u32 dotClock;
280 int muxmode = 0;
281 int DACMask = 0;
282
283 dotClock = 100000000 / pll->ics2595.period_in_ps;
284
285 switch (bpp) {
286 case 8:
287 if (dotClock > 8000) {
288 DACMask = 0x24;
289 muxmode = 1;
290 } else
291 DACMask = 0x04;
292 break;
293 case 15:
294 DACMask = 0x16;
295 break;
296 case 16:
297 DACMask = 0x36;
298 break;
299 case 24:
300 DACMask = 0xE6;
301 break;
302 case 32:
303 DACMask = 0xE6;
304 break;
305 }
306
307 if (1 /* info->mach64DAC8Bit */)
308 DACMask |= 0x02;
309
310 aty_dac_waste4(info);
311 aty_st_8(DAC_REGS + 2, DACMask, info);
312
313 aty_st_le32(BUS_CNTL, 0x890e20f1, info);
314 aty_st_le32(DAC_CNTL, 0x00072000, info);
315 return muxmode;
316 }
317
318 const struct aty_dac_ops aty_dac_att21c498 = {
319 set_dac: aty_set_dac_ATT21C498,
320 };
321
322
323 /*
324 * ATI 18818 / ICS 2595 Clock Chip
325 */
326
aty_var_to_pll_18818(const struct fb_info_aty * info,u32 vclk_per,u8 bpp,u32 xres,union aty_pll * pll)327 static int aty_var_to_pll_18818(const struct fb_info_aty *info, u32 vclk_per,
328 u8 bpp, u32 xres, union aty_pll *pll)
329 {
330 u32 MHz100; /* in 0.01 MHz */
331 u32 program_bits;
332 u32 post_divider;
333
334 /* Calculate the programming word */
335 MHz100 = 100000000 / vclk_per;
336
337 program_bits = -1;
338 post_divider = 1;
339
340 if (MHz100 > MAX_FREQ_2595) {
341 MHz100 = MAX_FREQ_2595;
342 return -EINVAL;
343 } else if (MHz100 < ABS_MIN_FREQ_2595) {
344 program_bits = 0; /* MHz100 = 257 */
345 return -EINVAL;
346 } else {
347 while (MHz100 < MIN_FREQ_2595) {
348 MHz100 *= 2;
349 post_divider *= 2;
350 }
351 }
352 MHz100 *= 1000;
353 MHz100 = (REF_DIV_2595 * MHz100) / REF_FREQ_2595;
354
355 MHz100 += 500; /* + 0.5 round */
356 MHz100 /= 1000;
357
358 if (program_bits == -1) {
359 program_bits = MHz100 - N_ADJ_2595;
360 switch (post_divider) {
361 case 1:
362 program_bits |= 0x0600;
363 break;
364 case 2:
365 program_bits |= 0x0400;
366 break;
367 case 4:
368 program_bits |= 0x0200;
369 break;
370 case 8:
371 default:
372 break;
373 }
374 }
375
376 program_bits |= STOP_BITS_2595;
377
378 pll->ics2595.program_bits = program_bits;
379 pll->ics2595.locationAddr = 0;
380 pll->ics2595.post_divider = post_divider;
381 pll->ics2595.period_in_ps = vclk_per;
382
383 return 0;
384 }
385
aty_pll_18818_to_var(const struct fb_info_aty * info,const union aty_pll * pll)386 static u32 aty_pll_18818_to_var(const struct fb_info_aty *info,
387 const union aty_pll *pll)
388 {
389 return(pll->ics2595.period_in_ps); /* default for now */
390 }
391
aty_ICS2595_put1bit(u8 data,const struct fb_info_aty * info)392 static void aty_ICS2595_put1bit(u8 data, const struct fb_info_aty *info)
393 {
394 u8 tmp;
395
396 data &= 0x01;
397 tmp = aty_ld_8(CLOCK_CNTL, info);
398 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, (tmp & ~0x04) | (data << 2),
399 info);
400
401 tmp = aty_ld_8(CLOCK_CNTL, info);
402 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, (tmp & ~0x08) | (0 << 3), info);
403
404 aty_StrobeClock(info);
405
406 tmp = aty_ld_8(CLOCK_CNTL, info);
407 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, (tmp & ~0x08) | (1 << 3), info);
408
409 aty_StrobeClock(info);
410
411 return;
412 }
413
aty_set_pll18818(const struct fb_info_aty * info,const union aty_pll * pll)414 static void aty_set_pll18818(const struct fb_info_aty *info,
415 const union aty_pll *pll)
416 {
417 u32 program_bits;
418 u32 locationAddr;
419
420 u32 i;
421
422 u8 old_clock_cntl;
423 u8 old_crtc_ext_disp;
424
425 old_clock_cntl = aty_ld_8(CLOCK_CNTL, info);
426 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 0, info);
427
428 old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
429 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24),
430 info);
431
432 mdelay(15); /* delay for 50 (15) ms */
433
434 program_bits = pll->ics2595.program_bits;
435 locationAddr = pll->ics2595.locationAddr;
436
437 /* Program the clock chip */
438 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 0, info); /* Strobe = 0 */
439 aty_StrobeClock(info);
440 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 1, info); /* Strobe = 0 */
441 aty_StrobeClock(info);
442
443 aty_ICS2595_put1bit(1, info); /* Send start bits */
444 aty_ICS2595_put1bit(0, info); /* Start bit */
445 aty_ICS2595_put1bit(0, info); /* Read / ~Write */
446
447 for (i = 0; i < 5; i++) { /* Location 0..4 */
448 aty_ICS2595_put1bit(locationAddr & 1, info);
449 locationAddr >>= 1;
450 }
451
452 for (i = 0; i < 8 + 1 + 2 + 2; i++) {
453 aty_ICS2595_put1bit(program_bits & 1, info);
454 program_bits >>= 1;
455 }
456
457 mdelay(1); /* delay for 1 ms */
458
459 (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */
460 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info);
461 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, old_clock_cntl | CLOCK_STROBE,
462 info);
463
464 mdelay(50); /* delay for 50 (15) ms */
465 aty_st_8(CLOCK_CNTL + info->clk_wr_offset,
466 ((pll->ics2595.locationAddr & 0x0F) | CLOCK_STROBE), info);
467
468 return;
469 }
470
471 const struct aty_pll_ops aty_pll_ati18818_1 = {
472 var_to_pll: aty_var_to_pll_18818,
473 pll_to_var: aty_pll_18818_to_var,
474 set_pll: aty_set_pll18818,
475 init_pll: (void *)dummy
476 };
477
478
479 /*
480 * STG 1703 Clock Chip
481 */
482
aty_var_to_pll_1703(const struct fb_info_aty * info,u32 vclk_per,u8 bpp,u32 xres,union aty_pll * pll)483 static int aty_var_to_pll_1703(const struct fb_info_aty *info, u32 vclk_per,
484 u8 bpp, u32 xres, union aty_pll *pll)
485 {
486 u32 mhz100; /* in 0.01 MHz */
487 u32 program_bits;
488 /* u32 post_divider; */
489 u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
490 u32 temp, tempB;
491 u16 remainder, preRemainder;
492 short divider = 0, tempA;
493
494 /* Calculate the programming word */
495 mhz100 = 100000000 / vclk_per;
496 mach64MinFreq = MIN_FREQ_2595;
497 mach64MaxFreq = MAX_FREQ_2595;
498 mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */
499
500 /* Calculate program word */
501 if (mhz100 == 0)
502 program_bits = 0xE0;
503 else {
504 if (mhz100 < mach64MinFreq)
505 mhz100 = mach64MinFreq;
506 if (mhz100 > mach64MaxFreq)
507 mhz100 = mach64MaxFreq;
508
509 divider = 0;
510 while (mhz100 < (mach64MinFreq << 3)) {
511 mhz100 <<= 1;
512 divider += 0x20;
513 }
514
515 temp = (unsigned int)(mhz100);
516 temp = (unsigned int)(temp * (MIN_N_1703 + 2));
517 temp -= (short)(mach64RefFreq << 1);
518
519 tempA = MIN_N_1703;
520 preRemainder = 0xffff;
521
522 do {
523 tempB = temp;
524 remainder = tempB % mach64RefFreq;
525 tempB = tempB / mach64RefFreq;
526
527 if ((tempB & 0xffff) <= 127 && (remainder <= preRemainder)) {
528 preRemainder = remainder;
529 divider &= ~0x1f;
530 divider |= tempA;
531 divider = (divider & 0x00ff) + ((tempB & 0xff) << 8);
532 }
533
534 temp += mhz100;
535 tempA++;
536 } while (tempA <= (MIN_N_1703 << 1));
537
538 program_bits = divider;
539 }
540
541 pll->ics2595.program_bits = program_bits;
542 pll->ics2595.locationAddr = 0;
543 pll->ics2595.post_divider = divider; /* fuer nix */
544 pll->ics2595.period_in_ps = vclk_per;
545
546 return 0;
547 }
548
aty_pll_1703_to_var(const struct fb_info_aty * info,const union aty_pll * pll)549 static u32 aty_pll_1703_to_var(const struct fb_info_aty *info,
550 const union aty_pll *pll)
551 {
552 return(pll->ics2595.period_in_ps); /* default for now */
553 }
554
aty_set_pll_1703(const struct fb_info_aty * info,const union aty_pll * pll)555 static void aty_set_pll_1703(const struct fb_info_aty *info,
556 const union aty_pll *pll)
557 {
558 u32 program_bits;
559 u32 locationAddr;
560
561 char old_crtc_ext_disp;
562
563 old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
564 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24),
565 info);
566
567 program_bits = pll->ics2595.program_bits;
568 locationAddr = pll->ics2595.locationAddr;
569
570 /* Program clock */
571 aty_dac_waste4(info);
572
573 (void)aty_ld_8(DAC_REGS + 2, info);
574 aty_st_8(DAC_REGS+2, (locationAddr << 1) + 0x20, info);
575 aty_st_8(DAC_REGS+2, 0, info);
576 aty_st_8(DAC_REGS+2, (program_bits & 0xFF00) >> 8, info);
577 aty_st_8(DAC_REGS+2, (program_bits & 0xFF), info);
578
579 (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */
580 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info);
581
582 return;
583 }
584
585 const struct aty_pll_ops aty_pll_stg1703 = {
586 var_to_pll: aty_var_to_pll_1703,
587 pll_to_var: aty_pll_1703_to_var,
588 set_pll: aty_set_pll_1703,
589 init_pll: (void *)dummy
590 };
591
592
593 /*
594 * Chrontel 8398 Clock Chip
595 */
596
aty_var_to_pll_8398(const struct fb_info_aty * info,u32 vclk_per,u8 bpp,u32 xres,union aty_pll * pll)597 static int aty_var_to_pll_8398(const struct fb_info_aty *info, u32 vclk_per,
598 u8 bpp, u32 xres, union aty_pll *pll)
599 {
600 u32 tempA, tempB, fOut, longMHz100, diff, preDiff;
601
602 u32 mhz100; /* in 0.01 MHz */
603 u32 program_bits;
604 /* u32 post_divider; */
605 u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
606 u16 m, n, k=0, save_m, save_n, twoToKth;
607
608 /* Calculate the programming word */
609 mhz100 = 100000000 / vclk_per;
610 mach64MinFreq = MIN_FREQ_2595;
611 mach64MaxFreq = MAX_FREQ_2595;
612 mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */
613
614 save_m = 0;
615 save_n = 0;
616
617 /* Calculate program word */
618 if (mhz100 == 0)
619 program_bits = 0xE0;
620 else
621 {
622 if (mhz100 < mach64MinFreq)
623 mhz100 = mach64MinFreq;
624 if (mhz100 > mach64MaxFreq)
625 mhz100 = mach64MaxFreq;
626
627 longMHz100 = mhz100 * 256 / 100; /* 8 bit scale this */
628
629 while (mhz100 < (mach64MinFreq << 3))
630 {
631 mhz100 <<= 1;
632 k++;
633 }
634
635 twoToKth = 1 << k;
636 diff = 0;
637 preDiff = 0xFFFFFFFF;
638
639 for (m = MIN_M; m <= MAX_M; m++)
640 {
641 for (n = MIN_N; n <= MAX_N; n++)
642 {
643 tempA = (14.31818 * 65536);
644 tempA *= (n + 8); /* 43..256 */
645 tempB = twoToKth * 256;
646 tempB *= (m + 2); /* 4..32 */
647 fOut = tempA / tempB; /* 8 bit scale */
648
649 if (longMHz100 > fOut)
650 diff = longMHz100 - fOut;
651 else
652 diff = fOut - longMHz100;
653
654 if (diff < preDiff)
655 {
656 save_m = m;
657 save_n = n;
658 preDiff = diff;
659 }
660 }
661 }
662
663 program_bits = (k << 6) + (save_m) + (save_n << 8);
664 }
665
666 pll->ics2595.program_bits = program_bits;
667 pll->ics2595.locationAddr = 0;
668 pll->ics2595.post_divider = 0;
669 pll->ics2595.period_in_ps = vclk_per;
670
671 return 0;
672 }
673
aty_pll_8398_to_var(const struct fb_info_aty * info,const union aty_pll * pll)674 static u32 aty_pll_8398_to_var(const struct fb_info_aty *info,
675 const union aty_pll *pll)
676 {
677 return(pll->ics2595.period_in_ps); /* default for now */
678 }
679
aty_set_pll_8398(const struct fb_info_aty * info,const union aty_pll * pll)680 static void aty_set_pll_8398(const struct fb_info_aty *info,
681 const union aty_pll *pll)
682 {
683 u32 program_bits;
684 u32 locationAddr;
685
686 char old_crtc_ext_disp;
687 char tmp;
688
689 old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
690 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24),
691 info);
692
693 program_bits = pll->ics2595.program_bits;
694 locationAddr = pll->ics2595.locationAddr;
695
696 /* Program clock */
697 tmp = aty_ld_8(DAC_CNTL, info);
698 aty_st_8(DAC_CNTL, tmp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, info);
699
700 aty_st_8(DAC_REGS, locationAddr, info);
701 aty_st_8(DAC_REGS+1, (program_bits & 0xff00) >> 8, info);
702 aty_st_8(DAC_REGS+1, (program_bits & 0xff), info);
703
704 tmp = aty_ld_8(DAC_CNTL, info);
705 aty_st_8(DAC_CNTL, (tmp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3, info);
706
707 (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */
708 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info);
709
710 return;
711 }
712
713 const struct aty_pll_ops aty_pll_ch8398 = {
714 var_to_pll: aty_var_to_pll_8398,
715 pll_to_var: aty_pll_8398_to_var,
716 set_pll: aty_set_pll_8398,
717 init_pll: (void *)dummy
718 };
719
720
721 /*
722 * AT&T 20C408 Clock Chip
723 */
724
aty_var_to_pll_408(const struct fb_info_aty * info,u32 vclk_per,u8 bpp,u32 xres,union aty_pll * pll)725 static int aty_var_to_pll_408(const struct fb_info_aty *info, u32 vclk_per,
726 u8 bpp, u32 xres, union aty_pll *pll)
727 {
728 u32 mhz100; /* in 0.01 MHz */
729 u32 program_bits;
730 /* u32 post_divider; */
731 u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
732 u32 temp, tempB;
733 u16 remainder, preRemainder;
734 short divider = 0, tempA;
735
736 /* Calculate the programming word */
737 mhz100 = 100000000 / vclk_per;
738 mach64MinFreq = MIN_FREQ_2595;
739 mach64MaxFreq = MAX_FREQ_2595;
740 mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */
741
742 /* Calculate program word */
743 if (mhz100 == 0)
744 program_bits = 0xFF;
745 else {
746 if (mhz100 < mach64MinFreq)
747 mhz100 = mach64MinFreq;
748 if (mhz100 > mach64MaxFreq)
749 mhz100 = mach64MaxFreq;
750
751 while (mhz100 < (mach64MinFreq << 3)) {
752 mhz100 <<= 1;
753 divider += 0x40;
754 }
755
756 temp = (unsigned int)mhz100;
757 temp = (unsigned int)(temp * (MIN_N_408 + 2));
758 temp -= ((short)(mach64RefFreq << 1));
759
760 tempA = MIN_N_408;
761 preRemainder = 0xFFFF;
762
763 do {
764 tempB = temp;
765 remainder = tempB % mach64RefFreq;
766 tempB = tempB / mach64RefFreq;
767 if (((tempB & 0xFFFF) <= 255) && (remainder <= preRemainder)) {
768 preRemainder = remainder;
769 divider &= ~0x3f;
770 divider |= tempA;
771 divider = (divider & 0x00FF) + ((tempB & 0xFF) << 8);
772 }
773 temp += mhz100;
774 tempA++;
775 } while(tempA <= 32);
776
777 program_bits = divider;
778 }
779
780 pll->ics2595.program_bits = program_bits;
781 pll->ics2595.locationAddr = 0;
782 pll->ics2595.post_divider = divider; /* fuer nix */
783 pll->ics2595.period_in_ps = vclk_per;
784
785 return 0;
786 }
787
aty_pll_408_to_var(const struct fb_info_aty * info,const union aty_pll * pll)788 static u32 aty_pll_408_to_var(const struct fb_info_aty *info,
789 const union aty_pll *pll)
790 {
791 return(pll->ics2595.period_in_ps); /* default for now */
792 }
793
aty_set_pll_408(const struct fb_info_aty * info,const union aty_pll * pll)794 static void aty_set_pll_408(const struct fb_info_aty *info,
795 const union aty_pll *pll)
796 {
797 u32 program_bits;
798 u32 locationAddr;
799
800 u8 tmpA, tmpB, tmpC;
801 char old_crtc_ext_disp;
802
803 old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
804 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24),
805 info);
806
807 program_bits = pll->ics2595.program_bits;
808 locationAddr = pll->ics2595.locationAddr;
809
810 /* Program clock */
811 aty_dac_waste4(info);
812 tmpB = aty_ld_8(DAC_REGS + 2, info) | 1;
813 aty_dac_waste4(info);
814 aty_st_8(DAC_REGS + 2, tmpB, info);
815
816 tmpA = tmpB;
817 tmpC = tmpA;
818 tmpA |= 8;
819 tmpB = 1;
820
821 aty_st_8(DAC_REGS, tmpB, info);
822 aty_st_8(DAC_REGS + 2, tmpA, info);
823
824 udelay(400); /* delay for 400 us */
825
826 locationAddr = (locationAddr << 2) + 0x40;
827 tmpB = locationAddr;
828 tmpA = program_bits >> 8;
829
830 aty_st_8(DAC_REGS, tmpB, info);
831 aty_st_8(DAC_REGS + 2, tmpA, info);
832
833 tmpB = locationAddr + 1;
834 tmpA = (u8)program_bits;
835
836 aty_st_8(DAC_REGS, tmpB, info);
837 aty_st_8(DAC_REGS + 2, tmpA, info);
838
839 tmpB = locationAddr + 2;
840 tmpA = 0x77;
841
842 aty_st_8(DAC_REGS, tmpB, info);
843 aty_st_8(DAC_REGS + 2, tmpA, info);
844
845 udelay(400); /* delay for 400 us */
846 tmpA = tmpC & (~(1 | 8));
847 tmpB = 1;
848
849 aty_st_8(DAC_REGS, tmpB, info);
850 aty_st_8(DAC_REGS + 2, tmpA, info);
851
852 (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */
853 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info);
854
855 return;
856 }
857
858 const struct aty_pll_ops aty_pll_att20c408 = {
859 var_to_pll: aty_var_to_pll_408,
860 pll_to_var: aty_pll_408_to_var,
861 set_pll: aty_set_pll_408,
862 init_pll: (void *)dummy
863 };
864
865
866 /*
867 * Unsupported DAC and Clock Chip
868 */
869
aty_set_dac_unsupported(const struct fb_info_aty * info,const union aty_pll * pll,u32 bpp,u32 accel)870 static int aty_set_dac_unsupported(const struct fb_info_aty *info,
871 const union aty_pll *pll, u32 bpp,
872 u32 accel)
873 {
874 aty_st_le32(BUS_CNTL, 0x890e20f1, info);
875 aty_st_le32(DAC_CNTL, 0x47052100, info);
876 /* new in 2.2.3p1 from Geert. ???????? */
877 aty_st_le32(BUS_CNTL, 0x590e10ff, info);
878 aty_st_le32(DAC_CNTL, 0x47012100, info);
879 return 0;
880 }
881
882 const struct aty_dac_ops aty_dac_unsupported = {
883 set_dac: aty_set_dac_unsupported,
884 };
885
886 const struct aty_pll_ops aty_pll_unsupported = {
887 var_to_pll: (void *)dummy,
888 pll_to_var: (void *)dummy,
889 set_pll: (void *)dummy,
890 init_pll: (void *)dummy
891 };
892
893