Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mach64_gx.c
Go to the documentation of this file.
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);
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);
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);
271  par);
272 
273  aty_st_le32(BUS_CNTL, 0x890e20f1, par);
274  aty_st_le32(DAC_CNTL, 0x47052100, par);
275  return 0;
276 }
277 
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 
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);
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);
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);
477  old_clock_cntl | CLOCK_STROBE, par);
478 
479  mdelay(50); /* delay for 50 (15) ms */
481  ((pll->ics2595.locationAddr & 0x0F) | CLOCK_STROBE), par);
482  return;
483 }
484 
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);
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);
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);
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);
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);
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 
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 
903  .set_dac = aty_set_dac_unsupported,
904 };
905 
907  .var_to_pll = (void *) dummy,
908  .pll_to_var = (void *) dummy,
909  .set_pll = (void *) dummy,
910 };