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