12 #include <asm/machdep.h>
116 #define Maximum_DSP_PRECISION 7
117 static u8 postdividers[] = {1,2,4,8,3};
121 u32 dsp_off, dsp_on, dsp_xclks;
122 u32 multiplier, divider, ras_multiplier, ras_divider,
tmp;
133 divider = divider * (bpp >> 2);
140 #ifdef CONFIG_FB_ATY_GENERIC_LCD
141 if (pll->xres != 0) {
144 multiplier = multiplier * par->lcd_width;
145 divider = divider * pll->xres & ~7;
147 ras_multiplier = ras_multiplier * par->lcd_width;
148 ras_divider = ras_divider * pll->xres & ~7;
153 while (((multiplier | divider) & 1) == 0) {
154 multiplier = multiplier >> 1;
155 divider = divider >> 1;
159 tmp = ((multiplier * pll->
fifo_size) << vshift) / divider;
161 for (dsp_precision = -5;
tmp; dsp_precision++)
163 if (dsp_precision < 0)
168 xshift = 6 - dsp_precision;
172 dsp_off = ((multiplier * (pll->
fifo_size - 1)) << vshift) / divider -
173 (1 << (vshift - xshift));
179 dsp_on = ((multiplier << vshift) + divider) / divider;
180 tmp = ((ras_multiplier << xshift) + ras_divider) / ras_divider;
188 dsp_on = ((dsp_on +
tmp) / (tmp + 1)) * (tmp + 1);
190 if (dsp_on >= ((dsp_off / (tmp + 1)) * (tmp + 1))) {
191 dsp_on = dsp_off - (multiplier << vshift) / divider;
192 dsp_on = (dsp_on / (tmp + 1)) * (tmp + 1);
196 dsp_xclks = ((multiplier << (vshift + 5)) + divider) / divider;
202 printk(
"atyfb(%s): dsp_config 0x%08x, dsp_on_off 0x%08x\n",
208 static int aty_valid_pll_ct(
const struct fb_info *info,
u32 vclk_per,
struct pll_ct *pll)
216 if (q < 16*8 || q > 255*8) {
230 printk(
"atyfb(%s): pllvclk=%d MHz, vclk=%d MHz\n",
240 while (ecp > par->
pll_limits.ecp_max && ecp_div < 2) {
250 static int aty_var_to_pll_ct(
const struct fb_info *info,
u32 vclk_per,
u32 bpp,
union aty_pll *pll)
255 if ((
err = aty_valid_pll_ct(info, vclk_per, &pll->
ct)))
257 if (
M64_HAS(GTB_DSP) && (
err = aty_dsp_gt(info, bpp, &pll->
ct)))
263 static u32 aty_pll_to_var_ct(
const struct fb_info *info,
const union aty_pll *pll)
267 ret = par->
ref_clk_per * pll->
ct.pll_ref_div * pll->
ct.vclk_post_div_real / pll->
ct.vclk_fb_div / 2;
268 #ifdef CONFIG_FB_ATY_GENERIC_LCD
269 if(pll->
ct.xres > 0) {
270 ret *= par->lcd_width;
275 printk(
"atyfb(%s): calculated 0x%08X(%i)\n", __func__,
ret,
ret);
283 u32 crtc_gen_cntl, lcd_gen_cntrl;
288 printk(
"atyfb(%s): about to program:\n"
289 "pll_ext_cntl=0x%02x pll_gen_cntl=0x%02x pll_vclk_cntl=0x%02x\n",
291 pll->
ct.pll_ext_cntl, pll->
ct.pll_gen_cntl, pll->
ct.pll_vclk_cntl);
293 printk(
"atyfb(%s): setting clock %lu for FeedBackDivider %i, ReferenceDivider %i, PostDivider %i(%i)\n",
296 pll->
ct.pll_ref_div, pll->
ct.vclk_post_div, pll->
ct.vclk_post_div_real);
298 #ifdef CONFIG_FB_ATY_GENERIC_LCD
299 if (par->lcd_table != 0) {
318 tmp &= ~(0x03
U << tmp2);
319 tmp |= ((pll->
ct.vclk_post_div & 0x03
U) << tmp2);
326 tmp |= pll->
ct.pll_ext_cntl;
331 aty_st_pll_ct(tmp, (pll->
ct.vclk_fb_div & 0xFFU), par);
344 if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
356 aty_st_pll_ct(
DLL_CNTL, dll_cntl, par);
362 aty_st_pll_ct(
DLL_CNTL, dll_cntl, par);
364 aty_st_pll_ct(
DLL_CNTL, dll_cntl | 0x40, par);
366 aty_st_pll_ct(
DLL_CNTL, dll_cntl & ~0x40, par);
368 #ifdef CONFIG_FB_ATY_GENERIC_LCD
369 if (par->lcd_table != 0) {
404 u8 mpost_div, xpost_div, sclk_post_div_real;
406 u32 dsp_config, dsp_on_off, vga_dsp_config, vga_dsp_on_off;
408 int pllmclk, pllsclk;
411 pll->
ct.xclk_post_div = pll->
ct.pll_ext_cntl & 0x07;
412 pll->
ct.xclk_ref_div = 1;
413 switch (pll->
ct.xclk_post_div) {
414 case 0:
case 1:
case 2:
case 3:
418 pll->
ct.xclk_ref_div = 3;
419 pll->
ct.xclk_post_div = 0;
423 printk(
KERN_CRIT "atyfb: Unsupported xclk source: %d.\n", pll->
ct.xclk_post_div);
426 pll->
ct.mclk_fb_mult = 2;
428 pll->
ct.mclk_fb_mult = 4;
429 pll->
ct.xclk_post_div -= 1;
433 printk(
"atyfb(%s): mclk_fb_mult=%d, xclk_post_div=%d\n",
434 __func__, pll->
ct.mclk_fb_mult, pll->
ct.xclk_post_div);
438 trp = (memcntl & 0x300) >> 8;
440 pll->
ct.xclkpagefaultdelay = ((memcntl & 0xc00) >> 10) + ((memcntl & 0x1000) >> 12) + trp + 2;
441 pll->
ct.xclkmaxrasdelay = ((memcntl & 0x70000) >> 16) + trp + 2;
444 pll->
ct.fifo_size = 32;
446 pll->
ct.fifo_size = 24;
447 pll->
ct.xclkpagefaultdelay += 2;
448 pll->
ct.xclkmaxrasdelay += 3;
454 pll->
ct.dsp_loop_latency = 10;
456 pll->
ct.dsp_loop_latency = 8;
457 pll->
ct.xclkpagefaultdelay += 2;
463 pll->
ct.dsp_loop_latency = 9;
465 pll->
ct.dsp_loop_latency = 8;
466 pll->
ct.xclkpagefaultdelay += 1;
471 pll->
ct.dsp_loop_latency = 11;
473 pll->
ct.dsp_loop_latency = 10;
474 pll->
ct.xclkpagefaultdelay += 1;
478 pll->
ct.dsp_loop_latency = 8;
479 pll->
ct.xclkpagefaultdelay += 3;
482 pll->
ct.dsp_loop_latency = 11;
483 pll->
ct.xclkpagefaultdelay += 3;
487 if (pll->
ct.xclkmaxrasdelay <= pll->
ct.xclkpagefaultdelay)
488 pll->
ct.xclkmaxrasdelay = pll->
ct.xclkpagefaultdelay + 1;
499 FIXME:
is it relevant
for us?
500 if ((!dsp_on_off && !
M64_HAS(RESET_3D)) ||
501 ((dsp_on_off == vga_dsp_on_off) &&
505 if (ATIDivide(vga_dsp_on_off, vga_dsp_config, 5, 1) > 24)
506 pll->
ct.fifo_size = 32;
508 pll->
ct.fifo_size = 24;
514 u8 mclk_fb_div, pll_ext_cntl;
517 pll->
ct.xclk_post_div_real = postdividers[pll_ext_cntl & 0x07];
521 pll->
ct.mclk_fb_div = mclk_fb_div;
531 if (q < 16*8 || q > 255*8) {
535 xpost_div = (q < 128*8);
536 xpost_div += (q < 64*8);
537 xpost_div += (q < 32*8);
539 pll->
ct.xclk_post_div_real = postdividers[xpost_div];
540 pll->
ct.mclk_fb_div = q * pll->
ct.xclk_post_div_real / 8;
543 if (machine_is(powermac)) {
545 pll->
ct.xclk_post_div = xpost_div;
546 pll->
ct.xclk_ref_div = 1;
551 pllmclk = (1000000 * pll->
ct.mclk_fb_mult * pll->
ct.mclk_fb_div) /
553 printk(
"atyfb(%s): pllmclk=%d MHz, xclk=%d MHz\n",
554 __func__, pllmclk, pllmclk / pll->
ct.xclk_post_div_real);
563 pll->
ct.pll_ext_cntl = 0;
565 pll->
ct.pll_ext_cntl = xpost_div;
567 if (pll->
ct.mclk_fb_mult == 4)
571 pll->
ct.pll_gen_cntl |= (xpost_div << 4);
577 pll->
ct.pll_gen_cntl |= (6 << 4);
580 if (q < 16*8 || q > 255*8) {
584 mpost_div = (q < 128*8);
585 mpost_div += (q < 64*8);
586 mpost_div += (q < 32*8);
588 sclk_post_div_real = postdividers[mpost_div];
589 pll->
ct.sclk_fb_div = q * sclk_post_div_real / 8;
590 pll->
ct.spll_cntl2 = mpost_div << 4;
592 pllsclk = (1000000 * 2 * pll->
ct.sclk_fb_div) /
594 printk(
"atyfb(%s): use sclk, pllsclk=%d MHz, sclk=mclk=%d MHz\n",
595 __func__, pllsclk, pllsclk / sclk_post_div_real);
606 static void aty_resume_pll_ct(
const struct fb_info *info,
635 static int dummy(
void)
641 .set_dac = (
void *)
dummy,
645 .var_to_pll = aty_var_to_pll_ct,
646 .pll_to_var = aty_pll_to_var_ct,
648 .get_pll = aty_get_pll_ct,
649 .init_pll = aty_init_pll_ct,
650 .resume_pll = aty_resume_pll_ct,