static int atyfb_set_par()

in fbdev/aty/atyfb_base.c [1302:1531]


static int atyfb_set_par(struct fb_info *info)
{
	struct atyfb_par *par = (struct atyfb_par *) info->par;
	struct fb_var_screeninfo *var = &info->var;
	u32 tmp, pixclock;
	int err;
#ifdef DEBUG
	struct fb_var_screeninfo debug;
	u32 pixclock_in_ps;
#endif
	if (par->asleep)
		return 0;

	err = aty_var_to_crtc(info, var, &par->crtc);
	if (err)
		return err;

	pixclock = atyfb_get_pixclock(var, par);

	if (pixclock == 0) {
		PRINTKE("Invalid pixclock\n");
		return -EINVAL;
	} else {
		err = par->pll_ops->var_to_pll(info, pixclock,
					       var->bits_per_pixel, &par->pll);
		if (err)
			return err;
	}

	par->accel_flags = var->accel_flags; /* hack */

	if (var->accel_flags) {
		atyfb_ops.fb_sync = atyfb_sync;
		info->flags &= ~FBINFO_HWACCEL_DISABLED;
	} else {
		atyfb_ops.fb_sync = NULL;
		info->flags |= FBINFO_HWACCEL_DISABLED;
	}

	if (par->blitter_may_be_busy)
		wait_for_idle(par);

	aty_set_crtc(par, &par->crtc);
	par->dac_ops->set_dac(info, &par->pll,
			      var->bits_per_pixel, par->accel_flags);
	par->pll_ops->set_pll(info, &par->pll);

#ifdef DEBUG
	if (par->pll_ops && par->pll_ops->pll_to_var)
		pixclock_in_ps = par->pll_ops->pll_to_var(info, &par->pll);
	else
		pixclock_in_ps = 0;

	if (0 == pixclock_in_ps) {
		PRINTKE("ALERT ops->pll_to_var get 0\n");
		pixclock_in_ps = pixclock;
	}

	memset(&debug, 0, sizeof(debug));
	if (!aty_crtc_to_var(&par->crtc, &debug)) {
		u32 hSync, vRefresh;
		u32 h_disp, h_sync_strt, h_sync_end, h_total;
		u32 v_disp, v_sync_strt, v_sync_end, v_total;

		h_disp = debug.xres;
		h_sync_strt = h_disp + debug.right_margin;
		h_sync_end = h_sync_strt + debug.hsync_len;
		h_total = h_sync_end + debug.left_margin;
		v_disp = debug.yres;
		v_sync_strt = v_disp + debug.lower_margin;
		v_sync_end = v_sync_strt + debug.vsync_len;
		v_total = v_sync_end + debug.upper_margin;

		hSync = 1000000000 / (pixclock_in_ps * h_total);
		vRefresh = (hSync * 1000) / v_total;
		if (par->crtc.gen_cntl & CRTC_INTERLACE_EN)
			vRefresh *= 2;
		if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN)
			vRefresh /= 2;

		DPRINTK("atyfb_set_par\n");
		DPRINTK(" Set Visible Mode to %ix%i-%i\n",
			var->xres, var->yres, var->bits_per_pixel);
		DPRINTK(" Virtual resolution %ix%i, "
			"pixclock_in_ps %i (calculated %i)\n",
			var->xres_virtual, var->yres_virtual,
			pixclock, pixclock_in_ps);
		DPRINTK(" Dot clock:           %i MHz\n",
			1000000 / pixclock_in_ps);
		DPRINTK(" Horizontal sync:     %i kHz\n", hSync);
		DPRINTK(" Vertical refresh:    %i Hz\n", vRefresh);
		DPRINTK(" x  style: %i.%03i %i %i %i %i   %i %i %i %i\n",
			1000000 / pixclock_in_ps, 1000000 % pixclock_in_ps,
			h_disp, h_sync_strt, h_sync_end, h_total,
			v_disp, v_sync_strt, v_sync_end, v_total);
		DPRINTK(" fb style: %i  %i %i %i %i %i %i %i %i\n",
			pixclock_in_ps,
			debug.left_margin, h_disp, debug.right_margin, debug.hsync_len,
			debug.upper_margin, v_disp, debug.lower_margin, debug.vsync_len);
	}
