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