0001
0002
0003
0004
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
0016
0017 #define REF_FREQ_2595 1432
0018 #define REF_DIV_2595 46
0019
0020 #define MAX_FREQ_2595 15938
0021 #define MIN_FREQ_2595 8000
0022
0023 #define ABS_MIN_FREQ_2595 1000
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
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
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
0073 aty_st_8(DAC_W_INDEX, offset & 0xff, par);
0074
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},
0093 {
0094 0, 0x45, 0x04, 0x0c, 0x01},
0095 {
0096 0, 0x45, 0x06, 0x0e, 0x00},
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);
0113 aty_st_514(0x04, tab[i].pixel_dly, par);
0114 aty_st_514(0x05, 0x00, par);
0115 aty_st_514(0x02, 0x01, par);
0116 aty_st_514(0x71, tab[i].misc2_cntl, par);
0117 aty_st_514(0x0a, tab[i].pixel_rep, par);
0118 aty_st_514(tab[i].pixel_cntl_index, tab[i].pixel_cntl_v1, par);
0119
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
0128
0129
0130 static struct {
0131 u32 limit;
0132 u8 m;
0133 u8 n;
0134 } RGB514_clocks[7] = {
0135 {
0136 8000, (3 << 6) | 20, 9},
0137 {
0138 10000, (1 << 6) | 19, 3},
0139 {
0140 13000, (1 << 6) | 2, 3},
0141 {
0142 14000, (2 << 6) | 8, 7},
0143 {
0144 16000, (1 << 6) | 44, 6},
0145 {
0146 25000, (1 << 6) | 15, 5},
0147 {
0148 50000, (0 << 6) | 53, 7},
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);
0181 aty_st_514(0x10, 0x01, par);
0182 aty_st_514(0x70, 0x01, par);
0183 aty_st_514(0x8f, 0x1f, par);
0184 aty_st_514(0x03, 0x00, par);
0185 aty_st_514(0x05, 0x00, par);
0186 aty_st_514(0x20, pll->ibm514.m, par);
0187 aty_st_514(0x21, pll->ibm514.n, par);
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
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 ;
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
0263
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
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 )
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
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;
0345 u32 program_bits;
0346 u32 post_divider;
0347
0348
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;
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);
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);
0447
0448 program_bits = pll->ics2595.program_bits;
0449 locationAddr = pll->ics2595.locationAddr;
0450
0451
0452 aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 0, par);
0453 aty_StrobeClock(par);
0454 aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 1, par);
0455 aty_StrobeClock(par);
0456
0457 aty_ICS2595_put1bit(1, par);
0458 aty_ICS2595_put1bit(0, par);
0459 aty_ICS2595_put1bit(0, par);
0460
0461 for (i = 0; i < 5; i++) {
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);
0472
0473 (void) aty_ld_8(DAC_REGS, par);
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);
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
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;
0499 u32 program_bits;
0500
0501 u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
0502 u32 temp, tempB;
0503 u16 remainder, preRemainder;
0504 short divider = 0, tempA;
0505
0506
0507 mhz100 = 100000000 / vclk_per;
0508 mach64MinFreq = MIN_FREQ_2595;
0509 mach64MaxFreq = MAX_FREQ_2595;
0510 mach64RefFreq = REF_FREQ_2595;
0511
0512
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;
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);
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
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);
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
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;
0617 u32 program_bits;
0618
0619 u32 mach64MinFreq, mach64MaxFreq;
0620 u16 m, n, k = 0, save_m, save_n, twoToKth;
0621
0622
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
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;
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;
0653 tempA *= (n + 8);
0654 tempB = twoToKth * 256;
0655 tempB *= (m + 2);
0656 fOut = tempA / tempB;
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);
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
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);
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
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;
0738 u32 program_bits;
0739
0740 u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
0741 u32 temp, tempB;
0742 u16 remainder, preRemainder;
0743 short divider = 0, tempA;
0744
0745
0746 mhz100 = 100000000 / vclk_per;
0747 mach64MinFreq = MIN_FREQ_2595;
0748 mach64MaxFreq = MAX_FREQ_2595;
0749 mach64RefFreq = REF_FREQ_2595;
0750
0751
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;
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);
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
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);
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);
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);
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
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
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 };