Linux Audio

Check our new training course

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