Lines Matching +full:rate +full:- +full:ati +full:- +full:ms
1 // SPDX-License-Identifier: GPL-2.0
4 * ATI Mach64 CT/VT/GT/LT Support
46 * ATI Mach64 CT clock synthesis description.
51 * CLK = ----------------------
67 * MCLK The clock rate of the chip
68 * XCLK The clock rate of the on-chip memory
75 * SCLK Multi-purpose clock
77 * - MCLK and XCLK use the same FB_DIV
78 * - VCLK0 .. VCLK3 use the same FB_DIV
79 * - V2CLK is needed when the second CRTC is used (can be used for dualhead);
82 * - SCLK is not available on all cards; it is know to exist on the Rage LT-PRO,
84 * - V2CLK is not available on all cards, most likely only the Rage LT-PRO,
88 * - Clock the chip instead of MCLK
89 * - Replace XTALIN with a user defined frequency
90 * - Generate the pixel clock for the LCD monitor (instead of VCLK)
100 /* ------------------------------------------------------------------------- */
125 multiplier = ((u32)pll->mclk_fb_div) * pll->vclk_post_div_real; in aty_dsp_gt()
126 divider = ((u32)pll->vclk_fb_div) * pll->xclk_ref_div; in aty_dsp_gt()
128 ras_multiplier = pll->xclkmaxrasdelay; in aty_dsp_gt()
134 vshift = (6 - 2) - pll->xclk_post_div; /* FIFO is 64 bits wide in accelerator mode ... */ in aty_dsp_gt()
137 vshift--; /* ... but only 32 bits in VGA mode. */ in aty_dsp_gt()
140 if (pll->xres != 0) { in aty_dsp_gt()
141 struct atyfb_par *par = (struct atyfb_par *) info->par; in aty_dsp_gt()
143 multiplier = multiplier * par->lcd_width; in aty_dsp_gt()
144 divider = divider * pll->xres & ~7; in aty_dsp_gt()
146 ras_multiplier = ras_multiplier * par->lcd_width; in aty_dsp_gt()
147 ras_divider = ras_divider * pll->xres & ~7; in aty_dsp_gt()
158 tmp = ((multiplier * pll->fifo_size) << vshift) / divider; in aty_dsp_gt()
160 for (dsp_precision = -5; tmp; dsp_precision++) in aty_dsp_gt()
167 xshift = 6 - dsp_precision; in aty_dsp_gt()
171 dsp_off = ((multiplier * (pll->fifo_size - 1)) << vshift) / divider - in aty_dsp_gt()
172 (1 << (vshift - xshift)); in aty_dsp_gt()
182 dsp_on = dsp_on + (tmp * 2) + (pll->xclkpagefaultdelay << xshift); in aty_dsp_gt()
186 tmp = ((1 << (Maximum_DSP_PRECISION - dsp_precision)) - 1) >> 1; in aty_dsp_gt()
190 dsp_on = dsp_off - (multiplier << vshift) / divider; in aty_dsp_gt()
198 pll->dsp_on_off = (dsp_on << 16) + dsp_off; in aty_dsp_gt()
199 pll->dsp_config = (dsp_precision << 20) | (pll->dsp_loop_latency << 16) | dsp_xclks; in aty_dsp_gt()
202 __func__, pll->dsp_config, pll->dsp_on_off); in aty_dsp_gt()
210 struct atyfb_par *par = (struct atyfb_par *) info->par; in aty_valid_pll_ct()
214 q = par->ref_clk_per * pll->pll_ref_div * 4 / vclk_per; in aty_valid_pll_ct()
217 return -EINVAL; in aty_valid_pll_ct()
219 pll->vclk_post_div = (q < 128*8); in aty_valid_pll_ct()
220 pll->vclk_post_div += (q < 64*8); in aty_valid_pll_ct()
221 pll->vclk_post_div += (q < 32*8); in aty_valid_pll_ct()
223 pll->vclk_post_div_real = aty_postdividers[pll->vclk_post_div]; in aty_valid_pll_ct()
224 // pll->vclk_post_div <<= 6; in aty_valid_pll_ct()
225 pll->vclk_fb_div = q * pll->vclk_post_div_real / 8; in aty_valid_pll_ct()
226 pllvclk = (1000000 * 2 * pll->vclk_fb_div) / in aty_valid_pll_ct()
227 (par->ref_clk_per * pll->pll_ref_div); in aty_valid_pll_ct()
230 __func__, pllvclk, pllvclk / pll->vclk_post_div_real); in aty_valid_pll_ct()
232 pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */ in aty_valid_pll_ct()
235 if (par->pll_limits.ecp_max) { in aty_valid_pll_ct()
236 int ecp = pllvclk / pll->vclk_post_div_real; in aty_valid_pll_ct()
239 while (ecp > par->pll_limits.ecp_max && ecp_div < 2) { in aty_valid_pll_ct()
243 pll->pll_vclk_cntl |= ecp_div << 4; in aty_valid_pll_ct()
251 struct atyfb_par *par = (struct atyfb_par *) info->par; in aty_var_to_pll_ct()
254 if ((err = aty_valid_pll_ct(info, vclk_per, &pll->ct))) in aty_var_to_pll_ct()
256 if (M64_HAS(GTB_DSP) && (err = aty_dsp_gt(info, bpp, &pll->ct))) in aty_var_to_pll_ct()
258 /*aty_calc_pll_ct(info, &pll->ct);*/ in aty_var_to_pll_ct()
264 struct atyfb_par *par = (struct atyfb_par *) info->par; in aty_pll_to_var_ct()
266 …ret = par->ref_clk_per * pll->ct.pll_ref_div * pll->ct.vclk_post_div_real / pll->ct.vclk_fb_div / … in aty_pll_to_var_ct()
268 if(pll->ct.xres > 0) { in aty_pll_to_var_ct()
269 ret *= par->lcd_width; in aty_pll_to_var_ct()
270 ret /= pll->ct.xres; in aty_pll_to_var_ct()
281 struct atyfb_par *par = (struct atyfb_par *) info->par; in aty_set_pll_ct()
293 pll->ct.pll_ext_cntl, pll->ct.pll_gen_cntl, pll->ct.pll_vclk_cntl); in aty_set_pll_ct()
297 par->clk_wr_offset, pll->ct.vclk_fb_div, in aty_set_pll_ct()
298 pll->ct.pll_ref_div, pll->ct.vclk_post_div, pll->ct.vclk_post_div_real); in aty_set_pll_ct()
301 if (par->lcd_table != 0) { in aty_set_pll_ct()
307 aty_st_8(CLOCK_CNTL, par->clk_wr_offset | CLOCK_STROBE, par); in aty_set_pll_ct()
315 aty_st_pll_ct(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl, par); in aty_set_pll_ct()
317 /* Set post-divider */ in aty_set_pll_ct()
318 tmp2 = par->clk_wr_offset << 1; in aty_set_pll_ct()
321 tmp |= ((pll->ct.vclk_post_div & 0x03U) << tmp2); in aty_set_pll_ct()
324 /* Set extended post-divider */ in aty_set_pll_ct()
326 tmp &= ~(0x10U << par->clk_wr_offset); in aty_set_pll_ct()
328 tmp |= pll->ct.pll_ext_cntl; in aty_set_pll_ct()
332 tmp = VCLK0_FB_DIV + par->clk_wr_offset; in aty_set_pll_ct()
333 aty_st_pll_ct(tmp, (pll->ct.vclk_fb_div & 0xFFU), par); in aty_set_pll_ct()
335 …aty_st_pll_ct(PLL_GEN_CNTL, (pll->ct.pll_gen_cntl & (~(PLL_OVERRIDE | PLL_MCLK_RST))) | OSC_EN, pa… in aty_set_pll_ct()
338 aty_st_pll_ct(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl & ~(PLL_VCLK_RST), par); in aty_set_pll_ct()
341 aty_st_pll_ct(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, par); in aty_set_pll_ct()
342 aty_st_pll_ct(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl, par); in aty_set_pll_ct()
354 else if (par->ram_type >= SDRAM) in aty_set_pll_ct()
360 aty_st_le32(DSP_CONFIG, pll->ct.dsp_config, par); in aty_set_pll_ct()
361 aty_st_le32(DSP_ON_OFF, pll->ct.dsp_on_off, par); in aty_set_pll_ct()
371 if (par->lcd_table != 0) { in aty_set_pll_ct()
380 struct atyfb_par *par = (struct atyfb_par *) info->par; in aty_get_pll_ct()
385 pll->ct.vclk_post_div = (aty_ld_pll_ct(VCLK_POST_DIV, par) >> tmp) & 0x03U; in aty_get_pll_ct()
387 pll->ct.pll_ext_cntl = aty_ld_pll_ct(PLL_EXT_CNTL, par) & 0x0FU; in aty_get_pll_ct()
388 pll->ct.vclk_fb_div = aty_ld_pll_ct(VCLK0_FB_DIV + clock, par) & 0xFFU; in aty_get_pll_ct()
389 pll->ct.pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par); in aty_get_pll_ct()
390 pll->ct.mclk_fb_div = aty_ld_pll_ct(MCLK_FB_DIV, par); in aty_get_pll_ct()
392 pll->ct.pll_gen_cntl = aty_ld_pll_ct(PLL_GEN_CNTL, par); in aty_get_pll_ct()
393 pll->ct.pll_vclk_cntl = aty_ld_pll_ct(PLL_VCLK_CNTL, par); in aty_get_pll_ct()
396 pll->ct.dsp_config = aty_ld_le32(DSP_CONFIG, par); in aty_get_pll_ct()
397 pll->ct.dsp_on_off = aty_ld_le32(DSP_ON_OFF, par); in aty_get_pll_ct()
403 struct atyfb_par *par = (struct atyfb_par *) info->par; in aty_init_pll_ct()
410 pll->ct.pll_ext_cntl = aty_ld_pll_ct(PLL_EXT_CNTL, par); in aty_init_pll_ct()
411 pll->ct.xclk_post_div = pll->ct.pll_ext_cntl & 0x07; in aty_init_pll_ct()
412 pll->ct.xclk_ref_div = 1; in aty_init_pll_ct()
413 switch (pll->ct.xclk_post_div) { in aty_init_pll_ct()
418 pll->ct.xclk_ref_div = 3; in aty_init_pll_ct()
419 pll->ct.xclk_post_div = 0; in aty_init_pll_ct()
423 printk(KERN_CRIT "atyfb: Unsupported xclk source: %d.\n", pll->ct.xclk_post_div); in aty_init_pll_ct()
424 return -EINVAL; in aty_init_pll_ct()
426 pll->ct.mclk_fb_mult = 2; in aty_init_pll_ct()
427 if(pll->ct.pll_ext_cntl & PLL_MFB_TIMES_4_2B) { in aty_init_pll_ct()
428 pll->ct.mclk_fb_mult = 4; in aty_init_pll_ct()
429 pll->ct.xclk_post_div -= 1; in aty_init_pll_ct()
434 __func__, pll->ct.mclk_fb_mult, pll->ct.xclk_post_div); in aty_init_pll_ct()
440 pll->ct.xclkpagefaultdelay = ((memcntl & 0xc00) >> 10) + ((memcntl & 0x1000) >> 12) + trp + 2; in aty_init_pll_ct()
441 pll->ct.xclkmaxrasdelay = ((memcntl & 0x70000) >> 16) + trp + 2; in aty_init_pll_ct()
444 pll->ct.fifo_size = 32; in aty_init_pll_ct()
446 pll->ct.fifo_size = 24; in aty_init_pll_ct()
447 pll->ct.xclkpagefaultdelay += 2; in aty_init_pll_ct()
448 pll->ct.xclkmaxrasdelay += 3; in aty_init_pll_ct()
451 switch (par->ram_type) { in aty_init_pll_ct()
453 if (info->fix.smem_len<=ONE_MB) { in aty_init_pll_ct()
454 pll->ct.dsp_loop_latency = 10; in aty_init_pll_ct()
456 pll->ct.dsp_loop_latency = 8; in aty_init_pll_ct()
457 pll->ct.xclkpagefaultdelay += 2; in aty_init_pll_ct()
462 if (info->fix.smem_len<=ONE_MB) { in aty_init_pll_ct()
463 pll->ct.dsp_loop_latency = 9; in aty_init_pll_ct()
465 pll->ct.dsp_loop_latency = 8; in aty_init_pll_ct()
466 pll->ct.xclkpagefaultdelay += 1; in aty_init_pll_ct()
470 if (info->fix.smem_len<=ONE_MB) { in aty_init_pll_ct()
471 pll->ct.dsp_loop_latency = 11; in aty_init_pll_ct()
473 pll->ct.dsp_loop_latency = 10; in aty_init_pll_ct()
474 pll->ct.xclkpagefaultdelay += 1; in aty_init_pll_ct()
478 pll->ct.dsp_loop_latency = 8; in aty_init_pll_ct()
479 pll->ct.xclkpagefaultdelay += 3; in aty_init_pll_ct()
482 pll->ct.dsp_loop_latency = 11; in aty_init_pll_ct()
483 pll->ct.xclkpagefaultdelay += 3; in aty_init_pll_ct()
487 if (pll->ct.xclkmaxrasdelay <= pll->ct.xclkpagefaultdelay) in aty_init_pll_ct()
488 pll->ct.xclkmaxrasdelay = pll->ct.xclkpagefaultdelay + 1; in aty_init_pll_ct()
497 pll->ct.dsp_loop_latency = (dsp_config & DSP_LOOP_LATENCY) >> 16; in aty_init_pll_ct()
506 pll->ct.fifo_size = 32; in aty_init_pll_ct()
508 pll->ct.fifo_size = 24; in aty_init_pll_ct()
513 if (par->mclk_per == 0) { in aty_init_pll_ct()
515 pll->ct.pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par); in aty_init_pll_ct()
517 pll->ct.xclk_post_div_real = aty_postdividers[pll_ext_cntl & 0x07]; in aty_init_pll_ct()
521 pll->ct.mclk_fb_div = mclk_fb_div; in aty_init_pll_ct()
525 pll->ct.pll_ref_div = par->pll_per * 2 * 255 / par->ref_clk_per; in aty_init_pll_ct()
528 q = par->ref_clk_per * pll->ct.pll_ref_div * 8 / in aty_init_pll_ct()
529 (pll->ct.mclk_fb_mult * par->xclk_per); in aty_init_pll_ct()
533 return -EINVAL; in aty_init_pll_ct()
539 pll->ct.xclk_post_div_real = aty_postdividers[xpost_div]; in aty_init_pll_ct()
540 pll->ct.mclk_fb_div = q * pll->ct.xclk_post_div_real / 8; in aty_init_pll_ct()
545 pll->ct.xclk_post_div = xpost_div; in aty_init_pll_ct()
546 pll->ct.xclk_ref_div = 1; in aty_init_pll_ct()
551 pllmclk = (1000000 * pll->ct.mclk_fb_mult * pll->ct.mclk_fb_div) / in aty_init_pll_ct()
552 (par->ref_clk_per * pll->ct.pll_ref_div); in aty_init_pll_ct()
554 __func__, pllmclk, pllmclk / pll->ct.xclk_post_div_real); in aty_init_pll_ct()
557 if (M64_HAS(SDRAM_MAGIC_PLL) && (par->ram_type >= SDRAM)) in aty_init_pll_ct()
558 pll->ct.pll_gen_cntl = OSC_EN; in aty_init_pll_ct()
560 pll->ct.pll_gen_cntl = OSC_EN | DLL_PWDN /* | FORCE_DCLK_TRI_STATE */; in aty_init_pll_ct()
563 pll->ct.pll_ext_cntl = 0; in aty_init_pll_ct()
565 pll->ct.pll_ext_cntl = xpost_div; in aty_init_pll_ct()
567 if (pll->ct.mclk_fb_mult == 4) in aty_init_pll_ct()
568 pll->ct.pll_ext_cntl |= PLL_MFB_TIMES_4_2B; in aty_init_pll_ct()
570 if (par->mclk_per == par->xclk_per) { in aty_init_pll_ct()
571 pll->ct.pll_gen_cntl |= (xpost_div << 4); /* mclk == xclk */ in aty_init_pll_ct()
577 pll->ct.pll_gen_cntl |= (6 << 4); /* mclk == sclk */ in aty_init_pll_ct()
579 q = par->ref_clk_per * pll->ct.pll_ref_div * 4 / par->mclk_per; in aty_init_pll_ct()
582 return -EINVAL; in aty_init_pll_ct()
589 pll->ct.sclk_fb_div = q * sclk_post_div_real / 8; in aty_init_pll_ct()
590 pll->ct.spll_cntl2 = mpost_div << 4; in aty_init_pll_ct()
592 pllsclk = (1000000 * 2 * pll->ct.sclk_fb_div) / in aty_init_pll_ct()
593 (par->ref_clk_per * pll->ct.pll_ref_div); in aty_init_pll_ct()
600 pll->ct.ext_vpll_cntl = aty_ld_pll_ct(EXT_VPLL_CNTL, par); in aty_init_pll_ct()
601 pll->ct.ext_vpll_cntl &= ~(EXT_VPLL_EN | EXT_VPLL_VGA_EN | EXT_VPLL_INSYNC); in aty_init_pll_ct()
609 struct atyfb_par *par = info->par; in aty_resume_pll_ct()
611 if (par->mclk_per != par->xclk_per) { in aty_resume_pll_ct()
619 aty_st_pll_ct(SCLK_FB_DIV, pll->ct.sclk_fb_div, par); in aty_resume_pll_ct()
620 aty_st_pll_ct(SPLL_CNTL2, pll->ct.spll_cntl2, par); in aty_resume_pll_ct()
622 * SCLK has been started. Wait for the PLL to lock. 5 ms in aty_resume_pll_ct()
628 aty_st_pll_ct(PLL_REF_DIV, pll->ct.pll_ref_div, par); in aty_resume_pll_ct()
629 aty_st_pll_ct(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, par); in aty_resume_pll_ct()
630 aty_st_pll_ct(MCLK_FB_DIV, pll->ct.mclk_fb_div, par); in aty_resume_pll_ct()
631 aty_st_pll_ct(PLL_EXT_CNTL, pll->ct.pll_ext_cntl, par); in aty_resume_pll_ct()
632 aty_st_pll_ct(EXT_VPLL_CNTL, pll->ct.ext_vpll_cntl, par); in aty_resume_pll_ct()