Commit 61640c29 authored by Geert Uytterhoeven's avatar Geert Uytterhoeven Committed by Florian Tobias Schandinat

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