xref: /openbmc/linux/drivers/video/fbdev/amifb.c (revision 14474950)
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 	delta = 1 << par->crsr.fmode;
1859 	lspr = lofsprite + (delta << 1);
1860 	if (par->bplcon0 & BPC0_LACE)
1861 		sspr = shfsprite + (delta << 1);
1862 	else
1863 		sspr = NULL;
1864 	for (height = (short)var->height - 1; height >= 0; height--) {
1865 		bits = 0; words = delta; datawords = 0;
1866 		for (width = (short)var->width - 1; width >= 0; width--) {
1867 			if (bits == 0) {
1868 				bits = 16; --words;
1869 #ifdef __mc68000__
1870 				asm volatile ("movew %1@(%3:w:2),%0 ; swap %0 ; movew %1@+,%0"
1871 					: "=d" (datawords), "=a" (lspr) : "1" (lspr), "d" (delta));
1872 #else
1873 				datawords = (*(lspr + delta) << 16) | (*lspr++);
1874 #endif
1875 			}
1876 			--bits;
1877 #ifdef __mc68000__
1878 			asm volatile (
1879 				"clrb %0 ; swap %1 ; lslw #1,%1 ; roxlb #1,%0 ; "
1880 				"swap %1 ; lslw #1,%1 ; roxlb #1,%0"
1881 				: "=d" (color), "=d" (datawords) : "1" (datawords));
1882 #else
1883 			color = (((datawords >> 30) & 2)
1884 				 | ((datawords >> 15) & 1));
1885 			datawords <<= 1;
1886 #endif
1887 			put_user(color, data++);
1888 		}
1889 		if (bits > 0) {
1890 			--words; ++lspr;
1891 		}
1892 		while (--words >= 0)
1893 			++lspr;
1894 #ifdef __mc68000__
1895 		asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
1896 			: "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
1897 #else
1898 		lspr += delta;
1899 		if (sspr) {
1900 			u_short *tmp = lspr;
1901 			lspr = sspr;
1902 			sspr = tmp;
1903 		}
1904 #endif
1905 	}
1906 	return 0;
1907 }
1908 
1909 static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var,
1910 				  u_char __user *data, struct amifb_par *par)
1911 {
1912 	register u_short *lspr, *sspr;
1913 #ifdef __mc68000__
1914 	register u_long datawords asm ("d2");
1915 #else
1916 	register u_long datawords;
1917 #endif
1918 	register short delta;
1919 	u_short fmode;
1920 	short height, width, bits, words;
1921 
1922 	if (!var->width)
1923 		return -EINVAL;
1924 	else if (var->width <= 16)
1925 		fmode = TAG_FMODE_1;
1926 	else if (var->width <= 32)
1927 		fmode = TAG_FMODE_2;
1928 	else if (var->width <= 64)
1929 		fmode = TAG_FMODE_4;
1930 	else
1931 		return -EINVAL;
1932 	if (fmode > maxfmode)
1933 		return -EINVAL;
1934 	if (!var->height)
1935 		return -EINVAL;
1936 	delta = 1 << fmode;
1937 	lofsprite = shfsprite = (u_short *)spritememory;
1938 	lspr = lofsprite + (delta << 1);
1939 	if (par->bplcon0 & BPC0_LACE) {
1940 		if (((var->height + 4) << fmode << 2) > SPRITEMEMSIZE)
1941 			return -EINVAL;
1942 		memset(lspr, 0, (var->height + 4) << fmode << 2);
1943 		shfsprite += ((var->height + 5)&-2) << fmode;
1944 		sspr = shfsprite + (delta << 1);
1945 	} else {
1946 		if (((var->height + 2) << fmode << 2) > SPRITEMEMSIZE)
1947 			return -EINVAL;
1948 		memset(lspr, 0, (var->height + 2) << fmode << 2);
1949 		sspr = NULL;
1950 	}
1951 	for (height = (short)var->height - 1; height >= 0; height--) {
1952 		bits = 16; words = delta; datawords = 0;
1953 		for (width = (short)var->width - 1; width >= 0; width--) {
1954 			unsigned long tdata = 0;
1955 			get_user(tdata, data);
1956 			data++;
1957 #ifdef __mc68000__
1958 			asm volatile (
1959 				"lsrb #1,%2 ; roxlw #1,%0 ; swap %0 ; "
1960 				"lsrb #1,%2 ; roxlw #1,%0 ; swap %0"
1961 				: "=d" (datawords)
1962 				: "0" (datawords), "d" (tdata));
1963 #else
1964 			datawords = ((datawords << 1) & 0xfffefffe);
1965 			datawords |= tdata & 1;
1966 			datawords |= (tdata & 2) << (16 - 1);
1967 #endif
1968 			if (--bits == 0) {
1969 				bits = 16; --words;
1970 #ifdef __mc68000__
1971 				asm volatile ("swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+"
1972 					: "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta));
1973 #else
1974 				*(lspr + delta) = (u_short) (datawords >> 16);
1975 				*lspr++ = (u_short) (datawords & 0xffff);
1976 #endif
1977 			}
1978 		}
1979 		if (bits < 16) {
1980 			--words;
1981 #ifdef __mc68000__
1982 			asm volatile (
1983 				"swap %2 ; lslw %4,%2 ; movew %2,%0@(%3:w:2) ; "
1984 				"swap %2 ; lslw %4,%2 ; movew %2,%0@+"
1985 				: "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta), "d" (bits));
1986 #else
1987 			*(lspr + delta) = (u_short) (datawords >> (16 + bits));
1988 			*lspr++ = (u_short) ((datawords & 0x0000ffff) >> bits);
1989 #endif
1990 		}
1991 		while (--words >= 0) {
1992 #ifdef __mc68000__
1993 			asm volatile ("moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+"
1994 				: "=a" (lspr) : "0" (lspr), "d" (delta) : "d0");
1995 #else
1996 			*(lspr + delta) = 0;
1997 			*lspr++ = 0;
1998 #endif
1999 		}
2000 #ifdef __mc68000__
2001 		asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
2002 			: "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
2003 #else
2004 		lspr += delta;
2005 		if (sspr) {
2006 			u_short *tmp = lspr;
2007 			lspr = sspr;
2008 			sspr = tmp;
2009 		}
2010 #endif
2011 	}
2012 	par->crsr.height = var->height;
2013 	par->crsr.width = var->width;
2014 	par->crsr.spot_x = var->xspot;
2015 	par->crsr.spot_y = var->yspot;
2016 	par->crsr.fmode = fmode;
2017 	if (IS_AGA) {
2018 		par->fmode &= ~(FMODE_SPAGEM | FMODE_SPR32);
2019 		par->fmode |= sprfetchmode[fmode];
2020 		custom.fmode = par->fmode;
2021 	}
2022 	return 0;
2023 }
2024 
2025 static int ami_get_cursorstate(struct fb_cursorstate *state,
2026 			       const struct amifb_par *par)
2027 {
2028 	state->xoffset = par->crsr.crsr_x;
2029 	state->yoffset = par->crsr.crsr_y;
2030 	state->mode = cursormode;
2031 	return 0;
2032 }
2033 
2034 static int ami_set_cursorstate(struct fb_cursorstate *state,
2035 			       struct amifb_par *par)
2036 {
2037 	par->crsr.crsr_x = state->xoffset;
2038 	par->crsr.crsr_y = state->yoffset;
2039 	if ((cursormode = state->mode) == FB_CURSOR_OFF)
2040 		cursorstate = -1;
2041 	do_cursor = 1;
2042 	return 0;
2043 }
2044 
2045 static void ami_set_sprite(const struct amifb_par *par)
2046 {
2047 	copins *copl, *cops;
2048 	u_short hs, vs, ve;
2049 	u_long pl, ps;
2050 	short mx, my;
2051 
2052 	cops = copdisplay.list[currentcop][0];
2053 	copl = copdisplay.list[currentcop][1];
2054 	ps = pl = ZTWO_PADDR(dummysprite);
2055 	mx = par->crsr.crsr_x - par->crsr.spot_x;
2056 	my = par->crsr.crsr_y - par->crsr.spot_y;
2057 	if (!(par->vmode & FB_VMODE_YWRAP)) {
2058 		mx -= par->xoffset;
2059 		my -= par->yoffset;
2060 	}
2061 	if (!is_blanked && cursorstate > 0 && par->crsr.height > 0 &&
2062 	    mx > -(short)par->crsr.width && mx < par->xres &&
2063 	    my > -(short)par->crsr.height && my < par->yres) {
2064 		pl = ZTWO_PADDR(lofsprite);
2065 		hs = par->diwstrt_h + (mx << par->clk_shift) - 4;
2066 		vs = par->diwstrt_v + (my << par->line_shift);
2067 		ve = vs + (par->crsr.height << par->line_shift);
2068 		if (par->bplcon0 & BPC0_LACE) {
2069 			ps = ZTWO_PADDR(shfsprite);
2070 			lofsprite[0] = spr2hw_pos(vs, hs);
2071 			shfsprite[0] = spr2hw_pos(vs + 1, hs);
2072 			if (mod2(vs)) {
2073 				lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
2074 				shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve + 1);
2075 				swap(pl, ps);
2076 			} else {
2077 				lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve + 1);
2078 				shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve);
2079 			}
2080 		} else {
2081 			lofsprite[0] = spr2hw_pos(vs, hs) | (IS_AGA && (par->fmode & FMODE_BSCAN2) ? 0x80 : 0);
2082 			lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
2083 		}
2084 	}
2085 	copl[cop_spr0ptrh].w[1] = highw(pl);
2086 	copl[cop_spr0ptrl].w[1] = loww(pl);
2087 	if (par->bplcon0 & BPC0_LACE) {
2088 		cops[cop_spr0ptrh].w[1] = highw(ps);
2089 		cops[cop_spr0ptrl].w[1] = loww(ps);
2090 	}
2091 }
2092 
2093 
2094 	/*
2095 	 * Initialise the Copper Initialisation List
2096 	 */
2097 
2098 static void __init ami_init_copper(void)
2099 {
2100 	copins *cop = copdisplay.init;
2101 	u_long p;
2102 	int i;
2103 
2104 	if (!IS_OCS) {
2105 		(cop++)->l = CMOVE(BPC0_COLOR | BPC0_SHRES | BPC0_ECSENA, bplcon0);
2106 		(cop++)->l = CMOVE(0x0181, diwstrt);
2107 		(cop++)->l = CMOVE(0x0281, diwstop);
2108 		(cop++)->l = CMOVE(0x0000, diwhigh);
2109 	} else
2110 		(cop++)->l = CMOVE(BPC0_COLOR, bplcon0);
2111 	p = ZTWO_PADDR(dummysprite);
2112 	for (i = 0; i < 8; i++) {
2113 		(cop++)->l = CMOVE(0, spr[i].pos);
2114 		(cop++)->l = CMOVE(highw(p), sprpt[i]);
2115 		(cop++)->l = CMOVE2(loww(p), sprpt[i]);
2116 	}
2117 
2118 	(cop++)->l = CMOVE(IF_SETCLR | IF_COPER, intreq);
2119 	copdisplay.wait = cop;
2120 	(cop++)->l = CEND;
2121 	(cop++)->l = CMOVE(0, copjmp2);
2122 	cop->l = CEND;
2123 
2124 	custom.cop1lc = (u_short *)ZTWO_PADDR(copdisplay.init);
2125 	custom.copjmp1 = 0;
2126 }
2127 
2128 static void ami_reinit_copper(const struct amifb_par *par)
2129 {
2130 	copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0;
2131 	copdisplay.wait->l = CWAIT(32, par->diwstrt_v - 4);
2132 }
2133 
2134 
2135 	/*
2136 	 * Rebuild the Copper List
2137 	 *
2138 	 * We only change the things that are not static
2139 	 */
2140 
2141 static void ami_rebuild_copper(const struct amifb_par *par)
2142 {
2143 	copins *copl, *cops;
2144 	u_short line, h_end1, h_end2;
2145 	short i;
2146 	u_long p;
2147 
2148 	if (IS_AGA && maxfmode + par->clk_shift == 0)
2149 		h_end1 = par->diwstrt_h - 64;
2150 	else
2151 		h_end1 = par->htotal - 32;
2152 	h_end2 = par->ddfstop + 64;
2153 
2154 	ami_set_sprite(par);
2155 
2156 	copl = copdisplay.rebuild[1];
2157 	p = par->bplpt0;
2158 	if (par->vmode & FB_VMODE_YWRAP) {
2159 		if ((par->vyres - par->yoffset) != 1 || !mod2(par->diwstrt_v)) {
2160 			if (par->yoffset > par->vyres - par->yres) {
2161 				for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2162 					(copl++)->l = CMOVE(highw(p), bplpt[i]);
2163 					(copl++)->l = CMOVE2(loww(p), bplpt[i]);
2164 				}
2165 				line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 1;
2166 				while (line >= 512) {
2167 					(copl++)->l = CWAIT(h_end1, 510);
2168 					line -= 512;
2169 				}
2170 				if (line >= 510 && IS_AGA && maxfmode + par->clk_shift == 0)
2171 					(copl++)->l = CWAIT(h_end1, line);
2172 				else
2173 					(copl++)->l = CWAIT(h_end2, line);
2174 				p = par->bplpt0wrap;
2175 			}
2176 		} else
2177 			p = par->bplpt0wrap;
2178 	}
2179 	for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2180 		(copl++)->l = CMOVE(highw(p), bplpt[i]);
2181 		(copl++)->l = CMOVE2(loww(p), bplpt[i]);
2182 	}
2183 	copl->l = CEND;
2184 
2185 	if (par->bplcon0 & BPC0_LACE) {
2186 		cops = copdisplay.rebuild[0];
2187 		p = par->bplpt0;
2188 		if (mod2(par->diwstrt_v))
2189 			p -= par->next_line;
2190 		else
2191 			p += par->next_line;
2192 		if (par->vmode & FB_VMODE_YWRAP) {
2193 			if ((par->vyres - par->yoffset) != 1 || mod2(par->diwstrt_v)) {
2194 				if (par->yoffset > par->vyres - par->yres + 1) {
2195 					for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2196 						(cops++)->l = CMOVE(highw(p), bplpt[i]);
2197 						(cops++)->l = CMOVE2(loww(p), bplpt[i]);
2198 					}
2199 					line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 2;
2200 					while (line >= 512) {
2201 						(cops++)->l = CWAIT(h_end1, 510);
2202 						line -= 512;
2203 					}
2204 					if (line > 510 && IS_AGA && maxfmode + par->clk_shift == 0)
2205 						(cops++)->l = CWAIT(h_end1, line);
2206 					else
2207 						(cops++)->l = CWAIT(h_end2, line);
2208 					p = par->bplpt0wrap;
2209 					if (mod2(par->diwstrt_v + par->vyres -
2210 					    par->yoffset))
2211 						p -= par->next_line;
2212 					else
2213 						p += par->next_line;
2214 				}
2215 			} else
2216 				p = par->bplpt0wrap - par->next_line;
2217 		}
2218 		for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2219 			(cops++)->l = CMOVE(highw(p), bplpt[i]);
2220 			(cops++)->l = CMOVE2(loww(p), bplpt[i]);
2221 		}
2222 		cops->l = CEND;
2223 	}
2224 }
2225 
2226 
2227 	/*
2228 	 * Build the Copper List
2229 	 */
2230 
2231 static void ami_build_copper(struct fb_info *info)
2232 {
2233 	struct amifb_par *par = info->par;
2234 	copins *copl, *cops;
2235 	u_long p;
2236 
2237 	currentcop = 1 - currentcop;
2238 
2239 	copl = copdisplay.list[currentcop][1];
2240 
2241 	(copl++)->l = CWAIT(0, 10);
2242 	(copl++)->l = CMOVE(par->bplcon0, bplcon0);
2243 	(copl++)->l = CMOVE(0, sprpt[0]);
2244 	(copl++)->l = CMOVE2(0, sprpt[0]);
2245 
2246 	if (par->bplcon0 & BPC0_LACE) {
2247 		cops = copdisplay.list[currentcop][0];
2248 
2249 		(cops++)->l = CWAIT(0, 10);
2250 		(cops++)->l = CMOVE(par->bplcon0, bplcon0);
2251 		(cops++)->l = CMOVE(0, sprpt[0]);
2252 		(cops++)->l = CMOVE2(0, sprpt[0]);
2253 
2254 		(copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v + 1), diwstrt);
2255 		(copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v + 1), diwstop);
2256 		(cops++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
2257 		(cops++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
2258 		if (!IS_OCS) {
2259 			(copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v + 1,
2260 					    par->diwstop_h, par->diwstop_v + 1), diwhigh);
2261 			(cops++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
2262 					    par->diwstop_h, par->diwstop_v), diwhigh);
2263 #if 0
2264 			if (par->beamcon0 & BMC0_VARBEAMEN) {
2265 				(copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
2266 				(copl++)->l = CMOVE(vbstrt2hw(par->vbstrt + 1), vbstrt);
2267 				(copl++)->l = CMOVE(vbstop2hw(par->vbstop + 1), vbstop);
2268 				(cops++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
2269 				(cops++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
2270 				(cops++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
2271 			}
2272 #endif
2273 		}
2274 		p = ZTWO_PADDR(copdisplay.list[currentcop][0]);
2275 		(copl++)->l = CMOVE(highw(p), cop2lc);
2276 		(copl++)->l = CMOVE2(loww(p), cop2lc);
2277 		p = ZTWO_PADDR(copdisplay.list[currentcop][1]);
2278 		(cops++)->l = CMOVE(highw(p), cop2lc);
2279 		(cops++)->l = CMOVE2(loww(p), cop2lc);
2280 		copdisplay.rebuild[0] = cops;
2281 	} else {
2282 		(copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
2283 		(copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
2284 		if (!IS_OCS) {
2285 			(copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
2286 					    par->diwstop_h, par->diwstop_v), diwhigh);
2287 #if 0
2288 			if (par->beamcon0 & BMC0_VARBEAMEN) {
2289 				(copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
2290 				(copl++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
2291 				(copl++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
2292 			}
2293 #endif
2294 		}
2295 	}
2296 	copdisplay.rebuild[1] = copl;
2297 
2298 	ami_update_par(info);
2299 	ami_rebuild_copper(info->par);
2300 }
2301 
2302 #ifndef MODULE
2303 static void __init amifb_setup_mcap(char *spec)
2304 {
2305 	char *p;
2306 	int vmin, vmax, hmin, hmax;
2307 
2308 	/* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
2309 	 * <V*> vertical freq. in Hz
2310 	 * <H*> horizontal freq. in kHz
2311 	 */
2312 
2313 	if (!(p = strsep(&spec, ";")) || !*p)
2314 		return;
2315 	vmin = simple_strtoul(p, NULL, 10);
2316 	if (vmin <= 0)
2317 		return;
2318 	if (!(p = strsep(&spec, ";")) || !*p)
2319 		return;
2320 	vmax = simple_strtoul(p, NULL, 10);
2321 	if (vmax <= 0 || vmax <= vmin)
2322 		return;
2323 	if (!(p = strsep(&spec, ";")) || !*p)
2324 		return;
2325 	hmin = 1000 * simple_strtoul(p, NULL, 10);
2326 	if (hmin <= 0)
2327 		return;
2328 	if (!(p = strsep(&spec, "")) || !*p)
2329 		return;
2330 	hmax = 1000 * simple_strtoul(p, NULL, 10);
2331 	if (hmax <= 0 || hmax <= hmin)
2332 		return;
2333 
2334 	amifb_hfmin = hmin;
2335 	amifb_hfmax = hmax;
2336 	amifb_vfmin = vmin;
2337 	amifb_vfmax = vmax;
2338 }
2339 
2340 static int __init amifb_setup(char *options)
2341 {
2342 	char *this_opt;
2343 
2344 	if (!options || !*options)
2345 		return 0;
2346 
2347 	while ((this_opt = strsep(&options, ",")) != NULL) {
2348 		if (!*this_opt)
2349 			continue;
2350 		if (!strcmp(this_opt, "inverse")) {
2351 			fb_invert_cmaps();
2352 		} else if (!strcmp(this_opt, "ilbm"))
2353 			amifb_ilbm = 1;
2354 		else if (!strncmp(this_opt, "monitorcap:", 11))
2355 			amifb_setup_mcap(this_opt + 11);
2356 		else if (!strncmp(this_opt, "fstart:", 7))
2357 			min_fstrt = simple_strtoul(this_opt + 7, NULL, 0);
2358 		else
2359 			mode_option = this_opt;
2360 	}
2361 
2362 	if (min_fstrt < 48)
2363 		min_fstrt = 48;
2364 
2365 	return 0;
2366 }
2367 #endif
2368 
2369 static int amifb_check_var(struct fb_var_screeninfo *var,
2370 			   struct fb_info *info)
2371 {
2372 	int err;
2373 	struct amifb_par par;
2374 
2375 	/* Validate wanted screen parameters */
2376 	err = ami_decode_var(var, &par, info);
2377 	if (err)
2378 		return err;
2379 
2380 	/* Encode (possibly rounded) screen parameters */
2381 	ami_encode_var(var, &par);
2382 	return 0;
2383 }
2384 
2385 
2386 static int amifb_set_par(struct fb_info *info)
2387 {
2388 	struct amifb_par *par = info->par;
2389 	int error;
2390 
2391 	do_vmode_pan = 0;
2392 	do_vmode_full = 0;
2393 
2394 	/* Decode wanted screen parameters */
2395 	error = ami_decode_var(&info->var, par, info);
2396 	if (error)
2397 		return error;
2398 
2399 	/* Set new videomode */
2400 	ami_build_copper(info);
2401 
2402 	/* Set VBlank trigger */
2403 	do_vmode_full = 1;
2404 
2405 	/* Update fix for new screen parameters */
2406 	if (par->bpp == 1) {
2407 		info->fix.type = FB_TYPE_PACKED_PIXELS;
2408 		info->fix.type_aux = 0;
2409 	} else if (amifb_ilbm) {
2410 		info->fix.type = FB_TYPE_INTERLEAVED_PLANES;
2411 		info->fix.type_aux = par->next_line;
2412 	} else {
2413 		info->fix.type = FB_TYPE_PLANES;
2414 		info->fix.type_aux = 0;
2415 	}
2416 	info->fix.line_length = div8(upx(16 << maxfmode, par->vxres));
2417 
2418 	if (par->vmode & FB_VMODE_YWRAP) {
2419 		info->fix.ywrapstep = 1;
2420 		info->fix.xpanstep = 0;
2421 		info->fix.ypanstep = 0;
2422 		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP |
2423 			FBINFO_READS_FAST; /* override SCROLL_REDRAW */
2424 	} else {
2425 		info->fix.ywrapstep = 0;
2426 		if (par->vmode & FB_VMODE_SMOOTH_XPAN)
2427 			info->fix.xpanstep = 1;
2428 		else
2429 			info->fix.xpanstep = 16 << maxfmode;
2430 		info->fix.ypanstep = 1;
2431 		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
2432 	}
2433 	return 0;
2434 }
2435 
2436 
2437 	/*
2438 	 * Set a single color register. The values supplied are already
2439 	 * rounded down to the hardware's capabilities (according to the
2440 	 * entries in the var structure). Return != 0 for invalid regno.
2441 	 */
2442 
2443 static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
2444 			   u_int transp, struct fb_info *info)
2445 {
2446 	const struct amifb_par *par = info->par;
2447 
2448 	if (IS_AGA) {
2449 		if (regno > 255)
2450 			return 1;
2451 	} else if (par->bplcon0 & BPC0_SHRES) {
2452 		if (regno > 3)
2453 			return 1;
2454 	} else {
2455 		if (regno > 31)
2456 			return 1;
2457 	}
2458 	red >>= 8;
2459 	green >>= 8;
2460 	blue >>= 8;
2461 	if (!regno) {
2462 		red0 = red;
2463 		green0 = green;
2464 		blue0 = blue;
2465 	}
2466 
2467 	/*
2468 	 * Update the corresponding Hardware Color Register, unless it's Color
2469 	 * Register 0 and the screen is blanked.
2470 	 *
2471 	 * VBlank is switched off to protect bplcon3 or ecs_palette[] from
2472 	 * being changed by ami_do_blank() during the VBlank.
2473 	 */
2474 
2475 	if (regno || !is_blanked) {
2476 #if defined(CONFIG_FB_AMIGA_AGA)
2477 		if (IS_AGA) {
2478 			u_short bplcon3 = par->bplcon3;
2479 			VBlankOff();
2480 			custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000);
2481 			custom.color[regno & 31] = rgb2hw8_high(red, green,
2482 								blue);
2483 			custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000) |
2484 					 BPC3_LOCT;
2485 			custom.color[regno & 31] = rgb2hw8_low(red, green,
2486 							       blue);
2487 			custom.bplcon3 = bplcon3;
2488 			VBlankOn();
2489 		} else
2490 #endif
2491 #if defined(CONFIG_FB_AMIGA_ECS)
2492 		if (par->bplcon0 & BPC0_SHRES) {
2493 			u_short color, mask;
2494 			int i;
2495 
2496 			mask = 0x3333;
2497 			color = rgb2hw2(red, green, blue);
2498 			VBlankOff();
2499 			for (i = regno + 12; i >= (int)regno; i -= 4)
2500 				custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
2501 			mask <<= 2; color >>= 2;
2502 			regno = down16(regno) + mul4(mod4(regno));
2503 			for (i = regno + 3; i >= (int)regno; i--)
2504 				custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
2505 			VBlankOn();
2506 		} else
2507 #endif
2508 			custom.color[regno] = rgb2hw4(red, green, blue);
2509 	}
2510 	return 0;
2511 }
2512 
2513 
2514 	/*
2515 	 * Blank the display.
2516 	 */
2517 
2518 static int amifb_blank(int blank, struct fb_info *info)
2519 {
2520 	do_blank = blank ? blank : -1;
2521 
2522 	return 0;
2523 }
2524 
2525 
2526 	/*
2527 	 * Pan or Wrap the Display
2528 	 *
2529 	 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
2530 	 */
2531 
2532 static int amifb_pan_display(struct fb_var_screeninfo *var,
2533 			     struct fb_info *info)
2534 {
2535 	if (var->vmode & FB_VMODE_YWRAP) {
2536 		if (var->yoffset < 0 ||
2537 			var->yoffset >= info->var.yres_virtual || var->xoffset)
2538 				return -EINVAL;
2539 	} else {
2540 		/*
2541 		 * TODO: There will be problems when xpan!=1, so some columns
2542 		 * on the right side will never be seen
2543 		 */
2544 		if (var->xoffset + info->var.xres >
2545 		    upx(16 << maxfmode, info->var.xres_virtual) ||
2546 		    var->yoffset + info->var.yres > info->var.yres_virtual)
2547 			return -EINVAL;
2548 	}
2549 	ami_pan_var(var, info);
2550 	info->var.xoffset = var->xoffset;
2551 	info->var.yoffset = var->yoffset;
2552 	if (var->vmode & FB_VMODE_YWRAP)
2553 		info->var.vmode |= FB_VMODE_YWRAP;
2554 	else
2555 		info->var.vmode &= ~FB_VMODE_YWRAP;
2556 	return 0;
2557 }
2558 
2559 
2560 #if BITS_PER_LONG == 32
2561 #define BYTES_PER_LONG	4
2562 #define SHIFT_PER_LONG	5
2563 #elif BITS_PER_LONG == 64
2564 #define BYTES_PER_LONG	8
2565 #define SHIFT_PER_LONG	6
2566 #else
2567 #define Please update me
2568 #endif
2569 
2570 
2571 	/*
2572 	 *  Compose two values, using a bitmask as decision value
2573 	 *  This is equivalent to (a & mask) | (b & ~mask)
2574 	 */
2575 
2576 static inline unsigned long comp(unsigned long a, unsigned long b,
2577 				 unsigned long mask)
2578 {
2579 	return ((a ^ b) & mask) ^ b;
2580 }
2581 
2582 
2583 static inline unsigned long xor(unsigned long a, unsigned long b,
2584 				unsigned long mask)
2585 {
2586 	return (a & mask) ^ b;
2587 }
2588 
2589 
2590 	/*
2591 	 *  Unaligned forward bit copy using 32-bit or 64-bit memory accesses
2592 	 */
2593 
2594 static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
2595 		   int src_idx, u32 n)
2596 {
2597 	unsigned long first, last;
2598 	int shift = dst_idx - src_idx, left, right;
2599 	unsigned long d0, d1;
2600 	int m;
2601 
2602 	if (!n)
2603 		return;
2604 
2605 	shift = dst_idx - src_idx;
2606 	first = ~0UL >> dst_idx;
2607 	last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
2608 
2609 	if (!shift) {
2610 		// Same alignment for source and dest
2611 
2612 		if (dst_idx + n <= BITS_PER_LONG) {
2613 			// Single word
2614 			if (last)
2615 				first &= last;
2616 			*dst = comp(*src, *dst, first);
2617 		} else {
2618 			// Multiple destination words
2619 			// Leading bits
2620 			if (first) {
2621 				*dst = comp(*src, *dst, first);
2622 				dst++;
2623 				src++;
2624 				n -= BITS_PER_LONG - dst_idx;
2625 			}
2626 
2627 			// Main chunk
2628 			n /= BITS_PER_LONG;
2629 			while (n >= 8) {
2630 				*dst++ = *src++;
2631 				*dst++ = *src++;
2632 				*dst++ = *src++;
2633 				*dst++ = *src++;
2634 				*dst++ = *src++;
2635 				*dst++ = *src++;
2636 				*dst++ = *src++;
2637 				*dst++ = *src++;
2638 				n -= 8;
2639 			}
2640 			while (n--)
2641 				*dst++ = *src++;
2642 
2643 			// Trailing bits
2644 			if (last)
2645 				*dst = comp(*src, *dst, last);
2646 		}
2647 	} else {
2648 		// Different alignment for source and dest
2649 
2650 		right = shift & (BITS_PER_LONG - 1);
2651 		left = -shift & (BITS_PER_LONG - 1);
2652 
2653 		if (dst_idx + n <= BITS_PER_LONG) {
2654 			// Single destination word
2655 			if (last)
2656 				first &= last;
2657 			if (shift > 0) {
2658 				// Single source word
2659 				*dst = comp(*src >> right, *dst, first);
2660 			} else if (src_idx + n <= BITS_PER_LONG) {
2661 				// Single source word
2662 				*dst = comp(*src << left, *dst, first);
2663 			} else {
2664 				// 2 source words
2665 				d0 = *src++;
2666 				d1 = *src;
2667 				*dst = comp(d0 << left | d1 >> right, *dst,
2668 					    first);
2669 			}
2670 		} else {
2671 			// Multiple destination words
2672 			d0 = *src++;
2673 			// Leading bits
2674 			if (shift > 0) {
2675 				// Single source word
2676 				*dst = comp(d0 >> right, *dst, first);
2677 				dst++;
2678 				n -= BITS_PER_LONG - dst_idx;
2679 			} else {
2680 				// 2 source words
2681 				d1 = *src++;
2682 				*dst = comp(d0 << left | d1 >> right, *dst,
2683 					    first);
2684 				d0 = d1;
2685 				dst++;
2686 				n -= BITS_PER_LONG - dst_idx;
2687 			}
2688 
2689 			// Main chunk
2690 			m = n % BITS_PER_LONG;
2691 			n /= BITS_PER_LONG;
2692 			while (n >= 4) {
2693 				d1 = *src++;
2694 				*dst++ = d0 << left | d1 >> right;
2695 				d0 = d1;
2696 				d1 = *src++;
2697 				*dst++ = d0 << left | d1 >> right;
2698 				d0 = d1;
2699 				d1 = *src++;
2700 				*dst++ = d0 << left | d1 >> right;
2701 				d0 = d1;
2702 				d1 = *src++;
2703 				*dst++ = d0 << left | d1 >> right;
2704 				d0 = d1;
2705 				n -= 4;
2706 			}
2707 			while (n--) {
2708 				d1 = *src++;
2709 				*dst++ = d0 << left | d1 >> right;
2710 				d0 = d1;
2711 			}
2712 
2713 			// Trailing bits
2714 			if (last) {
2715 				if (m <= right) {
2716 					// Single source word
2717 					*dst = comp(d0 << left, *dst, last);
2718 				} else {
2719 					// 2 source words
2720 					d1 = *src;
2721 					*dst = comp(d0 << left | d1 >> right,
2722 						    *dst, last);
2723 				}
2724 			}
2725 		}
2726 	}
2727 }
2728 
2729 
2730 	/*
2731 	 *  Unaligned reverse bit copy using 32-bit or 64-bit memory accesses
2732 	 */
2733 
2734 static void bitcpy_rev(unsigned long *dst, int dst_idx,
2735 		       const unsigned long *src, int src_idx, u32 n)
2736 {
2737 	unsigned long first, last;
2738 	int shift = dst_idx - src_idx, left, right;
2739 	unsigned long d0, d1;
2740 	int m;
2741 
2742 	if (!n)
2743 		return;
2744 
2745 	dst += (n - 1) / BITS_PER_LONG;
2746 	src += (n - 1) / BITS_PER_LONG;
2747 	if ((n - 1) % BITS_PER_LONG) {
2748 		dst_idx += (n - 1) % BITS_PER_LONG;
2749 		dst += dst_idx >> SHIFT_PER_LONG;
2750 		dst_idx &= BITS_PER_LONG - 1;
2751 		src_idx += (n - 1) % BITS_PER_LONG;
2752 		src += src_idx >> SHIFT_PER_LONG;
2753 		src_idx &= BITS_PER_LONG - 1;
2754 	}
2755 
2756 	shift = dst_idx - src_idx;
2757 	first = ~0UL << (BITS_PER_LONG - 1 - dst_idx);
2758 	last = ~(~0UL << (BITS_PER_LONG - 1 - ((dst_idx - n) % BITS_PER_LONG)));
2759 
2760 	if (!shift) {
2761 		// Same alignment for source and dest
2762 
2763 		if ((unsigned long)dst_idx + 1 >= n) {
2764 			// Single word
2765 			if (last)
2766 				first &= last;
2767 			*dst = comp(*src, *dst, first);
2768 		} else {
2769 			// Multiple destination words
2770 			// Leading bits
2771 			if (first) {
2772 				*dst = comp(*src, *dst, first);
2773 				dst--;
2774 				src--;
2775 				n -= dst_idx + 1;
2776 			}
2777 
2778 			// Main chunk
2779 			n /= BITS_PER_LONG;
2780 			while (n >= 8) {
2781 				*dst-- = *src--;
2782 				*dst-- = *src--;
2783 				*dst-- = *src--;
2784 				*dst-- = *src--;
2785 				*dst-- = *src--;
2786 				*dst-- = *src--;
2787 				*dst-- = *src--;
2788 				*dst-- = *src--;
2789 				n -= 8;
2790 			}
2791 			while (n--)
2792 				*dst-- = *src--;
2793 
2794 			// Trailing bits
2795 			if (last)
2796 				*dst = comp(*src, *dst, last);
2797 		}
2798 	} else {
2799 		// Different alignment for source and dest
2800 
2801 		right = shift & (BITS_PER_LONG - 1);
2802 		left = -shift & (BITS_PER_LONG - 1);
2803 
2804 		if ((unsigned long)dst_idx + 1 >= n) {
2805 			// Single destination word
2806 			if (last)
2807 				first &= last;
2808 			if (shift < 0) {
2809 				// Single source word
2810 				*dst = comp(*src << left, *dst, first);
2811 			} else if (1 + (unsigned long)src_idx >= n) {
2812 				// Single source word
2813 				*dst = comp(*src >> right, *dst, first);
2814 			} else {
2815 				// 2 source words
2816 				d0 = *src--;
2817 				d1 = *src;
2818 				*dst = comp(d0 >> right | d1 << left, *dst,
2819 					    first);
2820 			}
2821 		} else {
2822 			// Multiple destination words
2823 			d0 = *src--;
2824 			// Leading bits
2825 			if (shift < 0) {
2826 				// Single source word
2827 				*dst = comp(d0 << left, *dst, first);
2828 				dst--;
2829 				n -= dst_idx + 1;
2830 			} else {
2831 				// 2 source words
2832 				d1 = *src--;
2833 				*dst = comp(d0 >> right | d1 << left, *dst,
2834 					    first);
2835 				d0 = d1;
2836 				dst--;
2837 				n -= dst_idx + 1;
2838 			}
2839 
2840 			// Main chunk
2841 			m = n % BITS_PER_LONG;
2842 			n /= BITS_PER_LONG;
2843 			while (n >= 4) {
2844 				d1 = *src--;
2845 				*dst-- = d0 >> right | d1 << left;
2846 				d0 = d1;
2847 				d1 = *src--;
2848 				*dst-- = d0 >> right | d1 << left;
2849 				d0 = d1;
2850 				d1 = *src--;
2851 				*dst-- = d0 >> right | d1 << left;
2852 				d0 = d1;
2853 				d1 = *src--;
2854 				*dst-- = d0 >> right | d1 << left;
2855 				d0 = d1;
2856 				n -= 4;
2857 			}
2858 			while (n--) {
2859 				d1 = *src--;
2860 				*dst-- = d0 >> right | d1 << left;
2861 				d0 = d1;
2862 			}
2863 
2864 			// Trailing bits
2865 			if (last) {
2866 				if (m <= left) {
2867 					// Single source word
2868 					*dst = comp(d0 >> right, *dst, last);
2869 				} else {
2870 					// 2 source words
2871 					d1 = *src;
2872 					*dst = comp(d0 >> right | d1 << left,
2873 						    *dst, last);
2874 				}
2875 			}
2876 		}
2877 	}
2878 }
2879 
2880 
2881 	/*
2882 	 *  Unaligned forward inverting bit copy using 32-bit or 64-bit memory
2883 	 *  accesses
2884 	 */
2885 
2886 static void bitcpy_not(unsigned long *dst, int dst_idx,
2887 		       const unsigned long *src, int src_idx, u32 n)
2888 {
2889 	unsigned long first, last;
2890 	int shift = dst_idx - src_idx, left, right;
2891 	unsigned long d0, d1;
2892 	int m;
2893 
2894 	if (!n)
2895 		return;
2896 
2897 	shift = dst_idx - src_idx;
2898 	first = ~0UL >> dst_idx;
2899 	last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
2900 
2901 	if (!shift) {
2902 		// Same alignment for source and dest
2903 
2904 		if (dst_idx + n <= BITS_PER_LONG) {
2905 			// Single word
2906 			if (last)
2907 				first &= last;
2908 			*dst = comp(~*src, *dst, first);
2909 		} else {
2910 			// Multiple destination words
2911 			// Leading bits
2912 			if (first) {
2913 				*dst = comp(~*src, *dst, first);
2914 				dst++;
2915 				src++;
2916 				n -= BITS_PER_LONG - dst_idx;
2917 			}
2918 
2919 			// Main chunk
2920 			n /= BITS_PER_LONG;
2921 			while (n >= 8) {
2922 				*dst++ = ~*src++;
2923 				*dst++ = ~*src++;
2924 				*dst++ = ~*src++;
2925 				*dst++ = ~*src++;
2926 				*dst++ = ~*src++;
2927 				*dst++ = ~*src++;
2928 				*dst++ = ~*src++;
2929 				*dst++ = ~*src++;
2930 				n -= 8;
2931 			}
2932 			while (n--)
2933 				*dst++ = ~*src++;
2934 
2935 			// Trailing bits
2936 			if (last)
2937 				*dst = comp(~*src, *dst, last);
2938 		}
2939 	} else {
2940 		// Different alignment for source and dest
2941 
2942 		right = shift & (BITS_PER_LONG - 1);
2943 		left = -shift & (BITS_PER_LONG - 1);
2944 
2945 		if (dst_idx + n <= BITS_PER_LONG) {
2946 			// Single destination word
2947 			if (last)
2948 				first &= last;
2949 			if (shift > 0) {
2950 				// Single source word
2951 				*dst = comp(~*src >> right, *dst, first);
2952 			} else if (src_idx + n <= BITS_PER_LONG) {
2953 				// Single source word
2954 				*dst = comp(~*src << left, *dst, first);
2955 			} else {
2956 				// 2 source words
2957 				d0 = ~*src++;
2958 				d1 = ~*src;
2959 				*dst = comp(d0 << left | d1 >> right, *dst,
2960 					    first);
2961 			}
2962 		} else {
2963 			// Multiple destination words
2964 			d0 = ~*src++;
2965 			// Leading bits
2966 			if (shift > 0) {
2967 				// Single source word
2968 				*dst = comp(d0 >> right, *dst, first);
2969 				dst++;
2970 				n -= BITS_PER_LONG - dst_idx;
2971 			} else {
2972 				// 2 source words
2973 				d1 = ~*src++;
2974 				*dst = comp(d0 << left | d1 >> right, *dst,
2975 					    first);
2976 				d0 = d1;
2977 				dst++;
2978 				n -= BITS_PER_LONG - dst_idx;
2979 			}
2980 
2981 			// Main chunk
2982 			m = n % BITS_PER_LONG;
2983 			n /= BITS_PER_LONG;
2984 			while (n >= 4) {
2985 				d1 = ~*src++;
2986 				*dst++ = d0 << left | d1 >> right;
2987 				d0 = d1;
2988 				d1 = ~*src++;
2989 				*dst++ = d0 << left | d1 >> right;
2990 				d0 = d1;
2991 				d1 = ~*src++;
2992 				*dst++ = d0 << left | d1 >> right;
2993 				d0 = d1;
2994 				d1 = ~*src++;
2995 				*dst++ = d0 << left | d1 >> right;
2996 				d0 = d1;
2997 				n -= 4;
2998 			}
2999 			while (n--) {
3000 				d1 = ~*src++;
3001 				*dst++ = d0 << left | d1 >> right;
3002 				d0 = d1;
3003 			}
3004 
3005 			// Trailing bits
3006 			if (last) {
3007 				if (m <= right) {
3008 					// Single source word
3009 					*dst = comp(d0 << left, *dst, last);
3010 				} else {
3011 					// 2 source words
3012 					d1 = ~*src;
3013 					*dst = comp(d0 << left | d1 >> right,
3014 						    *dst, last);
3015 				}
3016 			}
3017 		}
3018 	}
3019 }
3020 
3021 
3022 	/*
3023 	 *  Unaligned 32-bit pattern fill using 32/64-bit memory accesses
3024 	 */
3025 
3026 static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
3027 {
3028 	unsigned long val = pat;
3029 	unsigned long first, last;
3030 
3031 	if (!n)
3032 		return;
3033 
3034 #if BITS_PER_LONG == 64
3035 	val |= val << 32;
3036 #endif
3037 
3038 	first = ~0UL >> dst_idx;
3039 	last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
3040 
3041 	if (dst_idx + n <= BITS_PER_LONG) {
3042 		// Single word
3043 		if (last)
3044 			first &= last;
3045 		*dst = comp(val, *dst, first);
3046 	} else {
3047 		// Multiple destination words
3048 		// Leading bits
3049 		if (first) {
3050 			*dst = comp(val, *dst, first);
3051 			dst++;
3052 			n -= BITS_PER_LONG - dst_idx;
3053 		}
3054 
3055 		// Main chunk
3056 		n /= BITS_PER_LONG;
3057 		while (n >= 8) {
3058 			*dst++ = val;
3059 			*dst++ = val;
3060 			*dst++ = val;
3061 			*dst++ = val;
3062 			*dst++ = val;
3063 			*dst++ = val;
3064 			*dst++ = val;
3065 			*dst++ = val;
3066 			n -= 8;
3067 		}
3068 		while (n--)
3069 			*dst++ = val;
3070 
3071 		// Trailing bits
3072 		if (last)
3073 			*dst = comp(val, *dst, last);
3074 	}
3075 }
3076 
3077 
3078 	/*
3079 	 *  Unaligned 32-bit pattern xor using 32/64-bit memory accesses
3080 	 */
3081 
3082 static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
3083 {
3084 	unsigned long val = pat;
3085 	unsigned long first, last;
3086 
3087 	if (!n)
3088 		return;
3089 
3090 #if BITS_PER_LONG == 64
3091 	val |= val << 32;
3092 #endif
3093 
3094 	first = ~0UL >> dst_idx;
3095 	last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
3096 
3097 	if (dst_idx + n <= BITS_PER_LONG) {
3098 		// Single word
3099 		if (last)
3100 			first &= last;
3101 		*dst = xor(val, *dst, first);
3102 	} else {
3103 		// Multiple destination words
3104 		// Leading bits
3105 		if (first) {
3106 			*dst = xor(val, *dst, first);
3107 			dst++;
3108 			n -= BITS_PER_LONG - dst_idx;
3109 		}
3110 
3111 		// Main chunk
3112 		n /= BITS_PER_LONG;
3113 		while (n >= 4) {
3114 			*dst++ ^= val;
3115 			*dst++ ^= val;
3116 			*dst++ ^= val;
3117 			*dst++ ^= val;
3118 			n -= 4;
3119 		}
3120 		while (n--)
3121 			*dst++ ^= val;
3122 
3123 		// Trailing bits
3124 		if (last)
3125 			*dst = xor(val, *dst, last);
3126 	}
3127 }
3128 
3129 static inline void fill_one_line(int bpp, unsigned long next_plane,
3130 				 unsigned long *dst, int dst_idx, u32 n,
3131 				 u32 color)
3132 {
3133 	while (1) {
3134 		dst += dst_idx >> SHIFT_PER_LONG;
3135 		dst_idx &= (BITS_PER_LONG - 1);
3136 		bitfill32(dst, dst_idx, color & 1 ? ~0 : 0, n);
3137 		if (!--bpp)
3138 			break;
3139 		color >>= 1;
3140 		dst_idx += next_plane * 8;
3141 	}
3142 }
3143 
3144 static inline void xor_one_line(int bpp, unsigned long next_plane,
3145 				unsigned long *dst, int dst_idx, u32 n,
3146 				u32 color)
3147 {
3148 	while (color) {
3149 		dst += dst_idx >> SHIFT_PER_LONG;
3150 		dst_idx &= (BITS_PER_LONG - 1);
3151 		bitxor32(dst, dst_idx, color & 1 ? ~0 : 0, n);
3152 		if (!--bpp)
3153 			break;
3154 		color >>= 1;
3155 		dst_idx += next_plane * 8;
3156 	}
3157 }
3158 
3159 
3160 static void amifb_fillrect(struct fb_info *info,
3161 			   const struct fb_fillrect *rect)
3162 {
3163 	struct amifb_par *par = info->par;
3164 	int dst_idx, x2, y2;
3165 	unsigned long *dst;
3166 	u32 width, height;
3167 
3168 	if (!rect->width || !rect->height)
3169 		return;
3170 
3171 	/*
3172 	 * We could use hardware clipping but on many cards you get around
3173 	 * hardware clipping by writing to framebuffer directly.
3174 	 * */
3175 	x2 = rect->dx + rect->width;
3176 	y2 = rect->dy + rect->height;
3177 	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
3178 	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
3179 	width = x2 - rect->dx;
3180 	height = y2 - rect->dy;
3181 
3182 	dst = (unsigned long *)
3183 		((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
3184 	dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
3185 	dst_idx += rect->dy * par->next_line * 8 + rect->dx;
3186 	while (height--) {
3187 		switch (rect->rop) {
3188 		case ROP_COPY:
3189 			fill_one_line(info->var.bits_per_pixel,
3190 				      par->next_plane, dst, dst_idx, width,
3191 				      rect->color);
3192 			break;
3193 
3194 		case ROP_XOR:
3195 			xor_one_line(info->var.bits_per_pixel, par->next_plane,
3196 				     dst, dst_idx, width, rect->color);
3197 			break;
3198 		}
3199 		dst_idx += par->next_line * 8;
3200 	}
3201 }
3202 
3203 static inline void copy_one_line(int bpp, unsigned long next_plane,
3204 				 unsigned long *dst, int dst_idx,
3205 				 unsigned long *src, int src_idx, u32 n)
3206 {
3207 	while (1) {
3208 		dst += dst_idx >> SHIFT_PER_LONG;
3209 		dst_idx &= (BITS_PER_LONG - 1);
3210 		src += src_idx >> SHIFT_PER_LONG;
3211 		src_idx &= (BITS_PER_LONG - 1);
3212 		bitcpy(dst, dst_idx, src, src_idx, n);
3213 		if (!--bpp)
3214 			break;
3215 		dst_idx += next_plane * 8;
3216 		src_idx += next_plane * 8;
3217 	}
3218 }
3219 
3220 static inline void copy_one_line_rev(int bpp, unsigned long next_plane,
3221 				     unsigned long *dst, int dst_idx,
3222 				     unsigned long *src, int src_idx, u32 n)
3223 {
3224 	while (1) {
3225 		dst += dst_idx >> SHIFT_PER_LONG;
3226 		dst_idx &= (BITS_PER_LONG - 1);
3227 		src += src_idx >> SHIFT_PER_LONG;
3228 		src_idx &= (BITS_PER_LONG - 1);
3229 		bitcpy_rev(dst, dst_idx, src, src_idx, n);
3230 		if (!--bpp)
3231 			break;
3232 		dst_idx += next_plane * 8;
3233 		src_idx += next_plane * 8;
3234 	}
3235 }
3236 
3237 
3238 static void amifb_copyarea(struct fb_info *info,
3239 			   const struct fb_copyarea *area)
3240 {
3241 	struct amifb_par *par = info->par;
3242 	int x2, y2;
3243 	u32 dx, dy, sx, sy, width, height;
3244 	unsigned long *dst, *src;
3245 	int dst_idx, src_idx;
3246 	int rev_copy = 0;
3247 
3248 	/* clip the destination */
3249 	x2 = area->dx + area->width;
3250 	y2 = area->dy + area->height;
3251 	dx = area->dx > 0 ? area->dx : 0;
3252 	dy = area->dy > 0 ? area->dy : 0;
3253 	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
3254 	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
3255 	width = x2 - dx;
3256 	height = y2 - dy;
3257 
3258 	if (area->sx + dx < area->dx || area->sy + dy < area->dy)
3259 		return;
3260 
3261 	/* update sx,sy */
3262 	sx = area->sx + (dx - area->dx);
3263 	sy = area->sy + (dy - area->dy);
3264 
3265 	/* the source must be completely inside the virtual screen */
3266 	if (sx + width > info->var.xres_virtual ||
3267 			sy + height > info->var.yres_virtual)
3268 		return;
3269 
3270 	if (dy > sy || (dy == sy && dx > sx)) {
3271 		dy += height;
3272 		sy += height;
3273 		rev_copy = 1;
3274 	}
3275 	dst = (unsigned long *)
3276 		((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
3277 	src = dst;
3278 	dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
3279 	src_idx = dst_idx;
3280 	dst_idx += dy * par->next_line * 8 + dx;
3281 	src_idx += sy * par->next_line * 8 + sx;
3282 	if (rev_copy) {
3283 		while (height--) {
3284 			dst_idx -= par->next_line * 8;
3285 			src_idx -= par->next_line * 8;
3286 			copy_one_line_rev(info->var.bits_per_pixel,
3287 					  par->next_plane, dst, dst_idx, src,
3288 					  src_idx, width);
3289 		}
3290 	} else {
3291 		while (height--) {
3292 			copy_one_line(info->var.bits_per_pixel,
3293 				      par->next_plane, dst, dst_idx, src,
3294 				      src_idx, width);
3295 			dst_idx += par->next_line * 8;
3296 			src_idx += par->next_line * 8;
3297 		}
3298 	}
3299 }
3300 
3301 
3302 static inline void expand_one_line(int bpp, unsigned long next_plane,
3303 				   unsigned long *dst, int dst_idx, u32 n,
3304 				   const u8 *data, u32 bgcolor, u32 fgcolor)
3305 {
3306 	const unsigned long *src;
3307 	int src_idx;
3308 
3309 	while (1) {
3310 		dst += dst_idx >> SHIFT_PER_LONG;
3311 		dst_idx &= (BITS_PER_LONG - 1);
3312 		if ((bgcolor ^ fgcolor) & 1) {
3313 			src = (unsigned long *)
3314 				((unsigned long)data & ~(BYTES_PER_LONG - 1));
3315 			src_idx = ((unsigned long)data & (BYTES_PER_LONG - 1)) * 8;
3316 			if (fgcolor & 1)
3317 				bitcpy(dst, dst_idx, src, src_idx, n);
3318 			else
3319 				bitcpy_not(dst, dst_idx, src, src_idx, n);
3320 			/* set or clear */
3321 		} else
3322 			bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n);
3323 		if (!--bpp)
3324 			break;
3325 		bgcolor >>= 1;
3326 		fgcolor >>= 1;
3327 		dst_idx += next_plane * 8;
3328 	}
3329 }
3330 
3331 
3332 static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
3333 {
3334 	struct amifb_par *par = info->par;
3335 	int x2, y2;
3336 	unsigned long *dst;
3337 	int dst_idx;
3338 	const char *src;
3339 	u32 dx, dy, width, height, pitch;
3340 
3341 	/*
3342 	 * We could use hardware clipping but on many cards you get around
3343 	 * hardware clipping by writing to framebuffer directly like we are
3344 	 * doing here.
3345 	 */
3346 	x2 = image->dx + image->width;
3347 	y2 = image->dy + image->height;
3348 	dx = image->dx;
3349 	dy = image->dy;
3350 	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
3351 	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
3352 	width  = x2 - dx;
3353 	height = y2 - dy;
3354 
3355 	if (image->depth == 1) {
3356 		dst = (unsigned long *)
3357 			((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
3358 		dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
3359 		dst_idx += dy * par->next_line * 8 + dx;
3360 		src = image->data;
3361 		pitch = (image->width + 7) / 8;
3362 		while (height--) {
3363 			expand_one_line(info->var.bits_per_pixel,
3364 					par->next_plane, dst, dst_idx, width,
3365 					src, image->bg_color,
3366 					image->fg_color);
3367 			dst_idx += par->next_line * 8;
3368 			src += pitch;
3369 		}
3370 	} else {
3371 		c2p_planar(info->screen_base, image->data, dx, dy, width,
3372 			   height, par->next_line, par->next_plane,
3373 			   image->width, info->var.bits_per_pixel);
3374 	}
3375 }
3376 
3377 
3378 	/*
3379 	 * Amiga Frame Buffer Specific ioctls
3380 	 */
3381 
3382 static int amifb_ioctl(struct fb_info *info,
3383 		       unsigned int cmd, unsigned long arg)
3384 {
3385 	union {
3386 		struct fb_fix_cursorinfo fix;
3387 		struct fb_var_cursorinfo var;
3388 		struct fb_cursorstate state;
3389 	} crsr;
3390 	void __user *argp = (void __user *)arg;
3391 	int i;
3392 
3393 	switch (cmd) {
3394 	case FBIOGET_FCURSORINFO:
3395 		i = ami_get_fix_cursorinfo(&crsr.fix, info->par);
3396 		if (i)
3397 			return i;
3398 		return copy_to_user(argp, &crsr.fix,
3399 				    sizeof(crsr.fix)) ? -EFAULT : 0;
3400 
3401 	case FBIOGET_VCURSORINFO:
3402 		i = ami_get_var_cursorinfo(&crsr.var,
3403 			((struct fb_var_cursorinfo __user *)arg)->data,
3404 			info->par);
3405 		if (i)
3406 			return i;
3407 		return copy_to_user(argp, &crsr.var,
3408 				    sizeof(crsr.var)) ? -EFAULT : 0;
3409 
3410 	case FBIOPUT_VCURSORINFO:
3411 		if (copy_from_user(&crsr.var, argp, sizeof(crsr.var)))
3412 			return -EFAULT;
3413 		return ami_set_var_cursorinfo(&crsr.var,
3414 			((struct fb_var_cursorinfo __user *)arg)->data,
3415 			info->par);
3416 
3417 	case FBIOGET_CURSORSTATE:
3418 		i = ami_get_cursorstate(&crsr.state, info->par);
3419 		if (i)
3420 			return i;
3421 		return copy_to_user(argp, &crsr.state,
3422 				    sizeof(crsr.state)) ? -EFAULT : 0;
3423 
3424 	case FBIOPUT_CURSORSTATE:
3425 		if (copy_from_user(&crsr.state, argp, sizeof(crsr.state)))
3426 			return -EFAULT;
3427 		return ami_set_cursorstate(&crsr.state, info->par);
3428 	}
3429 	return -EINVAL;
3430 }
3431 
3432 
3433 	/*
3434 	 * Flash the cursor (called by VBlank interrupt)
3435 	 */
3436 
3437 static int flash_cursor(void)
3438 {
3439 	static int cursorcount = 1;
3440 
3441 	if (cursormode == FB_CURSOR_FLASH) {
3442 		if (!--cursorcount) {
3443 			cursorstate = -cursorstate;
3444 			cursorcount = cursorrate;
3445 			if (!is_blanked)
3446 				return 1;
3447 		}
3448 	}
3449 	return 0;
3450 }
3451 
3452 	/*
3453 	 * VBlank Display Interrupt
3454 	 */
3455 
3456 static irqreturn_t amifb_interrupt(int irq, void *dev_id)
3457 {
3458 	struct amifb_par *par = dev_id;
3459 
3460 	if (do_vmode_pan || do_vmode_full)
3461 		ami_update_display(par);
3462 
3463 	if (do_vmode_full)
3464 		ami_init_display(par);
3465 
3466 	if (do_vmode_pan) {
3467 		flash_cursor();
3468 		ami_rebuild_copper(par);
3469 		do_cursor = do_vmode_pan = 0;
3470 	} else if (do_cursor) {
3471 		flash_cursor();
3472 		ami_set_sprite(par);
3473 		do_cursor = 0;
3474 	} else {
3475 		if (flash_cursor())
3476 			ami_set_sprite(par);
3477 	}
3478 
3479 	if (do_blank) {
3480 		ami_do_blank(par);
3481 		do_blank = 0;
3482 	}
3483 
3484 	if (do_vmode_full) {
3485 		ami_reinit_copper(par);
3486 		do_vmode_full = 0;
3487 	}
3488 	return IRQ_HANDLED;
3489 }
3490 
3491 
3492 static const struct fb_ops amifb_ops = {
3493 	.owner		= THIS_MODULE,
3494 	.fb_check_var	= amifb_check_var,
3495 	.fb_set_par	= amifb_set_par,
3496 	.fb_setcolreg	= amifb_setcolreg,
3497 	.fb_blank	= amifb_blank,
3498 	.fb_pan_display	= amifb_pan_display,
3499 	.fb_fillrect	= amifb_fillrect,
3500 	.fb_copyarea	= amifb_copyarea,
3501 	.fb_imageblit	= amifb_imageblit,
3502 	.fb_ioctl	= amifb_ioctl,
3503 };
3504 
3505 
3506 	/*
3507 	 * Allocate, Clear and Align a Block of Chip Memory
3508 	 */
3509 
3510 static void *aligned_chipptr;
3511 
3512 static inline u_long __init chipalloc(u_long size)
3513 {
3514 	aligned_chipptr = amiga_chip_alloc(size, "amifb [RAM]");
3515 	if (!aligned_chipptr) {
3516 		pr_err("amifb: No Chip RAM for frame buffer");
3517 		return 0;
3518 	}
3519 	memset(aligned_chipptr, 0, size);
3520 	return (u_long)aligned_chipptr;
3521 }
3522 
3523 static inline void chipfree(void)
3524 {
3525 	if (aligned_chipptr)
3526 		amiga_chip_free(aligned_chipptr);
3527 }
3528 
3529 
3530 	/*
3531 	 * Initialisation
3532 	 */
3533 
3534 static int __init amifb_probe(struct platform_device *pdev)
3535 {
3536 	struct fb_info *info;
3537 	int tag, i, err = 0;
3538 	u_long chipptr;
3539 	u_int defmode;
3540 
3541 #ifndef MODULE
3542 	char *option = NULL;
3543 
3544 	if (fb_get_options("amifb", &option)) {
3545 		amifb_video_off();
3546 		return -ENODEV;
3547 	}
3548 	amifb_setup(option);
3549 #endif
3550 	custom.dmacon = DMAF_ALL | DMAF_MASTER;
3551 
3552 	info = framebuffer_alloc(sizeof(struct amifb_par), &pdev->dev);
3553 	if (!info)
3554 		return -ENOMEM;
3555 
3556 	strcpy(info->fix.id, "Amiga ");
3557 	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
3558 	info->fix.accel = FB_ACCEL_AMIGABLITT;
3559 
3560 	switch (amiga_chipset) {
3561 #ifdef CONFIG_FB_AMIGA_OCS
3562 	case CS_OCS:
3563 		strcat(info->fix.id, "OCS");
3564 default_chipset:
3565 		chipset = TAG_OCS;
3566 		maxdepth[TAG_SHRES] = 0;	/* OCS means no SHRES */
3567 		maxdepth[TAG_HIRES] = 4;
3568 		maxdepth[TAG_LORES] = 6;
3569 		maxfmode = TAG_FMODE_1;
3570 		defmode = amiga_vblank == 50 ? DEFMODE_PAL : DEFMODE_NTSC;
3571 		info->fix.smem_len = VIDEOMEMSIZE_OCS;
3572 		break;
3573 #endif /* CONFIG_FB_AMIGA_OCS */
3574 
3575 #ifdef CONFIG_FB_AMIGA_ECS
3576 	case CS_ECS:
3577 		strcat(info->fix.id, "ECS");
3578 		chipset = TAG_ECS;
3579 		maxdepth[TAG_SHRES] = 2;
3580 		maxdepth[TAG_HIRES] = 4;
3581 		maxdepth[TAG_LORES] = 6;
3582 		maxfmode = TAG_FMODE_1;
3583 		if (AMIGAHW_PRESENT(AMBER_FF))
3584 			defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL
3585 						     : DEFMODE_AMBER_NTSC;
3586 		else
3587 			defmode = amiga_vblank == 50 ? DEFMODE_PAL
3588 						     : DEFMODE_NTSC;
3589 		if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
3590 		    VIDEOMEMSIZE_ECS_2M)
3591 			info->fix.smem_len = VIDEOMEMSIZE_ECS_2M;
3592 		else
3593 			info->fix.smem_len = VIDEOMEMSIZE_ECS_1M;
3594 		break;
3595 #endif /* CONFIG_FB_AMIGA_ECS */
3596 
3597 #ifdef CONFIG_FB_AMIGA_AGA
3598 	case CS_AGA:
3599 		strcat(info->fix.id, "AGA");
3600 		chipset = TAG_AGA;
3601 		maxdepth[TAG_SHRES] = 8;
3602 		maxdepth[TAG_HIRES] = 8;
3603 		maxdepth[TAG_LORES] = 8;
3604 		maxfmode = TAG_FMODE_4;
3605 		defmode = DEFMODE_AGA;
3606 		if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
3607 		    VIDEOMEMSIZE_AGA_2M)
3608 			info->fix.smem_len = VIDEOMEMSIZE_AGA_2M;
3609 		else
3610 			info->fix.smem_len = VIDEOMEMSIZE_AGA_1M;
3611 		break;
3612 #endif /* CONFIG_FB_AMIGA_AGA */
3613 
3614 	default:
3615 #ifdef CONFIG_FB_AMIGA_OCS
3616 		printk("Unknown graphics chipset, defaulting to OCS\n");
3617 		strcat(info->fix.id, "Unknown");
3618 		goto default_chipset;
3619 #else /* CONFIG_FB_AMIGA_OCS */
3620 		err = -ENODEV;
3621 		goto release;
3622 #endif /* CONFIG_FB_AMIGA_OCS */
3623 		break;
3624 	}
3625 
3626 	/*
3627 	 * Calculate the Pixel Clock Values for this Machine
3628 	 */
3629 
3630 	{
3631 	u_long tmp = DIVUL(200000000000ULL, amiga_eclock);
3632 
3633 	pixclock[TAG_SHRES] = (tmp + 4) / 8;	/* SHRES:  35 ns / 28 MHz */
3634 	pixclock[TAG_HIRES] = (tmp + 2) / 4;	/* HIRES:  70 ns / 14 MHz */
3635 	pixclock[TAG_LORES] = (tmp + 1) / 2;	/* LORES: 140 ns /  7 MHz */
3636 	}
3637 
3638 	/*
3639 	 * Replace the Tag Values with the Real Pixel Clock Values
3640 	 */
3641 
3642 	for (i = 0; i < NUM_TOTAL_MODES; i++) {
3643 		struct fb_videomode *mode = &ami_modedb[i];
3644 		tag = mode->pixclock;
3645 		if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) {
3646 			mode->pixclock = pixclock[tag];
3647 		}
3648 	}
3649 
3650 	if (amifb_hfmin) {
3651 		info->monspecs.hfmin = amifb_hfmin;
3652 		info->monspecs.hfmax = amifb_hfmax;
3653 		info->monspecs.vfmin = amifb_vfmin;
3654 		info->monspecs.vfmax = amifb_vfmax;
3655 	} else {
3656 		/*
3657 		 *  These are for a typical Amiga monitor (e.g. A1960)
3658 		 */
3659 		info->monspecs.hfmin = 15000;
3660 		info->monspecs.hfmax = 38000;
3661 		info->monspecs.vfmin = 49;
3662 		info->monspecs.vfmax = 90;
3663 	}
3664 
3665 	info->fbops = &amifb_ops;
3666 	info->flags = FBINFO_DEFAULT;
3667 	info->device = &pdev->dev;
3668 
3669 	if (!fb_find_mode(&info->var, info, mode_option, ami_modedb,
3670 			  NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
3671 		err = -EINVAL;
3672 		goto release;
3673 	}
3674 
3675 	fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES,
3676 				 &info->modelist);
3677 
3678 	round_down_bpp = 0;
3679 	chipptr = chipalloc(info->fix.smem_len + SPRITEMEMSIZE +
3680 			    DUMMYSPRITEMEMSIZE + COPINITSIZE +
3681 			    4 * COPLISTSIZE);
3682 	if (!chipptr) {
3683 		err = -ENOMEM;
3684 		goto release;
3685 	}
3686 
3687 	assignchunk(videomemory, u_long, chipptr, info->fix.smem_len);
3688 	assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE);
3689 	assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE);
3690 	assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE);
3691 	assignchunk(copdisplay.list[0][0], copins *, chipptr, COPLISTSIZE);
3692 	assignchunk(copdisplay.list[0][1], copins *, chipptr, COPLISTSIZE);
3693 	assignchunk(copdisplay.list[1][0], copins *, chipptr, COPLISTSIZE);
3694 	assignchunk(copdisplay.list[1][1], copins *, chipptr, COPLISTSIZE);
3695 
3696 	/*
3697 	 * access the videomem with writethrough cache
3698 	 */
3699 	info->fix.smem_start = (u_long)ZTWO_PADDR(videomemory);
3700 	videomemory = (u_long)ioremap_wt(info->fix.smem_start,
3701 					 info->fix.smem_len);
3702 	if (!videomemory) {
3703 		dev_warn(&pdev->dev,
3704 			 "Unable to map videomem cached writethrough\n");
3705 		info->screen_base = ZTWO_VADDR(info->fix.smem_start);
3706 	} else
3707 		info->screen_base = (char *)videomemory;
3708 
3709 	memset(dummysprite, 0, DUMMYSPRITEMEMSIZE);
3710 
3711 	/*
3712 	 * Make sure the Copper has something to do
3713 	 */
3714 	ami_init_copper();
3715 
3716 	/*
3717 	 * Enable Display DMA
3718 	 */
3719 	custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
3720 			DMAF_BLITTER | DMAF_SPRITE;
3721 
3722 	err = request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0,
3723 			  "fb vertb handler", info->par);
3724 	if (err)
3725 		goto disable_dma;
3726 
3727 	err = fb_alloc_cmap(&info->cmap, 1 << info->var.bits_per_pixel, 0);
3728 	if (err)
3729 		goto free_irq;
3730 
3731 	dev_set_drvdata(&pdev->dev, info);
3732 
3733 	err = register_framebuffer(info);
3734 	if (err)
3735 		goto unset_drvdata;
3736 
3737 	fb_info(info, "%s frame buffer device, using %dK of video memory\n",
3738 		info->fix.id, info->fix.smem_len>>10);
3739 
3740 	return 0;
3741 
3742 unset_drvdata:
3743 	fb_dealloc_cmap(&info->cmap);
3744 free_irq:
3745 	free_irq(IRQ_AMIGA_COPPER, info->par);
3746 disable_dma:
3747 	custom.dmacon = DMAF_ALL | DMAF_MASTER;
3748 	if (videomemory)
3749 		iounmap((void *)videomemory);
3750 	chipfree();
3751 release:
3752 	framebuffer_release(info);
3753 	return err;
3754 }
3755 
3756 
3757 static int __exit amifb_remove(struct platform_device *pdev)
3758 {
3759 	struct fb_info *info = dev_get_drvdata(&pdev->dev);
3760 
3761 	unregister_framebuffer(info);
3762 	fb_dealloc_cmap(&info->cmap);
3763 	free_irq(IRQ_AMIGA_COPPER, info->par);
3764 	custom.dmacon = DMAF_ALL | DMAF_MASTER;
3765 	if (videomemory)
3766 		iounmap((void *)videomemory);
3767 	chipfree();
3768 	framebuffer_release(info);
3769 	amifb_video_off();
3770 	return 0;
3771 }
3772 
3773 static struct platform_driver amifb_driver = {
3774 	.remove = __exit_p(amifb_remove),
3775 	.driver   = {
3776 		.name	= "amiga-video",
3777 	},
3778 };
3779 
3780 module_platform_driver_probe(amifb_driver, amifb_probe);
3781 
3782 MODULE_LICENSE("GPL");
3783 MODULE_ALIAS("platform:amiga-video");
3784