Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * linux/drivers/video/amifb.c -- Amiga builtin chipset frame buffer device
0003  *
0004  *    Copyright (C) 1995-2003 Geert Uytterhoeven
0005  *
0006  *          with work by Roman Zippel
0007  *
0008  *
0009  * This file is based on the Atari frame buffer device (atafb.c):
0010  *
0011  *    Copyright (C) 1994 Martin Schaller
0012  *                       Roman Hodek
0013  *
0014  *          with work by Andreas Schwab
0015  *                       Guenther Kelleter
0016  *
0017  * and on the original Amiga console driver (amicon.c):
0018  *
0019  *    Copyright (C) 1993 Hamish Macdonald
0020  *                       Greg Harp
0021  *    Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk]
0022  *
0023  *          with work by William Rucklidge (wjr@cs.cornell.edu)
0024  *                       Geert Uytterhoeven
0025  *                       Jes Sorensen (jds@kom.auc.dk)
0026  *
0027  *
0028  * History:
0029  *
0030  *   - 24 Jul 96: Copper generates now vblank interrupt and
0031  *                VESA Power Saving Protocol is fully implemented
0032  *   - 14 Jul 96: Rework and hopefully last ECS bugs fixed
0033  *   -  7 Mar 96: Hardware sprite support by Roman Zippel
0034  *   - 18 Feb 96: OCS and ECS support by Roman Zippel
0035  *                Hardware functions completely rewritten
0036  *   -  2 Dec 95: AGA version by Geert Uytterhoeven
0037  *
0038  * This file is subject to the terms and conditions of the GNU General Public
0039  * License. See the file COPYING in the main directory of this archive
0040  * for more details.
0041  */
0042 
0043 #include <linux/module.h>
0044 #include <linux/kernel.h>
0045 #include <linux/errno.h>
0046 #include <linux/string.h>
0047 #include <linux/mm.h>
0048 #include <linux/delay.h>
0049 #include <linux/interrupt.h>
0050 #include <linux/fb.h>
0051 #include <linux/init.h>
0052 #include <linux/ioport.h>
0053 #include <linux/platform_device.h>
0054 #include <linux/uaccess.h>
0055 
0056 #include <asm/irq.h>
0057 #include <asm/amigahw.h>
0058 #include <asm/amigaints.h>
0059 #include <asm/setup.h>
0060 
0061 #include "c2p.h"
0062 
0063 
0064 #define DEBUG
0065 
0066 #if !defined(CONFIG_FB_AMIGA_OCS) && !defined(CONFIG_FB_AMIGA_ECS) && !defined(CONFIG_FB_AMIGA_AGA)
0067 #define CONFIG_FB_AMIGA_OCS   /* define at least one fb driver, this will change later */
0068 #endif
0069 
0070 #if !defined(CONFIG_FB_AMIGA_OCS)
0071 #  define IS_OCS (0)
0072 #elif defined(CONFIG_FB_AMIGA_ECS) || defined(CONFIG_FB_AMIGA_AGA)
0073 #  define IS_OCS (chipset == TAG_OCS)
0074 #else
0075 #  define CONFIG_FB_AMIGA_OCS_ONLY
0076 #  define IS_OCS (1)
0077 #endif
0078 
0079 #if !defined(CONFIG_FB_AMIGA_ECS)
0080 #  define IS_ECS (0)
0081 #elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_AGA)
0082 #  define IS_ECS (chipset == TAG_ECS)
0083 #else
0084 #  define CONFIG_FB_AMIGA_ECS_ONLY
0085 #  define IS_ECS (1)
0086 #endif
0087 
0088 #if !defined(CONFIG_FB_AMIGA_AGA)
0089 #  define IS_AGA (0)
0090 #elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_ECS)
0091 #  define IS_AGA (chipset == TAG_AGA)
0092 #else
0093 #  define CONFIG_FB_AMIGA_AGA_ONLY
0094 #  define IS_AGA (1)
0095 #endif
0096 
0097 #ifdef DEBUG
0098 #  define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
0099 #else
0100 #  define DPRINTK(fmt, args...)
0101 #endif
0102 
0103 /*******************************************************************************
0104 
0105 
0106    Generic video timings
0107    ---------------------
0108 
0109    Timings used by the frame buffer interface:
0110 
0111    +----------+---------------------------------------------+----------+-------+
0112    |          |                ^                            |          |       |
0113    |          |                |upper_margin                |          |       |
0114    |          |                v                            |          |       |
0115    +----------###############################################----------+-------+
0116    |          #                ^                            #          |       |
0117    |          #                |                            #          |       |
0118    |          #                |                            #          |       |
0119    |          #                |                            #          |       |
0120    |   left   #                |                            #  right   | hsync |
0121    |  margin  #                |       xres                 #  margin  |  len  |
0122    |<-------->#<---------------+--------------------------->#<-------->|<----->|
0123    |          #                |                            #          |       |
0124    |          #                |                            #          |       |
0125    |          #                |                            #          |       |
0126    |          #                |yres                        #          |       |
0127    |          #                |                            #          |       |
0128    |          #                |                            #          |       |
0129    |          #                |                            #          |       |
0130    |          #                |                            #          |       |
0131    |          #                |                            #          |       |
0132    |          #                |                            #          |       |
0133    |          #                |                            #          |       |
0134    |          #                |                            #          |       |
0135    |          #                v                            #          |       |
0136    +----------###############################################----------+-------+
0137    |          |                ^                            |          |       |
0138    |          |                |lower_margin                |          |       |
0139    |          |                v                            |          |       |
0140    +----------+---------------------------------------------+----------+-------+
0141    |          |                ^                            |          |       |
0142    |          |                |vsync_len                   |          |       |
0143    |          |                v                            |          |       |
0144    +----------+---------------------------------------------+----------+-------+
0145 
0146 
0147    Amiga video timings
0148    -------------------
0149 
0150    The Amiga native chipsets uses another timing scheme:
0151 
0152       - hsstrt:   Start of horizontal synchronization pulse
0153       - hsstop:   End of horizontal synchronization pulse
0154       - htotal:   Last value on the line (i.e. line length = htotal + 1)
0155       - vsstrt:   Start of vertical synchronization pulse
0156       - vsstop:   End of vertical synchronization pulse
0157       - vtotal:   Last line value (i.e. number of lines = vtotal + 1)
0158       - hcenter:  Start of vertical retrace for interlace
0159 
0160    You can specify the blanking timings independently. Currently I just set
0161    them equal to the respective synchronization values:
0162 
0163       - hbstrt:   Start of horizontal blank
0164       - hbstop:   End of horizontal blank
0165       - vbstrt:   Start of vertical blank
0166       - vbstop:   End of vertical blank
0167 
0168    Horizontal values are in color clock cycles (280 ns), vertical values are in
0169    scanlines.
0170 
0171    (0, 0) is somewhere in the upper-left corner :-)
0172 
0173 
0174    Amiga visible window definitions
0175    --------------------------------
0176 
0177    Currently I only have values for AGA, SHRES (28 MHz dotclock). Feel free to
0178    make corrections and/or additions.
0179 
0180    Within the above synchronization specifications, the visible window is
0181    defined by the following parameters (actual register resolutions may be
0182    different; all horizontal values are normalized with respect to the pixel
0183    clock):
0184 
0185       - diwstrt_h:   Horizontal start of the visible window
0186       - diwstop_h:   Horizontal stop + 1(*) of the visible window
0187       - diwstrt_v:   Vertical start of the visible window
0188       - diwstop_v:   Vertical stop of the visible window
0189       - ddfstrt:     Horizontal start of display DMA
0190       - ddfstop:     Horizontal stop of display DMA
0191       - hscroll:     Horizontal display output delay
0192 
0193    Sprite positioning:
0194 
0195       - sprstrt_h:   Horizontal start - 4 of sprite
0196       - sprstrt_v:   Vertical start of sprite
0197 
0198    (*) Even Commodore did it wrong in the AGA monitor drivers by not adding 1.
0199 
0200    Horizontal values are in dotclock cycles (35 ns), vertical values are in
0201    scanlines.
0202 
0203    (0, 0) is somewhere in the upper-left corner :-)
0204 
0205 
0206    Dependencies (AGA, SHRES (35 ns dotclock))
0207    -------------------------------------------
0208 
0209    Since there are much more parameters for the Amiga display than for the
0210    frame buffer interface, there must be some dependencies among the Amiga
0211    display parameters. Here's what I found out:
0212 
0213       - ddfstrt and ddfstop are best aligned to 64 pixels.
0214       - the chipset needs 64 + 4 horizontal pixels after the DMA start before
0215     the first pixel is output, so diwstrt_h = ddfstrt + 64 + 4 if you want
0216     to display the first pixel on the line too. Increase diwstrt_h for
0217     virtual screen panning.
0218       - the display DMA always fetches 64 pixels at a time (fmode = 3).
0219       - ddfstop is ddfstrt+#pixels - 64.
0220       - diwstop_h = diwstrt_h + xres + 1. Because of the additional 1 this can
0221     be 1 more than htotal.
0222       - hscroll simply adds a delay to the display output. Smooth horizontal
0223     panning needs an extra 64 pixels on the left to prefetch the pixels that
0224     `fall off' on the left.
0225       - if ddfstrt < 192, the sprite DMA cycles are all stolen by the bitplane
0226     DMA, so it's best to make the DMA start as late as possible.
0227       - you really don't want to make ddfstrt < 128, since this will steal DMA
0228     cycles from the other DMA channels (audio, floppy and Chip RAM refresh).
0229       - I make diwstop_h and diwstop_v as large as possible.
0230 
0231    General dependencies
0232    --------------------
0233 
0234       - all values are SHRES pixel (35ns)
0235 
0236           table 1:fetchstart  table 2:prefetch    table 3:fetchsize
0237           ------------------  ----------------    -----------------
0238    Pixclock     # SHRES|HIRES|LORES # SHRES|HIRES|LORES # SHRES|HIRES|LORES
0239    -------------#------+-----+------#------+-----+------#------+-----+------
0240    Bus width 1x #   16 |  32 |  64  #   16 |  32 |  64  #   64 |  64 |  64
0241    Bus width 2x #   32 |  64 | 128  #   32 |  64 |  64  #   64 |  64 | 128
0242    Bus width 4x #   64 | 128 | 256  #   64 |  64 |  64  #   64 | 128 | 256
0243 
0244       - chipset needs 4 pixels before the first pixel is output
0245       - ddfstrt must be aligned to fetchstart (table 1)
0246       - chipset needs also prefetch (table 2) to get first pixel data, so
0247     ddfstrt = ((diwstrt_h - 4) & -fetchstart) - prefetch
0248       - for horizontal panning decrease diwstrt_h
0249       - the length of a fetchline must be aligned to fetchsize (table 3)
0250       - if fetchstart is smaller than fetchsize, then ddfstrt can a little bit
0251     moved to optimize use of dma (useful for OCS/ECS overscan displays)
0252       - ddfstop is ddfstrt + ddfsize - fetchsize
0253       - If C= didn't change anything for AGA, then at following positions the
0254     dma bus is already used:
0255     ddfstrt <  48 -> memory refresh
0256         <  96 -> disk dma
0257         < 160 -> audio dma
0258         < 192 -> sprite 0 dma
0259         < 416 -> sprite dma (32 per sprite)
0260       - in accordance with the hardware reference manual a hardware stop is at
0261     192, but AGA (ECS?) can go below this.
0262 
0263    DMA priorities
0264    --------------
0265 
0266    Since there are limits on the earliest start value for display DMA and the
0267    display of sprites, I use the following policy on horizontal panning and
0268    the hardware cursor:
0269 
0270       - if you want to start display DMA too early, you lose the ability to
0271     do smooth horizontal panning (xpanstep 1 -> 64).
0272       - if you want to go even further, you lose the hardware cursor too.
0273 
0274    IMHO a hardware cursor is more important for X than horizontal scrolling,
0275    so that's my motivation.
0276 
0277 
0278    Implementation
0279    --------------
0280 
0281    ami_decode_var() converts the frame buffer values to the Amiga values. It's
0282    just a `straightforward' implementation of the above rules.
0283 
0284 
0285    Standard VGA timings
0286    --------------------
0287 
0288            xres  yres    left  right  upper  lower    hsync    vsync
0289            ----  ----    ----  -----  -----  -----    -----    -----
0290       80x25     720   400      27     45     35     12      108        2
0291       80x30     720   480      27     45     30      9      108        2
0292 
0293    These were taken from a XFree86 configuration file, recalculated for a 28 MHz
0294    dotclock (Amigas don't have a 25 MHz dotclock) and converted to frame buffer
0295    generic timings.
0296 
0297    As a comparison, graphics/monitor.h suggests the following:
0298 
0299            xres  yres    left  right  upper  lower    hsync    vsync
0300            ----  ----    ----  -----  -----  -----    -----    -----
0301 
0302       VGA       640   480      52    112     24     19    112 -      2 +
0303       VGA70     640   400      52    112     27     21    112 -      2 -
0304 
0305 
0306    Sync polarities
0307    ---------------
0308 
0309       VSYNC    HSYNC    Vertical size    Vertical total
0310       -----    -----    -------------    --------------
0311     +        +           Reserved          Reserved
0312     +        -                400               414
0313     -        +                350               362
0314     -        -                480               496
0315 
0316    Source: CL-GD542X Technical Reference Manual, Cirrus Logic, Oct 1992
0317 
0318 
0319    Broadcast video timings
0320    -----------------------
0321 
0322    According to the CCIR and RETMA specifications, we have the following values:
0323 
0324    CCIR -> PAL
0325    -----------
0326 
0327       - a scanline is 64 µs long, of which 52.48 µs are visible. This is about
0328     736 visible 70 ns pixels per line.
0329       - we have 625 scanlines, of which 575 are visible (interlaced); after
0330     rounding this becomes 576.
0331 
0332    RETMA -> NTSC
0333    -------------
0334 
0335       - a scanline is 63.5 µs long, of which 53.5 µs are visible.  This is about
0336     736 visible 70 ns pixels per line.
0337       - we have 525 scanlines, of which 485 are visible (interlaced); after
0338     rounding this becomes 484.
0339 
0340    Thus if you want a PAL compatible display, you have to do the following:
0341 
0342       - set the FB_SYNC_BROADCAST flag to indicate that standard broadcast
0343     timings are to be used.
0344       - make sure upper_margin + yres + lower_margin + vsync_len = 625 for an
0345     interlaced, 312 for a non-interlaced and 156 for a doublescanned
0346     display.
0347       - make sure left_margin + xres + right_margin + hsync_len = 1816 for a
0348     SHRES, 908 for a HIRES and 454 for a LORES display.
0349       - the left visible part begins at 360 (SHRES; HIRES:180, LORES:90),
0350     left_margin + 2 * hsync_len must be greater or equal.
0351       - the upper visible part begins at 48 (interlaced; non-interlaced:24,
0352     doublescanned:12), upper_margin + 2 * vsync_len must be greater or
0353     equal.
0354       - ami_encode_var() calculates margins with a hsync of 5320 ns and a vsync
0355     of 4 scanlines
0356 
0357    The settings for a NTSC compatible display are straightforward.
0358 
0359    Note that in a strict sense the PAL and NTSC standards only define the
0360    encoding of the color part (chrominance) of the video signal and don't say
0361    anything about horizontal/vertical synchronization nor refresh rates.
0362 
0363 
0364                                 -- Geert --
0365 
0366 *******************************************************************************/
0367 
0368 
0369     /*
0370      * Custom Chipset Definitions
0371      */
0372 
0373 #define CUSTOM_OFS(fld) ((long)&((struct CUSTOM*)0)->fld)
0374 
0375     /*
0376      * BPLCON0 -- Bitplane Control Register 0
0377      */
0378 
0379 #define BPC0_HIRES  (0x8000)
0380 #define BPC0_BPU2   (0x4000) /* Bit plane used count */
0381 #define BPC0_BPU1   (0x2000)
0382 #define BPC0_BPU0   (0x1000)
0383 #define BPC0_HAM    (0x0800) /* HAM mode */
0384 #define BPC0_DPF    (0x0400) /* Double playfield */
0385 #define BPC0_COLOR  (0x0200) /* Enable colorburst */
0386 #define BPC0_GAUD   (0x0100) /* Genlock audio enable */
0387 #define BPC0_UHRES  (0x0080) /* Ultrahi res enable */
0388 #define BPC0_SHRES  (0x0040) /* Super hi res mode */
0389 #define BPC0_BYPASS (0x0020) /* Bypass LUT - AGA */
0390 #define BPC0_BPU3   (0x0010) /* AGA */
0391 #define BPC0_LPEN   (0x0008) /* Light pen enable */
0392 #define BPC0_LACE   (0x0004) /* Interlace */
0393 #define BPC0_ERSY   (0x0002) /* External resync */
0394 #define BPC0_ECSENA (0x0001) /* ECS enable */
0395 
0396     /*
0397      * BPLCON2 -- Bitplane Control Register 2
0398      */
0399 
0400 #define BPC2_ZDBPSEL2   (0x4000) /* Bitplane to be used for ZD - AGA */
0401 #define BPC2_ZDBPSEL1   (0x2000)
0402 #define BPC2_ZDBPSEL0   (0x1000)
0403 #define BPC2_ZDBPEN (0x0800) /* Enable ZD with ZDBPSELx - AGA */
0404 #define BPC2_ZDCTEN (0x0400) /* Enable ZD with palette bit #31 - AGA */
0405 #define BPC2_KILLEHB    (0x0200) /* Kill EHB mode - AGA */
0406 #define BPC2_RDRAM  (0x0100) /* Color table accesses read, not write - AGA */
0407 #define BPC2_SOGEN  (0x0080) /* SOG output pin high - AGA */
0408 #define BPC2_PF2PRI (0x0040) /* PF2 priority over PF1 */
0409 #define BPC2_PF2P2  (0x0020) /* PF2 priority wrt sprites */
0410 #define BPC2_PF2P1  (0x0010)
0411 #define BPC2_PF2P0  (0x0008)
0412 #define BPC2_PF1P2  (0x0004) /* ditto PF1 */
0413 #define BPC2_PF1P1  (0x0002)
0414 #define BPC2_PF1P0  (0x0001)
0415 
0416     /*
0417      * BPLCON3 -- Bitplane Control Register 3 (AGA)
0418      */
0419 
0420 #define BPC3_BANK2  (0x8000) /* Bits to select color register bank */
0421 #define BPC3_BANK1  (0x4000)
0422 #define BPC3_BANK0  (0x2000)
0423 #define BPC3_PF2OF2 (0x1000) /* Bits for color table offset when PF2 */
0424 #define BPC3_PF2OF1 (0x0800)
0425 #define BPC3_PF2OF0 (0x0400)
0426 #define BPC3_LOCT   (0x0200) /* Color register writes go to low bits */
0427 #define BPC3_SPRES1 (0x0080) /* Sprite resolution bits */
0428 #define BPC3_SPRES0 (0x0040)
0429 #define BPC3_BRDRBLNK   (0x0020) /* Border blanked? */
0430 #define BPC3_BRDRTRAN   (0x0010) /* Border transparent? */
0431 #define BPC3_ZDCLKEN    (0x0004) /* ZD pin is 14 MHz (HIRES) clock output */
0432 #define BPC3_BRDRSPRT   (0x0002) /* Sprites in border? */
0433 #define BPC3_EXTBLKEN   (0x0001) /* BLANK programmable */
0434 
0435     /*
0436      * BPLCON4 -- Bitplane Control Register 4 (AGA)
0437      */
0438 
0439 #define BPC4_BPLAM7 (0x8000) /* bitplane color XOR field */
0440 #define BPC4_BPLAM6 (0x4000)
0441 #define BPC4_BPLAM5 (0x2000)
0442 #define BPC4_BPLAM4 (0x1000)
0443 #define BPC4_BPLAM3 (0x0800)
0444 #define BPC4_BPLAM2 (0x0400)
0445 #define BPC4_BPLAM1 (0x0200)
0446 #define BPC4_BPLAM0 (0x0100)
0447 #define BPC4_ESPRM7 (0x0080) /* 4 high bits for even sprite colors */
0448 #define BPC4_ESPRM6 (0x0040)
0449 #define BPC4_ESPRM5 (0x0020)
0450 #define BPC4_ESPRM4 (0x0010)
0451 #define BPC4_OSPRM7 (0x0008) /* 4 high bits for odd sprite colors */
0452 #define BPC4_OSPRM6 (0x0004)
0453 #define BPC4_OSPRM5 (0x0002)
0454 #define BPC4_OSPRM4 (0x0001)
0455 
0456     /*
0457      * BEAMCON0 -- Beam Control Register
0458      */
0459 
0460 #define BMC0_HARDDIS    (0x4000) /* Disable hardware limits */
0461 #define BMC0_LPENDIS    (0x2000) /* Disable light pen latch */
0462 #define BMC0_VARVBEN    (0x1000) /* Enable variable vertical blank */
0463 #define BMC0_LOLDIS (0x0800) /* Disable long/short line toggle */
0464 #define BMC0_CSCBEN (0x0400) /* Composite sync/blank */
0465 #define BMC0_VARVSYEN   (0x0200) /* Enable variable vertical sync */
0466 #define BMC0_VARHSYEN   (0x0100) /* Enable variable horizontal sync */
0467 #define BMC0_VARBEAMEN  (0x0080) /* Enable variable beam counters */
0468 #define BMC0_DUAL   (0x0040) /* Enable alternate horizontal beam counter */
0469 #define BMC0_PAL    (0x0020) /* Set decodes for PAL */
0470 #define BMC0_VARCSYEN   (0x0010) /* Enable variable composite sync */
0471 #define BMC0_BLANKEN    (0x0008) /* Blank enable (no longer used on AGA) */
0472 #define BMC0_CSYTRUE    (0x0004) /* CSY polarity */
0473 #define BMC0_VSYTRUE    (0x0002) /* VSY polarity */
0474 #define BMC0_HSYTRUE    (0x0001) /* HSY polarity */
0475 
0476 
0477     /*
0478      * FMODE -- Fetch Mode Control Register (AGA)
0479      */
0480 
0481 #define FMODE_SSCAN2    (0x8000) /* Sprite scan-doubling */
0482 #define FMODE_BSCAN2    (0x4000) /* Use PF2 modulus every other line */
0483 #define FMODE_SPAGEM    (0x0008) /* Sprite page mode */
0484 #define FMODE_SPR32 (0x0004) /* Sprite 32 bit fetch */
0485 #define FMODE_BPAGEM    (0x0002) /* Bitplane page mode */
0486 #define FMODE_BPL32 (0x0001) /* Bitplane 32 bit fetch */
0487 
0488     /*
0489      * Tags used to indicate a specific Pixel Clock
0490      *
0491      * clk_shift is the shift value to get the timings in 35 ns units
0492      */
0493 
0494 enum { TAG_SHRES, TAG_HIRES, TAG_LORES };
0495 
0496     /*
0497      * Tags used to indicate the specific chipset
0498      */
0499 
0500 enum { TAG_OCS, TAG_ECS, TAG_AGA };
0501 
0502     /*
0503      * Tags used to indicate the memory bandwidth
0504      */
0505 
0506 enum { TAG_FMODE_1, TAG_FMODE_2, TAG_FMODE_4 };
0507 
0508 
0509     /*
0510      * Clock Definitions, Maximum Display Depth
0511      *
0512      * These depend on the E-Clock or the Chipset, so they are filled in
0513      * dynamically
0514      */
0515 
0516 static u_long pixclock[3];  /* SHRES/HIRES/LORES: index = clk_shift */
0517 static u_short maxdepth[3]; /* SHRES/HIRES/LORES: index = clk_shift */
0518 static u_short maxfmode, chipset;
0519 
0520 
0521     /*
0522      * Broadcast Video Timings
0523      *
0524      * Horizontal values are in 35 ns (SHRES) units
0525      * Vertical values are in interlaced scanlines
0526      */
0527 
0528 #define PAL_DIWSTRT_H   (360)   /* PAL Window Limits */
0529 #define PAL_DIWSTRT_V   (48)
0530 #define PAL_HTOTAL  (1816)
0531 #define PAL_VTOTAL  (625)
0532 
0533 #define NTSC_DIWSTRT_H  (360)   /* NTSC Window Limits */
0534 #define NTSC_DIWSTRT_V  (40)
0535 #define NTSC_HTOTAL (1816)
0536 #define NTSC_VTOTAL (525)
0537 
0538 
0539     /*
0540      * Various macros
0541      */
0542 
0543 #define up2(v)      (((v) + 1) & -2)
0544 #define down2(v)    ((v) & -2)
0545 #define div2(v)     ((v)>>1)
0546 #define mod2(v)     ((v) & 1)
0547 
0548 #define up4(v)      (((v) + 3) & -4)
0549 #define down4(v)    ((v) & -4)
0550 #define mul4(v)     ((v) << 2)
0551 #define div4(v)     ((v)>>2)
0552 #define mod4(v)     ((v) & 3)
0553 
0554 #define up8(v)      (((v) + 7) & -8)
0555 #define down8(v)    ((v) & -8)
0556 #define div8(v)     ((v)>>3)
0557 #define mod8(v)     ((v) & 7)
0558 
0559 #define up16(v)     (((v) + 15) & -16)
0560 #define down16(v)   ((v) & -16)
0561 #define div16(v)    ((v)>>4)
0562 #define mod16(v)    ((v) & 15)
0563 
0564 #define up32(v)     (((v) + 31) & -32)
0565 #define down32(v)   ((v) & -32)
0566 #define div32(v)    ((v)>>5)
0567 #define mod32(v)    ((v) & 31)
0568 
0569 #define up64(v)     (((v) + 63) & -64)
0570 #define down64(v)   ((v) & -64)
0571 #define div64(v)    ((v)>>6)
0572 #define mod64(v)    ((v) & 63)
0573 
0574 #define upx(x, v)   (((v) + (x) - 1) & -(x))
0575 #define downx(x, v) ((v) & -(x))
0576 #define modx(x, v)  ((v) & ((x) - 1))
0577 
0578 /*
0579  * FIXME: Use C variants of the code marked with #ifdef __mc68000__
0580  * in the driver. It shouldn't negatively affect the performance and
0581  * is required for APUS support (once it is re-added to the kernel).
0582  * Needs to be tested on the hardware though..
0583  */
0584 /* if x1 is not a constant, this macro won't make real sense :-) */
0585 #ifdef __mc68000__
0586 #define DIVUL(x1, x2) ({int res; asm("divul %1,%2,%3": "=d" (res): \
0587     "d" (x2), "d" ((long)((x1) / 0x100000000ULL)), "0" ((long)(x1))); res;})
0588 #else
0589 /* We know a bit about the numbers, so we can do it this way */
0590 #define DIVUL(x1, x2) ((((long)((unsigned long long)x1 >> 8) / x2) << 8) + \
0591     ((((long)((unsigned long long)x1 >> 8) % x2) << 8) / x2))
0592 #endif
0593 
0594 #define highw(x)    ((u_long)(x)>>16 & 0xffff)
0595 #define loww(x)     ((u_long)(x) & 0xffff)
0596 
0597 #define custom      amiga_custom
0598 
0599 #define VBlankOn()  custom.intena = IF_SETCLR|IF_COPER
0600 #define VBlankOff() custom.intena = IF_COPER
0601 
0602 
0603     /*
0604      * Chip RAM we reserve for the Frame Buffer
0605      *
0606      * This defines the Maximum Virtual Screen Size
0607      * (Setable per kernel options?)
0608      */
0609 
0610 #define VIDEOMEMSIZE_AGA_2M (1310720) /* AGA (2MB) : max 1280*1024*256  */
0611 #define VIDEOMEMSIZE_AGA_1M (786432)  /* AGA (1MB) : max 1024*768*256   */
0612 #define VIDEOMEMSIZE_ECS_2M (655360)  /* ECS (2MB) : max 1280*1024*16   */
0613 #define VIDEOMEMSIZE_ECS_1M (393216)  /* ECS (1MB) : max 1024*768*16    */
0614 #define VIDEOMEMSIZE_OCS    (262144)  /* OCS       : max ca. 800*600*16 */
0615 
0616 #define SPRITEMEMSIZE       (64 * 64 / 4) /* max 64*64*4 */
0617 #define DUMMYSPRITEMEMSIZE  (8)
0618 static u_long spritememory;
0619 
0620 #define CHIPRAM_SAFETY_LIMIT    (16384)
0621 
0622 static u_long videomemory;
0623 
0624     /*
0625      * This is the earliest allowed start of fetching display data.
0626      * Only if you really want no hardware cursor and audio,
0627      * set this to 128, but let it better at 192
0628      */
0629 
0630 static u_long min_fstrt = 192;
0631 
0632 #define assignchunk(name, type, ptr, size) \
0633 { \
0634     (name) = (type)(ptr); \
0635     ptr += size; \
0636 }
0637 
0638 
0639     /*
0640      * Copper Instructions
0641      */
0642 
0643 #define CMOVE(val, reg)     (CUSTOM_OFS(reg) << 16 | (val))
0644 #define CMOVE2(val, reg)    ((CUSTOM_OFS(reg) + 2) << 16 | (val))
0645 #define CWAIT(x, y)     (((y) & 0x1fe) << 23 | ((x) & 0x7f0) << 13 | 0x0001fffe)
0646 #define CEND            (0xfffffffe)
0647 
0648 
0649 typedef union {
0650     u_long l;
0651     u_short w[2];
0652 } copins;
0653 
0654 static struct copdisplay {
0655     copins *init;
0656     copins *wait;
0657     copins *list[2][2];
0658     copins *rebuild[2];
0659 } copdisplay;
0660 
0661 static u_short currentcop = 0;
0662 
0663     /*
0664      * Hardware Cursor API Definitions
0665      * These used to be in linux/fb.h, but were preliminary and used by
0666      * amifb only anyway
0667      */
0668 
0669 #define FBIOGET_FCURSORINFO     0x4607
0670 #define FBIOGET_VCURSORINFO     0x4608
0671 #define FBIOPUT_VCURSORINFO     0x4609
0672 #define FBIOGET_CURSORSTATE     0x460A
0673 #define FBIOPUT_CURSORSTATE     0x460B
0674 
0675 
0676 struct fb_fix_cursorinfo {
0677     __u16 crsr_width;       /* width and height of the cursor in */
0678     __u16 crsr_height;      /* pixels (zero if no cursor)   */
0679     __u16 crsr_xsize;       /* cursor size in display pixels */
0680     __u16 crsr_ysize;
0681     __u16 crsr_color1;      /* colormap entry for cursor color1 */
0682     __u16 crsr_color2;      /* colormap entry for cursor color2 */
0683 };
0684 
0685 struct fb_var_cursorinfo {
0686     __u16 width;
0687     __u16 height;
0688     __u16 xspot;
0689     __u16 yspot;
0690     __u8 data[1];           /* field with [height][width]        */
0691 };
0692 
0693 struct fb_cursorstate {
0694     __s16 xoffset;
0695     __s16 yoffset;
0696     __u16 mode;
0697 };
0698 
0699 #define FB_CURSOR_OFF       0
0700 #define FB_CURSOR_ON        1
0701 #define FB_CURSOR_FLASH     2
0702 
0703 
0704     /*
0705      * Hardware Cursor
0706      */
0707 
0708 static int cursorrate = 20; /* Number of frames/flash toggle */
0709 static u_short cursorstate = -1;
0710 static u_short cursormode = FB_CURSOR_OFF;
0711 
0712 static u_short *lofsprite, *shfsprite, *dummysprite;
0713 
0714     /*
0715      * Current Video Mode
0716      */
0717 
0718 struct amifb_par {
0719 
0720     /* General Values */
0721 
0722     int xres;       /* vmode */
0723     int yres;       /* vmode */
0724     int vxres;      /* vmode */
0725     int vyres;      /* vmode */
0726     int xoffset;        /* vmode */
0727     int yoffset;        /* vmode */
0728     u_short bpp;        /* vmode */
0729     u_short clk_shift;  /* vmode */
0730     u_short line_shift; /* vmode */
0731     int vmode;      /* vmode */
0732     u_short diwstrt_h;  /* vmode */
0733     u_short diwstop_h;  /* vmode */
0734     u_short diwstrt_v;  /* vmode */
0735     u_short diwstop_v;  /* vmode */
0736     u_long next_line;   /* modulo for next line */
0737     u_long next_plane;  /* modulo for next plane */
0738 
0739     /* Cursor Values */
0740 
0741     struct {
0742         short crsr_x;   /* movecursor */
0743         short crsr_y;   /* movecursor */
0744         short spot_x;
0745         short spot_y;
0746         u_short height;
0747         u_short width;
0748         u_short fmode;
0749     } crsr;
0750 
0751     /* OCS Hardware Registers */
0752 
0753     u_long bplpt0;      /* vmode, pan (Note: physical address) */
0754     u_long bplpt0wrap;  /* vmode, pan (Note: physical address) */
0755     u_short ddfstrt;
0756     u_short ddfstop;
0757     u_short bpl1mod;
0758     u_short bpl2mod;
0759     u_short bplcon0;    /* vmode */
0760     u_short bplcon1;    /* vmode */
0761     u_short htotal;     /* vmode */
0762     u_short vtotal;     /* vmode */
0763 
0764     /* Additional ECS Hardware Registers */
0765 
0766     u_short bplcon3;    /* vmode */
0767     u_short beamcon0;   /* vmode */
0768     u_short hsstrt;     /* vmode */
0769     u_short hsstop;     /* vmode */
0770     u_short hbstrt;     /* vmode */
0771     u_short hbstop;     /* vmode */
0772     u_short vsstrt;     /* vmode */
0773     u_short vsstop;     /* vmode */
0774     u_short vbstrt;     /* vmode */
0775     u_short vbstop;     /* vmode */
0776     u_short hcenter;    /* vmode */
0777 
0778     /* Additional AGA Hardware Registers */
0779 
0780     u_short fmode;      /* vmode */
0781 };
0782 
0783 
0784     /*
0785      *  Saved color entry 0 so we can restore it when unblanking
0786      */
0787 
0788 static u_char red0, green0, blue0;
0789 
0790 
0791 #if defined(CONFIG_FB_AMIGA_ECS)
0792 static u_short ecs_palette[32];
0793 #endif
0794 
0795 
0796     /*
0797      * Latches for Display Changes during VBlank
0798      */
0799 
0800 static u_short do_vmode_full = 0;   /* Change the Video Mode */
0801 static u_short do_vmode_pan = 0;    /* Update the Video Mode */
0802 static short do_blank = 0;      /* (Un)Blank the Screen (±1) */
0803 static u_short do_cursor = 0;       /* Move the Cursor */
0804 
0805 
0806     /*
0807      * Various Flags
0808      */
0809 
0810 static u_short is_blanked = 0;      /* Screen is Blanked */
0811 static u_short is_lace = 0;     /* Screen is laced */
0812 
0813     /*
0814      * Predefined Video Modes
0815      *
0816      */
0817 
0818 static struct fb_videomode ami_modedb[] __initdata = {
0819 
0820     /*
0821      *  AmigaOS Video Modes
0822      *
0823      *  If you change these, make sure to update DEFMODE_* as well!
0824      */
0825 
0826     {
0827         /* 640x200, 15 kHz, 60 Hz (NTSC) */
0828         "ntsc", 60, 640, 200, TAG_HIRES, 106, 86, 44, 16, 76, 2,
0829         FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0830     }, {
0831         /* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */
0832         "ntsc-lace", 60, 640, 400, TAG_HIRES, 106, 86, 88, 33, 76, 4,
0833         FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
0834     }, {
0835         /* 640x256, 15 kHz, 50 Hz (PAL) */
0836         "pal", 50, 640, 256, TAG_HIRES, 106, 86, 40, 14, 76, 2,
0837         FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0838     }, {
0839         /* 640x512, 15 kHz, 50 Hz interlaced (PAL) */
0840         "pal-lace", 50, 640, 512, TAG_HIRES, 106, 86, 80, 29, 76, 4,
0841         FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
0842     }, {
0843         /* 640x480, 29 kHz, 57 Hz */
0844         "multiscan", 57, 640, 480, TAG_SHRES, 96, 112, 29, 8, 72, 8,
0845         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0846     }, {
0847         /* 640x960, 29 kHz, 57 Hz interlaced */
0848         "multiscan-lace", 57, 640, 960, TAG_SHRES, 96, 112, 58, 16, 72,
0849         16,
0850         0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
0851     }, {
0852         /* 640x200, 15 kHz, 72 Hz */
0853         "euro36", 72, 640, 200, TAG_HIRES, 92, 124, 6, 6, 52, 5,
0854         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0855     }, {
0856         /* 640x400, 15 kHz, 72 Hz interlaced */
0857         "euro36-lace", 72, 640, 400, TAG_HIRES, 92, 124, 12, 12, 52,
0858         10,
0859         0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
0860     }, {
0861         /* 640x400, 29 kHz, 68 Hz */
0862         "euro72", 68, 640, 400, TAG_SHRES, 164, 92, 9, 9, 80, 8,
0863         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0864     }, {
0865         /* 640x800, 29 kHz, 68 Hz interlaced */
0866         "euro72-lace", 68, 640, 800, TAG_SHRES, 164, 92, 18, 18, 80,
0867         16,
0868         0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
0869     }, {
0870         /* 800x300, 23 kHz, 70 Hz */
0871         "super72", 70, 800, 300, TAG_SHRES, 212, 140, 10, 11, 80, 7,
0872         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0873     }, {
0874         /* 800x600, 23 kHz, 70 Hz interlaced */
0875         "super72-lace", 70, 800, 600, TAG_SHRES, 212, 140, 20, 22, 80,
0876         14,
0877         0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
0878     }, {
0879         /* 640x200, 27 kHz, 57 Hz doublescan */
0880         "dblntsc", 57, 640, 200, TAG_SHRES, 196, 124, 18, 17, 80, 4,
0881         0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
0882     }, {
0883         /* 640x400, 27 kHz, 57 Hz */
0884         "dblntsc-ff", 57, 640, 400, TAG_SHRES, 196, 124, 36, 35, 80, 7,
0885         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0886     }, {
0887         /* 640x800, 27 kHz, 57 Hz interlaced */
0888         "dblntsc-lace", 57, 640, 800, TAG_SHRES, 196, 124, 72, 70, 80,
0889         14,
0890         0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
0891     }, {
0892         /* 640x256, 27 kHz, 47 Hz doublescan */
0893         "dblpal", 47, 640, 256, TAG_SHRES, 196, 124, 14, 13, 80, 4,
0894         0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
0895     }, {
0896         /* 640x512, 27 kHz, 47 Hz */
0897         "dblpal-ff", 47, 640, 512, TAG_SHRES, 196, 124, 28, 27, 80, 7,
0898         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0899     }, {
0900         /* 640x1024, 27 kHz, 47 Hz interlaced */
0901         "dblpal-lace", 47, 640, 1024, TAG_SHRES, 196, 124, 56, 54, 80,
0902         14,
0903         0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
0904     },
0905 
0906     /*
0907      *  VGA Video Modes
0908      */
0909 
0910     {
0911         /* 640x480, 31 kHz, 60 Hz (VGA) */
0912         "vga", 60, 640, 480, TAG_SHRES, 64, 96, 30, 9, 112, 2,
0913         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0914     }, {
0915         /* 640x400, 31 kHz, 70 Hz (VGA) */
0916         "vga70", 70, 640, 400, TAG_SHRES, 64, 96, 35, 12, 112, 2,
0917         FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT,
0918         FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0919     },
0920 
0921 #if 0
0922 
0923     /*
0924      *  A2024 video modes
0925      *  These modes don't work yet because there's no A2024 driver.
0926      */
0927 
0928     {
0929         /* 1024x800, 10 Hz */
0930         "a2024-10", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
0931         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0932     }, {
0933         /* 1024x800, 15 Hz */
0934         "a2024-15", 15, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
0935         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0936     }
0937 #endif
0938 };
0939 
0940 #define NUM_TOTAL_MODES  ARRAY_SIZE(ami_modedb)
0941 
0942 static char *mode_option __initdata = NULL;
0943 static int round_down_bpp = 1;  /* for mode probing */
0944 
0945     /*
0946      * Some default modes
0947      */
0948 
0949 
0950 #define DEFMODE_PAL     2   /* "pal" for PAL OCS/ECS */
0951 #define DEFMODE_NTSC        0   /* "ntsc" for NTSC OCS/ECS */
0952 #define DEFMODE_AMBER_PAL   3   /* "pal-lace" for flicker fixed PAL (A3000) */
0953 #define DEFMODE_AMBER_NTSC  1   /* "ntsc-lace" for flicker fixed NTSC (A3000) */
0954 #define DEFMODE_AGA     19  /* "vga70" for AGA */
0955 
0956 
0957 static int amifb_ilbm = 0;  /* interleaved or normal bitplanes */
0958 
0959 static u32 amifb_hfmin __initdata;  /* monitor hfreq lower limit (Hz) */
0960 static u32 amifb_hfmax __initdata;  /* monitor hfreq upper limit (Hz) */
0961 static u16 amifb_vfmin __initdata;  /* monitor vfreq lower limit (Hz) */
0962 static u16 amifb_vfmax __initdata;  /* monitor vfreq upper limit (Hz) */
0963 
0964 
0965     /*
0966      * Macros for the conversion from real world values to hardware register
0967      * values
0968      *
0969      * This helps us to keep our attention on the real stuff...
0970      *
0971      * Hardware limits for AGA:
0972      *
0973      *  parameter  min    max  step
0974      *  ---------  ---   ----  ----
0975      *  diwstrt_h    0   2047     1
0976      *  diwstrt_v    0   2047     1
0977      *  diwstop_h    0   4095     1
0978      *  diwstop_v    0   4095     1
0979      *
0980      *  ddfstrt      0   2032    16
0981      *  ddfstop      0   2032    16
0982      *
0983      *  htotal       8   2048     8
0984      *  hsstrt       0   2040     8
0985      *  hsstop       0   2040     8
0986      *  vtotal       1   4096     1
0987      *  vsstrt       0   4095     1
0988      *  vsstop       0   4095     1
0989      *  hcenter      0   2040     8
0990      *
0991      *  hbstrt       0   2047     1
0992      *  hbstop       0   2047     1
0993      *  vbstrt       0   4095     1
0994      *  vbstop       0   4095     1
0995      *
0996      * Horizontal values are in 35 ns (SHRES) pixels
0997      * Vertical values are in half scanlines
0998      */
0999 
1000 /* bplcon1 (smooth scrolling) */
1001 
1002 #define hscroll2hw(hscroll) \
1003     (((hscroll) << 12 & 0x3000) | ((hscroll) << 8 & 0xc300) | \
1004      ((hscroll) << 4 & 0x0c00) | ((hscroll) << 2 & 0x00f0) | \
1005      ((hscroll)>>2 & 0x000f))
1006 
1007 /* diwstrt/diwstop/diwhigh (visible display window) */
1008 
1009 #define diwstrt2hw(diwstrt_h, diwstrt_v) \
1010     (((diwstrt_v) << 7 & 0xff00) | ((diwstrt_h)>>2 & 0x00ff))
1011 #define diwstop2hw(diwstop_h, diwstop_v) \
1012     (((diwstop_v) << 7 & 0xff00) | ((diwstop_h)>>2 & 0x00ff))
1013 #define diwhigh2hw(diwstrt_h, diwstrt_v, diwstop_h, diwstop_v) \
1014     (((diwstop_h) << 3 & 0x2000) | ((diwstop_h) << 11 & 0x1800) | \
1015      ((diwstop_v)>>1 & 0x0700) | ((diwstrt_h)>>5 & 0x0020) | \
1016      ((diwstrt_h) << 3 & 0x0018) | ((diwstrt_v)>>9 & 0x0007))
1017 
1018 /* ddfstrt/ddfstop (display DMA) */
1019 
1020 #define ddfstrt2hw(ddfstrt) div8(ddfstrt)
1021 #define ddfstop2hw(ddfstop) div8(ddfstop)
1022 
1023 /* hsstrt/hsstop/htotal/vsstrt/vsstop/vtotal/hcenter (sync timings) */
1024 
1025 #define hsstrt2hw(hsstrt)   (div8(hsstrt))
1026 #define hsstop2hw(hsstop)   (div8(hsstop))
1027 #define htotal2hw(htotal)   (div8(htotal) - 1)
1028 #define vsstrt2hw(vsstrt)   (div2(vsstrt))
1029 #define vsstop2hw(vsstop)   (div2(vsstop))
1030 #define vtotal2hw(vtotal)   (div2(vtotal) - 1)
1031 #define hcenter2hw(htotal)  (div8(htotal))
1032 
1033 /* hbstrt/hbstop/vbstrt/vbstop (blanking timings) */
1034 
1035 #define hbstrt2hw(hbstrt)   (((hbstrt) << 8 & 0x0700) | ((hbstrt)>>3 & 0x00ff))
1036 #define hbstop2hw(hbstop)   (((hbstop) << 8 & 0x0700) | ((hbstop)>>3 & 0x00ff))
1037 #define vbstrt2hw(vbstrt)   (div2(vbstrt))
1038 #define vbstop2hw(vbstop)   (div2(vbstop))
1039 
1040 /* colour */
1041 
1042 #define rgb2hw8_high(red, green, blue) \
1043     (((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0)>>4))
1044 #define rgb2hw8_low(red, green, blue) \
1045     (((red & 0x0f) << 8) | ((green & 0x0f) << 4) | (blue & 0x0f))
1046 #define rgb2hw4(red, green, blue) \
1047     (((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0)>>4))
1048 #define rgb2hw2(red, green, blue) \
1049     (((red & 0xc0) << 4) | (green & 0xc0) | ((blue & 0xc0)>>4))
1050 
1051 /* sprpos/sprctl (sprite positioning) */
1052 
1053 #define spr2hw_pos(start_v, start_h) \
1054     (((start_v) << 7 & 0xff00) | ((start_h)>>3 & 0x00ff))
1055 #define spr2hw_ctl(start_v, start_h, stop_v) \
1056     (((stop_v) << 7 & 0xff00) | ((start_v)>>4 & 0x0040) | \
1057      ((stop_v)>>5 & 0x0020) | ((start_h) << 3 & 0x0018) | \
1058      ((start_v)>>7 & 0x0004) | ((stop_v)>>8 & 0x0002) | \
1059      ((start_h)>>2 & 0x0001))
1060 
1061 /* get current vertical position of beam */
1062 #define get_vbpos() ((u_short)((*(u_long volatile *)&custom.vposr >> 7) & 0xffe))
1063 
1064     /*
1065      * Copper Initialisation List
1066      */
1067 
1068 #define COPINITSIZE (sizeof(copins) * 40)
1069 
1070 enum {
1071     cip_bplcon0
1072 };
1073 
1074     /*
1075      * Long Frame/Short Frame Copper List
1076      * Don't change the order, build_copper()/rebuild_copper() rely on this
1077      */
1078 
1079 #define COPLISTSIZE (sizeof(copins) * 64)
1080 
1081 enum {
1082     cop_wait, cop_bplcon0,
1083     cop_spr0ptrh, cop_spr0ptrl,
1084     cop_diwstrt, cop_diwstop,
1085     cop_diwhigh,
1086 };
1087 
1088     /*
1089      * Pixel modes for Bitplanes and Sprites
1090      */
1091 
1092 static u_short bplpixmode[3] = {
1093     BPC0_SHRES,         /*  35 ns */
1094     BPC0_HIRES,         /*  70 ns */
1095     0               /* 140 ns */
1096 };
1097 
1098 static u_short sprpixmode[3] = {
1099     BPC3_SPRES1 | BPC3_SPRES0,  /*  35 ns */
1100     BPC3_SPRES1,            /*  70 ns */
1101     BPC3_SPRES0         /* 140 ns */
1102 };
1103 
1104     /*
1105      * Fetch modes for Bitplanes and Sprites
1106      */
1107 
1108 static u_short bplfetchmode[3] = {
1109     0,              /* 1x */
1110     FMODE_BPL32,            /* 2x */
1111     FMODE_BPAGEM | FMODE_BPL32  /* 4x */
1112 };
1113 
1114 static u_short sprfetchmode[3] = {
1115     0,              /* 1x */
1116     FMODE_SPR32,            /* 2x */
1117     FMODE_SPAGEM | FMODE_SPR32  /* 4x */
1118 };
1119 
1120 
1121 /* --------------------------- Hardware routines --------------------------- */
1122 
1123     /*
1124      * Get the video params out of `var'. If a value doesn't fit, round
1125      * it up, if it's too big, return -EINVAL.
1126      */
1127 
1128 static int ami_decode_var(struct fb_var_screeninfo *var, struct amifb_par *par,
1129               const struct fb_info *info)
1130 {
1131     u_short clk_shift, line_shift;
1132     u_long maxfetchstop, fstrt, fsize, fconst, xres_n, yres_n;
1133     u_int htotal, vtotal;
1134 
1135     /*
1136      * Find a matching Pixel Clock
1137      */
1138 
1139     for (clk_shift = TAG_SHRES; clk_shift <= TAG_LORES; clk_shift++)
1140         if (var->pixclock <= pixclock[clk_shift])
1141             break;
1142     if (clk_shift > TAG_LORES) {
1143         DPRINTK("pixclock too high\n");
1144         return -EINVAL;
1145     }
1146     par->clk_shift = clk_shift;
1147 
1148     /*
1149      * Check the Geometry Values
1150      */
1151 
1152     if ((par->xres = var->xres) < 64)
1153         par->xres = 64;
1154     if ((par->yres = var->yres) < 64)
1155         par->yres = 64;
1156     if ((par->vxres = var->xres_virtual) < par->xres)
1157         par->vxres = par->xres;
1158     if ((par->vyres = var->yres_virtual) < par->yres)
1159         par->vyres = par->yres;
1160 
1161     par->bpp = var->bits_per_pixel;
1162     if (!var->nonstd) {
1163         if (par->bpp < 1)
1164             par->bpp = 1;
1165         if (par->bpp > maxdepth[clk_shift]) {
1166             if (round_down_bpp && maxdepth[clk_shift])
1167                 par->bpp = maxdepth[clk_shift];
1168             else {
1169                 DPRINTK("invalid bpp\n");
1170                 return -EINVAL;
1171             }
1172         }
1173     } else if (var->nonstd == FB_NONSTD_HAM) {
1174         if (par->bpp < 6)
1175             par->bpp = 6;
1176         if (par->bpp != 6) {
1177             if (par->bpp < 8)
1178                 par->bpp = 8;
1179             if (par->bpp != 8 || !IS_AGA) {
1180                 DPRINTK("invalid bpp for ham mode\n");
1181                 return -EINVAL;
1182             }
1183         }
1184     } else {
1185         DPRINTK("unknown nonstd mode\n");
1186         return -EINVAL;
1187     }
1188 
1189     /*
1190      * FB_VMODE_SMOOTH_XPAN will be cleared, if one of the following
1191      * checks failed and smooth scrolling is not possible
1192      */
1193 
1194     par->vmode = var->vmode | FB_VMODE_SMOOTH_XPAN;
1195     switch (par->vmode & FB_VMODE_MASK) {
1196     case FB_VMODE_INTERLACED:
1197         line_shift = 0;
1198         break;
1199     case FB_VMODE_NONINTERLACED:
1200         line_shift = 1;
1201         break;
1202     case FB_VMODE_DOUBLE:
1203         if (!IS_AGA) {
1204             DPRINTK("double mode only possible with aga\n");
1205             return -EINVAL;
1206         }
1207         line_shift = 2;
1208         break;
1209     default:
1210         DPRINTK("unknown video mode\n");
1211         return -EINVAL;
1212         break;
1213     }
1214     par->line_shift = line_shift;
1215 
1216     /*
1217      * Vertical and Horizontal Timings
1218      */
1219 
1220     xres_n = par->xres << clk_shift;
1221     yres_n = par->yres << line_shift;
1222     par->htotal = down8((var->left_margin + par->xres + var->right_margin +
1223                  var->hsync_len) << clk_shift);
1224     par->vtotal =
1225         down2(((var->upper_margin + par->yres + var->lower_margin +
1226             var->vsync_len) << line_shift) + 1);
1227 
1228     if (IS_AGA)
1229         par->bplcon3 = sprpixmode[clk_shift];
1230     else
1231         par->bplcon3 = 0;
1232     if (var->sync & FB_SYNC_BROADCAST) {
1233         par->diwstop_h = par->htotal -
1234             ((var->right_margin - var->hsync_len) << clk_shift);
1235         if (IS_AGA)
1236             par->diwstop_h += mod4(var->hsync_len);
1237         else
1238             par->diwstop_h = down4(par->diwstop_h);
1239 
1240         par->diwstrt_h = par->diwstop_h - xres_n;
1241         par->diwstop_v = par->vtotal -
1242             ((var->lower_margin - var->vsync_len) << line_shift);
1243         par->diwstrt_v = par->diwstop_v - yres_n;
1244         if (par->diwstop_h >= par->htotal + 8) {
1245             DPRINTK("invalid diwstop_h\n");
1246             return -EINVAL;
1247         }
1248         if (par->diwstop_v > par->vtotal) {
1249             DPRINTK("invalid diwstop_v\n");
1250             return -EINVAL;
1251         }
1252 
1253         if (!IS_OCS) {
1254             /* Initialize sync with some reasonable values for pwrsave */
1255             par->hsstrt = 160;
1256             par->hsstop = 320;
1257             par->vsstrt = 30;
1258             par->vsstop = 34;
1259         } else {
1260             par->hsstrt = 0;
1261             par->hsstop = 0;
1262             par->vsstrt = 0;
1263             par->vsstop = 0;
1264         }
1265         if (par->vtotal > (PAL_VTOTAL + NTSC_VTOTAL) / 2) {
1266             /* PAL video mode */
1267             if (par->htotal != PAL_HTOTAL) {
1268                 DPRINTK("htotal invalid for pal\n");
1269                 return -EINVAL;
1270             }
1271             if (par->diwstrt_h < PAL_DIWSTRT_H) {
1272                 DPRINTK("diwstrt_h too low for pal\n");
1273                 return -EINVAL;
1274             }
1275             if (par->diwstrt_v < PAL_DIWSTRT_V) {
1276                 DPRINTK("diwstrt_v too low for pal\n");
1277                 return -EINVAL;
1278             }
1279             htotal = PAL_HTOTAL>>clk_shift;
1280             vtotal = PAL_VTOTAL>>1;
1281             if (!IS_OCS) {
1282                 par->beamcon0 = BMC0_PAL;
1283                 par->bplcon3 |= BPC3_BRDRBLNK;
1284             } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
1285                    AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
1286                 par->beamcon0 = BMC0_PAL;
1287                 par->hsstop = 1;
1288             } else if (amiga_vblank != 50) {
1289                 DPRINTK("pal not supported by this chipset\n");
1290                 return -EINVAL;
1291             }
1292         } else {
1293             /* NTSC video mode
1294              * In the AGA chipset seems to be hardware bug with BPC3_BRDRBLNK
1295              * and NTSC activated, so than better let diwstop_h <= 1812
1296              */
1297             if (par->htotal != NTSC_HTOTAL) {
1298                 DPRINTK("htotal invalid for ntsc\n");
1299                 return -EINVAL;
1300             }
1301             if (par->diwstrt_h < NTSC_DIWSTRT_H) {
1302                 DPRINTK("diwstrt_h too low for ntsc\n");
1303                 return -EINVAL;
1304             }
1305             if (par->diwstrt_v < NTSC_DIWSTRT_V) {
1306                 DPRINTK("diwstrt_v too low for ntsc\n");
1307                 return -EINVAL;
1308             }
1309             htotal = NTSC_HTOTAL>>clk_shift;
1310             vtotal = NTSC_VTOTAL>>1;
1311             if (!IS_OCS) {
1312                 par->beamcon0 = 0;
1313                 par->bplcon3 |= BPC3_BRDRBLNK;
1314             } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
1315                    AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
1316                 par->beamcon0 = 0;
1317                 par->hsstop = 1;
1318             } else if (amiga_vblank != 60) {
1319                 DPRINTK("ntsc not supported by this chipset\n");
1320                 return -EINVAL;
1321             }
1322         }
1323         if (IS_OCS) {
1324             if (par->diwstrt_h >= 1024 || par->diwstop_h < 1024 ||
1325                 par->diwstrt_v >=  512 || par->diwstop_v <  256) {
1326                 DPRINTK("invalid position for display on ocs\n");
1327                 return -EINVAL;
1328             }
1329         }
1330     } else if (!IS_OCS) {
1331         /* Programmable video mode */
1332         par->hsstrt = var->right_margin << clk_shift;
1333         par->hsstop = (var->right_margin + var->hsync_len) << clk_shift;
1334         par->diwstop_h = par->htotal - mod8(par->hsstrt) + 8 - (1 << clk_shift);
1335         if (!IS_AGA)
1336             par->diwstop_h = down4(par->diwstop_h) - 16;
1337         par->diwstrt_h = par->diwstop_h - xres_n;
1338         par->hbstop = par->diwstrt_h + 4;
1339         par->hbstrt = par->diwstop_h + 4;
1340         if (par->hbstrt >= par->htotal + 8)
1341             par->hbstrt -= par->htotal;
1342         par->hcenter = par->hsstrt + (par->htotal >> 1);
1343         par->vsstrt = var->lower_margin << line_shift;
1344         par->vsstop = (var->lower_margin + var->vsync_len) << line_shift;
1345         par->diwstop_v = par->vtotal;
1346         if ((par->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
1347             par->diwstop_v -= 2;
1348         par->diwstrt_v = par->diwstop_v - yres_n;
1349         par->vbstop = par->diwstrt_v - 2;
1350         par->vbstrt = par->diwstop_v - 2;
1351         if (par->vtotal > 2048) {
1352             DPRINTK("vtotal too high\n");
1353             return -EINVAL;
1354         }
1355         if (par->htotal > 2048) {
1356             DPRINTK("htotal too high\n");
1357             return -EINVAL;
1358         }
1359         par->bplcon3 |= BPC3_EXTBLKEN;
1360         par->beamcon0 = BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS |
1361                 BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN |
1362                 BMC0_PAL | BMC0_VARCSYEN;
1363         if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1364             par->beamcon0 |= BMC0_HSYTRUE;
1365         if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1366             par->beamcon0 |= BMC0_VSYTRUE;
1367         if (var->sync & FB_SYNC_COMP_HIGH_ACT)
1368             par->beamcon0 |= BMC0_CSYTRUE;
1369         htotal = par->htotal>>clk_shift;
1370         vtotal = par->vtotal>>1;
1371     } else {
1372         DPRINTK("only broadcast modes possible for ocs\n");
1373         return -EINVAL;
1374     }
1375 
1376     /*
1377      * Checking the DMA timing
1378      */
1379 
1380     fconst = 16 << maxfmode << clk_shift;
1381 
1382     /*
1383      * smallest window start value without turn off other dma cycles
1384      * than sprite1-7, unless you change min_fstrt
1385      */
1386 
1387 
1388     fsize = ((maxfmode + clk_shift <= 1) ? fconst : 64);
1389     fstrt = downx(fconst, par->diwstrt_h - 4) - fsize;
1390     if (fstrt < min_fstrt) {
1391         DPRINTK("fetch start too low\n");
1392         return -EINVAL;
1393     }
1394 
1395     /*
1396      * smallest window start value where smooth scrolling is possible
1397      */
1398 
1399     fstrt = downx(fconst, par->diwstrt_h - fconst + (1 << clk_shift) - 4) -
1400         fsize;
1401     if (fstrt < min_fstrt)
1402         par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
1403 
1404     maxfetchstop = down16(par->htotal - 80);
1405 
1406     fstrt = downx(fconst, par->diwstrt_h - 4) - 64 - fconst;
1407     fsize = upx(fconst, xres_n +
1408             modx(fconst, downx(1 << clk_shift, par->diwstrt_h - 4)));
1409     if (fstrt + fsize > maxfetchstop)
1410         par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
1411 
1412     fsize = upx(fconst, xres_n);
1413     if (fstrt + fsize > maxfetchstop) {
1414         DPRINTK("fetch stop too high\n");
1415         return -EINVAL;
1416     }
1417 
1418     if (maxfmode + clk_shift <= 1) {
1419         fsize = up64(xres_n + fconst - 1);
1420         if (min_fstrt + fsize - 64 > maxfetchstop)
1421             par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
1422 
1423         fsize = up64(xres_n);
1424         if (min_fstrt + fsize - 64 > maxfetchstop) {
1425             DPRINTK("fetch size too high\n");
1426             return -EINVAL;
1427         }
1428 
1429         fsize -= 64;
1430     } else
1431         fsize -= fconst;
1432 
1433     /*
1434      * Check if there is enough time to update the bitplane pointers for ywrap
1435      */
1436 
1437     if (par->htotal - fsize - 64 < par->bpp * 64)
1438         par->vmode &= ~FB_VMODE_YWRAP;
1439 
1440     /*
1441      * Bitplane calculations and check the Memory Requirements
1442      */
1443 
1444     if (amifb_ilbm) {
1445         par->next_plane = div8(upx(16 << maxfmode, par->vxres));
1446         par->next_line = par->bpp * par->next_plane;
1447         if (par->next_line * par->vyres > info->fix.smem_len) {
1448             DPRINTK("too few video mem\n");
1449             return -EINVAL;
1450         }
1451     } else {
1452         par->next_line = div8(upx(16 << maxfmode, par->vxres));
1453         par->next_plane = par->vyres * par->next_line;
1454         if (par->next_plane * par->bpp > info->fix.smem_len) {
1455             DPRINTK("too few video mem\n");
1456             return -EINVAL;
1457         }
1458     }
1459 
1460     /*
1461      * Hardware Register Values
1462      */
1463 
1464     par->bplcon0 = BPC0_COLOR | bplpixmode[clk_shift];
1465     if (!IS_OCS)
1466         par->bplcon0 |= BPC0_ECSENA;
1467     if (par->bpp == 8)
1468         par->bplcon0 |= BPC0_BPU3;
1469     else
1470         par->bplcon0 |= par->bpp << 12;
1471     if (var->nonstd == FB_NONSTD_HAM)
1472         par->bplcon0 |= BPC0_HAM;
1473     if (var->sync & FB_SYNC_EXT)
1474         par->bplcon0 |= BPC0_ERSY;
1475 
1476     if (IS_AGA)
1477         par->fmode = bplfetchmode[maxfmode];
1478 
1479     switch (par->vmode & FB_VMODE_MASK) {
1480     case FB_VMODE_INTERLACED:
1481         par->bplcon0 |= BPC0_LACE;
1482         break;
1483     case FB_VMODE_DOUBLE:
1484         if (IS_AGA)
1485             par->fmode |= FMODE_SSCAN2 | FMODE_BSCAN2;
1486         break;
1487     }
1488 
1489     if (!((par->vmode ^ var->vmode) & FB_VMODE_YWRAP)) {
1490         par->xoffset = var->xoffset;
1491         par->yoffset = var->yoffset;
1492         if (par->vmode & FB_VMODE_YWRAP) {
1493             if (par->yoffset >= par->vyres)
1494                 par->xoffset = par->yoffset = 0;
1495         } else {
1496             if (par->xoffset > upx(16 << maxfmode, par->vxres - par->xres) ||
1497                 par->yoffset > par->vyres - par->yres)
1498                 par->xoffset = par->yoffset = 0;
1499         }
1500     } else
1501         par->xoffset = par->yoffset = 0;
1502 
1503     par->crsr.crsr_x = par->crsr.crsr_y = 0;
1504     par->crsr.spot_x = par->crsr.spot_y = 0;
1505     par->crsr.height = par->crsr.width = 0;
1506 
1507     return 0;
1508 }
1509 
1510     /*
1511      * Fill the `var' structure based on the values in `par' and maybe
1512      * other values read out of the hardware.
1513      */
1514 
1515 static void ami_encode_var(struct fb_var_screeninfo *var,
1516                struct amifb_par *par)
1517 {
1518     u_short clk_shift, line_shift;
1519 
1520     memset(var, 0, sizeof(struct fb_var_screeninfo));
1521 
1522     clk_shift = par->clk_shift;
1523     line_shift = par->line_shift;
1524 
1525     var->xres = par->xres;
1526     var->yres = par->yres;
1527     var->xres_virtual = par->vxres;
1528     var->yres_virtual = par->vyres;
1529     var->xoffset = par->xoffset;
1530     var->yoffset = par->yoffset;
1531 
1532     var->bits_per_pixel = par->bpp;
1533     var->grayscale = 0;
1534 
1535     var->red.offset = 0;
1536     var->red.msb_right = 0;
1537     var->red.length = par->bpp;
1538     if (par->bplcon0 & BPC0_HAM)
1539         var->red.length -= 2;
1540     var->blue = var->green = var->red;
1541     var->transp.offset = 0;
1542     var->transp.length = 0;
1543     var->transp.msb_right = 0;
1544 
1545     if (par->bplcon0 & BPC0_HAM)
1546         var->nonstd = FB_NONSTD_HAM;
1547     else
1548         var->nonstd = 0;
1549     var->activate = 0;
1550 
1551     var->height = -1;
1552     var->width = -1;
1553 
1554     var->pixclock = pixclock[clk_shift];
1555 
1556     if (IS_AGA && par->fmode & FMODE_BSCAN2)
1557         var->vmode = FB_VMODE_DOUBLE;
1558     else if (par->bplcon0 & BPC0_LACE)
1559         var->vmode = FB_VMODE_INTERLACED;
1560     else
1561         var->vmode = FB_VMODE_NONINTERLACED;
1562 
1563     if (!IS_OCS && par->beamcon0 & BMC0_VARBEAMEN) {
1564         var->hsync_len = (par->hsstop - par->hsstrt)>>clk_shift;
1565         var->right_margin = par->hsstrt>>clk_shift;
1566         var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
1567         var->vsync_len = (par->vsstop - par->vsstrt)>>line_shift;
1568         var->lower_margin = par->vsstrt>>line_shift;
1569         var->upper_margin = (par->vtotal>>line_shift) - var->yres - var->lower_margin - var->vsync_len;
1570         var->sync = 0;
1571         if (par->beamcon0 & BMC0_HSYTRUE)
1572             var->sync |= FB_SYNC_HOR_HIGH_ACT;
1573         if (par->beamcon0 & BMC0_VSYTRUE)
1574             var->sync |= FB_SYNC_VERT_HIGH_ACT;
1575         if (par->beamcon0 & BMC0_CSYTRUE)
1576             var->sync |= FB_SYNC_COMP_HIGH_ACT;
1577     } else {
1578         var->sync = FB_SYNC_BROADCAST;
1579         var->hsync_len = (152>>clk_shift) + mod4(par->diwstop_h);
1580         var->right_margin = ((par->htotal - down4(par->diwstop_h))>>clk_shift) + var->hsync_len;
1581         var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
1582         var->vsync_len = 4>>line_shift;
1583         var->lower_margin = ((par->vtotal - par->diwstop_v)>>line_shift) + var->vsync_len;
1584         var->upper_margin = (((par->vtotal - 2)>>line_shift) + 1) - var->yres -
1585                     var->lower_margin - var->vsync_len;
1586     }
1587 
1588     if (par->bplcon0 & BPC0_ERSY)
1589         var->sync |= FB_SYNC_EXT;
1590     if (par->vmode & FB_VMODE_YWRAP)
1591         var->vmode |= FB_VMODE_YWRAP;
1592 }
1593 
1594 
1595     /*
1596      * Update hardware
1597      */
1598 
1599 static void ami_update_par(struct fb_info *info)
1600 {
1601     struct amifb_par *par = info->par;
1602     short clk_shift, vshift, fstrt, fsize, fstop, fconst,  shift, move, mod;
1603 
1604     clk_shift = par->clk_shift;
1605 
1606     if (!(par->vmode & FB_VMODE_SMOOTH_XPAN))
1607         par->xoffset = upx(16 << maxfmode, par->xoffset);
1608 
1609     fconst = 16 << maxfmode << clk_shift;
1610     vshift = modx(16 << maxfmode, par->xoffset);
1611     fstrt = par->diwstrt_h - (vshift << clk_shift) - 4;
1612     fsize = (par->xres + vshift) << clk_shift;
1613     shift = modx(fconst, fstrt);
1614     move = downx(2 << maxfmode, div8(par->xoffset));
1615     if (maxfmode + clk_shift > 1) {
1616         fstrt = downx(fconst, fstrt) - 64;
1617         fsize = upx(fconst, fsize);
1618         fstop = fstrt + fsize - fconst;
1619     } else {
1620         mod = fstrt = downx(fconst, fstrt) - fconst;
1621         fstop = fstrt + upx(fconst, fsize) - 64;
1622         fsize = up64(fsize);
1623         fstrt = fstop - fsize + 64;
1624         if (fstrt < min_fstrt) {
1625             fstop += min_fstrt - fstrt;
1626             fstrt = min_fstrt;
1627         }
1628         move = move - div8((mod - fstrt)>>clk_shift);
1629     }
1630     mod = par->next_line - div8(fsize>>clk_shift);
1631     par->ddfstrt = fstrt;
1632     par->ddfstop = fstop;
1633     par->bplcon1 = hscroll2hw(shift);
1634     par->bpl2mod = mod;
1635     if (par->bplcon0 & BPC0_LACE)
1636         par->bpl2mod += par->next_line;
1637     if (IS_AGA && (par->fmode & FMODE_BSCAN2))
1638         par->bpl1mod = -div8(fsize>>clk_shift);
1639     else
1640         par->bpl1mod = par->bpl2mod;
1641 
1642     if (par->yoffset) {
1643         par->bplpt0 = info->fix.smem_start +
1644                   par->next_line * par->yoffset + move;
1645         if (par->vmode & FB_VMODE_YWRAP) {
1646             if (par->yoffset > par->vyres - par->yres) {
1647                 par->bplpt0wrap = info->fix.smem_start + move;
1648                 if (par->bplcon0 & BPC0_LACE &&
1649                     mod2(par->diwstrt_v + par->vyres -
1650                      par->yoffset))
1651                     par->bplpt0wrap += par->next_line;
1652             }
1653         }
1654     } else
1655         par->bplpt0 = info->fix.smem_start + move;
1656 
1657     if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v))
1658         par->bplpt0 += par->next_line;
1659 }
1660 
1661 
1662     /*
1663      * Pan or Wrap the Display
1664      *
1665      * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
1666      * in `var'.
1667      */
1668 
1669 static void ami_pan_var(struct fb_var_screeninfo *var, struct fb_info *info)
1670 {
1671     struct amifb_par *par = info->par;
1672 
1673     par->xoffset = var->xoffset;
1674     par->yoffset = var->yoffset;
1675     if (var->vmode & FB_VMODE_YWRAP)
1676         par->vmode |= FB_VMODE_YWRAP;
1677     else
1678         par->vmode &= ~FB_VMODE_YWRAP;
1679 
1680     do_vmode_pan = 0;
1681     ami_update_par(info);
1682     do_vmode_pan = 1;
1683 }
1684 
1685 
1686 static void ami_update_display(const struct amifb_par *par)
1687 {
1688     custom.bplcon1 = par->bplcon1;
1689     custom.bpl1mod = par->bpl1mod;
1690     custom.bpl2mod = par->bpl2mod;
1691     custom.ddfstrt = ddfstrt2hw(par->ddfstrt);
1692     custom.ddfstop = ddfstop2hw(par->ddfstop);
1693 }
1694 
1695     /*
1696      * Change the video mode (called by VBlank interrupt)
1697      */
1698 
1699 static void ami_init_display(const struct amifb_par *par)
1700 {
1701     int i;
1702 
1703     custom.bplcon0 = par->bplcon0 & ~BPC0_LACE;
1704     custom.bplcon2 = (IS_OCS ? 0 : BPC2_KILLEHB) | BPC2_PF2P2 | BPC2_PF1P2;
1705     if (!IS_OCS) {
1706         custom.bplcon3 = par->bplcon3;
1707         if (IS_AGA)
1708             custom.bplcon4 = BPC4_ESPRM4 | BPC4_OSPRM4;
1709         if (par->beamcon0 & BMC0_VARBEAMEN) {
1710             custom.htotal = htotal2hw(par->htotal);
1711             custom.hbstrt = hbstrt2hw(par->hbstrt);
1712             custom.hbstop = hbstop2hw(par->hbstop);
1713             custom.hsstrt = hsstrt2hw(par->hsstrt);
1714             custom.hsstop = hsstop2hw(par->hsstop);
1715             custom.hcenter = hcenter2hw(par->hcenter);
1716             custom.vtotal = vtotal2hw(par->vtotal);
1717             custom.vbstrt = vbstrt2hw(par->vbstrt);
1718             custom.vbstop = vbstop2hw(par->vbstop);
1719             custom.vsstrt = vsstrt2hw(par->vsstrt);
1720             custom.vsstop = vsstop2hw(par->vsstop);
1721         }
1722     }
1723     if (!IS_OCS || par->hsstop)
1724         custom.beamcon0 = par->beamcon0;
1725     if (IS_AGA)
1726         custom.fmode = par->fmode;
1727 
1728     /*
1729      * The minimum period for audio depends on htotal
1730      */
1731 
1732     amiga_audio_min_period = div16(par->htotal);
1733 
1734     is_lace = par->bplcon0 & BPC0_LACE ? 1 : 0;
1735 #if 1
1736     if (is_lace) {
1737         i = custom.vposr >> 15;
1738     } else {
1739         custom.vposw = custom.vposr | 0x8000;
1740         i = 1;
1741     }
1742 #else
1743     i = 1;
1744     custom.vposw = custom.vposr | 0x8000;
1745 #endif
1746     custom.cop2lc = (u_short *)ZTWO_PADDR(copdisplay.list[currentcop][i]);
1747 }
1748 
1749     /*
1750      * (Un)Blank the screen (called by VBlank interrupt)
1751      */
1752 
1753 static void ami_do_blank(const struct amifb_par *par)
1754 {
1755 #if defined(CONFIG_FB_AMIGA_AGA)
1756     u_short bplcon3 = par->bplcon3;
1757 #endif
1758     u_char red, green, blue;
1759 
1760     if (do_blank > 0) {
1761         custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
1762         red = green = blue = 0;
1763         if (!IS_OCS && do_blank > 1) {
1764             switch (do_blank) {
1765             case FB_BLANK_VSYNC_SUSPEND:
1766                 custom.hsstrt = hsstrt2hw(par->hsstrt);
1767                 custom.hsstop = hsstop2hw(par->hsstop);
1768                 custom.vsstrt = vsstrt2hw(par->vtotal + 4);
1769                 custom.vsstop = vsstop2hw(par->vtotal + 4);
1770                 break;
1771             case FB_BLANK_HSYNC_SUSPEND:
1772                 custom.hsstrt = hsstrt2hw(par->htotal + 16);
1773                 custom.hsstop = hsstop2hw(par->htotal + 16);
1774                 custom.vsstrt = vsstrt2hw(par->vsstrt);
1775                 custom.vsstop = vsstrt2hw(par->vsstop);
1776                 break;
1777             case FB_BLANK_POWERDOWN:
1778                 custom.hsstrt = hsstrt2hw(par->htotal + 16);
1779                 custom.hsstop = hsstop2hw(par->htotal + 16);
1780                 custom.vsstrt = vsstrt2hw(par->vtotal + 4);
1781                 custom.vsstop = vsstop2hw(par->vtotal + 4);
1782                 break;
1783             }
1784             if (!(par->beamcon0 & BMC0_VARBEAMEN)) {
1785                 custom.htotal = htotal2hw(par->htotal);
1786                 custom.vtotal = vtotal2hw(par->vtotal);
1787                 custom.beamcon0 = BMC0_HARDDIS | BMC0_VARBEAMEN |
1788                           BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARCSYEN;
1789             }
1790         }
1791     } else {
1792         custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_SPRITE;
1793         red = red0;
1794         green = green0;
1795         blue = blue0;
1796         if (!IS_OCS) {
1797             custom.hsstrt = hsstrt2hw(par->hsstrt);
1798             custom.hsstop = hsstop2hw(par->hsstop);
1799             custom.vsstrt = vsstrt2hw(par->vsstrt);
1800             custom.vsstop = vsstop2hw(par->vsstop);
1801             custom.beamcon0 = par->beamcon0;
1802         }
1803     }
1804 #if defined(CONFIG_FB_AMIGA_AGA)
1805     if (IS_AGA) {
1806         custom.bplcon3 = bplcon3;
1807         custom.color[0] = rgb2hw8_high(red, green, blue);
1808         custom.bplcon3 = bplcon3 | BPC3_LOCT;
1809         custom.color[0] = rgb2hw8_low(red, green, blue);
1810         custom.bplcon3 = bplcon3;
1811     } else
1812 #endif
1813 #if defined(CONFIG_FB_AMIGA_ECS)
1814     if (par->bplcon0 & BPC0_SHRES) {
1815         u_short color, mask;
1816         int i;
1817 
1818         mask = 0x3333;
1819         color = rgb2hw2(red, green, blue);
1820         for (i = 12; i >= 0; i -= 4)
1821             custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
1822         mask <<= 2; color >>= 2;
1823         for (i = 3; i >= 0; i--)
1824             custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
1825     } else
1826 #endif
1827         custom.color[0] = rgb2hw4(red, green, blue);
1828     is_blanked = do_blank > 0 ? do_blank : 0;
1829 }
1830 
1831 static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix,
1832                   const struct amifb_par *par)
1833 {
1834     fix->crsr_width = fix->crsr_xsize = par->crsr.width;
1835     fix->crsr_height = fix->crsr_ysize = par->crsr.height;
1836     fix->crsr_color1 = 17;
1837     fix->crsr_color2 = 18;
1838     return 0;
1839 }
1840 
1841 static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var,
1842                   u_char __user *data,
1843                   const struct amifb_par *par)
1844 {
1845     register u_short *lspr, *sspr;
1846 #ifdef __mc68000__
1847     register u_long datawords asm ("d2");
1848 #else
1849     register u_long datawords;
1850 #endif
1851     register short delta;
1852     register u_char color;
1853     short height, width, bits, words;
1854     int size, alloc;
1855 
1856     size = par->crsr.height * par->crsr.width;
1857     alloc = var->height * var->width;
1858     var->height = par->crsr.height;
1859     var->width = par->crsr.width;
1860     var->xspot = par->crsr.spot_x;
1861     var->yspot = par->crsr.spot_y;
1862     if (size > var->height * var->width)
1863         return -ENAMETOOLONG;
1864     delta = 1 << par->crsr.fmode;
1865     lspr = lofsprite + (delta << 1);
1866     if (par->bplcon0 & BPC0_LACE)
1867         sspr = shfsprite + (delta << 1);
1868     else
1869         sspr = NULL;
1870     for (height = (short)var->height - 1; height >= 0; height--) {
1871         bits = 0; words = delta; datawords = 0;
1872         for (width = (short)var->width - 1; width >= 0; width--) {
1873             if (bits == 0) {
1874                 bits = 16; --words;
1875 #ifdef __mc68000__
1876                 asm volatile ("movew %1@(%3:w:2),%0 ; swap %0 ; movew %1@+,%0"
1877                     : "=d" (datawords), "=a" (lspr) : "1" (lspr), "d" (delta));
1878 #else
1879                 datawords = (*(lspr + delta) << 16) | (*lspr++);
1880 #endif
1881             }
1882             --bits;
1883 #ifdef __mc68000__
1884             asm volatile (
1885                 "clrb %0 ; swap %1 ; lslw #1,%1 ; roxlb #1,%0 ; "
1886                 "swap %1 ; lslw #1,%1 ; roxlb #1,%0"
1887                 : "=d" (color), "=d" (datawords) : "1" (datawords));
1888 #else
1889             color = (((datawords >> 30) & 2)
1890                  | ((datawords >> 15) & 1));
1891             datawords <<= 1;
1892 #endif
1893             /* FIXME: check the return value + test the change */
1894             put_user(color, data++);
1895         }
1896         if (bits > 0) {
1897             --words; ++lspr;
1898         }
1899         while (--words >= 0)
1900             ++lspr;
1901 #ifdef __mc68000__
1902         asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
1903             : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
1904 #else
1905         lspr += delta;
1906         if (sspr) {
1907             u_short *tmp = lspr;
1908             lspr = sspr;
1909             sspr = tmp;
1910         }
1911 #endif
1912     }
1913     return 0;
1914 }
1915 
1916 static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var,
1917                   u_char __user *data, struct amifb_par *par)
1918 {
1919     register u_short *lspr, *sspr;
1920 #ifdef __mc68000__
1921     register u_long datawords asm ("d2");
1922 #else
1923     register u_long datawords;
1924 #endif
1925     register short delta;
1926     u_short fmode;
1927     short height, width, bits, words;
1928 
1929     if (!var->width)
1930         return -EINVAL;
1931     else if (var->width <= 16)
1932         fmode = TAG_FMODE_1;
1933     else if (var->width <= 32)
1934         fmode = TAG_FMODE_2;
1935     else if (var->width <= 64)
1936         fmode = TAG_FMODE_4;
1937     else
1938         return -EINVAL;
1939     if (fmode > maxfmode)
1940         return -EINVAL;
1941     if (!var->height)
1942         return -EINVAL;
1943     delta = 1 << fmode;
1944     lofsprite = shfsprite = (u_short *)spritememory;
1945     lspr = lofsprite + (delta << 1);
1946     if (par->bplcon0 & BPC0_LACE) {
1947         if (((var->height + 4) << fmode << 2) > SPRITEMEMSIZE)
1948             return -EINVAL;
1949         memset(lspr, 0, (var->height + 4) << fmode << 2);
1950         shfsprite += ((var->height + 5)&-2) << fmode;
1951         sspr = shfsprite + (delta << 1);
1952     } else {
1953         if (((var->height + 2) << fmode << 2) > SPRITEMEMSIZE)
1954             return -EINVAL;
1955         memset(lspr, 0, (var->height + 2) << fmode << 2);
1956         sspr = NULL;
1957     }
1958     for (height = (short)var->height - 1; height >= 0; height--) {
1959         bits = 16; words = delta; datawords = 0;
1960         for (width = (short)var->width - 1; width >= 0; width--) {
1961             unsigned long tdata = 0;
1962             /* FIXME: check the return value + test the change */
1963             get_user(tdata, data);
1964             data++;
1965 #ifdef __mc68000__
1966             asm volatile (
1967                 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0 ; "
1968                 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0"
1969                 : "=d" (datawords)
1970                 : "0" (datawords), "d" (tdata));
1971 #else
1972             datawords = ((datawords << 1) & 0xfffefffe);
1973             datawords |= tdata & 1;
1974             datawords |= (tdata & 2) << (16 - 1);
1975 #endif
1976             if (--bits == 0) {
1977                 bits = 16; --words;
1978 #ifdef __mc68000__
1979                 asm volatile ("swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+"
1980                     : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta));
1981 #else
1982                 *(lspr + delta) = (u_short) (datawords >> 16);
1983                 *lspr++ = (u_short) (datawords & 0xffff);
1984 #endif
1985             }
1986         }
1987         if (bits < 16) {
1988             --words;
1989 #ifdef __mc68000__
1990             asm volatile (
1991                 "swap %2 ; lslw %4,%2 ; movew %2,%0@(%3:w:2) ; "
1992                 "swap %2 ; lslw %4,%2 ; movew %2,%0@+"
1993                 : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta), "d" (bits));
1994 #else
1995             *(lspr + delta) = (u_short) (datawords >> (16 + bits));
1996             *lspr++ = (u_short) ((datawords & 0x0000ffff) >> bits);
1997 #endif
1998         }
1999         while (--words >= 0) {
2000 #ifdef __mc68000__
2001             asm volatile ("moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+"
2002                 : "=a" (lspr) : "0" (lspr), "d" (delta) : "d0");
2003 #else
2004             *(lspr + delta) = 0;
2005             *lspr++ = 0;
2006 #endif
2007         }
2008 #ifdef __mc68000__
2009         asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
2010             : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
2011 #else
2012         lspr += delta;
2013         if (sspr) {
2014             u_short *tmp = lspr;
2015             lspr = sspr;
2016             sspr = tmp;
2017         }
2018 #endif
2019     }
2020     par->crsr.height = var->height;
2021     par->crsr.width = var->width;
2022     par->crsr.spot_x = var->xspot;
2023     par->crsr.spot_y = var->yspot;
2024     par->crsr.fmode = fmode;
2025     if (IS_AGA) {
2026         par->fmode &= ~(FMODE_SPAGEM | FMODE_SPR32);
2027         par->fmode |= sprfetchmode[fmode];
2028         custom.fmode = par->fmode;
2029     }
2030     return 0;
2031 }
2032 
2033 static int ami_get_cursorstate(struct fb_cursorstate *state,
2034                    const struct amifb_par *par)
2035 {
2036     state->xoffset = par->crsr.crsr_x;
2037     state->yoffset = par->crsr.crsr_y;
2038     state->mode = cursormode;
2039     return 0;
2040 }
2041 
2042 static int ami_set_cursorstate(struct fb_cursorstate *state,
2043                    struct amifb_par *par)
2044 {
2045     par->crsr.crsr_x = state->xoffset;
2046     par->crsr.crsr_y = state->yoffset;
2047     if ((cursormode = state->mode) == FB_CURSOR_OFF)
2048         cursorstate = -1;
2049     do_cursor = 1;
2050     return 0;
2051 }
2052 
2053 static void ami_set_sprite(const struct amifb_par *par)
2054 {
2055     copins *copl, *cops;
2056     u_short hs, vs, ve;
2057     u_long pl, ps;
2058     short mx, my;
2059 
2060     cops = copdisplay.list[currentcop][0];
2061     copl = copdisplay.list[currentcop][1];
2062     ps = pl = ZTWO_PADDR(dummysprite);
2063     mx = par->crsr.crsr_x - par->crsr.spot_x;
2064     my = par->crsr.crsr_y - par->crsr.spot_y;
2065     if (!(par->vmode & FB_VMODE_YWRAP)) {
2066         mx -= par->xoffset;
2067         my -= par->yoffset;
2068     }
2069     if (!is_blanked && cursorstate > 0 && par->crsr.height > 0 &&
2070         mx > -(short)par->crsr.width && mx < par->xres &&
2071         my > -(short)par->crsr.height && my < par->yres) {
2072         pl = ZTWO_PADDR(lofsprite);
2073         hs = par->diwstrt_h + (mx << par->clk_shift) - 4;
2074         vs = par->diwstrt_v + (my << par->line_shift);
2075         ve = vs + (par->crsr.height << par->line_shift);
2076         if (par->bplcon0 & BPC0_LACE) {
2077             ps = ZTWO_PADDR(shfsprite);
2078             lofsprite[0] = spr2hw_pos(vs, hs);
2079             shfsprite[0] = spr2hw_pos(vs + 1, hs);
2080             if (mod2(vs)) {
2081                 lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
2082                 shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve + 1);
2083                 swap(pl, ps);
2084             } else {
2085                 lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve + 1);
2086                 shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve);
2087             }
2088         } else {
2089             lofsprite[0] = spr2hw_pos(vs, hs) | (IS_AGA && (par->fmode & FMODE_BSCAN2) ? 0x80 : 0);
2090             lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
2091         }
2092     }
2093     copl[cop_spr0ptrh].w[1] = highw(pl);
2094     copl[cop_spr0ptrl].w[1] = loww(pl);
2095     if (par->bplcon0 & BPC0_LACE) {
2096         cops[cop_spr0ptrh].w[1] = highw(ps);
2097         cops[cop_spr0ptrl].w[1] = loww(ps);
2098     }
2099 }
2100 
2101 
2102     /*
2103      * Initialise the Copper Initialisation List
2104      */
2105 
2106 static void __init ami_init_copper(void)
2107 {
2108     copins *cop = copdisplay.init;
2109     u_long p;
2110     int i;
2111 
2112     if (!IS_OCS) {
2113         (cop++)->l = CMOVE(BPC0_COLOR | BPC0_SHRES | BPC0_ECSENA, bplcon0);
2114         (cop++)->l = CMOVE(0x0181, diwstrt);
2115         (cop++)->l = CMOVE(0x0281, diwstop);
2116         (cop++)->l = CMOVE(0x0000, diwhigh);
2117     } else
2118         (cop++)->l = CMOVE(BPC0_COLOR, bplcon0);
2119     p = ZTWO_PADDR(dummysprite);
2120     for (i = 0; i < 8; i++) {
2121         (cop++)->l = CMOVE(0, spr[i].pos);
2122         (cop++)->l = CMOVE(highw(p), sprpt[i]);
2123         (cop++)->l = CMOVE2(loww(p), sprpt[i]);
2124     }
2125 
2126     (cop++)->l = CMOVE(IF_SETCLR | IF_COPER, intreq);
2127     copdisplay.wait = cop;
2128     (cop++)->l = CEND;
2129     (cop++)->l = CMOVE(0, copjmp2);
2130     cop->l = CEND;
2131 
2132     custom.cop1lc = (u_short *)ZTWO_PADDR(copdisplay.init);
2133     custom.copjmp1 = 0;
2134 }
2135 
2136 static void ami_reinit_copper(const struct amifb_par *par)
2137 {
2138     copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0;
2139     copdisplay.wait->l = CWAIT(32, par->diwstrt_v - 4);
2140 }
2141 
2142 
2143     /*
2144      * Rebuild the Copper List
2145      *
2146      * We only change the things that are not static
2147      */
2148 
2149 static void ami_rebuild_copper(const struct amifb_par *par)
2150 {
2151     copins *copl, *cops;
2152     u_short line, h_end1, h_end2;
2153     short i;
2154     u_long p;
2155 
2156     if (IS_AGA && maxfmode + par->clk_shift == 0)
2157         h_end1 = par->diwstrt_h - 64;
2158     else
2159         h_end1 = par->htotal - 32;
2160     h_end2 = par->ddfstop + 64;
2161 
2162     ami_set_sprite(par);
2163 
2164     copl = copdisplay.rebuild[1];
2165     p = par->bplpt0;
2166     if (par->vmode & FB_VMODE_YWRAP) {
2167         if ((par->vyres - par->yoffset) != 1 || !mod2(par->diwstrt_v)) {
2168             if (par->yoffset > par->vyres - par->yres) {
2169                 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2170                     (copl++)->l = CMOVE(highw(p), bplpt[i]);
2171                     (copl++)->l = CMOVE2(loww(p), bplpt[i]);
2172                 }
2173                 line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 1;
2174                 while (line >= 512) {
2175                     (copl++)->l = CWAIT(h_end1, 510);
2176                     line -= 512;
2177                 }
2178                 if (line >= 510 && IS_AGA && maxfmode + par->clk_shift == 0)
2179                     (copl++)->l = CWAIT(h_end1, line);
2180                 else
2181                     (copl++)->l = CWAIT(h_end2, line);
2182                 p = par->bplpt0wrap;
2183             }
2184         } else
2185             p = par->bplpt0wrap;
2186     }
2187     for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2188         (copl++)->l = CMOVE(highw(p), bplpt[i]);
2189         (copl++)->l = CMOVE2(loww(p), bplpt[i]);
2190     }
2191     copl->l = CEND;
2192 
2193     if (par->bplcon0 & BPC0_LACE) {
2194         cops = copdisplay.rebuild[0];
2195         p = par->bplpt0;
2196         if (mod2(par->diwstrt_v))
2197             p -= par->next_line;
2198         else
2199             p += par->next_line;
2200         if (par->vmode & FB_VMODE_YWRAP) {
2201             if ((par->vyres - par->yoffset) != 1 || mod2(par->diwstrt_v)) {
2202                 if (par->yoffset > par->vyres - par->yres + 1) {
2203                     for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2204                         (cops++)->l = CMOVE(highw(p), bplpt[i]);
2205                         (cops++)->l = CMOVE2(loww(p), bplpt[i]);
2206                     }
2207                     line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 2;
2208                     while (line >= 512) {
2209                         (cops++)->l = CWAIT(h_end1, 510);
2210                         line -= 512;
2211                     }
2212                     if (line > 510 && IS_AGA && maxfmode + par->clk_shift == 0)
2213                         (cops++)->l = CWAIT(h_end1, line);
2214                     else
2215                         (cops++)->l = CWAIT(h_end2, line);
2216                     p = par->bplpt0wrap;
2217                     if (mod2(par->diwstrt_v + par->vyres -
2218                         par->yoffset))
2219                         p -= par->next_line;
2220                     else
2221                         p += par->next_line;
2222                 }
2223             } else
2224                 p = par->bplpt0wrap - par->next_line;
2225         }
2226         for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2227             (cops++)->l = CMOVE(highw(p), bplpt[i]);
2228             (cops++)->l = CMOVE2(loww(p), bplpt[i]);
2229         }
2230         cops->l = CEND;
2231     }
2232 }
2233 
2234 
2235     /*
2236      * Build the Copper List
2237      */
2238 
2239 static void ami_build_copper(struct fb_info *info)
2240 {
2241     struct amifb_par *par = info->par;
2242     copins *copl, *cops;
2243     u_long p;
2244 
2245     currentcop = 1 - currentcop;
2246 
2247     copl = copdisplay.list[currentcop][1];
2248 
2249     (copl++)->l = CWAIT(0, 10);
2250     (copl++)->l = CMOVE(par->bplcon0, bplcon0);
2251     (copl++)->l = CMOVE(0, sprpt[0]);
2252     (copl++)->l = CMOVE2(0, sprpt[0]);
2253 
2254     if (par->bplcon0 & BPC0_LACE) {
2255         cops = copdisplay.list[currentcop][0];
2256 
2257         (cops++)->l = CWAIT(0, 10);
2258         (cops++)->l = CMOVE(par->bplcon0, bplcon0);
2259         (cops++)->l = CMOVE(0, sprpt[0]);
2260         (cops++)->l = CMOVE2(0, sprpt[0]);
2261 
2262         (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v + 1), diwstrt);
2263         (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v + 1), diwstop);
2264         (cops++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
2265         (cops++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
2266         if (!IS_OCS) {
2267             (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v + 1,
2268                         par->diwstop_h, par->diwstop_v + 1), diwhigh);
2269             (cops++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
2270                         par->diwstop_h, par->diwstop_v), diwhigh);
2271 #if 0
2272             if (par->beamcon0 & BMC0_VARBEAMEN) {
2273                 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
2274                 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt + 1), vbstrt);
2275                 (copl++)->l = CMOVE(vbstop2hw(par->vbstop + 1), vbstop);
2276                 (cops++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
2277                 (cops++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
2278                 (cops++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
2279             }
2280 #endif
2281         }
2282         p = ZTWO_PADDR(copdisplay.list[currentcop][0]);
2283         (copl++)->l = CMOVE(highw(p), cop2lc);
2284         (copl++)->l = CMOVE2(loww(p), cop2lc);
2285         p = ZTWO_PADDR(copdisplay.list[currentcop][1]);
2286         (cops++)->l = CMOVE(highw(p), cop2lc);
2287         (cops++)->l = CMOVE2(loww(p), cop2lc);
2288         copdisplay.rebuild[0] = cops;
2289     } else {
2290         (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
2291         (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
2292         if (!IS_OCS) {
2293             (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
2294                         par->diwstop_h, par->diwstop_v), diwhigh);
2295 #if 0
2296             if (par->beamcon0 & BMC0_VARBEAMEN) {
2297                 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
2298                 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
2299                 (copl++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
2300             }
2301 #endif
2302         }
2303     }
2304     copdisplay.rebuild[1] = copl;
2305 
2306     ami_update_par(info);
2307     ami_rebuild_copper(info->par);
2308 }
2309 
2310 #ifndef MODULE
2311 static void __init amifb_setup_mcap(char *spec)
2312 {
2313     char *p;
2314     int vmin, vmax, hmin, hmax;
2315 
2316     /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
2317      * <V*> vertical freq. in Hz
2318      * <H*> horizontal freq. in kHz
2319      */
2320 
2321     if (!(p = strsep(&spec, ";")) || !*p)
2322         return;
2323     vmin = simple_strtoul(p, NULL, 10);
2324     if (vmin <= 0)
2325         return;
2326     if (!(p = strsep(&spec, ";")) || !*p)
2327         return;
2328     vmax = simple_strtoul(p, NULL, 10);
2329     if (vmax <= 0 || vmax <= vmin)
2330         return;
2331     if (!(p = strsep(&spec, ";")) || !*p)
2332         return;
2333     hmin = 1000 * simple_strtoul(p, NULL, 10);
2334     if (hmin <= 0)
2335         return;
2336     if (!(p = strsep(&spec, "")) || !*p)
2337         return;
2338     hmax = 1000 * simple_strtoul(p, NULL, 10);
2339     if (hmax <= 0 || hmax <= hmin)
2340         return;
2341 
2342     amifb_hfmin = hmin;
2343     amifb_hfmax = hmax;
2344     amifb_vfmin = vmin;
2345     amifb_vfmax = vmax;
2346 }
2347 
2348 static int __init amifb_setup(char *options)
2349 {
2350     char *this_opt;
2351 
2352     if (!options || !*options)
2353         return 0;
2354 
2355     while ((this_opt = strsep(&options, ",")) != NULL) {
2356         if (!*this_opt)
2357             continue;
2358         if (!strcmp(this_opt, "inverse")) {
2359             fb_invert_cmaps();
2360         } else if (!strcmp(this_opt, "ilbm"))
2361             amifb_ilbm = 1;
2362         else if (!strncmp(this_opt, "monitorcap:", 11))
2363             amifb_setup_mcap(this_opt + 11);
2364         else if (!strncmp(this_opt, "fstart:", 7))
2365             min_fstrt = simple_strtoul(this_opt + 7, NULL, 0);
2366         else
2367             mode_option = this_opt;
2368     }
2369 
2370     if (min_fstrt < 48)
2371         min_fstrt = 48;
2372 
2373     return 0;
2374 }
2375 #endif
2376 
2377 static int amifb_check_var(struct fb_var_screeninfo *var,
2378                struct fb_info *info)
2379 {
2380     int err;
2381     struct amifb_par par;
2382 
2383     /* Validate wanted screen parameters */
2384     err = ami_decode_var(var, &par, info);
2385     if (err)
2386         return err;
2387 
2388     /* Encode (possibly rounded) screen parameters */
2389     ami_encode_var(var, &par);
2390     return 0;
2391 }
2392 
2393 
2394 static int amifb_set_par(struct fb_info *info)
2395 {
2396     struct amifb_par *par = info->par;
2397     int error;
2398 
2399     do_vmode_pan = 0;
2400     do_vmode_full = 0;
2401 
2402     /* Decode wanted screen parameters */
2403     error = ami_decode_var(&info->var, par, info);
2404     if (error)
2405         return error;
2406 
2407     /* Set new videomode */
2408     ami_build_copper(info);
2409 
2410     /* Set VBlank trigger */
2411     do_vmode_full = 1;
2412 
2413     /* Update fix for new screen parameters */
2414     if (par->bpp == 1) {
2415         info->fix.type = FB_TYPE_PACKED_PIXELS;
2416         info->fix.type_aux = 0;
2417     } else if (amifb_ilbm) {
2418         info->fix.type = FB_TYPE_INTERLEAVED_PLANES;
2419         info->fix.type_aux = par->next_line;
2420     } else {
2421         info->fix.type = FB_TYPE_PLANES;
2422         info->fix.type_aux = 0;
2423     }
2424     info->fix.line_length = div8(upx(16 << maxfmode, par->vxres));
2425 
2426     if (par->vmode & FB_VMODE_YWRAP) {
2427         info->fix.ywrapstep = 1;
2428         info->fix.xpanstep = 0;
2429         info->fix.ypanstep = 0;
2430         info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP |
2431             FBINFO_READS_FAST; /* override SCROLL_REDRAW */
2432     } else {
2433         info->fix.ywrapstep = 0;
2434         if (par->vmode & FB_VMODE_SMOOTH_XPAN)
2435             info->fix.xpanstep = 1;
2436         else
2437             info->fix.xpanstep = 16 << maxfmode;
2438         info->fix.ypanstep = 1;
2439         info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
2440     }
2441     return 0;
2442 }
2443 
2444 
2445     /*
2446      * Set a single color register. The values supplied are already
2447      * rounded down to the hardware's capabilities (according to the
2448      * entries in the var structure). Return != 0 for invalid regno.
2449      */
2450 
2451 static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
2452                u_int transp, struct fb_info *info)
2453 {
2454     const struct amifb_par *par = info->par;
2455 
2456     if (IS_AGA) {
2457         if (regno > 255)
2458             return 1;
2459     } else if (par->bplcon0 & BPC0_SHRES) {
2460         if (regno > 3)
2461             return 1;
2462     } else {
2463         if (regno > 31)
2464             return 1;
2465     }
2466     red >>= 8;
2467     green >>= 8;
2468     blue >>= 8;
2469     if (!regno) {
2470         red0 = red;
2471         green0 = green;
2472         blue0 = blue;
2473     }
2474 
2475     /*
2476      * Update the corresponding Hardware Color Register, unless it's Color
2477      * Register 0 and the screen is blanked.
2478      *
2479      * VBlank is switched off to protect bplcon3 or ecs_palette[] from
2480      * being changed by ami_do_blank() during the VBlank.
2481      */
2482 
2483     if (regno || !is_blanked) {
2484 #if defined(CONFIG_FB_AMIGA_AGA)
2485         if (IS_AGA) {
2486             u_short bplcon3 = par->bplcon3;
2487             VBlankOff();
2488             custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000);
2489             custom.color[regno & 31] = rgb2hw8_high(red, green,
2490                                 blue);
2491             custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000) |
2492                      BPC3_LOCT;
2493             custom.color[regno & 31] = rgb2hw8_low(red, green,
2494                                    blue);
2495             custom.bplcon3 = bplcon3;
2496             VBlankOn();
2497         } else
2498 #endif
2499 #if defined(CONFIG_FB_AMIGA_ECS)
2500         if (par->bplcon0 & BPC0_SHRES) {
2501             u_short color, mask;
2502             int i;
2503 
2504             mask = 0x3333;
2505             color = rgb2hw2(red, green, blue);
2506             VBlankOff();
2507             for (i = regno + 12; i >= (int)regno; i -= 4)
2508                 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
2509             mask <<= 2; color >>= 2;
2510             regno = down16(regno) + mul4(mod4(regno));
2511             for (i = regno + 3; i >= (int)regno; i--)
2512                 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
2513             VBlankOn();
2514         } else
2515 #endif
2516             custom.color[regno] = rgb2hw4(red, green, blue);
2517     }
2518     return 0;
2519 }
2520 
2521 
2522     /*
2523      * Blank the display.
2524      */
2525 
2526 static int amifb_blank(int blank, struct fb_info *info)
2527 {
2528     do_blank = blank ? blank : -1;
2529 
2530     return 0;
2531 }
2532 
2533 
2534     /*
2535      * Pan or Wrap the Display
2536      *
2537      * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
2538      */
2539 
2540 static int amifb_pan_display(struct fb_var_screeninfo *var,
2541                  struct fb_info *info)
2542 {
2543     if (!(var->vmode & FB_VMODE_YWRAP)) {
2544         /*
2545          * TODO: There will be problems when xpan!=1, so some columns
2546          * on the right side will never be seen
2547          */
2548         if (var->xoffset + info->var.xres >
2549             upx(16 << maxfmode, info->var.xres_virtual))
2550             return -EINVAL;
2551     }
2552     ami_pan_var(var, info);
2553     return 0;
2554 }
2555 
2556 
2557 #if BITS_PER_LONG == 32
2558 #define BYTES_PER_LONG  4
2559 #define SHIFT_PER_LONG  5
2560 #elif BITS_PER_LONG == 64
2561 #define BYTES_PER_LONG  8
2562 #define SHIFT_PER_LONG  6
2563 #else
2564 #define Please update me
2565 #endif
2566 
2567 
2568     /*
2569      *  Compose two values, using a bitmask as decision value
2570      *  This is equivalent to (a & mask) | (b & ~mask)
2571      */
2572 
2573 static inline unsigned long comp(unsigned long a, unsigned long b,
2574                  unsigned long mask)
2575 {
2576     return ((a ^ b) & mask) ^ b;
2577 }
2578 
2579 
2580 static inline unsigned long xor(unsigned long a, unsigned long b,
2581                 unsigned long mask)
2582 {
2583     return (a & mask) ^ b;
2584 }
2585 
2586 
2587     /*
2588      *  Unaligned forward bit copy using 32-bit or 64-bit memory accesses
2589      */
2590 
2591 static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
2592            int src_idx, u32 n)
2593 {
2594     unsigned long first, last;
2595     int shift = dst_idx - src_idx, left, right;
2596     unsigned long d0, d1;
2597     int m;
2598 
2599     if (!n)
2600         return;
2601 
2602     shift = dst_idx - src_idx;
2603     first = ~0UL >> dst_idx;
2604     last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
2605 
2606     if (!shift) {
2607         // Same alignment for source and dest
2608 
2609         if (dst_idx + n <= BITS_PER_LONG) {
2610             // Single word
2611             if (last)
2612                 first &= last;
2613             *dst = comp(*src, *dst, first);
2614         } else {
2615             // Multiple destination words
2616             // Leading bits
2617             if (first) {
2618                 *dst = comp(*src, *dst, first);
2619                 dst++;
2620                 src++;
2621                 n -= BITS_PER_LONG - dst_idx;
2622             }
2623 
2624             // Main chunk
2625             n /= BITS_PER_LONG;
2626             while (n >= 8) {
2627                 *dst++ = *src++;
2628                 *dst++ = *src++;
2629                 *dst++ = *src++;
2630                 *dst++ = *src++;
2631                 *dst++ = *src++;
2632                 *dst++ = *src++;
2633                 *dst++ = *src++;
2634                 *dst++ = *src++;
2635                 n -= 8;
2636             }
2637             while (n--)
2638                 *dst++ = *src++;
2639 
2640             // Trailing bits
2641             if (last)
2642                 *dst = comp(*src, *dst, last);
2643         }
2644     } else {
2645         // Different alignment for source and dest
2646 
2647         right = shift & (BITS_PER_LONG - 1);
2648         left = -shift & (BITS_PER_LONG - 1);
2649 
2650         if (dst_idx + n <= BITS_PER_LONG) {
2651             // Single destination word
2652             if (last)
2653                 first &= last;
2654             if (shift > 0) {
2655                 // Single source word
2656                 *dst = comp(*src >> right, *dst, first);
2657             } else if (src_idx + n <= BITS_PER_LONG) {
2658                 // Single source word
2659                 *dst = comp(*src << left, *dst, first);
2660             } else {
2661                 // 2 source words
2662                 d0 = *src++;
2663                 d1 = *src;
2664                 *dst = comp(d0 << left | d1 >> right, *dst,
2665                         first);
2666             }
2667         } else {
2668             // Multiple destination words
2669             d0 = *src++;
2670             // Leading bits
2671             if (shift > 0) {
2672                 // Single source word
2673                 *dst = comp(d0 >> right, *dst, first);
2674                 dst++;
2675                 n -= BITS_PER_LONG - dst_idx;
2676             } else {
2677                 // 2 source words
2678                 d1 = *src++;
2679                 *dst = comp(d0 << left | d1 >> right, *dst,
2680                         first);
2681                 d0 = d1;
2682                 dst++;
2683                 n -= BITS_PER_LONG - dst_idx;
2684             }
2685 
2686             // Main chunk
2687             m = n % BITS_PER_LONG;
2688             n /= BITS_PER_LONG;
2689             while (n >= 4) {
2690                 d1 = *src++;
2691                 *dst++ = d0 << left | d1 >> right;
2692                 d0 = d1;
2693                 d1 = *src++;
2694                 *dst++ = d0 << left | d1 >> right;
2695                 d0 = d1;
2696                 d1 = *src++;
2697                 *dst++ = d0 << left | d1 >> right;
2698                 d0 = d1;
2699                 d1 = *src++;
2700                 *dst++ = d0 << left | d1 >> right;
2701                 d0 = d1;
2702                 n -= 4;
2703             }
2704             while (n--) {
2705                 d1 = *src++;
2706                 *dst++ = d0 << left | d1 >> right;
2707                 d0 = d1;
2708             }
2709 
2710             // Trailing bits
2711             if (last) {
2712                 if (m <= right) {
2713                     // Single source word
2714                     *dst = comp(d0 << left, *dst, last);
2715                 } else {
2716                     // 2 source words
2717                     d1 = *src;
2718                     *dst = comp(d0 << left | d1 >> right,
2719                             *dst, last);
2720                 }
2721             }
2722         }
2723     }
2724 }
2725 
2726 
2727     /*
2728      *  Unaligned reverse bit copy using 32-bit or 64-bit memory accesses
2729      */
2730 
2731 static void bitcpy_rev(unsigned long *dst, int dst_idx,
2732                const unsigned long *src, int src_idx, u32 n)
2733 {
2734     unsigned long first, last;
2735     int shift = dst_idx - src_idx, left, right;
2736     unsigned long d0, d1;
2737     int m;
2738 
2739     if (!n)
2740         return;
2741 
2742     dst += (n - 1) / BITS_PER_LONG;
2743     src += (n - 1) / BITS_PER_LONG;
2744     if ((n - 1) % BITS_PER_LONG) {
2745         dst_idx += (n - 1) % BITS_PER_LONG;
2746         dst += dst_idx >> SHIFT_PER_LONG;
2747         dst_idx &= BITS_PER_LONG - 1;
2748         src_idx += (n - 1) % BITS_PER_LONG;
2749         src += src_idx >> SHIFT_PER_LONG;
2750         src_idx &= BITS_PER_LONG - 1;
2751     }
2752 
2753     shift = dst_idx - src_idx;
2754     first = ~0UL << (BITS_PER_LONG - 1 - dst_idx);
2755     last = ~(~0UL << (BITS_PER_LONG - 1 - ((dst_idx - n) % BITS_PER_LONG)));
2756 
2757     if (!shift) {
2758         // Same alignment for source and dest
2759 
2760         if ((unsigned long)dst_idx + 1 >= n) {
2761             // Single word
2762             if (last)
2763                 first &= last;
2764             *dst = comp(*src, *dst, first);
2765         } else {
2766             // Multiple destination words
2767             // Leading bits
2768             if (first) {
2769                 *dst = comp(*src, *dst, first);
2770                 dst--;
2771                 src--;
2772                 n -= dst_idx + 1;
2773             }
2774 
2775             // Main chunk
2776             n /= BITS_PER_LONG;
2777             while (n >= 8) {
2778                 *dst-- = *src--;
2779                 *dst-- = *src--;
2780                 *dst-- = *src--;
2781                 *dst-- = *src--;
2782                 *dst-- = *src--;
2783                 *dst-- = *src--;
2784                 *dst-- = *src--;
2785                 *dst-- = *src--;
2786                 n -= 8;
2787             }
2788             while (n--)
2789                 *dst-- = *src--;
2790 
2791             // Trailing bits
2792             if (last)
2793                 *dst = comp(*src, *dst, last);
2794         }
2795     } else {
2796         // Different alignment for source and dest
2797 
2798         right = shift & (BITS_PER_LONG - 1);
2799         left = -shift & (BITS_PER_LONG - 1);
2800 
2801         if ((unsigned long)dst_idx + 1 >= n) {
2802             // Single destination word
2803             if (last)
2804                 first &= last;
2805             if (shift < 0) {
2806                 // Single source word
2807                 *dst = comp(*src << left, *dst, first);
2808             } else if (1 + (unsigned long)src_idx >= n) {
2809                 // Single source word
2810                 *dst = comp(*src >> right, *dst, first);
2811             } else {
2812                 // 2 source words
2813                 d0 = *src--;
2814                 d1 = *src;
2815                 *dst = comp(d0 >> right | d1 << left, *dst,
2816                         first);
2817             }
2818         } else {
2819             // Multiple destination words
2820             d0 = *src--;
2821             // Leading bits
2822             if (shift < 0) {
2823                 // Single source word
2824                 *dst = comp(d0 << left, *dst, first);
2825                 dst--;
2826                 n -= dst_idx + 1;
2827             } else {
2828                 // 2 source words
2829                 d1 = *src--;
2830                 *dst = comp(d0 >> right | d1 << left, *dst,
2831                         first);
2832                 d0 = d1;
2833                 dst--;
2834                 n -= dst_idx + 1;
2835             }
2836 
2837             // Main chunk
2838             m = n % BITS_PER_LONG;
2839             n /= BITS_PER_LONG;
2840             while (n >= 4) {
2841                 d1 = *src--;
2842                 *dst-- = d0 >> right | d1 << left;
2843                 d0 = d1;
2844                 d1 = *src--;
2845                 *dst-- = d0 >> right | d1 << left;
2846                 d0 = d1;
2847                 d1 = *src--;
2848                 *dst-- = d0 >> right | d1 << left;
2849                 d0 = d1;
2850                 d1 = *src--;
2851                 *dst-- = d0 >> right | d1 << left;
2852                 d0 = d1;
2853                 n -= 4;
2854             }
2855             while (n--) {
2856                 d1 = *src--;
2857                 *dst-- = d0 >> right | d1 << left;
2858                 d0 = d1;
2859             }
2860 
2861             // Trailing bits
2862             if (last) {
2863                 if (m <= left) {
2864                     // Single source word
2865                     *dst = comp(d0 >> right, *dst, last);
2866                 } else {
2867                     // 2 source words
2868                     d1 = *src;
2869                     *dst = comp(d0 >> right | d1 << left,
2870                             *dst, last);
2871                 }
2872             }
2873         }
2874     }
2875 }
2876 
2877 
2878     /*
2879      *  Unaligned forward inverting bit copy using 32-bit or 64-bit memory
2880      *  accesses
2881      */
2882 
2883 static void bitcpy_not(unsigned long *dst, int dst_idx,
2884                const unsigned long *src, int src_idx, u32 n)
2885 {
2886     unsigned long first, last;
2887     int shift = dst_idx - src_idx, left, right;
2888     unsigned long d0, d1;
2889     int m;
2890 
2891     if (!n)
2892         return;
2893 
2894     shift = dst_idx - src_idx;
2895     first = ~0UL >> dst_idx;
2896     last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
2897 
2898     if (!shift) {
2899         // Same alignment for source and dest
2900 
2901         if (dst_idx + n <= BITS_PER_LONG) {
2902             // Single word
2903             if (last)
2904                 first &= last;
2905             *dst = comp(~*src, *dst, first);
2906         } else {
2907             // Multiple destination words
2908             // Leading bits
2909             if (first) {
2910                 *dst = comp(~*src, *dst, first);
2911                 dst++;
2912                 src++;
2913                 n -= BITS_PER_LONG - dst_idx;
2914             }
2915 
2916             // Main chunk
2917             n /= BITS_PER_LONG;
2918             while (n >= 8) {
2919                 *dst++ = ~*src++;
2920                 *dst++ = ~*src++;
2921                 *dst++ = ~*src++;
2922                 *dst++ = ~*src++;
2923                 *dst++ = ~*src++;
2924                 *dst++ = ~*src++;
2925                 *dst++ = ~*src++;
2926                 *dst++ = ~*src++;
2927                 n -= 8;
2928             }
2929             while (n--)
2930                 *dst++ = ~*src++;
2931 
2932             // Trailing bits
2933             if (last)
2934                 *dst = comp(~*src, *dst, last);
2935         }
2936     } else {
2937         // Different alignment for source and dest
2938 
2939         right = shift & (BITS_PER_LONG - 1);
2940         left = -shift & (BITS_PER_LONG - 1);
2941 
2942         if (dst_idx + n <= BITS_PER_LONG) {
2943             // Single destination word
2944             if (last)
2945                 first &= last;
2946             if (shift > 0) {
2947                 // Single source word
2948                 *dst = comp(~*src >> right, *dst, first);
2949             } else if (src_idx + n <= BITS_PER_LONG) {
2950                 // Single source word
2951                 *dst = comp(~*src << left, *dst, first);
2952             } else {
2953                 // 2 source words
2954                 d0 = ~*src++;
2955                 d1 = ~*src;
2956                 *dst = comp(d0 << left | d1 >> right, *dst,
2957                         first);
2958             }
2959         } else {
2960             // Multiple destination words
2961             d0 = ~*src++;
2962             // Leading bits
2963             if (shift > 0) {
2964                 // Single source word
2965                 *dst = comp(d0 >> right, *dst, first);
2966                 dst++;
2967                 n -= BITS_PER_LONG - dst_idx;
2968             } else {
2969                 // 2 source words
2970                 d1 = ~*src++;
2971                 *dst = comp(d0 << left | d1 >> right, *dst,
2972                         first);
2973                 d0 = d1;
2974                 dst++;
2975                 n -= BITS_PER_LONG - dst_idx;
2976             }
2977 
2978             // Main chunk
2979             m = n % BITS_PER_LONG;
2980             n /= BITS_PER_LONG;
2981             while (n >= 4) {
2982                 d1 = ~*src++;
2983                 *dst++ = d0 << left | d1 >> right;
2984                 d0 = d1;
2985                 d1 = ~*src++;
2986                 *dst++ = d0 << left | d1 >> right;
2987                 d0 = d1;
2988                 d1 = ~*src++;
2989                 *dst++ = d0 << left | d1 >> right;
2990                 d0 = d1;
2991                 d1 = ~*src++;
2992                 *dst++ = d0 << left | d1 >> right;
2993                 d0 = d1;
2994                 n -= 4;
2995             }
2996             while (n--) {
2997                 d1 = ~*src++;
2998                 *dst++ = d0 << left | d1 >> right;
2999                 d0 = d1;
3000             }
3001 
3002             // Trailing bits
3003             if (last) {
3004                 if (m <= right) {
3005                     // Single source word
3006                     *dst = comp(d0 << left, *dst, last);
3007                 } else {
3008                     // 2 source words
3009                     d1 = ~*src;
3010                     *dst = comp(d0 << left | d1 >> right,
3011                             *dst, last);
3012                 }
3013             }
3014         }
3015     }
3016 }
3017 
3018 
3019     /*
3020      *  Unaligned 32-bit pattern fill using 32/64-bit memory accesses
3021      */
3022 
3023 static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
3024 {
3025     unsigned long val = pat;
3026     unsigned long first, last;
3027 
3028     if (!n)
3029         return;
3030 
3031 #if BITS_PER_LONG == 64
3032     val |= val << 32;
3033 #endif
3034 
3035     first = ~0UL >> dst_idx;
3036     last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
3037 
3038     if (dst_idx + n <= BITS_PER_LONG) {
3039         // Single word
3040         if (last)
3041             first &= last;
3042         *dst = comp(val, *dst, first);
3043     } else {
3044         // Multiple destination words
3045         // Leading bits
3046         if (first) {
3047             *dst = comp(val, *dst, first);
3048             dst++;
3049             n -= BITS_PER_LONG - dst_idx;
3050         }
3051 
3052         // Main chunk
3053         n /= BITS_PER_LONG;
3054         while (n >= 8) {
3055             *dst++ = val;
3056             *dst++ = val;
3057             *dst++ = val;
3058             *dst++ = val;
3059             *dst++ = val;
3060             *dst++ = val;
3061             *dst++ = val;
3062             *dst++ = val;
3063             n -= 8;
3064         }
3065         while (n--)
3066             *dst++ = val;
3067 
3068         // Trailing bits
3069         if (last)
3070             *dst = comp(val, *dst, last);
3071     }
3072 }
3073 
3074 
3075     /*
3076      *  Unaligned 32-bit pattern xor using 32/64-bit memory accesses
3077      */
3078 
3079 static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
3080 {
3081     unsigned long val = pat;
3082     unsigned long first, last;
3083 
3084     if (!n)
3085         return;
3086 
3087 #if BITS_PER_LONG == 64
3088     val |= val << 32;
3089 #endif
3090 
3091     first = ~0UL >> dst_idx;
3092     last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
3093 
3094     if (dst_idx + n <= BITS_PER_LONG) {
3095         // Single word
3096         if (last)
3097             first &= last;
3098         *dst = xor(val, *dst, first);
3099     } else {
3100         // Multiple destination words
3101         // Leading bits
3102         if (first) {
3103             *dst = xor(val, *dst, first);
3104             dst++;
3105             n -= BITS_PER_LONG - dst_idx;
3106         }
3107 
3108         // Main chunk
3109         n /= BITS_PER_LONG;
3110         while (n >= 4) {
3111             *dst++ ^= val;
3112             *dst++ ^= val;
3113             *dst++ ^= val;
3114             *dst++ ^= val;
3115             n -= 4;
3116         }
3117         while (n--)
3118             *dst++ ^= val;
3119 
3120         // Trailing bits
3121         if (last)
3122             *dst = xor(val, *dst, last);
3123     }
3124 }
3125 
3126 static inline void fill_one_line(int bpp, unsigned long next_plane,
3127                  unsigned long *dst, int dst_idx, u32 n,
3128                  u32 color)
3129 {
3130     while (1) {
3131         dst += dst_idx >> SHIFT_PER_LONG;
3132         dst_idx &= (BITS_PER_LONG - 1);
3133         bitfill32(dst, dst_idx, color & 1 ? ~0 : 0, n);
3134         if (!--bpp)
3135             break;
3136         color >>= 1;
3137         dst_idx += next_plane * 8;
3138     }
3139 }
3140 
3141 static inline void xor_one_line(int bpp, unsigned long next_plane,
3142                 unsigned long *dst, int dst_idx, u32 n,
3143                 u32 color)
3144 {
3145     while (color) {
3146         dst += dst_idx >> SHIFT_PER_LONG;
3147         dst_idx &= (BITS_PER_LONG - 1);
3148         bitxor32(dst, dst_idx, color & 1 ? ~0 : 0, n);
3149         if (!--bpp)
3150             break;
3151         color >>= 1;
3152         dst_idx += next_plane * 8;
3153     }
3154 }
3155 
3156 
3157 static void amifb_fillrect(struct fb_info *info,
3158                const struct fb_fillrect *rect)
3159 {
3160     struct amifb_par *par = info->par;
3161     int dst_idx, x2, y2;
3162     unsigned long *dst;
3163     u32 width, height;
3164 
3165     if (!rect->width || !rect->height)
3166         return;
3167 
3168     /*
3169      * We could use hardware clipping but on many cards you get around
3170      * hardware clipping by writing to framebuffer directly.
3171      * */
3172     x2 = rect->dx + rect->width;
3173     y2 = rect->dy + rect->height;
3174     x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
3175     y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
3176     width = x2 - rect->dx;
3177     height = y2 - rect->dy;
3178 
3179     dst = (unsigned long *)
3180         ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
3181     dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
3182     dst_idx += rect->dy * par->next_line * 8 + rect->dx;
3183     while (height--) {
3184         switch (rect->rop) {
3185         case ROP_COPY:
3186             fill_one_line(info->var.bits_per_pixel,
3187                       par->next_plane, dst, dst_idx, width,
3188                       rect->color);
3189             break;
3190 
3191         case ROP_XOR:
3192             xor_one_line(info->var.bits_per_pixel, par->next_plane,
3193                      dst, dst_idx, width, rect->color);
3194             break;
3195         }
3196         dst_idx += par->next_line * 8;
3197     }
3198 }
3199 
3200 static inline void copy_one_line(int bpp, unsigned long next_plane,
3201                  unsigned long *dst, int dst_idx,
3202                  unsigned long *src, int src_idx, u32 n)
3203 {
3204     while (1) {
3205         dst += dst_idx >> SHIFT_PER_LONG;
3206         dst_idx &= (BITS_PER_LONG - 1);
3207         src += src_idx >> SHIFT_PER_LONG;
3208         src_idx &= (BITS_PER_LONG - 1);
3209         bitcpy(dst, dst_idx, src, src_idx, n);
3210         if (!--bpp)
3211             break;
3212         dst_idx += next_plane * 8;
3213         src_idx += next_plane * 8;
3214     }
3215 }
3216 
3217 static inline void copy_one_line_rev(int bpp, unsigned long next_plane,
3218                      unsigned long *dst, int dst_idx,
3219                      unsigned long *src, int src_idx, u32 n)
3220 {
3221     while (1) {
3222         dst += dst_idx >> SHIFT_PER_LONG;
3223         dst_idx &= (BITS_PER_LONG - 1);
3224         src += src_idx >> SHIFT_PER_LONG;
3225         src_idx &= (BITS_PER_LONG - 1);
3226         bitcpy_rev(dst, dst_idx, src, src_idx, n);
3227         if (!--bpp)
3228             break;
3229         dst_idx += next_plane * 8;
3230         src_idx += next_plane * 8;
3231     }
3232 }
3233 
3234 
3235 static void amifb_copyarea(struct fb_info *info,
3236                const struct fb_copyarea *area)
3237 {
3238     struct amifb_par *par = info->par;
3239     int x2, y2;
3240     u32 dx, dy, sx, sy, width, height;
3241     unsigned long *dst, *src;
3242     int dst_idx, src_idx;
3243     int rev_copy = 0;
3244 
3245     /* clip the destination */
3246     x2 = area->dx + area->width;
3247     y2 = area->dy + area->height;
3248     dx = area->dx > 0 ? area->dx : 0;
3249     dy = area->dy > 0 ? area->dy : 0;
3250     x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
3251     y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
3252     width = x2 - dx;
3253     height = y2 - dy;
3254 
3255     if (area->sx + dx < area->dx || area->sy + dy < area->dy)
3256         return;
3257 
3258     /* update sx,sy */
3259     sx = area->sx + (dx - area->dx);
3260     sy = area->sy + (dy - area->dy);
3261 
3262     /* the source must be completely inside the virtual screen */
3263     if (sx + width > info->var.xres_virtual ||
3264             sy + height > info->var.yres_virtual)
3265         return;
3266 
3267     if (dy > sy || (dy == sy && dx > sx)) {
3268         dy += height;
3269         sy += height;
3270         rev_copy = 1;
3271     }
3272     dst = (unsigned long *)
3273         ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
3274     src = dst;
3275     dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
3276     src_idx = dst_idx;
3277     dst_idx += dy * par->next_line * 8 + dx;
3278     src_idx += sy * par->next_line * 8 + sx;
3279     if (rev_copy) {
3280         while (height--) {
3281             dst_idx -= par->next_line * 8;
3282             src_idx -= par->next_line * 8;
3283             copy_one_line_rev(info->var.bits_per_pixel,
3284                       par->next_plane, dst, dst_idx, src,
3285                       src_idx, width);
3286         }
3287     } else {
3288         while (height--) {
3289             copy_one_line(info->var.bits_per_pixel,
3290                       par->next_plane, dst, dst_idx, src,
3291                       src_idx, width);
3292             dst_idx += par->next_line * 8;
3293             src_idx += par->next_line * 8;
3294         }
3295     }
3296 }
3297 
3298 
3299 static inline void expand_one_line(int bpp, unsigned long next_plane,
3300                    unsigned long *dst, int dst_idx, u32 n,
3301                    const u8 *data, u32 bgcolor, u32 fgcolor)
3302 {
3303     const unsigned long *src;
3304     int src_idx;
3305 
3306     while (1) {
3307         dst += dst_idx >> SHIFT_PER_LONG;
3308         dst_idx &= (BITS_PER_LONG - 1);
3309         if ((bgcolor ^ fgcolor) & 1) {
3310             src = (unsigned long *)
3311                 ((unsigned long)data & ~(BYTES_PER_LONG - 1));
3312             src_idx = ((unsigned long)data & (BYTES_PER_LONG - 1)) * 8;
3313             if (fgcolor & 1)
3314                 bitcpy(dst, dst_idx, src, src_idx, n);
3315             else
3316                 bitcpy_not(dst, dst_idx, src, src_idx, n);
3317             /* set or clear */
3318         } else
3319             bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n);
3320         if (!--bpp)
3321             break;
3322         bgcolor >>= 1;
3323         fgcolor >>= 1;
3324         dst_idx += next_plane * 8;
3325     }
3326 }
3327 
3328 
3329 static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
3330 {
3331     struct amifb_par *par = info->par;
3332     int x2, y2;
3333     unsigned long *dst;
3334     int dst_idx;
3335     const char *src;
3336     u32 dx, dy, width, height, pitch;
3337 
3338     /*
3339      * We could use hardware clipping but on many cards you get around
3340      * hardware clipping by writing to framebuffer directly like we are
3341      * doing here.
3342      */
3343     x2 = image->dx + image->width;
3344     y2 = image->dy + image->height;
3345     dx = image->dx;
3346     dy = image->dy;
3347     x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
3348     y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
3349     width  = x2 - dx;
3350     height = y2 - dy;
3351 
3352     if (image->depth == 1) {
3353         dst = (unsigned long *)
3354             ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
3355         dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
3356         dst_idx += dy * par->next_line * 8 + dx;
3357         src = image->data;
3358         pitch = (image->width + 7) / 8;
3359         while (height--) {
3360             expand_one_line(info->var.bits_per_pixel,
3361                     par->next_plane, dst, dst_idx, width,
3362                     src, image->bg_color,
3363                     image->fg_color);
3364             dst_idx += par->next_line * 8;
3365             src += pitch;
3366         }
3367     } else {
3368         c2p_planar(info->screen_base, image->data, dx, dy, width,
3369                height, par->next_line, par->next_plane,
3370                image->width, info->var.bits_per_pixel);
3371     }
3372 }
3373 
3374 
3375     /*
3376      * Amiga Frame Buffer Specific ioctls
3377      */
3378 
3379 static int amifb_ioctl(struct fb_info *info,
3380                unsigned int cmd, unsigned long arg)
3381 {
3382     union {
3383         struct fb_fix_cursorinfo fix;
3384         struct fb_var_cursorinfo var;
3385         struct fb_cursorstate state;
3386     } crsr;
3387     void __user *argp = (void __user *)arg;
3388     int i;
3389 
3390     switch (cmd) {
3391     case FBIOGET_FCURSORINFO:
3392         i = ami_get_fix_cursorinfo(&crsr.fix, info->par);
3393         if (i)
3394             return i;
3395         return copy_to_user(argp, &crsr.fix,
3396                     sizeof(crsr.fix)) ? -EFAULT : 0;
3397 
3398     case FBIOGET_VCURSORINFO:
3399         i = ami_get_var_cursorinfo(&crsr.var,
3400             ((struct fb_var_cursorinfo __user *)arg)->data,
3401             info->par);
3402         if (i)
3403             return i;
3404         return copy_to_user(argp, &crsr.var,
3405                     sizeof(crsr.var)) ? -EFAULT : 0;
3406 
3407     case FBIOPUT_VCURSORINFO:
3408         if (copy_from_user(&crsr.var, argp, sizeof(crsr.var)))
3409             return -EFAULT;
3410         return ami_set_var_cursorinfo(&crsr.var,
3411             ((struct fb_var_cursorinfo __user *)arg)->data,
3412             info->par);
3413 
3414     case FBIOGET_CURSORSTATE:
3415         i = ami_get_cursorstate(&crsr.state, info->par);
3416         if (i)
3417             return i;
3418         return copy_to_user(argp, &crsr.state,
3419                     sizeof(crsr.state)) ? -EFAULT : 0;
3420 
3421     case FBIOPUT_CURSORSTATE:
3422         if (copy_from_user(&crsr.state, argp, sizeof(crsr.state)))
3423             return -EFAULT;
3424         return ami_set_cursorstate(&crsr.state, info->par);
3425     }
3426     return -EINVAL;
3427 }
3428 
3429 
3430     /*
3431      * Flash the cursor (called by VBlank interrupt)
3432      */
3433 
3434 static int flash_cursor(void)
3435 {
3436     static int cursorcount = 1;
3437 
3438     if (cursormode == FB_CURSOR_FLASH) {
3439         if (!--cursorcount) {
3440             cursorstate = -cursorstate;
3441             cursorcount = cursorrate;
3442             if (!is_blanked)
3443                 return 1;
3444         }
3445     }
3446     return 0;
3447 }
3448 
3449     /*
3450      * VBlank Display Interrupt
3451      */
3452 
3453 static irqreturn_t amifb_interrupt(int irq, void *dev_id)
3454 {
3455     struct amifb_par *par = dev_id;
3456 
3457     if (do_vmode_pan || do_vmode_full)
3458         ami_update_display(par);
3459 
3460     if (do_vmode_full)
3461         ami_init_display(par);
3462 
3463     if (do_vmode_pan) {
3464         flash_cursor();
3465         ami_rebuild_copper(par);
3466         do_cursor = do_vmode_pan = 0;
3467     } else if (do_cursor) {
3468         flash_cursor();
3469         ami_set_sprite(par);
3470         do_cursor = 0;
3471     } else {
3472         if (flash_cursor())
3473             ami_set_sprite(par);
3474     }
3475 
3476     if (do_blank) {
3477         ami_do_blank(par);
3478         do_blank = 0;
3479     }
3480 
3481     if (do_vmode_full) {
3482         ami_reinit_copper(par);
3483         do_vmode_full = 0;
3484     }
3485     return IRQ_HANDLED;
3486 }
3487 
3488 
3489 static const struct fb_ops amifb_ops = {
3490     .owner      = THIS_MODULE,
3491     .fb_check_var   = amifb_check_var,
3492     .fb_set_par = amifb_set_par,
3493     .fb_setcolreg   = amifb_setcolreg,
3494     .fb_blank   = amifb_blank,
3495     .fb_pan_display = amifb_pan_display,
3496     .fb_fillrect    = amifb_fillrect,
3497     .fb_copyarea    = amifb_copyarea,
3498     .fb_imageblit   = amifb_imageblit,
3499     .fb_ioctl   = amifb_ioctl,
3500 };
3501 
3502 
3503     /*
3504      * Allocate, Clear and Align a Block of Chip Memory
3505      */
3506 
3507 static void *aligned_chipptr;
3508 
3509 static inline u_long __init chipalloc(u_long size)
3510 {
3511     aligned_chipptr = amiga_chip_alloc(size, "amifb [RAM]");
3512     if (!aligned_chipptr) {
3513         pr_err("amifb: No Chip RAM for frame buffer");
3514         return 0;
3515     }
3516     memset(aligned_chipptr, 0, size);
3517     return (u_long)aligned_chipptr;
3518 }
3519 
3520 static inline void chipfree(void)
3521 {
3522     if (aligned_chipptr)
3523         amiga_chip_free(aligned_chipptr);
3524 }
3525 
3526 
3527     /*
3528      * Initialisation
3529      */
3530 
3531 static int __init amifb_probe(struct platform_device *pdev)
3532 {
3533     struct fb_info *info;
3534     int tag, i, err = 0;
3535     u_long chipptr;
3536     u_int defmode;
3537 
3538 #ifndef MODULE
3539     char *option = NULL;
3540 
3541     if (fb_get_options("amifb", &option)) {
3542         amifb_video_off();
3543         return -ENODEV;
3544     }
3545     amifb_setup(option);
3546 #endif
3547     custom.dmacon = DMAF_ALL | DMAF_MASTER;
3548 
3549     info = framebuffer_alloc(sizeof(struct amifb_par), &pdev->dev);
3550     if (!info)
3551         return -ENOMEM;
3552 
3553     strcpy(info->fix.id, "Amiga ");
3554     info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
3555     info->fix.accel = FB_ACCEL_AMIGABLITT;
3556 
3557     switch (amiga_chipset) {
3558 #ifdef CONFIG_FB_AMIGA_OCS
3559     case CS_OCS:
3560         strcat(info->fix.id, "OCS");
3561 default_chipset:
3562         chipset = TAG_OCS;
3563         maxdepth[TAG_SHRES] = 0;    /* OCS means no SHRES */
3564         maxdepth[TAG_HIRES] = 4;
3565         maxdepth[TAG_LORES] = 6;
3566         maxfmode = TAG_FMODE_1;
3567         defmode = amiga_vblank == 50 ? DEFMODE_PAL : DEFMODE_NTSC;
3568         info->fix.smem_len = VIDEOMEMSIZE_OCS;
3569         break;
3570 #endif /* CONFIG_FB_AMIGA_OCS */
3571 
3572 #ifdef CONFIG_FB_AMIGA_ECS
3573     case CS_ECS:
3574         strcat(info->fix.id, "ECS");
3575         chipset = TAG_ECS;
3576         maxdepth[TAG_SHRES] = 2;
3577         maxdepth[TAG_HIRES] = 4;
3578         maxdepth[TAG_LORES] = 6;
3579         maxfmode = TAG_FMODE_1;
3580         if (AMIGAHW_PRESENT(AMBER_FF))
3581             defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL
3582                              : DEFMODE_AMBER_NTSC;
3583         else
3584             defmode = amiga_vblank == 50 ? DEFMODE_PAL
3585                              : DEFMODE_NTSC;
3586         if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
3587             VIDEOMEMSIZE_ECS_2M)
3588             info->fix.smem_len = VIDEOMEMSIZE_ECS_2M;
3589         else
3590             info->fix.smem_len = VIDEOMEMSIZE_ECS_1M;
3591         break;
3592 #endif /* CONFIG_FB_AMIGA_ECS */
3593 
3594 #ifdef CONFIG_FB_AMIGA_AGA
3595     case CS_AGA:
3596         strcat(info->fix.id, "AGA");
3597         chipset = TAG_AGA;
3598         maxdepth[TAG_SHRES] = 8;
3599         maxdepth[TAG_HIRES] = 8;
3600         maxdepth[TAG_LORES] = 8;
3601         maxfmode = TAG_FMODE_4;
3602         defmode = DEFMODE_AGA;
3603         if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
3604             VIDEOMEMSIZE_AGA_2M)
3605             info->fix.smem_len = VIDEOMEMSIZE_AGA_2M;
3606         else
3607             info->fix.smem_len = VIDEOMEMSIZE_AGA_1M;
3608         break;
3609 #endif /* CONFIG_FB_AMIGA_AGA */
3610 
3611     default:
3612 #ifdef CONFIG_FB_AMIGA_OCS
3613         printk("Unknown graphics chipset, defaulting to OCS\n");
3614         strcat(info->fix.id, "Unknown");
3615         goto default_chipset;
3616 #else /* CONFIG_FB_AMIGA_OCS */
3617         err = -ENODEV;
3618         goto release;
3619 #endif /* CONFIG_FB_AMIGA_OCS */
3620         break;
3621     }
3622 
3623     /*
3624      * Calculate the Pixel Clock Values for this Machine
3625      */
3626 
3627     {
3628     u_long tmp = DIVUL(200000000000ULL, amiga_eclock);
3629 
3630     pixclock[TAG_SHRES] = (tmp + 4) / 8;    /* SHRES:  35 ns / 28 MHz */
3631     pixclock[TAG_HIRES] = (tmp + 2) / 4;    /* HIRES:  70 ns / 14 MHz */
3632     pixclock[TAG_LORES] = (tmp + 1) / 2;    /* LORES: 140 ns /  7 MHz */
3633     }
3634 
3635     /*
3636      * Replace the Tag Values with the Real Pixel Clock Values
3637      */
3638 
3639     for (i = 0; i < NUM_TOTAL_MODES; i++) {
3640         struct fb_videomode *mode = &ami_modedb[i];
3641         tag = mode->pixclock;
3642         if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) {
3643             mode->pixclock = pixclock[tag];
3644         }
3645     }
3646 
3647     if (amifb_hfmin) {
3648         info->monspecs.hfmin = amifb_hfmin;
3649         info->monspecs.hfmax = amifb_hfmax;
3650         info->monspecs.vfmin = amifb_vfmin;
3651         info->monspecs.vfmax = amifb_vfmax;
3652     } else {
3653         /*
3654          *  These are for a typical Amiga monitor (e.g. A1960)
3655          */
3656         info->monspecs.hfmin = 15000;
3657         info->monspecs.hfmax = 38000;
3658         info->monspecs.vfmin = 49;
3659         info->monspecs.vfmax = 90;
3660     }
3661 
3662     info->fbops = &amifb_ops;
3663     info->flags = FBINFO_DEFAULT;
3664     info->device = &pdev->dev;
3665 
3666     if (!fb_find_mode(&info->var, info, mode_option, ami_modedb,
3667               NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
3668         err = -EINVAL;
3669         goto release;
3670     }
3671 
3672     fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES,
3673                  &info->modelist);
3674 
3675     round_down_bpp = 0;
3676     chipptr = chipalloc(info->fix.smem_len + SPRITEMEMSIZE +
3677                 DUMMYSPRITEMEMSIZE + COPINITSIZE +
3678                 4 * COPLISTSIZE);
3679     if (!chipptr) {
3680         err = -ENOMEM;
3681         goto release;
3682     }
3683 
3684     assignchunk(videomemory, u_long, chipptr, info->fix.smem_len);
3685     assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE);
3686     assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE);
3687     assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE);
3688     assignchunk(copdisplay.list[0][0], copins *, chipptr, COPLISTSIZE);
3689     assignchunk(copdisplay.list[0][1], copins *, chipptr, COPLISTSIZE);
3690     assignchunk(copdisplay.list[1][0], copins *, chipptr, COPLISTSIZE);
3691     assignchunk(copdisplay.list[1][1], copins *, chipptr, COPLISTSIZE);
3692 
3693     /*
3694      * access the videomem with writethrough cache
3695      */
3696     info->fix.smem_start = (u_long)ZTWO_PADDR(videomemory);
3697     videomemory = (u_long)ioremap_wt(info->fix.smem_start,
3698                      info->fix.smem_len);
3699     if (!videomemory) {
3700         dev_warn(&pdev->dev,
3701              "Unable to map videomem cached writethrough\n");
3702         info->screen_base = ZTWO_VADDR(info->fix.smem_start);
3703     } else
3704         info->screen_base = (char *)videomemory;
3705 
3706     memset(dummysprite, 0, DUMMYSPRITEMEMSIZE);
3707 
3708     /*
3709      * Make sure the Copper has something to do
3710      */
3711     ami_init_copper();
3712 
3713     /*
3714      * Enable Display DMA
3715      */
3716     custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
3717             DMAF_BLITTER | DMAF_SPRITE;
3718 
3719     err = request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0,
3720               "fb vertb handler", info->par);
3721     if (err)
3722         goto disable_dma;
3723 
3724     err = fb_alloc_cmap(&info->cmap, 1 << info->var.bits_per_pixel, 0);
3725     if (err)
3726         goto free_irq;
3727 
3728     platform_set_drvdata(pdev, info);
3729 
3730     err = register_framebuffer(info);
3731     if (err)
3732         goto unset_drvdata;
3733 
3734     fb_info(info, "%s frame buffer device, using %dK of video memory\n",
3735         info->fix.id, info->fix.smem_len>>10);
3736 
3737     return 0;
3738 
3739 unset_drvdata:
3740     fb_dealloc_cmap(&info->cmap);
3741 free_irq:
3742     free_irq(IRQ_AMIGA_COPPER, info->par);
3743 disable_dma:
3744     custom.dmacon = DMAF_ALL | DMAF_MASTER;
3745     if (videomemory)
3746         iounmap((void *)videomemory);
3747     chipfree();
3748 release:
3749     framebuffer_release(info);
3750     return err;
3751 }
3752 
3753 
3754 static int __exit amifb_remove(struct platform_device *pdev)
3755 {
3756     struct fb_info *info = platform_get_drvdata(pdev);
3757 
3758     unregister_framebuffer(info);
3759     fb_dealloc_cmap(&info->cmap);
3760     free_irq(IRQ_AMIGA_COPPER, info->par);
3761     custom.dmacon = DMAF_ALL | DMAF_MASTER;
3762     if (videomemory)
3763         iounmap((void *)videomemory);
3764     chipfree();
3765     framebuffer_release(info);
3766     amifb_video_off();
3767     return 0;
3768 }
3769 
3770 static struct platform_driver amifb_driver = {
3771     .remove = __exit_p(amifb_remove),
3772     .driver   = {
3773         .name   = "amiga-video",
3774     },
3775 };
3776 
3777 module_platform_driver_probe(amifb_driver, amifb_probe);
3778 
3779 MODULE_LICENSE("GPL");
3780 MODULE_ALIAS("platform:amiga-video");