Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 
0003 /*
0004  *  ATI Mach64 GX Support
0005  */
0006 
0007 #include <linux/delay.h>
0008 #include <linux/fb.h>
0009 
0010 #include <asm/io.h>
0011 
0012 #include <video/mach64.h>
0013 #include "atyfb.h"
0014 
0015 /* Definitions for the ICS 2595 == ATI 18818_1 Clockchip */
0016 
0017 #define REF_FREQ_2595       1432    /*  14.33 MHz  (exact   14.31818) */
0018 #define REF_DIV_2595          46    /* really 43 on ICS 2595 !!!  */
0019                   /* ohne Prescaler */
0020 #define MAX_FREQ_2595      15938    /* 159.38 MHz  (really 170.486) */
0021 #define MIN_FREQ_2595       8000    /*  80.00 MHz  (        85.565) */
0022                   /* mit Prescaler 2, 4, 8 */
0023 #define ABS_MIN_FREQ_2595   1000    /*  10.00 MHz  (really  10.697) */
0024 #define N_ADJ_2595           257
0025 
0026 #define STOP_BITS_2595     0x1800
0027 
0028 
0029 #define MIN_N_408       2
0030 
0031 #define MIN_N_1703      6
0032 
0033 #define MIN_M       2
0034 #define MAX_M       30
0035 #define MIN_N       35
0036 #define MAX_N       255-8
0037 
0038 
0039     /*
0040      *  Support Functions
0041      */
0042 
0043 static void aty_dac_waste4(const struct atyfb_par *par)
0044 {
0045     (void) aty_ld_8(DAC_REGS, par);
0046 
0047     (void) aty_ld_8(DAC_REGS + 2, par);
0048     (void) aty_ld_8(DAC_REGS + 2, par);
0049     (void) aty_ld_8(DAC_REGS + 2, par);
0050     (void) aty_ld_8(DAC_REGS + 2, par);
0051 }
0052 
0053 static void aty_StrobeClock(const struct atyfb_par *par)
0054 {
0055     u8 tmp;
0056 
0057     udelay(26);
0058 
0059     tmp = aty_ld_8(CLOCK_CNTL, par);
0060     aty_st_8(CLOCK_CNTL + par->clk_wr_offset, tmp | CLOCK_STROBE, par);
0061     return;
0062 }
0063 
0064 
0065     /*
0066      *  IBM RGB514 DAC and Clock Chip
0067      */
0068 
0069 static void aty_st_514(int offset, u8 val, const struct atyfb_par *par)
0070 {
0071     aty_st_8(DAC_CNTL, 1, par);
0072     /* right addr byte */
0073     aty_st_8(DAC_W_INDEX, offset & 0xff, par);
0074     /* left addr byte */
0075     aty_st_8(DAC_DATA, (offset >> 8) & 0xff, par);
0076     aty_st_8(DAC_MASK, val, par);
0077     aty_st_8(DAC_CNTL, 0, par);
0078 }
0079 
0080 static int aty_set_dac_514(const struct fb_info *info,
0081                const union aty_pll *pll, u32 bpp, u32 accel)
0082 {
0083     struct atyfb_par *par = (struct atyfb_par *) info->par;
0084     static struct {
0085         u8 pixel_dly;
0086         u8 misc2_cntl;
0087         u8 pixel_rep;
0088         u8 pixel_cntl_index;
0089         u8 pixel_cntl_v1;
0090     } tab[3] = {
0091         {
0092         0, 0x41, 0x03, 0x71, 0x45}, /* 8 bpp */
0093         {
0094         0, 0x45, 0x04, 0x0c, 0x01}, /* 555 */
0095         {
0096         0, 0x45, 0x06, 0x0e, 0x00}, /* XRGB */
0097     };
0098     int i;
0099 
0100     switch (bpp) {
0101     case 8:
0102     default:
0103         i = 0;
0104         break;
0105     case 16:
0106         i = 1;
0107         break;
0108     case 32:
0109         i = 2;
0110         break;
0111     }
0112     aty_st_514(0x90, 0x00, par);    /* VRAM Mask Low */
0113     aty_st_514(0x04, tab[i].pixel_dly, par);    /* Horizontal Sync Control */
0114     aty_st_514(0x05, 0x00, par);    /* Power Management */
0115     aty_st_514(0x02, 0x01, par);    /* Misc Clock Control */
0116     aty_st_514(0x71, tab[i].misc2_cntl, par);   /* Misc Control 2 */
0117     aty_st_514(0x0a, tab[i].pixel_rep, par);    /* Pixel Format */
0118     aty_st_514(tab[i].pixel_cntl_index, tab[i].pixel_cntl_v1, par);
0119     /* Misc Control 2 / 16 BPP Control / 32 BPP Control */
0120     return 0;
0121 }
0122 
0123 static int aty_var_to_pll_514(const struct fb_info *info, u32 vclk_per,
0124                   u32 bpp, union aty_pll *pll)
0125 {
0126     /*
0127      *  FIXME: use real calculations instead of using fixed values from the old
0128      *         driver
0129      */
0130     static struct {
0131         u32 limit;  /* pixlock rounding limit (arbitrary) */
0132         u8 m;       /* (df<<6) | vco_div_count */
0133         u8 n;       /* ref_div_count */
0134     } RGB514_clocks[7] = {
0135         {
0136         8000, (3 << 6) | 20, 9},    /*  7395 ps / 135.2273 MHz */
0137         {
0138         10000, (1 << 6) | 19, 3},   /*  9977 ps / 100.2273 MHz */
0139         {
0140         13000, (1 << 6) | 2, 3},    /* 12509 ps /  79.9432 MHz */
0141         {
0142         14000, (2 << 6) | 8, 7},    /* 13394 ps /  74.6591 MHz */
0143         {
0144         16000, (1 << 6) | 44, 6},   /* 15378 ps /  65.0284 MHz */
0145         {
0146         25000, (1 << 6) | 15, 5},   /* 17460 ps /  57.2727 MHz */
0147         {
0148         50000, (0 << 6) | 53, 7},   /* 33145 ps /  30.1705 MHz */
0149     };
0150     int i;
0151 
0152     for (i = 0; i < ARRAY_SIZE(RGB514_clocks); i++)
0153         if (vclk_per <= RGB514_clocks[i].limit) {
0154             pll->ibm514.m = RGB514_clocks[i].m;
0155             pll->ibm514.n = RGB514_clocks[i].n;
0156             return 0;
0157         }
0158     return -EINVAL;
0159 }
0160 
0161 static u32 aty_pll_514_to_var(const struct fb_info *info,
0162                   const union aty_pll *pll)
0163 {
0164     struct atyfb_par *par = (struct atyfb_par *) info->par;
0165     u8 df, vco_div_count, ref_div_count;
0166 
0167     df = pll->ibm514.m >> 6;
0168     vco_div_count = pll->ibm514.m & 0x3f;
0169     ref_div_count = pll->ibm514.n;
0170 
0171     return ((par->ref_clk_per * ref_div_count) << (3 - df))/
0172                 (vco_div_count + 65);
0173 }
0174 
0175 static void aty_set_pll_514(const struct fb_info *info,
0176                 const union aty_pll *pll)
0177 {
0178     struct atyfb_par *par = (struct atyfb_par *) info->par;
0179 
0180     aty_st_514(0x06, 0x02, par);    /* DAC Operation */
0181     aty_st_514(0x10, 0x01, par);    /* PLL Control 1 */
0182     aty_st_514(0x70, 0x01, par);    /* Misc Control 1 */
0183     aty_st_514(0x8f, 0x1f, par);    /* PLL Ref. Divider Input */
0184     aty_st_514(0x03, 0x00, par);    /* Sync Control */
0185     aty_st_514(0x05, 0x00, par);    /* Power Management */
0186     aty_st_514(0x20, pll->ibm514.m, par);   /* F0 / M0 */
0187     aty_st_514(0x21, pll->ibm514.n, par);   /* F1 / N0 */
0188 }
0189 
0190 const struct aty_dac_ops aty_dac_ibm514 = {
0191     .set_dac    = aty_set_dac_514,
0192 };
0193 
0194 const struct aty_pll_ops aty_pll_ibm514 = {
0195     .var_to_pll = aty_var_to_pll_514,
0196     .pll_to_var = aty_pll_514_to_var,
0197     .set_pll    = aty_set_pll_514,
0198 };
0199 
0200 
0201     /*
0202      *  ATI 68860-B DAC
0203      */
0204 
0205 static int aty_set_dac_ATI68860_B(const struct fb_info *info,
0206                   const union aty_pll *pll, u32 bpp,
0207                   u32 accel)
0208 {
0209     struct atyfb_par *par = (struct atyfb_par *) info->par;
0210     u32 gModeReg, devSetupRegA, temp, mask;
0211 
0212     gModeReg = 0;
0213     devSetupRegA = 0;
0214 
0215     switch (bpp) {
0216     case 8:
0217         gModeReg = 0x83;
0218         devSetupRegA =
0219             0x60 | 0x00 /*(info->mach64DAC8Bit ? 0x00 : 0x01) */ ;
0220         break;
0221     case 15:
0222         gModeReg = 0xA0;
0223         devSetupRegA = 0x60;
0224         break;
0225     case 16:
0226         gModeReg = 0xA1;
0227         devSetupRegA = 0x60;
0228         break;
0229     case 24:
0230         gModeReg = 0xC0;
0231         devSetupRegA = 0x60;
0232         break;
0233     case 32:
0234         gModeReg = 0xE3;
0235         devSetupRegA = 0x60;
0236         break;
0237     }
0238 
0239     if (!accel) {
0240         gModeReg = 0x80;
0241         devSetupRegA = 0x61;
0242     }
0243 
0244     temp = aty_ld_8(DAC_CNTL, par);
0245     aty_st_8(DAC_CNTL, (temp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3,
0246          par);
0247 
0248     aty_st_8(DAC_REGS + 2, 0x1D, par);
0249     aty_st_8(DAC_REGS + 3, gModeReg, par);
0250     aty_st_8(DAC_REGS, 0x02, par);
0251 
0252     temp = aty_ld_8(DAC_CNTL, par);
0253     aty_st_8(DAC_CNTL, temp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, par);
0254 
0255     if (info->fix.smem_len < ONE_MB)
0256         mask = 0x04;
0257     else if (info->fix.smem_len == ONE_MB)
0258         mask = 0x08;
0259     else
0260         mask = 0x0C;
0261 
0262     /* The following assumes that the BIOS has correctly set R7 of the
0263      * Device Setup Register A at boot time.
0264      */
0265 #define A860_DELAY_L    0x80
0266 
0267     temp = aty_ld_8(DAC_REGS, par);
0268     aty_st_8(DAC_REGS, (devSetupRegA | mask) | (temp & A860_DELAY_L),
0269          par);
0270     temp = aty_ld_8(DAC_CNTL, par);
0271     aty_st_8(DAC_CNTL, (temp & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3)),
0272          par);
0273 
0274     aty_st_le32(BUS_CNTL, 0x890e20f1, par);
0275     aty_st_le32(DAC_CNTL, 0x47052100, par);
0276     return 0;
0277 }
0278 
0279 const struct aty_dac_ops aty_dac_ati68860b = {
0280     .set_dac    = aty_set_dac_ATI68860_B,
0281 };
0282 
0283 
0284     /*
0285      *  AT&T 21C498 DAC
0286      */
0287 
0288 static int aty_set_dac_ATT21C498(const struct fb_info *info,
0289                  const union aty_pll *pll, u32 bpp,
0290                  u32 accel)
0291 {
0292     struct atyfb_par *par = (struct atyfb_par *) info->par;
0293     u32 dotClock;
0294     int muxmode = 0;
0295     int DACMask = 0;
0296 
0297     dotClock = 100000000 / pll->ics2595.period_in_ps;
0298 
0299     switch (bpp) {
0300     case 8:
0301         if (dotClock > 8000) {
0302             DACMask = 0x24;
0303             muxmode = 1;
0304         } else
0305             DACMask = 0x04;
0306         break;
0307     case 15:
0308         DACMask = 0x16;
0309         break;
0310     case 16:
0311         DACMask = 0x36;
0312         break;
0313     case 24:
0314         DACMask = 0xE6;
0315         break;
0316     case 32:
0317         DACMask = 0xE6;
0318         break;
0319     }
0320 
0321     if (1 /* info->mach64DAC8Bit */ )
0322         DACMask |= 0x02;
0323 
0324     aty_dac_waste4(par);
0325     aty_st_8(DAC_REGS + 2, DACMask, par);
0326 
0327     aty_st_le32(BUS_CNTL, 0x890e20f1, par);
0328     aty_st_le32(DAC_CNTL, 0x00072000, par);
0329     return muxmode;
0330 }
0331 
0332 const struct aty_dac_ops aty_dac_att21c498 = {
0333     .set_dac    = aty_set_dac_ATT21C498,
0334 };
0335 
0336 
0337     /*
0338      *  ATI 18818 / ICS 2595 Clock Chip
0339      */
0340 
0341 static int aty_var_to_pll_18818(const struct fb_info *info, u32 vclk_per,
0342                 u32 bpp, union aty_pll *pll)
0343 {
0344     u32 MHz100;     /* in 0.01 MHz */
0345     u32 program_bits;
0346     u32 post_divider;
0347 
0348     /* Calculate the programming word */
0349     MHz100 = 100000000 / vclk_per;
0350 
0351     program_bits = -1;
0352     post_divider = 1;
0353 
0354     if (MHz100 > MAX_FREQ_2595) {
0355         return -EINVAL;
0356     } else if (MHz100 < ABS_MIN_FREQ_2595) {
0357         return -EINVAL;
0358     } else {
0359         while (MHz100 < MIN_FREQ_2595) {
0360             MHz100 *= 2;
0361             post_divider *= 2;
0362         }
0363     }
0364     MHz100 *= 1000;
0365     MHz100 = (REF_DIV_2595 * MHz100) / REF_FREQ_2595;
0366  
0367     MHz100 += 500;      /* + 0.5 round */
0368     MHz100 /= 1000;
0369 
0370     if (program_bits == -1) {
0371         program_bits = MHz100 - N_ADJ_2595;
0372         switch (post_divider) {
0373         case 1:
0374             program_bits |= 0x0600;
0375             break;
0376         case 2:
0377             program_bits |= 0x0400;
0378             break;
0379         case 4:
0380             program_bits |= 0x0200;
0381             break;
0382         case 8:
0383         default:
0384             break;
0385         }
0386     }
0387 
0388     program_bits |= STOP_BITS_2595;
0389 
0390     pll->ics2595.program_bits = program_bits;
0391     pll->ics2595.locationAddr = 0;
0392     pll->ics2595.post_divider = post_divider;
0393     pll->ics2595.period_in_ps = vclk_per;
0394 
0395     return 0;
0396 }
0397 
0398 static u32 aty_pll_18818_to_var(const struct fb_info *info,
0399                 const union aty_pll *pll)
0400 {
0401     return (pll->ics2595.period_in_ps); /* default for now */
0402 }
0403 
0404 static void aty_ICS2595_put1bit(u8 data, const struct atyfb_par *par)
0405 {
0406     u8 tmp;
0407 
0408     data &= 0x01;
0409     tmp = aty_ld_8(CLOCK_CNTL, par);
0410     aty_st_8(CLOCK_CNTL + par->clk_wr_offset,
0411          (tmp & ~0x04) | (data << 2), par);
0412 
0413     tmp = aty_ld_8(CLOCK_CNTL, par);
0414     aty_st_8(CLOCK_CNTL + par->clk_wr_offset, (tmp & ~0x08) | (0 << 3),
0415          par);
0416 
0417     aty_StrobeClock(par);
0418 
0419     tmp = aty_ld_8(CLOCK_CNTL, par);
0420     aty_st_8(CLOCK_CNTL + par->clk_wr_offset, (tmp & ~0x08) | (1 << 3),
0421          par);
0422 
0423     aty_StrobeClock(par);
0424     return;
0425 }
0426 
0427 static void aty_set_pll18818(const struct fb_info *info,
0428                  const union aty_pll *pll)
0429 {
0430     struct atyfb_par *par = (struct atyfb_par *) info->par;
0431     u32 program_bits;
0432     u32 locationAddr;
0433 
0434     u32 i;
0435 
0436     u8 old_clock_cntl;
0437     u8 old_crtc_ext_disp;
0438 
0439     old_clock_cntl = aty_ld_8(CLOCK_CNTL, par);
0440     aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 0, par);
0441 
0442     old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
0443     aty_st_8(CRTC_GEN_CNTL + 3,
0444          old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par);
0445 
0446     mdelay(15);     /* delay for 50 (15) ms */
0447 
0448     program_bits = pll->ics2595.program_bits;
0449     locationAddr = pll->ics2595.locationAddr;
0450 
0451     /* Program the clock chip */
0452     aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 0, par);  /* Strobe = 0 */
0453     aty_StrobeClock(par);
0454     aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 1, par);  /* Strobe = 0 */
0455     aty_StrobeClock(par);
0456 
0457     aty_ICS2595_put1bit(1, par);    /* Send start bits */
0458     aty_ICS2595_put1bit(0, par);    /* Start bit */
0459     aty_ICS2595_put1bit(0, par);    /* Read / ~Write */
0460 
0461     for (i = 0; i < 5; i++) {   /* Location 0..4 */
0462         aty_ICS2595_put1bit(locationAddr & 1, par);
0463         locationAddr >>= 1;
0464     }
0465 
0466     for (i = 0; i < 8 + 1 + 2 + 2; i++) {
0467         aty_ICS2595_put1bit(program_bits & 1, par);
0468         program_bits >>= 1;
0469     }
0470 
0471     mdelay(1);      /* delay for 1 ms */
0472 
0473     (void) aty_ld_8(DAC_REGS, par); /* Clear DAC Counter */
0474     aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par);
0475     aty_st_8(CLOCK_CNTL + par->clk_wr_offset,
0476          old_clock_cntl | CLOCK_STROBE, par);
0477 
0478     mdelay(50);     /* delay for 50 (15) ms */
0479     aty_st_8(CLOCK_CNTL + par->clk_wr_offset,
0480          ((pll->ics2595.locationAddr & 0x0F) | CLOCK_STROBE), par);
0481     return;
0482 }
0483 
0484 const struct aty_pll_ops aty_pll_ati18818_1 = {
0485     .var_to_pll = aty_var_to_pll_18818,
0486     .pll_to_var = aty_pll_18818_to_var,
0487     .set_pll    = aty_set_pll18818,
0488 };
0489 
0490 
0491     /*
0492      *  STG 1703 Clock Chip
0493      */
0494 
0495 static int aty_var_to_pll_1703(const struct fb_info *info, u32 vclk_per,
0496                    u32 bpp, union aty_pll *pll)
0497 {
0498     u32 mhz100;     /* in 0.01 MHz */
0499     u32 program_bits;
0500     /* u32 post_divider; */
0501     u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
0502     u32 temp, tempB;
0503     u16 remainder, preRemainder;
0504     short divider = 0, tempA;
0505 
0506     /* Calculate the programming word */
0507     mhz100 = 100000000 / vclk_per;
0508     mach64MinFreq = MIN_FREQ_2595;
0509     mach64MaxFreq = MAX_FREQ_2595;
0510     mach64RefFreq = REF_FREQ_2595;  /* 14.32 MHz */
0511 
0512     /* Calculate program word */
0513     if (mhz100 == 0)
0514         program_bits = 0xE0;
0515     else {
0516         if (mhz100 < mach64MinFreq)
0517             mhz100 = mach64MinFreq;
0518         if (mhz100 > mach64MaxFreq)
0519             mhz100 = mach64MaxFreq;
0520 
0521         divider = 0;
0522         while (mhz100 < (mach64MinFreq << 3)) {
0523             mhz100 <<= 1;
0524             divider += 0x20;
0525         }
0526 
0527         temp = (unsigned int) (mhz100);
0528         temp = (unsigned int) (temp * (MIN_N_1703 + 2));
0529         temp -= (short) (mach64RefFreq << 1);
0530 
0531         tempA = MIN_N_1703;
0532         preRemainder = 0xffff;
0533 
0534         do {
0535             tempB = temp;
0536             remainder = tempB % mach64RefFreq;
0537             tempB = tempB / mach64RefFreq;
0538 
0539             if ((tempB & 0xffff) <= 127
0540                 && (remainder <= preRemainder)) {
0541                 preRemainder = remainder;
0542                 divider &= ~0x1f;
0543                 divider |= tempA;
0544                 divider =
0545                     (divider & 0x00ff) +
0546                     ((tempB & 0xff) << 8);
0547             }
0548 
0549             temp += mhz100;
0550             tempA++;
0551         } while (tempA <= (MIN_N_1703 << 1));
0552 
0553         program_bits = divider;
0554     }
0555 
0556     pll->ics2595.program_bits = program_bits;
0557     pll->ics2595.locationAddr = 0;
0558     pll->ics2595.post_divider = divider;    /* fuer nix */
0559     pll->ics2595.period_in_ps = vclk_per;
0560 
0561     return 0;
0562 }
0563 
0564 static u32 aty_pll_1703_to_var(const struct fb_info *info,
0565                    const union aty_pll *pll)
0566 {
0567     return (pll->ics2595.period_in_ps); /* default for now */
0568 }
0569 
0570 static void aty_set_pll_1703(const struct fb_info *info,
0571                  const union aty_pll *pll)
0572 {
0573     struct atyfb_par *par = (struct atyfb_par *) info->par;
0574     u32 program_bits;
0575     u32 locationAddr;
0576 
0577     char old_crtc_ext_disp;
0578 
0579     old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
0580     aty_st_8(CRTC_GEN_CNTL + 3,
0581          old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par);
0582 
0583     program_bits = pll->ics2595.program_bits;
0584     locationAddr = pll->ics2595.locationAddr;
0585 
0586     /* Program clock */
0587     aty_dac_waste4(par);
0588 
0589     (void) aty_ld_8(DAC_REGS + 2, par);
0590     aty_st_8(DAC_REGS + 2, (locationAddr << 1) + 0x20, par);
0591     aty_st_8(DAC_REGS + 2, 0, par);
0592     aty_st_8(DAC_REGS + 2, (program_bits & 0xFF00) >> 8, par);
0593     aty_st_8(DAC_REGS + 2, (program_bits & 0xFF), par);
0594 
0595     (void) aty_ld_8(DAC_REGS, par); /* Clear DAC Counter */
0596     aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par);
0597     return;
0598 }
0599 
0600 const struct aty_pll_ops aty_pll_stg1703 = {
0601     .var_to_pll = aty_var_to_pll_1703,
0602     .pll_to_var = aty_pll_1703_to_var,
0603     .set_pll    = aty_set_pll_1703,
0604 };
0605 
0606 
0607     /*
0608      *  Chrontel 8398 Clock Chip
0609      */
0610 
0611 static int aty_var_to_pll_8398(const struct fb_info *info, u32 vclk_per,
0612                    u32 bpp, union aty_pll *pll)
0613 {
0614     u32 tempA, tempB, fOut, longMHz100, diff, preDiff;
0615 
0616     u32 mhz100;     /* in 0.01 MHz */
0617     u32 program_bits;
0618     /* u32 post_divider; */
0619     u32 mach64MinFreq, mach64MaxFreq;
0620     u16 m, n, k = 0, save_m, save_n, twoToKth;
0621 
0622     /* Calculate the programming word */
0623     mhz100 = 100000000 / vclk_per;
0624     mach64MinFreq = MIN_FREQ_2595;
0625     mach64MaxFreq = MAX_FREQ_2595;
0626 
0627     save_m = 0;
0628     save_n = 0;
0629 
0630     /* Calculate program word */
0631     if (mhz100 == 0)
0632         program_bits = 0xE0;
0633     else {
0634         if (mhz100 < mach64MinFreq)
0635             mhz100 = mach64MinFreq;
0636         if (mhz100 > mach64MaxFreq)
0637             mhz100 = mach64MaxFreq;
0638 
0639         longMHz100 = mhz100 * 256 / 100;    /* 8 bit scale this */
0640 
0641         while (mhz100 < (mach64MinFreq << 3)) {
0642             mhz100 <<= 1;
0643             k++;
0644         }
0645 
0646         twoToKth = 1 << k;
0647         diff = 0;
0648         preDiff = 0xFFFFFFFF;
0649 
0650         for (m = MIN_M; m <= MAX_M; m++) {
0651             for (n = MIN_N; n <= MAX_N; n++) {
0652                 tempA = 938356;     /* 14.31818 * 65536 */
0653                 tempA *= (n + 8);   /* 43..256 */
0654                 tempB = twoToKth * 256;
0655                 tempB *= (m + 2);   /* 4..32 */
0656                 fOut = tempA / tempB;   /* 8 bit scale */
0657 
0658                 if (longMHz100 > fOut)
0659                     diff = longMHz100 - fOut;
0660                 else
0661                     diff = fOut - longMHz100;
0662 
0663                 if (diff < preDiff) {
0664                     save_m = m;
0665                     save_n = n;
0666                     preDiff = diff;
0667                 }
0668             }
0669         }
0670 
0671         program_bits = (k << 6) + (save_m) + (save_n << 8);
0672     }
0673 
0674     pll->ics2595.program_bits = program_bits;
0675     pll->ics2595.locationAddr = 0;
0676     pll->ics2595.post_divider = 0;
0677     pll->ics2595.period_in_ps = vclk_per;
0678 
0679     return 0;
0680 }
0681 
0682 static u32 aty_pll_8398_to_var(const struct fb_info *info,
0683                    const union aty_pll *pll)
0684 {
0685     return (pll->ics2595.period_in_ps); /* default for now */
0686 }
0687 
0688 static void aty_set_pll_8398(const struct fb_info *info,
0689                  const union aty_pll *pll)
0690 {
0691     struct atyfb_par *par = (struct atyfb_par *) info->par;
0692     u32 program_bits;
0693     u32 locationAddr;
0694 
0695     char old_crtc_ext_disp;
0696     char tmp;
0697 
0698     old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
0699     aty_st_8(CRTC_GEN_CNTL + 3,
0700          old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par);
0701 
0702     program_bits = pll->ics2595.program_bits;
0703     locationAddr = pll->ics2595.locationAddr;
0704 
0705     /* Program clock */
0706     tmp = aty_ld_8(DAC_CNTL, par);
0707     aty_st_8(DAC_CNTL, tmp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, par);
0708 
0709     aty_st_8(DAC_REGS, locationAddr, par);
0710     aty_st_8(DAC_REGS + 1, (program_bits & 0xff00) >> 8, par);
0711     aty_st_8(DAC_REGS + 1, (program_bits & 0xff), par);
0712 
0713     tmp = aty_ld_8(DAC_CNTL, par);
0714     aty_st_8(DAC_CNTL, (tmp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3,
0715          par);
0716 
0717     (void) aty_ld_8(DAC_REGS, par); /* Clear DAC Counter */
0718     aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par);
0719 
0720     return;
0721 }
0722 
0723 const struct aty_pll_ops aty_pll_ch8398 = {
0724     .var_to_pll = aty_var_to_pll_8398,
0725     .pll_to_var = aty_pll_8398_to_var,
0726     .set_pll    = aty_set_pll_8398,
0727 };
0728 
0729 
0730     /*
0731      *  AT&T 20C408 Clock Chip
0732      */
0733 
0734 static int aty_var_to_pll_408(const struct fb_info *info, u32 vclk_per,
0735                   u32 bpp, union aty_pll *pll)
0736 {
0737     u32 mhz100;     /* in 0.01 MHz */
0738     u32 program_bits;
0739     /* u32 post_divider; */
0740     u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
0741     u32 temp, tempB;
0742     u16 remainder, preRemainder;
0743     short divider = 0, tempA;
0744 
0745     /* Calculate the programming word */
0746     mhz100 = 100000000 / vclk_per;
0747     mach64MinFreq = MIN_FREQ_2595;
0748     mach64MaxFreq = MAX_FREQ_2595;
0749     mach64RefFreq = REF_FREQ_2595;  /* 14.32 MHz */
0750 
0751     /* Calculate program word */
0752     if (mhz100 == 0)
0753         program_bits = 0xFF;
0754     else {
0755         if (mhz100 < mach64MinFreq)
0756             mhz100 = mach64MinFreq;
0757         if (mhz100 > mach64MaxFreq)
0758             mhz100 = mach64MaxFreq;
0759 
0760         while (mhz100 < (mach64MinFreq << 3)) {
0761             mhz100 <<= 1;
0762             divider += 0x40;
0763         }
0764 
0765         temp = (unsigned int) mhz100;
0766         temp = (unsigned int) (temp * (MIN_N_408 + 2));
0767         temp -= ((short) (mach64RefFreq << 1));
0768 
0769         tempA = MIN_N_408;
0770         preRemainder = 0xFFFF;
0771 
0772         do {
0773             tempB = temp;
0774             remainder = tempB % mach64RefFreq;
0775             tempB = tempB / mach64RefFreq;
0776             if (((tempB & 0xFFFF) <= 255)
0777                 && (remainder <= preRemainder)) {
0778                 preRemainder = remainder;
0779                 divider &= ~0x3f;
0780                 divider |= tempA;
0781                 divider =
0782                     (divider & 0x00FF) +
0783                     ((tempB & 0xFF) << 8);
0784             }
0785             temp += mhz100;
0786             tempA++;
0787         } while (tempA <= 32);
0788 
0789         program_bits = divider;
0790     }
0791 
0792     pll->ics2595.program_bits = program_bits;
0793     pll->ics2595.locationAddr = 0;
0794     pll->ics2595.post_divider = divider;    /* fuer nix */
0795     pll->ics2595.period_in_ps = vclk_per;
0796 
0797     return 0;
0798 }
0799 
0800 static u32 aty_pll_408_to_var(const struct fb_info *info,
0801                   const union aty_pll *pll)
0802 {
0803     return (pll->ics2595.period_in_ps); /* default for now */
0804 }
0805 
0806 static void aty_set_pll_408(const struct fb_info *info,
0807                 const union aty_pll *pll)
0808 {
0809     struct atyfb_par *par = (struct atyfb_par *) info->par;
0810     u32 program_bits;
0811     u32 locationAddr;
0812 
0813     u8 tmpA, tmpB, tmpC;
0814     char old_crtc_ext_disp;
0815 
0816     old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
0817     aty_st_8(CRTC_GEN_CNTL + 3,
0818          old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par);
0819 
0820     program_bits = pll->ics2595.program_bits;
0821     locationAddr = pll->ics2595.locationAddr;
0822 
0823     /* Program clock */
0824     aty_dac_waste4(par);
0825     tmpB = aty_ld_8(DAC_REGS + 2, par) | 1;
0826     aty_dac_waste4(par);
0827     aty_st_8(DAC_REGS + 2, tmpB, par);
0828 
0829     tmpA = tmpB;
0830     tmpC = tmpA;
0831     tmpA |= 8;
0832     tmpB = 1;
0833 
0834     aty_st_8(DAC_REGS, tmpB, par);
0835     aty_st_8(DAC_REGS + 2, tmpA, par);
0836 
0837     udelay(400);        /* delay for 400 us */
0838 
0839     locationAddr = (locationAddr << 2) + 0x40;
0840     tmpB = locationAddr;
0841     tmpA = program_bits >> 8;
0842 
0843     aty_st_8(DAC_REGS, tmpB, par);
0844     aty_st_8(DAC_REGS + 2, tmpA, par);
0845 
0846     tmpB = locationAddr + 1;
0847     tmpA = (u8) program_bits;
0848 
0849     aty_st_8(DAC_REGS, tmpB, par);
0850     aty_st_8(DAC_REGS + 2, tmpA, par);
0851 
0852     tmpB = locationAddr + 2;
0853     tmpA = 0x77;
0854 
0855     aty_st_8(DAC_REGS, tmpB, par);
0856     aty_st_8(DAC_REGS + 2, tmpA, par);
0857 
0858     udelay(400);        /* delay for 400 us */
0859     tmpA = tmpC & (~(1 | 8));
0860     tmpB = 1;
0861 
0862     aty_st_8(DAC_REGS, tmpB, par);
0863     aty_st_8(DAC_REGS + 2, tmpA, par);
0864 
0865     (void) aty_ld_8(DAC_REGS, par); /* Clear DAC Counter */
0866     aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par);
0867     return;
0868 }
0869 
0870 const struct aty_pll_ops aty_pll_att20c408 = {
0871     .var_to_pll = aty_var_to_pll_408,
0872     .pll_to_var = aty_pll_408_to_var,
0873     .set_pll    = aty_set_pll_408,
0874 };
0875 
0876 
0877     /*
0878      *  Unsupported DAC and Clock Chip
0879      */
0880 
0881 static int aty_set_dac_unsupported(const struct fb_info *info,
0882                    const union aty_pll *pll, u32 bpp,
0883                    u32 accel)
0884 {
0885     struct atyfb_par *par = (struct atyfb_par *) info->par;
0886 
0887     aty_st_le32(BUS_CNTL, 0x890e20f1, par);
0888     aty_st_le32(DAC_CNTL, 0x47052100, par);
0889     /* new in 2.2.3p1 from Geert. ???????? */
0890     aty_st_le32(BUS_CNTL, 0x590e10ff, par);
0891     aty_st_le32(DAC_CNTL, 0x47012100, par);
0892     return 0;
0893 }
0894 
0895 static int dummy(void)
0896 {
0897     return 0;
0898 }
0899 
0900 const struct aty_dac_ops aty_dac_unsupported = {
0901     .set_dac    = aty_set_dac_unsupported,
0902 };
0903 
0904 const struct aty_pll_ops aty_pll_unsupported = {
0905     .var_to_pll = (void *) dummy,
0906     .pll_to_var = (void *) dummy,
0907     .set_pll    = (void *) dummy,
0908 };