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