Back to home page

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