Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Geert Uytterhoeven and committed by
Florian Tobias Schandinat
61640c29 af5761d6

+147 -141
+147 -141
drivers/video/amifb.c
··· 710 710 * Current Video Mode 711 711 */ 712 712 713 - static struct amifb_par { 713 + struct amifb_par { 714 714 715 715 /* General Values */ 716 716 ··· 773 773 /* Additional AGA Hardware Registers */ 774 774 775 775 u_short fmode; /* vmode */ 776 - } currentpar; 777 - 778 - 779 - static struct fb_info fb_info = { 780 - .fix = { 781 - .id = "Amiga ", 782 - .visual = FB_VISUAL_PSEUDOCOLOR, 783 - .accel = FB_ACCEL_AMIGABLITT 784 - } 785 776 }; 786 777 787 778 ··· 1121 1130 * it up, if it's too big, return -EINVAL. 1122 1131 */ 1123 1132 1124 - static int ami_decode_var(struct fb_var_screeninfo *var, 1125 - struct amifb_par *par) 1133 + static int ami_decode_var(struct fb_var_screeninfo *var, struct amifb_par *par, 1134 + const struct fb_info *info) 1126 1135 { 1127 1136 u_short clk_shift, line_shift; 1128 1137 u_long maxfetchstop, fstrt, fsize, fconst, xres_n, yres_n; ··· 1440 1449 if (amifb_ilbm) { 1441 1450 par->next_plane = div8(upx(16 << maxfmode, par->vxres)); 1442 1451 par->next_line = par->bpp * par->next_plane; 1443 - if (par->next_line * par->vyres > fb_info.fix.smem_len) { 1452 + if (par->next_line * par->vyres > info->fix.smem_len) { 1444 1453 DPRINTK("too few video mem\n"); 1445 1454 return -EINVAL; 1446 1455 } 1447 1456 } else { 1448 1457 par->next_line = div8(upx(16 << maxfmode, par->vxres)); 1449 1458 par->next_plane = par->vyres * par->next_line; 1450 - if (par->next_plane * par->bpp > fb_info.fix.smem_len) { 1459 + if (par->next_plane * par->bpp > info->fix.smem_len) { 1451 1460 DPRINTK("too few video mem\n"); 1452 1461 return -EINVAL; 1453 1462 } ··· 1510 1519 * other values read out of the hardware. 1511 1520 */ 1512 1521 1513 - static int ami_encode_var(struct fb_var_screeninfo *var, 1514 - struct amifb_par *par) 1522 + static void ami_encode_var(struct fb_var_screeninfo *var, 1523 + struct amifb_par *par) 1515 1524 { 1516 1525 u_short clk_shift, line_shift; 1517 1526 ··· 1587 1596 var->sync |= FB_SYNC_EXT; 1588 1597 if (par->vmode & FB_VMODE_YWRAP) 1589 1598 var->vmode |= FB_VMODE_YWRAP; 1590 - 1591 - return 0; 1592 1599 } 1593 1600 1594 1601 ··· 1594 1605 * Update hardware 1595 1606 */ 1596 1607 1597 - static int ami_update_par(void) 1608 + static void ami_update_par(struct fb_info *info) 1598 1609 { 1599 - struct amifb_par *par = &currentpar; 1610 + struct amifb_par *par = info->par; 1600 1611 short clk_shift, vshift, fstrt, fsize, fstop, fconst, shift, move, mod; 1601 1612 1602 1613 clk_shift = par->clk_shift; ··· 1638 1649 par->bpl1mod = par->bpl2mod; 1639 1650 1640 1651 if (par->yoffset) { 1641 - par->bplpt0 = fb_info.fix.smem_start + 1652 + par->bplpt0 = info->fix.smem_start + 1642 1653 par->next_line * par->yoffset + move; 1643 1654 if (par->vmode & FB_VMODE_YWRAP) { 1644 1655 if (par->yoffset > par->vyres - par->yres) { 1645 - par->bplpt0wrap = fb_info.fix.smem_start + move; 1656 + par->bplpt0wrap = info->fix.smem_start + move; 1646 1657 if (par->bplcon0 & BPC0_LACE && 1647 1658 mod2(par->diwstrt_v + par->vyres - 1648 1659 par->yoffset)) ··· 1650 1661 } 1651 1662 } 1652 1663 } else 1653 - par->bplpt0 = fb_info.fix.smem_start + move; 1664 + par->bplpt0 = info->fix.smem_start + move; 1654 1665 1655 1666 if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v)) 1656 1667 par->bplpt0 += par->next_line; 1657 - 1658 - return 0; 1659 1668 } 1660 1669 1661 1670 ··· 1664 1677 * in `var'. 1665 1678 */ 1666 1679 1667 - static void ami_pan_var(struct fb_var_screeninfo *var) 1680 + static void ami_pan_var(struct fb_var_screeninfo *var, struct fb_info *info) 1668 1681 { 1669 - struct amifb_par *par = &currentpar; 1682 + struct amifb_par *par = info->par; 1670 1683 1671 1684 par->xoffset = var->xoffset; 1672 1685 par->yoffset = var->yoffset; ··· 1676 1689 par->vmode &= ~FB_VMODE_YWRAP; 1677 1690 1678 1691 do_vmode_pan = 0; 1679 - ami_update_par(); 1692 + ami_update_par(info); 1680 1693 do_vmode_pan = 1; 1681 1694 } 1682 1695 1683 1696 1684 - static void ami_update_display(void) 1697 + static void ami_update_display(const struct amifb_par *par) 1685 1698 { 1686 - struct amifb_par *par = &currentpar; 1687 - 1688 1699 custom.bplcon1 = par->bplcon1; 1689 1700 custom.bpl1mod = par->bpl1mod; 1690 1701 custom.bpl2mod = par->bpl2mod; ··· 1694 1709 * Change the video mode (called by VBlank interrupt) 1695 1710 */ 1696 1711 1697 - static void ami_init_display(void) 1712 + static void ami_init_display(const struct amifb_par *par) 1698 1713 { 1699 - struct amifb_par *par = &currentpar; 1700 1714 int i; 1701 1715 1702 1716 custom.bplcon0 = par->bplcon0 & ~BPC0_LACE; ··· 1748 1764 * (Un)Blank the screen (called by VBlank interrupt) 1749 1765 */ 1750 1766 1751 - static void ami_do_blank(void) 1767 + static void ami_do_blank(const struct amifb_par *par) 1752 1768 { 1753 - struct amifb_par *par = &currentpar; 1754 1769 #if defined(CONFIG_FB_AMIGA_AGA) 1755 1770 u_short bplcon3 = par->bplcon3; 1756 1771 #endif ··· 1826 1843 is_blanked = do_blank > 0 ? do_blank : 0; 1827 1844 } 1828 1845 1829 - static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix) 1846 + static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix, 1847 + const struct amifb_par *par) 1830 1848 { 1831 - struct amifb_par *par = &currentpar; 1832 - 1833 1849 fix->crsr_width = fix->crsr_xsize = par->crsr.width; 1834 1850 fix->crsr_height = fix->crsr_ysize = par->crsr.height; 1835 1851 fix->crsr_color1 = 17; ··· 1836 1854 return 0; 1837 1855 } 1838 1856 1839 - static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data) 1857 + static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, 1858 + u_char __user *data, 1859 + const struct amifb_par *par) 1840 1860 { 1841 - struct amifb_par *par = &currentpar; 1842 1861 register u_short *lspr, *sspr; 1843 1862 #ifdef __mc68000__ 1844 1863 register u_long datawords asm ("d2"); ··· 1912 1929 return 0; 1913 1930 } 1914 1931 1915 - static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data) 1932 + static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, 1933 + u_char __user *data, struct amifb_par *par) 1916 1934 { 1917 - struct amifb_par *par = &currentpar; 1918 1935 register u_short *lspr, *sspr; 1919 1936 #ifdef __mc68000__ 1920 1937 register u_long datawords asm ("d2"); ··· 2030 2047 return 0; 2031 2048 } 2032 2049 2033 - static int ami_get_cursorstate(struct fb_cursorstate *state) 2050 + static int ami_get_cursorstate(struct fb_cursorstate *state, 2051 + const struct amifb_par *par) 2034 2052 { 2035 - struct amifb_par *par = &currentpar; 2036 - 2037 2053 state->xoffset = par->crsr.crsr_x; 2038 2054 state->yoffset = par->crsr.crsr_y; 2039 2055 state->mode = cursormode; 2040 2056 return 0; 2041 2057 } 2042 2058 2043 - static int ami_set_cursorstate(struct fb_cursorstate *state) 2059 + static int ami_set_cursorstate(struct fb_cursorstate *state, 2060 + struct amifb_par *par) 2044 2061 { 2045 - struct amifb_par *par = &currentpar; 2046 - 2047 2062 par->crsr.crsr_x = state->xoffset; 2048 2063 par->crsr.crsr_y = state->yoffset; 2049 2064 if ((cursormode = state->mode) == FB_CURSOR_OFF) ··· 2050 2069 return 0; 2051 2070 } 2052 2071 2053 - static void ami_set_sprite(void) 2072 + static void ami_set_sprite(const struct amifb_par *par) 2054 2073 { 2055 - struct amifb_par *par = &currentpar; 2056 2074 copins *copl, *cops; 2057 2075 u_short hs, vs, ve; 2058 2076 u_long pl, ps, pt; ··· 2133 2153 custom.copjmp1 = 0; 2134 2154 } 2135 2155 2136 - static void ami_reinit_copper(void) 2156 + static void ami_reinit_copper(const struct amifb_par *par) 2137 2157 { 2138 - struct amifb_par *par = &currentpar; 2139 - 2140 2158 copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0; 2141 2159 copdisplay.wait->l = CWAIT(32, par->diwstrt_v - 4); 2142 2160 } ··· 2146 2168 * We only change the things that are not static 2147 2169 */ 2148 2170 2149 - static void ami_rebuild_copper(void) 2171 + static void ami_rebuild_copper(const struct amifb_par *par) 2150 2172 { 2151 - struct amifb_par *par = &currentpar; 2152 2173 copins *copl, *cops; 2153 2174 u_short line, h_end1, h_end2; 2154 2175 short i; ··· 2159 2182 h_end1 = par->htotal - 32; 2160 2183 h_end2 = par->ddfstop + 64; 2161 2184 2162 - ami_set_sprite(); 2185 + ami_set_sprite(par); 2163 2186 2164 2187 copl = copdisplay.rebuild[1]; 2165 2188 p = par->bplpt0; ··· 2236 2259 * Build the Copper List 2237 2260 */ 2238 2261 2239 - static void ami_build_copper(void) 2262 + static void ami_build_copper(struct fb_info *info) 2240 2263 { 2241 - struct amifb_par *par = &currentpar; 2264 + struct amifb_par *par = info->par; 2242 2265 copins *copl, *cops; 2243 2266 u_long p; 2244 2267 ··· 2303 2326 } 2304 2327 copdisplay.rebuild[1] = copl; 2305 2328 2306 - ami_update_par(); 2307 - ami_rebuild_copper(); 2329 + ami_update_par(info); 2330 + ami_rebuild_copper(info->par); 2308 2331 } 2309 2332 2310 2333 ··· 2382 2405 struct amifb_par par; 2383 2406 2384 2407 /* Validate wanted screen parameters */ 2385 - if ((err = ami_decode_var(var, &par))) 2408 + err = ami_decode_var(var, &par, info); 2409 + if (err) 2386 2410 return err; 2387 2411 2388 2412 /* Encode (possibly rounded) screen parameters */ ··· 2395 2417 static int amifb_set_par(struct fb_info *info) 2396 2418 { 2397 2419 struct amifb_par *par = info->par; 2420 + int error; 2398 2421 2399 2422 do_vmode_pan = 0; 2400 2423 do_vmode_full = 0; 2401 2424 2402 2425 /* Decode wanted screen parameters */ 2403 - ami_decode_var(&info->var, par); 2426 + error = ami_decode_var(&info->var, par, info); 2427 + if (error) 2428 + return error; 2404 2429 2405 2430 /* Set new videomode */ 2406 - ami_build_copper(); 2431 + ami_build_copper(info); 2407 2432 2408 2433 /* Set VBlank trigger */ 2409 2434 do_vmode_full = 1; ··· 2452 2471 static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 2453 2472 u_int transp, struct fb_info *info) 2454 2473 { 2474 + const struct amifb_par *par = info->par; 2475 + 2455 2476 if (IS_AGA) { 2456 2477 if (regno > 255) 2457 2478 return 1; 2458 - } else if (currentpar.bplcon0 & BPC0_SHRES) { 2479 + } else if (par->bplcon0 & BPC0_SHRES) { 2459 2480 if (regno > 3) 2460 2481 return 1; 2461 2482 } else { ··· 2484 2501 if (regno || !is_blanked) { 2485 2502 #if defined(CONFIG_FB_AMIGA_AGA) 2486 2503 if (IS_AGA) { 2487 - u_short bplcon3 = currentpar.bplcon3; 2504 + u_short bplcon3 = par->bplcon3; 2488 2505 VBlankOff(); 2489 2506 custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000); 2490 2507 custom.color[regno & 31] = rgb2hw8_high(red, green, ··· 2498 2515 } else 2499 2516 #endif 2500 2517 #if defined(CONFIG_FB_AMIGA_ECS) 2501 - if (currentpar.bplcon0 & BPC0_SHRES) { 2518 + if (par->bplcon0 & BPC0_SHRES) { 2502 2519 u_short color, mask; 2503 2520 int i; 2504 2521 ··· 2555 2572 var->yoffset + info->var.yres > info->var.yres_virtual) 2556 2573 return -EINVAL; 2557 2574 } 2558 - ami_pan_var(var); 2575 + ami_pan_var(var, info); 2559 2576 info->var.xoffset = var->xoffset; 2560 2577 info->var.yoffset = var->yoffset; 2561 2578 if (var->vmode & FB_VMODE_YWRAP) ··· 3401 3418 3402 3419 switch (cmd) { 3403 3420 case FBIOGET_FCURSORINFO: 3404 - i = ami_get_fix_cursorinfo(&crsr.fix); 3421 + i = ami_get_fix_cursorinfo(&crsr.fix, info->par); 3405 3422 if (i) 3406 3423 return i; 3407 3424 return copy_to_user(argp, &crsr.fix, ··· 3409 3426 3410 3427 case FBIOGET_VCURSORINFO: 3411 3428 i = ami_get_var_cursorinfo(&crsr.var, 3412 - ((struct fb_var_cursorinfo __user *)arg)->data); 3429 + ((struct fb_var_cursorinfo __user *)arg)->data, 3430 + info->par); 3413 3431 if (i) 3414 3432 return i; 3415 3433 return copy_to_user(argp, &crsr.var, ··· 3420 3436 if (copy_from_user(&crsr.var, argp, sizeof(crsr.var))) 3421 3437 return -EFAULT; 3422 3438 return ami_set_var_cursorinfo(&crsr.var, 3423 - ((struct fb_var_cursorinfo __user *)arg)->data); 3439 + ((struct fb_var_cursorinfo __user *)arg)->data, 3440 + info->par); 3424 3441 3425 3442 case FBIOGET_CURSORSTATE: 3426 - i = ami_get_cursorstate(&crsr.state); 3443 + i = ami_get_cursorstate(&crsr.state, info->par); 3427 3444 if (i) 3428 3445 return i; 3429 3446 return copy_to_user(argp, &crsr.state, ··· 3433 3448 case FBIOPUT_CURSORSTATE: 3434 3449 if (copy_from_user(&crsr.state, argp, sizeof(crsr.state))) 3435 3450 return -EFAULT; 3436 - return ami_set_cursorstate(&crsr.state); 3451 + return ami_set_cursorstate(&crsr.state, info->par); 3437 3452 } 3438 3453 return -EINVAL; 3439 3454 } ··· 3464 3479 3465 3480 static irqreturn_t amifb_interrupt(int irq, void *dev_id) 3466 3481 { 3482 + struct amifb_par *par = dev_id; 3483 + 3467 3484 if (do_vmode_pan || do_vmode_full) 3468 - ami_update_display(); 3485 + ami_update_display(par); 3469 3486 3470 3487 if (do_vmode_full) 3471 - ami_init_display(); 3488 + ami_init_display(par); 3472 3489 3473 3490 if (do_vmode_pan) { 3474 3491 flash_cursor(); 3475 - ami_rebuild_copper(); 3492 + ami_rebuild_copper(par); 3476 3493 do_cursor = do_vmode_pan = 0; 3477 3494 } else if (do_cursor) { 3478 3495 flash_cursor(); 3479 - ami_set_sprite(); 3496 + ami_set_sprite(par); 3480 3497 do_cursor = 0; 3481 3498 } else { 3482 3499 if (flash_cursor()) 3483 - ami_set_sprite(); 3500 + ami_set_sprite(par); 3484 3501 } 3485 3502 3486 3503 if (do_blank) { 3487 - ami_do_blank(); 3504 + ami_do_blank(par); 3488 3505 do_blank = 0; 3489 3506 } 3490 3507 3491 3508 if (do_vmode_full) { 3492 - ami_reinit_copper(); 3509 + ami_reinit_copper(par); 3493 3510 do_vmode_full = 0; 3494 3511 } 3495 3512 return IRQ_HANDLED; ··· 3536 3549 } 3537 3550 3538 3551 3539 - static void amifb_deinit(struct platform_device *pdev) 3540 - { 3541 - if (fb_info.cmap.len) 3542 - fb_dealloc_cmap(&fb_info.cmap); 3543 - chipfree(); 3544 - if (videomemory) 3545 - iounmap((void *)videomemory); 3546 - custom.dmacon = DMAF_ALL | DMAF_MASTER; 3547 - } 3548 - 3549 - 3550 3552 /* 3551 3553 * Initialisation 3552 3554 */ 3553 3555 3554 3556 static int __init amifb_probe(struct platform_device *pdev) 3555 3557 { 3558 + struct fb_info *info; 3556 3559 int tag, i, err = 0; 3557 3560 u_long chipptr; 3558 3561 u_int defmode; ··· 3558 3581 #endif 3559 3582 custom.dmacon = DMAF_ALL | DMAF_MASTER; 3560 3583 3584 + info = framebuffer_alloc(sizeof(struct amifb_par), &pdev->dev); 3585 + if (!info) { 3586 + dev_err(&pdev->dev, "framebuffer_alloc failed\n"); 3587 + return -ENOMEM; 3588 + } 3589 + 3590 + strcpy(info->fix.id, "Amiga "); 3591 + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; 3592 + info->fix.accel = FB_ACCEL_AMIGABLITT; 3593 + 3561 3594 switch (amiga_chipset) { 3562 3595 #ifdef CONFIG_FB_AMIGA_OCS 3563 3596 case CS_OCS: 3564 - strcat(fb_info.fix.id, "OCS"); 3597 + strcat(info->fix.id, "OCS"); 3565 3598 default_chipset: 3566 3599 chipset = TAG_OCS; 3567 3600 maxdepth[TAG_SHRES] = 0; /* OCS means no SHRES */ ··· 3579 3592 maxdepth[TAG_LORES] = 6; 3580 3593 maxfmode = TAG_FMODE_1; 3581 3594 defmode = amiga_vblank == 50 ? DEFMODE_PAL : DEFMODE_NTSC; 3582 - fb_info.fix.smem_len = VIDEOMEMSIZE_OCS; 3595 + info->fix.smem_len = VIDEOMEMSIZE_OCS; 3583 3596 break; 3584 3597 #endif /* CONFIG_FB_AMIGA_OCS */ 3585 3598 3586 3599 #ifdef CONFIG_FB_AMIGA_ECS 3587 3600 case CS_ECS: 3588 - strcat(fb_info.fix.id, "ECS"); 3601 + strcat(info->fix.id, "ECS"); 3589 3602 chipset = TAG_ECS; 3590 3603 maxdepth[TAG_SHRES] = 2; 3591 3604 maxdepth[TAG_HIRES] = 4; ··· 3599 3612 : DEFMODE_NTSC; 3600 3613 if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT > 3601 3614 VIDEOMEMSIZE_ECS_2M) 3602 - fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_2M; 3615 + info->fix.smem_len = VIDEOMEMSIZE_ECS_2M; 3603 3616 else 3604 - fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_1M; 3617 + info->fix.smem_len = VIDEOMEMSIZE_ECS_1M; 3605 3618 break; 3606 3619 #endif /* CONFIG_FB_AMIGA_ECS */ 3607 3620 3608 3621 #ifdef CONFIG_FB_AMIGA_AGA 3609 3622 case CS_AGA: 3610 - strcat(fb_info.fix.id, "AGA"); 3623 + strcat(info->fix.id, "AGA"); 3611 3624 chipset = TAG_AGA; 3612 3625 maxdepth[TAG_SHRES] = 8; 3613 3626 maxdepth[TAG_HIRES] = 8; ··· 3616 3629 defmode = DEFMODE_AGA; 3617 3630 if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT > 3618 3631 VIDEOMEMSIZE_AGA_2M) 3619 - fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_2M; 3632 + info->fix.smem_len = VIDEOMEMSIZE_AGA_2M; 3620 3633 else 3621 - fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_1M; 3634 + info->fix.smem_len = VIDEOMEMSIZE_AGA_1M; 3622 3635 break; 3623 3636 #endif /* CONFIG_FB_AMIGA_AGA */ 3624 3637 3625 3638 default: 3626 3639 #ifdef CONFIG_FB_AMIGA_OCS 3627 3640 printk("Unknown graphics chipset, defaulting to OCS\n"); 3628 - strcat(fb_info.fix.id, "Unknown"); 3641 + strcat(info->fix.id, "Unknown"); 3629 3642 goto default_chipset; 3630 3643 #else /* CONFIG_FB_AMIGA_OCS */ 3631 3644 err = -ENODEV; 3632 - goto amifb_error; 3645 + goto release; 3633 3646 #endif /* CONFIG_FB_AMIGA_OCS */ 3634 3647 break; 3635 3648 } ··· 3659 3672 } 3660 3673 3661 3674 if (amifb_hfmin) { 3662 - fb_info.monspecs.hfmin = amifb_hfmin; 3663 - fb_info.monspecs.hfmax = amifb_hfmax; 3664 - fb_info.monspecs.vfmin = amifb_vfmin; 3665 - fb_info.monspecs.vfmax = amifb_vfmax; 3675 + info->monspecs.hfmin = amifb_hfmin; 3676 + info->monspecs.hfmax = amifb_hfmax; 3677 + info->monspecs.vfmin = amifb_vfmin; 3678 + info->monspecs.vfmax = amifb_vfmax; 3666 3679 } else { 3667 3680 /* 3668 3681 * These are for a typical Amiga monitor (e.g. A1960) 3669 3682 */ 3670 - fb_info.monspecs.hfmin = 15000; 3671 - fb_info.monspecs.hfmax = 38000; 3672 - fb_info.monspecs.vfmin = 49; 3673 - fb_info.monspecs.vfmax = 90; 3683 + info->monspecs.hfmin = 15000; 3684 + info->monspecs.hfmax = 38000; 3685 + info->monspecs.vfmin = 49; 3686 + info->monspecs.vfmax = 90; 3674 3687 } 3675 3688 3676 - fb_info.fbops = &amifb_ops; 3677 - fb_info.par = &currentpar; 3678 - fb_info.flags = FBINFO_DEFAULT; 3679 - fb_info.device = &pdev->dev; 3689 + info->fbops = &amifb_ops; 3690 + info->flags = FBINFO_DEFAULT; 3691 + info->device = &pdev->dev; 3680 3692 3681 - if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb, 3693 + if (!fb_find_mode(&info->var, info, mode_option, ami_modedb, 3682 3694 NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) { 3683 3695 err = -EINVAL; 3684 - goto amifb_error; 3696 + goto release; 3685 3697 } 3686 3698 3687 3699 fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES, 3688 - &fb_info.modelist); 3700 + &info->modelist); 3689 3701 3690 3702 round_down_bpp = 0; 3691 - chipptr = chipalloc(fb_info.fix.smem_len + SPRITEMEMSIZE + 3703 + chipptr = chipalloc(info->fix.smem_len + SPRITEMEMSIZE + 3692 3704 DUMMYSPRITEMEMSIZE + COPINITSIZE + 3693 3705 4 * COPLISTSIZE); 3694 3706 if (!chipptr) { 3695 3707 err = -ENOMEM; 3696 - goto amifb_error; 3708 + goto release; 3697 3709 } 3698 3710 3699 - assignchunk(videomemory, u_long, chipptr, fb_info.fix.smem_len); 3711 + assignchunk(videomemory, u_long, chipptr, info->fix.smem_len); 3700 3712 assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE); 3701 3713 assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE); 3702 3714 assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE); ··· 3707 3721 /* 3708 3722 * access the videomem with writethrough cache 3709 3723 */ 3710 - fb_info.fix.smem_start = (u_long)ZTWO_PADDR(videomemory); 3711 - videomemory = (u_long)ioremap_writethrough(fb_info.fix.smem_start, 3712 - fb_info.fix.smem_len); 3724 + info->fix.smem_start = (u_long)ZTWO_PADDR(videomemory); 3725 + videomemory = (u_long)ioremap_writethrough(info->fix.smem_start, 3726 + info->fix.smem_len); 3713 3727 if (!videomemory) { 3714 - printk("amifb: WARNING! unable to map videomem cached writethrough\n"); 3715 - fb_info.screen_base = (char *)ZTWO_VADDR(fb_info.fix.smem_start); 3728 + dev_warn(&pdev->dev, 3729 + "Unable to map videomem cached writethrough\n"); 3730 + info->screen_base = (char *)ZTWO_VADDR(info->fix.smem_start); 3716 3731 } else 3717 - fb_info.screen_base = (char *)videomemory; 3732 + info->screen_base = (char *)videomemory; 3718 3733 3719 3734 memset(dummysprite, 0, DUMMYSPRITEMEMSIZE); 3720 3735 ··· 3730 3743 custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER | 3731 3744 DMAF_BLITTER | DMAF_SPRITE; 3732 3745 3733 - if (request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0, 3734 - "fb vertb handler", &currentpar)) { 3735 - err = -EBUSY; 3736 - goto amifb_error; 3737 - } 3738 - 3739 - err = fb_alloc_cmap(&fb_info.cmap, 1 << fb_info.var.bits_per_pixel, 0); 3746 + err = request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0, 3747 + "fb vertb handler", info->par); 3740 3748 if (err) 3741 - goto amifb_error; 3749 + goto disable_dma; 3742 3750 3743 - if (register_framebuffer(&fb_info) < 0) { 3744 - err = -EINVAL; 3745 - goto amifb_error; 3746 - } 3751 + err = fb_alloc_cmap(&info->cmap, 1 << info->var.bits_per_pixel, 0); 3752 + if (err) 3753 + goto free_irq; 3754 + 3755 + dev_set_drvdata(&pdev->dev, info); 3756 + 3757 + err = register_framebuffer(info); 3758 + if (err) 3759 + goto unset_drvdata; 3747 3760 3748 3761 printk("fb%d: %s frame buffer device, using %dK of video memory\n", 3749 - fb_info.node, fb_info.fix.id, fb_info.fix.smem_len>>10); 3762 + info->node, info->fix.id, info->fix.smem_len>>10); 3750 3763 3751 3764 return 0; 3752 3765 3753 - amifb_error: 3754 - amifb_deinit(pdev); 3766 + unset_drvdata: 3767 + dev_set_drvdata(&pdev->dev, NULL); 3768 + fb_dealloc_cmap(&info->cmap); 3769 + free_irq: 3770 + free_irq(IRQ_AMIGA_COPPER, info->par); 3771 + disable_dma: 3772 + custom.dmacon = DMAF_ALL | DMAF_MASTER; 3773 + if (videomemory) 3774 + iounmap((void *)videomemory); 3775 + chipfree(); 3776 + release: 3777 + framebuffer_release(info); 3755 3778 return err; 3756 3779 } 3757 3780 3758 3781 3759 3782 static int __exit amifb_remove(struct platform_device *pdev) 3760 3783 { 3761 - unregister_framebuffer(&fb_info); 3762 - amifb_deinit(pdev); 3784 + struct fb_info *info = dev_get_drvdata(&pdev->dev); 3785 + 3786 + unregister_framebuffer(info); 3787 + dev_set_drvdata(&pdev->dev, NULL); 3788 + fb_dealloc_cmap(&info->cmap); 3789 + free_irq(IRQ_AMIGA_COPPER, info->par); 3790 + custom.dmacon = DMAF_ALL | DMAF_MASTER; 3791 + if (videomemory) 3792 + iounmap((void *)videomemory); 3793 + chipfree(); 3794 + framebuffer_release(info); 3763 3795 amifb_video_off(); 3764 3796 return 0; 3765 3797 }