[PATCH 8/8] fbdev/amifb: Use framebuffer_alloc()

Geert Uytterhoeven
2011-11-21T20:53:59Z

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>
---
drivers/video/amifb.c | 286 +++++++++++++++++++++++++------------------------
1 files changed, 146 insertions(+), 140 deletions(-)

diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index 2bfaf1b..f23cae0 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -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 = &currentpar;
+ 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 = &currentpar;
+ 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 = &currentpar;
-
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 = &currentpar;
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 = &currentpar;
#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 = &currentpar;
-
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 = &currentpar;
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 = &currentpar;
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 = &currentpar;
-
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 = &currentpar;
-
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 = &currentpar;
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 = &currentpar;
-
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 = &currentpar;
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 = &currentpar;
+ 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 = &currentpar;
- 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", &currentpar)) {
- err = -EBUSY;
- goto amifb_error;
- }
+ err = request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0,
+ "fb vertb handler", info->par);
+ if (err)
+ goto disable_dma;

- err = fb_alloc_cmap(&fb_info.cmap, 1 << fb_info.var.bits_per_pixel, 0);
+ err = fb_alloc_cmap(&info->cmap, 1 << info->var.bits_per_pixel, 0);
if (err)
- goto amifb_error;
+ goto free_irq;

- if (register_framebuffer(&fb_info) < 0) {
- err = -EINVAL;
- goto amifb_error;
- }
+ 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;
}
--
1.7.0.4