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