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