root/drivers/video/fbdev/aty/mach64_gx.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. aty_dac_waste4
  2. aty_StrobeClock
  3. aty_st_514
  4. aty_set_dac_514
  5. aty_var_to_pll_514
  6. aty_pll_514_to_var
  7. aty_set_pll_514
  8. aty_set_dac_ATI68860_B
  9. aty_set_dac_ATT21C498
  10. aty_var_to_pll_18818
  11. aty_pll_18818_to_var
  12. aty_ICS2595_put1bit
  13. aty_set_pll18818
  14. aty_var_to_pll_1703
  15. aty_pll_1703_to_var
  16. aty_set_pll_1703
  17. aty_var_to_pll_8398
  18. aty_pll_8398_to_var
  19. aty_set_pll_8398
  20. aty_var_to_pll_408
  21. aty_pll_408_to_var
  22. aty_set_pll_408
  23. aty_set_dac_unsupported
  24. dummy

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

/* [<][>][^][v][top][bottom][index][help] */