2  * linux/drivers/video/amifb.c -- Amiga builtin chipset frame buffer device
 
   4  *    Copyright (C) 1995-2003 Geert Uytterhoeven
 
   6  *          with work by Roman Zippel
 
   9  * This file is based on the Atari frame buffer device (atafb.c):
 
  11  *    Copyright (C) 1994 Martin Schaller
 
  14  *          with work by Andreas Schwab
 
  17  * and on the original Amiga console driver (amicon.c):
 
  19  *    Copyright (C) 1993 Hamish Macdonald
 
  21  *    Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk]
 
  23  *          with work by William Rucklidge (wjr@cs.cornell.edu)
 
  25  *                       Jes Sorensen (jds@kom.auc.dk)
 
  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
 
  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
 
  43 #include <linux/module.h>
 
  44 #include <linux/kernel.h>
 
  45 #include <linux/errno.h>
 
  46 #include <linux/string.h>
 
  48 #include <linux/slab.h>
 
  49 #include <linux/delay.h>
 
  50 #include <linux/interrupt.h>
 
  52 #include <linux/init.h>
 
  53 #include <linux/ioport.h>
 
  55 #include <linux/uaccess.h>
 
  56 #include <asm/system.h>
 
  58 #include <asm/amigahw.h>
 
  59 #include <asm/amigaints.h>
 
  60 #include <asm/setup.h>
 
  67 #if !defined(CONFIG_FB_AMIGA_OCS) && !defined(CONFIG_FB_AMIGA_ECS) && !defined(CONFIG_FB_AMIGA_AGA)
 
  68 #define CONFIG_FB_AMIGA_OCS   /* define at least one fb driver, this will change later */
 
  71 #if !defined(CONFIG_FB_AMIGA_OCS)
 
  73 #elif defined(CONFIG_FB_AMIGA_ECS) || defined(CONFIG_FB_AMIGA_AGA)
 
  74 #  define IS_OCS (chipset == TAG_OCS)
 
  76 #  define CONFIG_FB_AMIGA_OCS_ONLY
 
  80 #if !defined(CONFIG_FB_AMIGA_ECS)
 
  82 #elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_AGA)
 
  83 #  define IS_ECS (chipset == TAG_ECS)
 
  85 #  define CONFIG_FB_AMIGA_ECS_ONLY
 
  89 #if !defined(CONFIG_FB_AMIGA_AGA)
 
  91 #elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_ECS)
 
  92 #  define IS_AGA (chipset == TAG_AGA)
 
  94 #  define CONFIG_FB_AMIGA_AGA_ONLY
 
  99 #  define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
 
 101 #  define DPRINTK(fmt, args...)
 
 104 /*******************************************************************************
 
 107    Generic video timings
 
 108    ---------------------
 
 110    Timings used by the frame buffer interface:
 
 112    +----------+---------------------------------------------+----------+-------+
 
 114    |          |                |upper_margin                |          |       |
 
 116    +----------###############################################----------+-------+
 
 121    |   left   #                |                            #  right   | hsync |
 
 122    |  margin  #                |       xres                 #  margin  |  len  |
 
 123    |<-------->#<---------------+--------------------------->#<-------->|<----->|
 
 137    +----------###############################################----------+-------+
 
 139    |          |                |lower_margin                |          |       |
 
 141    +----------+---------------------------------------------+----------+-------+
 
 145    +----------+---------------------------------------------+----------+-------+
 
 151    The Amiga native chipsets uses another timing scheme:
 
 153       - hsstrt:   Start of horizontal synchronization pulse
 
 154       - hsstop:   End of horizontal synchronization pulse
 
 155       - htotal:   Last value on the line (i.e. line length = htotal+1)
 
 156       - vsstrt:   Start of vertical synchronization pulse
 
 157       - vsstop:   End of vertical synchronization pulse
 
 158       - vtotal:   Last line value (i.e. number of lines = vtotal+1)
 
 159       - hcenter:  Start of vertical retrace for interlace
 
 161    You can specify the blanking timings independently. Currently I just set
 
 162    them equal to the respective synchronization values:
 
 164       - hbstrt:   Start of horizontal blank
 
 165       - hbstop:   End of horizontal blank
 
 166       - vbstrt:   Start of vertical blank
 
 167       - vbstop:   End of vertical blank
 
 169    Horizontal values are in color clock cycles (280 ns), vertical values are in
 
 172    (0, 0) is somewhere in the upper-left corner :-)
 
 175    Amiga visible window definitions
 
 176    --------------------------------
 
 178    Currently I only have values for AGA, SHRES (28 MHz dotclock). Feel free to
 
 179    make corrections and/or additions.
 
 181    Within the above synchronization specifications, the visible window is
 
 182    defined by the following parameters (actual register resolutions may be
 
 183    different; all horizontal values are normalized with respect to the pixel
 
 186       - diwstrt_h:   Horizontal start of the visible window
 
 187       - diwstop_h:   Horizontal stop+1(*) of the visible window
 
 188       - diwstrt_v:   Vertical start of the visible window
 
 189       - diwstop_v:   Vertical stop of the visible window
 
 190       - ddfstrt:     Horizontal start of display DMA
 
 191       - ddfstop:     Horizontal stop of display DMA
 
 192       - hscroll:     Horizontal display output delay
 
 196       - sprstrt_h:   Horizontal start-4 of sprite
 
 197       - sprstrt_v:   Vertical start of sprite
 
 199    (*) Even Commodore did it wrong in the AGA monitor drivers by not adding 1.
 
 201    Horizontal values are in dotclock cycles (35 ns), vertical values are in
 
 204    (0, 0) is somewhere in the upper-left corner :-)
 
 207    Dependencies (AGA, SHRES (35 ns dotclock))
 
 208    -------------------------------------------
 
 210    Since there are much more parameters for the Amiga display than for the
 
 211    frame buffer interface, there must be some dependencies among the Amiga
 
 212    display parameters. Here's what I found out:
 
 214       - ddfstrt and ddfstop are best aligned to 64 pixels.
 
 215       - the chipset needs 64+4 horizontal pixels after the DMA start before the
 
 216         first pixel is output, so diwstrt_h = ddfstrt+64+4 if you want to
 
 217         display the first pixel on the line too. Increase diwstrt_h for virtual
 
 219       - the display DMA always fetches 64 pixels at a time (fmode = 3).
 
 220       - ddfstop is ddfstrt+#pixels-64.
 
 221       - diwstop_h = diwstrt_h+xres+1. Because of the additional 1 this can be 1
 
 223       - hscroll simply adds a delay to the display output. Smooth horizontal
 
 224         panning needs an extra 64 pixels on the left to prefetch the pixels that
 
 225         `fall off' on the left.
 
 226       - if ddfstrt < 192, the sprite DMA cycles are all stolen by the bitplane
 
 227         DMA, so it's best to make the DMA start as late as possible.
 
 228       - you really don't want to make ddfstrt < 128, since this will steal DMA
 
 229         cycles from the other DMA channels (audio, floppy and Chip RAM refresh).
 
 230       - I make diwstop_h and diwstop_v as large as possible.
 
 235       - all values are SHRES pixel (35ns)
 
 237                   table 1:fetchstart  table 2:prefetch    table 3:fetchsize
 
 238                   ------------------  ----------------    -----------------
 
 239    Pixclock     # SHRES|HIRES|LORES # SHRES|HIRES|LORES # SHRES|HIRES|LORES
 
 240    -------------#------+-----+------#------+-----+------#------+-----+------
 
 241    Bus width 1x #   16 |  32 |  64  #   16 |  32 |  64  #   64 |  64 |  64
 
 242    Bus width 2x #   32 |  64 | 128  #   32 |  64 |  64  #   64 |  64 | 128
 
 243    Bus width 4x #   64 | 128 | 256  #   64 |  64 |  64  #   64 | 128 | 256
 
 245       - chipset needs 4 pixels before the first pixel is output
 
 246       - ddfstrt must be aligned to fetchstart (table 1)
 
 247       - chipset needs also prefetch (table 2) to get first pixel data, so
 
 248         ddfstrt = ((diwstrt_h-4) & -fetchstart) - prefetch
 
 249       - for horizontal panning decrease diwstrt_h
 
 250       - the length of a fetchline must be aligned to fetchsize (table 3)
 
 251       - if fetchstart is smaller than fetchsize, then ddfstrt can a little bit
 
 252         moved to optimize use of dma (useful for OCS/ECS overscan displays)
 
 253       - ddfstop is ddfstrt+ddfsize-fetchsize
 
 254       - If C= didn't change anything for AGA, then at following positions the
 
 255         dma bus is already used:
 
 256         ddfstrt <  48 -> memory refresh
 
 259                 < 192 -> sprite 0 dma
 
 260                 < 416 -> sprite dma (32 per sprite)
 
 261       - in accordance with the hardware reference manual a hardware stop is at
 
 262         192, but AGA (ECS?) can go below this.
 
 267    Since there are limits on the earliest start value for display DMA and the
 
 268    display of sprites, I use the following policy on horizontal panning and
 
 271       - if you want to start display DMA too early, you lose the ability to
 
 272         do smooth horizontal panning (xpanstep 1 -> 64).
 
 273       - if you want to go even further, you lose the hardware cursor too.
 
 275    IMHO a hardware cursor is more important for X than horizontal scrolling,
 
 276    so that's my motivation.
 
 282    ami_decode_var() converts the frame buffer values to the Amiga values. It's
 
 283    just a `straightforward' implementation of the above rules.
 
 289                xres  yres    left  right  upper  lower    hsync    vsync
 
 290                ----  ----    ----  -----  -----  -----    -----    -----
 
 291       80x25     720   400      27     45     35     12      108        2
 
 292       80x30     720   480      27     45     30      9      108        2
 
 294    These were taken from a XFree86 configuration file, recalculated for a 28 MHz
 
 295    dotclock (Amigas don't have a 25 MHz dotclock) and converted to frame buffer
 
 298    As a comparison, graphics/monitor.h suggests the following:
 
 300                xres  yres    left  right  upper  lower    hsync    vsync
 
 301                ----  ----    ----  -----  -----  -----    -----    -----
 
 303       VGA       640   480      52    112     24     19    112 -      2 +
 
 304       VGA70     640   400      52    112     27     21    112 -      2 -
 
 310       VSYNC    HSYNC    Vertical size    Vertical total
 
 311       -----    -----    -------------    --------------
 
 312         +        +           Reserved          Reserved
 
 317    Source: CL-GD542X Technical Reference Manual, Cirrus Logic, Oct 1992
 
 320    Broadcast video timings
 
 321    -----------------------
 
 323    According to the CCIR and RETMA specifications, we have the following values:
 
 328       - a scanline is 64 Âµs long, of which 52.48 Âµs are visible. This is about
 
 329         736 visible 70 ns pixels per line.
 
 330       - we have 625 scanlines, of which 575 are visible (interlaced); after
 
 331         rounding this becomes 576.
 
 336       - a scanline is 63.5 Âµs long, of which 53.5 Âµs are visible.  This is about
 
 337         736 visible 70 ns pixels per line.
 
 338       - we have 525 scanlines, of which 485 are visible (interlaced); after
 
 339         rounding this becomes 484.
 
 341    Thus if you want a PAL compatible display, you have to do the following:
 
 343       - set the FB_SYNC_BROADCAST flag to indicate that standard broadcast
 
 344         timings are to be used.
 
 345       - make sure upper_margin+yres+lower_margin+vsync_len = 625 for an
 
 346         interlaced, 312 for a non-interlaced and 156 for a doublescanned
 
 348       - make sure left_margin+xres+right_margin+hsync_len = 1816 for a SHRES,
 
 349         908 for a HIRES and 454 for a LORES display.
 
 350       - the left visible part begins at 360 (SHRES; HIRES:180, LORES:90),
 
 351         left_margin+2*hsync_len must be greater or equal.
 
 352       - the upper visible part begins at 48 (interlaced; non-interlaced:24,
 
 353         doublescanned:12), upper_margin+2*vsync_len must be greater or equal.
 
 354       - ami_encode_var() calculates margins with a hsync of 5320 ns and a vsync
 
 357    The settings for a NTSC compatible display are straightforward.
 
 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.
 
 366 *******************************************************************************/
 
 370          * Custom Chipset Definitions
 
 373 #define CUSTOM_OFS(fld) ((long)&((struct CUSTOM*)0)->fld)
 
 376          * BPLCON0 -- Bitplane Control Register 0
 
 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 */
 
 397          * BPLCON2 -- Bitplane Control Register 2
 
 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)
 
 417          * BPLCON3 -- Bitplane Control Register 3 (AGA)
 
 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 */
 
 436          * BPLCON4 -- Bitplane Control Register 4 (AGA)
 
 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)
 
 457          * BEAMCON0 -- Beam Control Register
 
 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 */
 
 478          * FMODE -- Fetch Mode Control Register (AGA)
 
 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 */
 
 489          * Tags used to indicate a specific Pixel Clock
 
 491          * clk_shift is the shift value to get the timings in 35 ns units
 
 494 enum { TAG_SHRES, TAG_HIRES, TAG_LORES };
 
 497          * Tags used to indicate the specific chipset
 
 500 enum { TAG_OCS, TAG_ECS, TAG_AGA };
 
 503          * Tags used to indicate the memory bandwidth
 
 506 enum { TAG_FMODE_1, TAG_FMODE_2, TAG_FMODE_4 };
 
 510          * Clock Definitions, Maximum Display Depth
 
 512          * These depend on the E-Clock or the Chipset, so they are filled in
 
 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;
 
 522          * Broadcast Video Timings
 
 524          * Horizontal values are in 35 ns (SHRES) units
 
 525          * Vertical values are in interlaced scanlines
 
 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)
 
 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)
 
 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)
 
 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)
 
 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)
 
 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)
 
 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)
 
 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)
 
 574 #define upx(x,v)        (((v)+(x)-1) & -(x))
 
 575 #define downx(x,v)      ((v) & -(x))
 
 576 #define modx(x,v)       ((v) & ((x)-1))
 
 578 /* if x1 is not a constant, this macro won't make real sense :-) */
 
 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;})
 
 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))
 
 588 #define highw(x)        ((u_long)(x)>>16 & 0xffff)
 
 589 #define loww(x)         ((u_long)(x) & 0xffff)
 
 591 #define custom          amiga_custom
 
 593 #define VBlankOn()      custom.intena = IF_SETCLR|IF_COPER
 
 594 #define VBlankOff()     custom.intena = IF_COPER
 
 598          * Chip RAM we reserve for the Frame Buffer
 
 600          * This defines the Maximum Virtual Screen Size
 
 601          * (Setable per kernel options?)
 
 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 */
 
 610 #define SPRITEMEMSIZE           (64*64/4) /* max 64*64*4 */
 
 611 #define DUMMYSPRITEMEMSIZE      (8)
 
 612 static u_long spritememory;
 
 614 #define CHIPRAM_SAFETY_LIMIT    (16384)
 
 616 static u_long videomemory;
 
 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
 
 624 static u_long min_fstrt = 192;
 
 626 #define assignchunk(name, type, ptr, size) \
 
 628         (name) = (type)(ptr); \
 
 634          * Copper Instructions
 
 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)
 
 648 static struct copdisplay {
 
 655 static u_short currentcop = 0;
 
 658          * Hardware Cursor API Definitions
 
 659          * These used to be in linux/fb.h, but were preliminary and used by
 
 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
 
 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 */
 
 675         __u16 crsr_color1;              /* colormap entry for cursor color1 */
 
 676         __u16 crsr_color2;              /* colormap entry for cursor color2 */
 
 679 struct fb_var_cursorinfo {
 
 684         __u8 data[1];                   /* field with [height][width]        */
 
 687 struct fb_cursorstate {
 
 693 #define FB_CURSOR_OFF           0
 
 694 #define FB_CURSOR_ON            1
 
 695 #define FB_CURSOR_FLASH         2
 
 702 static int cursorrate = 20;     /* Number of frames/flash toggle */
 
 703 static u_short cursorstate = -1;
 
 704 static u_short cursormode = FB_CURSOR_OFF;
 
 706 static u_short *lofsprite, *shfsprite, *dummysprite;
 
 712 static struct amifb_par {
 
 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 */
 
 736                 short crsr_x;   /* movecursor */
 
 737                 short crsr_y;   /* movecursor */
 
 745         /* OCS Hardware Registers */
 
 747         u_long bplpt0;          /* vmode, pan (Note: physical address) */
 
 748         u_long bplpt0wrap;      /* vmode, pan (Note: physical address) */
 
 753         u_short bplcon0;        /* vmode */
 
 754         u_short bplcon1;        /* vmode */
 
 755         u_short htotal;         /* vmode */
 
 756         u_short vtotal;         /* vmode */
 
 758         /* Additional ECS Hardware Registers */
 
 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 */
 
 772         /* Additional AGA Hardware Registers */
 
 774         u_short fmode;          /* vmode */
 
 778 static struct fb_info fb_info = {
 
 781         .visual         = FB_VISUAL_PSEUDOCOLOR,
 
 782         .accel          = FB_ACCEL_AMIGABLITT
 
 788          *  Saved color entry 0 so we can restore it when unblanking
 
 791 static u_char red0, green0, blue0;
 
 794 #if defined(CONFIG_FB_AMIGA_ECS)
 
 795 static u_short ecs_palette[32];
 
 800          * Latches for Display Changes during VBlank
 
 803 static u_short do_vmode_full = 0;       /* Change the Video Mode */
 
 804 static u_short do_vmode_pan = 0;        /* Update the Video Mode */
 
 805 static short do_blank = 0;              /* (Un)Blank the Screen (±1) */
 
 806 static u_short do_cursor = 0;           /* Move the Cursor */
 
 813 static u_short is_blanked = 0;          /* Screen is Blanked */
 
 814 static u_short is_lace = 0;             /* Screen is laced */
 
 817          * Predefined Video Modes
 
 821 static struct fb_videomode ami_modedb[] __initdata = {
 
 824      *  AmigaOS Video Modes
 
 826      *  If you change these, make sure to update DEFMODE_* as well!
 
 830         /* 640x200, 15 kHz, 60 Hz (NTSC) */
 
 831         "ntsc", 60, 640, 200, TAG_HIRES, 106, 86, 44, 16, 76, 2,
 
 832         FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 
 834         /* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */
 
 835         "ntsc-lace", 60, 640, 400, TAG_HIRES, 106, 86, 88, 33, 76, 4,
 
 836         FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
 
 838         /* 640x256, 15 kHz, 50 Hz (PAL) */
 
 839         "pal", 50, 640, 256, TAG_HIRES, 106, 86, 40, 14, 76, 2,
 
 840         FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 
 842         /* 640x512, 15 kHz, 50 Hz interlaced (PAL) */
 
 843         "pal-lace", 50, 640, 512, TAG_HIRES, 106, 86, 80, 29, 76, 4,
 
 844         FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
 
 846         /* 640x480, 29 kHz, 57 Hz */
 
 847         "multiscan", 57, 640, 480, TAG_SHRES, 96, 112, 29, 8, 72, 8,
 
 848         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 
 850         /* 640x960, 29 kHz, 57 Hz interlaced */
 
 851         "multiscan-lace", 57, 640, 960, TAG_SHRES, 96, 112, 58, 16, 72, 16,
 
 852         0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
 
 854         /* 640x200, 15 kHz, 72 Hz */
 
 855         "euro36", 72, 640, 200, TAG_HIRES, 92, 124, 6, 6, 52, 5,
 
 856         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 
 858         /* 640x400, 15 kHz, 72 Hz interlaced */
 
 859         "euro36-lace", 72, 640, 400, TAG_HIRES, 92, 124, 12, 12, 52, 10,
 
 860         0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
 
 862         /* 640x400, 29 kHz, 68 Hz */
 
 863         "euro72", 68, 640, 400, TAG_SHRES, 164, 92, 9, 9, 80, 8,
 
 864         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 
 866         /* 640x800, 29 kHz, 68 Hz interlaced */
 
 867         "euro72-lace", 68, 640, 800, TAG_SHRES, 164, 92, 18, 18, 80, 16,
 
 868         0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
 
 870         /* 800x300, 23 kHz, 70 Hz */
 
 871         "super72", 70, 800, 300, TAG_SHRES, 212, 140, 10, 11, 80, 7,
 
 872         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 
 874         /* 800x600, 23 kHz, 70 Hz interlaced */
 
 875         "super72-lace", 70, 800, 600, TAG_SHRES, 212, 140, 20, 22, 80, 14,
 
 876         0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
 
 878         /* 640x200, 27 kHz, 57 Hz doublescan */
 
 879         "dblntsc", 57, 640, 200, TAG_SHRES, 196, 124, 18, 17, 80, 4,
 
 880         0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
 
 882         /* 640x400, 27 kHz, 57 Hz */
 
 883         "dblntsc-ff", 57, 640, 400, TAG_SHRES, 196, 124, 36, 35, 80, 7,
 
 884         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 
 886         /* 640x800, 27 kHz, 57 Hz interlaced */
 
 887         "dblntsc-lace", 57, 640, 800, TAG_SHRES, 196, 124, 72, 70, 80, 14,
 
 888         0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
 
 890         /* 640x256, 27 kHz, 47 Hz doublescan */
 
 891         "dblpal", 47, 640, 256, TAG_SHRES, 196, 124, 14, 13, 80, 4,
 
 892         0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
 
 894         /* 640x512, 27 kHz, 47 Hz */
 
 895         "dblpal-ff", 47, 640, 512, TAG_SHRES, 196, 124, 28, 27, 80, 7,
 
 896         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 
 898         /* 640x1024, 27 kHz, 47 Hz interlaced */
 
 899         "dblpal-lace", 47, 640, 1024, TAG_SHRES, 196, 124, 56, 54, 80, 14,
 
 900         0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
 
 908         /* 640x480, 31 kHz, 60 Hz (VGA) */
 
 909         "vga", 60, 640, 480, TAG_SHRES, 64, 96, 30, 9, 112, 2,
 
 910         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 
 912         /* 640x400, 31 kHz, 70 Hz (VGA) */
 
 913         "vga70", 70, 640, 400, TAG_SHRES, 64, 96, 35, 12, 112, 2,
 
 914         FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 
 921      *  These modes don't work yet because there's no A2024 driver.
 
 925         /* 1024x800, 10 Hz */
 
 926         "a2024-10", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
 
 927         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 
 929         /* 1024x800, 15 Hz */
 
 930         "a2024-15", 15, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
 
 931         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 
 936 #define NUM_TOTAL_MODES  ARRAY_SIZE(ami_modedb)
 
 938 static char *mode_option __initdata = NULL;
 
 939 static int round_down_bpp = 1;  /* for mode probing */
 
 946 #define DEFMODE_PAL         2   /* "pal" for PAL OCS/ECS */
 
 947 #define DEFMODE_NTSC        0   /* "ntsc" for NTSC OCS/ECS */
 
 948 #define DEFMODE_AMBER_PAL   3   /* "pal-lace" for flicker fixed PAL (A3000) */
 
 949 #define DEFMODE_AMBER_NTSC  1   /* "ntsc-lace" for flicker fixed NTSC (A3000) */
 
 950 #define DEFMODE_AGA         19  /* "vga70" for AGA */
 
 953 static int amifb_ilbm = 0;      /* interleaved or normal bitplanes */
 
 954 static int amifb_inverse = 0;
 
 958          * Macros for the conversion from real world values to hardware register
 
 961          * This helps us to keep our attention on the real stuff...
 
 963          * Hardware limits for AGA:
 
 965          *      parameter  min    max  step
 
 966          *      ---------  ---   ----  ----
 
 988          * Horizontal values are in 35 ns (SHRES) pixels
 
 989          * Vertical values are in half scanlines
 
 992 /* bplcon1 (smooth scrolling) */
 
 994 #define hscroll2hw(hscroll) \
 
 995         (((hscroll)<<12 & 0x3000) | ((hscroll)<<8 & 0xc300) | \
 
 996          ((hscroll)<<4 & 0x0c00) | ((hscroll)<<2 & 0x00f0) | ((hscroll)>>2 & 0x000f))
 
 998 /* diwstrt/diwstop/diwhigh (visible display window) */
 
1000 #define diwstrt2hw(diwstrt_h, diwstrt_v) \
 
1001         (((diwstrt_v)<<7 & 0xff00) | ((diwstrt_h)>>2 & 0x00ff))
 
1002 #define diwstop2hw(diwstop_h, diwstop_v) \
 
1003         (((diwstop_v)<<7 & 0xff00) | ((diwstop_h)>>2 & 0x00ff))
 
1004 #define diwhigh2hw(diwstrt_h, diwstrt_v, diwstop_h, diwstop_v) \
 
1005         (((diwstop_h)<<3 & 0x2000) | ((diwstop_h)<<11 & 0x1800) | \
 
1006          ((diwstop_v)>>1 & 0x0700) | ((diwstrt_h)>>5 & 0x0020) | \
 
1007          ((diwstrt_h)<<3 & 0x0018) | ((diwstrt_v)>>9 & 0x0007))
 
1009 /* ddfstrt/ddfstop (display DMA) */
 
1011 #define ddfstrt2hw(ddfstrt)     div8(ddfstrt)
 
1012 #define ddfstop2hw(ddfstop)     div8(ddfstop)
 
1014 /* hsstrt/hsstop/htotal/vsstrt/vsstop/vtotal/hcenter (sync timings) */
 
1016 #define hsstrt2hw(hsstrt)       (div8(hsstrt))
 
1017 #define hsstop2hw(hsstop)       (div8(hsstop))
 
1018 #define htotal2hw(htotal)       (div8(htotal)-1)
 
1019 #define vsstrt2hw(vsstrt)       (div2(vsstrt))
 
1020 #define vsstop2hw(vsstop)       (div2(vsstop))
 
1021 #define vtotal2hw(vtotal)       (div2(vtotal)-1)
 
1022 #define hcenter2hw(htotal)      (div8(htotal))
 
1024 /* hbstrt/hbstop/vbstrt/vbstop (blanking timings) */
 
1026 #define hbstrt2hw(hbstrt)       (((hbstrt)<<8 & 0x0700) | ((hbstrt)>>3 & 0x00ff))
 
1027 #define hbstop2hw(hbstop)       (((hbstop)<<8 & 0x0700) | ((hbstop)>>3 & 0x00ff))
 
1028 #define vbstrt2hw(vbstrt)       (div2(vbstrt))
 
1029 #define vbstop2hw(vbstop)       (div2(vbstop))
 
1033 #define rgb2hw8_high(red, green, blue) \
 
1034         (((red & 0xf0)<<4) | (green & 0xf0) | ((blue & 0xf0)>>4))
 
1035 #define rgb2hw8_low(red, green, blue) \
 
1036         (((red & 0x0f)<<8) | ((green & 0x0f)<<4) | (blue & 0x0f))
 
1037 #define rgb2hw4(red, green, blue) \
 
1038         (((red & 0xf0)<<4) | (green & 0xf0) | ((blue & 0xf0)>>4))
 
1039 #define rgb2hw2(red, green, blue) \
 
1040         (((red & 0xc0)<<4) | (green & 0xc0) | ((blue & 0xc0)>>4))
 
1042 /* sprpos/sprctl (sprite positioning) */
 
1044 #define spr2hw_pos(start_v, start_h) \
 
1045         (((start_v)<<7&0xff00) | ((start_h)>>3&0x00ff))
 
1046 #define spr2hw_ctl(start_v, start_h, stop_v) \
 
1047         (((stop_v)<<7&0xff00) | ((start_v)>>4&0x0040) | ((stop_v)>>5&0x0020) | \
 
1048          ((start_h)<<3&0x0018) | ((start_v)>>7&0x0004) | ((stop_v)>>8&0x0002) | \
 
1049          ((start_h)>>2&0x0001))
 
1051 /* get current vertical position of beam */
 
1052 #define get_vbpos()     ((u_short)((*(u_long volatile *)&custom.vposr >> 7) & 0xffe))
 
1055          * Copper Initialisation List
 
1058 #define COPINITSIZE (sizeof(copins)*40)
 
1065          * Long Frame/Short Frame Copper List
 
1066          * Don't change the order, build_copper()/rebuild_copper() rely on this
 
1069 #define COPLISTSIZE (sizeof(copins)*64)
 
1072         cop_wait, cop_bplcon0,
 
1073         cop_spr0ptrh, cop_spr0ptrl,
 
1074         cop_diwstrt, cop_diwstop,
 
1079          * Pixel modes for Bitplanes and Sprites
 
1082 static u_short bplpixmode[3] = {
 
1083         BPC0_SHRES,                     /*  35 ns */
 
1084         BPC0_HIRES,                     /*  70 ns */
 
1088 static u_short sprpixmode[3] = {
 
1089         BPC3_SPRES1 | BPC3_SPRES0,      /*  35 ns */
 
1090         BPC3_SPRES1,                    /*  70 ns */
 
1091         BPC3_SPRES0                     /* 140 ns */
 
1095          * Fetch modes for Bitplanes and Sprites
 
1098 static u_short bplfetchmode[3] = {
 
1100         FMODE_BPL32,                    /* 2x */
 
1101         FMODE_BPAGEM | FMODE_BPL32      /* 4x */
 
1104 static u_short sprfetchmode[3] = {
 
1106         FMODE_SPR32,                    /* 2x */
 
1107         FMODE_SPAGEM | FMODE_SPR32      /* 4x */
 
1112          * Interface used by the world
 
1115 int amifb_setup(char*);
 
1117 static int amifb_check_var(struct fb_var_screeninfo *var,
 
1118                            struct fb_info *info);
 
1119 static int amifb_set_par(struct fb_info *info);
 
1120 static int amifb_setcolreg(unsigned regno, unsigned red, unsigned green,
 
1121                            unsigned blue, unsigned transp,
 
1122                            struct fb_info *info);
 
1123 static int amifb_blank(int blank, struct fb_info *info);
 
1124 static int amifb_pan_display(struct fb_var_screeninfo *var,
 
1125                              struct fb_info *info);
 
1126 static void amifb_fillrect(struct fb_info *info,
 
1127                            const struct fb_fillrect *rect);
 
1128 static void amifb_copyarea(struct fb_info *info,
 
1129                            const struct fb_copyarea *region);
 
1130 static void amifb_imageblit(struct fb_info *info,
 
1131                             const struct fb_image *image);
 
1132 static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg);
 
1136          * Interface to the low level console driver
 
1139 static void amifb_deinit(void);
 
1145 static int flash_cursor(void);
 
1146 static irqreturn_t amifb_interrupt(int irq, void *dev_id);
 
1147 static u_long chipalloc(u_long size);
 
1148 static void chipfree(void);
 
1154 static int ami_decode_var(struct fb_var_screeninfo *var,
 
1155                           struct amifb_par *par);
 
1156 static int ami_encode_var(struct fb_var_screeninfo *var,
 
1157                           struct amifb_par *par);
 
1158 static void ami_pan_var(struct fb_var_screeninfo *var);
 
1159 static int ami_update_par(void);
 
1160 static void ami_update_display(void);
 
1161 static void ami_init_display(void);
 
1162 static void ami_do_blank(void);
 
1163 static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix);
 
1164 static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data);
 
1165 static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data);
 
1166 static int ami_get_cursorstate(struct fb_cursorstate *state);
 
1167 static int ami_set_cursorstate(struct fb_cursorstate *state);
 
1168 static void ami_set_sprite(void);
 
1169 static void ami_init_copper(void);
 
1170 static void ami_reinit_copper(void);
 
1171 static void ami_build_copper(void);
 
1172 static void ami_rebuild_copper(void);
 
1175 static struct fb_ops amifb_ops = {
 
1176         .owner          = THIS_MODULE,
 
1177         .fb_check_var   = amifb_check_var,
 
1178         .fb_set_par     = amifb_set_par,
 
1179         .fb_setcolreg   = amifb_setcolreg,
 
1180         .fb_blank       = amifb_blank,
 
1181         .fb_pan_display = amifb_pan_display,
 
1182         .fb_fillrect    = amifb_fillrect,
 
1183         .fb_copyarea    = amifb_copyarea,
 
1184         .fb_imageblit   = amifb_imageblit,
 
1185         .fb_ioctl       = amifb_ioctl,
 
1188 static void __init amifb_setup_mcap(char *spec)
 
1191         int vmin, vmax, hmin, hmax;
 
1193         /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
 
1194          * <V*> vertical freq. in Hz
 
1195          * <H*> horizontal freq. in kHz
 
1198         if (!(p = strsep(&spec, ";")) || !*p)
 
1200         vmin = simple_strtoul(p, NULL, 10);
 
1203         if (!(p = strsep(&spec, ";")) || !*p)
 
1205         vmax = simple_strtoul(p, NULL, 10);
 
1206         if (vmax <= 0 || vmax <= vmin)
 
1208         if (!(p = strsep(&spec, ";")) || !*p)
 
1210         hmin = 1000 * simple_strtoul(p, NULL, 10);
 
1213         if (!(p = strsep(&spec, "")) || !*p)
 
1215         hmax = 1000 * simple_strtoul(p, NULL, 10);
 
1216         if (hmax <= 0 || hmax <= hmin)
 
1219         fb_info.monspecs.vfmin = vmin;
 
1220         fb_info.monspecs.vfmax = vmax;
 
1221         fb_info.monspecs.hfmin = hmin;
 
1222         fb_info.monspecs.hfmax = hmax;
 
1225 int __init amifb_setup(char *options)
 
1229         if (!options || !*options)
 
1232         while ((this_opt = strsep(&options, ",")) != NULL) {
 
1235                 if (!strcmp(this_opt, "inverse")) {
 
1238                 } else if (!strcmp(this_opt, "ilbm"))
 
1240                 else if (!strncmp(this_opt, "monitorcap:", 11))
 
1241                         amifb_setup_mcap(this_opt+11);
 
1242                 else if (!strncmp(this_opt, "fstart:", 7))
 
1243                         min_fstrt = simple_strtoul(this_opt+7, NULL, 0);
 
1245                         mode_option = this_opt;
 
1255 static int amifb_check_var(struct fb_var_screeninfo *var,
 
1256                            struct fb_info *info)
 
1259         struct amifb_par par;
 
1261         /* Validate wanted screen parameters */
 
1262         if ((err = ami_decode_var(var, &par)))
 
1265         /* Encode (possibly rounded) screen parameters */
 
1266         ami_encode_var(var, &par);
 
1271 static int amifb_set_par(struct fb_info *info)
 
1273         struct amifb_par *par = (struct amifb_par *)info->par;
 
1278         /* Decode wanted screen parameters */
 
1279         ami_decode_var(&info->var, par);
 
1281         /* Set new videomode */
 
1284         /* Set VBlank trigger */
 
1287         /* Update fix for new screen parameters */
 
1288         if (par->bpp == 1) {
 
1289                 info->fix.type = FB_TYPE_PACKED_PIXELS;
 
1290                 info->fix.type_aux = 0;
 
1291         } else if (amifb_ilbm) {
 
1292                 info->fix.type = FB_TYPE_INTERLEAVED_PLANES;
 
1293                 info->fix.type_aux = par->next_line;
 
1295                 info->fix.type = FB_TYPE_PLANES;
 
1296                 info->fix.type_aux = 0;
 
1298         info->fix.line_length = div8(upx(16<<maxfmode, par->vxres));
 
1300         if (par->vmode & FB_VMODE_YWRAP) {
 
1301                 info->fix.ywrapstep = 1;
 
1302                 info->fix.xpanstep = 0;
 
1303                 info->fix.ypanstep = 0;
 
1304                 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP |
 
1305                     FBINFO_READS_FAST; /* override SCROLL_REDRAW */
 
1307                 info->fix.ywrapstep = 0;
 
1308                 if (par->vmode & FB_VMODE_SMOOTH_XPAN)
 
1309                         info->fix.xpanstep = 1;
 
1311                         info->fix.xpanstep = 16<<maxfmode;
 
1312                 info->fix.ypanstep = 1;
 
1313                 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 
1320          * Pan or Wrap the Display
 
1322          * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
 
1325 static int amifb_pan_display(struct fb_var_screeninfo *var,
 
1326                              struct fb_info *info)
 
1328         if (var->vmode & FB_VMODE_YWRAP) {
 
1329                 if (var->yoffset < 0 ||
 
1330                     var->yoffset >= info->var.yres_virtual || var->xoffset)
 
1334                  * TODO: There will be problems when xpan!=1, so some columns
 
1335                  * on the right side will never be seen
 
1337                 if (var->xoffset+info->var.xres > upx(16<<maxfmode, info->var.xres_virtual) ||
 
1338                     var->yoffset+info->var.yres > info->var.yres_virtual)
 
1342         info->var.xoffset = var->xoffset;
 
1343         info->var.yoffset = var->yoffset;
 
1344         if (var->vmode & FB_VMODE_YWRAP)
 
1345                 info->var.vmode |= FB_VMODE_YWRAP;
 
1347                 info->var.vmode &= ~FB_VMODE_YWRAP;
 
1352 #if BITS_PER_LONG == 32
 
1353 #define BYTES_PER_LONG  4
 
1354 #define SHIFT_PER_LONG  5
 
1355 #elif BITS_PER_LONG == 64
 
1356 #define BYTES_PER_LONG  8
 
1357 #define SHIFT_PER_LONG  6
 
1359 #define Please update me
 
1364      *  Compose two values, using a bitmask as decision value
 
1365      *  This is equivalent to (a & mask) | (b & ~mask)
 
1368 static inline unsigned long comp(unsigned long a, unsigned long b,
 
1371         return ((a ^ b) & mask) ^ b;
 
1375 static inline unsigned long xor(unsigned long a, unsigned long b,
 
1378         return (a & mask) ^ b;
 
1383      *  Unaligned forward bit copy using 32-bit or 64-bit memory accesses
 
1386 static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
 
1389         unsigned long first, last;
 
1390         int shift = dst_idx-src_idx, left, right;
 
1391         unsigned long d0, d1;
 
1397         shift = dst_idx-src_idx;
 
1398         first = ~0UL >> dst_idx;
 
1399         last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
 
1402                 // Same alignment for source and dest
 
1404                 if (dst_idx+n <= BITS_PER_LONG) {
 
1408                         *dst = comp(*src, *dst, first);
 
1410                         // Multiple destination words
 
1413                                 *dst = comp(*src, *dst, first);
 
1416                                 n -= BITS_PER_LONG-dst_idx;
 
1437                                 *dst = comp(*src, *dst, last);
 
1440                 // Different alignment for source and dest
 
1442                 right = shift & (BITS_PER_LONG-1);
 
1443                 left = -shift & (BITS_PER_LONG-1);
 
1445                 if (dst_idx+n <= BITS_PER_LONG) {
 
1446                         // Single destination word
 
1450                                 // Single source word
 
1451                                 *dst = comp(*src >> right, *dst, first);
 
1452                         } else if (src_idx+n <= BITS_PER_LONG) {
 
1453                                 // Single source word
 
1454                                 *dst = comp(*src << left, *dst, first);
 
1459                                 *dst = comp(d0 << left | d1 >> right, *dst,
 
1463                         // Multiple destination words
 
1467                                 // Single source word
 
1468                                 *dst = comp(d0 >> right, *dst, first);
 
1470                                 n -= BITS_PER_LONG-dst_idx;
 
1474                                 *dst = comp(d0 << left | d1 >> right, *dst,
 
1478                                 n -= BITS_PER_LONG-dst_idx;
 
1482                         m = n % BITS_PER_LONG;
 
1486                                 *dst++ = d0 << left | d1 >> right;
 
1489                                 *dst++ = d0 << left | d1 >> right;
 
1492                                 *dst++ = d0 << left | d1 >> right;
 
1495                                 *dst++ = d0 << left | d1 >> right;
 
1501                                 *dst++ = d0 << left | d1 >> right;
 
1508                                         // Single source word
 
1509                                         *dst = comp(d0 << left, *dst, last);
 
1513                                         *dst = comp(d0 << left | d1 >> right,
 
1523      *  Unaligned reverse bit copy using 32-bit or 64-bit memory accesses
 
1526 static void bitcpy_rev(unsigned long *dst, int dst_idx,
 
1527                        const unsigned long *src, int src_idx, u32 n)
 
1529         unsigned long first, last;
 
1530         int shift = dst_idx-src_idx, left, right;
 
1531         unsigned long d0, d1;
 
1537         dst += (n-1)/BITS_PER_LONG;
 
1538         src += (n-1)/BITS_PER_LONG;
 
1539         if ((n-1) % BITS_PER_LONG) {
 
1540                 dst_idx += (n-1) % BITS_PER_LONG;
 
1541                 dst += dst_idx >> SHIFT_PER_LONG;
 
1542                 dst_idx &= BITS_PER_LONG-1;
 
1543                 src_idx += (n-1) % BITS_PER_LONG;
 
1544                 src += src_idx >> SHIFT_PER_LONG;
 
1545                 src_idx &= BITS_PER_LONG-1;
 
1548         shift = dst_idx-src_idx;
 
1549         first = ~0UL << (BITS_PER_LONG-1-dst_idx);
 
1550         last = ~(~0UL << (BITS_PER_LONG-1-((dst_idx-n) % BITS_PER_LONG)));
 
1553                 // Same alignment for source and dest
 
1555                 if ((unsigned long)dst_idx+1 >= n) {
 
1559                         *dst = comp(*src, *dst, first);
 
1561                         // Multiple destination words
 
1564                                 *dst = comp(*src, *dst, first);
 
1588                                 *dst = comp(*src, *dst, last);
 
1591                 // Different alignment for source and dest
 
1593                 right = shift & (BITS_PER_LONG-1);
 
1594                 left = -shift & (BITS_PER_LONG-1);
 
1596                 if ((unsigned long)dst_idx+1 >= n) {
 
1597                         // Single destination word
 
1601                                 // Single source word
 
1602                                 *dst = comp(*src << left, *dst, first);
 
1603                         } else if (1+(unsigned long)src_idx >= n) {
 
1604                                 // Single source word
 
1605                                 *dst = comp(*src >> right, *dst, first);
 
1610                                 *dst = comp(d0 >> right | d1 << left, *dst,
 
1614                         // Multiple destination words
 
1618                                 // Single source word
 
1619                                 *dst = comp(d0 << left, *dst, first);
 
1625                                 *dst = comp(d0 >> right | d1 << left, *dst,
 
1633                         m = n % BITS_PER_LONG;
 
1637                                 *dst-- = d0 >> right | d1 << left;
 
1640                                 *dst-- = d0 >> right | d1 << left;
 
1643                                 *dst-- = d0 >> right | d1 << left;
 
1646                                 *dst-- = d0 >> right | d1 << left;
 
1652                                 *dst-- = d0 >> right | d1 << left;
 
1659                                         // Single source word
 
1660                                         *dst = comp(d0 >> right, *dst, last);
 
1664                                         *dst = comp(d0 >> right | d1 << left,
 
1674      *  Unaligned forward inverting bit copy using 32-bit or 64-bit memory
 
1678 static void bitcpy_not(unsigned long *dst, int dst_idx,
 
1679                        const unsigned long *src, int src_idx, u32 n)
 
1681         unsigned long first, last;
 
1682         int shift = dst_idx-src_idx, left, right;
 
1683         unsigned long d0, d1;
 
1689         shift = dst_idx-src_idx;
 
1690         first = ~0UL >> dst_idx;
 
1691         last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
 
1694                 // Same alignment for source and dest
 
1696                 if (dst_idx+n <= BITS_PER_LONG) {
 
1700                         *dst = comp(~*src, *dst, first);
 
1702                         // Multiple destination words
 
1705                                 *dst = comp(~*src, *dst, first);
 
1708                                 n -= BITS_PER_LONG-dst_idx;
 
1729                                 *dst = comp(~*src, *dst, last);
 
1732                 // Different alignment for source and dest
 
1734                 right = shift & (BITS_PER_LONG-1);
 
1735                 left = -shift & (BITS_PER_LONG-1);
 
1737                 if (dst_idx+n <= BITS_PER_LONG) {
 
1738                         // Single destination word
 
1742                                 // Single source word
 
1743                                 *dst = comp(~*src >> right, *dst, first);
 
1744                         } else if (src_idx+n <= BITS_PER_LONG) {
 
1745                                 // Single source word
 
1746                                 *dst = comp(~*src << left, *dst, first);
 
1751                                 *dst = comp(d0 << left | d1 >> right, *dst,
 
1755                         // Multiple destination words
 
1759                                 // Single source word
 
1760                                 *dst = comp(d0 >> right, *dst, first);
 
1762                                 n -= BITS_PER_LONG-dst_idx;
 
1766                                 *dst = comp(d0 << left | d1 >> right, *dst,
 
1770                                 n -= BITS_PER_LONG-dst_idx;
 
1774                         m = n % BITS_PER_LONG;
 
1778                                 *dst++ = d0 << left | d1 >> right;
 
1781                                 *dst++ = d0 << left | d1 >> right;
 
1784                                 *dst++ = d0 << left | d1 >> right;
 
1787                                 *dst++ = d0 << left | d1 >> right;
 
1793                                 *dst++ = d0 << left | d1 >> right;
 
1800                                         // Single source word
 
1801                                         *dst = comp(d0 << left, *dst, last);
 
1805                                         *dst = comp(d0 << left | d1 >> right,
 
1815      *  Unaligned 32-bit pattern fill using 32/64-bit memory accesses
 
1818 static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
 
1820         unsigned long val = pat;
 
1821         unsigned long first, last;
 
1826 #if BITS_PER_LONG == 64
 
1830         first = ~0UL >> dst_idx;
 
1831         last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
 
1833         if (dst_idx+n <= BITS_PER_LONG) {
 
1837                 *dst = comp(val, *dst, first);
 
1839                 // Multiple destination words
 
1842                         *dst = comp(val, *dst, first);
 
1844                         n -= BITS_PER_LONG-dst_idx;
 
1865                         *dst = comp(val, *dst, last);
 
1871      *  Unaligned 32-bit pattern xor using 32/64-bit memory accesses
 
1874 static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
 
1876         unsigned long val = pat;
 
1877         unsigned long first, last;
 
1882 #if BITS_PER_LONG == 64
 
1886         first = ~0UL >> dst_idx;
 
1887         last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
 
1889         if (dst_idx+n <= BITS_PER_LONG) {
 
1893                 *dst = xor(val, *dst, first);
 
1895                 // Multiple destination words
 
1898                         *dst = xor(val, *dst, first);
 
1900                         n -= BITS_PER_LONG-dst_idx;
 
1917                         *dst = xor(val, *dst, last);
 
1921 static inline void fill_one_line(int bpp, unsigned long next_plane,
 
1922                                  unsigned long *dst, int dst_idx, u32 n,
 
1926                 dst += dst_idx >> SHIFT_PER_LONG;
 
1927                 dst_idx &= (BITS_PER_LONG-1);
 
1928                 bitfill32(dst, dst_idx, color & 1 ? ~0 : 0, n);
 
1932                 dst_idx += next_plane*8;
 
1936 static inline void xor_one_line(int bpp, unsigned long next_plane,
 
1937                                 unsigned long *dst, int dst_idx, u32 n,
 
1941                 dst += dst_idx >> SHIFT_PER_LONG;
 
1942                 dst_idx &= (BITS_PER_LONG-1);
 
1943                 bitxor32(dst, dst_idx, color & 1 ? ~0 : 0, n);
 
1947                 dst_idx += next_plane*8;
 
1952 static void amifb_fillrect(struct fb_info *info,
 
1953                            const struct fb_fillrect *rect)
 
1955         struct amifb_par *par = (struct amifb_par *)info->par;
 
1956         int dst_idx, x2, y2;
 
1960         if (!rect->width || !rect->height)
 
1964          * We could use hardware clipping but on many cards you get around
 
1965          * hardware clipping by writing to framebuffer directly.
 
1967         x2 = rect->dx + rect->width;
 
1968         y2 = rect->dy + rect->height;
 
1969         x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
 
1970         y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
 
1971         width = x2 - rect->dx;
 
1972         height = y2 - rect->dy;
 
1974         dst = (unsigned long *)
 
1975                 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1));
 
1976         dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8;
 
1977         dst_idx += rect->dy*par->next_line*8+rect->dx;
 
1979                 switch (rect->rop) {
 
1981                         fill_one_line(info->var.bits_per_pixel,
 
1982                                       par->next_plane, dst, dst_idx, width,
 
1987                         xor_one_line(info->var.bits_per_pixel, par->next_plane,
 
1988                                      dst, dst_idx, width, rect->color);
 
1991                 dst_idx += par->next_line*8;
 
1995 static inline void copy_one_line(int bpp, unsigned long next_plane,
 
1996                                  unsigned long *dst, int dst_idx,
 
1997                                  unsigned long *src, int src_idx, u32 n)
 
2000                 dst += dst_idx >> SHIFT_PER_LONG;
 
2001                 dst_idx &= (BITS_PER_LONG-1);
 
2002                 src += src_idx >> SHIFT_PER_LONG;
 
2003                 src_idx &= (BITS_PER_LONG-1);
 
2004                 bitcpy(dst, dst_idx, src, src_idx, n);
 
2007                 dst_idx += next_plane*8;
 
2008                 src_idx += next_plane*8;
 
2012 static inline void copy_one_line_rev(int bpp, unsigned long next_plane,
 
2013                                      unsigned long *dst, int dst_idx,
 
2014                                      unsigned long *src, int src_idx, u32 n)
 
2017                 dst += dst_idx >> SHIFT_PER_LONG;
 
2018                 dst_idx &= (BITS_PER_LONG-1);
 
2019                 src += src_idx >> SHIFT_PER_LONG;
 
2020                 src_idx &= (BITS_PER_LONG-1);
 
2021                 bitcpy_rev(dst, dst_idx, src, src_idx, n);
 
2024                 dst_idx += next_plane*8;
 
2025                 src_idx += next_plane*8;
 
2030 static void amifb_copyarea(struct fb_info *info,
 
2031                            const struct fb_copyarea *area)
 
2033         struct amifb_par *par = (struct amifb_par *)info->par;
 
2035         u32 dx, dy, sx, sy, width, height;
 
2036         unsigned long *dst, *src;
 
2037         int dst_idx, src_idx;
 
2040         /* clip the destination */
 
2041         x2 = area->dx + area->width;
 
2042         y2 = area->dy + area->height;
 
2043         dx = area->dx > 0 ? area->dx : 0;
 
2044         dy = area->dy > 0 ? area->dy : 0;
 
2045         x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
 
2046         y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
 
2050         if (area->sx + dx < area->dx || area->sy + dy < area->dy)
 
2054         sx = area->sx + (dx - area->dx);
 
2055         sy = area->sy + (dy - area->dy);
 
2057         /* the source must be completely inside the virtual screen */
 
2058         if (sx + width > info->var.xres_virtual ||
 
2059                         sy + height > info->var.yres_virtual)
 
2062         if (dy > sy || (dy == sy && dx > sx)) {
 
2067         dst = (unsigned long *)
 
2068                 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1));
 
2070         dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8;
 
2072         dst_idx += dy*par->next_line*8+dx;
 
2073         src_idx += sy*par->next_line*8+sx;
 
2076                         dst_idx -= par->next_line*8;
 
2077                         src_idx -= par->next_line*8;
 
2078                         copy_one_line_rev(info->var.bits_per_pixel,
 
2079                                           par->next_plane, dst, dst_idx, src,
 
2084                         copy_one_line(info->var.bits_per_pixel,
 
2085                                       par->next_plane, dst, dst_idx, src,
 
2087                         dst_idx += par->next_line*8;
 
2088                         src_idx += par->next_line*8;
 
2094 static inline void expand_one_line(int bpp, unsigned long next_plane,
 
2095                                    unsigned long *dst, int dst_idx, u32 n,
 
2096                                    const u8 *data, u32 bgcolor, u32 fgcolor)
 
2098     const unsigned long *src;
 
2102         dst += dst_idx >> SHIFT_PER_LONG;
 
2103         dst_idx &= (BITS_PER_LONG-1);
 
2104         if ((bgcolor ^ fgcolor) & 1) {
 
2105             src = (unsigned long *)((unsigned long)data & ~(BYTES_PER_LONG-1));
 
2106             src_idx = ((unsigned long)data & (BYTES_PER_LONG-1))*8;
 
2108                 bitcpy(dst, dst_idx, src, src_idx, n);
 
2110                 bitcpy_not(dst, dst_idx, src, src_idx, n);
 
2113             bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n);
 
2118         dst_idx += next_plane*8;
 
2123 static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
 
2125         struct amifb_par *par = (struct amifb_par *)info->par;
 
2130         u32 dx, dy, width, height, pitch;
 
2133          * We could use hardware clipping but on many cards you get around
 
2134          * hardware clipping by writing to framebuffer directly like we are
 
2137         x2 = image->dx + image->width;
 
2138         y2 = image->dy + image->height;
 
2141         x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
 
2142         y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
 
2146         if (image->depth == 1) {
 
2147                 dst = (unsigned long *)
 
2148                         ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1));
 
2149                 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8;
 
2150                 dst_idx += dy*par->next_line*8+dx;
 
2152                 pitch = (image->width+7)/8;
 
2154                         expand_one_line(info->var.bits_per_pixel,
 
2155                                         par->next_plane, dst, dst_idx, width,
 
2156                                         src, image->bg_color,
 
2158                         dst_idx += par->next_line*8;
 
2162                 c2p(info->screen_base, image->data, dx, dy, width, height,
 
2163                     par->next_line, par->next_plane, image->width,
 
2164                     info->var.bits_per_pixel);
 
2170          * Amiga Frame Buffer Specific ioctls
 
2173 static int amifb_ioctl(struct fb_info *info,
 
2174                        unsigned int cmd, unsigned long arg)
 
2177                 struct fb_fix_cursorinfo fix;
 
2178                 struct fb_var_cursorinfo var;
 
2179                 struct fb_cursorstate state;
 
2181         void __user *argp = (void __user *)arg;
 
2185                 case FBIOGET_FCURSORINFO:
 
2186                         i = ami_get_fix_cursorinfo(&crsr.fix);
 
2189                         return copy_to_user(argp, &crsr.fix,
 
2190                                             sizeof(crsr.fix)) ? -EFAULT : 0;
 
2192                 case FBIOGET_VCURSORINFO:
 
2193                         i = ami_get_var_cursorinfo(&crsr.var,
 
2194                                 ((struct fb_var_cursorinfo __user *)arg)->data);
 
2197                         return copy_to_user(argp, &crsr.var,
 
2198                                             sizeof(crsr.var)) ? -EFAULT : 0;
 
2200                 case FBIOPUT_VCURSORINFO:
 
2201                         if (copy_from_user(&crsr.var, argp, sizeof(crsr.var)))
 
2203                         return ami_set_var_cursorinfo(&crsr.var,
 
2204                                 ((struct fb_var_cursorinfo __user *)arg)->data);
 
2206                 case FBIOGET_CURSORSTATE:
 
2207                         i = ami_get_cursorstate(&crsr.state);
 
2210                         return copy_to_user(argp, &crsr.state,
 
2211                                             sizeof(crsr.state)) ? -EFAULT : 0;
 
2213                 case FBIOPUT_CURSORSTATE:
 
2214                         if (copy_from_user(&crsr.state, argp,
 
2215                                            sizeof(crsr.state)))
 
2217                         return ami_set_cursorstate(&crsr.state);
 
2224          * Allocate, Clear and Align a Block of Chip Memory
 
2227 static u_long unaligned_chipptr = 0;
 
2229 static inline u_long __init chipalloc(u_long size)
 
2231         size += PAGE_SIZE-1;
 
2232         if (!(unaligned_chipptr = (u_long)amiga_chip_alloc(size,
 
2234                 panic("No Chip RAM for frame buffer");
 
2235         memset((void *)unaligned_chipptr, 0, size);
 
2236         return PAGE_ALIGN(unaligned_chipptr);
 
2239 static inline void chipfree(void)
 
2241         if (unaligned_chipptr)
 
2242                 amiga_chip_free((void *)unaligned_chipptr);
 
2250 static int __init amifb_init(void)
 
2252         int tag, i, err = 0;
 
2257         char *option = NULL;
 
2259         if (fb_get_options("amifb", &option)) {
 
2263         amifb_setup(option);
 
2265         if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO))
 
2269          * We request all registers starting from bplpt[0]
 
2271         if (!request_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120,
 
2272                                 "amifb [Denise/Lisa]"))
 
2275         custom.dmacon = DMAF_ALL | DMAF_MASTER;
 
2277         switch (amiga_chipset) {
 
2278 #ifdef CONFIG_FB_AMIGA_OCS
 
2280                         strcat(fb_info.fix.id, "OCS");
 
2283                         maxdepth[TAG_SHRES] = 0;        /* OCS means no SHRES */
 
2284                         maxdepth[TAG_HIRES] = 4;
 
2285                         maxdepth[TAG_LORES] = 6;
 
2286                         maxfmode = TAG_FMODE_1;
 
2287                         defmode = amiga_vblank == 50 ? DEFMODE_PAL
 
2289                         fb_info.fix.smem_len = VIDEOMEMSIZE_OCS;
 
2291 #endif /* CONFIG_FB_AMIGA_OCS */
 
2293 #ifdef CONFIG_FB_AMIGA_ECS
 
2295                         strcat(fb_info.fix.id, "ECS");
 
2297                         maxdepth[TAG_SHRES] = 2;
 
2298                         maxdepth[TAG_HIRES] = 4;
 
2299                         maxdepth[TAG_LORES] = 6;
 
2300                         maxfmode = TAG_FMODE_1;
 
2301                         if (AMIGAHW_PRESENT(AMBER_FF))
 
2302                             defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL
 
2303                                                          : DEFMODE_AMBER_NTSC;
 
2305                             defmode = amiga_vblank == 50 ? DEFMODE_PAL
 
2307                         if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT >
 
2308                             VIDEOMEMSIZE_ECS_1M)
 
2309                                 fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_2M;
 
2311                                 fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_1M;
 
2313 #endif /* CONFIG_FB_AMIGA_ECS */
 
2315 #ifdef CONFIG_FB_AMIGA_AGA
 
2317                         strcat(fb_info.fix.id, "AGA");
 
2319                         maxdepth[TAG_SHRES] = 8;
 
2320                         maxdepth[TAG_HIRES] = 8;
 
2321                         maxdepth[TAG_LORES] = 8;
 
2322                         maxfmode = TAG_FMODE_4;
 
2323                         defmode = DEFMODE_AGA;
 
2324                         if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT >
 
2325                             VIDEOMEMSIZE_AGA_1M)
 
2326                                 fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_2M;
 
2328                                 fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_1M;
 
2330 #endif /* CONFIG_FB_AMIGA_AGA */
 
2333 #ifdef CONFIG_FB_AMIGA_OCS
 
2334                         printk("Unknown graphics chipset, defaulting to OCS\n");
 
2335                         strcat(fb_info.fix.id, "Unknown");
 
2336                         goto default_chipset;
 
2337 #else /* CONFIG_FB_AMIGA_OCS */
 
2340 #endif /* CONFIG_FB_AMIGA_OCS */
 
2345          * Calculate the Pixel Clock Values for this Machine
 
2349         u_long tmp = DIVUL(200000000000ULL, amiga_eclock);
 
2351         pixclock[TAG_SHRES] = (tmp + 4) / 8;    /* SHRES:  35 ns / 28 MHz */
 
2352         pixclock[TAG_HIRES] = (tmp + 2) / 4;    /* HIRES:  70 ns / 14 MHz */
 
2353         pixclock[TAG_LORES] = (tmp + 1) / 2;    /* LORES: 140 ns /  7 MHz */
 
2357          * Replace the Tag Values with the Real Pixel Clock Values
 
2360         for (i = 0; i < NUM_TOTAL_MODES; i++) {
 
2361                 struct fb_videomode *mode = &ami_modedb[i];
 
2362                 tag = mode->pixclock;
 
2363                 if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) {
 
2364                         mode->pixclock = pixclock[tag];
 
2369          *  These monitor specs are for a typical Amiga monitor (e.g. A1960)
 
2371         if (fb_info.monspecs.hfmin == 0) {
 
2372             fb_info.monspecs.hfmin = 15000;
 
2373             fb_info.monspecs.hfmax = 38000;
 
2374             fb_info.monspecs.vfmin = 49;
 
2375             fb_info.monspecs.vfmax = 90;
 
2378         fb_info.fbops = &amifb_ops;
 
2379         fb_info.par = ¤tpar;
 
2380         fb_info.flags = FBINFO_DEFAULT;
 
2382         if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb,
 
2383                           NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
 
2388         fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES,
 
2392         chipptr = chipalloc(fb_info.fix.smem_len+
 
2398         assignchunk(videomemory, u_long, chipptr, fb_info.fix.smem_len);
 
2399         assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE);
 
2400         assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE);
 
2401         assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE);
 
2402         assignchunk(copdisplay.list[0][0], copins *, chipptr, COPLISTSIZE);
 
2403         assignchunk(copdisplay.list[0][1], copins *, chipptr, COPLISTSIZE);
 
2404         assignchunk(copdisplay.list[1][0], copins *, chipptr, COPLISTSIZE);
 
2405         assignchunk(copdisplay.list[1][1], copins *, chipptr, COPLISTSIZE);
 
2408          * access the videomem with writethrough cache
 
2410         fb_info.fix.smem_start = (u_long)ZTWO_PADDR(videomemory);
 
2411         videomemory = (u_long)ioremap_writethrough(fb_info.fix.smem_start,
 
2412                                                    fb_info.fix.smem_len);
 
2414                 printk("amifb: WARNING! unable to map videomem cached writethrough\n");
 
2415                 fb_info.screen_base = (char *)ZTWO_VADDR(fb_info.fix.smem_start);
 
2417                 fb_info.screen_base = (char *)videomemory;
 
2419         memset(dummysprite, 0, DUMMYSPRITEMEMSIZE);
 
2422          * Enable Display DMA
 
2425         custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
 
2426                         DMAF_BLITTER | DMAF_SPRITE;
 
2429          * Make sure the Copper has something to do
 
2434         if (request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0,
 
2435                         "fb vertb handler", ¤tpar)) {
 
2440         fb_alloc_cmap(&fb_info.cmap, 1<<fb_info.var.bits_per_pixel, 0);
 
2442         if (register_framebuffer(&fb_info) < 0) {
 
2447         printk("fb%d: %s frame buffer device, using %dK of video memory\n",
 
2448                fb_info.node, fb_info.fix.id, fb_info.fix.smem_len>>10);
 
2457 static void amifb_deinit(void)
 
2459         fb_dealloc_cmap(&fb_info.cmap);
 
2462                 iounmap((void*)videomemory);
 
2463         release_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120);
 
2464         custom.dmacon = DMAF_ALL | DMAF_MASTER;
 
2469          * Blank the display.
 
2472 static int amifb_blank(int blank, struct fb_info *info)
 
2474         do_blank = blank ? blank : -1;
 
2480          * Flash the cursor (called by VBlank interrupt)
 
2483 static int flash_cursor(void)
 
2485         static int cursorcount = 1;
 
2487         if (cursormode == FB_CURSOR_FLASH) {
 
2488                 if (!--cursorcount) {
 
2489                         cursorstate = -cursorstate;
 
2490                         cursorcount = cursorrate;
 
2499          * VBlank Display Interrupt
 
2502 static irqreturn_t amifb_interrupt(int irq, void *dev_id)
 
2504         if (do_vmode_pan || do_vmode_full)
 
2505                 ami_update_display();
 
2512                 ami_rebuild_copper();
 
2513                 do_cursor = do_vmode_pan = 0;
 
2514         } else if (do_cursor) {
 
2528         if (do_vmode_full) {
 
2529                 ami_reinit_copper();
 
2535 /* --------------------------- Hardware routines --------------------------- */
 
2538          * Get the video params out of `var'. If a value doesn't fit, round
 
2539          * it up, if it's too big, return -EINVAL.
 
2542 static int ami_decode_var(struct fb_var_screeninfo *var,
 
2543                           struct amifb_par *par)
 
2545         u_short clk_shift, line_shift;
 
2546         u_long maxfetchstop, fstrt, fsize, fconst, xres_n, yres_n;
 
2547         u_int htotal, vtotal;
 
2550          * Find a matching Pixel Clock
 
2553         for (clk_shift = TAG_SHRES; clk_shift <= TAG_LORES; clk_shift++)
 
2554                 if (var->pixclock <= pixclock[clk_shift])
 
2556         if (clk_shift > TAG_LORES) {
 
2557                 DPRINTK("pixclock too high\n");
 
2560         par->clk_shift = clk_shift;
 
2563          * Check the Geometry Values
 
2566         if ((par->xres = var->xres) < 64)
 
2568         if ((par->yres = var->yres) < 64)
 
2570         if ((par->vxres = var->xres_virtual) < par->xres)
 
2571                 par->vxres = par->xres;
 
2572         if ((par->vyres = var->yres_virtual) < par->yres)
 
2573                 par->vyres = par->yres;
 
2575         par->bpp = var->bits_per_pixel;
 
2579                 if (par->bpp > maxdepth[clk_shift]) {
 
2580                         if (round_down_bpp && maxdepth[clk_shift])
 
2581                                 par->bpp = maxdepth[clk_shift];
 
2583                                 DPRINTK("invalid bpp\n");
 
2587         } else if (var->nonstd == FB_NONSTD_HAM) {
 
2590                 if (par->bpp != 6) {
 
2593                         if (par->bpp != 8 || !IS_AGA) {
 
2594                                 DPRINTK("invalid bpp for ham mode\n");
 
2599                 DPRINTK("unknown nonstd mode\n");
 
2604          * FB_VMODE_SMOOTH_XPAN will be cleared, if one of the folloing
 
2605          * checks failed and smooth scrolling is not possible
 
2608         par->vmode = var->vmode | FB_VMODE_SMOOTH_XPAN;
 
2609         switch (par->vmode & FB_VMODE_MASK) {
 
2610                 case FB_VMODE_INTERLACED:
 
2613                 case FB_VMODE_NONINTERLACED:
 
2616                 case FB_VMODE_DOUBLE:
 
2618                                 DPRINTK("double mode only possible with aga\n");
 
2624                         DPRINTK("unknown video mode\n");
 
2628         par->line_shift = line_shift;
 
2631          * Vertical and Horizontal Timings
 
2634         xres_n = par->xres<<clk_shift;
 
2635         yres_n = par->yres<<line_shift;
 
2636         par->htotal = down8((var->left_margin+par->xres+var->right_margin+var->hsync_len)<<clk_shift);
 
2637         par->vtotal = down2(((var->upper_margin+par->yres+var->lower_margin+var->vsync_len)<<line_shift)+1);
 
2640                 par->bplcon3 = sprpixmode[clk_shift];
 
2643         if (var->sync & FB_SYNC_BROADCAST) {
 
2644                 par->diwstop_h = par->htotal-((var->right_margin-var->hsync_len)<<clk_shift);
 
2646                         par->diwstop_h += mod4(var->hsync_len);
 
2648                         par->diwstop_h = down4(par->diwstop_h);
 
2650                 par->diwstrt_h = par->diwstop_h - xres_n;
 
2651                 par->diwstop_v = par->vtotal-((var->lower_margin-var->vsync_len)<<line_shift);
 
2652                 par->diwstrt_v = par->diwstop_v - yres_n;
 
2653                 if (par->diwstop_h >= par->htotal+8) {
 
2654                         DPRINTK("invalid diwstop_h\n");
 
2657                 if (par->diwstop_v > par->vtotal) {
 
2658                         DPRINTK("invalid diwstop_v\n");
 
2663                         /* Initialize sync with some reasonable values for pwrsave */
 
2674                 if (par->vtotal > (PAL_VTOTAL+NTSC_VTOTAL)/2) {
 
2675                         /* PAL video mode */
 
2676                         if (par->htotal != PAL_HTOTAL) {
 
2677                                 DPRINTK("htotal invalid for pal\n");
 
2680                         if (par->diwstrt_h < PAL_DIWSTRT_H) {
 
2681                                 DPRINTK("diwstrt_h too low for pal\n");
 
2684                         if (par->diwstrt_v < PAL_DIWSTRT_V) {
 
2685                                 DPRINTK("diwstrt_v too low for pal\n");
 
2688                         htotal = PAL_HTOTAL>>clk_shift;
 
2689                         vtotal = PAL_VTOTAL>>1;
 
2691                                 par->beamcon0 = BMC0_PAL;
 
2692                                 par->bplcon3 |= BPC3_BRDRBLNK;
 
2693                         } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
 
2694                                    AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
 
2695                                 par->beamcon0 = BMC0_PAL;
 
2697                         } else if (amiga_vblank != 50) {
 
2698                                 DPRINTK("pal not supported by this chipset\n");
 
2703                          * In the AGA chipset seems to be hardware bug with BPC3_BRDRBLNK
 
2704                          * and NTSC activated, so than better let diwstop_h <= 1812
 
2706                         if (par->htotal != NTSC_HTOTAL) {
 
2707                                 DPRINTK("htotal invalid for ntsc\n");
 
2710                         if (par->diwstrt_h < NTSC_DIWSTRT_H) {
 
2711                                 DPRINTK("diwstrt_h too low for ntsc\n");
 
2714                         if (par->diwstrt_v < NTSC_DIWSTRT_V) {
 
2715                                 DPRINTK("diwstrt_v too low for ntsc\n");
 
2718                         htotal = NTSC_HTOTAL>>clk_shift;
 
2719                         vtotal = NTSC_VTOTAL>>1;
 
2722                                 par->bplcon3 |= BPC3_BRDRBLNK;
 
2723                         } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
 
2724                                    AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
 
2727                         } else if (amiga_vblank != 60) {
 
2728                                 DPRINTK("ntsc not supported by this chipset\n");
 
2733                         if (par->diwstrt_h >= 1024 || par->diwstop_h < 1024 ||
 
2734                             par->diwstrt_v >=  512 || par->diwstop_v <  256) {
 
2735                                 DPRINTK("invalid position for display on ocs\n");
 
2739         } else if (!IS_OCS) {
 
2740                 /* Programmable video mode */
 
2741                 par->hsstrt = var->right_margin<<clk_shift;
 
2742                 par->hsstop = (var->right_margin+var->hsync_len)<<clk_shift;
 
2743                 par->diwstop_h = par->htotal - mod8(par->hsstrt) + 8 - (1 << clk_shift);
 
2745                         par->diwstop_h = down4(par->diwstop_h) - 16;
 
2746                 par->diwstrt_h = par->diwstop_h - xres_n;
 
2747                 par->hbstop = par->diwstrt_h + 4;
 
2748                 par->hbstrt = par->diwstop_h + 4;
 
2749                 if (par->hbstrt >= par->htotal + 8)
 
2750                         par->hbstrt -= par->htotal;
 
2751                 par->hcenter = par->hsstrt + (par->htotal >> 1);
 
2752                 par->vsstrt = var->lower_margin<<line_shift;
 
2753                 par->vsstop = (var->lower_margin+var->vsync_len)<<line_shift;
 
2754                 par->diwstop_v = par->vtotal;
 
2755                 if ((par->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
 
2756                         par->diwstop_v -= 2;
 
2757                 par->diwstrt_v = par->diwstop_v - yres_n;
 
2758                 par->vbstop = par->diwstrt_v - 2;
 
2759                 par->vbstrt = par->diwstop_v - 2;
 
2760                 if (par->vtotal > 2048) {
 
2761                         DPRINTK("vtotal too high\n");
 
2764                 if (par->htotal > 2048) {
 
2765                         DPRINTK("htotal too high\n");
 
2768                 par->bplcon3 |= BPC3_EXTBLKEN;
 
2769                 par->beamcon0 = BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS |
 
2770                                 BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN |
 
2771                                 BMC0_PAL | BMC0_VARCSYEN;
 
2772                 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
 
2773                         par->beamcon0 |= BMC0_HSYTRUE;
 
2774                 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
 
2775                         par->beamcon0 |= BMC0_VSYTRUE;
 
2776                 if (var->sync & FB_SYNC_COMP_HIGH_ACT)
 
2777                         par->beamcon0 |= BMC0_CSYTRUE;
 
2778                 htotal = par->htotal>>clk_shift;
 
2779                 vtotal = par->vtotal>>1;
 
2781                 DPRINTK("only broadcast modes possible for ocs\n");
 
2786          * Checking the DMA timing
 
2789         fconst = 16<<maxfmode<<clk_shift;
 
2792          * smallest window start value without turn off other dma cycles
 
2793          * than sprite1-7, unless you change min_fstrt
 
2797         fsize = ((maxfmode+clk_shift <= 1) ? fconst : 64);
 
2798         fstrt = downx(fconst, par->diwstrt_h-4) - fsize;
 
2799         if (fstrt < min_fstrt) {
 
2800                 DPRINTK("fetch start too low\n");
 
2805          * smallest window start value where smooth scrolling is possible
 
2808         fstrt = downx(fconst, par->diwstrt_h-fconst+(1<<clk_shift)-4) - fsize;
 
2809         if (fstrt < min_fstrt)
 
2810                 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
 
2812         maxfetchstop = down16(par->htotal - 80);
 
2814         fstrt = downx(fconst, par->diwstrt_h-4) - 64 - fconst;
 
2815         fsize = upx(fconst, xres_n + modx(fconst, downx(1<<clk_shift, par->diwstrt_h-4)));
 
2816         if (fstrt + fsize > maxfetchstop)
 
2817                 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
 
2819         fsize = upx(fconst, xres_n);
 
2820         if (fstrt + fsize > maxfetchstop) {
 
2821                 DPRINTK("fetch stop too high\n");
 
2825         if (maxfmode + clk_shift <= 1) {
 
2826                 fsize = up64(xres_n + fconst - 1);
 
2827                 if (min_fstrt + fsize - 64 > maxfetchstop)
 
2828                         par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
 
2830                 fsize = up64(xres_n);
 
2831                 if (min_fstrt + fsize - 64 > maxfetchstop) {
 
2832                         DPRINTK("fetch size too high\n");
 
2841          * Check if there is enough time to update the bitplane pointers for ywrap
 
2844         if (par->htotal-fsize-64 < par->bpp*64)
 
2845                 par->vmode &= ~FB_VMODE_YWRAP;
 
2848          * Bitplane calculations and check the Memory Requirements
 
2852                 par->next_plane = div8(upx(16<<maxfmode, par->vxres));
 
2853                 par->next_line = par->bpp*par->next_plane;
 
2854                 if (par->next_line * par->vyres > fb_info.fix.smem_len) {
 
2855                         DPRINTK("too few video mem\n");
 
2859                 par->next_line = div8(upx(16<<maxfmode, par->vxres));
 
2860                 par->next_plane = par->vyres*par->next_line;
 
2861                 if (par->next_plane * par->bpp > fb_info.fix.smem_len) {
 
2862                         DPRINTK("too few video mem\n");
 
2868          * Hardware Register Values
 
2871         par->bplcon0 = BPC0_COLOR | bplpixmode[clk_shift];
 
2873                 par->bplcon0 |= BPC0_ECSENA;
 
2875                 par->bplcon0 |= BPC0_BPU3;
 
2877                 par->bplcon0 |= par->bpp<<12;
 
2878         if (var->nonstd == FB_NONSTD_HAM)
 
2879                 par->bplcon0 |= BPC0_HAM;
 
2880         if (var->sync & FB_SYNC_EXT)
 
2881                 par->bplcon0 |= BPC0_ERSY;
 
2884                 par->fmode = bplfetchmode[maxfmode];
 
2886         switch (par->vmode & FB_VMODE_MASK) {
 
2887                 case FB_VMODE_INTERLACED:
 
2888                         par->bplcon0 |= BPC0_LACE;
 
2890                 case FB_VMODE_DOUBLE:
 
2892                                 par->fmode |= FMODE_SSCAN2 | FMODE_BSCAN2;
 
2896         if (!((par->vmode ^ var->vmode) & FB_VMODE_YWRAP)) {
 
2897                 par->xoffset = var->xoffset;
 
2898                 par->yoffset = var->yoffset;
 
2899                 if (par->vmode & FB_VMODE_YWRAP) {
 
2900                         if (par->xoffset || par->yoffset < 0 || par->yoffset >= par->vyres)
 
2901                                 par->xoffset = par->yoffset = 0;
 
2903                         if (par->xoffset < 0 || par->xoffset > upx(16<<maxfmode, par->vxres-par->xres) ||
 
2904                             par->yoffset < 0 || par->yoffset > par->vyres-par->yres)
 
2905                                 par->xoffset = par->yoffset = 0;
 
2908                 par->xoffset = par->yoffset = 0;
 
2910         par->crsr.crsr_x = par->crsr.crsr_y = 0;
 
2911         par->crsr.spot_x = par->crsr.spot_y = 0;
 
2912         par->crsr.height = par->crsr.width = 0;
 
2918          * Fill the `var' structure based on the values in `par' and maybe
 
2919          * other values read out of the hardware.
 
2922 static int ami_encode_var(struct fb_var_screeninfo *var,
 
2923                           struct amifb_par *par)
 
2925         u_short clk_shift, line_shift;
 
2927         memset(var, 0, sizeof(struct fb_var_screeninfo));
 
2929         clk_shift = par->clk_shift;
 
2930         line_shift = par->line_shift;
 
2932         var->xres = par->xres;
 
2933         var->yres = par->yres;
 
2934         var->xres_virtual = par->vxres;
 
2935         var->yres_virtual = par->vyres;
 
2936         var->xoffset = par->xoffset;
 
2937         var->yoffset = par->yoffset;
 
2939         var->bits_per_pixel = par->bpp;
 
2942         var->red.offset = 0;
 
2943         var->red.msb_right = 0;
 
2944         var->red.length = par->bpp;
 
2945         if (par->bplcon0 & BPC0_HAM)
 
2946             var->red.length -= 2;
 
2947         var->blue = var->green = var->red;
 
2948         var->transp.offset = 0;
 
2949         var->transp.length = 0;
 
2950         var->transp.msb_right = 0;
 
2952         if (par->bplcon0 & BPC0_HAM)
 
2953                 var->nonstd = FB_NONSTD_HAM;
 
2961         var->pixclock = pixclock[clk_shift];
 
2963         if (IS_AGA && par->fmode & FMODE_BSCAN2)
 
2964                 var->vmode = FB_VMODE_DOUBLE;
 
2965         else if (par->bplcon0 & BPC0_LACE)
 
2966                 var->vmode = FB_VMODE_INTERLACED;
 
2968                 var->vmode = FB_VMODE_NONINTERLACED;
 
2970         if (!IS_OCS && par->beamcon0 & BMC0_VARBEAMEN) {
 
2971                 var->hsync_len = (par->hsstop-par->hsstrt)>>clk_shift;
 
2972                 var->right_margin = par->hsstrt>>clk_shift;
 
2973                 var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
 
2974                 var->vsync_len = (par->vsstop-par->vsstrt)>>line_shift;
 
2975                 var->lower_margin = par->vsstrt>>line_shift;
 
2976                 var->upper_margin = (par->vtotal>>line_shift) - var->yres - var->lower_margin - var->vsync_len;
 
2978                 if (par->beamcon0 & BMC0_HSYTRUE)
 
2979                         var->sync |= FB_SYNC_HOR_HIGH_ACT;
 
2980                 if (par->beamcon0 & BMC0_VSYTRUE)
 
2981                         var->sync |= FB_SYNC_VERT_HIGH_ACT;
 
2982                 if (par->beamcon0 & BMC0_CSYTRUE)
 
2983                         var->sync |= FB_SYNC_COMP_HIGH_ACT;
 
2985                 var->sync = FB_SYNC_BROADCAST;
 
2986                 var->hsync_len = (152>>clk_shift) + mod4(par->diwstop_h);
 
2987                 var->right_margin = ((par->htotal - down4(par->diwstop_h))>>clk_shift) + var->hsync_len;
 
2988                 var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
 
2989                 var->vsync_len = 4>>line_shift;
 
2990                 var->lower_margin = ((par->vtotal - par->diwstop_v)>>line_shift) + var->vsync_len;
 
2991                 var->upper_margin = (((par->vtotal - 2)>>line_shift) + 1) - var->yres -
 
2992                                     var->lower_margin - var->vsync_len;
 
2995         if (par->bplcon0 & BPC0_ERSY)
 
2996                 var->sync |= FB_SYNC_EXT;
 
2997         if (par->vmode & FB_VMODE_YWRAP)
 
2998                 var->vmode |= FB_VMODE_YWRAP;
 
3005          * Pan or Wrap the Display
 
3007          * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
 
3011 static void ami_pan_var(struct fb_var_screeninfo *var)
 
3013         struct amifb_par *par = ¤tpar;
 
3015         par->xoffset = var->xoffset;
 
3016         par->yoffset = var->yoffset;
 
3017         if (var->vmode & FB_VMODE_YWRAP)
 
3018                 par->vmode |= FB_VMODE_YWRAP;
 
3020                 par->vmode &= ~FB_VMODE_YWRAP;
 
3031 static int ami_update_par(void)
 
3033         struct amifb_par *par = ¤tpar;
 
3034         short clk_shift, vshift, fstrt, fsize, fstop, fconst,  shift, move, mod;
 
3036         clk_shift = par->clk_shift;
 
3038         if (!(par->vmode & FB_VMODE_SMOOTH_XPAN))
 
3039                 par->xoffset = upx(16<<maxfmode, par->xoffset);
 
3041         fconst = 16<<maxfmode<<clk_shift;
 
3042         vshift = modx(16<<maxfmode, par->xoffset);
 
3043         fstrt = par->diwstrt_h - (vshift<<clk_shift) - 4;
 
3044         fsize = (par->xres+vshift)<<clk_shift;
 
3045         shift = modx(fconst, fstrt);
 
3046         move = downx(2<<maxfmode, div8(par->xoffset));
 
3047         if (maxfmode + clk_shift > 1) {
 
3048                 fstrt = downx(fconst, fstrt) - 64;
 
3049                 fsize = upx(fconst, fsize);
 
3050                 fstop = fstrt + fsize - fconst;
 
3052                 mod = fstrt = downx(fconst, fstrt) - fconst;
 
3053                 fstop = fstrt + upx(fconst, fsize) - 64;
 
3054                 fsize = up64(fsize);
 
3055                 fstrt = fstop - fsize + 64;
 
3056                 if (fstrt < min_fstrt) {
 
3057                         fstop += min_fstrt - fstrt;
 
3060                 move = move - div8((mod-fstrt)>>clk_shift);
 
3062         mod = par->next_line - div8(fsize>>clk_shift);
 
3063         par->ddfstrt = fstrt;
 
3064         par->ddfstop = fstop;
 
3065         par->bplcon1 = hscroll2hw(shift);
 
3067         if (par->bplcon0 & BPC0_LACE)
 
3068                 par->bpl2mod += par->next_line;
 
3069         if (IS_AGA && (par->fmode & FMODE_BSCAN2))
 
3070                 par->bpl1mod = -div8(fsize>>clk_shift);
 
3072                 par->bpl1mod = par->bpl2mod;
 
3075                 par->bplpt0 = fb_info.fix.smem_start + par->next_line*par->yoffset + move;
 
3076                 if (par->vmode & FB_VMODE_YWRAP) {
 
3077                         if (par->yoffset > par->vyres-par->yres) {
 
3078                                 par->bplpt0wrap = fb_info.fix.smem_start + move;
 
3079                                 if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v+par->vyres-par->yoffset))
 
3080                                         par->bplpt0wrap += par->next_line;
 
3084                 par->bplpt0 = fb_info.fix.smem_start + move;
 
3086         if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v))
 
3087                 par->bplpt0 += par->next_line;
 
3094          * Set a single color register. The values supplied are already
 
3095          * rounded down to the hardware's capabilities (according to the
 
3096          * entries in the var structure). Return != 0 for invalid regno.
 
3099 static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 
3100                            u_int transp, struct fb_info *info)
 
3105         } else if (currentpar.bplcon0 & BPC0_SHRES) {
 
3122          * Update the corresponding Hardware Color Register, unless it's Color
 
3123          * Register 0 and the screen is blanked.
 
3125          * VBlank is switched off to protect bplcon3 or ecs_palette[] from
 
3126          * being changed by ami_do_blank() during the VBlank.
 
3129         if (regno || !is_blanked) {
 
3130 #if defined(CONFIG_FB_AMIGA_AGA)
 
3132                         u_short bplcon3 = currentpar.bplcon3;
 
3134                         custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000);
 
3135                         custom.color[regno&31] = rgb2hw8_high(red, green, blue);
 
3136                         custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000) | BPC3_LOCT;
 
3137                         custom.color[regno&31] = rgb2hw8_low(red, green, blue);
 
3138                         custom.bplcon3 = bplcon3;
 
3142 #if defined(CONFIG_FB_AMIGA_ECS)
 
3143                 if (currentpar.bplcon0 & BPC0_SHRES) {
 
3144                         u_short color, mask;
 
3148                         color = rgb2hw2(red, green, blue);
 
3150                         for (i = regno+12; i >= (int)regno; i -= 4)
 
3151                                 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
 
3152                         mask <<=2; color >>= 2;
 
3153                         regno = down16(regno)+mul4(mod4(regno));
 
3154                         for (i = regno+3; i >= (int)regno; i--)
 
3155                                 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
 
3159                         custom.color[regno] = rgb2hw4(red, green, blue);
 
3164 static void ami_update_display(void)
 
3166         struct amifb_par *par = ¤tpar;
 
3168         custom.bplcon1 = par->bplcon1;
 
3169         custom.bpl1mod = par->bpl1mod;
 
3170         custom.bpl2mod = par->bpl2mod;
 
3171         custom.ddfstrt = ddfstrt2hw(par->ddfstrt);
 
3172         custom.ddfstop = ddfstop2hw(par->ddfstop);
 
3176          * Change the video mode (called by VBlank interrupt)
 
3179 static void ami_init_display(void)
 
3181         struct amifb_par *par = ¤tpar;
 
3184         custom.bplcon0 = par->bplcon0 & ~BPC0_LACE;
 
3185         custom.bplcon2 = (IS_OCS ? 0 : BPC2_KILLEHB) | BPC2_PF2P2 | BPC2_PF1P2;
 
3187                 custom.bplcon3 = par->bplcon3;
 
3189                         custom.bplcon4 = BPC4_ESPRM4 | BPC4_OSPRM4;
 
3190                 if (par->beamcon0 & BMC0_VARBEAMEN) {
 
3191                         custom.htotal = htotal2hw(par->htotal);
 
3192                         custom.hbstrt = hbstrt2hw(par->hbstrt);
 
3193                         custom.hbstop = hbstop2hw(par->hbstop);
 
3194                         custom.hsstrt = hsstrt2hw(par->hsstrt);
 
3195                         custom.hsstop = hsstop2hw(par->hsstop);
 
3196                         custom.hcenter = hcenter2hw(par->hcenter);
 
3197                         custom.vtotal = vtotal2hw(par->vtotal);
 
3198                         custom.vbstrt = vbstrt2hw(par->vbstrt);
 
3199                         custom.vbstop = vbstop2hw(par->vbstop);
 
3200                         custom.vsstrt = vsstrt2hw(par->vsstrt);
 
3201                         custom.vsstop = vsstop2hw(par->vsstop);
 
3204         if (!IS_OCS || par->hsstop)
 
3205                 custom.beamcon0 = par->beamcon0;
 
3207                 custom.fmode = par->fmode;
 
3210          * The minimum period for audio depends on htotal
 
3213         amiga_audio_min_period = div16(par->htotal);
 
3215         is_lace = par->bplcon0 & BPC0_LACE ? 1 : 0;
 
3218                 i = custom.vposr >> 15;
 
3220                 custom.vposw = custom.vposr | 0x8000;
 
3225         custom.vposw = custom.vposr | 0x8000;
 
3227         custom.cop2lc = (u_short *)ZTWO_PADDR(copdisplay.list[currentcop][i]);
 
3231          * (Un)Blank the screen (called by VBlank interrupt)
 
3234 static void ami_do_blank(void)
 
3236         struct amifb_par *par = ¤tpar;
 
3237 #if defined(CONFIG_FB_AMIGA_AGA)
 
3238         u_short bplcon3 = par->bplcon3;
 
3240         u_char red, green, blue;
 
3243                 custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
 
3244                 red = green = blue = 0;
 
3245                 if (!IS_OCS && do_blank > 1) {
 
3247                                 case FB_BLANK_VSYNC_SUSPEND:
 
3248                                         custom.hsstrt = hsstrt2hw(par->hsstrt);
 
3249                                         custom.hsstop = hsstop2hw(par->hsstop);
 
3250                                         custom.vsstrt = vsstrt2hw(par->vtotal+4);
 
3251                                         custom.vsstop = vsstop2hw(par->vtotal+4);
 
3253                                 case FB_BLANK_HSYNC_SUSPEND:
 
3254                                         custom.hsstrt = hsstrt2hw(par->htotal+16);
 
3255                                         custom.hsstop = hsstop2hw(par->htotal+16);
 
3256                                         custom.vsstrt = vsstrt2hw(par->vsstrt);
 
3257                                         custom.vsstop = vsstrt2hw(par->vsstop);
 
3259                                 case FB_BLANK_POWERDOWN:
 
3260                                         custom.hsstrt = hsstrt2hw(par->htotal+16);
 
3261                                         custom.hsstop = hsstop2hw(par->htotal+16);
 
3262                                         custom.vsstrt = vsstrt2hw(par->vtotal+4);
 
3263                                         custom.vsstop = vsstop2hw(par->vtotal+4);
 
3266                         if (!(par->beamcon0 & BMC0_VARBEAMEN)) {
 
3267                                 custom.htotal = htotal2hw(par->htotal);
 
3268                                 custom.vtotal = vtotal2hw(par->vtotal);
 
3269                                 custom.beamcon0 = BMC0_HARDDIS | BMC0_VARBEAMEN |
 
3270                                                   BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARCSYEN;
 
3274                 custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_SPRITE;
 
3279                         custom.hsstrt = hsstrt2hw(par->hsstrt);
 
3280                         custom.hsstop = hsstop2hw(par->hsstop);
 
3281                         custom.vsstrt = vsstrt2hw(par->vsstrt);
 
3282                         custom.vsstop = vsstop2hw(par->vsstop);
 
3283                         custom.beamcon0 = par->beamcon0;
 
3286 #if defined(CONFIG_FB_AMIGA_AGA)
 
3288                 custom.bplcon3 = bplcon3;
 
3289                 custom.color[0] = rgb2hw8_high(red, green, blue);
 
3290                 custom.bplcon3 = bplcon3 | BPC3_LOCT;
 
3291                 custom.color[0] = rgb2hw8_low(red, green, blue);
 
3292                 custom.bplcon3 = bplcon3;
 
3295 #if defined(CONFIG_FB_AMIGA_ECS)
 
3296         if (par->bplcon0 & BPC0_SHRES) {
 
3297                 u_short color, mask;
 
3301                 color = rgb2hw2(red, green, blue);
 
3302                 for (i = 12; i >= 0; i -= 4)
 
3303                         custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
 
3304                 mask <<=2; color >>= 2;
 
3305                 for (i = 3; i >= 0; i--)
 
3306                         custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
 
3309                 custom.color[0] = rgb2hw4(red, green, blue);
 
3310         is_blanked = do_blank > 0 ? do_blank : 0;
 
3313 static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix)
 
3315         struct amifb_par *par = ¤tpar;
 
3317         fix->crsr_width = fix->crsr_xsize = par->crsr.width;
 
3318         fix->crsr_height = fix->crsr_ysize = par->crsr.height;
 
3319         fix->crsr_color1 = 17;
 
3320         fix->crsr_color2 = 18;
 
3324 static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data)
 
3326         struct amifb_par *par = ¤tpar;
 
3327         register u_short *lspr, *sspr;
 
3329         register u_long datawords asm ("d2");
 
3331         register u_long datawords;
 
3333         register short delta;
 
3334         register u_char color;
 
3335         short height, width, bits, words;
 
3338         size = par->crsr.height*par->crsr.width;
 
3339         alloc = var->height*var->width;
 
3340         var->height = par->crsr.height;
 
3341         var->width = par->crsr.width;
 
3342         var->xspot = par->crsr.spot_x;
 
3343         var->yspot = par->crsr.spot_y;
 
3344         if (size > var->height*var->width)
 
3345                 return -ENAMETOOLONG;
 
3346         if (!access_ok(VERIFY_WRITE, data, size))
 
3348         delta = 1<<par->crsr.fmode;
 
3349         lspr = lofsprite + (delta<<1);
 
3350         if (par->bplcon0 & BPC0_LACE)
 
3351                 sspr = shfsprite + (delta<<1);
 
3354         for (height = (short)var->height-1; height >= 0; height--) {
 
3355                 bits = 0; words = delta; datawords = 0;
 
3356                 for (width = (short)var->width-1; width >= 0; width--) {
 
3360                                 asm volatile ("movew %1@(%3:w:2),%0 ; swap %0 ; movew %1@+,%0"
 
3361                                         : "=d" (datawords), "=a" (lspr) : "1" (lspr), "d" (delta));
 
3363                                 datawords = (*(lspr+delta) << 16) | (*lspr++);
 
3369                                 "clrb %0 ; swap %1 ; lslw #1,%1 ; roxlb #1,%0 ; "
 
3370                                 "swap %1 ; lslw #1,%1 ; roxlb #1,%0"
 
3371                                 : "=d" (color), "=d" (datawords) : "1" (datawords));
 
3373                         color = (((datawords >> 30) & 2)
 
3374                                  | ((datawords >> 15) & 1));
 
3377                         put_user(color, data++);
 
3382                 while (--words >= 0)
 
3385                 asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
 
3386                         : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
 
3390                         u_short *tmp = lspr;
 
3399 static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data)
 
3401         struct amifb_par *par = ¤tpar;
 
3402         register u_short *lspr, *sspr;
 
3404         register u_long datawords asm ("d2");
 
3406         register u_long datawords;
 
3408         register short delta;
 
3410         short height, width, bits, words;
 
3414         else if (var->width <= 16)
 
3415                 fmode = TAG_FMODE_1;
 
3416         else if (var->width <= 32)
 
3417                 fmode = TAG_FMODE_2;
 
3418         else if (var->width <= 64)
 
3419                 fmode = TAG_FMODE_4;
 
3422         if (fmode > maxfmode)
 
3426         if (!access_ok(VERIFY_READ, data, var->width*var->height))
 
3429         lofsprite = shfsprite = (u_short *)spritememory;
 
3430         lspr = lofsprite + (delta<<1);
 
3431         if (par->bplcon0 & BPC0_LACE) {
 
3432                 if (((var->height+4)<<fmode<<2) > SPRITEMEMSIZE)
 
3434                 memset(lspr, 0, (var->height+4)<<fmode<<2);
 
3435                 shfsprite += ((var->height+5)&-2)<<fmode;
 
3436                 sspr = shfsprite + (delta<<1);
 
3438                 if (((var->height+2)<<fmode<<2) > SPRITEMEMSIZE)
 
3440                 memset(lspr, 0, (var->height+2)<<fmode<<2);
 
3443         for (height = (short)var->height-1; height >= 0; height--) {
 
3444                 bits = 16; words = delta; datawords = 0;
 
3445                 for (width = (short)var->width-1; width >= 0; width--) {
 
3446                         unsigned long tdata = 0;
 
3447                         get_user(tdata, data);
 
3451                                 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0 ; "
 
3452                                 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0"
 
3454                                 : "0" (datawords), "d" (tdata));
 
3456                         datawords = ((datawords << 1) & 0xfffefffe);
 
3457                         datawords |= tdata & 1;
 
3458                         datawords |= (tdata & 2) << (16-1);
 
3463                                 asm volatile ("swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+"
 
3464                                         : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta));
 
3466                                 *(lspr+delta) = (u_short) (datawords >> 16);
 
3467                                 *lspr++ = (u_short) (datawords & 0xffff);
 
3475                                 "swap %2 ; lslw %4,%2 ; movew %2,%0@(%3:w:2) ; "
 
3476                                 "swap %2 ; lslw %4,%2 ; movew %2,%0@+"
 
3477                                 : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta), "d" (bits));
 
3479                         *(lspr+delta) = (u_short) (datawords >> (16+bits));
 
3480                         *lspr++ = (u_short) ((datawords & 0x0000ffff) >> bits);
 
3483                 while (--words >= 0) {
 
3485                         asm volatile ("moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+"
 
3486                                 : "=a" (lspr) : "0" (lspr), "d" (delta) : "d0");
 
3493                 asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
 
3494                         : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
 
3498                         u_short *tmp = lspr;
 
3504         par->crsr.height = var->height;
 
3505         par->crsr.width = var->width;
 
3506         par->crsr.spot_x = var->xspot;
 
3507         par->crsr.spot_y = var->yspot;
 
3508         par->crsr.fmode = fmode;
 
3510                 par->fmode &= ~(FMODE_SPAGEM | FMODE_SPR32);
 
3511                 par->fmode |= sprfetchmode[fmode];
 
3512                 custom.fmode = par->fmode;
 
3517 static int ami_get_cursorstate(struct fb_cursorstate *state)
 
3519         struct amifb_par *par = ¤tpar;
 
3521         state->xoffset = par->crsr.crsr_x;
 
3522         state->yoffset = par->crsr.crsr_y;
 
3523         state->mode = cursormode;
 
3527 static int ami_set_cursorstate(struct fb_cursorstate *state)
 
3529         struct amifb_par *par = ¤tpar;
 
3531         par->crsr.crsr_x = state->xoffset;
 
3532         par->crsr.crsr_y = state->yoffset;
 
3533         if ((cursormode = state->mode) == FB_CURSOR_OFF)
 
3539 static void ami_set_sprite(void)
 
3541         struct amifb_par *par = ¤tpar;
 
3542         copins *copl, *cops;
 
3547         cops = copdisplay.list[currentcop][0];
 
3548         copl = copdisplay.list[currentcop][1];
 
3549         ps = pl = ZTWO_PADDR(dummysprite);
 
3550         mx = par->crsr.crsr_x-par->crsr.spot_x;
 
3551         my = par->crsr.crsr_y-par->crsr.spot_y;
 
3552         if (!(par->vmode & FB_VMODE_YWRAP)) {
 
3556         if (!is_blanked && cursorstate > 0 && par->crsr.height > 0 &&
 
3557             mx > -(short)par->crsr.width && mx < par->xres &&
 
3558             my > -(short)par->crsr.height && my < par->yres) {
 
3559                 pl = ZTWO_PADDR(lofsprite);
 
3560                 hs = par->diwstrt_h + (mx<<par->clk_shift) - 4;
 
3561                 vs = par->diwstrt_v + (my<<par->line_shift);
 
3562                 ve = vs + (par->crsr.height<<par->line_shift);
 
3563                 if (par->bplcon0 & BPC0_LACE) {
 
3564                         ps = ZTWO_PADDR(shfsprite);
 
3565                         lofsprite[0] = spr2hw_pos(vs, hs);
 
3566                         shfsprite[0] = spr2hw_pos(vs+1, hs);
 
3568                                 lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
 
3569                                 shfsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs+1, hs, ve+1);
 
3570                                 pt = pl; pl = ps; ps = pt;
 
3572                                 lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve+1);
 
3573                                 shfsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs+1, hs, ve);
 
3576                         lofsprite[0] = spr2hw_pos(vs, hs) | (IS_AGA && (par->fmode & FMODE_BSCAN2) ? 0x80 : 0);
 
3577                         lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
 
3580         copl[cop_spr0ptrh].w[1] = highw(pl);
 
3581         copl[cop_spr0ptrl].w[1] = loww(pl);
 
3582         if (par->bplcon0 & BPC0_LACE) {
 
3583                 cops[cop_spr0ptrh].w[1] = highw(ps);
 
3584                 cops[cop_spr0ptrl].w[1] = loww(ps);
 
3590          * Initialise the Copper Initialisation List
 
3593 static void __init ami_init_copper(void)
 
3595         copins *cop = copdisplay.init;
 
3600                 (cop++)->l = CMOVE(BPC0_COLOR | BPC0_SHRES | BPC0_ECSENA, bplcon0);
 
3601                 (cop++)->l = CMOVE(0x0181, diwstrt);
 
3602                 (cop++)->l = CMOVE(0x0281, diwstop);
 
3603                 (cop++)->l = CMOVE(0x0000, diwhigh);
 
3605                 (cop++)->l = CMOVE(BPC0_COLOR, bplcon0);
 
3606         p = ZTWO_PADDR(dummysprite);
 
3607         for (i = 0; i < 8; i++) {
 
3608                 (cop++)->l = CMOVE(0, spr[i].pos);
 
3609                 (cop++)->l = CMOVE(highw(p), sprpt[i]);
 
3610                 (cop++)->l = CMOVE2(loww(p), sprpt[i]);
 
3613         (cop++)->l = CMOVE(IF_SETCLR | IF_COPER, intreq);
 
3614         copdisplay.wait = cop;
 
3616         (cop++)->l = CMOVE(0, copjmp2);
 
3619         custom.cop1lc = (u_short *)ZTWO_PADDR(copdisplay.init);
 
3623 static void ami_reinit_copper(void)
 
3625         struct amifb_par *par = ¤tpar;
 
3627         copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0;
 
3628         copdisplay.wait->l = CWAIT(32, par->diwstrt_v-4);
 
3632          * Build the Copper List
 
3635 static void ami_build_copper(void)
 
3637         struct amifb_par *par = ¤tpar;
 
3638         copins *copl, *cops;
 
3641         currentcop = 1 - currentcop;
 
3643         copl = copdisplay.list[currentcop][1];
 
3645         (copl++)->l = CWAIT(0, 10);
 
3646         (copl++)->l = CMOVE(par->bplcon0, bplcon0);
 
3647         (copl++)->l = CMOVE(0, sprpt[0]);
 
3648         (copl++)->l = CMOVE2(0, sprpt[0]);
 
3650         if (par->bplcon0 & BPC0_LACE) {
 
3651                 cops = copdisplay.list[currentcop][0];
 
3653                 (cops++)->l = CWAIT(0, 10);
 
3654                 (cops++)->l = CMOVE(par->bplcon0, bplcon0);
 
3655                 (cops++)->l = CMOVE(0, sprpt[0]);
 
3656                 (cops++)->l = CMOVE2(0, sprpt[0]);
 
3658                 (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v+1), diwstrt);
 
3659                 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v+1), diwstop);
 
3660                 (cops++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
 
3661                 (cops++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
 
3663                         (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v+1,
 
3664                                             par->diwstop_h, par->diwstop_v+1), diwhigh);
 
3665                         (cops++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
 
3666                                             par->diwstop_h, par->diwstop_v), diwhigh);
 
3668                         if (par->beamcon0 & BMC0_VARBEAMEN) {
 
3669                                 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
 
3670                                 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt+1), vbstrt);
 
3671                                 (copl++)->l = CMOVE(vbstop2hw(par->vbstop+1), vbstop);
 
3672                                 (cops++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
 
3673                                 (cops++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
 
3674                                 (cops++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
 
3678                 p = ZTWO_PADDR(copdisplay.list[currentcop][0]);
 
3679                 (copl++)->l = CMOVE(highw(p), cop2lc);
 
3680                 (copl++)->l = CMOVE2(loww(p), cop2lc);
 
3681                 p = ZTWO_PADDR(copdisplay.list[currentcop][1]);
 
3682                 (cops++)->l = CMOVE(highw(p), cop2lc);
 
3683                 (cops++)->l = CMOVE2(loww(p), cop2lc);
 
3684                 copdisplay.rebuild[0] = cops;
 
3686                 (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
 
3687                 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
 
3689                         (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
 
3690                                             par->diwstop_h, par->diwstop_v), diwhigh);
 
3692                         if (par->beamcon0 & BMC0_VARBEAMEN) {
 
3693                                 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
 
3694                                 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
 
3695                                 (copl++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
 
3700         copdisplay.rebuild[1] = copl;
 
3703         ami_rebuild_copper();
 
3707          * Rebuild the Copper List
 
3709          * We only change the things that are not static
 
3712 static void ami_rebuild_copper(void)
 
3714         struct amifb_par *par = ¤tpar;
 
3715         copins *copl, *cops;
 
3716         u_short line, h_end1, h_end2;
 
3720         if (IS_AGA && maxfmode + par->clk_shift == 0)
 
3721                 h_end1 = par->diwstrt_h-64;
 
3723                 h_end1 = par->htotal-32;
 
3724         h_end2 = par->ddfstop+64;
 
3728         copl = copdisplay.rebuild[1];
 
3730         if (par->vmode & FB_VMODE_YWRAP) {
 
3731                 if ((par->vyres-par->yoffset) != 1 || !mod2(par->diwstrt_v)) {
 
3732                         if (par->yoffset > par->vyres-par->yres) {
 
3733                                 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
 
3734                                         (copl++)->l = CMOVE(highw(p), bplpt[i]);
 
3735                                         (copl++)->l = CMOVE2(loww(p), bplpt[i]);
 
3737                                 line = par->diwstrt_v + ((par->vyres-par->yoffset)<<par->line_shift) - 1;
 
3738                                 while (line >= 512) {
 
3739                                         (copl++)->l = CWAIT(h_end1, 510);
 
3742                                 if (line >= 510 && IS_AGA && maxfmode + par->clk_shift == 0)
 
3743                                         (copl++)->l = CWAIT(h_end1, line);
 
3745                                         (copl++)->l = CWAIT(h_end2, line);
 
3746                                 p = par->bplpt0wrap;
 
3748                 } else p = par->bplpt0wrap;
 
3750         for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
 
3751                 (copl++)->l = CMOVE(highw(p), bplpt[i]);
 
3752                 (copl++)->l = CMOVE2(loww(p), bplpt[i]);
 
3756         if (par->bplcon0 & BPC0_LACE) {
 
3757                 cops = copdisplay.rebuild[0];
 
3759                 if (mod2(par->diwstrt_v))
 
3760                         p -= par->next_line;
 
3762                         p += par->next_line;
 
3763                 if (par->vmode & FB_VMODE_YWRAP) {
 
3764                         if ((par->vyres-par->yoffset) != 1 || mod2(par->diwstrt_v)) {
 
3765                                 if (par->yoffset > par->vyres-par->yres+1) {
 
3766                                         for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
 
3767                                                 (cops++)->l = CMOVE(highw(p), bplpt[i]);
 
3768                                                 (cops++)->l = CMOVE2(loww(p), bplpt[i]);
 
3770                                         line = par->diwstrt_v + ((par->vyres-par->yoffset)<<par->line_shift) - 2;
 
3771                                         while (line >= 512) {
 
3772                                                 (cops++)->l = CWAIT(h_end1, 510);
 
3775                                         if (line > 510 && IS_AGA && maxfmode + par->clk_shift == 0)
 
3776                                                 (cops++)->l = CWAIT(h_end1, line);
 
3778                                                 (cops++)->l = CWAIT(h_end2, line);
 
3779                                         p = par->bplpt0wrap;
 
3780                                         if (mod2(par->diwstrt_v+par->vyres-par->yoffset))
 
3781                                                 p -= par->next_line;
 
3783                                                 p += par->next_line;
 
3785                         } else p = par->bplpt0wrap - par->next_line;
 
3787                 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
 
3788                         (cops++)->l = CMOVE(highw(p), bplpt[i]);
 
3789                         (cops++)->l = CMOVE2(loww(p), bplpt[i]);
 
3795 static void __exit amifb_exit(void)
 
3797         unregister_framebuffer(&fb_info);
 
3802 module_init(amifb_init);
 
3803 module_exit(amifb_exit);
 
3805 MODULE_LICENSE("GPL");