Commit 03a0590e authored by James Simmons's avatar James Simmons

More changes to port over teh ATI 128 driver to new api. Optimizations for...

More changes to port over teh ATI 128 driver to new api. Optimizations for fbgen and small bug fix for gen_update_var 
parent 6f8d8d4b
......@@ -109,35 +109,36 @@ static struct fb_var_screeninfo default_var = {
1024, 768, 1024, 768, 0, 0, 8, 0,
{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
0, 0, -1, -1, 0, 12699, 160, 32, 28, 1, 96, 3,
FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
FB_VMODE_NONINTERLACED
};
#endif /* CONFIG_PPC */
/* default modedb mode */
/* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
static struct fb_videomode defaultmode __initdata = {
refresh: 60,
xres: 640,
yres: 480,
pixclock: 39722,
left_margin: 48,
right_margin: 16,
upper_margin: 33,
lower_margin: 10,
hsync_len: 96,
vsync_len: 2,
sync: 0,
vmode: FB_VMODE_NONINTERLACED
refresh:60,
xres:640,
yres:480,
pixclock:39722,
left_margin:48,
right_margin:16,
upper_margin:33,
lower_margin:10,
hsync_len:96,
vsync_len:2,
sync:0,
vmode:FB_VMODE_NONINTERLACED
};
static struct fb_fix_screeninfo aty128fb_fix __initdata = {
id: "ATY Rage128",
type: FB_TYPE_PACKED_PIXELS,
visual: FB_VISUAL_PSEUDOCOLOR,
xpanstep: 8,
ypanstep: 1,
mmio_len: 0x1fff,
accel: FB_ACCEL_ATI_RAGE128
id:"ATY Rage128",
type:FB_TYPE_PACKED_PIXELS,
visual:FB_VISUAL_PSEUDOCOLOR,
xpanstep:8,
ypanstep:1,
mmio_len:0x1fff,
accel:FB_ACCEL_ATI_RAGE128
};
/* struct to hold chip description information */
......@@ -155,19 +156,21 @@ enum {
};
/* supported Rage128 chipsets */
static struct aty128_chip_info aty128_pci_probe_list[] __initdata =
{
static struct aty128_chip_info aty128_pci_probe_list[] __initdata = {
{"Rage128 RE (PCI)", PCI_DEVICE_ID_ATI_RAGE128_RE, rage_128},
{"Rage128 RF (AGP)", PCI_DEVICE_ID_ATI_RAGE128_RF, rage_128},
{"Rage128 RK (PCI)", PCI_DEVICE_ID_ATI_RAGE128_RK, rage_128},
{"Rage128 RL (AGP)", PCI_DEVICE_ID_ATI_RAGE128_RL, rage_128},
{"Rage128 Pro PF (AGP)", PCI_DEVICE_ID_ATI_RAGE128_PF, rage_128_pro},
{"Rage128 Pro PR (PCI)", PCI_DEVICE_ID_ATI_RAGE128_PR, rage_128_pro},
{"Rage128 Pro TR (AGP)", PCI_DEVICE_ID_ATI_RAGE128_U3, rage_128_pro},
{"Rage128 Pro PF (AGP)", PCI_DEVICE_ID_ATI_RAGE128_PF,
rage_128_pro},
{"Rage128 Pro PR (PCI)", PCI_DEVICE_ID_ATI_RAGE128_PR,
rage_128_pro},
{"Rage128 Pro TR (AGP)", PCI_DEVICE_ID_ATI_RAGE128_U3,
rage_128_pro},
{"Rage Mobility M3 (PCI)", PCI_DEVICE_ID_ATI_RAGE128_LE, rage_M3},
{"Rage Mobility M3 (AGP)", PCI_DEVICE_ID_ATI_RAGE128_LF, rage_M3},
{NULL, 0, rage_128}
};
};
/* packed BIOS settings */
#ifndef CONFIG_PPC
......@@ -224,7 +227,6 @@ static const struct aty128_meminfo ddr_sgram =
static char fontname[40] __initdata = { 0 };
static int noaccel __initdata = 0;
#ifdef MODULE
static char *font __initdata = NULL;
static char *mode __initdata = NULL;
......@@ -263,7 +265,7 @@ struct aty128_crtc {
u32 pitch;
u32 offset, offset_cntl;
u32 xoffset, yoffset;
u32 vxres, vyres;
u32 vyres;
u32 bpp;
};
......@@ -283,7 +285,9 @@ struct aty128fb_par {
struct aty128_crtc crtc;
struct aty128_pll pll;
struct aty128_ddafifo fifo_reg;
u32 accel_flags;
int blitter_may_be_busy;
int fifo_slots; /* free slots in FIFO (64 max) */
int chip_gen;
#ifdef CONFIG_MTRR
struct { int vram; int vram_valid; } mtrr;
#endif
......@@ -294,10 +298,7 @@ struct fb_info_aty128 {
struct fb_info_aty128 *next;
struct aty128_constants constants; /* PLL and others */
void *regbase; /* remapped mmio */
int chip_gen;
const struct aty128_meminfo *mem; /* onboard mem info */
int blitter_may_be_busy;
int fifo_slots; /* free slots in FIFO (64 max) */
};
static struct fb_info_aty128 *board_list = NULL;
......@@ -307,38 +308,25 @@ static struct fb_info_aty128 *board_list = NULL;
/*
* Interface used by the world
*/
int aty128fb_init(void);
int aty128fb_setup(char *options);
static int aty128fb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info);
static int aty128fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int aty128fb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info);
static int aty128fb_setcolreg(u_int regno, u_int red, u_int green,
u_int blue, u_int transp,
struct fb_info *info);
static int aty128fb_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *fb);
static int aty128fb_blank(int blank, struct fb_info *fb);
static int aty128fb_rasterimg(struct fb_info *info, int start);
/*
* Interface to the low level console driver
*/
int aty128fb_init(void);
static int aty128fbcon_switch(int con, struct fb_info *fb);
/*
* Internal routines
*/
static void aty128_encode_fix(struct fb_fix_screeninfo *fix,
struct aty128fb_par *par,
const struct fb_info_aty128 *info);
static void aty128_set_dispsw(struct display *disp,
struct fb_info_aty128 *info, int bpp, int accel);
static void aty128_set_disp(struct display *disp,
struct fb_info *info);
static int aty128_encode_var(struct fb_var_screeninfo *var,
const struct aty128fb_par *par,
const struct fb_info_aty128 *info);
......@@ -348,7 +336,9 @@ static int aty128_decode_var(struct fb_var_screeninfo *var,
static int aty128_pci_register(struct pci_dev *pdev,
const struct aty128_chip_info *aci);
static struct fb_info_aty128 *aty128_board_list_add(struct fb_info_aty128
*board_list, struct fb_info_aty128 *new_node);
*board_list,
struct fb_info_aty128
*new_node);
#if !defined(CONFIG_PPC) && !defined(__sparc__)
static void __init aty128_get_pllinfo(struct fb_info_aty128 *info,
char *bios_seg);
......@@ -399,8 +389,8 @@ static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p,
static struct fb_ops aty128fb_ops = {
owner: THIS_MODULE,
fb_get_fix: aty128fb_get_fix,
fb_get_var: aty128fb_get_var,
fb_get_fix: gen_get_fix,
fb_get_var: gen_get_var,
fb_set_var: aty128fb_set_var,
fb_get_cmap: gen_get_cmap,
fb_set_cmap: gen_set_cmap,
......@@ -411,8 +401,8 @@ static struct fb_ops aty128fb_ops = {
};
#ifdef CONFIG_PMAC_BACKLIGHT
static int aty128_set_backlight_enable(int on, int level, void* data);
static int aty128_set_backlight_level(int level, void* data);
static int aty128_set_backlight_enable(int on, int level, void *data);
static int aty128_set_backlight_level(int level, void *data);
static struct backlight_controller aty128_backlight_controller = {
aty128_set_backlight_enable,
......@@ -432,9 +422,11 @@ _aty_ld_le32(volatile unsigned int regindex,
u32 val;
#if defined(__powerpc__)
asm("lwbrx %0,%1,%2;eieio" : "=r"(val) : "b"(regindex), "r"(info->regbase));
asm("lwbrx %0,%1,%2;eieio": "=r"(val):"b"(regindex),
"r"(info->
regbase));
#else
val = readl (info->regbase + regindex);
val = readl(info->regbase + regindex);
#endif
return val;
......@@ -445,23 +437,22 @@ _aty_st_le32(volatile unsigned int regindex, u32 val,
const struct fb_info_aty128 *info)
{
#if defined(__powerpc__)
asm("stwbrx %0,%1,%2;eieio" : : "r"(val), "b"(regindex),
"r"(info->regbase) : "memory");
asm("stwbrx %0,%1,%2;eieio": : "r"(val), "b"(regindex), "r"(info->regbase):"memory");
#else
writel (val, info->regbase + regindex);
writel(val, info->regbase + regindex);
#endif
}
static inline u8
_aty_ld_8(unsigned int regindex, const struct fb_info_aty128 *info)
{
return readb (info->regbase + regindex);
return readb(info->regbase + regindex);
}
static inline void
_aty_st_8(unsigned int regindex, u8 val, const struct fb_info_aty128 *info)
{
writeb (val, info->regbase + regindex);
writeb(val, info->regbase + regindex);
}
#define aty_ld_le32(regindex) _aty_ld_le32(regindex, info)
......@@ -478,8 +469,7 @@ _aty_st_8(unsigned int regindex, u8 val, const struct fb_info_aty128 *info)
static u32
_aty_ld_pll(unsigned int pll_index,
const struct fb_info_aty128 *info)
_aty_ld_pll(unsigned int pll_index, const struct fb_info_aty128 *info)
{
aty_st_8(CLOCK_CNTL_INDEX, pll_index & 0x1F);
return aty_ld_le32(CLOCK_CNTL_DATA);
......@@ -496,17 +486,15 @@ _aty_st_pll(unsigned int pll_index, u32 val,
/* return true when the PLL has completed an atomic update */
static int
aty_pll_readupdate(const struct fb_info_aty128 *info)
static int aty_pll_readupdate(const struct fb_info_aty128 *info)
{
return !(aty_ld_pll(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R);
}
static void
aty_pll_wait_readupdate(const struct fb_info_aty128 *info)
static void aty_pll_wait_readupdate(const struct fb_info_aty128 *info)
{
unsigned long timeout = jiffies + HZ/100; // should be more than enough
unsigned long timeout = jiffies + HZ / 100; // should be more than enough
int reset = 1;
while (time_before(jiffies, timeout))
......@@ -521,8 +509,7 @@ aty_pll_wait_readupdate(const struct fb_info_aty128 *info)
/* tell PLL to update */
static void
aty_pll_writeupdate(const struct fb_info_aty128 *info)
static void aty_pll_writeupdate(const struct fb_info_aty128 *info)
{
aty_pll_wait_readupdate(info);
......@@ -532,8 +519,7 @@ aty_pll_writeupdate(const struct fb_info_aty128 *info)
/* write to the scratch register to test r/w functionality */
static int __init
register_test(const struct fb_info_aty128 *info)
static int __init register_test(const struct fb_info_aty128 *info)
{
u32 val;
int flag = 0;
......@@ -556,15 +542,15 @@ register_test(const struct fb_info_aty128 *info)
/*
* Accelerator engine functions
*/
static void
do_wait_for_fifo(u16 entries, struct fb_info_aty128 *info)
static void do_wait_for_fifo(u16 entries, struct fb_info_aty128 *info)
{
struct aty128fb_par *par = (struct aty128fb_par *) info->fb_info.par;
int i;
for (;;) {
for (i = 0; i < 2000000; i++) {
info->fifo_slots = aty_ld_le32(GUI_STAT) & 0x0fff;
if (info->fifo_slots >= entries)
par->fifo_slots = aty_ld_le32(GUI_STAT) & 0x0fff;
if (par->fifo_slots >= entries)
return;
}
aty128_reset_engine(info);
......@@ -572,9 +558,9 @@ do_wait_for_fifo(u16 entries, struct fb_info_aty128 *info)
}
static void
wait_for_idle(struct fb_info_aty128 *info)
static void wait_for_idle(struct fb_info_aty128 *info)
{
struct aty128fb_par *par = (struct aty128fb_par *) info->fb_info.par;
int i;
do_wait_for_fifo(64, info);
......@@ -583,7 +569,7 @@ wait_for_idle(struct fb_info_aty128 *info)
for (i = 0; i < 2000000; i++) {
if (!(aty_ld_le32(GUI_STAT) & (1 << 31))) {
aty128_flush_pixel_cache(info);
info->blitter_may_be_busy = 0;
par->blitter_may_be_busy = 0;
return;
}
}
......@@ -592,17 +578,17 @@ wait_for_idle(struct fb_info_aty128 *info)
}
static void
wait_for_fifo(u16 entries, struct fb_info_aty128 *info)
static void wait_for_fifo(u16 entries, struct fb_info_aty128 *info)
{
if (info->fifo_slots < entries)
struct aty128fb_par *par = (struct aty128fb_par *) info->fb_info.par;
if (par->fifo_slots < entries)
do_wait_for_fifo(64, info);
info->fifo_slots -= entries;
par->fifo_slots -= entries;
}
static void
aty128_flush_pixel_cache(const struct fb_info_aty128 *info)
static void aty128_flush_pixel_cache(const struct fb_info_aty128 *info)
{
int i;
u32 tmp;
......@@ -618,8 +604,7 @@ aty128_flush_pixel_cache(const struct fb_info_aty128 *info)
}
static void
aty128_reset_engine(const struct fb_info_aty128 *info)
static void aty128_reset_engine(const struct fb_info_aty128 *info)
{
u32 gen_reset_cntl, clock_cntl_index, mclk_cntl;
......@@ -691,8 +676,7 @@ aty128_init_engine(const struct aty128fb_par *par,
GMC_DP_SRC_RECT |
GMC_3D_FCN_EN_CLR |
GMC_DST_CLR_CMP_FCN_CLEAR |
GMC_AUX_CLIP_CLEAR |
GMC_WRITE_MASK_SET);
GMC_AUX_CLIP_CLEAR | GMC_WRITE_MASK_SET);
wait_for_fifo(8, info);
/* clear the line drawing registers */
......@@ -717,8 +701,7 @@ aty128_init_engine(const struct aty128fb_par *par,
/* convert bpp values to their register representation */
static u32
bpp_to_depth(u32 bpp)
static u32 bpp_to_depth(u32 bpp)
{
if (bpp <= 8)
return DST_8BPP;
......@@ -760,7 +743,7 @@ aty128_set_crtc(const struct aty128_crtc *crtc,
static int
aty128_var_to_crtc(const struct fb_var_screeninfo *var,
aty128_var_to_crtc(struct fb_var_screeninfo *var,
struct aty128_crtc *crtc,
const struct fb_info_aty128 *info)
{
......@@ -817,7 +800,7 @@ aty128_var_to_crtc(const struct fb_var_screeninfo *var,
bytpp = mode_bytpp[depth];
/* make sure there is enough video ram for the mode */
if ((u32)(vxres * vyres * bytpp) > info->fb_info.fix.smem_len) {
if ((u32) (vxres * vyres * bytpp) > info->fb_info.fix.smem_len) {
printk(KERN_ERR "aty128fb: Not enough memory for mode\n");
return -EINVAL;
}
......@@ -860,10 +843,11 @@ aty128_var_to_crtc(const struct fb_var_screeninfo *var,
crtc->h_total = h_total | (h_disp << 16);
crtc->v_total = v_total | (v_disp << 16);
crtc->h_sync_strt_wid = hsync_strt_pix[bytpp] | (h_sync_strt << 3) |
(h_sync_wid << 16) | (h_sync_pol << 23);
crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid << 16) |
(v_sync_pol << 23);
crtc->h_sync_strt_wid =
hsync_strt_pix[bytpp] | (h_sync_strt << 3) | (h_sync_wid << 16)
| (h_sync_pol << 23);
crtc->v_sync_strt_wid =
v_sync_strt | (v_sync_wid << 16) | (v_sync_pol << 23);
crtc->pitch = vxres >> 3;
......@@ -874,7 +858,7 @@ aty128_var_to_crtc(const struct fb_var_screeninfo *var,
else
crtc->offset_cntl = 0;
crtc->vxres = vxres;
var->xres_virtual = vxres;
crtc->vyres = vyres;
crtc->xoffset = xoffset;
crtc->yoffset = yoffset;
......@@ -884,8 +868,7 @@ aty128_var_to_crtc(const struct fb_var_screeninfo *var,
}
static int
aty128_bpp_to_var(int pix_width, struct fb_var_screeninfo *var)
static int aty128_bpp_to_var(int pix_width, struct fb_var_screeninfo *var)
{
/* fill in pixel info */
......@@ -949,7 +932,8 @@ aty128_crtc_to_var(const struct aty128_crtc *crtc,
struct fb_var_screeninfo *var)
{
u32 xres, yres, left, right, upper, lower, hslen, vslen, sync;
u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid,
h_sync_pol;
u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
u32 pix_width;
......@@ -985,7 +969,6 @@ aty128_crtc_to_var(const struct aty128_crtc *crtc,
var->xres = xres;
var->yres = yres;
var->xres_virtual = crtc->vxres;
var->yres_virtual = crtc->vyres;
var->xoffset = crtc->xoffset;
var->yoffset = crtc->yoffset;
......@@ -1010,11 +993,13 @@ aty128_set_pll(struct aty128_pll *pll, const struct fb_info_aty128 *info)
{ 2, 0, 1, 4, 2, 2, 6, 2, 3, 2, 2, 2, 7 };
/* select PPLL_DIV_3 */
aty_st_le32(CLOCK_CNTL_INDEX, aty_ld_le32(CLOCK_CNTL_INDEX) | (3 << 8));
aty_st_le32(CLOCK_CNTL_INDEX,
aty_ld_le32(CLOCK_CNTL_INDEX) | (3 << 8));
/* reset PLL */
aty_st_pll(PPLL_CNTL,
aty_ld_pll(PPLL_CNTL) | PPLL_RESET | PPLL_ATOMIC_UPDATE_EN);
aty_ld_pll(PPLL_CNTL) | PPLL_RESET |
PPLL_ATOMIC_UPDATE_EN);
/* write the reference divider */
aty_pll_wait_readupdate(info);
......@@ -1046,7 +1031,7 @@ aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
const struct fb_info_aty128 *info)
{
const struct aty128_constants c = info->constants;
unsigned char post_dividers[] = {1,2,4,8,3,6,12};
unsigned char post_dividers[] = { 1, 2, 4, 8, 3, 6, 12 };
u32 output_freq;
u32 vclk; /* in .01 MHz */
int i;
......@@ -1058,7 +1043,7 @@ aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
if (vclk > c.ppll_max)
vclk = c.ppll_max;
if (vclk * 12 < c.ppll_min)
vclk = c.ppll_min/12;
vclk = c.ppll_min / 12;
/* now, find an acceptable divider */
for (i = 0; i < sizeof(post_dividers); i++) {
......@@ -1085,7 +1070,8 @@ aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
static int
aty128_pll_to_var(const struct aty128_pll *pll, struct fb_var_screeninfo *var,
aty128_pll_to_var(const struct aty128_pll *pll,
struct fb_var_screeninfo *var,
const struct fb_info_aty128 *info)
{
var->pixclock = 100000000 / pll->vclk;
......@@ -1106,8 +1092,7 @@ aty128_set_fifo(const struct aty128_ddafifo *dsp,
static int
aty128_ddafifo(struct aty128_ddafifo *dsp,
const struct aty128_pll *pll,
u32 bpp,
const struct fb_info_aty128 *info)
u32 bpp, const struct fb_info_aty128 *info)
{
const struct aty128_meminfo *m = info->mem;
u32 xclk = info->constants.xclk;
......@@ -1126,11 +1111,7 @@ aty128_ddafifo(struct aty128_ddafifo *dsp,
ron = 4 * m->MB +
3 * ((m->Trcd - 2 > 0) ? m->Trcd - 2 : 0) +
2 * m->Trp +
m->Twr +
m->CL +
m->Tr2w +
x;
2 * m->Trp + m->Twr + m->CL + m->Tr2w + x;
DBG("x %x\n", x);
......@@ -1165,15 +1146,13 @@ aty128_ddafifo(struct aty128_ddafifo *dsp,
/*
* This actually sets the video mode.
*/
static void
aty128_set_par(struct aty128fb_par *par,
struct fb_info_aty128 *info)
static int
aty128fb_set_par(struct fb_info_aty128 *info)
{
struct aty128fb_par *par = (struct aty128fb_par *) info->fb_info.par;
u32 config;
info->fb_info.par = par;
if (info->blitter_may_be_busy)
if (par->blitter_may_be_busy)
wait_for_idle(info);
/* clear all registers that may interfere with mode setting */
......@@ -1208,16 +1187,19 @@ aty128_set_par(struct aty128fb_par *par,
aty_st_le32(CONFIG_CNTL, config);
aty_st_8(CRTC_EXT_CNTL + 1, 0); /* turn the video back on */
if (par->accel_flags & FB_ACCELF_TEXT)
if (info->fb_info.var.accel_flags & FB_ACCELF_TEXT)
aty128_init_engine(par, info);
#if defined(CONFIG_BOOTX_TEXT)
btext_update_display(info->fb_info.fix.smem_start,
(((par->crtc.h_total>>16) & 0xff)+1)*8,
((par->crtc.v_total>>16) & 0x7ff)+1,
(((par->crtc.h_total >> 16) & 0xff) + 1) * 8,
((par->crtc.v_total >> 16) & 0x7ff) + 1,
par->crtc.bpp,
par->crtc.vxres*par->crtc.bpp/8);
par->crtc.vxres * par->crtc.bpp / 8);
#endif /* CONFIG_BOOTX_TEXT */
info->fb_info.fix.line_length = (info->fb_info.var.xres_virtual * info->fb_info.var.bits_per_pixel) >> 3;
info->fb_info.fix.visual = info->fb_info.var.bits_per_pixel <= 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
return 0;
}
/*
......@@ -1236,14 +1218,10 @@ aty128_decode_var(struct fb_var_screeninfo *var, struct aty128fb_par *par,
if ((err = aty128_var_to_pll(var->pixclock, &par->pll, info)))
return err;
if ((err = aty128_ddafifo(&par->fifo_reg, &par->pll, par->crtc.bpp, info)))
if ((err =
aty128_ddafifo(&par->fifo_reg, &par->pll, par->crtc.bpp,
info)))
return err;
if (var->accel_flags & FB_ACCELF_TEXT)
par->accel_flags = FB_ACCELF_TEXT;
else
par->accel_flags = 0;
return 0;
}
......@@ -1260,56 +1238,12 @@ aty128_encode_var(struct fb_var_screeninfo *var,
if ((err = aty128_pll_to_var(&par->pll, var, info)))
return err;
var->red.msb_right = 0;
var->green.msb_right = 0;
var->blue.msb_right = 0;
var->transp.msb_right = 0;
var->nonstd = 0;
var->activate = 0;
var->height = -1;
var->width = -1;
var->accel_flags = par->accel_flags;
return 0;
}
/*
* Get the User Defined Part of the Display
*/
static int
aty128fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb)
aty128fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
const struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
struct aty128fb_par *par = (struct aty128fb_par *) fb->par;
if (con == -1)
aty128_encode_var(var, par, info);
else
*var = fb_display[con].var;
return 0;
}
/*
* Set the User Defined Part of the Display
*/
static int
aty128fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb)
{
struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
struct aty128fb_par par;
struct display *display;
int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
int accel, err;
display = (con >= 0) ? &fb_display[con] : fb->disp;
/* basic (in)sanity checks */
if (!var->xres)
var->xres = 1;
......@@ -1337,89 +1271,108 @@ aty128fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb)
return -EINVAL;
}
if ((err = aty128_decode_var(var, &par, info)))
return err;
var->red.msb_right = 0;
var->green.msb_right = 0;
var->blue.msb_right = 0;
var->transp.msb_right = 0;
aty128_encode_var(var, &par, info);
var->nonstd = 0;
var->activate = 0;
if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
var->height = -1;
var->width = -1;
return 0;
}
/*
* Set the User Defined Part of the Display
*/
static int
aty128fb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *fb)
{
struct fb_info_aty128 *info = (struct fb_info_aty128 *) fb;
struct aty128fb_par *par = (struct aty128fb_par *) fb->par;
struct display *display;
int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
int err;
display = (con >= 0) ? &fb_display[con] : fb->disp;
aty128fb_check_var(var, fb);
oldxres = display->var.xres;
oldyres = display->var.yres;
oldvxres = display->var.xres_virtual;
oldvyres = display->var.yres_virtual;
oldbpp = display->var.bits_per_pixel;
oldaccel = display->var.accel_flags;
display->var = *var;
if ((err = aty128_decode_var(var, par, info)))
return err;
aty128_encode_var(var, par, info);
if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_TEST) {
oldxres = info->fb_info.var.xres;
oldyres = info->fb_info.var.yres;
oldvxres = info->fb_info.var.xres_virtual;
oldvyres = info->fb_info.var.yres_virtual;
oldbpp = info->fb_info.var.bits_per_pixel;
oldaccel = info->fb_info.var.accel_flags;
display->var = info->fb_info.var = *var;
if (oldxres != var->xres || oldyres != var->yres ||
oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) {
struct fb_fix_screeninfo fix;
aty128_encode_fix(&fix, &par, info);
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
display->ypanstep = fix.ypanstep;
display->ywrapstep = fix.ywrapstep;
display->line_length = fix.line_length;
oldvxres != var->xres_virtual || oldvyres != var->yres_virtual
|| oldbpp != var->bits_per_pixel
|| oldaccel != var->accel_flags) {
display->visual = info->fb_info.fix.visual;
display->type = info->fb_info.fix.type;
display->type_aux = info->fb_info.fix.type_aux;
display->ypanstep = info->fb_info.fix.ypanstep;
display->ywrapstep = info->fb_info.fix.ywrapstep;
display->line_length = info->fb_info.fix.line_length;
display->can_soft_blank = 1;
display->inverse = 0;
accel = var->accel_flags & FB_ACCELF_TEXT;
aty128_set_dispsw(display, info, par.crtc.bpp, accel);
if (accel)
display->scrollmode = SCROLL_YNOMOVE;
else
display->scrollmode = SCROLL_YREDRAW;
if (info->fb_info.changevar)
(*info->fb_info.changevar)(con);
aty128_set_disp(display, &info->fb_info);
}
if (!info->fb_info.display_fg || info->fb_info.display_fg->vc_num == con)
aty128_set_par(&par, info);
if (!info->fb_info.display_fg
|| info->fb_info.display_fg->vc_num == con)
aty128fb_set_par(info);
if (oldbpp != var->bits_per_pixel) {
if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
return err;
do_install_cmap(con, &info->fb_info);
}
}
return 0;
}
static void
aty128_set_dispsw(struct display *disp,
struct fb_info_aty128 *info, int bpp, int accel)
aty128_set_disp(struct display *disp,
struct fb_info *info)
{
switch (bpp) {
disp->scrollmode = SCROLL_YNOMOVE;
switch (info->var.bits_per_pixel) {
#ifdef FBCON_HAS_CFB8
case 8:
disp->dispsw = accel ? &fbcon_aty128_8 : &fbcon_cfb8;
disp->dispsw = &fbcon_aty128_8;
break;
#endif
#ifdef FBCON_HAS_CFB16
case 15:
case 16:
disp->dispsw = accel ? &fbcon_aty128_16 : &fbcon_cfb16;
disp->dispsw_data = info->fb_info.pseudo_palette;
disp->dispsw = &fbcon_aty128_16;
disp->dispsw_data = info->pseudo_palette;
break;
#endif
#ifdef FBCON_HAS_CFB24
case 24:
disp->dispsw = accel ? &fbcon_aty128_24 : &fbcon_cfb24;
disp->dispsw_data = info->fb_info.pseudo_palette;
disp->dispsw = &fbcon_aty128_24;
disp->dispsw_data = info->pseudo_palette;
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
disp->dispsw = accel ? &fbcon_aty128_32 : &fbcon_cfb32;
disp->dispsw_data = info->fb_info.pseudo_palette;
disp->dispsw = &fbcon_aty128_32;
disp->dispsw_data = info->pseudo_palette;
break;
#endif
default:
......@@ -1427,51 +1380,6 @@ aty128_set_dispsw(struct display *disp,
}
}
static void
aty128_encode_fix(struct fb_fix_screeninfo *fix,
struct aty128fb_par *par,
const struct fb_info_aty128 *info)
{
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id, info->fb_info.fix.id);
fix->smem_start = info->fb_info.fix.smem_start;
fix->mmio_start = info->fb_info.fix.mmio_start;
fix->smem_len = info->fb_info.fix.smem_len;
fix->mmio_len = info->fb_info.fix.mmio_len;
fix->type = info->fb_info.fix.type;
fix->type_aux = info->fb_info.fix.type_aux;
fix->line_length = (par->crtc.vxres * par->crtc.bpp) >> 3;
fix->visual = par->crtc.bpp <= 8 ? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_DIRECTCOLOR;
fix->ywrapstep = info->fb_info.fix.ywrapstep;
fix->xpanstep = info->fb_info.fix.xpanstep;
fix->ypanstep = info->fb_info.fix.ypanstep;
fix->accel = info->fb_info.fix.accel;
return;
}
/*
* Get the Fixed Part of the Display
*/
static int
aty128fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *fb)
{
const struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
struct aty128fb_par *par = (struct aty128fb_par *) fb->par;
aty128_decode_var(&fb_display[con].var, par, info);
aty128_encode_fix(fix, par, info);
return 0;
}
/*
* Pan or Wrap the Display
*
......@@ -1481,7 +1389,7 @@ static int
aty128fb_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *fb)
{
struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
struct fb_info_aty128 *info = (struct fb_info_aty128 *) fb;
struct aty128fb_par *par = (struct aty128fb_par *) fb->par;
u32 xoffset, yoffset;
u32 offset;
......@@ -1490,36 +1398,36 @@ aty128fb_pan_display(struct fb_var_screeninfo *var, int con,
xres = (((par->crtc.h_total >> 16) & 0xff) + 1) << 3;
yres = ((par->crtc.v_total >> 16) & 0x7ff) + 1;
xoffset = (var->xoffset +7) & ~7;
xoffset = (var->xoffset + 7) & ~7;
yoffset = var->yoffset;
if (xoffset+xres > par->crtc.vxres || yoffset+yres > par->crtc.vyres)
if (xoffset + xres > info->fb_info.var.xres_virtual
|| yoffset + yres > par->crtc.vyres)
return -EINVAL;
par->crtc.xoffset = xoffset;
par->crtc.yoffset = yoffset;
offset = ((yoffset * par->crtc.vxres + xoffset) * par->crtc.bpp) >> 6;
offset =
((yoffset * info->fb_info.var.xres_virtual + xoffset) * par->crtc.bpp) >> 6;
aty_st_le32(CRTC_OFFSET, offset);
return 0;
}
static int
aty128fb_rasterimg(struct fb_info *info, int start)
static int aty128fb_rasterimg(struct fb_info *info, int start)
{
struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info;
struct fb_info_aty128 *fb = (struct fb_info_aty128 *) info;
struct aty128fb_par *par = (struct aty128fb_par *) info->par;
if (fb->blitter_may_be_busy)
if (par->blitter_may_be_busy)
wait_for_idle(fb);
return 0;
}
int __init
aty128fb_setup(char *options)
int __init aty128fb_setup(char *options)
{
char *this_opt;
......@@ -1531,28 +1439,28 @@ aty128fb_setup(char *options)
char *p;
int i;
p = this_opt +5;
p = this_opt + 5;
for (i = 0; i < sizeof(fontname) - 1; i++)
if (!*p || *p == ' ' || *p == ',')
break;
memcpy(fontname, this_opt + 5, i);
fontname[i] = 0;
} else if (!strncmp(this_opt, "noaccel", 7)) {
noaccel = 1;
}
#ifdef CONFIG_MTRR
else if(!strncmp(this_opt, "nomtrr", 6)) {
else if (!strncmp(this_opt, "nomtrr", 6)) {
mtrr = 0;
}
#endif
#ifdef CONFIG_PPC
/* vmode and cmode depreciated */
else if (!strncmp(this_opt, "vmode:", 6)) {
unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
unsigned int vmode =
simple_strtoul(this_opt + 6, NULL, 0);
if (vmode > 0 && vmode <= VMODE_MAX)
default_vmode = vmode;
} else if (!strncmp(this_opt, "cmode:", 6)) {
unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0);
unsigned int cmode =
simple_strtoul(this_opt + 6, NULL, 0);
switch (cmode) {
case 0:
case 8:
......@@ -1581,7 +1489,8 @@ aty128fb_setup(char *options)
*/
static int __init
aty128_init(struct fb_info_aty128 *info, struct aty128fb_par *par, struct pci_dev *pdev, const char *name)
aty128_init(struct fb_info_aty128 *info, struct aty128fb_par *par,
struct pci_dev *pdev, const char *name)
{
struct fb_var_screeninfo var;
u32 dac;
......@@ -1591,12 +1500,14 @@ aty128_init(struct fb_info_aty128 *info, struct aty128fb_par *par, struct pci_de
char *video_card = "Rage128";
if (!info->fb_info.fix.smem_len) /* may have already been probed */
info->fb_info.fix.smem_len = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
info->fb_info.fix.smem_len =
aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
#ifdef CONFIG_MTRR
if (mtrr) {
par->mtrr.vram = mtrr_add(info->fb_info.fix.smem_start,
info->fb_info.fix.smem_len, MTRR_TYPE_WRCOMB, 1);
info->fb_info.fix.smem_len,
MTRR_TYPE_WRCOMB, 1);
par->mtrr.vram_valid = 1;
/* let there be speed */
printk(KERN_INFO "aty128fb: Rage128 MTRR set to ON\n");
......@@ -1607,16 +1518,22 @@ aty128_init(struct fb_info_aty128 *info, struct aty128fb_par *par, struct pci_de
chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F;
/* put a name with the face */
while (aci->name && pdev->device != aci->device) { aci++; }
video_card = (char *)aci->name;
info->chip_gen = aci->chip_gen;
while (aci->name && pdev->device != aci->device) {
aci++;
}
video_card = (char *) aci->name;
par->chip_gen = aci->chip_gen;
printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev);
printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card,
chip_rev);
if (info->fb_info.fix.smem_len % (1024 * 1024) == 0)
printk("%dM %s\n", info->fb_info.fix.smem_len / (1024*1024), info->mem->name);
printk("%dM %s\n",
info->fb_info.fix.smem_len / (1024 * 1024),
info->mem->name);
else
printk("%dk %s\n", info->fb_info.fix.smem_len / 1024, info->mem->name);
printk("%dk %s\n", info->fb_info.fix.smem_len / 1024,
info->mem->name);
/* fill in info */
strcpy(info->fb_info.modename, info->fb_info.fix.id);
......@@ -1624,7 +1541,7 @@ aty128_init(struct fb_info_aty128 *info, struct aty128fb_par *par, struct pci_de
info->fb_info.fbops = &aty128fb_ops;
strcpy(info->fb_info.fontname, fontname);
info->fb_info.changevar = NULL;
info->fb_info.switch_con = &aty128fbcon_switch;
info->fb_info.switch_con = gen_switch;
info->fb_info.updatevar = NULL;
info->fb_info.flags = FBINFO_FLAG_DEFAULT;
......@@ -1632,10 +1549,12 @@ aty128_init(struct fb_info_aty128 *info, struct aty128fb_par *par, struct pci_de
#ifdef CONFIG_PPC
if (_machine == _MACH_Pmac) {
if (mode_option) {
if (!mac_find_mode(&var, &info->fb_info, mode_option, 8))
if (!mac_find_mode
(&var, &info->fb_info, mode_option, 8))
var = default_var;
} else {
if (default_vmode <= 0 || default_vmode > VMODE_MAX)
if (default_vmode <= 0
|| default_vmode > VMODE_MAX)
default_vmode = VMODE_1024_768_60;
/* iMacs need that resolution
......@@ -1661,25 +1580,27 @@ aty128_init(struct fb_info_aty128 *info, struct aty128fb_par *par, struct pci_de
if (machine_is_compatible("PowerBook3,2"))
default_vmode = VMODE_1152_768_60;
if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
if (default_cmode < CMODE_8
|| default_cmode > CMODE_32)
default_cmode = CMODE_8;
if (mac_vmode_to_var(default_vmode, default_cmode, &var))
if (mac_vmode_to_var
(default_vmode, default_cmode, &var))
var = default_var;
}
} else
#endif /* CONFIG_PPC */
{
if (fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0,
if (fb_find_mode
(&var, &info->fb_info, mode_option, NULL, 0,
&defaultmode, 8) == 0)
var = default_var;
}
if (noaccel)
var.accel_flags &= ~FB_ACCELF_TEXT;
else
var.accel_flags |= FB_ACCELF_TEXT;
info->fb_info.var = var;
if (aty128_decode_var(&var, par, info)) {
printk(KERN_ERR "aty128fb: Cannot set default mode.\n");
return 0;
......@@ -1708,7 +1629,8 @@ aty128_init(struct fb_info_aty128 *info, struct aty128fb_par *par, struct pci_de
#ifdef CONFIG_PMAC_BACKLIGHT
/* Could be extended to Rage128Pro LVDS output too */
if (info->chip_gen == rage_M3)
register_backlight_controller(&aty128_backlight_controller, info, "ati");
register_backlight_controller(&aty128_backlight_controller,
info, "ati");
#endif /* CONFIG_PMAC_BACKLIGHT */
printk(KERN_INFO "fb%d: %s frame buffer device on %s\n",
......@@ -1726,9 +1648,9 @@ fb_info_aty128 *aty128_board_list_add(struct fb_info_aty128 *board_list,
struct fb_info_aty128 *i_p = board_list;
new_node->next = NULL;
if(board_list == NULL)
if (board_list == NULL)
return new_node;
while(i_p->next != NULL)
while (i_p->next != NULL)
i_p = i_p->next;
i_p->next = new_node;
......@@ -1736,19 +1658,21 @@ fb_info_aty128 *aty128_board_list_add(struct fb_info_aty128 *board_list,
}
int __init
aty128fb_init(void)
int __init aty128fb_init(void)
{
#ifdef CONFIG_PCI
struct pci_dev *pdev = NULL;
const struct aty128_chip_info *aci = &aty128_pci_probe_list[0];
while (aci->name != NULL) {
pdev = pci_find_device(PCI_VENDOR_ID_ATI, aci->device, pdev);
pdev =
pci_find_device(PCI_VENDOR_ID_ATI, aci->device, pdev);
while (pdev != NULL) {
if (aty128_pci_register(pdev, aci) == 0)
return 0;
pdev = pci_find_device(PCI_VENDOR_ID_ATI, aci->device, pdev);
pdev =
pci_find_device(PCI_VENDOR_ID_ATI, aci->device,
pdev);
}
aci++;
}
......@@ -1779,7 +1703,8 @@ aty128_pci_register(struct pci_dev *pdev,
}
aty128fb_fix.smem_start = pci_resource_start(pdev, 0);
if (!request_mem_region(aty128fb_fix.smem_start, pci_resource_len(pdev, 0),
if (!request_mem_region
(aty128fb_fix.smem_start, pci_resource_len(pdev, 0),
"aty128fb FB")) {
printk(KERN_ERR "aty128fb: cannot reserve frame "
"buffer memory\n");
......@@ -1787,14 +1712,19 @@ aty128_pci_register(struct pci_dev *pdev,
}
aty128fb_fix.mmio_start = pci_resource_start(pdev, 2);
if (!request_mem_region(aty128fb_fix.mmio_start, pci_resource_len(pdev, 2),
if (!request_mem_region
(aty128fb_fix.mmio_start, pci_resource_len(pdev, 2),
"aty128fb MMIO")) {
printk(KERN_ERR "aty128fb: cannot reserve MMIO region\n");
goto err_free_mmio;
}
/* We have the resources. Now virtualize them */
if (!(info = kmalloc(sizeof(struct fb_info_aty128) + sizeof(struct display) + sizeof(u32) * 17, GFP_ATOMIC))) {
if (!
(info =
kmalloc(sizeof(struct fb_info_aty128) +
sizeof(struct display) + sizeof(u32) * 17,
GFP_ATOMIC))) {
printk(KERN_ERR "aty128fb: can't alloc fb_info_aty128\n");
goto err_unmap_out;
}
......@@ -1806,8 +1736,8 @@ aty128_pci_register(struct pci_dev *pdev,
memset(info, 0, sizeof(struct fb_info_aty128));
memset(par, 0, sizeof(struct aty128fb_par));
info->fb_info.disp = (struct display *)(info + 1);
info->fb_info.pseudo_palette = (void *)(info->fb_info.disp + 1);
info->fb_info.disp = (struct display *) (info + 1);
info->fb_info.pseudo_palette = (void *) (info->fb_info.disp + 1);
info->fb_info.par = par;
info->fb_info.currcon = -1;
......@@ -1820,29 +1750,31 @@ aty128_pci_register(struct pci_dev *pdev,
goto err_free_info;
/* Grab memory size from the card */
info->fb_info.fix.smem_len = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
info->fb_info.fix.smem_len =
aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
/* Virtualize the framebuffer */
info->fb_info.screen_base = ioremap(aty128fb_fix.smem_start, info->fb_info.fix.smem_len);
info->fb_info.screen_base =
ioremap(aty128fb_fix.smem_start, info->fb_info.fix.smem_len);
if (!info->fb_info.screen_base) {
iounmap((void *)info->regbase);
iounmap((void *) info->regbase);
goto err_free_info;
}
/* If we can't test scratch registers, something is seriously wrong */
if (!register_test(info)) {
printk(KERN_ERR "aty128fb: Can't write to video register!\n");
printk(KERN_ERR
"aty128fb: Can't write to video register!\n");
goto err_out;
}
#if !defined(CONFIG_PPC) && !defined(__sparc__)
if (!(bios_seg = aty128find_ROM(info)))
printk(KERN_INFO "aty128fb: Rage128 BIOS not located. "
"Guessing...\n");
else {
printk(KERN_INFO "aty128fb: Rage128 BIOS located at "
"segment %4.4X\n", (unsigned int)bios_seg);
"segment %4.4X\n", (unsigned int) bios_seg);
aty128_get_pllinfo(info, bios_seg);
}
#endif
......@@ -1852,18 +1784,18 @@ aty128_pci_register(struct pci_dev *pdev,
goto err_out;
return 0;
err_out:
err_out:
iounmap(info->fb_info.screen_base);
iounmap(info->regbase);
err_free_info:
err_free_info:
kfree(info);
err_unmap_out:
err_unmap_out:
release_mem_region(pci_resource_start(pdev, 2),
pci_resource_len(pdev, 2));
err_free_mmio:
err_free_mmio:
release_mem_region(pci_resource_start(pdev, 0),
pci_resource_len(pdev, 0));
err_free_fb:
err_free_fb:
release_mem_region(pci_resource_start(pdev, 1),
pci_resource_len(pdev, 1));
return -ENODEV;
......@@ -1873,8 +1805,7 @@ aty128_pci_register(struct pci_dev *pdev,
/* PPC and Sparc cannot read video ROM */
#if !defined(CONFIG_PPC) && !defined(__sparc__)
static char __init
*aty128find_ROM(struct fb_info_aty128 *info)
static char __init * aty128find_ROM(struct fb_info_aty128 *info)
{
u32 segstart;
char *rom_base;
......@@ -1884,12 +1815,14 @@ static char __init
char aty_rom_sig[] = "761295520"; /* ATI ROM Signature */
char R128_sig[] = "R128"; /* Rage128 ROM identifier */
for (segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
for (segstart = 0x000c0000; segstart < 0x000f0000;
segstart += 0x00001000) {
stage = 1;
rom_base = (char *)ioremap(segstart, 0x1000);
rom_base = (char *) ioremap(segstart, 0x1000);
if ((*rom_base == 0x55) && (((*(rom_base + 1)) & 0xff) == 0xaa))
if ((*rom_base == 0x55)
&& (((*(rom_base + 1)) & 0xff) == 0xaa))
stage = 2;
if (stage != 2) {
......@@ -1898,7 +1831,9 @@ static char __init
}
rom = rom_base;
for (i = 0; (i < 128 - strlen(aty_rom_sig)) && (stage != 3); i++) {
for (i = 0;
(i < 128 - strlen(aty_rom_sig)) && (stage != 3);
i++) {
if (aty_rom_sig[0] == *rom)
if (strncmp(aty_rom_sig, rom,
strlen(aty_rom_sig)) == 0)
......@@ -1954,9 +1889,9 @@ aty128_get_pllinfo(struct fb_info_aty128 *info, char *bios_seg)
info->constants.ppll_max = pll.PCLK_max_freq;
info->constants.ppll_min = pll.PCLK_min_freq;
info->constants.xclk = (u32)pll.XCLK;
info->constants.ref_divider = (u32)pll.PCLK_ref_divider;
info->constants.dotclock = (u32)pll.PCLK_ref_freq;
info->constants.xclk = (u32) pll.XCLK;
info->constants.ref_divider = (u32) pll.PCLK_ref_divider;
info->constants.dotclock = (u32) pll.PCLK_ref_freq;
DBG("ppll_max %d ppll_min %d xclk %d ref_divider %d dotclock %d\n",
info->constants.ppll_max, info->constants.ppll_min,
......@@ -1968,8 +1903,7 @@ aty128_get_pllinfo(struct fb_info_aty128 *info, char *bios_seg)
/* fill in known card constants if pll_block is not available */
static void __init
aty128_timings(struct fb_info_aty128 *info)
static void __init aty128_timings(struct fb_info_aty128 *info)
{
#ifdef CONFIG_PPC
/* instead of a table lookup, assume OF has properly
......@@ -1979,8 +1913,7 @@ aty128_timings(struct fb_info_aty128 *info)
u32 x_mpll_ref_fb_div;
u32 xclk_cntl;
u32 Nx, M;
unsigned PostDivSet[] =
{ 0, 1, 2, 4, 8, 3, 6, 12 };
unsigned PostDivSet[] = { 0, 1, 2, 4, 8, 3, 6, 12 };
#endif
if (!info->constants.dotclock)
......@@ -1993,7 +1926,8 @@ aty128_timings(struct fb_info_aty128 *info)
M = x_mpll_ref_fb_div & 0x0000ff;
info->constants.xclk = round_div((2 * Nx *
info->constants.dotclock), (M * PostDivSet[xclk_cntl]));
info->constants.dotclock),
(M * PostDivSet[xclk_cntl]));
info->constants.ref_divider =
aty_ld_pll(PPLL_REF_DIV) & PPLL_REF_DIV_MASK;
......@@ -2034,42 +1968,12 @@ aty128_timings(struct fb_info_aty128 *info)
}
}
static int
aty128fbcon_switch(int con, struct fb_info *fb)
{
struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
struct display *disp;
struct aty128fb_par par;
if (info->fb_info.currcon >= 0) {
disp = fb_display + info->fb_info.currcon;
if (disp->cmap.len)
fb_copy_cmap(&info->fb_info.cmap, &disp->cmap, 0);
}
/* set the current console */
fb->currcon = con;
aty128_decode_var(&fb_display[con].var, &par, info);
aty128_set_par(&par, info);
aty128_set_dispsw(&fb_display[con], info, par.crtc.bpp,
par.accel_flags & FB_ACCELF_TEXT);
do_install_cmap(con, fb);
return 1;
}
/*
* Blank the display.
*/
static int
aty128fb_blank(int blank, struct fb_info *fb)
static int aty128fb_blank(int blank, struct fb_info *fb)
{
struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
struct fb_info_aty128 *info = (struct fb_info_aty128 *) fb;
u8 state = 0;
#ifdef CONFIG_PMAC_BACKLIGHT
......@@ -2084,7 +1988,7 @@ aty128fb_blank(int blank, struct fb_info *fb)
if (blank & VESA_POWERDOWN)
state |= 4;
aty_st_8(CRTC_EXT_CNTL+1, state);
aty_st_8(CRTC_EXT_CNTL + 1, state);
#ifdef CONFIG_PMAC_BACKLIGHT
if ((_machine == _MACH_Pmac) && !blank)
......@@ -2102,7 +2006,7 @@ static int
aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *fb)
{
struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
struct fb_info_aty128 *info = (struct fb_info_aty128 *) fb;
struct aty128fb_par *par = (struct aty128fb_par *) fb->par;
u32 col;
......@@ -2121,19 +2025,23 @@ aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
if ((par->crtc.bpp > 8) && (regno == 0)) {
int i;
if (info->chip_gen == rage_M3)
aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL);
if (par->chip_gen == rage_M3)
aty_st_le32(DAC_CNTL,
aty_ld_le32(DAC_CNTL) &
~DAC_PALETTE_ACCESS_CNTL);
for (i=16; i<256; i++) {
for (i = 16; i < 256; i++) {
aty_st_8(PALETTE_INDEX, i);
col = (i << 16) | (i << 8) | i;
aty_st_le32(PALETTE_DATA, col);
}
if (info->chip_gen == rage_M3) {
aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL);
if (par->chip_gen == rage_M3) {
aty_st_le32(DAC_CNTL,
aty_ld_le32(DAC_CNTL) |
DAC_PALETTE_ACCESS_CNTL);
for (i=16; i<256; i++) {
for (i = 16; i < 256; i++) {
aty_st_8(PALETTE_INDEX, i);
col = (i << 16) | (i << 8) | i;
aty_st_le32(PALETTE_DATA, col);
......@@ -2143,8 +2051,10 @@ aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
/* initialize palette */
if (info->chip_gen == rage_M3)
aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL);
if (par->chip_gen == rage_M3)
aty_st_le32(DAC_CNTL,
aty_ld_le32(DAC_CNTL) &
~DAC_PALETTE_ACCESS_CNTL);
if (par->crtc.bpp == 16)
aty_st_8(PALETTE_INDEX, (regno << 3));
......@@ -2152,8 +2062,10 @@ aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
aty_st_8(PALETTE_INDEX, regno);
col = (red << 16) | (green << 8) | blue;
aty_st_le32(PALETTE_DATA, col);
if (info->chip_gen == rage_M3) {
aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL);
if (par->chip_gen == rage_M3) {
aty_st_le32(DAC_CNTL,
aty_ld_le32(DAC_CNTL) |
DAC_PALETTE_ACCESS_CNTL);
if (par->crtc.bpp == 16)
aty_st_8(PALETTE_INDEX, (regno << 3));
else
......@@ -2165,20 +2077,24 @@ aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
switch (par->crtc.bpp) {
#ifdef FBCON_HAS_CFB16
case 9 ... 16:
((u32*) (info->fb_info.pseudo_palette))[regno] = (regno << 10) | (regno << 5) | regno;
((u32 *) (info->fb_info.pseudo_palette))[regno] =
(regno << 10) | (regno << 5) | regno;
break;
#endif
#ifdef FBCON_HAS_CFB24
case 17 ... 24:
((u32*) (info->fb_info.pseudo_palette))[regno] = (regno << 16) | (regno << 8) | regno;
((u32 *) (info->fb_info.pseudo_palette))[regno] =
(regno << 16) | (regno << 8) | regno;
break;
#endif
#ifdef FBCON_HAS_CFB32
case 25 ... 32: {
case 25 ... 32:{
u32 i;
i = (regno << 8) | regno;
((u32*) (info->fb_info.pseudo_palette))[regno] = (i << 16) | i;
((u32 *) (info->fb_info.
pseudo_palette))[regno] =
(i << 16) | i;
break;
}
#endif
......@@ -2192,10 +2108,9 @@ static int backlight_conv[] = {
0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24
};
static int
aty128_set_backlight_enable(int on, int level, void* data)
static int aty128_set_backlight_enable(int on, int level, void *data)
{
struct fb_info_aty128 *info = (struct fb_info_aty128 *)data;
struct fb_info_aty128 *info = (struct fb_info_aty128 *) data;
unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
reg |= LVDS_BL_MOD_EN | LVDS_BLON;
......@@ -2211,8 +2126,7 @@ aty128_set_backlight_enable(int on, int level, void* data)
return 0;
}
static int
aty128_set_backlight_level(int level, void* data)
static int aty128_set_backlight_level(int level, void *data)
{
return aty128_set_backlight_enable(1, level, data);
}
......@@ -2224,10 +2138,10 @@ aty128_set_backlight_level(int level, void* data)
static inline void
aty128_rectcopy(int srcx, int srcy, int dstx, int dsty,
u_int width, u_int height,
struct fb_info_aty128 *info)
u_int width, u_int height, struct fb_info_aty128 *info)
{
struct aty128fb_par *par = (struct aty128fb_par *) info->fb_info.par;
struct aty128fb_par *par =
(struct aty128fb_par *) info->fb_info.par;
u32 save_dp_datatype, save_dp_cntl, bppval;
if (!width || !height)
......@@ -2256,7 +2170,7 @@ aty128_rectcopy(int srcx, int srcy, int dstx, int dsty,
aty_st_le32(DST_Y_X, (dsty << 16) | dstx);
aty_st_le32(DST_HEIGHT_WIDTH, (height << 16) | width);
info->blitter_may_be_busy = 1;
par->blitter_may_be_busy = 1;
wait_for_fifo(2, info);
aty_st_le32(DP_DATATYPE, save_dp_datatype);
......@@ -2280,7 +2194,7 @@ fbcon_aty128_bmove(struct display *p, int sy, int sx, int dy, int dx,
height *= fontheight(p);
aty128_rectcopy(sx, sy, dx, dy, width, height,
(struct fb_info_aty128 *)p->fb_info);
(struct fb_info_aty128 *) p->fb_info);
}
......@@ -2288,9 +2202,10 @@ fbcon_aty128_bmove(struct display *p, int sy, int sx, int dy, int dx,
static void fbcon_aty8_putc(struct vc_data *conp, struct display *p,
int c, int yy, int xx)
{
struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
struct fb_info_aty128 *fb = (struct fb_info_aty128 *) (p->fb_info);
struct aty128fb_par *par = (struct aty128fb_par *) fb->fb_info.par;
if (fb->blitter_may_be_busy)
if (par->blitter_may_be_busy)
wait_for_idle(fb);
fbcon_cfb8_putc(conp, p, c, yy, xx);
......@@ -2301,9 +2216,10 @@ static void fbcon_aty8_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count,
int yy, int xx)
{
struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
struct fb_info_aty128 *fb = (struct fb_info_aty128 *) (p->fb_info);
struct aty128fb_par *par = (struct aty128fb_par *) fb->fb_info.par;
if (fb->blitter_may_be_busy)
if (par->blitter_may_be_busy)
wait_for_idle(fb);
fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
......@@ -2313,32 +2229,35 @@ static void fbcon_aty8_putcs(struct vc_data *conp, struct display *p,
static void fbcon_aty8_clear_margins(struct vc_data *conp,
struct display *p, int bottom_only)
{
struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
struct fb_info_aty128 *fb = (struct fb_info_aty128 *) (p->fb_info);
struct aty128fb_par *par = (struct aty128fb_par *) fb->fb_info.par;
if (fb->blitter_may_be_busy)
if (par->blitter_may_be_busy)
wait_for_idle(fb);
fbcon_cfb8_clear_margins(conp, p, bottom_only);
}
static struct display_switch fbcon_aty128_8 = {
setup: fbcon_cfb8_setup,
bmove: fbcon_aty128_bmove,
clear: fbcon_cfb8_clear,
putc: fbcon_aty8_putc,
putcs: fbcon_aty8_putcs,
revc: fbcon_cfb8_revc,
clear_margins: fbcon_aty8_clear_margins,
fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
setup:fbcon_cfb8_setup,
bmove:fbcon_aty128_bmove,
clear:fbcon_cfb8_clear,
putc:fbcon_aty8_putc,
putcs:fbcon_aty8_putcs,
revc:fbcon_cfb8_revc,
clear_margins:fbcon_aty8_clear_margins,
fontwidthmask:FONTWIDTH(4) | FONTWIDTH(8) | FONTWIDTH(12) |
FONTWIDTH(16)
};
#endif
#ifdef FBCON_HAS_CFB16
static void fbcon_aty16_putc(struct vc_data *conp, struct display *p,
int c, int yy, int xx)
{
struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
struct fb_info_aty128 *fb = (struct fb_info_aty128 *) (p->fb_info);
struct aty128fb_par *par = (struct aty128fb_par *) fb->fb_info.par;
if (fb->blitter_may_be_busy)
if (par->blitter_may_be_busy)
wait_for_idle(fb);
fbcon_cfb16_putc(conp, p, c, yy, xx);
......@@ -2349,9 +2268,10 @@ static void fbcon_aty16_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count,
int yy, int xx)
{
struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
struct fb_info_aty128 *fb = (struct fb_info_aty128 *) (p->fb_info);
struct aty128fb_par *par = (struct aty128fb_par *) fb->fb_info.par;
if (fb->blitter_may_be_busy)
if (par->blitter_may_be_busy)
wait_for_idle(fb);
fbcon_cfb16_putcs(conp, p, s, count, yy, xx);
......@@ -2361,32 +2281,35 @@ static void fbcon_aty16_putcs(struct vc_data *conp, struct display *p,
static void fbcon_aty16_clear_margins(struct vc_data *conp,
struct display *p, int bottom_only)
{
struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
struct fb_info_aty128 *fb = (struct fb_info_aty128 *) (p->fb_info);
struct aty128fb_par *par = (struct aty128fb_par *) fb->fb_info.par;
if (fb->blitter_may_be_busy)
if (par->blitter_may_be_busy)
wait_for_idle(fb);
fbcon_cfb16_clear_margins(conp, p, bottom_only);
}
static struct display_switch fbcon_aty128_16 = {
setup: fbcon_cfb16_setup,
bmove: fbcon_aty128_bmove,
clear: fbcon_cfb16_clear,
putc: fbcon_aty16_putc,
putcs: fbcon_aty16_putcs,
revc: fbcon_cfb16_revc,
clear_margins: fbcon_aty16_clear_margins,
fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
setup:fbcon_cfb16_setup,
bmove:fbcon_aty128_bmove,
clear:fbcon_cfb16_clear,
putc:fbcon_aty16_putc,
putcs:fbcon_aty16_putcs,
revc:fbcon_cfb16_revc,
clear_margins:fbcon_aty16_clear_margins,
fontwidthmask:FONTWIDTH(4) | FONTWIDTH(8) | FONTWIDTH(12) |
FONTWIDTH(16)
};
#endif
#ifdef FBCON_HAS_CFB24
static void fbcon_aty24_putc(struct vc_data *conp, struct display *p,
int c, int yy, int xx)
{
struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
struct fb_info_aty128 *fb = (struct fb_info_aty128 *) (p->fb_info);
struct aty128fb_par *par = (struct aty128fb_par *) fb->fb_info.par;
if (fb->blitter_may_be_busy)
if (par->blitter_may_be_busy)
wait_for_idle(fb);
fbcon_cfb24_putc(conp, p, c, yy, xx);
......@@ -2397,9 +2320,10 @@ static void fbcon_aty24_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count,
int yy, int xx)
{
struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
struct fb_info_aty128 *fb = (struct fb_info_aty128 *) (p->fb_info);
struct aty128fb_par *par = (struct aty128fb_par *) fb->fb_info.par;
if (fb->blitter_may_be_busy)
if (par->blitter_may_be_busy)
wait_for_idle(fb);
fbcon_cfb24_putcs(conp, p, s, count, yy, xx);
......@@ -2409,32 +2333,35 @@ static void fbcon_aty24_putcs(struct vc_data *conp, struct display *p,
static void fbcon_aty24_clear_margins(struct vc_data *conp,
struct display *p, int bottom_only)
{
struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
struct fb_info_aty128 *fb = (struct fb_info_aty128 *) (p->fb_info);
struct aty128fb_par *par = (struct aty128fb_par *) fb->fb_info.par;
if (fb->blitter_may_be_busy)
if (par->blitter_may_be_busy)
wait_for_idle(fb);
fbcon_cfb24_clear_margins(conp, p, bottom_only);
}
static struct display_switch fbcon_aty128_24 = {
setup: fbcon_cfb24_setup,
bmove: fbcon_aty128_bmove,
clear: fbcon_cfb24_clear,
putc: fbcon_aty24_putc,
putcs: fbcon_aty24_putcs,
revc: fbcon_cfb24_revc,
clear_margins: fbcon_aty24_clear_margins,
fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
setup:fbcon_cfb24_setup,
bmove:fbcon_aty128_bmove,
clear:fbcon_cfb24_clear,
putc:fbcon_aty24_putc,
putcs:fbcon_aty24_putcs,
revc:fbcon_cfb24_revc,
clear_margins:fbcon_aty24_clear_margins,
fontwidthmask:FONTWIDTH(4) | FONTWIDTH(8) | FONTWIDTH(12) |
FONTWIDTH(16)
};
#endif
#ifdef FBCON_HAS_CFB32
static void fbcon_aty32_putc(struct vc_data *conp, struct display *p,
int c, int yy, int xx)
{
struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
struct fb_info_aty128 *fb = (struct fb_info_aty128 *) (p->fb_info);
struct aty128fb_par *par = (struct aty128fb_par *) fb->fb_info.par;
if (fb->blitter_may_be_busy)
if (par->blitter_may_be_busy)
wait_for_idle(fb);
fbcon_cfb32_putc(conp, p, c, yy, xx);
......@@ -2445,9 +2372,10 @@ static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count,
int yy, int xx)
{
struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
struct fb_info_aty128 *fb = (struct fb_info_aty128 *) (p->fb_info);
struct aty128fb_par *par = (struct aty128fb_par *) fb->fb_info.par;
if (fb->blitter_may_be_busy)
if (par->blitter_may_be_busy)
wait_for_idle(fb);
fbcon_cfb32_putcs(conp, p, s, count, yy, xx);
......@@ -2457,23 +2385,25 @@ static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p,
static void fbcon_aty32_clear_margins(struct vc_data *conp,
struct display *p, int bottom_only)
{
struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
struct fb_info_aty128 *fb = (struct fb_info_aty128 *) (p->fb_info);
struct aty128fb_par *par = (struct aty128fb_par *) fb->fb_info.par;
if (fb->blitter_may_be_busy)
if (par->blitter_may_be_busy)
wait_for_idle(fb);
fbcon_cfb32_clear_margins(conp, p, bottom_only);
}
static struct display_switch fbcon_aty128_32 = {
setup: fbcon_cfb32_setup,
bmove: fbcon_aty128_bmove,
clear: fbcon_cfb32_clear,
putc: fbcon_aty32_putc,
putcs: fbcon_aty32_putcs,
revc: fbcon_cfb32_revc,
clear_margins: fbcon_aty32_clear_margins,
fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
setup:fbcon_cfb32_setup,
bmove:fbcon_aty128_bmove,
clear:fbcon_cfb32_clear,
putc:fbcon_aty32_putc,
putcs:fbcon_aty32_putcs,
revc:fbcon_cfb32_revc,
clear_margins:fbcon_aty32_clear_margins,
fontwidthmask:FONTWIDTH(4) | FONTWIDTH(8) | FONTWIDTH(12) |
FONTWIDTH(16)
};
#endif
......@@ -2481,31 +2411,33 @@ static struct display_switch fbcon_aty128_32 = {
MODULE_AUTHOR("(c)1999-2000 Brad Douglas <brad@neruo.com>");
MODULE_DESCRIPTION("FBDev driver for ATI Rage128 / Pro cards");
MODULE_LICENSE("GPL");
MODULE_PARM(noaccel, "i");
MODULE_PARM_DESC(noaccel, "Disable hardware acceleration (0 or 1=disabled) (default=0)");
MODULE_PARM(font, "s");
MODULE_PARM_DESC(font, "Specify one of the compiled-in fonts (default=none)");
MODULE_PARM_DESC(font,
"Specify one of the compiled-in fonts (default=none)");
MODULE_PARM(mode, "s");
MODULE_PARM_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
MODULE_PARM_DESC(mode,
"Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
#ifdef CONFIG_MTRR
MODULE_PARM(nomtrr, "i");
MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)");
MODULE_PARM_DESC(nomtrr,
"Disable MTRR support (0 or 1=disabled) (default=0)");
#endif
int __init
init_module(void)
int __init init_module(void)
{
if (noaccel) {
noaccel = 1;
printk(KERN_INFO "aty128fb: Parameter NOACCEL set\n");
}
if (font) {
strncpy(fontname, font, sizeof(fontname)-1);
printk(KERN_INFO "aty128fb: Parameter FONT set to %s\n", font);
strncpy(fontname, font, sizeof(fontname) - 1);
printk(KERN_INFO "aty128fb: Parameter FONT set to %s\n",
font);
}
if (mode) {
mode_option = mode;
printk(KERN_INFO "aty128fb: Parameter MODE set to %s\n", mode);
printk(KERN_INFO "aty128fb: Parameter MODE set to %s\n",
mode);
}
#ifdef CONFIG_MTRR
if (nomtrr) {
......@@ -2518,8 +2450,7 @@ init_module(void)
return 0;
}
void __exit
cleanup_module(void)
void __exit cleanup_module(void)
{
struct fb_info_aty128 *info = board_list;
struct aty128fb_par *par;
......@@ -2532,7 +2463,8 @@ cleanup_module(void)
unregister_framebuffer(&info->fb_info);
#ifdef CONFIG_MTRR
if (par->mtrr.vram_valid)
mtrr_del(par->mtrr.vram, info->fb_info.fix.smem_start,
mtrr_del(par->mtrr.vram,
info->fb_info.fix.smem_start,
info->fb_info.fix.smem_len);
#endif /* CONFIG_MTRR */
iounmap(info->regbase);
......
......@@ -414,12 +414,7 @@ void fbgen_set_disp(int con, struct fb_info_gen *info)
void gen_set_disp(int con, struct fb_info *info)
{
struct display *display;
if (con >= 0)
display = fb_display + con;
else
display = info->disp;
struct display *display = (con < 0) ? info->disp : (fb_display + con);
display->visual = info->fix.visual;
display->type = info->fix.type;
......@@ -510,9 +505,13 @@ int fbgen_update_var(int con, struct fb_info *info)
int gen_update_var(int con, struct fb_info *info)
{
struct display *disp = (con < 0) ? info->disp : (fb_display + con);
int err;
if (con == info->currcon) {
info->var.xoffset = disp->var.xoffset;
info->var.yoffset = disp->var.yoffset;
info->var.vmode = disp->var.vmode;
if (info->fbops->fb_pan_display) {
if ((err = info->fbops->fb_pan_display(&info->var, con, info)))
return err;
......
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