Commit 87520e1e authored by James Simmons's avatar James Simmons

Porting Mach 64 drive over to new api.

parent 4ec16d90
...@@ -254,7 +254,7 @@ if [ "$CONFIG_FB" = "y" ]; then ...@@ -254,7 +254,7 @@ if [ "$CONFIG_FB" = "y" ]; then
fi fi
fi fi
if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_ATARI" = "y" -o \ if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_ATARI" = "y" -o \
"$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_CYBER2000" = "y" -o \ "$CONFIG_FB_P9100" = "y" -o "$CONFIG_FB_CYBER2000" = "y" -o \
"$CONFIG_FB_RADEON" = "y" -o "$CONFIG_FB_TGA" = "y" -o \ "$CONFIG_FB_RADEON" = "y" -o "$CONFIG_FB_TGA" = "y" -o \
"$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_PM3" = "y" -o \ "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_PM3" = "y" -o \
"$CONFIG_FB_TCX" = "y" -o "$CONFIG_FB_CGTHREE" = "y" -o \ "$CONFIG_FB_TCX" = "y" -o "$CONFIG_FB_CGTHREE" = "y" -o \
...@@ -264,11 +264,11 @@ if [ "$CONFIG_FB" = "y" ]; then ...@@ -264,11 +264,11 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \ "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
"$CONFIG_FB_IGA" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \ "$CONFIG_FB_IGA" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \
"$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_PM2" = "y" -o \ "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_PM2" = "y" -o \
"$CONFIG_FB_P9100" = "y" ]; then "$CONFIG_FB_ATY" = "y" ]; then
define_tristate CONFIG_FBCON_CFB8 y define_tristate CONFIG_FBCON_CFB8 y
else else
if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \ if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
"$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_CYBER2000" = "m" -o \ "$CONFIG_FB_P9100" = "m" -o "$CONFIG_FB_CYBER2000" = "m" -o \
"$CONFIG_FB_RADEON" = "m" -o "$CONFIG_FB_TGA" = "m" -o \ "$CONFIG_FB_RADEON" = "m" -o "$CONFIG_FB_TGA" = "m" -o \
"$CONFIG_FB_SIS" = "m" -o "$CONFIG_FB_PM3" = "m" -o \ "$CONFIG_FB_SIS" = "m" -o "$CONFIG_FB_PM3" = "m" -o \
"$CONFIG_FB_TCX" = "m" -o "$CONFIG_FB_CGTHREE" = "m" -o \ "$CONFIG_FB_TCX" = "m" -o "$CONFIG_FB_CGTHREE" = "m" -o \
...@@ -277,12 +277,11 @@ if [ "$CONFIG_FB" = "y" ]; then ...@@ -277,12 +277,11 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \ "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \
"$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \ "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
"$CONFIG_FB_IGA" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \ "$CONFIG_FB_IGA" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \
"$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_PM2" = "m" -o \ "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_PM2" = "m" ]; then
"$CONFIG_FB_P9100" = "m" ]; then
define_tristate CONFIG_FBCON_CFB8 m define_tristate CONFIG_FBCON_CFB8 m
fi fi
fi fi
if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATY" = "y" -o \ if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_PM3" = "y" -o \
"$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_PVR2" = "y" -o \ "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_PVR2" = "y" -o \
"$CONFIG_FB_TRIDENT" = "y" -o "$CONFIG_FB_TBOX" = "y" -o \ "$CONFIG_FB_TRIDENT" = "y" -o "$CONFIG_FB_TBOX" = "y" -o \
"$CONFIG_FB_VOODOO1" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \ "$CONFIG_FB_VOODOO1" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \
...@@ -291,10 +290,10 @@ if [ "$CONFIG_FB" = "y" ]; then ...@@ -291,10 +290,10 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \ "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
"$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \ "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \
"$CONFIG_FB_PM2" = "y" -o "$CONFIG_FB_CYBER2000" = "y" -o \ "$CONFIG_FB_PM2" = "y" -o "$CONFIG_FB_CYBER2000" = "y" -o \
"$CONFIG_FB_PM3" = "y" ]; then "$CONFIG_FB_ATY" = "y" ]; then
define_tristate CONFIG_FBCON_CFB16 y define_tristate CONFIG_FBCON_CFB16 y
else else
if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \ if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_SIS" = "m" -o \
"$CONFIG_FB_RADEON" = "m" -o "$CONFIG_FB_PVR2" = "m" -o \ "$CONFIG_FB_RADEON" = "m" -o "$CONFIG_FB_PVR2" = "m" -o \
"$CONFIG_FB_TRIDENT" = "m" -o "$CONFIG_FB_TBOX" = "m" -o \ "$CONFIG_FB_TRIDENT" = "m" -o "$CONFIG_FB_TBOX" = "m" -o \
"$CONFIG_FB_VOODOO1" = "m" -o "$CONFIG_FB_PM3" = "m" -o \ "$CONFIG_FB_VOODOO1" = "m" -o "$CONFIG_FB_PM3" = "m" -o \
...@@ -302,8 +301,7 @@ if [ "$CONFIG_FB" = "y" ]; then ...@@ -302,8 +301,7 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \ "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \
"$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \ "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
"$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \ "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \
"$CONFIG_FB_PM2" = "m" -o "$CONFIG_FB_CYBER2000" = "m" -o \ "$CONFIG_FB_PM2" = "m" -o "$CONFIG_FB_CYBER2000" = "m" ]; then
"$CONFIG_FB_SIS" = "m" ]; then
define_tristate CONFIG_FBCON_CFB16 m define_tristate CONFIG_FBCON_CFB16 m
fi fi
fi fi
...@@ -324,22 +322,22 @@ if [ "$CONFIG_FB" = "y" ]; then ...@@ -324,22 +322,22 @@ if [ "$CONFIG_FB" = "y" ]; then
define_tristate CONFIG_FBCON_CFB24 m define_tristate CONFIG_FBCON_CFB24 m
fi fi
fi fi
if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATY" = "y" -o \ if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \
"$CONFIG_FB_VOODOO1" = "y" -o "$CONFIG_FB_TRIDENT" = "y" -o \ "$CONFIG_FB_VOODOO1" = "y" -o "$CONFIG_FB_TRIDENT" = "y" -o \
"$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \ "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
"$CONFIG_FB_TGA" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \ "$CONFIG_FB_TGA" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
"$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" -o \ "$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" -o \
"$CONFIG_FB_PVR2" = "y" -o "$CONFIG_FB_PM3" = "y" -o \ "$CONFIG_FB_PVR2" = "y" -o "$CONFIG_FB_PM3" = "y" -o \
"$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_RADEON" = "y" ]; then "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_ATY" = "y" ]; then
define_tristate CONFIG_FBCON_CFB32 y define_tristate CONFIG_FBCON_CFB32 y
else else
if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \ if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \
"$CONFIG_FB_VOODOO1" = "m" -o "$CONFIG_FB_TRIDENT" = "m" -o \ "$CONFIG_FB_VOODOO1" = "m" -o "$CONFIG_FB_TRIDENT" = "m" -o \
"$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \ "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
"$CONFIG_FB_TGA" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \ "$CONFIG_FB_TGA" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
"$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" -o \ "$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" -o \
"$CONFIG_FB_SIS" = "m" -o "$CONFIG_FB_PVR2" = "m" -o \ "$CONFIG_FB_SIS" = "m" -o "$CONFIG_FB_PVR2" = "m" -o \
"$CONFIG_FB_PM3" = "m" -o "$CONFIG_FB_RADEON" = "m" ]; then "$CONFIG_FB_PM3" = "m" ]; then
define_tristate CONFIG_FBCON_CFB32 m define_tristate CONFIG_FBCON_CFB32 m
fi fi
fi fi
...@@ -353,14 +351,15 @@ if [ "$CONFIG_FB" = "y" ]; then ...@@ -353,14 +351,15 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_MAXINE" = "y" -o "$CONFIG_FB_APOLLO" = "y" -o \ "$CONFIG_FB_MAXINE" = "y" -o "$CONFIG_FB_APOLLO" = "y" -o \
"$CONFIG_FB_ATY128" = "y" -o "$CONFIG_FB_MAC" = "y" -o \ "$CONFIG_FB_ATY128" = "y" -o "$CONFIG_FB_MAC" = "y" -o \
"$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_SA1100" = "y" -o \ "$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_SA1100" = "y" -o \
"$CONFIG_FB_OF" = "y" -o "$CONFIG_FB_SGIVW" = "y" ]; then "$CONFIG_FB_OF" = "y" -o "$CONFIG_FB_SGIVW" = "y" -o \
"$CONFIG_FB_ATY" = "y" ]; then
define_tristate CONFIG_FBCON_ACCEL y define_tristate CONFIG_FBCON_ACCEL y
else else
if [ "$CONFIG_FB_NEOMAGIC" = "m" -o "$CONFIG_FB_HIT" = "m" -o \ if [ "$CONFIG_FB_NEOMAGIC" = "m" -o "$CONFIG_FB_HIT" = "m" -o \
"$CONFIG_FB_G364" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \ "$CONFIG_FB_G364" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
"$CONFIG_FB_CLPS711X" = "m" -o "$CONFIG_FB_3DFX" = "m" -o \ "$CONFIG_FB_CLPS711X" = "m" -o "$CONFIG_FB_3DFX" = "m" -o \
"$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \ "$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \
"$CONFIG_FB_SGIVW" = "m" ]; then "$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_ATY" = "m" ]; then
define_tristate CONFIG_FBCON_ACCEL m define_tristate CONFIG_FBCON_ACCEL m
fi fi
fi fi
......
...@@ -44,7 +44,7 @@ obj-$(CONFIG_FB_PM3) += pm3fb.o ...@@ -44,7 +44,7 @@ obj-$(CONFIG_FB_PM3) += pm3fb.o
obj-$(CONFIG_FB_APOLLO) += dnfb.o cfbfillrect.o cfbimgblt.o obj-$(CONFIG_FB_APOLLO) += dnfb.o cfbfillrect.o cfbimgblt.o
obj-$(CONFIG_FB_Q40) += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_Q40) += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_ATARI) += atafb.o obj-$(CONFIG_FB_ATARI) += atafb.o
obj-$(CONFIG_FB_ATY128) += aty128fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_ATY128) += aty128fb.o
obj-$(CONFIG_FB_RADEON) += radeonfb.o obj-$(CONFIG_FB_RADEON) += radeonfb.o
obj-$(CONFIG_FB_NEOMAGIC) += neofb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_NEOMAGIC) += neofb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_IGA) += igafb.o obj-$(CONFIG_FB_IGA) += igafb.o
......
...@@ -3,7 +3,7 @@ export-objs := atyfb_base.o mach64_accel.o ...@@ -3,7 +3,7 @@ export-objs := atyfb_base.o mach64_accel.o
obj-$(CONFIG_FB_ATY) += atyfb.o obj-$(CONFIG_FB_ATY) += atyfb.o
atyfb-y := atyfb_base.o mach64_accel.o atyfb-y := atyfb_base.o mach64_accel.o ../cfbimgblt.o
atyfb-$(CONFIG_FB_ATY_GX) += mach64_gx.o atyfb-$(CONFIG_FB_ATY_GX) += mach64_gx.o
atyfb-$(CONFIG_FB_ATY_CT) += mach64_ct.o mach64_cursor.o atyfb-$(CONFIG_FB_ATY_CT) += mach64_ct.o mach64_cursor.o
atyfb-objs := $(atyfb-y) atyfb-objs := $(atyfb-y)
......
...@@ -10,120 +10,109 @@ ...@@ -10,120 +10,109 @@
*/ */
struct crtc { struct crtc {
u32 vxres; u32 vxres;
u32 vyres; u32 vyres;
u32 xoffset; u32 xoffset;
u32 yoffset; u32 yoffset;
u32 bpp; u32 bpp;
u32 h_tot_disp; u32 h_tot_disp;
u32 h_sync_strt_wid; u32 h_sync_strt_wid;
u32 v_tot_disp; u32 v_tot_disp;
u32 v_sync_strt_wid; u32 v_sync_strt_wid;
u32 off_pitch; u32 off_pitch;
u32 gen_cntl; u32 gen_cntl;
u32 dp_pix_width; /* acceleration */ u32 dp_pix_width; /* acceleration */
u32 dp_chain_mask; /* acceleration */ u32 dp_chain_mask; /* acceleration */
}; };
struct pll_514 { struct pll_514 {
u8 m; u8 m;
u8 n; u8 n;
}; };
struct pll_18818 struct pll_18818 {
{ u32 program_bits;
u32 program_bits; u32 locationAddr;
u32 locationAddr; u32 period_in_ps;
u32 period_in_ps; u32 post_divider;
u32 post_divider;
}; };
struct pll_ct { struct pll_ct {
u8 pll_ref_div; u8 pll_ref_div;
u8 pll_gen_cntl; u8 pll_gen_cntl;
u8 mclk_fb_div; u8 mclk_fb_div;
u8 pll_vclk_cntl; u8 pll_vclk_cntl;
u8 vclk_post_div; u8 vclk_post_div;
u8 vclk_fb_div; u8 vclk_fb_div;
u8 pll_ext_cntl; u8 pll_ext_cntl;
u32 dsp_config; /* Mach64 GTB DSP */ u32 dsp_config; /* Mach64 GTB DSP */
u32 dsp_on_off; /* Mach64 GTB DSP */ u32 dsp_on_off; /* Mach64 GTB DSP */
u8 mclk_post_div_real; u8 mclk_post_div_real;
u8 vclk_post_div_real; u8 vclk_post_div_real;
}; };
union aty_pll { union aty_pll {
struct pll_ct ct; struct pll_ct ct;
struct pll_514 ibm514; struct pll_514 ibm514;
struct pll_18818 ics2595; struct pll_18818 ics2595;
}; };
/* /*
* The hardware parameters for each card * The hardware parameters for each card
*/ */
struct atyfb_par {
struct crtc crtc;
union aty_pll pll;
u32 accel_flags;
};
struct aty_cursor { struct aty_cursor {
int enable; int enable;
int on; int on;
int vbl_cnt; int vbl_cnt;
int blink_rate; int blink_rate;
u32 offset; u32 offset;
struct { struct {
u16 x, y; u16 x, y;
} pos, hot, size; } pos, hot, size;
u32 color[2]; u32 color[2];
u8 bits[8][64]; u8 bits[8][64];
u8 mask[8][64]; u8 mask[8][64];
u8 *ram; u8 *ram;
struct timer_list *timer; struct timer_list *timer;
}; };
struct fb_info_aty { struct atyfb_par {
struct fb_info fb_info; struct aty_cmap_regs *aty_cmap_regs;
struct fb_info_aty *next; const struct aty_dac_ops *dac_ops;
unsigned long ati_regbase; const struct aty_pll_ops *pll_ops;
unsigned long clk_wr_offset; struct aty_cursor *cursor;
struct pci_mmap_map *mmap_map; unsigned long ati_regbase;
struct aty_cursor *cursor; unsigned long clk_wr_offset;
struct aty_cmap_regs *aty_cmap_regs; struct crtc crtc;
struct atyfb_par default_par; union aty_pll pll;
struct atyfb_par current_par; u32 features;
u32 features; u32 ref_clk_per;
u32 ref_clk_per; u32 pll_per;
u32 pll_per; u32 mclk_per;
u32 mclk_per; u8 bus_type;
u8 bus_type; u8 ram_type;
u8 ram_type; u8 mem_refresh_rate;
u8 mem_refresh_rate; u8 blitter_may_be_busy;
const struct aty_dac_ops *dac_ops; u32 accel_flags;
const struct aty_pll_ops *pll_ops;
struct display_switch dispsw;
u8 blitter_may_be_busy;
#ifdef __sparc__ #ifdef __sparc__
u8 mmaped; struct pci_mmap_map *mmap_map;
int open; int consolecnt;
int vtconsole; int vtconsole;
int consolecnt; u8 mmaped;
int open;
#endif #endif
#ifdef CONFIG_PMAC_PBOOK #ifdef CONFIG_PMAC_PBOOK
unsigned char *save_framebuffer; unsigned char *save_framebuffer;
unsigned long save_pll[64]; unsigned long save_pll[64];
#endif #endif
}; };
/* /*
* ATI Mach64 features * ATI Mach64 features
*/ */
#define M64_HAS(feature) ((info)->features & (M64F_##feature)) #define M64_HAS(feature) ((par)->features & (M64F_##feature))
#define M64F_RESET_3D 0x00000001 #define M64F_RESET_3D 0x00000001
#define M64F_MAGIC_FIFO 0x00000002 #define M64F_MAGIC_FIFO 0x00000002
...@@ -151,63 +140,63 @@ struct fb_info_aty { ...@@ -151,63 +140,63 @@ struct fb_info_aty {
* Register access * Register access
*/ */
static inline u32 aty_ld_le32(int regindex, static inline u32 aty_ld_le32(int regindex, const struct atyfb_par *par)
const struct fb_info_aty *info)
{ {
/* Hack for bloc 1, should be cleanly optimized by compiler */ /* Hack for bloc 1, should be cleanly optimized by compiler */
if (regindex >= 0x400) if (regindex >= 0x400)
regindex -= 0x800; regindex -= 0x800;
#if defined(__mc68000__) #if defined(__mc68000__)
return le32_to_cpu(*((volatile u32 *)(info->ati_regbase+regindex))); return
le32_to_cpu(*((volatile u32 *) (par->ati_regbase + regindex)));
#else #else
return readl (info->ati_regbase + regindex); return readl(par->ati_regbase + regindex);
#endif #endif
} }
static inline void aty_st_le32(int regindex, u32 val, static inline void aty_st_le32(int regindex, u32 val,
const struct fb_info_aty *info) const struct atyfb_par *par)
{ {
/* Hack for bloc 1, should be cleanly optimized by compiler */ /* Hack for bloc 1, should be cleanly optimized by compiler */
if (regindex >= 0x400) if (regindex >= 0x400)
regindex -= 0x800; regindex -= 0x800;
#if defined(__mc68000__) #if defined(__mc68000__)
*((volatile u32 *)(info->ati_regbase+regindex)) = cpu_to_le32(val); *((volatile u32 *) (par->ati_regbase + regindex)) =
cpu_to_le32(val);
#else #else
writel (val, info->ati_regbase + regindex); writel(val, par->ati_regbase + regindex);
#endif #endif
} }
static inline u8 aty_ld_8(int regindex, static inline u8 aty_ld_8(int regindex, const struct atyfb_par *par)
const struct fb_info_aty *info)
{ {
/* Hack for bloc 1, should be cleanly optimized by compiler */ /* Hack for bloc 1, should be cleanly optimized by compiler */
if (regindex >= 0x400) if (regindex >= 0x400)
regindex -= 0x800; regindex -= 0x800;
return readb (info->ati_regbase + regindex); return readb(par->ati_regbase + regindex);
} }
static inline void aty_st_8(int regindex, u8 val, static inline void aty_st_8(int regindex, u8 val,
const struct fb_info_aty *info) const struct atyfb_par *par)
{ {
/* Hack for bloc 1, should be cleanly optimized by compiler */ /* Hack for bloc 1, should be cleanly optimized by compiler */
if (regindex >= 0x400) if (regindex >= 0x400)
regindex -= 0x800; regindex -= 0x800;
writeb (val, info->ati_regbase + regindex); writeb(val, par->ati_regbase + regindex);
} }
static inline u8 aty_ld_pll(int offset, const struct fb_info_aty *info) static inline u8 aty_ld_pll(int offset, const struct atyfb_par *par)
{ {
u8 res; u8 res;
/* write addr byte */ /* write addr byte */
aty_st_8(CLOCK_CNTL + 1, (offset << 2), info); aty_st_8(CLOCK_CNTL + 1, (offset << 2), par);
/* read the register value */ /* read the register value */
res = aty_ld_8(CLOCK_CNTL + 2, info); res = aty_ld_8(CLOCK_CNTL + 2, par);
return res; return res;
} }
...@@ -216,15 +205,15 @@ static inline u8 aty_ld_pll(int offset, const struct fb_info_aty *info) ...@@ -216,15 +205,15 @@ static inline u8 aty_ld_pll(int offset, const struct fb_info_aty *info)
*/ */
struct aty_dac_ops { struct aty_dac_ops {
int (*set_dac)(const struct fb_info_aty *info, const union aty_pll *pll, int (*set_dac) (const struct fb_info * info,
u32 bpp, u32 accel); const union aty_pll * pll, u32 bpp, u32 accel);
}; };
extern const struct aty_dac_ops aty_dac_ibm514; /* IBM RGB514 */ extern const struct aty_dac_ops aty_dac_ibm514; /* IBM RGB514 */
extern const struct aty_dac_ops aty_dac_ati68860b; /* ATI 68860-B */ extern const struct aty_dac_ops aty_dac_ati68860b; /* ATI 68860-B */
extern const struct aty_dac_ops aty_dac_att21c498; /* AT&T 21C498 */ extern const struct aty_dac_ops aty_dac_att21c498; /* AT&T 21C498 */
extern const struct aty_dac_ops aty_dac_unsupported; /* unsupported */ extern const struct aty_dac_ops aty_dac_unsupported; /* unsupported */
extern const struct aty_dac_ops aty_dac_ct; /* Integrated */ extern const struct aty_dac_ops aty_dac_ct; /* Integrated */
/* /*
...@@ -232,25 +221,26 @@ extern const struct aty_dac_ops aty_dac_ct; /* Integrated */ ...@@ -232,25 +221,26 @@ extern const struct aty_dac_ops aty_dac_ct; /* Integrated */
*/ */
struct aty_pll_ops { struct aty_pll_ops {
int (*var_to_pll)(const struct fb_info_aty *info, u32 vclk_per, u8 bpp, int (*var_to_pll) (const struct fb_info * info, u32 vclk_per,
union aty_pll *pll); u8 bpp, union aty_pll * pll);
u32 (*pll_to_var)(const struct fb_info_aty *info, u32(*pll_to_var) (const struct fb_info * info,
const union aty_pll *pll); const union aty_pll * pll);
void (*set_pll)(const struct fb_info_aty *info, const union aty_pll *pll); void (*set_pll) (const struct fb_info * info,
const union aty_pll * pll);
}; };
extern const struct aty_pll_ops aty_pll_ati18818_1; /* ATI 18818 */ extern const struct aty_pll_ops aty_pll_ati18818_1; /* ATI 18818 */
extern const struct aty_pll_ops aty_pll_stg1703; /* STG 1703 */ extern const struct aty_pll_ops aty_pll_stg1703; /* STG 1703 */
extern const struct aty_pll_ops aty_pll_ch8398; /* Chrontel 8398 */ extern const struct aty_pll_ops aty_pll_ch8398; /* Chrontel 8398 */
extern const struct aty_pll_ops aty_pll_att20c408; /* AT&T 20C408 */ extern const struct aty_pll_ops aty_pll_att20c408; /* AT&T 20C408 */
extern const struct aty_pll_ops aty_pll_ibm514; /* IBM RGB514 */ extern const struct aty_pll_ops aty_pll_ibm514; /* IBM RGB514 */
extern const struct aty_pll_ops aty_pll_unsupported; /* unsupported */ extern const struct aty_pll_ops aty_pll_unsupported; /* unsupported */
extern const struct aty_pll_ops aty_pll_ct; /* Integrated */ extern const struct aty_pll_ops aty_pll_ct; /* Integrated */
extern void aty_set_pll_ct(const struct fb_info_aty *info, extern void aty_set_pll_ct(const struct fb_info *info,
const union aty_pll *pll); const union aty_pll *pll);
extern void aty_calc_pll_ct(const struct fb_info_aty *info, extern void aty_calc_pll_ct(const struct fb_info *info,
struct pll_ct *pll); struct pll_ct *pll);
...@@ -258,10 +248,10 @@ extern void aty_calc_pll_ct(const struct fb_info_aty *info, ...@@ -258,10 +248,10 @@ extern void aty_calc_pll_ct(const struct fb_info_aty *info,
* Hardware cursor support * Hardware cursor support
*/ */
extern struct aty_cursor *aty_init_cursor(struct fb_info_aty *fb); extern struct aty_cursor *aty_init_cursor(struct fb_info *info);
extern void atyfb_cursor(struct display *p, int mode, int x, int y); extern void atyfb_cursor(struct display *p, int mode, int x, int y);
extern void aty_set_cursor_color(struct fb_info_aty *fb); extern void aty_set_cursor_color(struct fb_info *info);
extern void aty_set_cursor_shape(struct fb_info_aty *fb); extern void aty_set_cursor_shape(struct fb_info *info);
extern int atyfb_set_font(struct display *d, int width, int height); extern int atyfb_set_font(struct display *d, int width, int height);
...@@ -269,25 +259,23 @@ extern int atyfb_set_font(struct display *d, int width, int height); ...@@ -269,25 +259,23 @@ extern int atyfb_set_font(struct display *d, int width, int height);
* Hardware acceleration * Hardware acceleration
*/ */
static inline void wait_for_fifo(u16 entries, const struct fb_info_aty *info) static inline void wait_for_fifo(u16 entries, const struct atyfb_par *par)
{ {
while ((aty_ld_le32(FIFO_STAT, info) & 0xffff) > while ((aty_ld_le32(FIFO_STAT, par) & 0xffff) >
((u32)(0x8000 >> entries))); ((u32) (0x8000 >> entries)));
} }
static inline void wait_for_idle(struct fb_info_aty *info) static inline void wait_for_idle(struct atyfb_par *par)
{ {
wait_for_fifo(16, info); wait_for_fifo(16, par);
while ((aty_ld_le32(GUI_STAT, info) & 1)!= 0); while ((aty_ld_le32(GUI_STAT, par) & 1) != 0);
info->blitter_may_be_busy = 0; par->blitter_may_be_busy = 0;
} }
extern void aty_reset_engine(const struct fb_info_aty *info); extern void aty_reset_engine(const struct atyfb_par *par);
extern void aty_init_engine(const struct atyfb_par *par, extern void aty_init_engine(struct atyfb_par *par,
struct fb_info_aty *info); struct fb_info *info);
extern void aty_rectfill(int dstx, int dsty, u_int width, u_int height, extern void atyfb_fillrect(struct fb_info *info, struct fb_fillrect *rect);
u_int color, struct fb_info_aty *info);
/* /*
* Text console acceleration * Text console acceleration
...@@ -297,4 +285,3 @@ extern const struct display_switch fbcon_aty8; ...@@ -297,4 +285,3 @@ extern const struct display_switch fbcon_aty8;
extern const struct display_switch fbcon_aty16; extern const struct display_switch fbcon_aty16;
extern const struct display_switch fbcon_aty24; extern const struct display_switch fbcon_aty24;
extern const struct display_switch fbcon_aty32; extern const struct display_switch fbcon_aty32;
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -20,287 +20,299 @@ ...@@ -20,287 +20,299 @@
* Text console acceleration * Text console acceleration
*/ */
static void fbcon_aty_bmove(struct display *p, int sy, int sx, int dy, int dx, static void fbcon_aty_bmove(struct display *p, int sy, int sx, int dy,
int height, int width); int dx, int height, int width);
static void fbcon_aty_clear(struct vc_data *conp, struct display *p, int sy, static void fbcon_aty_clear(struct vc_data *conp, struct display *p,
int sx, int height, int width); int sy, int sx, int height, int width);
/* /*
* Generic Mach64 routines * Generic Mach64 routines
*/ */
void aty_reset_engine(const struct fb_info_aty *info) void aty_reset_engine(const struct atyfb_par *par)
{ {
/* reset engine */ /* reset engine */
aty_st_le32(GEN_TEST_CNTL, aty_st_le32(GEN_TEST_CNTL,
aty_ld_le32(GEN_TEST_CNTL, info) & ~GUI_ENGINE_ENABLE, info); aty_ld_le32(GEN_TEST_CNTL, par) & ~GUI_ENGINE_ENABLE,
/* enable engine */ par);
aty_st_le32(GEN_TEST_CNTL, /* enable engine */
aty_ld_le32(GEN_TEST_CNTL, info) | GUI_ENGINE_ENABLE, info); aty_st_le32(GEN_TEST_CNTL,
/* ensure engine is not locked up by clearing any FIFO or */ aty_ld_le32(GEN_TEST_CNTL, par) | GUI_ENGINE_ENABLE,
/* HOST errors */ par);
aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, info) | BUS_HOST_ERR_ACK | /* ensure engine is not locked up by clearing any FIFO or */
BUS_FIFO_ERR_ACK, info); /* HOST errors */
aty_st_le32(BUS_CNTL,
aty_ld_le32(BUS_CNTL,
par) | BUS_HOST_ERR_ACK | BUS_FIFO_ERR_ACK,
par);
} }
static void reset_GTC_3D_engine(const struct fb_info_aty *info) static void reset_GTC_3D_engine(const struct atyfb_par *par)
{ {
aty_st_le32(SCALE_3D_CNTL, 0xc0, info); aty_st_le32(SCALE_3D_CNTL, 0xc0, par);
mdelay(GTC_3D_RESET_DELAY); mdelay(GTC_3D_RESET_DELAY);
aty_st_le32(SETUP_CNTL, 0x00, info); aty_st_le32(SETUP_CNTL, 0x00, par);
mdelay(GTC_3D_RESET_DELAY); mdelay(GTC_3D_RESET_DELAY);
aty_st_le32(SCALE_3D_CNTL, 0x00, info); aty_st_le32(SCALE_3D_CNTL, 0x00, par);
mdelay(GTC_3D_RESET_DELAY); mdelay(GTC_3D_RESET_DELAY);
} }
void aty_init_engine(const struct atyfb_par *par, struct fb_info_aty *info) void aty_init_engine(struct atyfb_par *par, struct fb_info *info)
{ {
u32 pitch_value; u32 pitch_value;
/* determine modal information from global mode structure */ /* determine modal information from global mode structure */
pitch_value = par->crtc.vxres; pitch_value = par->crtc.vxres;
if (par->crtc.bpp == 24) { if (par->crtc.bpp == 24) {
/* In 24 bpp, the engine is in 8 bpp - this requires that all */ /* In 24 bpp, the engine is in 8 bpp - this requires that all */
/* horizontal coordinates and widths must be adjusted */ /* horizontal coordinates and widths must be adjusted */
pitch_value = pitch_value * 3; pitch_value = pitch_value * 3;
} }
/* On GTC (RagePro), we need to reset the 3D engine before */ /* On GTC (RagePro), we need to reset the 3D engine before */
if (M64_HAS(RESET_3D)) if (M64_HAS(RESET_3D))
reset_GTC_3D_engine(info); reset_GTC_3D_engine(par);
/* Reset engine, enable, and clear any engine errors */ /* Reset engine, enable, and clear any engine errors */
aty_reset_engine(info); aty_reset_engine(par);
/* Ensure that vga page pointers are set to zero - the upper */ /* Ensure that vga page pointers are set to zero - the upper */
/* page pointers are set to 1 to handle overflows in the */ /* page pointers are set to 1 to handle overflows in the */
/* lower page */ /* lower page */
aty_st_le32(MEM_VGA_WP_SEL, 0x00010000, info); aty_st_le32(MEM_VGA_WP_SEL, 0x00010000, par);
aty_st_le32(MEM_VGA_RP_SEL, 0x00010000, info); aty_st_le32(MEM_VGA_RP_SEL, 0x00010000, par);
/* ---- Setup standard engine context ---- */ /* ---- Setup standard engine context ---- */
/* All GUI registers here are FIFOed - therefore, wait for */ /* All GUI registers here are FIFOed - therefore, wait for */
/* the appropriate number of empty FIFO entries */ /* the appropriate number of empty FIFO entries */
wait_for_fifo(14, info); wait_for_fifo(14, par);
/* enable all registers to be loaded for context loads */ /* enable all registers to be loaded for context loads */
aty_st_le32(CONTEXT_MASK, 0xFFFFFFFF, info); aty_st_le32(CONTEXT_MASK, 0xFFFFFFFF, par);
/* set destination pitch to modal pitch, set offset to zero */ /* set destination pitch to modal pitch, set offset to zero */
aty_st_le32(DST_OFF_PITCH, (pitch_value / 8) << 22, info); aty_st_le32(DST_OFF_PITCH, (pitch_value / 8) << 22, par);
/* zero these registers (set them to a known state) */ /* zero these registers (set them to a known state) */
aty_st_le32(DST_Y_X, 0, info); aty_st_le32(DST_Y_X, 0, par);
aty_st_le32(DST_HEIGHT, 0, info); aty_st_le32(DST_HEIGHT, 0, par);
aty_st_le32(DST_BRES_ERR, 0, info); aty_st_le32(DST_BRES_ERR, 0, par);
aty_st_le32(DST_BRES_INC, 0, info); aty_st_le32(DST_BRES_INC, 0, par);
aty_st_le32(DST_BRES_DEC, 0, info); aty_st_le32(DST_BRES_DEC, 0, par);
/* set destination drawing attributes */ /* set destination drawing attributes */
aty_st_le32(DST_CNTL, DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM | aty_st_le32(DST_CNTL, DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM |
DST_X_LEFT_TO_RIGHT, info); DST_X_LEFT_TO_RIGHT, par);
/* set source pitch to modal pitch, set offset to zero */ /* set source pitch to modal pitch, set offset to zero */
aty_st_le32(SRC_OFF_PITCH, (pitch_value / 8) << 22, info); aty_st_le32(SRC_OFF_PITCH, (pitch_value / 8) << 22, par);
/* set these registers to a known state */ /* set these registers to a known state */
aty_st_le32(SRC_Y_X, 0, info); aty_st_le32(SRC_Y_X, 0, par);
aty_st_le32(SRC_HEIGHT1_WIDTH1, 1, info); aty_st_le32(SRC_HEIGHT1_WIDTH1, 1, par);
aty_st_le32(SRC_Y_X_START, 0, info); aty_st_le32(SRC_Y_X_START, 0, par);
aty_st_le32(SRC_HEIGHT2_WIDTH2, 1, info); aty_st_le32(SRC_HEIGHT2_WIDTH2, 1, par);
/* set source pixel retrieving attributes */ /* set source pixel retrieving attributes */
aty_st_le32(SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT, info); aty_st_le32(SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT, par);
/* set host attributes */ /* set host attributes */
wait_for_fifo(13, info); wait_for_fifo(13, par);
aty_st_le32(HOST_CNTL, 0, info); aty_st_le32(HOST_CNTL, 0, par);
/* set pattern attributes */ /* set pattern attributes */
aty_st_le32(PAT_REG0, 0, info); aty_st_le32(PAT_REG0, 0, par);
aty_st_le32(PAT_REG1, 0, info); aty_st_le32(PAT_REG1, 0, par);
aty_st_le32(PAT_CNTL, 0, info); aty_st_le32(PAT_CNTL, 0, par);
/* set scissors to modal size */ /* set scissors to modal size */
aty_st_le32(SC_LEFT, 0, info); aty_st_le32(SC_LEFT, 0, par);
aty_st_le32(SC_TOP, 0, info); aty_st_le32(SC_TOP, 0, par);
aty_st_le32(SC_BOTTOM, par->crtc.vyres-1, info); aty_st_le32(SC_BOTTOM, par->crtc.vyres - 1, par);
aty_st_le32(SC_RIGHT, pitch_value-1, info); aty_st_le32(SC_RIGHT, pitch_value - 1, par);
/* set background color to minimum value (usually BLACK) */ /* set background color to minimum value (usually BLACK) */
aty_st_le32(DP_BKGD_CLR, 0, info); aty_st_le32(DP_BKGD_CLR, 0, par);
/* set foreground color to maximum value (usually WHITE) */ /* set foreground color to maximum value (usually WHITE) */
aty_st_le32(DP_FRGD_CLR, 0xFFFFFFFF, info); aty_st_le32(DP_FRGD_CLR, 0xFFFFFFFF, par);
/* set write mask to effect all pixel bits */ /* set write mask to effect all pixel bits */
aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF, info); aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF, par);
/* set foreground mix to overpaint and background mix to */ /* set foreground mix to overpaint and background mix to */
/* no-effect */ /* no-effect */
aty_st_le32(DP_MIX, FRGD_MIX_S | BKGD_MIX_D, info); aty_st_le32(DP_MIX, FRGD_MIX_S | BKGD_MIX_D, par);
/* set primary source pixel channel to foreground color */ /* set primary source pixel channel to foreground color */
/* register */ /* register */
aty_st_le32(DP_SRC, FRGD_SRC_FRGD_CLR, info); aty_st_le32(DP_SRC, FRGD_SRC_FRGD_CLR, par);
/* set compare functionality to false (no-effect on */ /* set compare functionality to false (no-effect on */
/* destination) */ /* destination) */
wait_for_fifo(3, info); wait_for_fifo(3, par);
aty_st_le32(CLR_CMP_CLR, 0, info); aty_st_le32(CLR_CMP_CLR, 0, par);
aty_st_le32(CLR_CMP_MASK, 0xFFFFFFFF, info); aty_st_le32(CLR_CMP_MASK, 0xFFFFFFFF, par);
aty_st_le32(CLR_CMP_CNTL, 0, info); aty_st_le32(CLR_CMP_CNTL, 0, par);
/* set pixel depth */ /* set pixel depth */
wait_for_fifo(2, info); wait_for_fifo(2, par);
aty_st_le32(DP_PIX_WIDTH, par->crtc.dp_pix_width, info); aty_st_le32(DP_PIX_WIDTH, par->crtc.dp_pix_width, par);
aty_st_le32(DP_CHAIN_MASK, par->crtc.dp_chain_mask, info); aty_st_le32(DP_CHAIN_MASK, par->crtc.dp_chain_mask, par);
wait_for_fifo(5, info); wait_for_fifo(5, par);
aty_st_le32(SCALE_3D_CNTL, 0, info); aty_st_le32(SCALE_3D_CNTL, 0, par);
aty_st_le32(Z_CNTL, 0, info); aty_st_le32(Z_CNTL, 0, par);
aty_st_le32(CRTC_INT_CNTL, aty_ld_le32(CRTC_INT_CNTL, info) & ~0x20, info); aty_st_le32(CRTC_INT_CNTL, aty_ld_le32(CRTC_INT_CNTL, par) & ~0x20,
aty_st_le32(GUI_TRAJ_CNTL, 0x100023, info); par);
aty_st_le32(GUI_TRAJ_CNTL, 0x100023, par);
/* insure engine is idle before leaving */
wait_for_idle(info); /* insure engine is idle before leaving */
wait_for_idle(par);
} }
/* /*
* Accelerated functions * Accelerated functions
*/ */
static inline void draw_rect(s16 x, s16 y, u16 width, u16 height, static inline void draw_rect(s16 x, s16 y, u16 width, u16 height,
struct fb_info_aty *info) struct atyfb_par *par)
{ {
/* perform rectangle fill */ /* perform rectangle fill */
wait_for_fifo(2, info); wait_for_fifo(2, par);
aty_st_le32(DST_Y_X, (x << 16) | y, info); aty_st_le32(DST_Y_X, (x << 16) | y, par);
aty_st_le32(DST_HEIGHT_WIDTH, (width << 16) | height, info); aty_st_le32(DST_HEIGHT_WIDTH, (width << 16) | height, par);
info->blitter_may_be_busy = 1; par->blitter_may_be_busy = 1;
} }
static inline void aty_rectcopy(int srcx, int srcy, int dstx, int dsty, static void atyfb_copyarea(struct fb_info *info, struct fb_copyarea *area)
u_int width, u_int height,
struct fb_info_aty *info)
{ {
u32 direction = DST_LAST_PEL; struct atyfb_par *par = (struct atyfb_par *) info->par;
u32 pitch_value;
u32 direction = DST_LAST_PEL;
if (!width || !height) u32 pitch_value;
return;
if (!area->width || !area->height)
pitch_value = info->current_par.crtc.vxres; return;
if (info->current_par.crtc.bpp == 24) {
/* In 24 bpp, the engine is in 8 bpp - this requires that all */ pitch_value = par->crtc.vxres;
/* horizontal coordinates and widths must be adjusted */ if (par->crtc.bpp == 24) {
pitch_value *= 3; /* In 24 bpp, the engine is in 8 bpp - this requires that all */
srcx *= 3; /* horizontal coordinates and widths must be adjusted */
dstx *= 3; pitch_value *= 3;
width *= 3; area->sx *= 3;
} area->dx *= 3;
area->width *= 3;
if (srcy < dsty) { }
dsty += height - 1;
srcy += height - 1; if (area->sy < area->dy) {
} else area->dy += area->height - 1;
direction |= DST_Y_TOP_TO_BOTTOM; area->sy += area->height - 1;
} else
if (srcx < dstx) { direction |= DST_Y_TOP_TO_BOTTOM;
dstx += width - 1;
srcx += width - 1; if (area->sx < area->dx) {
} else area->dx += area->width - 1;
direction |= DST_X_LEFT_TO_RIGHT; area->sx += area->width - 1;
} else
wait_for_fifo(4, info); direction |= DST_X_LEFT_TO_RIGHT;
aty_st_le32(DP_SRC, FRGD_SRC_BLIT, info);
aty_st_le32(SRC_Y_X, (srcx << 16) | srcy, info); wait_for_fifo(4, par);
aty_st_le32(SRC_HEIGHT1_WIDTH1, (width << 16) | height, info); aty_st_le32(DP_SRC, FRGD_SRC_BLIT, par);
aty_st_le32(DST_CNTL, direction, info); aty_st_le32(SRC_Y_X, (area->sx << 16) | area->sy, par);
draw_rect(dstx, dsty, width, height, info); aty_st_le32(SRC_HEIGHT1_WIDTH1, (area->width << 16) | area->height,par);
aty_st_le32(DST_CNTL, direction, par);
draw_rect(area->dx, area->dy, area->width, area->height, par);
} }
void aty_rectfill(int dstx, int dsty, u_int width, u_int height, u_int color, void atyfb_fillrect(struct fb_info *info, struct fb_fillrect *rect)
struct fb_info_aty *info)
{ {
if (!width || !height) struct atyfb_par *par = (struct atyfb_par *) info->par;
return;
if (!rect->width || !rect->height)
if (info->current_par.crtc.bpp == 24) { return;
/* In 24 bpp, the engine is in 8 bpp - this requires that all */
/* horizontal coordinates and widths must be adjusted */ rect->color |= (rect->color << 8);
dstx *= 3; rect->color |= (rect->color << 16);
width *= 3;
} if (par->crtc.bpp == 24) {
/* In 24 bpp, the engine is in 8 bpp - this requires that all */
wait_for_fifo(3, info); /* horizontal coordinates and widths must be adjusted */
aty_st_le32(DP_FRGD_CLR, color, info); rect->dx *= 3;
aty_st_le32(DP_SRC, BKGD_SRC_BKGD_CLR | FRGD_SRC_FRGD_CLR | MONO_SRC_ONE, rect->width *= 3;
info); }
aty_st_le32(DST_CNTL, DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM |
DST_X_LEFT_TO_RIGHT, info); wait_for_fifo(3, par);
draw_rect(dstx, dsty, width, height, info); aty_st_le32(DP_FRGD_CLR, rect->color, par);
aty_st_le32(DP_SRC,
BKGD_SRC_BKGD_CLR | FRGD_SRC_FRGD_CLR | MONO_SRC_ONE,
par);
aty_st_le32(DST_CNTL,
DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM |
DST_X_LEFT_TO_RIGHT, par);
draw_rect(rect->dx, rect->dy, rect->width, rect->height, par);
} }
/* /*
* Text console acceleration * Text console acceleration
*/ */
static void fbcon_aty_bmove(struct display *p, int sy, int sx, int dy, int dx, static void fbcon_aty_bmove(struct display *p, int sy, int sx, int dy,
int height, int width) int dx, int height, int width)
{ {
struct fb_info *info = p->fb_info;
struct fb_copyarea area;
#ifdef __sparc__ #ifdef __sparc__
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); struct atyfb_par *par = (struct atyfb_par *) (info->par);
if (fb->mmaped && (!fb->fb_info.display_fg if (par->mmaped && (!info->display_fg
|| fb->fb_info.display_fg->vc_num == fb->vtconsole)) || info->display_fg->vc_num ==
return; par->vtconsole))
return;
#endif #endif
sx *= fontwidth(p); area.sx = sx * fontwidth(p);
sy *= fontheight(p); area.sy = sy * fontheight(p);
dx *= fontwidth(p); area.dx = dx * fontwidth(p);
dy *= fontheight(p); area.dy = dy * fontheight(p);
width *= fontwidth(p); area.width = width * fontwidth(p);
height *= fontheight(p); area.height = height * fontheight(p);
aty_rectcopy(sx, sy, dx, dy, width, height, atyfb_copyarea(info, &area);
(struct fb_info_aty *)p->fb_info);
} }
static void fbcon_aty_clear(struct vc_data *conp, struct display *p, int sy, static void fbcon_aty_clear(struct vc_data *conp, struct display *p,
int sx, int height, int width) int sy, int sx, int height, int width)
{ {
u32 bgx; struct fb_info *info = p->fb_info;
struct fb_fillrect region;
#ifdef __sparc__ #ifdef __sparc__
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); struct atyfb_par *par = (struct atyfb_par *) (info->par);
if (fb->mmaped && (!fb->fb_info.display_fg if (par->mmaped && (!info->display_fg
|| fb->fb_info.display_fg->vc_num == fb->vtconsole)) || info->display_fg->vc_num ==
return; par->vtconsole))
return;
#endif #endif
region.color = attr_bgcol_ec(p, conp);
region.color |= (region.color << 8);
region.color |= (region.color << 16);
bgx = attr_bgcol_ec(p, conp); region.dx = sx * fontwidth(p);
bgx |= (bgx << 8); region.dy = sy * fontheight(p);
bgx |= (bgx << 16); region.width = width * fontwidth(p);
region.height = height * fontheight(p);
region.rop = ROP_COPY;
sx *= fontwidth(p); atyfb_fillrect(info, &region);
sy *= fontheight(p);
width *= fontwidth(p);
height *= fontheight(p);
aty_rectfill(sx, sy, width, height, bgx,
(struct fb_info_aty *)p->fb_info);
} }
#ifdef __sparc__ #ifdef __sparc__
#define check_access \ #define check_access \
if (fb->mmaped && (!fb->fb_info.display_fg \ if (par->mmaped && (!info->display_fg \
|| fb->fb_info.display_fg->vc_num == fb->vtconsole)) \ || info->display_fg->vc_num == par->vtconsole)) \
return; return;
#else #else
#define check_access do { } while (0) #define check_access do { } while (0)
...@@ -309,10 +321,11 @@ static void fbcon_aty_clear(struct vc_data *conp, struct display *p, int sy, ...@@ -309,10 +321,11 @@ static void fbcon_aty_clear(struct vc_data *conp, struct display *p, int sy,
#define DEF_FBCON_ATY_OP(name, call, args...) \ #define DEF_FBCON_ATY_OP(name, call, args...) \
static void name(struct vc_data *conp, struct display *p, args) \ static void name(struct vc_data *conp, struct display *p, args) \
{ \ { \
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); \ struct fb_info *info = p->fb_info; \
struct atyfb_par *par = (struct atyfb_par *) info->par; \
check_access; \ check_access; \
if (fb->blitter_may_be_busy) \ if (par->blitter_may_be_busy) \
wait_for_idle((struct fb_info_aty *)p->fb_info); \ wait_for_idle(par); \
call; \ call; \
} }
...@@ -342,12 +355,11 @@ const struct display_switch fbcon_aty##width = { \ ...@@ -342,12 +355,11 @@ const struct display_switch fbcon_aty##width = { \
DEF_FBCON_ATY(8) DEF_FBCON_ATY(8)
#endif #endif
#ifdef FBCON_HAS_CFB16 #ifdef FBCON_HAS_CFB16
DEF_FBCON_ATY(16) DEF_FBCON_ATY(16)
#endif #endif
#ifdef FBCON_HAS_CFB24 #ifdef FBCON_HAS_CFB24
DEF_FBCON_ATY(24) DEF_FBCON_ATY(24)
#endif #endif
#ifdef FBCON_HAS_CFB32 #ifdef FBCON_HAS_CFB32
DEF_FBCON_ATY(32) DEF_FBCON_ATY(32)
#endif #endif
...@@ -16,26 +16,25 @@ ...@@ -16,26 +16,25 @@
/* FIXME: remove the FAIL definition */ /* FIXME: remove the FAIL definition */
#define FAIL(x) do { printk(x "\n"); return -EINVAL; } while (0) #define FAIL(x) do { printk(x "\n"); return -EINVAL; } while (0)
static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info); static void aty_st_pll(int offset, u8 val, const struct atyfb_par *par);
static int aty_valid_pll_ct(const struct fb_info *info, u32 vclk_per,
static int aty_valid_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
struct pll_ct *pll); struct pll_ct *pll);
static int aty_dsp_gt(const struct fb_info_aty *info, u8 bpp, static int aty_dsp_gt(const struct fb_info *info, u8 bpp,
struct pll_ct *pll); struct pll_ct *pll);
static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per, static int aty_var_to_pll_ct(const struct fb_info *info, u32 vclk_per,
u8 bpp, union aty_pll *pll); u8 bpp, union aty_pll *pll);
static u32 aty_pll_ct_to_var(const struct fb_info_aty *info, static u32 aty_pll_ct_to_var(const struct fb_info *info,
const union aty_pll *pll); const union aty_pll *pll);
static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info) static void aty_st_pll(int offset, u8 val, const struct atyfb_par *par)
{ {
/* write addr byte */ /* write addr byte */
aty_st_8(CLOCK_CNTL + 1, (offset << 2) | PLL_WR_EN, info); aty_st_8(CLOCK_CNTL + 1, (offset << 2) | PLL_WR_EN, par);
/* write the register value */ /* write the register value */
aty_st_8(CLOCK_CNTL + 2, val, info); aty_st_8(CLOCK_CNTL + 2, val, par);
aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN, info); aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN, par);
} }
...@@ -45,228 +44,238 @@ static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info) ...@@ -45,228 +44,238 @@ static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info)
* PLL programming (Mach64 CT family) * PLL programming (Mach64 CT family)
*/ */
static int aty_dsp_gt(const struct fb_info_aty *info, u8 bpp, static int aty_dsp_gt(const struct fb_info *info, u8 bpp,
struct pll_ct *pll) struct pll_ct *pll)
{ {
u32 dsp_xclks_per_row, dsp_loop_latency, dsp_precision, dsp_off, dsp_on; struct atyfb_par *par = (struct atyfb_par *) info->par;
u32 xclks_per_row, fifo_off, fifo_on, y, fifo_size, page_size; u32 dsp_xclks_per_row, dsp_loop_latency, dsp_precision, dsp_off,
dsp_on;
/* xclocks_per_row<<11 */ u32 xclks_per_row, fifo_off, fifo_on, y, fifo_size, page_size;
xclks_per_row = (pll->mclk_fb_div*pll->vclk_post_div_real*64<<11)/
(pll->vclk_fb_div*pll->mclk_post_div_real*bpp); /* xclocks_per_row<<11 */
if (xclks_per_row < (1<<11)) xclks_per_row =
FAIL("Dotclock to high"); (pll->mclk_fb_div * pll->vclk_post_div_real * 64 << 11) /
if (M64_HAS(FIFO_24)) { (pll->vclk_fb_div * pll->mclk_post_div_real * bpp);
fifo_size = 24; if (xclks_per_row < (1 << 11))
dsp_loop_latency = 0; FAIL("Dotclock to high");
} else { if (M64_HAS(FIFO_24)) {
fifo_size = 32; fifo_size = 24;
dsp_loop_latency = 2; dsp_loop_latency = 0;
}
dsp_precision = 0;
y = (xclks_per_row*fifo_size)>>11;
while (y) {
y >>= 1;
dsp_precision++;
}
dsp_precision -= 5;
/* fifo_off<<6 */
fifo_off = ((xclks_per_row*(fifo_size-1))>>5)+(3<<6);
if (info->fb_info.fix.smem_len > 1*1024*1024) {
if (info->ram_type >= SDRAM) {
/* >1 MB SDRAM */
dsp_loop_latency += 8;
page_size = 8;
} else { } else {
/* >1 MB DRAM */ fifo_size = 32;
dsp_loop_latency += 6; dsp_loop_latency = 2;
page_size = 9; }
dsp_precision = 0;
y = (xclks_per_row * fifo_size) >> 11;
while (y) {
y >>= 1;
dsp_precision++;
} }
} else { dsp_precision -= 5;
if (info->ram_type >= SDRAM) { /* fifo_off<<6 */
/* <2 MB SDRAM */ fifo_off = ((xclks_per_row * (fifo_size - 1)) >> 5) + (3 << 6);
dsp_loop_latency += 9;
page_size = 10; if (info->fix.smem_len > 1 * 1024 * 1024) {
if (par->ram_type >= SDRAM) {
/* >1 MB SDRAM */
dsp_loop_latency += 8;
page_size = 8;
} else {
/* >1 MB DRAM */
dsp_loop_latency += 6;
page_size = 9;
}
} else { } else {
/* <2 MB DRAM */ if (par->ram_type >= SDRAM) {
dsp_loop_latency += 8; /* <2 MB SDRAM */
page_size = 10; dsp_loop_latency += 9;
page_size = 10;
} else {
/* <2 MB DRAM */
dsp_loop_latency += 8;
page_size = 10;
}
} }
} /* fifo_on<<6 */
/* fifo_on<<6 */ if (xclks_per_row >= (page_size << 11))
if (xclks_per_row >= (page_size<<11)) fifo_on =
fifo_on = ((2*page_size+1)<<6)+(xclks_per_row>>5); ((2 * page_size + 1) << 6) + (xclks_per_row >> 5);
else else
fifo_on = (3*page_size+2)<<6; fifo_on = (3 * page_size + 2) << 6;
dsp_xclks_per_row = xclks_per_row>>dsp_precision; dsp_xclks_per_row = xclks_per_row >> dsp_precision;
dsp_on = fifo_on>>dsp_precision; dsp_on = fifo_on >> dsp_precision;
dsp_off = fifo_off>>dsp_precision; dsp_off = fifo_off >> dsp_precision;
pll->dsp_config = (dsp_xclks_per_row & 0x3fff) | pll->dsp_config = (dsp_xclks_per_row & 0x3fff) |
((dsp_loop_latency & 0xf)<<16) | ((dsp_loop_latency & 0xf) << 16) | ((dsp_precision & 7) << 20);
((dsp_precision & 7)<<20); pll->dsp_on_off = (dsp_on & 0x7ff) | ((dsp_off & 0x7ff) << 16);
pll->dsp_on_off = (dsp_on & 0x7ff) | ((dsp_off & 0x7ff)<<16); return 0;
return 0;
} }
static int aty_valid_pll_ct(const struct fb_info_aty *info, u32 vclk_per, static int aty_valid_pll_ct(const struct fb_info *info, u32 vclk_per,
struct pll_ct *pll) struct pll_ct *pll)
{ {
u32 q, x; /* x is a workaround for sparc64-linux-gcc */ struct atyfb_par *par = (struct atyfb_par *) info->par;
x = x; /* x is a workaround for sparc64-linux-gcc */ u32 q, x; /* x is a workaround for sparc64-linux-gcc */
x = x; /* x is a workaround for sparc64-linux-gcc */
pll->pll_ref_div = info->pll_per*2*255/info->ref_clk_per;
pll->pll_ref_div = par->pll_per * 2 * 255 / par->ref_clk_per;
/* FIXME: use the VTB/GTB /3 post divider if it's better suited */
q = info->ref_clk_per*pll->pll_ref_div*4/info->mclk_per; /* actually 8*q */ /* FIXME: use the VTB/GTB /3 post divider if it's better suited */
if (q < 16*8 || q > 255*8) q = par->ref_clk_per * pll->pll_ref_div * 4 / par->mclk_per; /* actually 8*q */
FAIL("mclk out of range"); if (q < 16 * 8 || q > 255 * 8)
else if (q < 32*8) FAIL("mclk out of range");
pll->mclk_post_div_real = 8; else if (q < 32 * 8)
else if (q < 64*8) pll->mclk_post_div_real = 8;
pll->mclk_post_div_real = 4; else if (q < 64 * 8)
else if (q < 128*8) pll->mclk_post_div_real = 4;
pll->mclk_post_div_real = 2; else if (q < 128 * 8)
else pll->mclk_post_div_real = 2;
pll->mclk_post_div_real = 1; else
pll->mclk_fb_div = q*pll->mclk_post_div_real/8; pll->mclk_post_div_real = 1;
pll->mclk_fb_div = q * pll->mclk_post_div_real / 8;
/* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */
q = info->ref_clk_per*pll->pll_ref_div*4/vclk_per; /* actually 8*q */ /* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */
if (q < 16*8 || q > 255*8) q = par->ref_clk_per * pll->pll_ref_div * 4 / vclk_per; /* actually 8*q */
FAIL("vclk out of range"); if (q < 16 * 8 || q > 255 * 8)
else if (q < 32*8) FAIL("vclk out of range");
pll->vclk_post_div_real = 8; else if (q < 32 * 8)
else if (q < 64*8) pll->vclk_post_div_real = 8;
pll->vclk_post_div_real = 4; else if (q < 64 * 8)
else if (q < 128*8) pll->vclk_post_div_real = 4;
pll->vclk_post_div_real = 2; else if (q < 128 * 8)
else pll->vclk_post_div_real = 2;
pll->vclk_post_div_real = 1; else
pll->vclk_fb_div = q*pll->vclk_post_div_real/8; pll->vclk_post_div_real = 1;
return 0; pll->vclk_fb_div = q * pll->vclk_post_div_real / 8;
return 0;
} }
void aty_calc_pll_ct(const struct fb_info_aty *info, struct pll_ct *pll) void aty_calc_pll_ct(const struct fb_info *info, struct pll_ct *pll)
{ {
u8 mpostdiv = 0; struct atyfb_par *par = (struct atyfb_par *) info->par;
u8 vpostdiv = 0; u8 mpostdiv = 0;
u8 vpostdiv = 0;
if (M64_HAS(SDRAM_MAGIC_PLL) && (info->ram_type >= SDRAM)) if (M64_HAS(SDRAM_MAGIC_PLL) && (par->ram_type >= SDRAM))
pll->pll_gen_cntl = 0x04; pll->pll_gen_cntl = 0x04;
else else
pll->pll_gen_cntl = 0x84; pll->pll_gen_cntl = 0x84;
switch (pll->mclk_post_div_real) { switch (pll->mclk_post_div_real) {
case 1: case 1:
mpostdiv = 0; mpostdiv = 0;
break; break;
case 2: case 2:
mpostdiv = 1; mpostdiv = 1;
break; break;
case 3: case 3:
mpostdiv = 4; mpostdiv = 4;
break; break;
case 4: case 4:
mpostdiv = 2; mpostdiv = 2;
break; break;
case 8: case 8:
mpostdiv = 3; mpostdiv = 3;
break; break;
} }
pll->pll_gen_cntl |= mpostdiv<<4; /* mclk */ pll->pll_gen_cntl |= mpostdiv << 4; /* mclk */
if (M64_HAS(MAGIC_POSTDIV)) if (M64_HAS(MAGIC_POSTDIV))
pll->pll_ext_cntl = 0; pll->pll_ext_cntl = 0;
else else
pll->pll_ext_cntl = mpostdiv; /* xclk == mclk */ pll->pll_ext_cntl = mpostdiv; /* xclk == mclk */
switch (pll->vclk_post_div_real) { switch (pll->vclk_post_div_real) {
case 2: case 2:
vpostdiv = 1; vpostdiv = 1;
break; break;
case 3: case 3:
pll->pll_ext_cntl |= 0x10; pll->pll_ext_cntl |= 0x10;
case 1: case 1:
vpostdiv = 0; vpostdiv = 0;
break; break;
case 6: case 6:
pll->pll_ext_cntl |= 0x10; pll->pll_ext_cntl |= 0x10;
case 4: case 4:
vpostdiv = 2; vpostdiv = 2;
break; break;
case 12: case 12:
pll->pll_ext_cntl |= 0x10; pll->pll_ext_cntl |= 0x10;
case 8: case 8:
vpostdiv = 3; vpostdiv = 3;
break; break;
} }
pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */ pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */
pll->vclk_post_div = vpostdiv; pll->vclk_post_div = vpostdiv;
} }
static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per, static int aty_var_to_pll_ct(const struct fb_info *info, u32 vclk_per,
u8 bpp, union aty_pll *pll) u8 bpp, union aty_pll *pll)
{ {
int err; 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 ((err = aty_valid_pll_ct(info, vclk_per, &pll->ct)))
if (M64_HAS(GTB_DSP) && (err = aty_dsp_gt(info, bpp, &pll->ct))) return err;
return err; if (M64_HAS(GTB_DSP) && (err = aty_dsp_gt(info, bpp, &pll->ct)))
aty_calc_pll_ct(info, &pll->ct); return err;
return 0; aty_calc_pll_ct(info, &pll->ct);
return 0;
} }
static u32 aty_pll_ct_to_var(const struct fb_info_aty *info, static u32 aty_pll_ct_to_var(const struct fb_info *info,
const union aty_pll *pll) const union aty_pll *pll)
{ {
u32 ref_clk_per = info->ref_clk_per; struct atyfb_par *par = (struct atyfb_par *) info->par;
u8 pll_ref_div = pll->ct.pll_ref_div;
u8 vclk_fb_div = pll->ct.vclk_fb_div; u32 ref_clk_per = par->ref_clk_per;
u8 vclk_post_div = pll->ct.vclk_post_div_real; u8 pll_ref_div = pll->ct.pll_ref_div;
u8 vclk_fb_div = pll->ct.vclk_fb_div;
u8 vclk_post_div = pll->ct.vclk_post_div_real;
return ref_clk_per*pll_ref_div*vclk_post_div/vclk_fb_div/2; return ref_clk_per * pll_ref_div * vclk_post_div / vclk_fb_div / 2;
} }
void aty_set_pll_ct(const struct fb_info_aty *info, const union aty_pll *pll) void aty_set_pll_ct(const struct fb_info *info,
const union aty_pll *pll)
{ {
aty_st_pll(PLL_REF_DIV, pll->ct.pll_ref_div, info); struct atyfb_par *par = (struct atyfb_par *) info->par;
aty_st_pll(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, info);
aty_st_pll(MCLK_FB_DIV, pll->ct.mclk_fb_div, info); aty_st_pll(PLL_REF_DIV, pll->ct.pll_ref_div, par);
aty_st_pll(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl, info); aty_st_pll(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, par);
aty_st_pll(VCLK_POST_DIV, pll->ct.vclk_post_div, info); aty_st_pll(MCLK_FB_DIV, pll->ct.mclk_fb_div, par);
aty_st_pll(VCLK0_FB_DIV, pll->ct.vclk_fb_div, info); aty_st_pll(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl, par);
aty_st_pll(PLL_EXT_CNTL, pll->ct.pll_ext_cntl, info); aty_st_pll(VCLK_POST_DIV, pll->ct.vclk_post_div, par);
aty_st_pll(VCLK0_FB_DIV, pll->ct.vclk_fb_div, par);
if (M64_HAS(GTB_DSP)) { aty_st_pll(PLL_EXT_CNTL, pll->ct.pll_ext_cntl, par);
if (M64_HAS(XL_DLL))
aty_st_pll(DLL_CNTL, 0x80, info); if (M64_HAS(GTB_DSP)) {
else if (info->ram_type >= SDRAM) if (M64_HAS(XL_DLL))
aty_st_pll(DLL_CNTL, 0xa6, info); aty_st_pll(DLL_CNTL, 0x80, par);
else else if (par->ram_type >= SDRAM)
aty_st_pll(DLL_CNTL, 0xa0, info); aty_st_pll(DLL_CNTL, 0xa6, par);
aty_st_pll(VFC_CNTL, 0x1b, info); else
aty_st_le32(DSP_CONFIG, pll->ct.dsp_config, info); aty_st_pll(DLL_CNTL, 0xa0, par);
aty_st_le32(DSP_ON_OFF, pll->ct.dsp_on_off, info); aty_st_pll(VFC_CNTL, 0x1b, par);
} aty_st_le32(DSP_CONFIG, pll->ct.dsp_config, par);
aty_st_le32(DSP_ON_OFF, pll->ct.dsp_on_off, par);
}
} }
static int dummy(void) static int dummy(void)
{ {
return 0; return 0;
} }
const struct aty_dac_ops aty_dac_ct = { const struct aty_dac_ops aty_dac_ct = {
set_dac: (void *)dummy, set_dac:(void *) dummy,
}; };
const struct aty_pll_ops aty_pll_ct = { const struct aty_pll_ops aty_pll_ct = {
var_to_pll: aty_var_to_pll_ct, var_to_pll:aty_var_to_pll_ct,
pll_to_var: aty_pll_ct_to_var, pll_to_var:aty_pll_ct_to_var,
set_pll: aty_set_pll_ct, set_pll:aty_set_pll_ct,
}; };
...@@ -33,21 +33,20 @@ ...@@ -33,21 +33,20 @@
static const u8 cursor_pixel_map[2] = { 0, 15 }; static const u8 cursor_pixel_map[2] = { 0, 15 };
static const u8 cursor_color_map[2] = { 0, 0xff }; static const u8 cursor_color_map[2] = { 0, 0xff };
static const u8 cursor_bits_lookup[16] = static const u8 cursor_bits_lookup[16] = {
{
0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54, 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
}; };
static const u8 cursor_mask_lookup[16] = static const u8 cursor_mask_lookup[16] = {
{
0xaa, 0x2a, 0x8a, 0x0a, 0xa2, 0x22, 0x82, 0x02, 0xaa, 0x2a, 0x8a, 0x0a, 0xa2, 0x22, 0x82, 0x02,
0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00 0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00
}; };
void aty_set_cursor_color(struct fb_info_aty *fb) void aty_set_cursor_color(struct fb_info *info)
{ {
struct aty_cursor *c = fb->cursor; struct atyfb_par *par = (struct atyfb_par *) info->par;
struct aty_cursor *c = par->cursor;
const u8 *pixel = cursor_pixel_map; /* ++Geert: Why?? */ const u8 *pixel = cursor_pixel_map; /* ++Geert: Why?? */
const u8 *red = cursor_color_map; const u8 *red = cursor_color_map;
const u8 *green = cursor_color_map; const u8 *green = cursor_color_map;
...@@ -58,26 +57,28 @@ void aty_set_cursor_color(struct fb_info_aty *fb) ...@@ -58,26 +57,28 @@ void aty_set_cursor_color(struct fb_info_aty *fb)
return; return;
#ifdef __sparc__ #ifdef __sparc__
if (fb->mmaped && (!fb->fb_info.display_fg if (par->mmaped && (!info->display_fg
|| fb->fb_info.display_fg->vc_num == fb->vtconsole)) || info->display_fg->vc_num ==
par->vtconsole))
return; return;
#endif #endif
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
c->color[i] = (u32)red[i] << 24; c->color[i] = (u32) red[i] << 24;
c->color[i] |= (u32)green[i] << 16; c->color[i] |= (u32) green[i] << 16;
c->color[i] |= (u32)blue[i] << 8; c->color[i] |= (u32) blue[i] << 8;
c->color[i] |= (u32)pixel[i]; c->color[i] |= (u32) pixel[i];
} }
wait_for_fifo(2, fb); wait_for_fifo(2, par);
aty_st_le32(CUR_CLR0, c->color[0], fb); aty_st_le32(CUR_CLR0, c->color[0], par);
aty_st_le32(CUR_CLR1, c->color[1], fb); aty_st_le32(CUR_CLR1, c->color[1], par);
} }
void aty_set_cursor_shape(struct fb_info_aty *fb) void aty_set_cursor_shape(struct fb_info *info)
{ {
struct aty_cursor *c = fb->cursor; struct atyfb_par *par = (struct atyfb_par *) info->par;
struct aty_cursor *c = par->cursor;
u8 *ram, m, b; u8 *ram, m, b;
int x, y; int x, y;
...@@ -85,8 +86,9 @@ void aty_set_cursor_shape(struct fb_info_aty *fb) ...@@ -85,8 +86,9 @@ void aty_set_cursor_shape(struct fb_info_aty *fb)
return; return;
#ifdef __sparc__ #ifdef __sparc__
if (fb->mmaped && (!fb->fb_info.display_fg if (par->mmaped && (!info->display_fg
|| fb->fb_info.display_fg->vc_num == fb->vtconsole)) || info->display_fg->vc_num ==
par->vtconsole))
return; return;
#endif #endif
...@@ -95,26 +97,24 @@ void aty_set_cursor_shape(struct fb_info_aty *fb) ...@@ -95,26 +97,24 @@ void aty_set_cursor_shape(struct fb_info_aty *fb)
for (x = 0; x < c->size.x >> 2; x++) { for (x = 0; x < c->size.x >> 2; x++) {
m = c->mask[x][y]; m = c->mask[x][y];
b = c->bits[x][y]; b = c->bits[x][y];
fb_writeb (cursor_mask_lookup[m >> 4] | fb_writeb(cursor_mask_lookup[m >> 4] |
cursor_bits_lookup[(b & m) >> 4], cursor_bits_lookup[(b & m) >> 4], ram++);
ram++); fb_writeb(cursor_mask_lookup[m & 0x0f] |
fb_writeb (cursor_mask_lookup[m & 0x0f] | cursor_bits_lookup[(b & m) & 0x0f],
cursor_bits_lookup[(b & m) & 0x0f], ram++);
ram++);
} }
for ( ; x < 8; x++) { for (; x < 8; x++) {
fb_writeb (0xaa, ram++); fb_writeb(0xaa, ram++);
fb_writeb (0xaa, ram++); fb_writeb(0xaa, ram++);
} }
} }
fb_memset (ram, 0xaa, (64 - c->size.y) * 16); fb_memset(ram, 0xaa, (64 - c->size.y) * 16);
} }
static void static void aty_set_cursor(struct fb_info *info, int on)
aty_set_cursor(struct fb_info_aty *fb, int on)
{ {
struct atyfb_par *par = &fb->current_par; struct atyfb_par *par = (struct atyfb_par *) info->par;
struct aty_cursor *c = fb->cursor; struct aty_cursor *c = par->cursor;
u16 xoff, yoff; u16 xoff, yoff;
int x, y; int x, y;
...@@ -122,8 +122,9 @@ aty_set_cursor(struct fb_info_aty *fb, int on) ...@@ -122,8 +122,9 @@ aty_set_cursor(struct fb_info_aty *fb, int on)
return; return;
#ifdef __sparc__ #ifdef __sparc__
if (fb->mmaped && (!fb->fb_info.display_fg if (par->mmaped && (!info->display_fg
|| fb->fb_info.display_fg->vc_num == fb->vtconsole)) || info->display_fg->vc_num ==
par->vtconsole))
return; return;
#endif #endif
...@@ -144,67 +145,72 @@ aty_set_cursor(struct fb_info_aty *fb, int on) ...@@ -144,67 +145,72 @@ aty_set_cursor(struct fb_info_aty *fb, int on)
yoff = 0; yoff = 0;
} }
wait_for_fifo(4, fb); wait_for_fifo(4, par);
aty_st_le32(CUR_OFFSET, (c->offset >> 3) + (yoff << 1), fb); aty_st_le32(CUR_OFFSET, (c->offset >> 3) + (yoff << 1),
par);
aty_st_le32(CUR_HORZ_VERT_OFF, aty_st_le32(CUR_HORZ_VERT_OFF,
((u32)(64 - c->size.y + yoff) << 16) | xoff, fb); ((u32) (64 - c->size.y + yoff) << 16) | xoff,
aty_st_le32(CUR_HORZ_VERT_POSN, ((u32)y << 16) | x, fb); par);
aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, fb) aty_st_le32(CUR_HORZ_VERT_POSN, ((u32) y << 16) | x, par);
| HWCURSOR_ENABLE, fb); aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par)
| HWCURSOR_ENABLE, par);
} else { } else {
wait_for_fifo(1, fb); wait_for_fifo(1, par);
aty_st_le32(GEN_TEST_CNTL, aty_st_le32(GEN_TEST_CNTL,
aty_ld_le32(GEN_TEST_CNTL, fb) & ~HWCURSOR_ENABLE, aty_ld_le32(GEN_TEST_CNTL,
fb); par) & ~HWCURSOR_ENABLE, par);
} }
if (fb->blitter_may_be_busy) if (par->blitter_may_be_busy)
wait_for_idle(fb); wait_for_idle(par);
} }
static void static void aty_cursor_timer_handler(unsigned long dev_addr)
aty_cursor_timer_handler(unsigned long dev_addr)
{ {
struct fb_info_aty *fb = (struct fb_info_aty *)dev_addr; struct fb_info *info = (struct fb_info *) dev_addr;
struct atyfb_par *par = (struct atyfb_par *) info->par;
if (!fb->cursor) if (!par->cursor)
return; return;
if (!fb->cursor->enable) if (!par->cursor->enable)
goto out; goto out;
if (fb->cursor->vbl_cnt && --fb->cursor->vbl_cnt == 0) { if (par->cursor->vbl_cnt && --par->cursor->vbl_cnt == 0) {
fb->cursor->on ^= 1; par->cursor->on ^= 1;
aty_set_cursor(fb, fb->cursor->on); aty_set_cursor(info, par->cursor->on);
fb->cursor->vbl_cnt = fb->cursor->blink_rate; par->cursor->vbl_cnt = par->cursor->blink_rate;
} }
out: out:
fb->cursor->timer->expires = jiffies + (HZ / 50); par->cursor->timer->expires = jiffies + (HZ / 50);
add_timer(fb->cursor->timer); add_timer(par->cursor->timer);
} }
void atyfb_cursor(struct display *p, int mode, int x, int y) void atyfb_cursor(struct display *p, int mode, int x, int y)
{ {
struct fb_info_aty *fb = (struct fb_info_aty *)p->fb_info; struct fb_info *info = p->fb_info;
struct aty_cursor *c = fb->cursor; struct atyfb_par *par = (struct atyfb_par *) info->par;
struct aty_cursor *c = par->cursor;
if (!c) if (!c)
return; return;
#ifdef __sparc__ #ifdef __sparc__
if (fb->mmaped && (!fb->fb_info.display_fg if (par->mmaped && (!info->display_fg
|| fb->fb_info.display_fg->vc_num == fb->vtconsole)) || info->display_fg->vc_num ==
par->vtconsole))
return; return;
#endif #endif
x *= fontwidth(p); x *= fontwidth(p);
y *= fontheight(p); y *= fontheight(p);
if (c->pos.x == x && c->pos.y == y && (mode == CM_ERASE) == !c->enable) if (c->pos.x == x && c->pos.y == y
&& (mode == CM_ERASE) == !c->enable)
return; return;
c->enable = 0; c->enable = 0;
if (c->on) if (c->on)
aty_set_cursor(fb, 0); aty_set_cursor(info, 0);
c->pos.x = x; c->pos.x = x;
c->pos.y = y; c->pos.y = y;
...@@ -216,7 +222,7 @@ void atyfb_cursor(struct display *p, int mode, int x, int y) ...@@ -216,7 +222,7 @@ void atyfb_cursor(struct display *p, int mode, int x, int y)
case CM_DRAW: case CM_DRAW:
case CM_MOVE: case CM_MOVE:
if (c->on) if (c->on)
aty_set_cursor(fb, 1); aty_set_cursor(info, 1);
else else
c->vbl_cnt = CURSOR_DRAW_DELAY; c->vbl_cnt = CURSOR_DRAW_DELAY;
c->enable = 1; c->enable = 1;
...@@ -224,7 +230,7 @@ void atyfb_cursor(struct display *p, int mode, int x, int y) ...@@ -224,7 +230,7 @@ void atyfb_cursor(struct display *p, int mode, int x, int y)
} }
} }
struct aty_cursor * __init aty_init_cursor(struct fb_info_aty *fb) struct aty_cursor *__init aty_init_cursor(struct fb_info *info)
{ {
struct aty_cursor *cursor; struct aty_cursor *cursor;
unsigned long addr; unsigned long addr;
...@@ -242,19 +248,19 @@ struct aty_cursor * __init aty_init_cursor(struct fb_info_aty *fb) ...@@ -242,19 +248,19 @@ struct aty_cursor * __init aty_init_cursor(struct fb_info_aty *fb)
memset(cursor->timer, 0, sizeof(*cursor->timer)); memset(cursor->timer, 0, sizeof(*cursor->timer));
cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE; cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE;
fb->fb_info.fix.smem_len -= PAGE_SIZE; info->fix.smem_len -= PAGE_SIZE;
cursor->offset = fb->fb_info.fix.smem_len; cursor->offset = info->fix.smem_len;
#ifdef __sparc__ #ifdef __sparc__
addr = fb->fb_info.screen_base - 0x800000 + cursor->offset; addr = info->screen_base - 0x800000 + cursor->offset;
cursor->ram = (u8 *)addr; cursor->ram = (u8 *) addr;
#else #else
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
addr = fb->fb_info.fix.smem_start - 0x800000 + cursor->offset; addr = info->fix.smem_start - 0x800000 + cursor->offset;
cursor->ram = (u8 *)ioremap(addr, 1024); cursor->ram = (u8 *) ioremap(addr, 1024);
#else #else
addr = (unsigned long) fb->fb_info.screen_base + cursor->offset; addr = (unsigned long) info->screen_base + cursor->offset;
cursor->ram = (u8 *)addr; cursor->ram = (u8 *) addr;
#endif #endif
#endif #endif
...@@ -265,41 +271,42 @@ struct aty_cursor * __init aty_init_cursor(struct fb_info_aty *fb) ...@@ -265,41 +271,42 @@ struct aty_cursor * __init aty_init_cursor(struct fb_info_aty *fb)
init_timer(cursor->timer); init_timer(cursor->timer);
cursor->timer->expires = jiffies + (HZ / 50); cursor->timer->expires = jiffies + (HZ / 50);
cursor->timer->data = (unsigned long)fb; cursor->timer->data = (unsigned long) info;
cursor->timer->function = aty_cursor_timer_handler; cursor->timer->function = aty_cursor_timer_handler;
add_timer(cursor->timer); add_timer(cursor->timer);
return cursor; return cursor;
} }
int atyfb_set_font(struct display *d, int width, int height) int atyfb_set_font(struct display *d, int width, int height)
{ {
struct fb_info_aty *fb = (struct fb_info_aty *)d->fb_info; struct fb_info *info = d->fb_info;
struct aty_cursor *c = fb->cursor; struct atyfb_par *par = (struct atyfb_par *) info->par;
int i, j; struct aty_cursor *c = par->cursor;
int i, j;
if (c) {
if (!width || !height) { if (c) {
width = 8; if (!width || !height) {
height = 16; width = 8;
} height = 16;
}
c->hot.x = 0; c->hot.x = 0;
c->hot.y = 0; c->hot.y = 0;
c->size.x = width; c->size.x = width;
c->size.y = height; c->size.y = height;
memset(c->bits, 0xff, sizeof(c->bits)); memset(c->bits, 0xff, sizeof(c->bits));
memset(c->mask, 0, sizeof(c->mask)); memset(c->mask, 0, sizeof(c->mask));
for (i = 0, j = width; j >= 0; j -= 8, i++) { for (i = 0, j = width; j >= 0; j -= 8, i++) {
c->mask[i][height-2] = (j >= 8) ? 0xff : (0xff << (8 - j)); c->mask[i][height - 2] =
c->mask[i][height-1] = (j >= 8) ? 0xff : (0xff << (8 - j)); (j >= 8) ? 0xff : (0xff << (8 - j));
} c->mask[i][height - 1] =
(j >= 8) ? 0xff : (0xff << (8 - j));
}
aty_set_cursor_color(fb); aty_set_cursor_color(info);
aty_set_cursor_shape(fb); aty_set_cursor_shape(info);
} }
return 1; return 1;
} }
...@@ -16,13 +16,13 @@ ...@@ -16,13 +16,13 @@
/* Definitions for the ICS 2595 == ATI 18818_1 Clockchip */ /* Definitions for the ICS 2595 == ATI 18818_1 Clockchip */
#define REF_FREQ_2595 1432 /* 14.33 MHz (exact 14.31818) */ #define REF_FREQ_2595 1432 /* 14.33 MHz (exact 14.31818) */
#define REF_DIV_2595 46 /* really 43 on ICS 2595 !!! */ #define REF_DIV_2595 46 /* really 43 on ICS 2595 !!! */
/* ohne Prescaler */ /* ohne Prescaler */
#define MAX_FREQ_2595 15938 /* 159.38 MHz (really 170.486) */ #define MAX_FREQ_2595 15938 /* 159.38 MHz (really 170.486) */
#define MIN_FREQ_2595 8000 /* 80.00 MHz ( 85.565) */ #define MIN_FREQ_2595 8000 /* 80.00 MHz ( 85.565) */
/* mit Prescaler 2, 4, 8 */ /* mit Prescaler 2, 4, 8 */
#define ABS_MIN_FREQ_2595 1000 /* 10.00 MHz (really 10.697) */ #define ABS_MIN_FREQ_2595 1000 /* 10.00 MHz (really 10.697) */
#define N_ADJ_2595 257 #define N_ADJ_2595 257
#define STOP_BITS_2595 0x1800 #define STOP_BITS_2595 0x1800
...@@ -42,26 +42,25 @@ ...@@ -42,26 +42,25 @@
* Support Functions * Support Functions
*/ */
static void aty_dac_waste4(const struct fb_info_aty *info) static void aty_dac_waste4(const struct atyfb_par *par)
{ {
(void)aty_ld_8(DAC_REGS, info); (void) aty_ld_8(DAC_REGS, par);
(void)aty_ld_8(DAC_REGS + 2, info); (void) aty_ld_8(DAC_REGS + 2, par);
(void)aty_ld_8(DAC_REGS + 2, info); (void) aty_ld_8(DAC_REGS + 2, par);
(void)aty_ld_8(DAC_REGS + 2, info); (void) aty_ld_8(DAC_REGS + 2, par);
(void)aty_ld_8(DAC_REGS + 2, info); (void) aty_ld_8(DAC_REGS + 2, par);
} }
static void aty_StrobeClock(const struct fb_info_aty *info) static void aty_StrobeClock(const struct atyfb_par *par)
{ {
u8 tmp; u8 tmp;
udelay(26); udelay(26);
tmp = aty_ld_8(CLOCK_CNTL, info); tmp = aty_ld_8(CLOCK_CNTL, par);
aty_st_8(CLOCK_CNTL + info->clk_wr_offset, tmp | CLOCK_STROBE, info); aty_st_8(CLOCK_CNTL + par->clk_wr_offset, tmp | CLOCK_STROBE, par);
return;
return;
} }
...@@ -69,120 +68,136 @@ static void aty_StrobeClock(const struct fb_info_aty *info) ...@@ -69,120 +68,136 @@ static void aty_StrobeClock(const struct fb_info_aty *info)
* IBM RGB514 DAC and Clock Chip * IBM RGB514 DAC and Clock Chip
*/ */
static void aty_st_514(int offset, u8 val, const struct fb_info_aty *info) static void aty_st_514(int offset, u8 val, const struct atyfb_par *par)
{ {
aty_st_8(DAC_CNTL, 1, info); aty_st_8(DAC_CNTL, 1, par);
/* right addr byte */ /* right addr byte */
aty_st_8(DAC_W_INDEX, offset & 0xff, info); aty_st_8(DAC_W_INDEX, offset & 0xff, par);
/* left addr byte */ /* left addr byte */
aty_st_8(DAC_DATA, (offset >> 8) & 0xff, info); aty_st_8(DAC_DATA, (offset >> 8) & 0xff, par);
aty_st_8(DAC_MASK, val, info); aty_st_8(DAC_MASK, val, par);
aty_st_8(DAC_CNTL, 0, info); aty_st_8(DAC_CNTL, 0, par);
} }
static int aty_set_dac_514(const struct fb_info_aty *info, static int aty_set_dac_514(const struct fb_info *info,
const union aty_pll *pll, u32 bpp, u32 accel) const union aty_pll *pll, u32 bpp, u32 accel)
{ {
static struct { struct atyfb_par *par = (struct atyfb_par *) info->par;
u8 pixel_dly; static struct {
u8 misc2_cntl; u8 pixel_dly;
u8 pixel_rep; u8 misc2_cntl;
u8 pixel_cntl_index; u8 pixel_rep;
u8 pixel_cntl_v1; u8 pixel_cntl_index;
} tab[3] = { u8 pixel_cntl_v1;
{ 0, 0x41, 0x03, 0x71, 0x45 }, /* 8 bpp */ } tab[3] = {
{ 0, 0x45, 0x04, 0x0c, 0x01 }, /* 555 */ {
{ 0, 0x45, 0x06, 0x0e, 0x00 }, /* XRGB */ 0, 0x41, 0x03, 0x71, 0x45}, /* 8 bpp */
}; {
int i; 0, 0x45, 0x04, 0x0c, 0x01}, /* 555 */
{
switch (bpp) { 0, 0x45, 0x06, 0x0e, 0x00}, /* XRGB */
};
int i;
switch (bpp) {
case 8: case 8:
default: default:
i = 0; i = 0;
break; break;
case 16: case 16:
i = 1; i = 1;
break; break;
case 32: case 32:
i = 2; i = 2;
break; break;
} }
aty_st_514(0x90, 0x00, info); /* VRAM Mask Low */ aty_st_514(0x90, 0x00, par); /* VRAM Mask Low */
aty_st_514(0x04, tab[i].pixel_dly, info); /* Horizontal Sync Control */ aty_st_514(0x04, tab[i].pixel_dly, par); /* Horizontal Sync Control */
aty_st_514(0x05, 0x00, info); /* Power Management */ aty_st_514(0x05, 0x00, par); /* Power Management */
aty_st_514(0x02, 0x01, info); /* Misc Clock Control */ aty_st_514(0x02, 0x01, par); /* Misc Clock Control */
aty_st_514(0x71, tab[i].misc2_cntl, info); /* Misc Control 2 */ aty_st_514(0x71, tab[i].misc2_cntl, par); /* Misc Control 2 */
aty_st_514(0x0a, tab[i].pixel_rep, info); /* Pixel Format */ aty_st_514(0x0a, tab[i].pixel_rep, par); /* Pixel Format */
aty_st_514(tab[i].pixel_cntl_index, tab[i].pixel_cntl_v1, info); aty_st_514(tab[i].pixel_cntl_index, tab[i].pixel_cntl_v1, par);
/* Misc Control 2 / 16 BPP Control / 32 BPP Control */ /* Misc Control 2 / 16 BPP Control / 32 BPP Control */
return 0; return 0;
} }
static int aty_var_to_pll_514(const struct fb_info_aty *info, u32 vclk_per, static int aty_var_to_pll_514(const struct fb_info *info, u32 vclk_per,
u8 bpp, union aty_pll *pll) u8 bpp, union aty_pll *pll)
{ {
/* /*
* FIXME: use real calculations instead of using fixed values from the old * FIXME: use real calculations instead of using fixed values from the old
* driver * driver
*/ */
static struct { static struct {
u32 limit; /* pixlock rounding limit (arbitrary) */ u32 limit; /* pixlock rounding limit (arbitrary) */
u8 m; /* (df<<6) | vco_div_count */ u8 m; /* (df<<6) | vco_div_count */
u8 n; /* ref_div_count */ u8 n; /* ref_div_count */
} RGB514_clocks[7] = { } RGB514_clocks[7] = {
{ 8000, (3<<6) | 20, 9 }, /* 7395 ps / 135.2273 MHz */ {
{ 10000, (1<<6) | 19, 3 }, /* 9977 ps / 100.2273 MHz */ 8000, (3 << 6) | 20, 9}, /* 7395 ps / 135.2273 MHz */
{ 13000, (1<<6) | 2, 3 }, /* 12509 ps / 79.9432 MHz */ {
{ 14000, (2<<6) | 8, 7 }, /* 13394 ps / 74.6591 MHz */ 10000, (1 << 6) | 19, 3}, /* 9977 ps / 100.2273 MHz */
{ 16000, (1<<6) | 44, 6 }, /* 15378 ps / 65.0284 MHz */ {
{ 25000, (1<<6) | 15, 5 }, /* 17460 ps / 57.2727 MHz */ 13000, (1 << 6) | 2, 3}, /* 12509 ps / 79.9432 MHz */
{ 50000, (0<<6) | 53, 7 }, /* 33145 ps / 30.1705 MHz */ {
}; 14000, (2 << 6) | 8, 7}, /* 13394 ps / 74.6591 MHz */
int i; {
16000, (1 << 6) | 44, 6}, /* 15378 ps / 65.0284 MHz */
for (i = 0; i < sizeof(RGB514_clocks)/sizeof(*RGB514_clocks); i++) {
if (vclk_per <= RGB514_clocks[i].limit) { 25000, (1 << 6) | 15, 5}, /* 17460 ps / 57.2727 MHz */
pll->ibm514.m = RGB514_clocks[i].m; {
pll->ibm514.n = RGB514_clocks[i].n; 50000, (0 << 6) | 53, 7}, /* 33145 ps / 30.1705 MHz */
return 0; };
} int i;
return -EINVAL;
for (i = 0; i < sizeof(RGB514_clocks) / sizeof(*RGB514_clocks);
i++)
if (vclk_per <= RGB514_clocks[i].limit) {
pll->ibm514.m = RGB514_clocks[i].m;
pll->ibm514.n = RGB514_clocks[i].n;
return 0;
}
return -EINVAL;
} }
static u32 aty_pll_514_to_var(const struct fb_info_aty *info, static u32 aty_pll_514_to_var(const struct fb_info *info,
const union aty_pll *pll) const union aty_pll *pll)
{ {
u8 df, vco_div_count, ref_div_count; struct atyfb_par *par = (struct atyfb_par *) info->par;
u8 df, vco_div_count, ref_div_count;
df = pll->ibm514.m >> 6; df = pll->ibm514.m >> 6;
vco_div_count = pll->ibm514.m & 0x3f; vco_div_count = pll->ibm514.m & 0x3f;
ref_div_count = pll->ibm514.n; ref_div_count = pll->ibm514.n;
return ((info->ref_clk_per*ref_div_count)<<(3-df))/(vco_div_count+65); return ((par->ref_clk_per * ref_div_count) << (3 - df))/
(vco_div_count + 65);
} }
static void aty_set_pll_514(const struct fb_info_aty *info, static void aty_set_pll_514(const struct fb_info *info,
const union aty_pll *pll) const union aty_pll *pll)
{ {
aty_st_514(0x06, 0x02, info); /* DAC Operation */ struct atyfb_par *par = (struct atyfb_par *) info->par;
aty_st_514(0x10, 0x01, info); /* PLL Control 1 */
aty_st_514(0x70, 0x01, info); /* Misc Control 1 */ aty_st_514(0x06, 0x02, par); /* DAC Operation */
aty_st_514(0x8f, 0x1f, info); /* PLL Ref. Divider Input */ aty_st_514(0x10, 0x01, par); /* PLL Control 1 */
aty_st_514(0x03, 0x00, info); /* Sync Control */ aty_st_514(0x70, 0x01, par); /* Misc Control 1 */
aty_st_514(0x05, 0x00, info); /* Power Management */ aty_st_514(0x8f, 0x1f, par); /* PLL Ref. Divider Input */
aty_st_514(0x20, pll->ibm514.m, info); /* F0 / M0 */ aty_st_514(0x03, 0x00, par); /* Sync Control */
aty_st_514(0x21, pll->ibm514.n, info); /* F1 / N0 */ aty_st_514(0x05, 0x00, par); /* Power Management */
aty_st_514(0x20, pll->ibm514.m, par); /* F0 / M0 */
aty_st_514(0x21, pll->ibm514.n, par); /* F1 / N0 */
} }
const struct aty_dac_ops aty_dac_ibm514 = { const struct aty_dac_ops aty_dac_ibm514 = {
set_dac: aty_set_dac_514, set_dac:aty_set_dac_514,
}; };
const struct aty_pll_ops aty_pll_ibm514 = { const struct aty_pll_ops aty_pll_ibm514 = {
var_to_pll: aty_var_to_pll_514, var_to_pll:aty_var_to_pll_514,
pll_to_var: aty_pll_514_to_var, pll_to_var:aty_pll_514_to_var,
set_pll: aty_set_pll_514, set_pll:aty_set_pll_514,
}; };
...@@ -190,77 +205,82 @@ const struct aty_pll_ops aty_pll_ibm514 = { ...@@ -190,77 +205,82 @@ const struct aty_pll_ops aty_pll_ibm514 = {
* ATI 68860-B DAC * ATI 68860-B DAC
*/ */
static int aty_set_dac_ATI68860_B(const struct fb_info_aty *info, static int aty_set_dac_ATI68860_B(const struct fb_info *info,
const union aty_pll *pll, u32 bpp, u32 accel) const union aty_pll *pll, u32 bpp,
u32 accel)
{ {
u32 gModeReg, devSetupRegA, temp, mask; struct atyfb_par *par = (struct atyfb_par *) info->par;
u32 gModeReg, devSetupRegA, temp, mask;
gModeReg = 0; gModeReg = 0;
devSetupRegA = 0; devSetupRegA = 0;
switch (bpp) { switch (bpp) {
case 8: case 8:
gModeReg = 0x83; gModeReg = 0x83;
devSetupRegA = 0x60 | 0x00 /*(info->mach64DAC8Bit ? 0x00 : 0x01) */; devSetupRegA =
break; 0x60 | 0x00 /*(info->mach64DAC8Bit ? 0x00 : 0x01) */ ;
break;
case 15: case 15:
gModeReg = 0xA0; gModeReg = 0xA0;
devSetupRegA = 0x60; devSetupRegA = 0x60;
break; break;
case 16: case 16:
gModeReg = 0xA1; gModeReg = 0xA1;
devSetupRegA = 0x60; devSetupRegA = 0x60;
break; break;
case 24: case 24:
gModeReg = 0xC0; gModeReg = 0xC0;
devSetupRegA = 0x60; devSetupRegA = 0x60;
break; break;
case 32: case 32:
gModeReg = 0xE3; gModeReg = 0xE3;
devSetupRegA = 0x60; devSetupRegA = 0x60;
break; break;
} }
if (!accel) { if (!accel) {
gModeReg = 0x80; gModeReg = 0x80;
devSetupRegA = 0x61; devSetupRegA = 0x61;
} }
temp = aty_ld_8(DAC_CNTL, info); temp = aty_ld_8(DAC_CNTL, par);
aty_st_8(DAC_CNTL, (temp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3, info); aty_st_8(DAC_CNTL, (temp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3,
par);
aty_st_8(DAC_REGS + 2, 0x1D, info);
aty_st_8(DAC_REGS + 3, gModeReg, info); aty_st_8(DAC_REGS + 2, 0x1D, par);
aty_st_8(DAC_REGS, 0x02, info); aty_st_8(DAC_REGS + 3, gModeReg, par);
aty_st_8(DAC_REGS, 0x02, par);
temp = aty_ld_8(DAC_CNTL, info);
aty_st_8(DAC_CNTL, temp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, info); temp = aty_ld_8(DAC_CNTL, par);
aty_st_8(DAC_CNTL, temp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, par);
if (info->total_vram < MEM_SIZE_1M)
mask = 0x04; if (info->fix.smem_len < MEM_SIZE_1M)
else if (info->total_vram == MEM_SIZE_1M) mask = 0x04;
mask = 0x08; else if (info->fix.smem_len == MEM_SIZE_1M)
else mask = 0x08;
mask = 0x0C; else
mask = 0x0C;
/* The following assumes that the BIOS has correctly set R7 of the
* Device Setup Register A at boot time.
*/
#define A860_DELAY_L 0x80
temp = aty_ld_8(DAC_REGS, info); /* The following assumes that the BIOS has correctly set R7 of the
aty_st_8(DAC_REGS, (devSetupRegA | mask) | (temp & A860_DELAY_L), info); * Device Setup Register A at boot time.
temp = aty_ld_8(DAC_CNTL, info); */
aty_st_8(DAC_CNTL, (temp & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3)), info); #define A860_DELAY_L 0x80
aty_st_le32(BUS_CNTL, 0x890e20f1, info); temp = aty_ld_8(DAC_REGS, par);
aty_st_le32(DAC_CNTL, 0x47052100, info); aty_st_8(DAC_REGS, (devSetupRegA | mask) | (temp & A860_DELAY_L),
par);
temp = aty_ld_8(DAC_CNTL, par);
aty_st_8(DAC_CNTL, (temp & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3)),
par);
return 0; aty_st_le32(BUS_CNTL, 0x890e20f1, par);
aty_st_le32(DAC_CNTL, 0x47052100, par);
return 0;
} }
const struct aty_dac_ops aty_dac_ati68860b = { const struct aty_dac_ops aty_dac_ati68860b = {
set_dac: aty_set_dac_ATI68860_B, set_dac:aty_set_dac_ATI68860_B,
}; };
...@@ -268,50 +288,52 @@ const struct aty_dac_ops aty_dac_ati68860b = { ...@@ -268,50 +288,52 @@ const struct aty_dac_ops aty_dac_ati68860b = {
* AT&T 21C498 DAC * AT&T 21C498 DAC
*/ */
static int aty_set_dac_ATT21C498(const struct fb_info_aty *info, static int aty_set_dac_ATT21C498(const struct fb_info *info,
const union aty_pll *pll, u32 bpp, u32 accel) const union aty_pll *pll, u32 bpp,
u32 accel)
{ {
u32 dotClock; struct atyfb_par *par = (struct atyfb_par *) info->par;
int muxmode = 0; u32 dotClock;
int DACMask = 0; int muxmode = 0;
int DACMask = 0;
dotClock = 100000000 / pll->ics2595.period_in_ps; dotClock = 100000000 / pll->ics2595.period_in_ps;
switch (bpp) { switch (bpp) {
case 8: case 8:
if (dotClock > 8000) { if (dotClock > 8000) {
DACMask = 0x24; DACMask = 0x24;
muxmode = 1; muxmode = 1;
} else } else
DACMask = 0x04; DACMask = 0x04;
break; break;
case 15: case 15:
DACMask = 0x16; DACMask = 0x16;
break; break;
case 16: case 16:
DACMask = 0x36; DACMask = 0x36;
break; break;
case 24: case 24:
DACMask = 0xE6; DACMask = 0xE6;
break; break;
case 32: case 32:
DACMask = 0xE6; DACMask = 0xE6;
break; break;
} }
if (1 /* info->mach64DAC8Bit */) if (1 /* info->mach64DAC8Bit */ )
DACMask |= 0x02; DACMask |= 0x02;
aty_dac_waste4(info); aty_dac_waste4(par);
aty_st_8(DAC_REGS + 2, DACMask, info); aty_st_8(DAC_REGS + 2, DACMask, par);
aty_st_le32(BUS_CNTL, 0x890e20f1, info); aty_st_le32(BUS_CNTL, 0x890e20f1, par);
aty_st_le32(DAC_CNTL, 0x00072000, info); aty_st_le32(DAC_CNTL, 0x00072000, par);
return muxmode; return muxmode;
} }
const struct aty_dac_ops aty_dac_att21c498 = { const struct aty_dac_ops aty_dac_att21c498 = {
set_dac: aty_set_dac_ATT21C498, set_dac: aty_set_dac_ATT21C498,
}; };
...@@ -319,154 +341,155 @@ const struct aty_dac_ops aty_dac_att21c498 = { ...@@ -319,154 +341,155 @@ const struct aty_dac_ops aty_dac_att21c498 = {
* ATI 18818 / ICS 2595 Clock Chip * ATI 18818 / ICS 2595 Clock Chip
*/ */
static int aty_var_to_pll_18818(const struct fb_info_aty *info, u32 vclk_per, static int aty_var_to_pll_18818(const struct fb_info *info,
u8 bpp, union aty_pll *pll) u32 vclk_per, u8 bpp, union aty_pll *pll)
{ {
u32 MHz100; /* in 0.01 MHz */ u32 MHz100; /* in 0.01 MHz */
u32 program_bits; u32 program_bits;
u32 post_divider; u32 post_divider;
/* Calculate the programming word */ /* Calculate the programming word */
MHz100 = 100000000 / vclk_per; MHz100 = 100000000 / vclk_per;
program_bits = -1; program_bits = -1;
post_divider = 1; post_divider = 1;
if (MHz100 > MAX_FREQ_2595) { if (MHz100 > MAX_FREQ_2595) {
MHz100 = MAX_FREQ_2595; MHz100 = MAX_FREQ_2595;
return -EINVAL; return -EINVAL;
} else if (MHz100 < ABS_MIN_FREQ_2595) { } else if (MHz100 < ABS_MIN_FREQ_2595) {
program_bits = 0; /* MHz100 = 257 */ program_bits = 0; /* MHz100 = 257 */
return -EINVAL; return -EINVAL;
} else { } else {
while (MHz100 < MIN_FREQ_2595) { while (MHz100 < MIN_FREQ_2595) {
MHz100 *= 2; MHz100 *= 2;
post_divider *= 2; post_divider *= 2;
}
} }
} MHz100 *= 1000;
MHz100 *= 1000; MHz100 = (REF_DIV_2595 * MHz100) / REF_FREQ_2595;
MHz100 = (REF_DIV_2595 * MHz100) / REF_FREQ_2595;
MHz100 += 500; /* + 0.5 round */
MHz100 += 500; /* + 0.5 round */ MHz100 /= 1000;
MHz100 /= 1000;
if (program_bits == -1) {
if (program_bits == -1) { program_bits = MHz100 - N_ADJ_2595;
program_bits = MHz100 - N_ADJ_2595; switch (post_divider) {
switch (post_divider) { case 1:
case 1: program_bits |= 0x0600;
program_bits |= 0x0600; break;
break; case 2:
case 2: program_bits |= 0x0400;
program_bits |= 0x0400; break;
break; case 4:
case 4: program_bits |= 0x0200;
program_bits |= 0x0200; break;
break; case 8:
case 8: default:
default: break;
break; }
} }
}
program_bits |= STOP_BITS_2595; program_bits |= STOP_BITS_2595;
pll->ics2595.program_bits = program_bits; pll->ics2595.program_bits = program_bits;
pll->ics2595.locationAddr = 0; pll->ics2595.locationAddr = 0;
pll->ics2595.post_divider = post_divider; pll->ics2595.post_divider = post_divider;
pll->ics2595.period_in_ps = vclk_per; pll->ics2595.period_in_ps = vclk_per;
return 0; return 0;
} }
static u32 aty_pll_18818_to_var(const struct fb_info_aty *info, static u32 aty_pll_18818_to_var(const struct fb_info *info,
const union aty_pll *pll) const union aty_pll *pll)
{ {
return(pll->ics2595.period_in_ps); /* default for now */ return (pll->ics2595.period_in_ps); /* default for now */
} }
static void aty_ICS2595_put1bit(u8 data, const struct fb_info_aty *info) static void aty_ICS2595_put1bit(u8 data, const struct atyfb_par *par)
{ {
u8 tmp; u8 tmp;
data &= 0x01; data &= 0x01;
tmp = aty_ld_8(CLOCK_CNTL, info); tmp = aty_ld_8(CLOCK_CNTL, par);
aty_st_8(CLOCK_CNTL + info->clk_wr_offset, (tmp & ~0x04) | (data << 2), aty_st_8(CLOCK_CNTL + par->clk_wr_offset,
info); (tmp & ~0x04) | (data << 2), par);
tmp = aty_ld_8(CLOCK_CNTL, info); tmp = aty_ld_8(CLOCK_CNTL, par);
aty_st_8(CLOCK_CNTL + info->clk_wr_offset, (tmp & ~0x08) | (0 << 3), info); aty_st_8(CLOCK_CNTL + par->clk_wr_offset, (tmp & ~0x08) | (0 << 3),
par);
aty_StrobeClock(info); aty_StrobeClock(par);
tmp = aty_ld_8(CLOCK_CNTL, info); tmp = aty_ld_8(CLOCK_CNTL, par);
aty_st_8(CLOCK_CNTL + info->clk_wr_offset, (tmp & ~0x08) | (1 << 3), info); aty_st_8(CLOCK_CNTL + par->clk_wr_offset, (tmp & ~0x08) | (1 << 3),
par);
aty_StrobeClock(info); aty_StrobeClock(par);
return;
return;
} }
static void aty_set_pll18818(const struct fb_info_aty *info, static void aty_set_pll18818(const struct fb_info *info,
const union aty_pll *pll) const union aty_pll *pll)
{ {
u32 program_bits; struct atyfb_par *par = (struct atyfb_par *) info->par;
u32 locationAddr; u32 program_bits;
u32 locationAddr;
u32 i;
u8 old_clock_cntl; u32 i;
u8 old_crtc_ext_disp;
old_clock_cntl = aty_ld_8(CLOCK_CNTL, info); u8 old_clock_cntl;
aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 0, info); u8 old_crtc_ext_disp;
old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info); old_clock_cntl = aty_ld_8(CLOCK_CNTL, par);
aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 0, par);
info);
mdelay(15); /* delay for 50 (15) ms */ old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
aty_st_8(CRTC_GEN_CNTL + 3,
old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par);
program_bits = pll->ics2595.program_bits; mdelay(15); /* delay for 50 (15) ms */
locationAddr = pll->ics2595.locationAddr;
/* Program the clock chip */ program_bits = pll->ics2595.program_bits;
aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 0, info); /* Strobe = 0 */ locationAddr = pll->ics2595.locationAddr;
aty_StrobeClock(info);
aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 1, info); /* Strobe = 0 */
aty_StrobeClock(info);
aty_ICS2595_put1bit(1, info); /* Send start bits */ /* Program the clock chip */
aty_ICS2595_put1bit(0, info); /* Start bit */ aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 0, par); /* Strobe = 0 */
aty_ICS2595_put1bit(0, info); /* Read / ~Write */ aty_StrobeClock(par);
aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 1, par); /* Strobe = 0 */
aty_StrobeClock(par);
for (i = 0; i < 5; i++) { /* Location 0..4 */ aty_ICS2595_put1bit(1, par); /* Send start bits */
aty_ICS2595_put1bit(locationAddr & 1, info); aty_ICS2595_put1bit(0, par); /* Start bit */
locationAddr >>= 1; aty_ICS2595_put1bit(0, par); /* Read / ~Write */
}
for (i = 0; i < 8 + 1 + 2 + 2; i++) { for (i = 0; i < 5; i++) { /* Location 0..4 */
aty_ICS2595_put1bit(program_bits & 1, info); aty_ICS2595_put1bit(locationAddr & 1, par);
program_bits >>= 1; locationAddr >>= 1;
} }
mdelay(1); /* delay for 1 ms */ for (i = 0; i < 8 + 1 + 2 + 2; i++) {
aty_ICS2595_put1bit(program_bits & 1, par);
program_bits >>= 1;
}
(void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */ mdelay(1); /* delay for 1 ms */
aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info);
aty_st_8(CLOCK_CNTL + info->clk_wr_offset, old_clock_cntl | CLOCK_STROBE,
info);
mdelay(50); /* delay for 50 (15) ms */ (void) aty_ld_8(DAC_REGS, par); /* Clear DAC Counter */
aty_st_8(CLOCK_CNTL + info->clk_wr_offset, aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par);
((pll->ics2595.locationAddr & 0x0F) | CLOCK_STROBE), info); aty_st_8(CLOCK_CNTL + par->clk_wr_offset,
old_clock_cntl | CLOCK_STROBE, par);
return; mdelay(50); /* delay for 50 (15) ms */
aty_st_8(CLOCK_CNTL + par->clk_wr_offset,
((pll->ics2595.locationAddr & 0x0F) | CLOCK_STROBE), par);
return;
} }
const struct aty_pll_ops aty_pll_ati18818_1 = { const struct aty_pll_ops aty_pll_ati18818_1 = {
var_to_pll: aty_var_to_pll_18818, var_to_pll:aty_var_to_pll_18818,
pll_to_var: aty_pll_18818_to_var, pll_to_var:aty_pll_18818_to_var,
set_pll: aty_set_pll18818, set_pll:aty_set_pll18818,
}; };
...@@ -474,112 +497,115 @@ const struct aty_pll_ops aty_pll_ati18818_1 = { ...@@ -474,112 +497,115 @@ const struct aty_pll_ops aty_pll_ati18818_1 = {
* STG 1703 Clock Chip * STG 1703 Clock Chip
*/ */
static int aty_var_to_pll_1703(const struct fb_info_aty *info, u32 vclk_per, static int aty_var_to_pll_1703(const struct fb_info *info,
u8 bpp, union aty_pll *pll) u32 vclk_per, u8 bpp, union aty_pll *pll)
{ {
u32 mhz100; /* in 0.01 MHz */ u32 mhz100; /* in 0.01 MHz */
u32 program_bits; u32 program_bits;
/* u32 post_divider; */ /* u32 post_divider; */
u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq; u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
u32 temp, tempB; u32 temp, tempB;
u16 remainder, preRemainder; u16 remainder, preRemainder;
short divider = 0, tempA; short divider = 0, tempA;
/* Calculate the programming word */ /* Calculate the programming word */
mhz100 = 100000000 / vclk_per; mhz100 = 100000000 / vclk_per;
mach64MinFreq = MIN_FREQ_2595; mach64MinFreq = MIN_FREQ_2595;
mach64MaxFreq = MAX_FREQ_2595; mach64MaxFreq = MAX_FREQ_2595;
mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */ mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */
/* Calculate program word */ /* Calculate program word */
if (mhz100 == 0) if (mhz100 == 0)
program_bits = 0xE0; program_bits = 0xE0;
else { else {
if (mhz100 < mach64MinFreq) if (mhz100 < mach64MinFreq)
mhz100 = mach64MinFreq; mhz100 = mach64MinFreq;
if (mhz100 > mach64MaxFreq) if (mhz100 > mach64MaxFreq)
mhz100 = mach64MaxFreq; mhz100 = mach64MaxFreq;
divider = 0; divider = 0;
while (mhz100 < (mach64MinFreq << 3)) { while (mhz100 < (mach64MinFreq << 3)) {
mhz100 <<= 1; mhz100 <<= 1;
divider += 0x20; divider += 0x20;
} }
temp = (unsigned int)(mhz100);
temp = (unsigned int)(temp * (MIN_N_1703 + 2));
temp -= (short)(mach64RefFreq << 1);
tempA = MIN_N_1703;
preRemainder = 0xffff;
do {
tempB = temp;
remainder = tempB % mach64RefFreq;
tempB = tempB / mach64RefFreq;
if ((tempB & 0xffff) <= 127 && (remainder <= preRemainder)) {
preRemainder = remainder;
divider &= ~0x1f;
divider |= tempA;
divider = (divider & 0x00ff) + ((tempB & 0xff) << 8);
}
temp += mhz100;
tempA++;
} while (tempA <= (MIN_N_1703 << 1));
program_bits = divider; temp = (unsigned int) (mhz100);
} temp = (unsigned int) (temp * (MIN_N_1703 + 2));
temp -= (short) (mach64RefFreq << 1);
tempA = MIN_N_1703;
preRemainder = 0xffff;
do {
tempB = temp;
remainder = tempB % mach64RefFreq;
tempB = tempB / mach64RefFreq;
if ((tempB & 0xffff) <= 127
&& (remainder <= preRemainder)) {
preRemainder = remainder;
divider &= ~0x1f;
divider |= tempA;
divider =
(divider & 0x00ff) +
((tempB & 0xff) << 8);
}
temp += mhz100;
tempA++;
} while (tempA <= (MIN_N_1703 << 1));
program_bits = divider;
}
pll->ics2595.program_bits = program_bits; pll->ics2595.program_bits = program_bits;
pll->ics2595.locationAddr = 0; pll->ics2595.locationAddr = 0;
pll->ics2595.post_divider = divider; /* fuer nix */ pll->ics2595.post_divider = divider; /* fuer nix */
pll->ics2595.period_in_ps = vclk_per; pll->ics2595.period_in_ps = vclk_per;
return 0; return 0;
} }
static u32 aty_pll_1703_to_var(const struct fb_info_aty *info, static u32 aty_pll_1703_to_var(const struct fb_info *info,
const union aty_pll *pll) const union aty_pll *pll)
{ {
return(pll->ics2595.period_in_ps); /* default for now */ return (pll->ics2595.period_in_ps); /* default for now */
} }
static void aty_set_pll_1703(const struct fb_info_aty *info, static void aty_set_pll_1703(const struct fb_info *info,
const union aty_pll *pll) const union aty_pll *pll)
{ {
u32 program_bits; struct atyfb_par *par = (struct atyfb_par *) info->par;
u32 locationAddr; u32 program_bits;
u32 locationAddr;
char old_crtc_ext_disp; char old_crtc_ext_disp;
old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info); old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), aty_st_8(CRTC_GEN_CNTL + 3,
info); old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par);
program_bits = pll->ics2595.program_bits; program_bits = pll->ics2595.program_bits;
locationAddr = pll->ics2595.locationAddr; locationAddr = pll->ics2595.locationAddr;
/* Program clock */ /* Program clock */
aty_dac_waste4(info); aty_dac_waste4(par);
(void)aty_ld_8(DAC_REGS + 2, info); (void) aty_ld_8(DAC_REGS + 2, par);
aty_st_8(DAC_REGS+2, (locationAddr << 1) + 0x20, info); aty_st_8(DAC_REGS + 2, (locationAddr << 1) + 0x20, par);
aty_st_8(DAC_REGS+2, 0, info); aty_st_8(DAC_REGS + 2, 0, par);
aty_st_8(DAC_REGS+2, (program_bits & 0xFF00) >> 8, info); aty_st_8(DAC_REGS + 2, (program_bits & 0xFF00) >> 8, par);
aty_st_8(DAC_REGS+2, (program_bits & 0xFF), info); aty_st_8(DAC_REGS + 2, (program_bits & 0xFF), par);
(void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */ (void) aty_ld_8(DAC_REGS, par); /* Clear DAC Counter */
aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info); aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par);
return;
return;
} }
const struct aty_pll_ops aty_pll_stg1703 = { const struct aty_pll_ops aty_pll_stg1703 = {
var_to_pll: aty_var_to_pll_1703, var_to_pll:aty_var_to_pll_1703,
pll_to_var: aty_pll_1703_to_var, pll_to_var:aty_pll_1703_to_var,
set_pll: aty_set_pll_1703, set_pll:aty_set_pll_1703,
}; };
...@@ -587,126 +613,123 @@ const struct aty_pll_ops aty_pll_stg1703 = { ...@@ -587,126 +613,123 @@ const struct aty_pll_ops aty_pll_stg1703 = {
* Chrontel 8398 Clock Chip * Chrontel 8398 Clock Chip
*/ */
static int aty_var_to_pll_8398(const struct fb_info_aty *info, u32 vclk_per, static int aty_var_to_pll_8398(const struct fb_info *info,
u8 bpp, union aty_pll *pll) u32 vclk_per, u8 bpp, union aty_pll *pll)
{ {
u32 tempA, tempB, fOut, longMHz100, diff, preDiff; u32 tempA, tempB, fOut, longMHz100, diff, preDiff;
u32 mhz100; /* in 0.01 MHz */ u32 mhz100; /* in 0.01 MHz */
u32 program_bits; u32 program_bits;
/* u32 post_divider; */ /* u32 post_divider; */
u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq; u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
u16 m, n, k=0, save_m, save_n, twoToKth; u16 m, n, k = 0, save_m, save_n, twoToKth;
/* Calculate the programming word */ /* Calculate the programming word */
mhz100 = 100000000 / vclk_per; mhz100 = 100000000 / vclk_per;
mach64MinFreq = MIN_FREQ_2595; mach64MinFreq = MIN_FREQ_2595;
mach64MaxFreq = MAX_FREQ_2595; mach64MaxFreq = MAX_FREQ_2595;
mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */ mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */
save_m = 0; save_m = 0;
save_n = 0; save_n = 0;
/* Calculate program word */ /* Calculate program word */
if (mhz100 == 0) if (mhz100 == 0)
program_bits = 0xE0; program_bits = 0xE0;
else else {
{ if (mhz100 < mach64MinFreq)
if (mhz100 < mach64MinFreq) mhz100 = mach64MinFreq;
mhz100 = mach64MinFreq; if (mhz100 > mach64MaxFreq)
if (mhz100 > mach64MaxFreq) mhz100 = mach64MaxFreq;
mhz100 = mach64MaxFreq;
longMHz100 = mhz100 * 256 / 100; /* 8 bit scale this */
longMHz100 = mhz100 * 256 / 100; /* 8 bit scale this */
while (mhz100 < (mach64MinFreq << 3)) {
while (mhz100 < (mach64MinFreq << 3)) mhz100 <<= 1;
{ k++;
mhz100 <<= 1; }
k++;
}
twoToKth = 1 << k; twoToKth = 1 << k;
diff = 0; diff = 0;
preDiff = 0xFFFFFFFF; preDiff = 0xFFFFFFFF;
for (m = MIN_M; m <= MAX_M; m++) for (m = MIN_M; m <= MAX_M; m++) {
{ for (n = MIN_N; n <= MAX_N; n++) {
for (n = MIN_N; n <= MAX_N; n++) tempA = (14.31818 * 65536);
{ tempA *= (n + 8); /* 43..256 */
tempA = (14.31818 * 65536); tempB = twoToKth * 256;
tempA *= (n + 8); /* 43..256 */ tempB *= (m + 2); /* 4..32 */
tempB = twoToKth * 256; fOut = tempA / tempB; /* 8 bit scale */
tempB *= (m + 2); /* 4..32 */
fOut = tempA / tempB; /* 8 bit scale */ if (longMHz100 > fOut)
diff = longMHz100 - fOut;
if (longMHz100 > fOut) else
diff = longMHz100 - fOut; diff = fOut - longMHz100;
else
diff = fOut - longMHz100; if (diff < preDiff) {
save_m = m;
if (diff < preDiff) save_n = n;
{ preDiff = diff;
save_m = m; }
save_n = n; }
preDiff = diff;
} }
}
}
program_bits = (k << 6) + (save_m) + (save_n << 8); program_bits = (k << 6) + (save_m) + (save_n << 8);
} }
pll->ics2595.program_bits = program_bits; pll->ics2595.program_bits = program_bits;
pll->ics2595.locationAddr = 0; pll->ics2595.locationAddr = 0;
pll->ics2595.post_divider = 0; pll->ics2595.post_divider = 0;
pll->ics2595.period_in_ps = vclk_per; pll->ics2595.period_in_ps = vclk_per;
return 0; return 0;
} }
static u32 aty_pll_8398_to_var(const struct fb_info_aty *info, static u32 aty_pll_8398_to_var(const struct fb_info *info,
const union aty_pll *pll) const union aty_pll *pll)
{ {
return(pll->ics2595.period_in_ps); /* default for now */ return (pll->ics2595.period_in_ps); /* default for now */
} }
static void aty_set_pll_8398(const struct fb_info_aty *info, static void aty_set_pll_8398(const struct fb_info *info,
const union aty_pll *pll) const union aty_pll *pll)
{ {
u32 program_bits; struct atyfb_par *par = (struct atyfb_par *) info->par;
u32 locationAddr; u32 program_bits;
u32 locationAddr;
char old_crtc_ext_disp; char old_crtc_ext_disp;
char tmp; char tmp;
old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info); old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), aty_st_8(CRTC_GEN_CNTL + 3,
info); old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par);
program_bits = pll->ics2595.program_bits; program_bits = pll->ics2595.program_bits;
locationAddr = pll->ics2595.locationAddr; locationAddr = pll->ics2595.locationAddr;
/* Program clock */ /* Program clock */
tmp = aty_ld_8(DAC_CNTL, info); tmp = aty_ld_8(DAC_CNTL, par);
aty_st_8(DAC_CNTL, tmp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, info); aty_st_8(DAC_CNTL, tmp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, par);
aty_st_8(DAC_REGS, locationAddr, info); aty_st_8(DAC_REGS, locationAddr, par);
aty_st_8(DAC_REGS+1, (program_bits & 0xff00) >> 8, info); aty_st_8(DAC_REGS + 1, (program_bits & 0xff00) >> 8, par);
aty_st_8(DAC_REGS+1, (program_bits & 0xff), info); aty_st_8(DAC_REGS + 1, (program_bits & 0xff), par);
tmp = aty_ld_8(DAC_CNTL, info); tmp = aty_ld_8(DAC_CNTL, par);
aty_st_8(DAC_CNTL, (tmp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3, info); aty_st_8(DAC_CNTL, (tmp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3,
par);
(void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */ (void) aty_ld_8(DAC_REGS, par); /* Clear DAC Counter */
aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info); aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par);
return; return;
} }
const struct aty_pll_ops aty_pll_ch8398 = { const struct aty_pll_ops aty_pll_ch8398 = {
var_to_pll: aty_var_to_pll_8398, var_to_pll:aty_var_to_pll_8398,
pll_to_var: aty_pll_8398_to_var, pll_to_var:aty_pll_8398_to_var,
set_pll: aty_set_pll_8398, set_pll:aty_set_pll_8398,
}; };
...@@ -714,143 +737,146 @@ const struct aty_pll_ops aty_pll_ch8398 = { ...@@ -714,143 +737,146 @@ const struct aty_pll_ops aty_pll_ch8398 = {
* AT&T 20C408 Clock Chip * AT&T 20C408 Clock Chip
*/ */
static int aty_var_to_pll_408(const struct fb_info_aty *info, u32 vclk_per, static int aty_var_to_pll_408(const struct fb_info *info, u32 vclk_per,
u8 bpp, union aty_pll *pll) u8 bpp, union aty_pll *pll)
{ {
u32 mhz100; /* in 0.01 MHz */ u32 mhz100; /* in 0.01 MHz */
u32 program_bits; u32 program_bits;
/* u32 post_divider; */ /* u32 post_divider; */
u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq; u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
u32 temp, tempB; u32 temp, tempB;
u16 remainder, preRemainder; u16 remainder, preRemainder;
short divider = 0, tempA; short divider = 0, tempA;
/* Calculate the programming word */ /* Calculate the programming word */
mhz100 = 100000000 / vclk_per; mhz100 = 100000000 / vclk_per;
mach64MinFreq = MIN_FREQ_2595; mach64MinFreq = MIN_FREQ_2595;
mach64MaxFreq = MAX_FREQ_2595; mach64MaxFreq = MAX_FREQ_2595;
mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */ mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */
/* Calculate program word */ /* Calculate program word */
if (mhz100 == 0) if (mhz100 == 0)
program_bits = 0xFF; program_bits = 0xFF;
else { else {
if (mhz100 < mach64MinFreq) if (mhz100 < mach64MinFreq)
mhz100 = mach64MinFreq; mhz100 = mach64MinFreq;
if (mhz100 > mach64MaxFreq) if (mhz100 > mach64MaxFreq)
mhz100 = mach64MaxFreq; mhz100 = mach64MaxFreq;
while (mhz100 < (mach64MinFreq << 3)) { while (mhz100 < (mach64MinFreq << 3)) {
mhz100 <<= 1; mhz100 <<= 1;
divider += 0x40; divider += 0x40;
}
temp = (unsigned int) mhz100;
temp = (unsigned int) (temp * (MIN_N_408 + 2));
temp -= ((short) (mach64RefFreq << 1));
tempA = MIN_N_408;
preRemainder = 0xFFFF;
do {
tempB = temp;
remainder = tempB % mach64RefFreq;
tempB = tempB / mach64RefFreq;
if (((tempB & 0xFFFF) <= 255)
&& (remainder <= preRemainder)) {
preRemainder = remainder;
divider &= ~0x3f;
divider |= tempA;
divider =
(divider & 0x00FF) +
((tempB & 0xFF) << 8);
}
temp += mhz100;
tempA++;
} while (tempA <= 32);
program_bits = divider;
} }
temp = (unsigned int)mhz100; pll->ics2595.program_bits = program_bits;
temp = (unsigned int)(temp * (MIN_N_408 + 2)); pll->ics2595.locationAddr = 0;
temp -= ((short)(mach64RefFreq << 1)); pll->ics2595.post_divider = divider; /* fuer nix */
pll->ics2595.period_in_ps = vclk_per;
tempA = MIN_N_408;
preRemainder = 0xFFFF; return 0;
do {
tempB = temp;
remainder = tempB % mach64RefFreq;
tempB = tempB / mach64RefFreq;
if (((tempB & 0xFFFF) <= 255) && (remainder <= preRemainder)) {
preRemainder = remainder;
divider &= ~0x3f;
divider |= tempA;
divider = (divider & 0x00FF) + ((tempB & 0xFF) << 8);
}
temp += mhz100;
tempA++;
} while(tempA <= 32);
program_bits = divider;
}
pll->ics2595.program_bits = program_bits;
pll->ics2595.locationAddr = 0;
pll->ics2595.post_divider = divider; /* fuer nix */
pll->ics2595.period_in_ps = vclk_per;
return 0;
} }
static u32 aty_pll_408_to_var(const struct fb_info_aty *info, static u32 aty_pll_408_to_var(const struct fb_info *info,
const union aty_pll *pll) const union aty_pll *pll)
{ {
return(pll->ics2595.period_in_ps); /* default for now */ return (pll->ics2595.period_in_ps); /* default for now */
} }
static void aty_set_pll_408(const struct fb_info_aty *info, static void aty_set_pll_408(const struct fb_info *info,
const union aty_pll *pll) const union aty_pll *pll)
{ {
u32 program_bits; struct atyfb_par *par = (struct atyfb_par *) info->par;
u32 locationAddr; u32 program_bits;
u32 locationAddr;
u8 tmpA, tmpB, tmpC; u8 tmpA, tmpB, tmpC;
char old_crtc_ext_disp; char old_crtc_ext_disp;
old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info); old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), aty_st_8(CRTC_GEN_CNTL + 3,
info); old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par);
program_bits = pll->ics2595.program_bits; program_bits = pll->ics2595.program_bits;
locationAddr = pll->ics2595.locationAddr; locationAddr = pll->ics2595.locationAddr;
/* Program clock */ /* Program clock */
aty_dac_waste4(info); aty_dac_waste4(par);
tmpB = aty_ld_8(DAC_REGS + 2, info) | 1; tmpB = aty_ld_8(DAC_REGS + 2, par) | 1;
aty_dac_waste4(info); aty_dac_waste4(par);
aty_st_8(DAC_REGS + 2, tmpB, info); aty_st_8(DAC_REGS + 2, tmpB, par);
tmpA = tmpB; tmpA = tmpB;
tmpC = tmpA; tmpC = tmpA;
tmpA |= 8; tmpA |= 8;
tmpB = 1; tmpB = 1;
aty_st_8(DAC_REGS, tmpB, info); aty_st_8(DAC_REGS, tmpB, par);
aty_st_8(DAC_REGS + 2, tmpA, info); aty_st_8(DAC_REGS + 2, tmpA, par);
udelay(400); /* delay for 400 us */ udelay(400); /* delay for 400 us */
locationAddr = (locationAddr << 2) + 0x40; locationAddr = (locationAddr << 2) + 0x40;
tmpB = locationAddr; tmpB = locationAddr;
tmpA = program_bits >> 8; tmpA = program_bits >> 8;
aty_st_8(DAC_REGS, tmpB, info); aty_st_8(DAC_REGS, tmpB, par);
aty_st_8(DAC_REGS + 2, tmpA, info); aty_st_8(DAC_REGS + 2, tmpA, par);
tmpB = locationAddr + 1; tmpB = locationAddr + 1;
tmpA = (u8)program_bits; tmpA = (u8) program_bits;
aty_st_8(DAC_REGS, tmpB, info); aty_st_8(DAC_REGS, tmpB, par);
aty_st_8(DAC_REGS + 2, tmpA, info); aty_st_8(DAC_REGS + 2, tmpA, par);
tmpB = locationAddr + 2; tmpB = locationAddr + 2;
tmpA = 0x77; tmpA = 0x77;
aty_st_8(DAC_REGS, tmpB, info); aty_st_8(DAC_REGS, tmpB, par);
aty_st_8(DAC_REGS + 2, tmpA, info); aty_st_8(DAC_REGS + 2, tmpA, par);
udelay(400); /* delay for 400 us */ udelay(400); /* delay for 400 us */
tmpA = tmpC & (~(1 | 8)); tmpA = tmpC & (~(1 | 8));
tmpB = 1; tmpB = 1;
aty_st_8(DAC_REGS, tmpB, info); aty_st_8(DAC_REGS, tmpB, par);
aty_st_8(DAC_REGS + 2, tmpA, info); aty_st_8(DAC_REGS + 2, tmpA, par);
(void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */ (void) aty_ld_8(DAC_REGS, par); /* Clear DAC Counter */
aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info); aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par);
return;
return;
} }
const struct aty_pll_ops aty_pll_att20c408 = { const struct aty_pll_ops aty_pll_att20c408 = {
var_to_pll: aty_var_to_pll_408, var_to_pll:aty_var_to_pll_408,
pll_to_var: aty_pll_408_to_var, pll_to_var:aty_pll_408_to_var,
set_pll: aty_set_pll_408, set_pll:aty_set_pll_408,
}; };
...@@ -858,30 +884,31 @@ const struct aty_pll_ops aty_pll_att20c408 = { ...@@ -858,30 +884,31 @@ const struct aty_pll_ops aty_pll_att20c408 = {
* Unsupported DAC and Clock Chip * Unsupported DAC and Clock Chip
*/ */
static int aty_set_dac_unsupported(const struct fb_info_aty *info, static int aty_set_dac_unsupported(const struct fb_info *info,
const union aty_pll *pll, u32 bpp, const union aty_pll *pll, u32 bpp,
u32 accel) u32 accel)
{ {
aty_st_le32(BUS_CNTL, 0x890e20f1, info); struct atyfb_par *par = (struct atyfb_par *) info->par;
aty_st_le32(DAC_CNTL, 0x47052100, info);
/* new in 2.2.3p1 from Geert. ???????? */ aty_st_le32(BUS_CNTL, 0x890e20f1, par);
aty_st_le32(BUS_CNTL, 0x590e10ff, info); aty_st_le32(DAC_CNTL, 0x47052100, par);
aty_st_le32(DAC_CNTL, 0x47012100, info); /* new in 2.2.3p1 from Geert. ???????? */
return 0; aty_st_le32(BUS_CNTL, 0x590e10ff, par);
aty_st_le32(DAC_CNTL, 0x47012100, par);
return 0;
} }
static int dummy(void) static int dummy(void)
{ {
return 0; return 0;
} }
const struct aty_dac_ops aty_dac_unsupported = { const struct aty_dac_ops aty_dac_unsupported = {
set_dac: aty_set_dac_unsupported, set_dac:aty_set_dac_unsupported,
}; };
const struct aty_pll_ops aty_pll_unsupported = { const struct aty_pll_ops aty_pll_unsupported = {
var_to_pll: (void *)dummy, var_to_pll:(void *) dummy,
pll_to_var: (void *)dummy, pll_to_var:(void *) dummy,
set_pll: (void *)dummy, set_pll:(void *) dummy,
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment