drivers/video/fbdev/aty/mach64_ct.c

Source file repositories/reference/linux-study-clean/drivers/video/fbdev/aty/mach64_ct.c

File Facts

System
Linux kernel
Corpus path
drivers/video/fbdev/aty/mach64_ct.c
Extension
.c
Size
19771 bytes
Lines
652
Domain
Driver Families
Bucket
drivers/video
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

while (ecp > par->pll_limits.ecp_max && ecp_div < 2) {
			ecp >>= 1;
			ecp_div++;
		}
		pll->pll_vclk_cntl |= ecp_div << 4;
	}

	return 0;
}

static int aty_var_to_pll_ct(const struct fb_info *info, u32 vclk_per, u32 bpp, union aty_pll *pll)
{
	struct atyfb_par *par = (struct atyfb_par *) info->par;
	int err;

	if ((err = aty_valid_pll_ct(info, vclk_per, &pll->ct)))
		return err;
	if (M64_HAS(GTB_DSP) && (err = aty_dsp_gt(info, bpp, &pll->ct)))
		return err;
	/*aty_calc_pll_ct(info, &pll->ct);*/
	return 0;
}

static u32 aty_pll_to_var_ct(const struct fb_info *info, const union aty_pll *pll)
{
	struct atyfb_par *par = (struct atyfb_par *) info->par;
	u32 ret;
	ret = par->ref_clk_per * pll->ct.pll_ref_div * pll->ct.vclk_post_div_real / pll->ct.vclk_fb_div / 2;
#ifdef CONFIG_FB_ATY_GENERIC_LCD
	if(pll->ct.xres > 0) {
		ret *= par->lcd_width;
		ret /= pll->ct.xres;
	}
#endif
#ifdef DEBUG
	printk("atyfb(%s): calculated 0x%08X(%i)\n", __func__, ret, ret);
#endif
	return ret;
}

void aty_set_pll_ct(const struct fb_info *info, const union aty_pll *pll)
{
	struct atyfb_par *par = (struct atyfb_par *) info->par;
	u32 crtc_gen_cntl;
	u8 tmp, tmp2;

#ifdef CONFIG_FB_ATY_GENERIC_LCD
	u32 lcd_gen_cntrl = 0;
#endif

#ifdef DEBUG
	printk("atyfb(%s): about to program:\n"
		"pll_ext_cntl=0x%02x pll_gen_cntl=0x%02x pll_vclk_cntl=0x%02x\n",
		__func__,
		pll->ct.pll_ext_cntl, pll->ct.pll_gen_cntl, pll->ct.pll_vclk_cntl);

	printk("atyfb(%s): setting clock %lu for FeedBackDivider %i, ReferenceDivider %i, PostDivider %i(%i)\n",
		__func__,
		par->clk_wr_offset, pll->ct.vclk_fb_div,
		pll->ct.pll_ref_div, pll->ct.vclk_post_div, pll->ct.vclk_post_div_real);
#endif
#ifdef CONFIG_FB_ATY_GENERIC_LCD
	if (par->lcd_table != 0) {
		/* turn off LCD */
		lcd_gen_cntrl = aty_ld_lcd(LCD_GEN_CNTL, par);
		aty_st_lcd(LCD_GEN_CNTL, lcd_gen_cntrl & ~LCD_ON, par);
	}
#endif
	aty_st_8(CLOCK_CNTL, par->clk_wr_offset | CLOCK_STROBE, par);

	/* Temporarily switch to accelerator mode */
	crtc_gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
	if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
		aty_st_le32(CRTC_GEN_CNTL, crtc_gen_cntl | CRTC_EXT_DISP_EN, par);

	/* Reset VCLK generator */
	aty_st_pll_ct(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl, par);

	/* Set post-divider */
	tmp2 = par->clk_wr_offset << 1;
	tmp = aty_ld_pll_ct(VCLK_POST_DIV, par);
	tmp &= ~(0x03U << tmp2);
	tmp |= ((pll->ct.vclk_post_div & 0x03U) << tmp2);
	aty_st_pll_ct(VCLK_POST_DIV, tmp, par);

	/* Set extended post-divider */
	tmp = aty_ld_pll_ct(PLL_EXT_CNTL, par);
	tmp &= ~(0x10U << par->clk_wr_offset);
	tmp &= 0xF0U;
	tmp |= pll->ct.pll_ext_cntl;

Annotation

Implementation Notes