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