diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-06-17 13:25:08 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-06-17 13:25:08 +0000 |
commit | 59223edaa18759982db0a8aced0e77457d10c68e (patch) | |
tree | 89354903b01fa0a447bffeefe00df3044495db2e /drivers/video/atyfb.c | |
parent | db7d4daea91e105e3859cf461d7e53b9b77454b2 (diff) |
Merge with Linux 2.3.6. Sorry, this isn't tested on silicon, I don't
have a MIPS box at hand.
Diffstat (limited to 'drivers/video/atyfb.c')
-rw-r--r-- | drivers/video/atyfb.c | 61 |
1 files changed, 40 insertions, 21 deletions
diff --git a/drivers/video/atyfb.c b/drivers/video/atyfb.c index 1f9e41ac8..522b790ed 100644 --- a/drivers/video/atyfb.c +++ b/drivers/video/atyfb.c @@ -1,4 +1,4 @@ -/* $Id: atyfb.c,v 1.106 1999/04/16 11:20:49 geert Exp $ +/* $Id: atyfb.c,v 1.107 1999/06/08 19:59:03 geert Exp $ * linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64 * * Copyright (C) 1997-1998 Geert Uytterhoeven @@ -200,6 +200,7 @@ struct fb_info_aty { struct atyfb_par default_par; struct atyfb_par current_par; u32 total_vram; + u32 ref_clk_per; u32 pll_per; u32 mclk_per; u16 chip_type; @@ -326,9 +327,7 @@ static void reset_engine(const struct fb_info_aty *info); static void init_engine(const struct atyfb_par *par, struct fb_info_aty *info); static void aty_st_514(int offset, u8 val, const struct fb_info_aty *info); static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info); -#if defined(__sparc__) || defined(DEBUG) static u8 aty_ld_pll(int offset, const struct fb_info_aty *info); -#endif static void aty_set_crtc(const struct fb_info_aty *info, const struct crtc *crtc); static int aty_var_to_crtc(const struct fb_info_aty *info, @@ -341,7 +340,8 @@ static void aty_set_pll_gx(const struct fb_info_aty *info, const struct pll_gx *pll); static int aty_var_to_pll_18818(u32 vclk_per, struct pll_gx *pll); static int aty_var_to_pll_514(u32 vclk_per, struct pll_gx *pll); -static int aty_pll_gx_to_var(const struct pll_gx *pll, u32 *vclk_per); +static int aty_pll_gx_to_var(const struct pll_gx *pll, u32 *vclk_per, + const struct fb_info_aty *info); static void aty_set_pll_ct(const struct fb_info_aty *info, const struct pll_ct *pll); static int aty_dsp_gt(const struct fb_info_aty *info, u8 mclk_fb_div, @@ -349,7 +349,8 @@ static int aty_dsp_gt(const struct fb_info_aty *info, u8 mclk_fb_div, u8 bpp, struct pll_ct *pll); static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per, u8 bpp, struct pll_ct *pll); -static int aty_pll_ct_to_var(const struct pll_ct *pll, u32 *vclk_per); +static int aty_pll_ct_to_var(const struct pll_ct *pll, u32 *vclk_per, + const struct fb_info_aty *info); static void atyfb_set_par(const struct atyfb_par *par, struct fb_info_aty *info); static int atyfb_decode_var(const struct fb_var_screeninfo *var, @@ -405,8 +406,6 @@ static u32 default_vram __initdata = 0; static int default_pll __initdata = 0; static int default_mclk __initdata = 0; -static const u32 ref_clk_per = 1000000000000ULL/14318180; - #if defined(CONFIG_PPC) static int default_vmode __initdata = VMODE_NVRAM; static int default_cmode __initdata = CMODE_NVRAM; @@ -689,7 +688,6 @@ static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info) aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN, info); } -#if defined(__sparc__) || defined(DEBUG) static u8 aty_ld_pll(int offset, const struct fb_info_aty *info) { u8 res; @@ -702,7 +700,6 @@ static u8 aty_ld_pll(int offset, const struct fb_info_aty *info) eieio(); return res; } -#endif #if defined(CONFIG_PPC) @@ -1455,7 +1452,8 @@ static int aty_var_to_pll_514(u32 vclk_per, struct pll_gx *pll) /* FIXME: ATI18818?? */ -static int aty_pll_gx_to_var(const struct pll_gx *pll, u32 *vclk_per) +static int aty_pll_gx_to_var(const struct pll_gx *pll, u32 *vclk_per, + const struct fb_info_aty *info) { u8 df, vco_div_count, ref_div_count; @@ -1463,7 +1461,7 @@ static int aty_pll_gx_to_var(const struct pll_gx *pll, u32 *vclk_per) vco_div_count = pll->m & 0x3f; ref_div_count = pll->n; - *vclk_per = ((ref_clk_per*ref_div_count)<<(3-df))/(vco_div_count+65); + *vclk_per = ((info->ref_clk_per*ref_div_count)<<(3-df))/(vco_div_count+65); return 0; } @@ -1579,10 +1577,10 @@ static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per, pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */ - pll_ref_div = info->pll_per*2*255/ref_clk_per; + pll_ref_div = info->pll_per*2*255/info->ref_clk_per; /* FIXME: use the VTB/GTB /3 post divider if it's better suited */ - q = ref_clk_per*pll_ref_div*4/info->mclk_per; /* actually 8*q */ + q = info->ref_clk_per*pll_ref_div*4/info->mclk_per; /* actually 8*q */ if (q < 16*8 || q > 255*8) FAIL("mclk out of range"); else if (q < 32*8) @@ -1596,7 +1594,7 @@ static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per, mclk_fb_div = q*mclk_post_div/8; /* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */ - q = ref_clk_per*pll_ref_div*4/vclk_per; /* actually 8*q */ + q = info->ref_clk_per*pll_ref_div*4/vclk_per; /* actually 8*q */ if (q < 16*8 || q > 255*8) FAIL("vclk out of range"); else if (q < 32*8) @@ -1677,7 +1675,8 @@ static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per, return 0; } -static int aty_pll_ct_to_var(const struct pll_ct *pll, u32 *vclk_per) +static int aty_pll_ct_to_var(const struct pll_ct *pll, u32 *vclk_per, + const struct fb_info_aty *info) { u8 pll_ref_div = pll->pll_ref_div; u8 vclk_fb_div = pll->vclk_fb_div; @@ -1691,7 +1690,7 @@ static int aty_pll_ct_to_var(const struct pll_ct *pll, u32 *vclk_per) (vclk_post_div & 3)]; if (vpostdiv == 0) return -EINVAL; - *vclk_per = pll_ref_div*vpostdiv*ref_clk_per/vclk_fb_div/2; + *vclk_per = pll_ref_div*vpostdiv*info->ref_clk_per/vclk_fb_div/2; return 0; } @@ -1845,9 +1844,9 @@ static int atyfb_encode_var(struct fb_var_screeninfo *var, if ((err = aty_crtc_to_var(&par->crtc, var))) return err; if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID)) - err = aty_pll_gx_to_var(&par->pll.gx, &var->pixclock); + err = aty_pll_gx_to_var(&par->pll.gx, &var->pixclock, info); else - err = aty_pll_ct_to_var(&par->pll.ct, &var->pixclock); + err = aty_pll_ct_to_var(&par->pll.ct, &var->pixclock, info); if (err) return err; @@ -2432,11 +2431,12 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name)) int j, k; struct fb_var_screeninfo var; struct display *disp; - const char *chipname = NULL, *ramname = NULL; + const char *chipname = NULL, *ramname = NULL, *xtal; int pll, mclk, gtb_memsize; #if defined(CONFIG_PPC) int sense; #endif + u8 pll_ref_div; info->aty_cmap_regs = (struct aty_cmap_regs *)(info->ati_regbase+0xc0); chip_id = aty_ld_le32(CONFIG_CHIP_ID, info); @@ -2524,6 +2524,25 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name)) } } + info->ref_clk_per = 1000000000000ULL/14318180; + xtal = "14.31818"; + if (!(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID || + Gx == ET_CHIP_ID || + ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07))) && + (pll_ref_div = aty_ld_pll(PLL_REF_DIV, info))) { + int diff1, diff2; + diff1 = 510*14/pll_ref_div-pll; + diff2 = 510*29/pll_ref_div-pll; + if (diff1 < 0) + diff1 = -diff1; + if (diff2 < 0) + diff2 = -diff2; + if (diff2 < diff1) { + info->ref_clk_per = 1000000000000ULL/29498928; + xtal = "29.498928"; + } + } + i = aty_ld_le32(MEM_CNTL, info); gtb_memsize = !(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID || Gx == ET_CHIP_ID || @@ -2602,9 +2621,9 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name)) if (default_mclk) mclk = default_mclk; - printk("%d%c %s, %d MHz PLL, %d Mhz MCLK\n", + printk("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK\n", info->total_vram == 0x80000 ? 512 : (info->total_vram >> 20), - info->total_vram == 0x80000 ? 'K' : 'M', ramname, pll, mclk); + info->total_vram == 0x80000 ? 'K' : 'M', ramname, xtal, pll, mclk); if (mclk < 44) info->mem_refresh_rate = 0; /* 000 = 10 Mhz - 43 Mhz */ |