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