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