root/drivers/video/fbdev/amifb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ami_decode_var
  2. ami_encode_var
  3. ami_update_par
  4. ami_pan_var
  5. ami_update_display
  6. ami_init_display
  7. ami_do_blank
  8. ami_get_fix_cursorinfo
  9. ami_get_var_cursorinfo
  10. ami_set_var_cursorinfo
  11. ami_get_cursorstate
  12. ami_set_cursorstate
  13. ami_set_sprite
  14. ami_init_copper
  15. ami_reinit_copper
  16. ami_rebuild_copper
  17. ami_build_copper
  18. amifb_setup_mcap
  19. amifb_setup
  20. amifb_check_var
  21. amifb_set_par
  22. amifb_setcolreg
  23. amifb_blank
  24. amifb_pan_display
  25. comp
  26. xor
  27. bitcpy
  28. bitcpy_rev
  29. bitcpy_not
  30. bitfill32
  31. bitxor32
  32. fill_one_line
  33. xor_one_line
  34. amifb_fillrect
  35. copy_one_line
  36. copy_one_line_rev
  37. amifb_copyarea
  38. expand_one_line
  39. amifb_imageblit
  40. amifb_ioctl
  41. flash_cursor
  42. amifb_interrupt
  43. chipalloc
  44. chipfree
  45. amifb_probe
  46. amifb_remove

   1 /*
   2  * linux/drivers/video/amifb.c -- Amiga builtin chipset frame buffer device
   3  *
   4  *    Copyright (C) 1995-2003 Geert Uytterhoeven
   5  *
   6  *          with work by Roman Zippel
   7  *
   8  *
   9  * This file is based on the Atari frame buffer device (atafb.c):
  10  *
  11  *    Copyright (C) 1994 Martin Schaller
  12  *                       Roman Hodek
  13  *
  14  *          with work by Andreas Schwab
  15  *                       Guenther Kelleter
  16  *
  17  * and on the original Amiga console driver (amicon.c):
  18  *
  19  *    Copyright (C) 1993 Hamish Macdonald
  20  *                       Greg Harp
  21  *    Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk]
  22  *
  23  *          with work by William Rucklidge (wjr@cs.cornell.edu)
  24  *                       Geert Uytterhoeven
  25  *                       Jes Sorensen (jds@kom.auc.dk)
  26  *
  27  *
  28  * History:
  29  *
  30  *   - 24 Jul 96: Copper generates now vblank interrupt and
  31  *                VESA Power Saving Protocol is fully implemented
  32  *   - 14 Jul 96: Rework and hopefully last ECS bugs fixed
  33  *   -  7 Mar 96: Hardware sprite support by Roman Zippel
  34  *   - 18 Feb 96: OCS and ECS support by Roman Zippel
  35  *                Hardware functions completely rewritten
  36  *   -  2 Dec 95: AGA version by Geert Uytterhoeven
  37  *
  38  * This file is subject to the terms and conditions of the GNU General Public
  39  * License. See the file COPYING in the main directory of this archive
  40  * for more details.
  41  */
  42 
  43 #include <linux/module.h>
  44 #include <linux/kernel.h>
  45 #include <linux/errno.h>
  46 #include <linux/string.h>
  47 #include <linux/mm.h>
  48 #include <linux/delay.h>
  49 #include <linux/interrupt.h>
  50 #include <linux/fb.h>
  51 #include <linux/init.h>
  52 #include <linux/ioport.h>
  53 #include <linux/platform_device.h>
  54 #include <linux/uaccess.h>
  55 
  56 #include <asm/irq.h>
  57 #include <asm/amigahw.h>
  58 #include <asm/amigaints.h>
  59 #include <asm/setup.h>
  60 
  61 #include "c2p.h"
  62 
  63 
  64 #define DEBUG
  65 
  66 #if !defined(CONFIG_FB_AMIGA_OCS) && !defined(CONFIG_FB_AMIGA_ECS) && !defined(CONFIG_FB_AMIGA_AGA)
  67 #define CONFIG_FB_AMIGA_OCS   /* define at least one fb driver, this will change later */
  68 #endif
  69 
  70 #if !defined(CONFIG_FB_AMIGA_OCS)
  71 #  define IS_OCS (0)
  72 #elif defined(CONFIG_FB_AMIGA_ECS) || defined(CONFIG_FB_AMIGA_AGA)
  73 #  define IS_OCS (chipset == TAG_OCS)
  74 #else
  75 #  define CONFIG_FB_AMIGA_OCS_ONLY
  76 #  define IS_OCS (1)
  77 #endif
  78 
  79 #if !defined(CONFIG_FB_AMIGA_ECS)
  80 #  define IS_ECS (0)
  81 #elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_AGA)
  82 #  define IS_ECS (chipset == TAG_ECS)
  83 #else
  84 #  define CONFIG_FB_AMIGA_ECS_ONLY
  85 #  define IS_ECS (1)
  86 #endif
  87 
  88 #if !defined(CONFIG_FB_AMIGA_AGA)
  89 #  define IS_AGA (0)
  90 #elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_ECS)
  91 #  define IS_AGA (chipset == TAG_AGA)
  92 #else
  93 #  define CONFIG_FB_AMIGA_AGA_ONLY
  94 #  define IS_AGA (1)
  95 #endif
  96 
  97 #ifdef DEBUG
  98 #  define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
  99 #else
 100 #  define DPRINTK(fmt, args...)
 101 #endif
 102 
 103 /*******************************************************************************
 104 
 105 
 106    Generic video timings
 107    ---------------------
 108 
 109    Timings used by the frame buffer interface:
 110 
 111    +----------+---------------------------------------------+----------+-------+
 112    |          |                ^                            |          |       |
 113    |          |                |upper_margin                |          |       |
 114    |          |                v                            |          |       |
 115    +----------###############################################----------+-------+
 116    |          #                ^                            #          |       |
 117    |          #                |                            #          |       |
 118    |          #                |                            #          |       |
 119    |          #                |                            #          |       |
 120    |   left   #                |                            #  right   | hsync |
 121    |  margin  #                |       xres                 #  margin  |  len  |
 122    |<-------->#<---------------+--------------------------->#<-------->|<----->|
 123    |          #                |                            #          |       |
 124    |          #                |                            #          |       |
 125    |          #                |                            #          |       |
 126    |          #                |yres                        #          |       |
 127    |          #                |                            #          |       |
 128    |          #                |                            #          |       |
 129    |          #                |                            #          |       |
 130    |          #                |                            #          |       |
 131    |          #                |                            #          |       |
 132    |          #                |                            #          |       |
 133    |          #                |                            #          |       |
 134    |          #                |                            #          |       |
 135    |          #                v                            #          |       |
 136    +----------###############################################----------+-------+
 137    |          |                ^                            |          |       |
 138    |          |                |lower_margin                |          |       |
 139    |          |                v                            |          |       |
 140    +----------+---------------------------------------------+----------+-------+
 141    |          |                ^                            |          |       |
 142    |          |                |vsync_len                   |          |       |
 143    |          |                v                            |          |       |
 144    +----------+---------------------------------------------+----------+-------+
 145 
 146 
 147    Amiga video timings
 148    -------------------
 149 
 150    The Amiga native chipsets uses another timing scheme:
 151 
 152       - hsstrt:   Start of horizontal synchronization pulse
 153       - hsstop:   End of horizontal synchronization pulse
 154       - htotal:   Last value on the line (i.e. line length = htotal + 1)
 155       - vsstrt:   Start of vertical synchronization pulse
 156       - vsstop:   End of vertical synchronization pulse
 157       - vtotal:   Last line value (i.e. number of lines = vtotal + 1)
 158       - hcenter:  Start of vertical retrace for interlace
 159 
 160    You can specify the blanking timings independently. Currently I just set
 161    them equal to the respective synchronization values:
 162 
 163       - hbstrt:   Start of horizontal blank
 164       - hbstop:   End of horizontal blank
 165       - vbstrt:   Start of vertical blank
 166       - vbstop:   End of vertical blank
 167 
 168    Horizontal values are in color clock cycles (280 ns), vertical values are in
 169    scanlines.
 170 
 171    (0, 0) is somewhere in the upper-left corner :-)
 172 
 173 
 174    Amiga visible window definitions
 175    --------------------------------
 176 
 177    Currently I only have values for AGA, SHRES (28 MHz dotclock). Feel free to
 178    make corrections and/or additions.
 179 
 180    Within the above synchronization specifications, the visible window is
 181    defined by the following parameters (actual register resolutions may be
 182    different; all horizontal values are normalized with respect to the pixel
 183    clock):
 184 
 185       - diwstrt_h:   Horizontal start of the visible window
 186       - diwstop_h:   Horizontal stop + 1(*) of the visible window
 187       - diwstrt_v:   Vertical start of the visible window
 188       - diwstop_v:   Vertical stop of the visible window
 189       - ddfstrt:     Horizontal start of display DMA
 190       - ddfstop:     Horizontal stop of display DMA
 191       - hscroll:     Horizontal display output delay
 192 
 193    Sprite positioning:
 194 
 195       - sprstrt_h:   Horizontal start - 4 of sprite
 196       - sprstrt_v:   Vertical start of sprite
 197 
 198    (*) Even Commodore did it wrong in the AGA monitor drivers by not adding 1.
 199 
 200    Horizontal values are in dotclock cycles (35 ns), vertical values are in
 201    scanlines.
 202 
 203    (0, 0) is somewhere in the upper-left corner :-)
 204 
 205 
 206    Dependencies (AGA, SHRES (35 ns dotclock))
 207    -------------------------------------------
 208 
 209    Since there are much more parameters for the Amiga display than for the
 210    frame buffer interface, there must be some dependencies among the Amiga
 211    display parameters. Here's what I found out:
 212 
 213       - ddfstrt and ddfstop are best aligned to 64 pixels.
 214       - the chipset needs 64 + 4 horizontal pixels after the DMA start before
 215         the first pixel is output, so diwstrt_h = ddfstrt + 64 + 4 if you want
 216         to display the first pixel on the line too. Increase diwstrt_h for
 217         virtual screen panning.
 218       - the display DMA always fetches 64 pixels at a time (fmode = 3).
 219       - ddfstop is ddfstrt+#pixels - 64.
 220       - diwstop_h = diwstrt_h + xres + 1. Because of the additional 1 this can
 221         be 1 more than htotal.
 222       - hscroll simply adds a delay to the display output. Smooth horizontal
 223         panning needs an extra 64 pixels on the left to prefetch the pixels that
 224         `fall off' on the left.
 225       - if ddfstrt < 192, the sprite DMA cycles are all stolen by the bitplane
 226         DMA, so it's best to make the DMA start as late as possible.
 227       - you really don't want to make ddfstrt < 128, since this will steal DMA
 228         cycles from the other DMA channels (audio, floppy and Chip RAM refresh).
 229       - I make diwstop_h and diwstop_v as large as possible.
 230 
 231    General dependencies
 232    --------------------
 233 
 234       - all values are SHRES pixel (35ns)
 235 
 236                   table 1:fetchstart  table 2:prefetch    table 3:fetchsize
 237                   ------------------  ----------------    -----------------
 238    Pixclock     # SHRES|HIRES|LORES # SHRES|HIRES|LORES # SHRES|HIRES|LORES
 239    -------------#------+-----+------#------+-----+------#------+-----+------
 240    Bus width 1x #   16 |  32 |  64  #   16 |  32 |  64  #   64 |  64 |  64
 241    Bus width 2x #   32 |  64 | 128  #   32 |  64 |  64  #   64 |  64 | 128
 242    Bus width 4x #   64 | 128 | 256  #   64 |  64 |  64  #   64 | 128 | 256
 243 
 244       - chipset needs 4 pixels before the first pixel is output
 245       - ddfstrt must be aligned to fetchstart (table 1)
 246       - chipset needs also prefetch (table 2) to get first pixel data, so
 247         ddfstrt = ((diwstrt_h - 4) & -fetchstart) - prefetch
 248       - for horizontal panning decrease diwstrt_h
 249       - the length of a fetchline must be aligned to fetchsize (table 3)
 250       - if fetchstart is smaller than fetchsize, then ddfstrt can a little bit
 251         moved to optimize use of dma (useful for OCS/ECS overscan displays)
 252       - ddfstop is ddfstrt + ddfsize - fetchsize
 253       - If C= didn't change anything for AGA, then at following positions the
 254         dma bus is already used:
 255         ddfstrt <  48 -> memory refresh
 256                 <  96 -> disk dma
 257                 < 160 -> audio dma
 258                 < 192 -> sprite 0 dma
 259                 < 416 -> sprite dma (32 per sprite)
 260       - in accordance with the hardware reference manual a hardware stop is at
 261         192, but AGA (ECS?) can go below this.
 262 
 263    DMA priorities
 264    --------------
 265 
 266    Since there are limits on the earliest start value for display DMA and the
 267    display of sprites, I use the following policy on horizontal panning and
 268    the hardware cursor:
 269 
 270       - if you want to start display DMA too early, you lose the ability to
 271         do smooth horizontal panning (xpanstep 1 -> 64).
 272       - if you want to go even further, you lose the hardware cursor too.
 273 
 274    IMHO a hardware cursor is more important for X than horizontal scrolling,
 275    so that's my motivation.
 276 
 277 
 278    Implementation
 279    --------------
 280 
 281    ami_decode_var() converts the frame buffer values to the Amiga values. It's
 282    just a `straightforward' implementation of the above rules.
 283 
 284 
 285    Standard VGA timings
 286    --------------------
 287 
 288                xres  yres    left  right  upper  lower    hsync    vsync
 289                ----  ----    ----  -----  -----  -----    -----    -----
 290       80x25     720   400      27     45     35     12      108        2
 291       80x30     720   480      27     45     30      9      108        2
 292 
 293    These were taken from a XFree86 configuration file, recalculated for a 28 MHz
 294    dotclock (Amigas don't have a 25 MHz dotclock) and converted to frame buffer
 295    generic timings.
 296 
 297    As a comparison, graphics/monitor.h suggests the following:
 298 
 299                xres  yres    left  right  upper  lower    hsync    vsync
 300                ----  ----    ----  -----  -----  -----    -----    -----
 301 
 302       VGA       640   480      52    112     24     19    112 -      2 +
 303       VGA70     640   400      52    112     27     21    112 -      2 -
 304 
 305 
 306    Sync polarities
 307    ---------------
 308 
 309       VSYNC    HSYNC    Vertical size    Vertical total
 310       -----    -----    -------------    --------------
 311         +        +           Reserved          Reserved
 312         +        -                400               414
 313         -        +                350               362
 314         -        -                480               496
 315 
 316    Source: CL-GD542X Technical Reference Manual, Cirrus Logic, Oct 1992
 317 
 318 
 319    Broadcast video timings
 320    -----------------------
 321 
 322    According to the CCIR and RETMA specifications, we have the following values:
 323 
 324    CCIR -> PAL
 325    -----------
 326 
 327       - a scanline is 64 µs long, of which 52.48 µs are visible. This is about
 328         736 visible 70 ns pixels per line.
 329       - we have 625 scanlines, of which 575 are visible (interlaced); after
 330         rounding this becomes 576.
 331 
 332    RETMA -> NTSC
 333    -------------
 334 
 335       - a scanline is 63.5 µs long, of which 53.5 µs are visible.  This is about
 336         736 visible 70 ns pixels per line.
 337       - we have 525 scanlines, of which 485 are visible (interlaced); after
 338         rounding this becomes 484.
 339 
 340    Thus if you want a PAL compatible display, you have to do the following:
 341 
 342       - set the FB_SYNC_BROADCAST flag to indicate that standard broadcast
 343         timings are to be used.
 344       - make sure upper_margin + yres + lower_margin + vsync_len = 625 for an
 345         interlaced, 312 for a non-interlaced and 156 for a doublescanned
 346         display.
 347       - make sure left_margin + xres + right_margin + hsync_len = 1816 for a
 348         SHRES, 908 for a HIRES and 454 for a LORES display.
 349       - the left visible part begins at 360 (SHRES; HIRES:180, LORES:90),
 350         left_margin + 2 * hsync_len must be greater or equal.
 351       - the upper visible part begins at 48 (interlaced; non-interlaced:24,
 352         doublescanned:12), upper_margin + 2 * vsync_len must be greater or
 353         equal.
 354       - ami_encode_var() calculates margins with a hsync of 5320 ns and a vsync
 355         of 4 scanlines
 356 
 357    The settings for a NTSC compatible display are straightforward.
 358 
 359    Note that in a strict sense the PAL and NTSC standards only define the
 360    encoding of the color part (chrominance) of the video signal and don't say
 361    anything about horizontal/vertical synchronization nor refresh rates.
 362 
 363 
 364                                                             -- Geert --
 365 
 366 *******************************************************************************/
 367 
 368 
 369         /*
 370          * Custom Chipset Definitions
 371          */
 372 
 373 #define CUSTOM_OFS(fld) ((long)&((struct CUSTOM*)0)->fld)
 374 
 375         /*
 376          * BPLCON0 -- Bitplane Control Register 0
 377          */
 378 
 379 #define BPC0_HIRES      (0x8000)
 380 #define BPC0_BPU2       (0x4000) /* Bit plane used count */
 381 #define BPC0_BPU1       (0x2000)
 382 #define BPC0_BPU0       (0x1000)
 383 #define BPC0_HAM        (0x0800) /* HAM mode */
 384 #define BPC0_DPF        (0x0400) /* Double playfield */
 385 #define BPC0_COLOR      (0x0200) /* Enable colorburst */
 386 #define BPC0_GAUD       (0x0100) /* Genlock audio enable */
 387 #define BPC0_UHRES      (0x0080) /* Ultrahi res enable */
 388 #define BPC0_SHRES      (0x0040) /* Super hi res mode */
 389 #define BPC0_BYPASS     (0x0020) /* Bypass LUT - AGA */
 390 #define BPC0_BPU3       (0x0010) /* AGA */
 391 #define BPC0_LPEN       (0x0008) /* Light pen enable */
 392 #define BPC0_LACE       (0x0004) /* Interlace */
 393 #define BPC0_ERSY       (0x0002) /* External resync */
 394 #define BPC0_ECSENA     (0x0001) /* ECS enable */
 395 
 396         /*
 397          * BPLCON2 -- Bitplane Control Register 2
 398          */
 399 
 400 #define BPC2_ZDBPSEL2   (0x4000) /* Bitplane to be used for ZD - AGA */
 401 #define BPC2_ZDBPSEL1   (0x2000)
 402 #define BPC2_ZDBPSEL0   (0x1000)
 403 #define BPC2_ZDBPEN     (0x0800) /* Enable ZD with ZDBPSELx - AGA */
 404 #define BPC2_ZDCTEN     (0x0400) /* Enable ZD with palette bit #31 - AGA */
 405 #define BPC2_KILLEHB    (0x0200) /* Kill EHB mode - AGA */
 406 #define BPC2_RDRAM      (0x0100) /* Color table accesses read, not write - AGA */
 407 #define BPC2_SOGEN      (0x0080) /* SOG output pin high - AGA */
 408 #define BPC2_PF2PRI     (0x0040) /* PF2 priority over PF1 */
 409 #define BPC2_PF2P2      (0x0020) /* PF2 priority wrt sprites */
 410 #define BPC2_PF2P1      (0x0010)
 411 #define BPC2_PF2P0      (0x0008)
 412 #define BPC2_PF1P2      (0x0004) /* ditto PF1 */
 413 #define BPC2_PF1P1      (0x0002)
 414 #define BPC2_PF1P0      (0x0001)
 415 
 416         /*
 417          * BPLCON3 -- Bitplane Control Register 3 (AGA)
 418          */
 419 
 420 #define BPC3_BANK2      (0x8000) /* Bits to select color register bank */
 421 #define BPC3_BANK1      (0x4000)
 422 #define BPC3_BANK0      (0x2000)
 423 #define BPC3_PF2OF2     (0x1000) /* Bits for color table offset when PF2 */
 424 #define BPC3_PF2OF1     (0x0800)
 425 #define BPC3_PF2OF0     (0x0400)
 426 #define BPC3_LOCT       (0x0200) /* Color register writes go to low bits */
 427 #define BPC3_SPRES1     (0x0080) /* Sprite resolution bits */
 428 #define BPC3_SPRES0     (0x0040)
 429 #define BPC3_BRDRBLNK   (0x0020) /* Border blanked? */
 430 #define BPC3_BRDRTRAN   (0x0010) /* Border transparent? */
 431 #define BPC3_ZDCLKEN    (0x0004) /* ZD pin is 14 MHz (HIRES) clock output */
 432 #define BPC3_BRDRSPRT   (0x0002) /* Sprites in border? */
 433 #define BPC3_EXTBLKEN   (0x0001) /* BLANK programmable */
 434 
 435         /*
 436          * BPLCON4 -- Bitplane Control Register 4 (AGA)
 437          */
 438 
 439 #define BPC4_BPLAM7     (0x8000) /* bitplane color XOR field */
 440 #define BPC4_BPLAM6     (0x4000)
 441 #define BPC4_BPLAM5     (0x2000)
 442 #define BPC4_BPLAM4     (0x1000)
 443 #define BPC4_BPLAM3     (0x0800)
 444 #define BPC4_BPLAM2     (0x0400)
 445 #define BPC4_BPLAM1     (0x0200)
 446 #define BPC4_BPLAM0     (0x0100)
 447 #define BPC4_ESPRM7     (0x0080) /* 4 high bits for even sprite colors */
 448 #define BPC4_ESPRM6     (0x0040)
 449 #define BPC4_ESPRM5     (0x0020)
 450 #define BPC4_ESPRM4     (0x0010)
 451 #define BPC4_OSPRM7     (0x0008) /* 4 high bits for odd sprite colors */
 452 #define BPC4_OSPRM6     (0x0004)
 453 #define BPC4_OSPRM5     (0x0002)
 454 #define BPC4_OSPRM4     (0x0001)
 455 
 456         /*
 457          * BEAMCON0 -- Beam Control Register
 458          */
 459 
 460 #define BMC0_HARDDIS    (0x4000) /* Disable hardware limits */
 461 #define BMC0_LPENDIS    (0x2000) /* Disable light pen latch */
 462 #define BMC0_VARVBEN    (0x1000) /* Enable variable vertical blank */
 463 #define BMC0_LOLDIS     (0x0800) /* Disable long/short line toggle */
 464 #define BMC0_CSCBEN     (0x0400) /* Composite sync/blank */
 465 #define BMC0_VARVSYEN   (0x0200) /* Enable variable vertical sync */
 466 #define BMC0_VARHSYEN   (0x0100) /* Enable variable horizontal sync */
 467 #define BMC0_VARBEAMEN  (0x0080) /* Enable variable beam counters */
 468 #define BMC0_DUAL       (0x0040) /* Enable alternate horizontal beam counter */
 469 #define BMC0_PAL        (0x0020) /* Set decodes for PAL */
 470 #define BMC0_VARCSYEN   (0x0010) /* Enable variable composite sync */
 471 #define BMC0_BLANKEN    (0x0008) /* Blank enable (no longer used on AGA) */
 472 #define BMC0_CSYTRUE    (0x0004) /* CSY polarity */
 473 #define BMC0_VSYTRUE    (0x0002) /* VSY polarity */
 474 #define BMC0_HSYTRUE    (0x0001) /* HSY polarity */
 475 
 476 
 477         /*
 478          * FMODE -- Fetch Mode Control Register (AGA)
 479          */
 480 
 481 #define FMODE_SSCAN2    (0x8000) /* Sprite scan-doubling */
 482 #define FMODE_BSCAN2    (0x4000) /* Use PF2 modulus every other line */
 483 #define FMODE_SPAGEM    (0x0008) /* Sprite page mode */
 484 #define FMODE_SPR32     (0x0004) /* Sprite 32 bit fetch */
 485 #define FMODE_BPAGEM    (0x0002) /* Bitplane page mode */
 486 #define FMODE_BPL32     (0x0001) /* Bitplane 32 bit fetch */
 487 
 488         /*
 489          * Tags used to indicate a specific Pixel Clock
 490          *
 491          * clk_shift is the shift value to get the timings in 35 ns units
 492          */
 493 
 494 enum { TAG_SHRES, TAG_HIRES, TAG_LORES };
 495 
 496         /*
 497          * Tags used to indicate the specific chipset
 498          */
 499 
 500 enum { TAG_OCS, TAG_ECS, TAG_AGA };
 501 
 502         /*
 503          * Tags used to indicate the memory bandwidth
 504          */
 505 
 506 enum { TAG_FMODE_1, TAG_FMODE_2, TAG_FMODE_4 };
 507 
 508 
 509         /*
 510          * Clock Definitions, Maximum Display Depth
 511          *
 512          * These depend on the E-Clock or the Chipset, so they are filled in
 513          * dynamically
 514          */
 515 
 516 static u_long pixclock[3];      /* SHRES/HIRES/LORES: index = clk_shift */
 517 static u_short maxdepth[3];     /* SHRES/HIRES/LORES: index = clk_shift */
 518 static u_short maxfmode, chipset;
 519 
 520 
 521         /*
 522          * Broadcast Video Timings
 523          *
 524          * Horizontal values are in 35 ns (SHRES) units
 525          * Vertical values are in interlaced scanlines
 526          */
 527 
 528 #define PAL_DIWSTRT_H   (360)   /* PAL Window Limits */
 529 #define PAL_DIWSTRT_V   (48)
 530 #define PAL_HTOTAL      (1816)
 531 #define PAL_VTOTAL      (625)
 532 
 533 #define NTSC_DIWSTRT_H  (360)   /* NTSC Window Limits */
 534 #define NTSC_DIWSTRT_V  (40)
 535 #define NTSC_HTOTAL     (1816)
 536 #define NTSC_VTOTAL     (525)
 537 
 538 
 539         /*
 540          * Various macros
 541          */
 542 
 543 #define up2(v)          (((v) + 1) & -2)
 544 #define down2(v)        ((v) & -2)
 545 #define div2(v)         ((v)>>1)
 546 #define mod2(v)         ((v) & 1)
 547 
 548 #define up4(v)          (((v) + 3) & -4)
 549 #define down4(v)        ((v) & -4)
 550 #define mul4(v)         ((v) << 2)
 551 #define div4(v)         ((v)>>2)
 552 #define mod4(v)         ((v) & 3)
 553 
 554 #define up8(v)          (((v) + 7) & -8)
 555 #define down8(v)        ((v) & -8)
 556 #define div8(v)         ((v)>>3)
 557 #define mod8(v)         ((v) & 7)
 558 
 559 #define up16(v)         (((v) + 15) & -16)
 560 #define down16(v)       ((v) & -16)
 561 #define div16(v)        ((v)>>4)
 562 #define mod16(v)        ((v) & 15)
 563 
 564 #define up32(v)         (((v) + 31) & -32)
 565 #define down32(v)       ((v) & -32)
 566 #define div32(v)        ((v)>>5)
 567 #define mod32(v)        ((v) & 31)
 568 
 569 #define up64(v)         (((v) + 63) & -64)
 570 #define down64(v)       ((v) & -64)
 571 #define div64(v)        ((v)>>6)
 572 #define mod64(v)        ((v) & 63)
 573 
 574 #define upx(x, v)       (((v) + (x) - 1) & -(x))
 575 #define downx(x, v)     ((v) & -(x))
 576 #define modx(x, v)      ((v) & ((x) - 1))
 577 
 578 /* if x1 is not a constant, this macro won't make real sense :-) */
 579 #ifdef __mc68000__
 580 #define DIVUL(x1, x2) ({int res; asm("divul %1,%2,%3": "=d" (res): \
 581         "d" (x2), "d" ((long)((x1) / 0x100000000ULL)), "0" ((long)(x1))); res;})
 582 #else
 583 /* We know a bit about the numbers, so we can do it this way */
 584 #define DIVUL(x1, x2) ((((long)((unsigned long long)x1 >> 8) / x2) << 8) + \
 585         ((((long)((unsigned long long)x1 >> 8) % x2) << 8) / x2))
 586 #endif
 587 
 588 #define highw(x)        ((u_long)(x)>>16 & 0xffff)
 589 #define loww(x)         ((u_long)(x) & 0xffff)
 590 
 591 #define custom          amiga_custom
 592 
 593 #define VBlankOn()      custom.intena = IF_SETCLR|IF_COPER
 594 #define VBlankOff()     custom.intena = IF_COPER
 595 
 596 
 597         /*
 598          * Chip RAM we reserve for the Frame Buffer
 599          *
 600          * This defines the Maximum Virtual Screen Size
 601          * (Setable per kernel options?)
 602          */
 603 
 604 #define VIDEOMEMSIZE_AGA_2M     (1310720) /* AGA (2MB) : max 1280*1024*256  */
 605 #define VIDEOMEMSIZE_AGA_1M     (786432)  /* AGA (1MB) : max 1024*768*256   */
 606 #define VIDEOMEMSIZE_ECS_2M     (655360)  /* ECS (2MB) : max 1280*1024*16   */
 607 #define VIDEOMEMSIZE_ECS_1M     (393216)  /* ECS (1MB) : max 1024*768*16    */
 608 #define VIDEOMEMSIZE_OCS        (262144)  /* OCS       : max ca. 800*600*16 */
 609 
 610 #define SPRITEMEMSIZE           (64 * 64 / 4) /* max 64*64*4 */
 611 #define DUMMYSPRITEMEMSIZE      (8)
 612 static u_long spritememory;
 613 
 614 #define CHIPRAM_SAFETY_LIMIT    (16384)
 615 
 616 static u_long videomemory;
 617 
 618         /*
 619          * This is the earliest allowed start of fetching display data.
 620          * Only if you really want no hardware cursor and audio,
 621          * set this to 128, but let it better at 192
 622          */
 623 
 624 static u_long min_fstrt = 192;
 625 
 626 #define assignchunk(name, type, ptr, size) \
 627 { \
 628         (name) = (type)(ptr); \
 629         ptr += size; \
 630 }
 631 
 632 
 633         /*
 634          * Copper Instructions
 635          */
 636 
 637 #define CMOVE(val, reg)         (CUSTOM_OFS(reg) << 16 | (val))
 638 #define CMOVE2(val, reg)        ((CUSTOM_OFS(reg) + 2) << 16 | (val))
 639 #define CWAIT(x, y)             (((y) & 0x1fe) << 23 | ((x) & 0x7f0) << 13 | 0x0001fffe)
 640 #define CEND                    (0xfffffffe)
 641 
 642 
 643 typedef union {
 644         u_long l;
 645         u_short w[2];
 646 } copins;
 647 
 648 static struct copdisplay {
 649         copins *init;
 650         copins *wait;
 651         copins *list[2][2];
 652         copins *rebuild[2];
 653 } copdisplay;
 654 
 655 static u_short currentcop = 0;
 656 
 657         /*
 658          * Hardware Cursor API Definitions
 659          * These used to be in linux/fb.h, but were preliminary and used by
 660          * amifb only anyway
 661          */
 662 
 663 #define FBIOGET_FCURSORINFO     0x4607
 664 #define FBIOGET_VCURSORINFO     0x4608
 665 #define FBIOPUT_VCURSORINFO     0x4609
 666 #define FBIOGET_CURSORSTATE     0x460A
 667 #define FBIOPUT_CURSORSTATE     0x460B
 668 
 669 
 670 struct fb_fix_cursorinfo {
 671         __u16 crsr_width;               /* width and height of the cursor in */
 672         __u16 crsr_height;              /* pixels (zero if no cursor)   */
 673         __u16 crsr_xsize;               /* cursor size in display pixels */
 674         __u16 crsr_ysize;
 675         __u16 crsr_color1;              /* colormap entry for cursor color1 */
 676         __u16 crsr_color2;              /* colormap entry for cursor color2 */
 677 };
 678 
 679 struct fb_var_cursorinfo {
 680         __u16 width;
 681         __u16 height;
 682         __u16 xspot;
 683         __u16 yspot;
 684         __u8 data[1];                   /* field with [height][width]        */
 685 };
 686 
 687 struct fb_cursorstate {
 688         __s16 xoffset;
 689         __s16 yoffset;
 690         __u16 mode;
 691 };
 692 
 693 #define FB_CURSOR_OFF           0
 694 #define FB_CURSOR_ON            1
 695 #define FB_CURSOR_FLASH         2
 696 
 697 
 698         /*
 699          * Hardware Cursor
 700          */
 701 
 702 static int cursorrate = 20;     /* Number of frames/flash toggle */
 703 static u_short cursorstate = -1;
 704 static u_short cursormode = FB_CURSOR_OFF;
 705 
 706 static u_short *lofsprite, *shfsprite, *dummysprite;
 707 
 708         /*
 709          * Current Video Mode
 710          */
 711 
 712 struct amifb_par {
 713 
 714         /* General Values */
 715 
 716         int xres;               /* vmode */
 717         int yres;               /* vmode */
 718         int vxres;              /* vmode */
 719         int vyres;              /* vmode */
 720         int xoffset;            /* vmode */
 721         int yoffset;            /* vmode */
 722         u_short bpp;            /* vmode */
 723         u_short clk_shift;      /* vmode */
 724         u_short line_shift;     /* vmode */
 725         int vmode;              /* vmode */
 726         u_short diwstrt_h;      /* vmode */
 727         u_short diwstop_h;      /* vmode */
 728         u_short diwstrt_v;      /* vmode */
 729         u_short diwstop_v;      /* vmode */
 730         u_long next_line;       /* modulo for next line */
 731         u_long next_plane;      /* modulo for next plane */
 732 
 733         /* Cursor Values */
 734 
 735         struct {
 736                 short crsr_x;   /* movecursor */
 737                 short crsr_y;   /* movecursor */
 738                 short spot_x;
 739                 short spot_y;
 740                 u_short height;
 741                 u_short width;
 742                 u_short fmode;
 743         } crsr;
 744 
 745         /* OCS Hardware Registers */
 746 
 747         u_long bplpt0;          /* vmode, pan (Note: physical address) */
 748         u_long bplpt0wrap;      /* vmode, pan (Note: physical address) */
 749         u_short ddfstrt;
 750         u_short ddfstop;
 751         u_short bpl1mod;
 752         u_short bpl2mod;
 753         u_short bplcon0;        /* vmode */
 754         u_short bplcon1;        /* vmode */
 755         u_short htotal;         /* vmode */
 756         u_short vtotal;         /* vmode */
 757 
 758         /* Additional ECS Hardware Registers */
 759 
 760         u_short bplcon3;        /* vmode */
 761         u_short beamcon0;       /* vmode */
 762         u_short hsstrt;         /* vmode */
 763         u_short hsstop;         /* vmode */
 764         u_short hbstrt;         /* vmode */
 765         u_short hbstop;         /* vmode */
 766         u_short vsstrt;         /* vmode */
 767         u_short vsstop;         /* vmode */
 768         u_short vbstrt;         /* vmode */
 769         u_short vbstop;         /* vmode */
 770         u_short hcenter;        /* vmode */
 771 
 772         /* Additional AGA Hardware Registers */
 773 
 774         u_short fmode;          /* vmode */
 775 };
 776 
 777 
 778         /*
 779          *  Saved color entry 0 so we can restore it when unblanking
 780          */
 781 
 782 static u_char red0, green0, blue0;
 783 
 784 
 785 #if defined(CONFIG_FB_AMIGA_ECS)
 786 static u_short ecs_palette[32];
 787 #endif
 788 
 789 
 790         /*
 791          * Latches for Display Changes during VBlank
 792          */
 793 
 794 static u_short do_vmode_full = 0;       /* Change the Video Mode */
 795 static u_short do_vmode_pan = 0;        /* Update the Video Mode */
 796 static short do_blank = 0;              /* (Un)Blank the Screen (±1) */
 797 static u_short do_cursor = 0;           /* Move the Cursor */
 798 
 799 
 800         /*
 801          * Various Flags
 802          */
 803 
 804 static u_short is_blanked = 0;          /* Screen is Blanked */
 805 static u_short is_lace = 0;             /* Screen is laced */
 806 
 807         /*
 808          * Predefined Video Modes
 809          *
 810          */
 811 
 812 static struct fb_videomode ami_modedb[] __initdata = {
 813 
 814         /*
 815          *  AmigaOS Video Modes
 816          *
 817          *  If you change these, make sure to update DEFMODE_* as well!
 818          */
 819 
 820         {
 821                 /* 640x200, 15 kHz, 60 Hz (NTSC) */
 822                 "ntsc", 60, 640, 200, TAG_HIRES, 106, 86, 44, 16, 76, 2,
 823                 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 824         }, {
 825                 /* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */
 826                 "ntsc-lace", 60, 640, 400, TAG_HIRES, 106, 86, 88, 33, 76, 4,
 827                 FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
 828         }, {
 829                 /* 640x256, 15 kHz, 50 Hz (PAL) */
 830                 "pal", 50, 640, 256, TAG_HIRES, 106, 86, 40, 14, 76, 2,
 831                 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 832         }, {
 833                 /* 640x512, 15 kHz, 50 Hz interlaced (PAL) */
 834                 "pal-lace", 50, 640, 512, TAG_HIRES, 106, 86, 80, 29, 76, 4,
 835                 FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
 836         }, {
 837                 /* 640x480, 29 kHz, 57 Hz */
 838                 "multiscan", 57, 640, 480, TAG_SHRES, 96, 112, 29, 8, 72, 8,
 839                 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 840         }, {
 841                 /* 640x960, 29 kHz, 57 Hz interlaced */
 842                 "multiscan-lace", 57, 640, 960, TAG_SHRES, 96, 112, 58, 16, 72,
 843                 16,
 844                 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
 845         }, {
 846                 /* 640x200, 15 kHz, 72 Hz */
 847                 "euro36", 72, 640, 200, TAG_HIRES, 92, 124, 6, 6, 52, 5,
 848                 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 849         }, {
 850                 /* 640x400, 15 kHz, 72 Hz interlaced */
 851                 "euro36-lace", 72, 640, 400, TAG_HIRES, 92, 124, 12, 12, 52,
 852                 10,
 853                 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
 854         }, {
 855                 /* 640x400, 29 kHz, 68 Hz */
 856                 "euro72", 68, 640, 400, TAG_SHRES, 164, 92, 9, 9, 80, 8,
 857                 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 858         }, {
 859                 /* 640x800, 29 kHz, 68 Hz interlaced */
 860                 "euro72-lace", 68, 640, 800, TAG_SHRES, 164, 92, 18, 18, 80,
 861                 16,
 862                 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
 863         }, {
 864                 /* 800x300, 23 kHz, 70 Hz */
 865                 "super72", 70, 800, 300, TAG_SHRES, 212, 140, 10, 11, 80, 7,
 866                 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 867         }, {
 868                 /* 800x600, 23 kHz, 70 Hz interlaced */
 869                 "super72-lace", 70, 800, 600, TAG_SHRES, 212, 140, 20, 22, 80,
 870                 14,
 871                 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
 872         }, {
 873                 /* 640x200, 27 kHz, 57 Hz doublescan */
 874                 "dblntsc", 57, 640, 200, TAG_SHRES, 196, 124, 18, 17, 80, 4,
 875                 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
 876         }, {
 877                 /* 640x400, 27 kHz, 57 Hz */
 878                 "dblntsc-ff", 57, 640, 400, TAG_SHRES, 196, 124, 36, 35, 80, 7,
 879                 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 880         }, {
 881                 /* 640x800, 27 kHz, 57 Hz interlaced */
 882                 "dblntsc-lace", 57, 640, 800, TAG_SHRES, 196, 124, 72, 70, 80,
 883                 14,
 884                 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
 885         }, {
 886                 /* 640x256, 27 kHz, 47 Hz doublescan */
 887                 "dblpal", 47, 640, 256, TAG_SHRES, 196, 124, 14, 13, 80, 4,
 888                 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
 889         }, {
 890                 /* 640x512, 27 kHz, 47 Hz */
 891                 "dblpal-ff", 47, 640, 512, TAG_SHRES, 196, 124, 28, 27, 80, 7,
 892                 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 893         }, {
 894                 /* 640x1024, 27 kHz, 47 Hz interlaced */
 895                 "dblpal-lace", 47, 640, 1024, TAG_SHRES, 196, 124, 56, 54, 80,
 896                 14,
 897                 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
 898         },
 899 
 900         /*
 901          *  VGA Video Modes
 902          */
 903 
 904         {
 905                 /* 640x480, 31 kHz, 60 Hz (VGA) */
 906                 "vga", 60, 640, 480, TAG_SHRES, 64, 96, 30, 9, 112, 2,
 907                 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 908         }, {
 909                 /* 640x400, 31 kHz, 70 Hz (VGA) */
 910                 "vga70", 70, 640, 400, TAG_SHRES, 64, 96, 35, 12, 112, 2,
 911                 FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT,
 912                 FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 913         },
 914 
 915 #if 0
 916 
 917         /*
 918          *  A2024 video modes
 919          *  These modes don't work yet because there's no A2024 driver.
 920          */
 921 
 922         {
 923                 /* 1024x800, 10 Hz */
 924                 "a2024-10", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
 925                 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 926         }, {
 927                 /* 1024x800, 15 Hz */
 928                 "a2024-15", 15, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
 929                 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 930         }
 931 #endif
 932 };
 933 
 934 #define NUM_TOTAL_MODES  ARRAY_SIZE(ami_modedb)
 935 
 936 static char *mode_option __initdata = NULL;
 937 static int round_down_bpp = 1;  /* for mode probing */
 938 
 939         /*
 940          * Some default modes
 941          */
 942 
 943 
 944 #define DEFMODE_PAL         2   /* "pal" for PAL OCS/ECS */
 945 #define DEFMODE_NTSC        0   /* "ntsc" for NTSC OCS/ECS */
 946 #define DEFMODE_AMBER_PAL   3   /* "pal-lace" for flicker fixed PAL (A3000) */
 947 #define DEFMODE_AMBER_NTSC  1   /* "ntsc-lace" for flicker fixed NTSC (A3000) */
 948 #define DEFMODE_AGA         19  /* "vga70" for AGA */
 949 
 950 
 951 static int amifb_ilbm = 0;      /* interleaved or normal bitplanes */
 952 
 953 static u32 amifb_hfmin __initdata;      /* monitor hfreq lower limit (Hz) */
 954 static u32 amifb_hfmax __initdata;      /* monitor hfreq upper limit (Hz) */
 955 static u16 amifb_vfmin __initdata;      /* monitor vfreq lower limit (Hz) */
 956 static u16 amifb_vfmax __initdata;      /* monitor vfreq upper limit (Hz) */
 957 
 958 
 959         /*
 960          * Macros for the conversion from real world values to hardware register
 961          * values
 962          *
 963          * This helps us to keep our attention on the real stuff...
 964          *
 965          * Hardware limits for AGA:
 966          *
 967          *      parameter  min    max  step
 968          *      ---------  ---   ----  ----
 969          *      diwstrt_h    0   2047     1
 970          *      diwstrt_v    0   2047     1
 971          *      diwstop_h    0   4095     1
 972          *      diwstop_v    0   4095     1
 973          *
 974          *      ddfstrt      0   2032    16
 975          *      ddfstop      0   2032    16
 976          *
 977          *      htotal       8   2048     8
 978          *      hsstrt       0   2040     8
 979          *      hsstop       0   2040     8
 980          *      vtotal       1   4096     1
 981          *      vsstrt       0   4095     1
 982          *      vsstop       0   4095     1
 983          *      hcenter      0   2040     8
 984          *
 985          *      hbstrt       0   2047     1
 986          *      hbstop       0   2047     1
 987          *      vbstrt       0   4095     1
 988          *      vbstop       0   4095     1
 989          *
 990          * Horizontal values are in 35 ns (SHRES) pixels
 991          * Vertical values are in half scanlines
 992          */
 993 
 994 /* bplcon1 (smooth scrolling) */
 995 
 996 #define hscroll2hw(hscroll) \
 997         (((hscroll) << 12 & 0x3000) | ((hscroll) << 8 & 0xc300) | \
 998          ((hscroll) << 4 & 0x0c00) | ((hscroll) << 2 & 0x00f0) | \
 999          ((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->yoffset >= par->vyres)
1488                                 par->xoffset = par->yoffset = 0;
1489                 } else {
1490                         if (par->xoffset > upx(16 << maxfmode, par->vxres - par->xres) ||
1491                             par->yoffset > par->vyres - par->yres)
1492                                 par->xoffset = par->yoffset = 0;
1493                 }
1494         } else
1495                 par->xoffset = par->yoffset = 0;
1496 
1497         par->crsr.crsr_x = par->crsr.crsr_y = 0;
1498         par->crsr.spot_x = par->crsr.spot_y = 0;
1499         par->crsr.height = par->crsr.width = 0;
1500 
1501         return 0;
1502 }
1503 
1504         /*
1505          * Fill the `var' structure based on the values in `par' and maybe
1506          * other values read out of the hardware.
1507          */
1508 
1509 static void ami_encode_var(struct fb_var_screeninfo *var,
1510                            struct amifb_par *par)
1511 {
1512         u_short clk_shift, line_shift;
1513 
1514         memset(var, 0, sizeof(struct fb_var_screeninfo));
1515 
1516         clk_shift = par->clk_shift;
1517         line_shift = par->line_shift;
1518 
1519         var->xres = par->xres;
1520         var->yres = par->yres;
1521         var->xres_virtual = par->vxres;
1522         var->yres_virtual = par->vyres;
1523         var->xoffset = par->xoffset;
1524         var->yoffset = par->yoffset;
1525 
1526         var->bits_per_pixel = par->bpp;
1527         var->grayscale = 0;
1528 
1529         var->red.offset = 0;
1530         var->red.msb_right = 0;
1531         var->red.length = par->bpp;
1532         if (par->bplcon0 & BPC0_HAM)
1533                 var->red.length -= 2;
1534         var->blue = var->green = var->red;
1535         var->transp.offset = 0;
1536         var->transp.length = 0;
1537         var->transp.msb_right = 0;
1538 
1539         if (par->bplcon0 & BPC0_HAM)
1540                 var->nonstd = FB_NONSTD_HAM;
1541         else
1542                 var->nonstd = 0;
1543         var->activate = 0;
1544 
1545         var->height = -1;
1546         var->width = -1;
1547 
1548         var->pixclock = pixclock[clk_shift];
1549 
1550         if (IS_AGA && par->fmode & FMODE_BSCAN2)
1551                 var->vmode = FB_VMODE_DOUBLE;
1552         else if (par->bplcon0 & BPC0_LACE)
1553                 var->vmode = FB_VMODE_INTERLACED;
1554         else
1555                 var->vmode = FB_VMODE_NONINTERLACED;
1556 
1557         if (!IS_OCS && par->beamcon0 & BMC0_VARBEAMEN) {
1558                 var->hsync_len = (par->hsstop - par->hsstrt)>>clk_shift;
1559                 var->right_margin = par->hsstrt>>clk_shift;
1560                 var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
1561                 var->vsync_len = (par->vsstop - par->vsstrt)>>line_shift;
1562                 var->lower_margin = par->vsstrt>>line_shift;
1563                 var->upper_margin = (par->vtotal>>line_shift) - var->yres - var->lower_margin - var->vsync_len;
1564                 var->sync = 0;
1565                 if (par->beamcon0 & BMC0_HSYTRUE)
1566                         var->sync |= FB_SYNC_HOR_HIGH_ACT;
1567                 if (par->beamcon0 & BMC0_VSYTRUE)
1568                         var->sync |= FB_SYNC_VERT_HIGH_ACT;
1569                 if (par->beamcon0 & BMC0_CSYTRUE)
1570                         var->sync |= FB_SYNC_COMP_HIGH_ACT;
1571         } else {
1572                 var->sync = FB_SYNC_BROADCAST;
1573                 var->hsync_len = (152>>clk_shift) + mod4(par->diwstop_h);
1574                 var->right_margin = ((par->htotal - down4(par->diwstop_h))>>clk_shift) + var->hsync_len;
1575                 var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
1576                 var->vsync_len = 4>>line_shift;
1577                 var->lower_margin = ((par->vtotal - par->diwstop_v)>>line_shift) + var->vsync_len;
1578                 var->upper_margin = (((par->vtotal - 2)>>line_shift) + 1) - var->yres -
1579                                     var->lower_margin - var->vsync_len;
1580         }
1581 
1582         if (par->bplcon0 & BPC0_ERSY)
1583                 var->sync |= FB_SYNC_EXT;
1584         if (par->vmode & FB_VMODE_YWRAP)
1585                 var->vmode |= FB_VMODE_YWRAP;
1586 }
1587 
1588 
1589         /*
1590          * Update hardware
1591          */
1592 
1593 static void ami_update_par(struct fb_info *info)
1594 {
1595         struct amifb_par *par = info->par;
1596         short clk_shift, vshift, fstrt, fsize, fstop, fconst,  shift, move, mod;
1597 
1598         clk_shift = par->clk_shift;
1599 
1600         if (!(par->vmode & FB_VMODE_SMOOTH_XPAN))
1601                 par->xoffset = upx(16 << maxfmode, par->xoffset);
1602 
1603         fconst = 16 << maxfmode << clk_shift;
1604         vshift = modx(16 << maxfmode, par->xoffset);
1605         fstrt = par->diwstrt_h - (vshift << clk_shift) - 4;
1606         fsize = (par->xres + vshift) << clk_shift;
1607         shift = modx(fconst, fstrt);
1608         move = downx(2 << maxfmode, div8(par->xoffset));
1609         if (maxfmode + clk_shift > 1) {
1610                 fstrt = downx(fconst, fstrt) - 64;
1611                 fsize = upx(fconst, fsize);
1612                 fstop = fstrt + fsize - fconst;
1613         } else {
1614                 mod = fstrt = downx(fconst, fstrt) - fconst;
1615                 fstop = fstrt + upx(fconst, fsize) - 64;
1616                 fsize = up64(fsize);
1617                 fstrt = fstop - fsize + 64;
1618                 if (fstrt < min_fstrt) {
1619                         fstop += min_fstrt - fstrt;
1620                         fstrt = min_fstrt;
1621                 }
1622                 move = move - div8((mod - fstrt)>>clk_shift);
1623         }
1624         mod = par->next_line - div8(fsize>>clk_shift);
1625         par->ddfstrt = fstrt;
1626         par->ddfstop = fstop;
1627         par->bplcon1 = hscroll2hw(shift);
1628         par->bpl2mod = mod;
1629         if (par->bplcon0 & BPC0_LACE)
1630                 par->bpl2mod += par->next_line;
1631         if (IS_AGA && (par->fmode & FMODE_BSCAN2))
1632                 par->bpl1mod = -div8(fsize>>clk_shift);
1633         else
1634                 par->bpl1mod = par->bpl2mod;
1635 
1636         if (par->yoffset) {
1637                 par->bplpt0 = info->fix.smem_start +
1638                               par->next_line * par->yoffset + move;
1639                 if (par->vmode & FB_VMODE_YWRAP) {
1640                         if (par->yoffset > par->vyres - par->yres) {
1641                                 par->bplpt0wrap = info->fix.smem_start + move;
1642                                 if (par->bplcon0 & BPC0_LACE &&
1643                                     mod2(par->diwstrt_v + par->vyres -
1644                                          par->yoffset))
1645                                         par->bplpt0wrap += par->next_line;
1646                         }
1647                 }
1648         } else
1649                 par->bplpt0 = info->fix.smem_start + move;
1650 
1651         if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v))
1652                 par->bplpt0 += par->next_line;
1653 }
1654 
1655 
1656         /*
1657          * Pan or Wrap the Display
1658          *
1659          * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
1660          * in `var'.
1661          */
1662 
1663 static void ami_pan_var(struct fb_var_screeninfo *var, struct fb_info *info)
1664 {
1665         struct amifb_par *par = info->par;
1666 
1667         par->xoffset = var->xoffset;
1668         par->yoffset = var->yoffset;
1669         if (var->vmode & FB_VMODE_YWRAP)
1670                 par->vmode |= FB_VMODE_YWRAP;
1671         else
1672                 par->vmode &= ~FB_VMODE_YWRAP;
1673 
1674         do_vmode_pan = 0;
1675         ami_update_par(info);
1676         do_vmode_pan = 1;
1677 }
1678 
1679 
1680 static void ami_update_display(const struct amifb_par *par)
1681 {
1682         custom.bplcon1 = par->bplcon1;
1683         custom.bpl1mod = par->bpl1mod;
1684         custom.bpl2mod = par->bpl2mod;
1685         custom.ddfstrt = ddfstrt2hw(par->ddfstrt);
1686         custom.ddfstop = ddfstop2hw(par->ddfstop);
1687 }
1688 
1689         /*
1690          * Change the video mode (called by VBlank interrupt)
1691          */
1692 
1693 static void ami_init_display(const struct amifb_par *par)
1694 {
1695         int i;
1696 
1697         custom.bplcon0 = par->bplcon0 & ~BPC0_LACE;
1698         custom.bplcon2 = (IS_OCS ? 0 : BPC2_KILLEHB) | BPC2_PF2P2 | BPC2_PF1P2;
1699         if (!IS_OCS) {
1700                 custom.bplcon3 = par->bplcon3;
1701                 if (IS_AGA)
1702                         custom.bplcon4 = BPC4_ESPRM4 | BPC4_OSPRM4;
1703                 if (par->beamcon0 & BMC0_VARBEAMEN) {
1704                         custom.htotal = htotal2hw(par->htotal);
1705                         custom.hbstrt = hbstrt2hw(par->hbstrt);
1706                         custom.hbstop = hbstop2hw(par->hbstop);
1707                         custom.hsstrt = hsstrt2hw(par->hsstrt);
1708                         custom.hsstop = hsstop2hw(par->hsstop);
1709                         custom.hcenter = hcenter2hw(par->hcenter);
1710                         custom.vtotal = vtotal2hw(par->vtotal);
1711                         custom.vbstrt = vbstrt2hw(par->vbstrt);
1712                         custom.vbstop = vbstop2hw(par->vbstop);
1713                         custom.vsstrt = vsstrt2hw(par->vsstrt);
1714                         custom.vsstop = vsstop2hw(par->vsstop);
1715                 }
1716         }
1717         if (!IS_OCS || par->hsstop)
1718                 custom.beamcon0 = par->beamcon0;
1719         if (IS_AGA)
1720                 custom.fmode = par->fmode;
1721 
1722         /*
1723          * The minimum period for audio depends on htotal
1724          */
1725 
1726         amiga_audio_min_period = div16(par->htotal);
1727 
1728         is_lace = par->bplcon0 & BPC0_LACE ? 1 : 0;
1729 #if 1
1730         if (is_lace) {
1731                 i = custom.vposr >> 15;
1732         } else {
1733                 custom.vposw = custom.vposr | 0x8000;
1734                 i = 1;
1735         }
1736 #else
1737         i = 1;
1738         custom.vposw = custom.vposr | 0x8000;
1739 #endif
1740         custom.cop2lc = (u_short *)ZTWO_PADDR(copdisplay.list[currentcop][i]);
1741 }
1742 
1743         /*
1744          * (Un)Blank the screen (called by VBlank interrupt)
1745          */
1746 
1747 static void ami_do_blank(const struct amifb_par *par)
1748 {
1749 #if defined(CONFIG_FB_AMIGA_AGA)
1750         u_short bplcon3 = par->bplcon3;
1751 #endif
1752         u_char red, green, blue;
1753 
1754         if (do_blank > 0) {
1755                 custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
1756                 red = green = blue = 0;
1757                 if (!IS_OCS && do_blank > 1) {
1758                         switch (do_blank) {
1759                         case FB_BLANK_VSYNC_SUSPEND:
1760                                 custom.hsstrt = hsstrt2hw(par->hsstrt);
1761                                 custom.hsstop = hsstop2hw(par->hsstop);
1762                                 custom.vsstrt = vsstrt2hw(par->vtotal + 4);
1763                                 custom.vsstop = vsstop2hw(par->vtotal + 4);
1764                                 break;
1765                         case FB_BLANK_HSYNC_SUSPEND:
1766                                 custom.hsstrt = hsstrt2hw(par->htotal + 16);
1767                                 custom.hsstop = hsstop2hw(par->htotal + 16);
1768                                 custom.vsstrt = vsstrt2hw(par->vsstrt);
1769                                 custom.vsstop = vsstrt2hw(par->vsstop);
1770                                 break;
1771                         case FB_BLANK_POWERDOWN:
1772                                 custom.hsstrt = hsstrt2hw(par->htotal + 16);
1773                                 custom.hsstop = hsstop2hw(par->htotal + 16);
1774                                 custom.vsstrt = vsstrt2hw(par->vtotal + 4);
1775                                 custom.vsstop = vsstop2hw(par->vtotal + 4);
1776                                 break;
1777                         }
1778                         if (!(par->beamcon0 & BMC0_VARBEAMEN)) {
1779                                 custom.htotal = htotal2hw(par->htotal);
1780                                 custom.vtotal = vtotal2hw(par->vtotal);
1781                                 custom.beamcon0 = BMC0_HARDDIS | BMC0_VARBEAMEN |
1782                                                   BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARCSYEN;
1783                         }
1784                 }
1785         } else {
1786                 custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_SPRITE;
1787                 red = red0;
1788                 green = green0;
1789                 blue = blue0;
1790                 if (!IS_OCS) {
1791                         custom.hsstrt = hsstrt2hw(par->hsstrt);
1792                         custom.hsstop = hsstop2hw(par->hsstop);
1793                         custom.vsstrt = vsstrt2hw(par->vsstrt);
1794                         custom.vsstop = vsstop2hw(par->vsstop);
1795                         custom.beamcon0 = par->beamcon0;
1796                 }
1797         }
1798 #if defined(CONFIG_FB_AMIGA_AGA)
1799         if (IS_AGA) {
1800                 custom.bplcon3 = bplcon3;
1801                 custom.color[0] = rgb2hw8_high(red, green, blue);
1802                 custom.bplcon3 = bplcon3 | BPC3_LOCT;
1803                 custom.color[0] = rgb2hw8_low(red, green, blue);
1804                 custom.bplcon3 = bplcon3;
1805         } else
1806 #endif
1807 #if defined(CONFIG_FB_AMIGA_ECS)
1808         if (par->bplcon0 & BPC0_SHRES) {
1809                 u_short color, mask;
1810                 int i;
1811 
1812                 mask = 0x3333;
1813                 color = rgb2hw2(red, green, blue);
1814                 for (i = 12; i >= 0; i -= 4)
1815                         custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
1816                 mask <<= 2; color >>= 2;
1817                 for (i = 3; i >= 0; i--)
1818                         custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
1819         } else
1820 #endif
1821                 custom.color[0] = rgb2hw4(red, green, blue);
1822         is_blanked = do_blank > 0 ? do_blank : 0;
1823 }
1824 
1825 static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix,
1826                                   const struct amifb_par *par)
1827 {
1828         fix->crsr_width = fix->crsr_xsize = par->crsr.width;
1829         fix->crsr_height = fix->crsr_ysize = par->crsr.height;
1830         fix->crsr_color1 = 17;
1831         fix->crsr_color2 = 18;
1832         return 0;
1833 }
1834 
1835 static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var,
1836                                   u_char __user *data,
1837                                   const struct amifb_par *par)
1838 {
1839         register u_short *lspr, *sspr;
1840 #ifdef __mc68000__
1841         register u_long datawords asm ("d2");
1842 #else
1843         register u_long datawords;
1844 #endif
1845         register short delta;
1846         register u_char color;
1847         short height, width, bits, words;
1848         int size, alloc;
1849 
1850         size = par->crsr.height * par->crsr.width;
1851         alloc = var->height * var->width;
1852         var->height = par->crsr.height;
1853         var->width = par->crsr.width;
1854         var->xspot = par->crsr.spot_x;
1855         var->yspot = par->crsr.spot_y;
1856         if (size > var->height * var->width)
1857                 return -ENAMETOOLONG;
1858         if (!access_ok(data, size))
1859                 return -EFAULT;
1860         delta = 1 << par->crsr.fmode;
1861         lspr = lofsprite + (delta << 1);
1862         if (par->bplcon0 & BPC0_LACE)
1863                 sspr = shfsprite + (delta << 1);
1864         else
1865                 sspr = NULL;
1866         for (height = (short)var->height - 1; height >= 0; height--) {
1867                 bits = 0; words = delta; datawords = 0;
1868                 for (width = (short)var->width - 1; width >= 0; width--) {
1869                         if (bits == 0) {
1870                                 bits = 16; --words;
1871 #ifdef __mc68000__
1872                                 asm volatile ("movew %1@(%3:w:2),%0 ; swap %0 ; movew %1@+,%0"
1873                                         : "=d" (datawords), "=a" (lspr) : "1" (lspr), "d" (delta));
1874 #else
1875                                 datawords = (*(lspr + delta) << 16) | (*lspr++);
1876 #endif
1877                         }
1878                         --bits;
1879 #ifdef __mc68000__
1880                         asm volatile (
1881                                 "clrb %0 ; swap %1 ; lslw #1,%1 ; roxlb #1,%0 ; "
1882                                 "swap %1 ; lslw #1,%1 ; roxlb #1,%0"
1883                                 : "=d" (color), "=d" (datawords) : "1" (datawords));
1884 #else
1885                         color = (((datawords >> 30) & 2)
1886                                  | ((datawords >> 15) & 1));
1887                         datawords <<= 1;
1888 #endif
1889                         put_user(color, data++);
1890                 }
1891                 if (bits > 0) {
1892                         --words; ++lspr;
1893                 }
1894                 while (--words >= 0)
1895                         ++lspr;
1896 #ifdef __mc68000__
1897                 asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
1898                         : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
1899 #else
1900                 lspr += delta;
1901                 if (sspr) {
1902                         u_short *tmp = lspr;
1903                         lspr = sspr;
1904                         sspr = tmp;
1905                 }
1906 #endif
1907         }
1908         return 0;
1909 }
1910 
1911 static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var,
1912                                   u_char __user *data, struct amifb_par *par)
1913 {
1914         register u_short *lspr, *sspr;
1915 #ifdef __mc68000__
1916         register u_long datawords asm ("d2");
1917 #else
1918         register u_long datawords;
1919 #endif
1920         register short delta;
1921         u_short fmode;
1922         short height, width, bits, words;
1923 
1924         if (!var->width)
1925                 return -EINVAL;
1926         else if (var->width <= 16)
1927                 fmode = TAG_FMODE_1;
1928         else if (var->width <= 32)
1929                 fmode = TAG_FMODE_2;
1930         else if (var->width <= 64)
1931                 fmode = TAG_FMODE_4;
1932         else
1933                 return -EINVAL;
1934         if (fmode > maxfmode)
1935                 return -EINVAL;
1936         if (!var->height)
1937                 return -EINVAL;
1938         if (!access_ok(data, var->width * var->height))
1939                 return -EFAULT;
1940         delta = 1 << fmode;
1941         lofsprite = shfsprite = (u_short *)spritememory;
1942         lspr = lofsprite + (delta << 1);
1943         if (par->bplcon0 & BPC0_LACE) {
1944                 if (((var->height + 4) << fmode << 2) > SPRITEMEMSIZE)
1945                         return -EINVAL;
1946                 memset(lspr, 0, (var->height + 4) << fmode << 2);
1947                 shfsprite += ((var->height + 5)&-2) << fmode;
1948                 sspr = shfsprite + (delta << 1);
1949         } else {
1950                 if (((var->height + 2) << fmode << 2) > SPRITEMEMSIZE)
1951                         return -EINVAL;
1952                 memset(lspr, 0, (var->height + 2) << fmode << 2);
1953                 sspr = NULL;
1954         }
1955         for (height = (short)var->height - 1; height >= 0; height--) {
1956                 bits = 16; words = delta; datawords = 0;
1957                 for (width = (short)var->width - 1; width >= 0; width--) {
1958                         unsigned long tdata = 0;
1959                         get_user(tdata, data);
1960                         data++;
1961 #ifdef __mc68000__
1962                         asm volatile (
1963                                 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0 ; "
1964                                 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0"
1965                                 : "=d" (datawords)
1966                                 : "0" (datawords), "d" (tdata));
1967 #else
1968                         datawords = ((datawords << 1) & 0xfffefffe);
1969                         datawords |= tdata & 1;
1970                         datawords |= (tdata & 2) << (16 - 1);
1971 #endif
1972                         if (--bits == 0) {
1973                                 bits = 16; --words;
1974 #ifdef __mc68000__
1975                                 asm volatile ("swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+"
1976                                         : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta));
1977 #else
1978                                 *(lspr + delta) = (u_short) (datawords >> 16);
1979                                 *lspr++ = (u_short) (datawords & 0xffff);
1980 #endif
1981                         }
1982                 }
1983                 if (bits < 16) {
1984                         --words;
1985 #ifdef __mc68000__
1986                         asm volatile (
1987                                 "swap %2 ; lslw %4,%2 ; movew %2,%0@(%3:w:2) ; "
1988                                 "swap %2 ; lslw %4,%2 ; movew %2,%0@+"
1989                                 : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta), "d" (bits));
1990 #else
1991                         *(lspr + delta) = (u_short) (datawords >> (16 + bits));
1992                         *lspr++ = (u_short) ((datawords & 0x0000ffff) >> bits);
1993 #endif
1994                 }
1995                 while (--words >= 0) {
1996 #ifdef __mc68000__
1997                         asm volatile ("moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+"
1998                                 : "=a" (lspr) : "0" (lspr), "d" (delta) : "d0");
1999 #else
2000                         *(lspr + delta) = 0;
2001                         *lspr++ = 0;
2002 #endif
2003                 }
2004 #ifdef __mc68000__
2005                 asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
2006                         : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
2007 #else
2008                 lspr += delta;
2009                 if (sspr) {
2010                         u_short *tmp = lspr;
2011                         lspr = sspr;
2012                         sspr = tmp;
2013                 }
2014 #endif
2015         }
2016         par->crsr.height = var->height;
2017         par->crsr.width = var->width;
2018         par->crsr.spot_x = var->xspot;
2019         par->crsr.spot_y = var->yspot;
2020         par->crsr.fmode = fmode;
2021         if (IS_AGA) {
2022                 par->fmode &= ~(FMODE_SPAGEM | FMODE_SPR32);
2023                 par->fmode |= sprfetchmode[fmode];
2024                 custom.fmode = par->fmode;
2025         }
2026         return 0;
2027 }
2028 
2029 static int ami_get_cursorstate(struct fb_cursorstate *state,
2030                                const struct amifb_par *par)
2031 {
2032         state->xoffset = par->crsr.crsr_x;
2033         state->yoffset = par->crsr.crsr_y;
2034         state->mode = cursormode;
2035         return 0;
2036 }
2037 
2038 static int ami_set_cursorstate(struct fb_cursorstate *state,
2039                                struct amifb_par *par)
2040 {
2041         par->crsr.crsr_x = state->xoffset;
2042         par->crsr.crsr_y = state->yoffset;
2043         if ((cursormode = state->mode) == FB_CURSOR_OFF)
2044                 cursorstate = -1;
2045         do_cursor = 1;
2046         return 0;
2047 }
2048 
2049 static void ami_set_sprite(const struct amifb_par *par)
2050 {
2051         copins *copl, *cops;
2052         u_short hs, vs, ve;
2053         u_long pl, ps;
2054         short mx, my;
2055 
2056         cops = copdisplay.list[currentcop][0];
2057         copl = copdisplay.list[currentcop][1];
2058         ps = pl = ZTWO_PADDR(dummysprite);
2059         mx = par->crsr.crsr_x - par->crsr.spot_x;
2060         my = par->crsr.crsr_y - par->crsr.spot_y;
2061         if (!(par->vmode & FB_VMODE_YWRAP)) {
2062                 mx -= par->xoffset;
2063                 my -= par->yoffset;
2064         }
2065         if (!is_blanked && cursorstate > 0 && par->crsr.height > 0 &&
2066             mx > -(short)par->crsr.width && mx < par->xres &&
2067             my > -(short)par->crsr.height && my < par->yres) {
2068                 pl = ZTWO_PADDR(lofsprite);
2069                 hs = par->diwstrt_h + (mx << par->clk_shift) - 4;
2070                 vs = par->diwstrt_v + (my << par->line_shift);
2071                 ve = vs + (par->crsr.height << par->line_shift);
2072                 if (par->bplcon0 & BPC0_LACE) {
2073                         ps = ZTWO_PADDR(shfsprite);
2074                         lofsprite[0] = spr2hw_pos(vs, hs);
2075                         shfsprite[0] = spr2hw_pos(vs + 1, hs);
2076                         if (mod2(vs)) {
2077                                 lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
2078                                 shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve + 1);
2079                                 swap(pl, ps);
2080                         } else {
2081                                 lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve + 1);
2082                                 shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve);
2083                         }
2084                 } else {
2085                         lofsprite[0] = spr2hw_pos(vs, hs) | (IS_AGA && (par->fmode & FMODE_BSCAN2) ? 0x80 : 0);
2086                         lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
2087                 }
2088         }
2089         copl[cop_spr0ptrh].w[1] = highw(pl);
2090         copl[cop_spr0ptrl].w[1] = loww(pl);
2091         if (par->bplcon0 & BPC0_LACE) {
2092                 cops[cop_spr0ptrh].w[1] = highw(ps);
2093                 cops[cop_spr0ptrl].w[1] = loww(ps);
2094         }
2095 }
2096 
2097 
2098         /*
2099          * Initialise the Copper Initialisation List
2100          */
2101 
2102 static void __init ami_init_copper(void)
2103 {
2104         copins *cop = copdisplay.init;
2105         u_long p;
2106         int i;
2107 
2108         if (!IS_OCS) {
2109                 (cop++)->l = CMOVE(BPC0_COLOR | BPC0_SHRES | BPC0_ECSENA, bplcon0);
2110                 (cop++)->l = CMOVE(0x0181, diwstrt);
2111                 (cop++)->l = CMOVE(0x0281, diwstop);
2112                 (cop++)->l = CMOVE(0x0000, diwhigh);
2113         } else
2114                 (cop++)->l = CMOVE(BPC0_COLOR, bplcon0);
2115         p = ZTWO_PADDR(dummysprite);
2116         for (i = 0; i < 8; i++) {
2117                 (cop++)->l = CMOVE(0, spr[i].pos);
2118                 (cop++)->l = CMOVE(highw(p), sprpt[i]);
2119                 (cop++)->l = CMOVE2(loww(p), sprpt[i]);
2120         }
2121 
2122         (cop++)->l = CMOVE(IF_SETCLR | IF_COPER, intreq);
2123         copdisplay.wait = cop;
2124         (cop++)->l = CEND;
2125         (cop++)->l = CMOVE(0, copjmp2);
2126         cop->l = CEND;
2127 
2128         custom.cop1lc = (u_short *)ZTWO_PADDR(copdisplay.init);
2129         custom.copjmp1 = 0;
2130 }
2131 
2132 static void ami_reinit_copper(const struct amifb_par *par)
2133 {
2134         copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0;
2135         copdisplay.wait->l = CWAIT(32, par->diwstrt_v - 4);
2136 }
2137 
2138 
2139         /*
2140          * Rebuild the Copper List
2141          *
2142          * We only change the things that are not static
2143          */
2144 
2145 static void ami_rebuild_copper(const struct amifb_par *par)
2146 {
2147         copins *copl, *cops;
2148         u_short line, h_end1, h_end2;
2149         short i;
2150         u_long p;
2151 
2152         if (IS_AGA && maxfmode + par->clk_shift == 0)
2153                 h_end1 = par->diwstrt_h - 64;
2154         else
2155                 h_end1 = par->htotal - 32;
2156         h_end2 = par->ddfstop + 64;
2157 
2158         ami_set_sprite(par);
2159 
2160         copl = copdisplay.rebuild[1];
2161         p = par->bplpt0;
2162         if (par->vmode & FB_VMODE_YWRAP) {
2163                 if ((par->vyres - par->yoffset) != 1 || !mod2(par->diwstrt_v)) {
2164                         if (par->yoffset > par->vyres - par->yres) {
2165                                 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2166                                         (copl++)->l = CMOVE(highw(p), bplpt[i]);
2167                                         (copl++)->l = CMOVE2(loww(p), bplpt[i]);
2168                                 }
2169                                 line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 1;
2170                                 while (line >= 512) {
2171                                         (copl++)->l = CWAIT(h_end1, 510);
2172                                         line -= 512;
2173                                 }
2174                                 if (line >= 510 && IS_AGA && maxfmode + par->clk_shift == 0)
2175                                         (copl++)->l = CWAIT(h_end1, line);
2176                                 else
2177                                         (copl++)->l = CWAIT(h_end2, line);
2178                                 p = par->bplpt0wrap;
2179                         }
2180                 } else
2181                         p = par->bplpt0wrap;
2182         }
2183         for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2184                 (copl++)->l = CMOVE(highw(p), bplpt[i]);
2185                 (copl++)->l = CMOVE2(loww(p), bplpt[i]);
2186         }
2187         copl->l = CEND;
2188 
2189         if (par->bplcon0 & BPC0_LACE) {
2190                 cops = copdisplay.rebuild[0];
2191                 p = par->bplpt0;
2192                 if (mod2(par->diwstrt_v))
2193                         p -= par->next_line;
2194                 else
2195                         p += par->next_line;
2196                 if (par->vmode & FB_VMODE_YWRAP) {
2197                         if ((par->vyres - par->yoffset) != 1 || mod2(par->diwstrt_v)) {
2198                                 if (par->yoffset > par->vyres - par->yres + 1) {
2199                                         for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2200                                                 (cops++)->l = CMOVE(highw(p), bplpt[i]);
2201                                                 (cops++)->l = CMOVE2(loww(p), bplpt[i]);
2202                                         }
2203                                         line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 2;
2204                                         while (line >= 512) {
2205                                                 (cops++)->l = CWAIT(h_end1, 510);
2206                                                 line -= 512;
2207                                         }
2208                                         if (line > 510 && IS_AGA && maxfmode + par->clk_shift == 0)
2209                                                 (cops++)->l = CWAIT(h_end1, line);
2210                                         else
2211                                                 (cops++)->l = CWAIT(h_end2, line);
2212                                         p = par->bplpt0wrap;
2213                                         if (mod2(par->diwstrt_v + par->vyres -
2214                                             par->yoffset))
2215                                                 p -= par->next_line;
2216                                         else
2217                                                 p += par->next_line;
2218                                 }
2219                         } else
2220                                 p = par->bplpt0wrap - par->next_line;
2221                 }
2222                 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2223                         (cops++)->l = CMOVE(highw(p), bplpt[i]);
2224                         (cops++)->l = CMOVE2(loww(p), bplpt[i]);
2225                 }
2226                 cops->l = CEND;
2227         }
2228 }
2229 
2230 
2231         /*
2232          * Build the Copper List
2233          */
2234 
2235 static void ami_build_copper(struct fb_info *info)
2236 {
2237         struct amifb_par *par = info->par;
2238         copins *copl, *cops;
2239         u_long p;
2240 
2241         currentcop = 1 - currentcop;
2242 
2243         copl = copdisplay.list[currentcop][1];
2244 
2245         (copl++)->l = CWAIT(0, 10);
2246         (copl++)->l = CMOVE(par->bplcon0, bplcon0);
2247         (copl++)->l = CMOVE(0, sprpt[0]);
2248         (copl++)->l = CMOVE2(0, sprpt[0]);
2249 
2250         if (par->bplcon0 & BPC0_LACE) {
2251                 cops = copdisplay.list[currentcop][0];
2252 
2253                 (cops++)->l = CWAIT(0, 10);
2254                 (cops++)->l = CMOVE(par->bplcon0, bplcon0);
2255                 (cops++)->l = CMOVE(0, sprpt[0]);
2256                 (cops++)->l = CMOVE2(0, sprpt[0]);
2257 
2258                 (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v + 1), diwstrt);
2259                 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v + 1), diwstop);
2260                 (cops++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
2261                 (cops++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
2262                 if (!IS_OCS) {
2263                         (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v + 1,
2264                                             par->diwstop_h, par->diwstop_v + 1), diwhigh);
2265                         (cops++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
2266                                             par->diwstop_h, par->diwstop_v), diwhigh);
2267 #if 0
2268                         if (par->beamcon0 & BMC0_VARBEAMEN) {
2269                                 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
2270                                 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt + 1), vbstrt);
2271                                 (copl++)->l = CMOVE(vbstop2hw(par->vbstop + 1), vbstop);
2272                                 (cops++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
2273                                 (cops++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
2274                                 (cops++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
2275                         }
2276 #endif
2277                 }
2278                 p = ZTWO_PADDR(copdisplay.list[currentcop][0]);
2279                 (copl++)->l = CMOVE(highw(p), cop2lc);
2280                 (copl++)->l = CMOVE2(loww(p), cop2lc);
2281                 p = ZTWO_PADDR(copdisplay.list[currentcop][1]);
2282                 (cops++)->l = CMOVE(highw(p), cop2lc);
2283                 (cops++)->l = CMOVE2(loww(p), cop2lc);
2284                 copdisplay.rebuild[0] = cops;
2285         } else {
2286                 (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
2287                 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
2288                 if (!IS_OCS) {
2289                         (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
2290                                             par->diwstop_h, par->diwstop_v), diwhigh);
2291 #if 0
2292                         if (par->beamcon0 & BMC0_VARBEAMEN) {
2293                                 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
2294                                 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
2295                                 (copl++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
2296                         }
2297 #endif
2298                 }
2299         }
2300         copdisplay.rebuild[1] = copl;
2301 
2302         ami_update_par(info);
2303         ami_rebuild_copper(info->par);
2304 }
2305 
2306 #ifndef MODULE
2307 static void __init amifb_setup_mcap(char *spec)
2308 {
2309         char *p;
2310         int vmin, vmax, hmin, hmax;
2311 
2312         /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
2313          * <V*> vertical freq. in Hz
2314          * <H*> horizontal freq. in kHz
2315          */
2316 
2317         if (!(p = strsep(&spec, ";")) || !*p)
2318                 return;
2319         vmin = simple_strtoul(p, NULL, 10);
2320         if (vmin <= 0)
2321                 return;
2322         if (!(p = strsep(&spec, ";")) || !*p)
2323                 return;
2324         vmax = simple_strtoul(p, NULL, 10);
2325         if (vmax <= 0 || vmax <= vmin)
2326                 return;
2327         if (!(p = strsep(&spec, ";")) || !*p)
2328                 return;
2329         hmin = 1000 * simple_strtoul(p, NULL, 10);
2330         if (hmin <= 0)
2331                 return;
2332         if (!(p = strsep(&spec, "")) || !*p)
2333                 return;
2334         hmax = 1000 * simple_strtoul(p, NULL, 10);
2335         if (hmax <= 0 || hmax <= hmin)
2336                 return;
2337 
2338         amifb_hfmin = hmin;
2339         amifb_hfmax = hmax;
2340         amifb_vfmin = vmin;
2341         amifb_vfmax = vmax;
2342 }
2343 
2344 static int __init amifb_setup(char *options)
2345 {
2346         char *this_opt;
2347 
2348         if (!options || !*options)
2349                 return 0;
2350 
2351         while ((this_opt = strsep(&options, ",")) != NULL) {
2352                 if (!*this_opt)
2353                         continue;
2354                 if (!strcmp(this_opt, "inverse")) {
2355                         fb_invert_cmaps();
2356                 } else if (!strcmp(this_opt, "ilbm"))
2357                         amifb_ilbm = 1;
2358                 else if (!strncmp(this_opt, "monitorcap:", 11))
2359                         amifb_setup_mcap(this_opt + 11);
2360                 else if (!strncmp(this_opt, "fstart:", 7))
2361                         min_fstrt = simple_strtoul(this_opt + 7, NULL, 0);
2362                 else
2363                         mode_option = this_opt;
2364         }
2365 
2366         if (min_fstrt < 48)
2367                 min_fstrt = 48;
2368 
2369         return 0;
2370 }
2371 #endif
2372 
2373 static int amifb_check_var(struct fb_var_screeninfo *var,
2374                            struct fb_info *info)
2375 {
2376         int err;
2377         struct amifb_par par;
2378 
2379         /* Validate wanted screen parameters */
2380         err = ami_decode_var(var, &par, info);
2381         if (err)
2382                 return err;
2383 
2384         /* Encode (possibly rounded) screen parameters */
2385         ami_encode_var(var, &par);
2386         return 0;
2387 }
2388 
2389 
2390 static int amifb_set_par(struct fb_info *info)
2391 {
2392         struct amifb_par *par = info->par;
2393         int error;
2394 
2395         do_vmode_pan = 0;
2396         do_vmode_full = 0;
2397 
2398         /* Decode wanted screen parameters */
2399         error = ami_decode_var(&info->var, par, info);
2400         if (error)
2401                 return error;
2402 
2403         /* Set new videomode */
2404         ami_build_copper(info);
2405 
2406         /* Set VBlank trigger */
2407         do_vmode_full = 1;
2408 
2409         /* Update fix for new screen parameters */
2410         if (par->bpp == 1) {
2411                 info->fix.type = FB_TYPE_PACKED_PIXELS;
2412                 info->fix.type_aux = 0;
2413         } else if (amifb_ilbm) {
2414                 info->fix.type = FB_TYPE_INTERLEAVED_PLANES;
2415                 info->fix.type_aux = par->next_line;
2416         } else {
2417                 info->fix.type = FB_TYPE_PLANES;
2418                 info->fix.type_aux = 0;
2419         }
2420         info->fix.line_length = div8(upx(16 << maxfmode, par->vxres));
2421 
2422         if (par->vmode & FB_VMODE_YWRAP) {
2423                 info->fix.ywrapstep = 1;
2424                 info->fix.xpanstep = 0;
2425                 info->fix.ypanstep = 0;
2426                 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP |
2427                         FBINFO_READS_FAST; /* override SCROLL_REDRAW */
2428         } else {
2429                 info->fix.ywrapstep = 0;
2430                 if (par->vmode & FB_VMODE_SMOOTH_XPAN)
2431                         info->fix.xpanstep = 1;
2432                 else
2433                         info->fix.xpanstep = 16 << maxfmode;
2434                 info->fix.ypanstep = 1;
2435                 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
2436         }
2437         return 0;
2438 }
2439 
2440 
2441         /*
2442          * Set a single color register. The values supplied are already
2443          * rounded down to the hardware's capabilities (according to the
2444          * entries in the var structure). Return != 0 for invalid regno.
2445          */
2446 
2447 static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
2448                            u_int transp, struct fb_info *info)
2449 {
2450         const struct amifb_par *par = info->par;
2451 
2452         if (IS_AGA) {
2453                 if (regno > 255)
2454                         return 1;
2455         } else if (par->bplcon0 & BPC0_SHRES) {
2456                 if (regno > 3)
2457                         return 1;
2458         } else {
2459                 if (regno > 31)
2460                         return 1;
2461         }
2462         red >>= 8;
2463         green >>= 8;
2464         blue >>= 8;
2465         if (!regno) {
2466                 red0 = red;
2467                 green0 = green;
2468                 blue0 = blue;
2469         }
2470 
2471         /*
2472          * Update the corresponding Hardware Color Register, unless it's Color
2473          * Register 0 and the screen is blanked.
2474          *
2475          * VBlank is switched off to protect bplcon3 or ecs_palette[] from
2476          * being changed by ami_do_blank() during the VBlank.
2477          */
2478 
2479         if (regno || !is_blanked) {
2480 #if defined(CONFIG_FB_AMIGA_AGA)
2481                 if (IS_AGA) {
2482                         u_short bplcon3 = par->bplcon3;
2483                         VBlankOff();
2484                         custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000);
2485                         custom.color[regno & 31] = rgb2hw8_high(red, green,
2486                                                                 blue);
2487                         custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000) |
2488                                          BPC3_LOCT;
2489                         custom.color[regno & 31] = rgb2hw8_low(red, green,
2490                                                                blue);
2491                         custom.bplcon3 = bplcon3;
2492                         VBlankOn();
2493                 } else
2494 #endif
2495 #if defined(CONFIG_FB_AMIGA_ECS)
2496                 if (par->bplcon0 & BPC0_SHRES) {
2497                         u_short color, mask;
2498                         int i;
2499 
2500                         mask = 0x3333;
2501                         color = rgb2hw2(red, green, blue);
2502                         VBlankOff();
2503                         for (i = regno + 12; i >= (int)regno; i -= 4)
2504                                 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
2505                         mask <<= 2; color >>= 2;
2506                         regno = down16(regno) + mul4(mod4(regno));
2507                         for (i = regno + 3; i >= (int)regno; i--)
2508                                 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
2509                         VBlankOn();
2510                 } else
2511 #endif
2512                         custom.color[regno] = rgb2hw4(red, green, blue);
2513         }
2514         return 0;
2515 }
2516 
2517 
2518         /*
2519          * Blank the display.
2520          */
2521 
2522 static int amifb_blank(int blank, struct fb_info *info)
2523 {
2524         do_blank = blank ? blank : -1;
2525 
2526         return 0;
2527 }
2528 
2529 
2530         /*
2531          * Pan or Wrap the Display
2532          *
2533          * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
2534          */
2535 
2536 static int amifb_pan_display(struct fb_var_screeninfo *var,
2537                              struct fb_info *info)
2538 {
2539         if (var->vmode & FB_VMODE_YWRAP) {
2540                 if (var->yoffset < 0 ||
2541                         var->yoffset >= info->var.yres_virtual || var->xoffset)
2542                                 return -EINVAL;
2543         } else {
2544                 /*
2545                  * TODO: There will be problems when xpan!=1, so some columns
2546                  * on the right side will never be seen
2547                  */
2548                 if (var->xoffset + info->var.xres >
2549                     upx(16 << maxfmode, info->var.xres_virtual) ||
2550                     var->yoffset + info->var.yres > info->var.yres_virtual)
2551                         return -EINVAL;
2552         }
2553         ami_pan_var(var, info);
2554         info->var.xoffset = var->xoffset;
2555         info->var.yoffset = var->yoffset;
2556         if (var->vmode & FB_VMODE_YWRAP)
2557                 info->var.vmode |= FB_VMODE_YWRAP;
2558         else
2559                 info->var.vmode &= ~FB_VMODE_YWRAP;
2560         return 0;
2561 }
2562 
2563 
2564 #if BITS_PER_LONG == 32
2565 #define BYTES_PER_LONG  4
2566 #define SHIFT_PER_LONG  5
2567 #elif BITS_PER_LONG == 64
2568 #define BYTES_PER_LONG  8
2569 #define SHIFT_PER_LONG  6
2570 #else
2571 #define Please update me
2572 #endif
2573 
2574 
2575         /*
2576          *  Compose two values, using a bitmask as decision value
2577          *  This is equivalent to (a & mask) | (b & ~mask)
2578          */
2579 
2580 static inline unsigned long comp(unsigned long a, unsigned long b,
2581                                  unsigned long mask)
2582 {
2583         return ((a ^ b) & mask) ^ b;
2584 }
2585 
2586 
2587 static inline unsigned long xor(unsigned long a, unsigned long b,
2588                                 unsigned long mask)
2589 {
2590         return (a & mask) ^ b;
2591 }
2592 
2593 
2594         /*
2595          *  Unaligned forward bit copy using 32-bit or 64-bit memory accesses
2596          */
2597 
2598 static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
2599                    int src_idx, u32 n)
2600 {
2601         unsigned long first, last;
2602         int shift = dst_idx - src_idx, left, right;
2603         unsigned long d0, d1;
2604         int m;
2605 
2606         if (!n)
2607                 return;
2608 
2609         shift = dst_idx - src_idx;
2610         first = ~0UL >> dst_idx;
2611         last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
2612 
2613         if (!shift) {
2614                 // Same alignment for source and dest
2615 
2616                 if (dst_idx + n <= BITS_PER_LONG) {
2617                         // Single word
2618                         if (last)
2619                                 first &= last;
2620                         *dst = comp(*src, *dst, first);
2621                 } else {
2622                         // Multiple destination words
2623                         // Leading bits
2624                         if (first) {
2625                                 *dst = comp(*src, *dst, first);
2626                                 dst++;
2627                                 src++;
2628                                 n -= BITS_PER_LONG - dst_idx;
2629                         }
2630 
2631                         // Main chunk
2632                         n /= BITS_PER_LONG;
2633                         while (n >= 8) {
2634                                 *dst++ = *src++;
2635                                 *dst++ = *src++;
2636                                 *dst++ = *src++;
2637                                 *dst++ = *src++;
2638                                 *dst++ = *src++;
2639                                 *dst++ = *src++;
2640                                 *dst++ = *src++;
2641                                 *dst++ = *src++;
2642                                 n -= 8;
2643                         }
2644                         while (n--)
2645                                 *dst++ = *src++;
2646 
2647                         // Trailing bits
2648                         if (last)
2649                                 *dst = comp(*src, *dst, last);
2650                 }
2651         } else {
2652                 // Different alignment for source and dest
2653 
2654                 right = shift & (BITS_PER_LONG - 1);
2655                 left = -shift & (BITS_PER_LONG - 1);
2656 
2657                 if (dst_idx + n <= BITS_PER_LONG) {
2658                         // Single destination word
2659                         if (last)
2660                                 first &= last;
2661                         if (shift > 0) {
2662                                 // Single source word
2663                                 *dst = comp(*src >> right, *dst, first);
2664                         } else if (src_idx + n <= BITS_PER_LONG) {
2665                                 // Single source word
2666                                 *dst = comp(*src << left, *dst, first);
2667                         } else {
2668                                 // 2 source words
2669                                 d0 = *src++;
2670                                 d1 = *src;
2671                                 *dst = comp(d0 << left | d1 >> right, *dst,
2672                                             first);
2673                         }
2674                 } else {
2675                         // Multiple destination words
2676                         d0 = *src++;
2677                         // Leading bits
2678                         if (shift > 0) {
2679                                 // Single source word
2680                                 *dst = comp(d0 >> right, *dst, first);
2681                                 dst++;
2682                                 n -= BITS_PER_LONG - dst_idx;
2683                         } else {
2684                                 // 2 source words
2685                                 d1 = *src++;
2686                                 *dst = comp(d0 << left | d1 >> right, *dst,
2687                                             first);
2688                                 d0 = d1;
2689                                 dst++;
2690                                 n -= BITS_PER_LONG - dst_idx;
2691                         }
2692 
2693                         // Main chunk
2694                         m = n % BITS_PER_LONG;
2695                         n /= BITS_PER_LONG;
2696                         while (n >= 4) {
2697                                 d1 = *src++;
2698                                 *dst++ = d0 << left | d1 >> right;
2699                                 d0 = d1;
2700                                 d1 = *src++;
2701                                 *dst++ = d0 << left | d1 >> right;
2702                                 d0 = d1;
2703                                 d1 = *src++;
2704                                 *dst++ = d0 << left | d1 >> right;
2705                                 d0 = d1;
2706                                 d1 = *src++;
2707                                 *dst++ = d0 << left | d1 >> right;
2708                                 d0 = d1;
2709                                 n -= 4;
2710                         }
2711                         while (n--) {
2712                                 d1 = *src++;
2713                                 *dst++ = d0 << left | d1 >> right;
2714                                 d0 = d1;
2715                         }
2716 
2717                         // Trailing bits
2718                         if (last) {
2719                                 if (m <= right) {
2720                                         // Single source word
2721                                         *dst = comp(d0 << left, *dst, last);
2722                                 } else {
2723                                         // 2 source words
2724                                         d1 = *src;
2725                                         *dst = comp(d0 << left | d1 >> right,
2726                                                     *dst, last);
2727                                 }
2728                         }
2729                 }
2730         }
2731 }
2732 
2733 
2734         /*
2735          *  Unaligned reverse bit copy using 32-bit or 64-bit memory accesses
2736          */
2737 
2738 static void bitcpy_rev(unsigned long *dst, int dst_idx,
2739                        const unsigned long *src, int src_idx, u32 n)
2740 {
2741         unsigned long first, last;
2742         int shift = dst_idx - src_idx, left, right;
2743         unsigned long d0, d1;
2744         int m;
2745 
2746         if (!n)
2747                 return;
2748 
2749         dst += (n - 1) / BITS_PER_LONG;
2750         src += (n - 1) / BITS_PER_LONG;
2751         if ((n - 1) % BITS_PER_LONG) {
2752                 dst_idx += (n - 1) % BITS_PER_LONG;
2753                 dst += dst_idx >> SHIFT_PER_LONG;
2754                 dst_idx &= BITS_PER_LONG - 1;
2755                 src_idx += (n - 1) % BITS_PER_LONG;
2756                 src += src_idx >> SHIFT_PER_LONG;
2757                 src_idx &= BITS_PER_LONG - 1;
2758         }
2759 
2760         shift = dst_idx - src_idx;
2761         first = ~0UL << (BITS_PER_LONG - 1 - dst_idx);
2762         last = ~(~0UL << (BITS_PER_LONG - 1 - ((dst_idx - n) % BITS_PER_LONG)));
2763 
2764         if (!shift) {
2765                 // Same alignment for source and dest
2766 
2767                 if ((unsigned long)dst_idx + 1 >= n) {
2768                         // Single word
2769                         if (last)
2770                                 first &= last;
2771                         *dst = comp(*src, *dst, first);
2772                 } else {
2773                         // Multiple destination words
2774                         // Leading bits
2775                         if (first) {
2776                                 *dst = comp(*src, *dst, first);
2777                                 dst--;
2778                                 src--;
2779                                 n -= dst_idx + 1;
2780                         }
2781 
2782                         // Main chunk
2783                         n /= BITS_PER_LONG;
2784                         while (n >= 8) {
2785                                 *dst-- = *src--;
2786                                 *dst-- = *src--;
2787                                 *dst-- = *src--;
2788                                 *dst-- = *src--;
2789                                 *dst-- = *src--;
2790                                 *dst-- = *src--;
2791                                 *dst-- = *src--;
2792                                 *dst-- = *src--;
2793                                 n -= 8;
2794                         }
2795                         while (n--)
2796                                 *dst-- = *src--;
2797 
2798                         // Trailing bits
2799                         if (last)
2800                                 *dst = comp(*src, *dst, last);
2801                 }
2802         } else {
2803                 // Different alignment for source and dest
2804 
2805                 right = shift & (BITS_PER_LONG - 1);
2806                 left = -shift & (BITS_PER_LONG - 1);
2807 
2808                 if ((unsigned long)dst_idx + 1 >= n) {
2809                         // Single destination word
2810                         if (last)
2811                                 first &= last;
2812                         if (shift < 0) {
2813                                 // Single source word
2814                                 *dst = comp(*src << left, *dst, first);
2815                         } else if (1 + (unsigned long)src_idx >= n) {
2816                                 // Single source word
2817                                 *dst = comp(*src >> right, *dst, first);
2818                         } else {
2819                                 // 2 source words
2820                                 d0 = *src--;
2821                                 d1 = *src;
2822                                 *dst = comp(d0 >> right | d1 << left, *dst,
2823                                             first);
2824                         }
2825                 } else {
2826                         // Multiple destination words
2827                         d0 = *src--;
2828                         // Leading bits
2829                         if (shift < 0) {
2830                                 // Single source word
2831                                 *dst = comp(d0 << left, *dst, first);
2832                                 dst--;
2833                                 n -= dst_idx + 1;
2834                         } else {
2835                                 // 2 source words
2836                                 d1 = *src--;
2837                                 *dst = comp(d0 >> right | d1 << left, *dst,
2838                                             first);
2839                                 d0 = d1;
2840                                 dst--;
2841                                 n -= dst_idx + 1;
2842                         }
2843 
2844                         // Main chunk
2845                         m = n % BITS_PER_LONG;
2846                         n /= BITS_PER_LONG;
2847                         while (n >= 4) {
2848                                 d1 = *src--;
2849                                 *dst-- = d0 >> right | d1 << left;
2850                                 d0 = d1;
2851                                 d1 = *src--;
2852                                 *dst-- = d0 >> right | d1 << left;
2853                                 d0 = d1;
2854                                 d1 = *src--;
2855                                 *dst-- = d0 >> right | d1 << left;
2856                                 d0 = d1;
2857                                 d1 = *src--;
2858                                 *dst-- = d0 >> right | d1 << left;
2859                                 d0 = d1;
2860                                 n -= 4;
2861                         }
2862                         while (n--) {
2863                                 d1 = *src--;
2864                                 *dst-- = d0 >> right | d1 << left;
2865                                 d0 = d1;
2866                         }
2867 
2868                         // Trailing bits
2869                         if (last) {
2870                                 if (m <= left) {
2871                                         // Single source word
2872                                         *dst = comp(d0 >> right, *dst, last);
2873                                 } else {
2874                                         // 2 source words
2875                                         d1 = *src;
2876                                         *dst = comp(d0 >> right | d1 << left,
2877                                                     *dst, last);
2878                                 }
2879                         }
2880                 }
2881         }
2882 }
2883 
2884 
2885         /*
2886          *  Unaligned forward inverting bit copy using 32-bit or 64-bit memory
2887          *  accesses
2888          */
2889 
2890 static void bitcpy_not(unsigned long *dst, int dst_idx,
2891                        const unsigned long *src, int src_idx, u32 n)
2892 {
2893         unsigned long first, last;
2894         int shift = dst_idx - src_idx, left, right;
2895         unsigned long d0, d1;
2896         int m;
2897 
2898         if (!n)
2899                 return;
2900 
2901         shift = dst_idx - src_idx;
2902         first = ~0UL >> dst_idx;
2903         last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
2904 
2905         if (!shift) {
2906                 // Same alignment for source and dest
2907 
2908                 if (dst_idx + n <= BITS_PER_LONG) {
2909                         // Single word
2910                         if (last)
2911                                 first &= last;
2912                         *dst = comp(~*src, *dst, first);
2913                 } else {
2914                         // Multiple destination words
2915                         // Leading bits
2916                         if (first) {
2917                                 *dst = comp(~*src, *dst, first);
2918                                 dst++;
2919                                 src++;
2920                                 n -= BITS_PER_LONG - dst_idx;
2921                         }
2922 
2923                         // Main chunk
2924                         n /= BITS_PER_LONG;
2925                         while (n >= 8) {
2926                                 *dst++ = ~*src++;
2927                                 *dst++ = ~*src++;
2928                                 *dst++ = ~*src++;
2929                                 *dst++ = ~*src++;
2930                                 *dst++ = ~*src++;
2931                                 *dst++ = ~*src++;
2932                                 *dst++ = ~*src++;
2933                                 *dst++ = ~*src++;
2934                                 n -= 8;
2935                         }
2936                         while (n--)
2937                                 *dst++ = ~*src++;
2938 
2939                         // Trailing bits
2940                         if (last)
2941                                 *dst = comp(~*src, *dst, last);
2942                 }
2943         } else {
2944                 // Different alignment for source and dest
2945 
2946                 right = shift & (BITS_PER_LONG - 1);
2947                 left = -shift & (BITS_PER_LONG - 1);
2948 
2949                 if (dst_idx + n <= BITS_PER_LONG) {
2950                         // Single destination word
2951                         if (last)
2952                                 first &= last;
2953                         if (shift > 0) {
2954                                 // Single source word
2955                                 *dst = comp(~*src >> right, *dst, first);
2956                         } else if (src_idx + n <= BITS_PER_LONG) {
2957                                 // Single source word
2958                                 *dst = comp(~*src << left, *dst, first);
2959                         } else {
2960                                 // 2 source words
2961                                 d0 = ~*src++;
2962                                 d1 = ~*src;
2963                                 *dst = comp(d0 << left | d1 >> right, *dst,
2964                                             first);
2965                         }
2966                 } else {
2967                         // Multiple destination words
2968                         d0 = ~*src++;
2969                         // Leading bits
2970                         if (shift > 0) {
2971                                 // Single source word
2972                                 *dst = comp(d0 >> right, *dst, first);
2973                                 dst++;
2974                                 n -= BITS_PER_LONG - dst_idx;
2975                         } else {
2976                                 // 2 source words
2977                                 d1 = ~*src++;
2978                                 *dst = comp(d0 << left | d1 >> right, *dst,
2979                                             first);
2980                                 d0 = d1;
2981                                 dst++;
2982                                 n -= BITS_PER_LONG - dst_idx;
2983                         }
2984 
2985                         // Main chunk
2986                         m = n % BITS_PER_LONG;
2987                         n /= BITS_PER_LONG;
2988                         while (n >= 4) {
2989                                 d1 = ~*src++;
2990                                 *dst++ = d0 << left | d1 >> right;
2991                                 d0 = d1;
2992                                 d1 = ~*src++;
2993                                 *dst++ = d0 << left | d1 >> right;
2994                                 d0 = d1;
2995                                 d1 = ~*src++;
2996                                 *dst++ = d0 << left | d1 >> right;
2997                                 d0 = d1;
2998                                 d1 = ~*src++;
2999                                 *dst++ = d0 << left | d1 >> right;
3000                                 d0 = d1;
3001                                 n -= 4;
3002                         }
3003                         while (n--) {
3004                                 d1 = ~*src++;
3005                                 *dst++ = d0 << left | d1 >> right;
3006                                 d0 = d1;
3007                         }
3008 
3009                         // Trailing bits
3010                         if (last) {
3011                                 if (m <= right) {
3012                                         // Single source word
3013                                         *dst = comp(d0 << left, *dst, last);
3014                                 } else {
3015                                         // 2 source words
3016                                         d1 = ~*src;
3017                                         *dst = comp(d0 << left | d1 >> right,
3018                                                     *dst, last);
3019                                 }
3020                         }
3021                 }
3022         }
3023 }
3024 
3025 
3026         /*
3027          *  Unaligned 32-bit pattern fill using 32/64-bit memory accesses
3028          */
3029 
3030 static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
3031 {
3032         unsigned long val = pat;
3033         unsigned long first, last;
3034 
3035         if (!n)
3036                 return;
3037 
3038 #if BITS_PER_LONG == 64
3039         val |= val << 32;
3040 #endif
3041 
3042         first = ~0UL >> dst_idx;
3043         last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
3044 
3045         if (dst_idx + n <= BITS_PER_LONG) {
3046                 // Single word
3047                 if (last)
3048                         first &= last;
3049                 *dst = comp(val, *dst, first);
3050         } else {
3051                 // Multiple destination words
3052                 // Leading bits
3053                 if (first) {
3054                         *dst = comp(val, *dst, first);
3055                         dst++;
3056                         n -= BITS_PER_LONG - dst_idx;
3057                 }
3058 
3059                 // Main chunk
3060                 n /= BITS_PER_LONG;
3061                 while (n >= 8) {
3062                         *dst++ = val;
3063                         *dst++ = val;
3064                         *dst++ = val;
3065                         *dst++ = val;
3066                         *dst++ = val;
3067                         *dst++ = val;
3068                         *dst++ = val;
3069                         *dst++ = val;
3070                         n -= 8;
3071                 }
3072                 while (n--)
3073                         *dst++ = val;
3074 
3075                 // Trailing bits
3076                 if (last)
3077                         *dst = comp(val, *dst, last);
3078         }
3079 }
3080 
3081 
3082         /*
3083          *  Unaligned 32-bit pattern xor using 32/64-bit memory accesses
3084          */
3085 
3086 static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
3087 {
3088         unsigned long val = pat;
3089         unsigned long first, last;
3090 
3091         if (!n)
3092                 return;
3093 
3094 #if BITS_PER_LONG == 64
3095         val |= val << 32;
3096 #endif
3097 
3098         first = ~0UL >> dst_idx;
3099         last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
3100 
3101         if (dst_idx + n <= BITS_PER_LONG) {
3102                 // Single word
3103                 if (last)
3104                         first &= last;
3105                 *dst = xor(val, *dst, first);
3106         } else {
3107                 // Multiple destination words
3108                 // Leading bits
3109                 if (first) {
3110                         *dst = xor(val, *dst, first);
3111                         dst++;
3112                         n -= BITS_PER_LONG - dst_idx;
3113                 }
3114 
3115                 // Main chunk
3116                 n /= BITS_PER_LONG;
3117                 while (n >= 4) {
3118                         *dst++ ^= val;
3119                         *dst++ ^= val;
3120                         *dst++ ^= val;
3121                         *dst++ ^= val;
3122                         n -= 4;
3123                 }
3124                 while (n--)
3125                         *dst++ ^= val;
3126 
3127                 // Trailing bits
3128                 if (last)
3129                         *dst = xor(val, *dst, last);
3130         }
3131 }
3132 
3133 static inline void fill_one_line(int bpp, unsigned long next_plane,
3134                                  unsigned long *dst, int dst_idx, u32 n,
3135                                  u32 color)
3136 {
3137         while (1) {
3138                 dst += dst_idx >> SHIFT_PER_LONG;
3139                 dst_idx &= (BITS_PER_LONG - 1);
3140                 bitfill32(dst, dst_idx, color & 1 ? ~0 : 0, n);
3141                 if (!--bpp)
3142                         break;
3143                 color >>= 1;
3144                 dst_idx += next_plane * 8;
3145         }
3146 }
3147 
3148 static inline void xor_one_line(int bpp, unsigned long next_plane,
3149                                 unsigned long *dst, int dst_idx, u32 n,
3150                                 u32 color)
3151 {
3152         while (color) {
3153                 dst += dst_idx >> SHIFT_PER_LONG;
3154                 dst_idx &= (BITS_PER_LONG - 1);
3155                 bitxor32(dst, dst_idx, color & 1 ? ~0 : 0, n);
3156                 if (!--bpp)
3157                         break;
3158                 color >>= 1;
3159                 dst_idx += next_plane * 8;
3160         }
3161 }
3162 
3163 
3164 static void amifb_fillrect(struct fb_info *info,
3165                            const struct fb_fillrect *rect)
3166 {
3167         struct amifb_par *par = info->par;
3168         int dst_idx, x2, y2;
3169         unsigned long *dst;
3170         u32 width, height;
3171 
3172         if (!rect->width || !rect->height)
3173                 return;
3174 
3175         /*
3176          * We could use hardware clipping but on many cards you get around
3177          * hardware clipping by writing to framebuffer directly.
3178          * */
3179         x2 = rect->dx + rect->width;
3180         y2 = rect->dy + rect->height;
3181         x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
3182         y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
3183         width = x2 - rect->dx;
3184         height = y2 - rect->dy;
3185 
3186         dst = (unsigned long *)
3187                 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
3188         dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
3189         dst_idx += rect->dy * par->next_line * 8 + rect->dx;
3190         while (height--) {
3191                 switch (rect->rop) {
3192                 case ROP_COPY:
3193                         fill_one_line(info->var.bits_per_pixel,
3194                                       par->next_plane, dst, dst_idx, width,
3195                                       rect->color);
3196                         break;
3197 
3198                 case ROP_XOR:
3199                         xor_one_line(info->var.bits_per_pixel, par->next_plane,
3200                                      dst, dst_idx, width, rect->color);
3201                         break;
3202                 }
3203                 dst_idx += par->next_line * 8;
3204         }
3205 }
3206 
3207 static inline void copy_one_line(int bpp, unsigned long next_plane,
3208                                  unsigned long *dst, int dst_idx,
3209                                  unsigned long *src, int src_idx, u32 n)
3210 {
3211         while (1) {
3212                 dst += dst_idx >> SHIFT_PER_LONG;
3213                 dst_idx &= (BITS_PER_LONG - 1);
3214                 src += src_idx >> SHIFT_PER_LONG;
3215                 src_idx &= (BITS_PER_LONG - 1);
3216                 bitcpy(dst, dst_idx, src, src_idx, n);
3217                 if (!--bpp)
3218                         break;
3219                 dst_idx += next_plane * 8;
3220                 src_idx += next_plane * 8;
3221         }
3222 }
3223 
3224 static inline void copy_one_line_rev(int bpp, unsigned long next_plane,
3225                                      unsigned long *dst, int dst_idx,
3226                                      unsigned long *src, int src_idx, u32 n)
3227 {
3228         while (1) {
3229                 dst += dst_idx >> SHIFT_PER_LONG;
3230                 dst_idx &= (BITS_PER_LONG - 1);
3231                 src += src_idx >> SHIFT_PER_LONG;
3232                 src_idx &= (BITS_PER_LONG - 1);
3233                 bitcpy_rev(dst, dst_idx, src, src_idx, n);
3234                 if (!--bpp)
3235                         break;
3236                 dst_idx += next_plane * 8;
3237                 src_idx += next_plane * 8;
3238         }
3239 }
3240 
3241 
3242 static void amifb_copyarea(struct fb_info *info,
3243                            const struct fb_copyarea *area)
3244 {
3245         struct amifb_par *par = info->par;
3246         int x2, y2;
3247         u32 dx, dy, sx, sy, width, height;
3248         unsigned long *dst, *src;
3249         int dst_idx, src_idx;
3250         int rev_copy = 0;
3251 
3252         /* clip the destination */
3253         x2 = area->dx + area->width;
3254         y2 = area->dy + area->height;
3255         dx = area->dx > 0 ? area->dx : 0;
3256         dy = area->dy > 0 ? area->dy : 0;
3257         x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
3258         y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
3259         width = x2 - dx;
3260         height = y2 - dy;
3261 
3262         if (area->sx + dx < area->dx || area->sy + dy < area->dy)
3263                 return;
3264 
3265         /* update sx,sy */
3266         sx = area->sx + (dx - area->dx);
3267         sy = area->sy + (dy - area->dy);
3268 
3269         /* the source must be completely inside the virtual screen */
3270         if (sx + width > info->var.xres_virtual ||
3271                         sy + height > info->var.yres_virtual)
3272                 return;
3273 
3274         if (dy > sy || (dy == sy && dx > sx)) {
3275                 dy += height;
3276                 sy += height;
3277                 rev_copy = 1;
3278         }
3279         dst = (unsigned long *)
3280                 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
3281         src = dst;
3282         dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
3283         src_idx = dst_idx;
3284         dst_idx += dy * par->next_line * 8 + dx;
3285         src_idx += sy * par->next_line * 8 + sx;
3286         if (rev_copy) {
3287                 while (height--) {
3288                         dst_idx -= par->next_line * 8;
3289                         src_idx -= par->next_line * 8;
3290                         copy_one_line_rev(info->var.bits_per_pixel,
3291                                           par->next_plane, dst, dst_idx, src,
3292                                           src_idx, width);
3293                 }
3294         } else {
3295                 while (height--) {
3296                         copy_one_line(info->var.bits_per_pixel,
3297                                       par->next_plane, dst, dst_idx, src,
3298                                       src_idx, width);
3299                         dst_idx += par->next_line * 8;
3300                         src_idx += par->next_line * 8;
3301                 }
3302         }
3303 }
3304 
3305 
3306 static inline void expand_one_line(int bpp, unsigned long next_plane,
3307                                    unsigned long *dst, int dst_idx, u32 n,
3308                                    const u8 *data, u32 bgcolor, u32 fgcolor)
3309 {
3310         const unsigned long *src;
3311         int src_idx;
3312 
3313         while (1) {
3314                 dst += dst_idx >> SHIFT_PER_LONG;
3315                 dst_idx &= (BITS_PER_LONG - 1);
3316                 if ((bgcolor ^ fgcolor) & 1) {
3317                         src = (unsigned long *)
3318                                 ((unsigned long)data & ~(BYTES_PER_LONG - 1));
3319                         src_idx = ((unsigned long)data & (BYTES_PER_LONG - 1)) * 8;
3320                         if (fgcolor & 1)
3321                                 bitcpy(dst, dst_idx, src, src_idx, n);
3322                         else
3323                                 bitcpy_not(dst, dst_idx, src, src_idx, n);
3324                         /* set or clear */
3325                 } else
3326                         bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n);
3327                 if (!--bpp)
3328                         break;
3329                 bgcolor >>= 1;
3330                 fgcolor >>= 1;
3331                 dst_idx += next_plane * 8;
3332         }
3333 }
3334 
3335 
3336 static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
3337 {
3338         struct amifb_par *par = info->par;
3339         int x2, y2;
3340         unsigned long *dst;
3341         int dst_idx;
3342         const char *src;
3343         u32 dx, dy, width, height, pitch;
3344 
3345         /*
3346          * We could use hardware clipping but on many cards you get around
3347          * hardware clipping by writing to framebuffer directly like we are
3348          * doing here.
3349          */
3350         x2 = image->dx + image->width;
3351         y2 = image->dy + image->height;
3352         dx = image->dx;
3353         dy = image->dy;
3354         x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
3355         y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
3356         width  = x2 - dx;
3357         height = y2 - dy;
3358 
3359         if (image->depth == 1) {
3360                 dst = (unsigned long *)
3361                         ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
3362                 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
3363                 dst_idx += dy * par->next_line * 8 + dx;
3364                 src = image->data;
3365                 pitch = (image->width + 7) / 8;
3366                 while (height--) {
3367                         expand_one_line(info->var.bits_per_pixel,
3368                                         par->next_plane, dst, dst_idx, width,
3369                                         src, image->bg_color,
3370                                         image->fg_color);
3371                         dst_idx += par->next_line * 8;
3372                         src += pitch;
3373                 }
3374         } else {
3375                 c2p_planar(info->screen_base, image->data, dx, dy, width,
3376                            height, par->next_line, par->next_plane,
3377                            image->width, info->var.bits_per_pixel);
3378         }
3379 }
3380 
3381 
3382         /*
3383          * Amiga Frame Buffer Specific ioctls
3384          */
3385 
3386 static int amifb_ioctl(struct fb_info *info,
3387                        unsigned int cmd, unsigned long arg)
3388 {
3389         union {
3390                 struct fb_fix_cursorinfo fix;
3391                 struct fb_var_cursorinfo var;
3392                 struct fb_cursorstate state;
3393         } crsr;
3394         void __user *argp = (void __user *)arg;
3395         int i;
3396 
3397         switch (cmd) {
3398         case FBIOGET_FCURSORINFO:
3399                 i = ami_get_fix_cursorinfo(&crsr.fix, info->par);
3400                 if (i)
3401                         return i;
3402                 return copy_to_user(argp, &crsr.fix,
3403                                     sizeof(crsr.fix)) ? -EFAULT : 0;
3404 
3405         case FBIOGET_VCURSORINFO:
3406                 i = ami_get_var_cursorinfo(&crsr.var,
3407                         ((struct fb_var_cursorinfo __user *)arg)->data,
3408                         info->par);
3409                 if (i)
3410                         return i;
3411                 return copy_to_user(argp, &crsr.var,
3412                                     sizeof(crsr.var)) ? -EFAULT : 0;
3413 
3414         case FBIOPUT_VCURSORINFO:
3415                 if (copy_from_user(&crsr.var, argp, sizeof(crsr.var)))
3416                         return -EFAULT;
3417                 return ami_set_var_cursorinfo(&crsr.var,
3418                         ((struct fb_var_cursorinfo __user *)arg)->data,
3419                         info->par);
3420 
3421         case FBIOGET_CURSORSTATE:
3422                 i = ami_get_cursorstate(&crsr.state, info->par);
3423                 if (i)
3424                         return i;
3425                 return copy_to_user(argp, &crsr.state,
3426                                     sizeof(crsr.state)) ? -EFAULT : 0;
3427 
3428         case FBIOPUT_CURSORSTATE:
3429                 if (copy_from_user(&crsr.state, argp, sizeof(crsr.state)))
3430                         return -EFAULT;
3431                 return ami_set_cursorstate(&crsr.state, info->par);
3432         }
3433         return -EINVAL;
3434 }
3435 
3436 
3437         /*
3438          * Flash the cursor (called by VBlank interrupt)
3439          */
3440 
3441 static int flash_cursor(void)
3442 {
3443         static int cursorcount = 1;
3444 
3445         if (cursormode == FB_CURSOR_FLASH) {
3446                 if (!--cursorcount) {
3447                         cursorstate = -cursorstate;
3448                         cursorcount = cursorrate;
3449                         if (!is_blanked)
3450                                 return 1;
3451                 }
3452         }
3453         return 0;
3454 }
3455 
3456         /*
3457          * VBlank Display Interrupt
3458          */
3459 
3460 static irqreturn_t amifb_interrupt(int irq, void *dev_id)
3461 {
3462         struct amifb_par *par = dev_id;
3463 
3464         if (do_vmode_pan || do_vmode_full)
3465                 ami_update_display(par);
3466 
3467         if (do_vmode_full)
3468                 ami_init_display(par);
3469 
3470         if (do_vmode_pan) {
3471                 flash_cursor();
3472                 ami_rebuild_copper(par);
3473                 do_cursor = do_vmode_pan = 0;
3474         } else if (do_cursor) {
3475                 flash_cursor();
3476                 ami_set_sprite(par);
3477                 do_cursor = 0;
3478         } else {
3479                 if (flash_cursor())
3480                         ami_set_sprite(par);
3481         }
3482 
3483         if (do_blank) {
3484                 ami_do_blank(par);
3485                 do_blank = 0;
3486         }
3487 
3488         if (do_vmode_full) {
3489                 ami_reinit_copper(par);
3490                 do_vmode_full = 0;
3491         }
3492         return IRQ_HANDLED;
3493 }
3494 
3495 
3496 static struct fb_ops amifb_ops = {
3497         .owner          = THIS_MODULE,
3498         .fb_check_var   = amifb_check_var,
3499         .fb_set_par     = amifb_set_par,
3500         .fb_setcolreg   = amifb_setcolreg,
3501         .fb_blank       = amifb_blank,
3502         .fb_pan_display = amifb_pan_display,
3503         .fb_fillrect    = amifb_fillrect,
3504         .fb_copyarea    = amifb_copyarea,
3505         .fb_imageblit   = amifb_imageblit,
3506         .fb_ioctl       = amifb_ioctl,
3507 };
3508 
3509 
3510         /*
3511          * Allocate, Clear and Align a Block of Chip Memory
3512          */
3513 
3514 static void *aligned_chipptr;
3515 
3516 static inline u_long __init chipalloc(u_long size)
3517 {
3518         aligned_chipptr = amiga_chip_alloc(size, "amifb [RAM]");
3519         if (!aligned_chipptr) {
3520                 pr_err("amifb: No Chip RAM for frame buffer");
3521                 return 0;
3522         }
3523         memset(aligned_chipptr, 0, size);
3524         return (u_long)aligned_chipptr;
3525 }
3526 
3527 static inline void chipfree(void)
3528 {
3529         if (aligned_chipptr)
3530                 amiga_chip_free(aligned_chipptr);
3531 }
3532 
3533 
3534         /*
3535          * Initialisation
3536          */
3537 
3538 static int __init amifb_probe(struct platform_device *pdev)
3539 {
3540         struct fb_info *info;
3541         int tag, i, err = 0;
3542         u_long chipptr;
3543         u_int defmode;
3544 
3545 #ifndef MODULE
3546         char *option = NULL;
3547 
3548         if (fb_get_options("amifb", &option)) {
3549                 amifb_video_off();
3550                 return -ENODEV;
3551         }
3552         amifb_setup(option);
3553 #endif
3554         custom.dmacon = DMAF_ALL | DMAF_MASTER;
3555 
3556         info = framebuffer_alloc(sizeof(struct amifb_par), &pdev->dev);
3557         if (!info)
3558                 return -ENOMEM;
3559 
3560         strcpy(info->fix.id, "Amiga ");
3561         info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
3562         info->fix.accel = FB_ACCEL_AMIGABLITT;
3563 
3564         switch (amiga_chipset) {
3565 #ifdef CONFIG_FB_AMIGA_OCS
3566         case CS_OCS:
3567                 strcat(info->fix.id, "OCS");
3568 default_chipset:
3569                 chipset = TAG_OCS;
3570                 maxdepth[TAG_SHRES] = 0;        /* OCS means no SHRES */
3571                 maxdepth[TAG_HIRES] = 4;
3572                 maxdepth[TAG_LORES] = 6;
3573                 maxfmode = TAG_FMODE_1;
3574                 defmode = amiga_vblank == 50 ? DEFMODE_PAL : DEFMODE_NTSC;
3575                 info->fix.smem_len = VIDEOMEMSIZE_OCS;
3576                 break;
3577 #endif /* CONFIG_FB_AMIGA_OCS */
3578 
3579 #ifdef CONFIG_FB_AMIGA_ECS
3580         case CS_ECS:
3581                 strcat(info->fix.id, "ECS");
3582                 chipset = TAG_ECS;
3583                 maxdepth[TAG_SHRES] = 2;
3584                 maxdepth[TAG_HIRES] = 4;
3585                 maxdepth[TAG_LORES] = 6;
3586                 maxfmode = TAG_FMODE_1;
3587                 if (AMIGAHW_PRESENT(AMBER_FF))
3588                         defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL
3589                                                      : DEFMODE_AMBER_NTSC;
3590                 else
3591                         defmode = amiga_vblank == 50 ? DEFMODE_PAL
3592                                                      : DEFMODE_NTSC;
3593                 if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
3594                     VIDEOMEMSIZE_ECS_2M)
3595                         info->fix.smem_len = VIDEOMEMSIZE_ECS_2M;
3596                 else
3597                         info->fix.smem_len = VIDEOMEMSIZE_ECS_1M;
3598                 break;
3599 #endif /* CONFIG_FB_AMIGA_ECS */
3600 
3601 #ifdef CONFIG_FB_AMIGA_AGA
3602         case CS_AGA:
3603                 strcat(info->fix.id, "AGA");
3604                 chipset = TAG_AGA;
3605                 maxdepth[TAG_SHRES] = 8;
3606                 maxdepth[TAG_HIRES] = 8;
3607                 maxdepth[TAG_LORES] = 8;
3608                 maxfmode = TAG_FMODE_4;
3609                 defmode = DEFMODE_AGA;
3610                 if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
3611                     VIDEOMEMSIZE_AGA_2M)
3612                         info->fix.smem_len = VIDEOMEMSIZE_AGA_2M;
3613                 else
3614                         info->fix.smem_len = VIDEOMEMSIZE_AGA_1M;
3615                 break;
3616 #endif /* CONFIG_FB_AMIGA_AGA */
3617 
3618         default:
3619 #ifdef CONFIG_FB_AMIGA_OCS
3620                 printk("Unknown graphics chipset, defaulting to OCS\n");
3621                 strcat(info->fix.id, "Unknown");
3622                 goto default_chipset;
3623 #else /* CONFIG_FB_AMIGA_OCS */
3624                 err = -ENODEV;
3625                 goto release;
3626 #endif /* CONFIG_FB_AMIGA_OCS */
3627                 break;
3628         }
3629 
3630         /*
3631          * Calculate the Pixel Clock Values for this Machine
3632          */
3633 
3634         {
3635         u_long tmp = DIVUL(200000000000ULL, amiga_eclock);
3636 
3637         pixclock[TAG_SHRES] = (tmp + 4) / 8;    /* SHRES:  35 ns / 28 MHz */
3638         pixclock[TAG_HIRES] = (tmp + 2) / 4;    /* HIRES:  70 ns / 14 MHz */
3639         pixclock[TAG_LORES] = (tmp + 1) / 2;    /* LORES: 140 ns /  7 MHz */
3640         }
3641 
3642         /*
3643          * Replace the Tag Values with the Real Pixel Clock Values
3644          */
3645 
3646         for (i = 0; i < NUM_TOTAL_MODES; i++) {
3647                 struct fb_videomode *mode = &ami_modedb[i];
3648                 tag = mode->pixclock;
3649                 if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) {
3650                         mode->pixclock = pixclock[tag];
3651                 }
3652         }
3653 
3654         if (amifb_hfmin) {
3655                 info->monspecs.hfmin = amifb_hfmin;
3656                 info->monspecs.hfmax = amifb_hfmax;
3657                 info->monspecs.vfmin = amifb_vfmin;
3658                 info->monspecs.vfmax = amifb_vfmax;
3659         } else {
3660                 /*
3661                  *  These are for a typical Amiga monitor (e.g. A1960)
3662                  */
3663                 info->monspecs.hfmin = 15000;
3664                 info->monspecs.hfmax = 38000;
3665                 info->monspecs.vfmin = 49;
3666                 info->monspecs.vfmax = 90;
3667         }
3668 
3669         info->fbops = &amifb_ops;
3670         info->flags = FBINFO_DEFAULT;
3671         info->device = &pdev->dev;
3672 
3673         if (!fb_find_mode(&info->var, info, mode_option, ami_modedb,
3674                           NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
3675                 err = -EINVAL;
3676                 goto release;
3677         }
3678 
3679         fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES,
3680                                  &info->modelist);
3681 
3682         round_down_bpp = 0;
3683         chipptr = chipalloc(info->fix.smem_len + SPRITEMEMSIZE +
3684                             DUMMYSPRITEMEMSIZE + COPINITSIZE +
3685                             4 * COPLISTSIZE);
3686         if (!chipptr) {
3687                 err = -ENOMEM;
3688                 goto release;
3689         }
3690 
3691         assignchunk(videomemory, u_long, chipptr, info->fix.smem_len);
3692         assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE);
3693         assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE);
3694         assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE);
3695         assignchunk(copdisplay.list[0][0], copins *, chipptr, COPLISTSIZE);
3696         assignchunk(copdisplay.list[0][1], copins *, chipptr, COPLISTSIZE);
3697         assignchunk(copdisplay.list[1][0], copins *, chipptr, COPLISTSIZE);
3698         assignchunk(copdisplay.list[1][1], copins *, chipptr, COPLISTSIZE);
3699 
3700         /*
3701          * access the videomem with writethrough cache
3702          */
3703         info->fix.smem_start = (u_long)ZTWO_PADDR(videomemory);
3704         videomemory = (u_long)ioremap_wt(info->fix.smem_start,
3705                                          info->fix.smem_len);
3706         if (!videomemory) {
3707                 dev_warn(&pdev->dev,
3708                          "Unable to map videomem cached writethrough\n");
3709                 info->screen_base = ZTWO_VADDR(info->fix.smem_start);
3710         } else
3711                 info->screen_base = (char *)videomemory;
3712 
3713         memset(dummysprite, 0, DUMMYSPRITEMEMSIZE);
3714 
3715         /*
3716          * Make sure the Copper has something to do
3717          */
3718         ami_init_copper();
3719 
3720         /*
3721          * Enable Display DMA
3722          */
3723         custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
3724                         DMAF_BLITTER | DMAF_SPRITE;
3725 
3726         err = request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0,
3727                           "fb vertb handler", info->par);
3728         if (err)
3729                 goto disable_dma;
3730 
3731         err = fb_alloc_cmap(&info->cmap, 1 << info->var.bits_per_pixel, 0);
3732         if (err)
3733                 goto free_irq;
3734 
3735         dev_set_drvdata(&pdev->dev, info);
3736 
3737         err = register_framebuffer(info);
3738         if (err)
3739                 goto unset_drvdata;
3740 
3741         fb_info(info, "%s frame buffer device, using %dK of video memory\n",
3742                 info->fix.id, info->fix.smem_len>>10);
3743 
3744         return 0;
3745 
3746 unset_drvdata:
3747         fb_dealloc_cmap(&info->cmap);
3748 free_irq:
3749         free_irq(IRQ_AMIGA_COPPER, info->par);
3750 disable_dma:
3751         custom.dmacon = DMAF_ALL | DMAF_MASTER;
3752         if (videomemory)
3753                 iounmap((void *)videomemory);
3754         chipfree();
3755 release:
3756         framebuffer_release(info);
3757         return err;
3758 }
3759 
3760 
3761 static int __exit amifb_remove(struct platform_device *pdev)
3762 {
3763         struct fb_info *info = dev_get_drvdata(&pdev->dev);
3764 
3765         unregister_framebuffer(info);
3766         fb_dealloc_cmap(&info->cmap);
3767         free_irq(IRQ_AMIGA_COPPER, info->par);
3768         custom.dmacon = DMAF_ALL | DMAF_MASTER;
3769         if (videomemory)
3770                 iounmap((void *)videomemory);
3771         chipfree();
3772         framebuffer_release(info);
3773         amifb_video_off();
3774         return 0;
3775 }
3776 
3777 static struct platform_driver amifb_driver = {
3778         .remove = __exit_p(amifb_remove),
3779         .driver   = {
3780                 .name   = "amiga-video",
3781         },
3782 };
3783 
3784 module_platform_driver_probe(amifb_driver, amifb_probe);
3785 
3786 MODULE_LICENSE("GPL");
3787 MODULE_ALIAS("platform:amiga-video");

/* [<][>][^][v][top][bottom][index][help] */