mach64_gx.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:21k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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