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