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