fbdev/amifb: Use framebuffer_alloc()
Use framebuffer_alloc() instead of static fb_info and currentpar variables. Also sanitize the error path and cleanup code (e.g. missing free_irq()). Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
This commit is contained in:
parent
af5761d609
commit
61640c295b
@ -710,7 +710,7 @@ static u_short *lofsprite, *shfsprite, *dummysprite;
|
||||
* Current Video Mode
|
||||
*/
|
||||
|
||||
static struct amifb_par {
|
||||
struct amifb_par {
|
||||
|
||||
/* General Values */
|
||||
|
||||
@ -773,15 +773,6 @@ static struct amifb_par {
|
||||
/* Additional AGA Hardware Registers */
|
||||
|
||||
u_short fmode; /* vmode */
|
||||
} currentpar;
|
||||
|
||||
|
||||
static struct fb_info fb_info = {
|
||||
.fix = {
|
||||
.id = "Amiga ",
|
||||
.visual = FB_VISUAL_PSEUDOCOLOR,
|
||||
.accel = FB_ACCEL_AMIGABLITT
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1130,8 +1121,8 @@ static u_short sprfetchmode[3] = {
|
||||
* it up, if it's too big, return -EINVAL.
|
||||
*/
|
||||
|
||||
static int ami_decode_var(struct fb_var_screeninfo *var,
|
||||
struct amifb_par *par)
|
||||
static int ami_decode_var(struct fb_var_screeninfo *var, struct amifb_par *par,
|
||||
const struct fb_info *info)
|
||||
{
|
||||
u_short clk_shift, line_shift;
|
||||
u_long maxfetchstop, fstrt, fsize, fconst, xres_n, yres_n;
|
||||
@ -1449,14 +1440,14 @@ static int ami_decode_var(struct fb_var_screeninfo *var,
|
||||
if (amifb_ilbm) {
|
||||
par->next_plane = div8(upx(16 << maxfmode, par->vxres));
|
||||
par->next_line = par->bpp * par->next_plane;
|
||||
if (par->next_line * par->vyres > fb_info.fix.smem_len) {
|
||||
if (par->next_line * par->vyres > info->fix.smem_len) {
|
||||
DPRINTK("too few video mem\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
par->next_line = div8(upx(16 << maxfmode, par->vxres));
|
||||
par->next_plane = par->vyres * par->next_line;
|
||||
if (par->next_plane * par->bpp > fb_info.fix.smem_len) {
|
||||
if (par->next_plane * par->bpp > info->fix.smem_len) {
|
||||
DPRINTK("too few video mem\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -1519,8 +1510,8 @@ static int ami_decode_var(struct fb_var_screeninfo *var,
|
||||
* other values read out of the hardware.
|
||||
*/
|
||||
|
||||
static int ami_encode_var(struct fb_var_screeninfo *var,
|
||||
struct amifb_par *par)
|
||||
static void ami_encode_var(struct fb_var_screeninfo *var,
|
||||
struct amifb_par *par)
|
||||
{
|
||||
u_short clk_shift, line_shift;
|
||||
|
||||
@ -1596,8 +1587,6 @@ static int ami_encode_var(struct fb_var_screeninfo *var,
|
||||
var->sync |= FB_SYNC_EXT;
|
||||
if (par->vmode & FB_VMODE_YWRAP)
|
||||
var->vmode |= FB_VMODE_YWRAP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -1605,9 +1594,9 @@ static int ami_encode_var(struct fb_var_screeninfo *var,
|
||||
* Update hardware
|
||||
*/
|
||||
|
||||
static int ami_update_par(void)
|
||||
static void ami_update_par(struct fb_info *info)
|
||||
{
|
||||
struct amifb_par *par = ¤tpar;
|
||||
struct amifb_par *par = info->par;
|
||||
short clk_shift, vshift, fstrt, fsize, fstop, fconst, shift, move, mod;
|
||||
|
||||
clk_shift = par->clk_shift;
|
||||
@ -1649,11 +1638,11 @@ static int ami_update_par(void)
|
||||
par->bpl1mod = par->bpl2mod;
|
||||
|
||||
if (par->yoffset) {
|
||||
par->bplpt0 = fb_info.fix.smem_start +
|
||||
par->bplpt0 = info->fix.smem_start +
|
||||
par->next_line * par->yoffset + move;
|
||||
if (par->vmode & FB_VMODE_YWRAP) {
|
||||
if (par->yoffset > par->vyres - par->yres) {
|
||||
par->bplpt0wrap = fb_info.fix.smem_start + move;
|
||||
par->bplpt0wrap = info->fix.smem_start + move;
|
||||
if (par->bplcon0 & BPC0_LACE &&
|
||||
mod2(par->diwstrt_v + par->vyres -
|
||||
par->yoffset))
|
||||
@ -1661,12 +1650,10 @@ static int ami_update_par(void)
|
||||
}
|
||||
}
|
||||
} else
|
||||
par->bplpt0 = fb_info.fix.smem_start + move;
|
||||
par->bplpt0 = info->fix.smem_start + move;
|
||||
|
||||
if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v))
|
||||
par->bplpt0 += par->next_line;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -1677,9 +1664,9 @@ static int ami_update_par(void)
|
||||
* in `var'.
|
||||
*/
|
||||
|
||||
static void ami_pan_var(struct fb_var_screeninfo *var)
|
||||
static void ami_pan_var(struct fb_var_screeninfo *var, struct fb_info *info)
|
||||
{
|
||||
struct amifb_par *par = ¤tpar;
|
||||
struct amifb_par *par = info->par;
|
||||
|
||||
par->xoffset = var->xoffset;
|
||||
par->yoffset = var->yoffset;
|
||||
@ -1689,15 +1676,13 @@ static void ami_pan_var(struct fb_var_screeninfo *var)
|
||||
par->vmode &= ~FB_VMODE_YWRAP;
|
||||
|
||||
do_vmode_pan = 0;
|
||||
ami_update_par();
|
||||
ami_update_par(info);
|
||||
do_vmode_pan = 1;
|
||||
}
|
||||
|
||||
|
||||
static void ami_update_display(void)
|
||||
static void ami_update_display(const struct amifb_par *par)
|
||||
{
|
||||
struct amifb_par *par = ¤tpar;
|
||||
|
||||
custom.bplcon1 = par->bplcon1;
|
||||
custom.bpl1mod = par->bpl1mod;
|
||||
custom.bpl2mod = par->bpl2mod;
|
||||
@ -1709,9 +1694,8 @@ static void ami_update_display(void)
|
||||
* Change the video mode (called by VBlank interrupt)
|
||||
*/
|
||||
|
||||
static void ami_init_display(void)
|
||||
static void ami_init_display(const struct amifb_par *par)
|
||||
{
|
||||
struct amifb_par *par = ¤tpar;
|
||||
int i;
|
||||
|
||||
custom.bplcon0 = par->bplcon0 & ~BPC0_LACE;
|
||||
@ -1764,9 +1748,8 @@ static void ami_init_display(void)
|
||||
* (Un)Blank the screen (called by VBlank interrupt)
|
||||
*/
|
||||
|
||||
static void ami_do_blank(void)
|
||||
static void ami_do_blank(const struct amifb_par *par)
|
||||
{
|
||||
struct amifb_par *par = ¤tpar;
|
||||
#if defined(CONFIG_FB_AMIGA_AGA)
|
||||
u_short bplcon3 = par->bplcon3;
|
||||
#endif
|
||||
@ -1843,10 +1826,9 @@ static void ami_do_blank(void)
|
||||
is_blanked = do_blank > 0 ? do_blank : 0;
|
||||
}
|
||||
|
||||
static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix)
|
||||
static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix,
|
||||
const struct amifb_par *par)
|
||||
{
|
||||
struct amifb_par *par = ¤tpar;
|
||||
|
||||
fix->crsr_width = fix->crsr_xsize = par->crsr.width;
|
||||
fix->crsr_height = fix->crsr_ysize = par->crsr.height;
|
||||
fix->crsr_color1 = 17;
|
||||
@ -1854,9 +1836,10 @@ static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data)
|
||||
static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var,
|
||||
u_char __user *data,
|
||||
const struct amifb_par *par)
|
||||
{
|
||||
struct amifb_par *par = ¤tpar;
|
||||
register u_short *lspr, *sspr;
|
||||
#ifdef __mc68000__
|
||||
register u_long datawords asm ("d2");
|
||||
@ -1929,9 +1912,9 @@ static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data)
|
||||
static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var,
|
||||
u_char __user *data, struct amifb_par *par)
|
||||
{
|
||||
struct amifb_par *par = ¤tpar;
|
||||
register u_short *lspr, *sspr;
|
||||
#ifdef __mc68000__
|
||||
register u_long datawords asm ("d2");
|
||||
@ -2047,20 +2030,18 @@ static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ami_get_cursorstate(struct fb_cursorstate *state)
|
||||
static int ami_get_cursorstate(struct fb_cursorstate *state,
|
||||
const struct amifb_par *par)
|
||||
{
|
||||
struct amifb_par *par = ¤tpar;
|
||||
|
||||
state->xoffset = par->crsr.crsr_x;
|
||||
state->yoffset = par->crsr.crsr_y;
|
||||
state->mode = cursormode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ami_set_cursorstate(struct fb_cursorstate *state)
|
||||
static int ami_set_cursorstate(struct fb_cursorstate *state,
|
||||
struct amifb_par *par)
|
||||
{
|
||||
struct amifb_par *par = ¤tpar;
|
||||
|
||||
par->crsr.crsr_x = state->xoffset;
|
||||
par->crsr.crsr_y = state->yoffset;
|
||||
if ((cursormode = state->mode) == FB_CURSOR_OFF)
|
||||
@ -2069,9 +2050,8 @@ static int ami_set_cursorstate(struct fb_cursorstate *state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ami_set_sprite(void)
|
||||
static void ami_set_sprite(const struct amifb_par *par)
|
||||
{
|
||||
struct amifb_par *par = ¤tpar;
|
||||
copins *copl, *cops;
|
||||
u_short hs, vs, ve;
|
||||
u_long pl, ps, pt;
|
||||
@ -2153,10 +2133,8 @@ static void __init ami_init_copper(void)
|
||||
custom.copjmp1 = 0;
|
||||
}
|
||||
|
||||
static void ami_reinit_copper(void)
|
||||
static void ami_reinit_copper(const struct amifb_par *par)
|
||||
{
|
||||
struct amifb_par *par = ¤tpar;
|
||||
|
||||
copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0;
|
||||
copdisplay.wait->l = CWAIT(32, par->diwstrt_v - 4);
|
||||
}
|
||||
@ -2168,9 +2146,8 @@ static void ami_reinit_copper(void)
|
||||
* We only change the things that are not static
|
||||
*/
|
||||
|
||||
static void ami_rebuild_copper(void)
|
||||
static void ami_rebuild_copper(const struct amifb_par *par)
|
||||
{
|
||||
struct amifb_par *par = ¤tpar;
|
||||
copins *copl, *cops;
|
||||
u_short line, h_end1, h_end2;
|
||||
short i;
|
||||
@ -2182,7 +2159,7 @@ static void ami_rebuild_copper(void)
|
||||
h_end1 = par->htotal - 32;
|
||||
h_end2 = par->ddfstop + 64;
|
||||
|
||||
ami_set_sprite();
|
||||
ami_set_sprite(par);
|
||||
|
||||
copl = copdisplay.rebuild[1];
|
||||
p = par->bplpt0;
|
||||
@ -2259,9 +2236,9 @@ static void ami_rebuild_copper(void)
|
||||
* Build the Copper List
|
||||
*/
|
||||
|
||||
static void ami_build_copper(void)
|
||||
static void ami_build_copper(struct fb_info *info)
|
||||
{
|
||||
struct amifb_par *par = ¤tpar;
|
||||
struct amifb_par *par = info->par;
|
||||
copins *copl, *cops;
|
||||
u_long p;
|
||||
|
||||
@ -2326,8 +2303,8 @@ static void ami_build_copper(void)
|
||||
}
|
||||
copdisplay.rebuild[1] = copl;
|
||||
|
||||
ami_update_par();
|
||||
ami_rebuild_copper();
|
||||
ami_update_par(info);
|
||||
ami_rebuild_copper(info->par);
|
||||
}
|
||||
|
||||
|
||||
@ -2405,7 +2382,8 @@ static int amifb_check_var(struct fb_var_screeninfo *var,
|
||||
struct amifb_par par;
|
||||
|
||||
/* Validate wanted screen parameters */
|
||||
if ((err = ami_decode_var(var, &par)))
|
||||
err = ami_decode_var(var, &par, info);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Encode (possibly rounded) screen parameters */
|
||||
@ -2417,15 +2395,18 @@ static int amifb_check_var(struct fb_var_screeninfo *var,
|
||||
static int amifb_set_par(struct fb_info *info)
|
||||
{
|
||||
struct amifb_par *par = info->par;
|
||||
int error;
|
||||
|
||||
do_vmode_pan = 0;
|
||||
do_vmode_full = 0;
|
||||
|
||||
/* Decode wanted screen parameters */
|
||||
ami_decode_var(&info->var, par);
|
||||
error = ami_decode_var(&info->var, par, info);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* Set new videomode */
|
||||
ami_build_copper();
|
||||
ami_build_copper(info);
|
||||
|
||||
/* Set VBlank trigger */
|
||||
do_vmode_full = 1;
|
||||
@ -2471,10 +2452,12 @@ static int amifb_set_par(struct fb_info *info)
|
||||
static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
|
||||
u_int transp, struct fb_info *info)
|
||||
{
|
||||
const struct amifb_par *par = info->par;
|
||||
|
||||
if (IS_AGA) {
|
||||
if (regno > 255)
|
||||
return 1;
|
||||
} else if (currentpar.bplcon0 & BPC0_SHRES) {
|
||||
} else if (par->bplcon0 & BPC0_SHRES) {
|
||||
if (regno > 3)
|
||||
return 1;
|
||||
} else {
|
||||
@ -2501,7 +2484,7 @@ static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
|
||||
if (regno || !is_blanked) {
|
||||
#if defined(CONFIG_FB_AMIGA_AGA)
|
||||
if (IS_AGA) {
|
||||
u_short bplcon3 = currentpar.bplcon3;
|
||||
u_short bplcon3 = par->bplcon3;
|
||||
VBlankOff();
|
||||
custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000);
|
||||
custom.color[regno & 31] = rgb2hw8_high(red, green,
|
||||
@ -2515,7 +2498,7 @@ static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
|
||||
} else
|
||||
#endif
|
||||
#if defined(CONFIG_FB_AMIGA_ECS)
|
||||
if (currentpar.bplcon0 & BPC0_SHRES) {
|
||||
if (par->bplcon0 & BPC0_SHRES) {
|
||||
u_short color, mask;
|
||||
int i;
|
||||
|
||||
@ -2572,7 +2555,7 @@ static int amifb_pan_display(struct fb_var_screeninfo *var,
|
||||
var->yoffset + info->var.yres > info->var.yres_virtual)
|
||||
return -EINVAL;
|
||||
}
|
||||
ami_pan_var(var);
|
||||
ami_pan_var(var, info);
|
||||
info->var.xoffset = var->xoffset;
|
||||
info->var.yoffset = var->yoffset;
|
||||
if (var->vmode & FB_VMODE_YWRAP)
|
||||
@ -3418,7 +3401,7 @@ static int amifb_ioctl(struct fb_info *info,
|
||||
|
||||
switch (cmd) {
|
||||
case FBIOGET_FCURSORINFO:
|
||||
i = ami_get_fix_cursorinfo(&crsr.fix);
|
||||
i = ami_get_fix_cursorinfo(&crsr.fix, info->par);
|
||||
if (i)
|
||||
return i;
|
||||
return copy_to_user(argp, &crsr.fix,
|
||||
@ -3426,7 +3409,8 @@ static int amifb_ioctl(struct fb_info *info,
|
||||
|
||||
case FBIOGET_VCURSORINFO:
|
||||
i = ami_get_var_cursorinfo(&crsr.var,
|
||||
((struct fb_var_cursorinfo __user *)arg)->data);
|
||||
((struct fb_var_cursorinfo __user *)arg)->data,
|
||||
info->par);
|
||||
if (i)
|
||||
return i;
|
||||
return copy_to_user(argp, &crsr.var,
|
||||
@ -3436,10 +3420,11 @@ static int amifb_ioctl(struct fb_info *info,
|
||||
if (copy_from_user(&crsr.var, argp, sizeof(crsr.var)))
|
||||
return -EFAULT;
|
||||
return ami_set_var_cursorinfo(&crsr.var,
|
||||
((struct fb_var_cursorinfo __user *)arg)->data);
|
||||
((struct fb_var_cursorinfo __user *)arg)->data,
|
||||
info->par);
|
||||
|
||||
case FBIOGET_CURSORSTATE:
|
||||
i = ami_get_cursorstate(&crsr.state);
|
||||
i = ami_get_cursorstate(&crsr.state, info->par);
|
||||
if (i)
|
||||
return i;
|
||||
return copy_to_user(argp, &crsr.state,
|
||||
@ -3448,7 +3433,7 @@ static int amifb_ioctl(struct fb_info *info,
|
||||
case FBIOPUT_CURSORSTATE:
|
||||
if (copy_from_user(&crsr.state, argp, sizeof(crsr.state)))
|
||||
return -EFAULT;
|
||||
return ami_set_cursorstate(&crsr.state);
|
||||
return ami_set_cursorstate(&crsr.state, info->par);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -3479,32 +3464,34 @@ static int flash_cursor(void)
|
||||
|
||||
static irqreturn_t amifb_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct amifb_par *par = dev_id;
|
||||
|
||||
if (do_vmode_pan || do_vmode_full)
|
||||
ami_update_display();
|
||||
ami_update_display(par);
|
||||
|
||||
if (do_vmode_full)
|
||||
ami_init_display();
|
||||
ami_init_display(par);
|
||||
|
||||
if (do_vmode_pan) {
|
||||
flash_cursor();
|
||||
ami_rebuild_copper();
|
||||
ami_rebuild_copper(par);
|
||||
do_cursor = do_vmode_pan = 0;
|
||||
} else if (do_cursor) {
|
||||
flash_cursor();
|
||||
ami_set_sprite();
|
||||
ami_set_sprite(par);
|
||||
do_cursor = 0;
|
||||
} else {
|
||||
if (flash_cursor())
|
||||
ami_set_sprite();
|
||||
ami_set_sprite(par);
|
||||
}
|
||||
|
||||
if (do_blank) {
|
||||
ami_do_blank();
|
||||
ami_do_blank(par);
|
||||
do_blank = 0;
|
||||
}
|
||||
|
||||
if (do_vmode_full) {
|
||||
ami_reinit_copper();
|
||||
ami_reinit_copper(par);
|
||||
do_vmode_full = 0;
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
@ -3549,23 +3536,13 @@ static inline void chipfree(void)
|
||||
}
|
||||
|
||||
|
||||
static void amifb_deinit(struct platform_device *pdev)
|
||||
{
|
||||
if (fb_info.cmap.len)
|
||||
fb_dealloc_cmap(&fb_info.cmap);
|
||||
chipfree();
|
||||
if (videomemory)
|
||||
iounmap((void *)videomemory);
|
||||
custom.dmacon = DMAF_ALL | DMAF_MASTER;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialisation
|
||||
*/
|
||||
|
||||
static int __init amifb_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct fb_info *info;
|
||||
int tag, i, err = 0;
|
||||
u_long chipptr;
|
||||
u_int defmode;
|
||||
@ -3581,10 +3558,20 @@ static int __init amifb_probe(struct platform_device *pdev)
|
||||
#endif
|
||||
custom.dmacon = DMAF_ALL | DMAF_MASTER;
|
||||
|
||||
info = framebuffer_alloc(sizeof(struct amifb_par), &pdev->dev);
|
||||
if (!info) {
|
||||
dev_err(&pdev->dev, "framebuffer_alloc failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
strcpy(info->fix.id, "Amiga ");
|
||||
info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
|
||||
info->fix.accel = FB_ACCEL_AMIGABLITT;
|
||||
|
||||
switch (amiga_chipset) {
|
||||
#ifdef CONFIG_FB_AMIGA_OCS
|
||||
case CS_OCS:
|
||||
strcat(fb_info.fix.id, "OCS");
|
||||
strcat(info->fix.id, "OCS");
|
||||
default_chipset:
|
||||
chipset = TAG_OCS;
|
||||
maxdepth[TAG_SHRES] = 0; /* OCS means no SHRES */
|
||||
@ -3592,13 +3579,13 @@ default_chipset:
|
||||
maxdepth[TAG_LORES] = 6;
|
||||
maxfmode = TAG_FMODE_1;
|
||||
defmode = amiga_vblank == 50 ? DEFMODE_PAL : DEFMODE_NTSC;
|
||||
fb_info.fix.smem_len = VIDEOMEMSIZE_OCS;
|
||||
info->fix.smem_len = VIDEOMEMSIZE_OCS;
|
||||
break;
|
||||
#endif /* CONFIG_FB_AMIGA_OCS */
|
||||
|
||||
#ifdef CONFIG_FB_AMIGA_ECS
|
||||
case CS_ECS:
|
||||
strcat(fb_info.fix.id, "ECS");
|
||||
strcat(info->fix.id, "ECS");
|
||||
chipset = TAG_ECS;
|
||||
maxdepth[TAG_SHRES] = 2;
|
||||
maxdepth[TAG_HIRES] = 4;
|
||||
@ -3612,15 +3599,15 @@ default_chipset:
|
||||
: DEFMODE_NTSC;
|
||||
if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
|
||||
VIDEOMEMSIZE_ECS_2M)
|
||||
fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_2M;
|
||||
info->fix.smem_len = VIDEOMEMSIZE_ECS_2M;
|
||||
else
|
||||
fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_1M;
|
||||
info->fix.smem_len = VIDEOMEMSIZE_ECS_1M;
|
||||
break;
|
||||
#endif /* CONFIG_FB_AMIGA_ECS */
|
||||
|
||||
#ifdef CONFIG_FB_AMIGA_AGA
|
||||
case CS_AGA:
|
||||
strcat(fb_info.fix.id, "AGA");
|
||||
strcat(info->fix.id, "AGA");
|
||||
chipset = TAG_AGA;
|
||||
maxdepth[TAG_SHRES] = 8;
|
||||
maxdepth[TAG_HIRES] = 8;
|
||||
@ -3629,20 +3616,20 @@ default_chipset:
|
||||
defmode = DEFMODE_AGA;
|
||||
if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
|
||||
VIDEOMEMSIZE_AGA_2M)
|
||||
fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_2M;
|
||||
info->fix.smem_len = VIDEOMEMSIZE_AGA_2M;
|
||||
else
|
||||
fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_1M;
|
||||
info->fix.smem_len = VIDEOMEMSIZE_AGA_1M;
|
||||
break;
|
||||
#endif /* CONFIG_FB_AMIGA_AGA */
|
||||
|
||||
default:
|
||||
#ifdef CONFIG_FB_AMIGA_OCS
|
||||
printk("Unknown graphics chipset, defaulting to OCS\n");
|
||||
strcat(fb_info.fix.id, "Unknown");
|
||||
strcat(info->fix.id, "Unknown");
|
||||
goto default_chipset;
|
||||
#else /* CONFIG_FB_AMIGA_OCS */
|
||||
err = -ENODEV;
|
||||
goto amifb_error;
|
||||
goto release;
|
||||
#endif /* CONFIG_FB_AMIGA_OCS */
|
||||
break;
|
||||
}
|
||||
@ -3672,44 +3659,43 @@ default_chipset:
|
||||
}
|
||||
|
||||
if (amifb_hfmin) {
|
||||
fb_info.monspecs.hfmin = amifb_hfmin;
|
||||
fb_info.monspecs.hfmax = amifb_hfmax;
|
||||
fb_info.monspecs.vfmin = amifb_vfmin;
|
||||
fb_info.monspecs.vfmax = amifb_vfmax;
|
||||
info->monspecs.hfmin = amifb_hfmin;
|
||||
info->monspecs.hfmax = amifb_hfmax;
|
||||
info->monspecs.vfmin = amifb_vfmin;
|
||||
info->monspecs.vfmax = amifb_vfmax;
|
||||
} else {
|
||||
/*
|
||||
* These are for a typical Amiga monitor (e.g. A1960)
|
||||
*/
|
||||
fb_info.monspecs.hfmin = 15000;
|
||||
fb_info.monspecs.hfmax = 38000;
|
||||
fb_info.monspecs.vfmin = 49;
|
||||
fb_info.monspecs.vfmax = 90;
|
||||
info->monspecs.hfmin = 15000;
|
||||
info->monspecs.hfmax = 38000;
|
||||
info->monspecs.vfmin = 49;
|
||||
info->monspecs.vfmax = 90;
|
||||
}
|
||||
|
||||
fb_info.fbops = &amifb_ops;
|
||||
fb_info.par = ¤tpar;
|
||||
fb_info.flags = FBINFO_DEFAULT;
|
||||
fb_info.device = &pdev->dev;
|
||||
info->fbops = &amifb_ops;
|
||||
info->flags = FBINFO_DEFAULT;
|
||||
info->device = &pdev->dev;
|
||||
|
||||
if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb,
|
||||
if (!fb_find_mode(&info->var, info, mode_option, ami_modedb,
|
||||
NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
|
||||
err = -EINVAL;
|
||||
goto amifb_error;
|
||||
goto release;
|
||||
}
|
||||
|
||||
fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES,
|
||||
&fb_info.modelist);
|
||||
&info->modelist);
|
||||
|
||||
round_down_bpp = 0;
|
||||
chipptr = chipalloc(fb_info.fix.smem_len + SPRITEMEMSIZE +
|
||||
chipptr = chipalloc(info->fix.smem_len + SPRITEMEMSIZE +
|
||||
DUMMYSPRITEMEMSIZE + COPINITSIZE +
|
||||
4 * COPLISTSIZE);
|
||||
if (!chipptr) {
|
||||
err = -ENOMEM;
|
||||
goto amifb_error;
|
||||
goto release;
|
||||
}
|
||||
|
||||
assignchunk(videomemory, u_long, chipptr, fb_info.fix.smem_len);
|
||||
assignchunk(videomemory, u_long, chipptr, info->fix.smem_len);
|
||||
assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE);
|
||||
assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE);
|
||||
assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE);
|
||||
@ -3721,14 +3707,15 @@ default_chipset:
|
||||
/*
|
||||
* access the videomem with writethrough cache
|
||||
*/
|
||||
fb_info.fix.smem_start = (u_long)ZTWO_PADDR(videomemory);
|
||||
videomemory = (u_long)ioremap_writethrough(fb_info.fix.smem_start,
|
||||
fb_info.fix.smem_len);
|
||||
info->fix.smem_start = (u_long)ZTWO_PADDR(videomemory);
|
||||
videomemory = (u_long)ioremap_writethrough(info->fix.smem_start,
|
||||
info->fix.smem_len);
|
||||
if (!videomemory) {
|
||||
printk("amifb: WARNING! unable to map videomem cached writethrough\n");
|
||||
fb_info.screen_base = (char *)ZTWO_VADDR(fb_info.fix.smem_start);
|
||||
dev_warn(&pdev->dev,
|
||||
"Unable to map videomem cached writethrough\n");
|
||||
info->screen_base = (char *)ZTWO_VADDR(info->fix.smem_start);
|
||||
} else
|
||||
fb_info.screen_base = (char *)videomemory;
|
||||
info->screen_base = (char *)videomemory;
|
||||
|
||||
memset(dummysprite, 0, DUMMYSPRITEMEMSIZE);
|
||||
|
||||
@ -3743,36 +3730,55 @@ default_chipset:
|
||||
custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
|
||||
DMAF_BLITTER | DMAF_SPRITE;
|
||||
|
||||
if (request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0,
|
||||
"fb vertb handler", ¤tpar)) {
|
||||
err = -EBUSY;
|
||||
goto amifb_error;
|
||||
}
|
||||
|
||||
err = fb_alloc_cmap(&fb_info.cmap, 1 << fb_info.var.bits_per_pixel, 0);
|
||||
err = request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0,
|
||||
"fb vertb handler", info->par);
|
||||
if (err)
|
||||
goto amifb_error;
|
||||
goto disable_dma;
|
||||
|
||||
if (register_framebuffer(&fb_info) < 0) {
|
||||
err = -EINVAL;
|
||||
goto amifb_error;
|
||||
}
|
||||
err = fb_alloc_cmap(&info->cmap, 1 << info->var.bits_per_pixel, 0);
|
||||
if (err)
|
||||
goto free_irq;
|
||||
|
||||
dev_set_drvdata(&pdev->dev, info);
|
||||
|
||||
err = register_framebuffer(info);
|
||||
if (err)
|
||||
goto unset_drvdata;
|
||||
|
||||
printk("fb%d: %s frame buffer device, using %dK of video memory\n",
|
||||
fb_info.node, fb_info.fix.id, fb_info.fix.smem_len>>10);
|
||||
info->node, info->fix.id, info->fix.smem_len>>10);
|
||||
|
||||
return 0;
|
||||
|
||||
amifb_error:
|
||||
amifb_deinit(pdev);
|
||||
unset_drvdata:
|
||||
dev_set_drvdata(&pdev->dev, NULL);
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
free_irq:
|
||||
free_irq(IRQ_AMIGA_COPPER, info->par);
|
||||
disable_dma:
|
||||
custom.dmacon = DMAF_ALL | DMAF_MASTER;
|
||||
if (videomemory)
|
||||
iounmap((void *)videomemory);
|
||||
chipfree();
|
||||
release:
|
||||
framebuffer_release(info);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int __exit amifb_remove(struct platform_device *pdev)
|
||||
{
|
||||
unregister_framebuffer(&fb_info);
|
||||
amifb_deinit(pdev);
|
||||
struct fb_info *info = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
unregister_framebuffer(info);
|
||||
dev_set_drvdata(&pdev->dev, NULL);
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
free_irq(IRQ_AMIGA_COPPER, info->par);
|
||||
custom.dmacon = DMAF_ALL | DMAF_MASTER;
|
||||
if (videomemory)
|
||||
iounmap((void *)videomemory);
|
||||
chipfree();
|
||||
framebuffer_release(info);
|
||||
amifb_video_off();
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user