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