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;
}