#endif /* DEBUG */

	if (!M64_HAS(INTEGRATED)) {
		/* Don't forget MEM_CNTL */
		tmp = aty_ld_le32(MEM_CNTL, par) & 0xf0ffffff;
		switch (var->bits_per_pixel) {
		case 8:
			tmp |= 0x02000000;
			break;
		case 16:
			tmp |= 0x03000000;
			break;
		case 32:
			tmp |= 0x06000000;
			break;
		}
		aty_st_le32(MEM_CNTL, tmp, par);
	} else {
		tmp = aty_ld_le32(MEM_CNTL, par) & 0xf00fffff;
		if (!M64_HAS(MAGIC_POSTDIV))
			tmp |= par->mem_refresh_rate << 20;
		switch (var->bits_per_pixel) {
		case 8:
		case 24:
			tmp |= 0x00000000;
			break;
		case 16:
			tmp |= 0x04000000;
			break;
		case 32:
			tmp |= 0x08000000;
			break;
		}
		if (M64_HAS(CT_BUS)) {
			aty_st_le32(DAC_CNTL, 0x87010184, par);
			aty_st_le32(BUS_CNTL, 0x680000f9, par);
		} else if (M64_HAS(VT_BUS)) {
			aty_st_le32(DAC_CNTL, 0x87010184, par);
			aty_st_le32(BUS_CNTL, 0x680000f9, par);
		} else if (M64_HAS(MOBIL_BUS)) {
			aty_st_le32(DAC_CNTL, 0x80010102, par);
			aty_st_le32(BUS_CNTL, 0x7b33a040 | (par->aux_start ? BUS_APER_REG_DIS : 0), par);
		} else {
			/* GT */
			aty_st_le32(DAC_CNTL, 0x86010102, par);
			aty_st_le32(BUS_CNTL, 0x7b23a040 | (par->aux_start ? BUS_APER_REG_DIS : 0), par);
			aty_st_le32(EXT_MEM_CNTL, aty_ld_le32(EXT_MEM_CNTL, par) | 0x5000001, par);
		}
		aty_st_le32(MEM_CNTL, tmp, par);
	}
	aty_st_8(DAC_MASK, 0xff, par);

	info->fix.line_length = calc_line_length(par, var->xres_virtual,
						 var->bits_per_pixel);

	info->fix.visual = var->bits_per_pixel <= 8 ?
		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;

	/* Initialize the graphics engine */
	if (par->accel_flags & FB_ACCELF_TEXT)
		aty_init_engine(par, info);

#ifdef CONFIG_BOOTX_TEXT
	btext_update_display(info->fix.smem_start,
		(((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8,
		((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1,
		var->bits_per_pixel,
		par->crtc.vxres * var->bits_per_pixel / 8);
#endif /* CONFIG_BOOTX_TEXT */
#ifdef DEBUG
{
	/* dump non shadow CRTC, pll, LCD registers */
	int i; u32 base;

	/* CRTC registers */
	base = 0x2000;
	printk("debug atyfb: Mach64 non-shadow register values:");
	for (i = 0; i < 256; i = i+4) {
		if (i % 16 == 0) {
			pr_cont("\n");
			printk("debug atyfb: 0x%04X: ", base + i);
		}
		pr_cont(" %08X", aty_ld_le32(i, par));
	}
	pr_cont("\n\n");

#ifdef CONFIG_FB_ATY_CT
	/* PLL registers */
	base = 0x00;
	printk("debug atyfb: Mach64 PLL register values:");
	for (i = 0; i < 64; i++) {
		if (i % 16 == 0) {
			pr_cont("\n");
			printk("debug atyfb: 0x%02X: ", base + i);
		}
		if (i % 4 == 0)
			pr_cont(" ");
		pr_cont("%02X", aty_ld_pll_ct(i, par));
	}
	pr_cont("\n\n");
#endif	/* CONFIG_FB_ATY_CT */

#ifdef CONFIG_FB_ATY_GENERIC_LCD
	if (par->lcd_table != 0) {
		/* LCD registers */
		base = 0x00;
		printk("debug atyfb: LCD register values:");
		if (M64_HAS(LT_LCD_REGS)) {
			for (i = 0; i <= POWER_MANAGEMENT; i++) {
				if (i == EXT_VERT_STRETCH)
					continue;
				pr_cont("\ndebug atyfb: 0x%04X: ",
				       lt_lcd_regs[i]);
				pr_cont(" %08X", aty_ld_lcd(i, par));
			}
		} else {
			for (i = 0; i < 64; i++) {
				if (i % 4 == 0)
					pr_cont("\ndebug atyfb: 0x%02X: ",
					       base + i);
				pr_cont(" %08X", aty_ld_lcd(i, par));
			}
		}
		pr_cont("\n\n");
	}
#endif /* CONFIG_FB_ATY_GENERIC_LCD */
}
#endif /* DEBUG */
	return 0;
}