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