Automatic merge with /usr/src/ntfs-2.6.git.
[linux-2.6] / 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, "ilbm"))
1243                         amifb_ilbm = 1;
1244                 else if (!strncmp(this_opt, "monitorcap:", 11))
1245                         amifb_setup_mcap(this_opt+11);
1246                 else if (!strncmp(this_opt, "fstart:", 7))
1247                         min_fstrt = simple_strtoul(this_opt+7, NULL, 0);
1248                 else
1249                         mode_option = this_opt;
1250         }
1251
1252         if (min_fstrt < 48)
1253                 min_fstrt = 48;
1254
1255         return 0;
1256 }
1257
1258
1259 static int amifb_check_var(struct fb_var_screeninfo *var,
1260                            struct fb_info *info)
1261 {
1262         int err;
1263         struct amifb_par par;
1264
1265         /* Validate wanted screen parameters */
1266         if ((err = ami_decode_var(var, &par)))
1267                 return err;
1268
1269         /* Encode (possibly rounded) screen parameters */
1270         ami_encode_var(var, &par);
1271         return 0;
1272 }
1273
1274
1275 static int amifb_set_par(struct fb_info *info)
1276 {
1277         struct amifb_par *par = (struct amifb_par *)info->par;
1278
1279         do_vmode_pan = 0;
1280         do_vmode_full = 0;
1281
1282         /* Decode wanted screen parameters */
1283         ami_decode_var(&info->var, par);
1284
1285         /* Set new videomode */
1286         ami_build_copper();
1287
1288         /* Set VBlank trigger */
1289         do_vmode_full = 1;
1290
1291         /* Update fix for new screen parameters */
1292         if (par->bpp == 1) {
1293                 info->fix.type = FB_TYPE_PACKED_PIXELS;
1294                 info->fix.type_aux = 0;
1295         } else if (amifb_ilbm) {
1296                 info->fix.type = FB_TYPE_INTERLEAVED_PLANES;
1297                 info->fix.type_aux = par->next_line;
1298         } else {
1299                 info->fix.type = FB_TYPE_PLANES;
1300                 info->fix.type_aux = 0;
1301         }
1302         info->fix.line_length = div8(upx(16<<maxfmode, par->vxres));
1303
1304         if (par->vmode & FB_VMODE_YWRAP) {
1305                 info->fix.ywrapstep = 1;
1306                 info->fix.xpanstep = 0;
1307                 info->fix.ypanstep = 0;
1308                 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP |
1309                     FBINFO_READS_FAST; /* override SCROLL_REDRAW */
1310         } else {
1311                 info->fix.ywrapstep = 0;
1312                 if (par->vmode & FB_VMODE_SMOOTH_XPAN)
1313                         info->fix.xpanstep = 1;
1314                 else
1315                         info->fix.xpanstep = 16<<maxfmode;
1316                 info->fix.ypanstep = 1;
1317                 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1318         }
1319         return 0;
1320 }
1321
1322
1323         /*
1324          * Pan or Wrap the Display
1325          *
1326          * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
1327          */
1328
1329 static int amifb_pan_display(struct fb_var_screeninfo *var,
1330                              struct fb_info *info)
1331 {
1332         if (var->vmode & FB_VMODE_YWRAP) {
1333                 if (var->yoffset < 0 ||
1334                     var->yoffset >= info->var.yres_virtual || var->xoffset)
1335                         return -EINVAL;
1336         } else {
1337                 /*
1338                  * TODO: There will be problems when xpan!=1, so some columns
1339                  * on the right side will never be seen
1340                  */
1341                 if (var->xoffset+info->var.xres > upx(16<<maxfmode, info->var.xres_virtual) ||
1342                     var->yoffset+info->var.yres > info->var.yres_virtual)
1343                         return -EINVAL;
1344         }
1345         ami_pan_var(var);
1346         info->var.xoffset = var->xoffset;
1347         info->var.yoffset = var->yoffset;
1348         if (var->vmode & FB_VMODE_YWRAP)
1349                 info->var.vmode |= FB_VMODE_YWRAP;
1350         else
1351                 info->var.vmode &= ~FB_VMODE_YWRAP;
1352         return 0;
1353 }
1354
1355
1356 #if BITS_PER_LONG == 32
1357 #define BYTES_PER_LONG  4
1358 #define SHIFT_PER_LONG  5
1359 #elif BITS_PER_LONG == 64
1360 #define BYTES_PER_LONG  8
1361 #define SHIFT_PER_LONG  6
1362 #else
1363 #define Please update me
1364 #endif
1365
1366
1367     /*
1368      *  Compose two values, using a bitmask as decision value
1369      *  This is equivalent to (a & mask) | (b & ~mask)
1370      */
1371
1372 static inline unsigned long comp(unsigned long a, unsigned long b,
1373                                  unsigned long mask)
1374 {
1375         return ((a ^ b) & mask) ^ b;
1376 }
1377
1378
1379 static inline unsigned long xor(unsigned long a, unsigned long b,
1380                                 unsigned long mask)
1381 {
1382         return (a & mask) ^ b;
1383 }
1384
1385
1386     /*
1387      *  Unaligned forward bit copy using 32-bit or 64-bit memory accesses
1388      */
1389
1390 static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
1391                    int src_idx, u32 n)
1392 {
1393         unsigned long first, last;
1394         int shift = dst_idx-src_idx, left, right;
1395         unsigned long d0, d1;
1396         int m;
1397
1398         if (!n)
1399                 return;
1400
1401         shift = dst_idx-src_idx;
1402         first = ~0UL >> dst_idx;
1403         last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
1404
1405         if (!shift) {
1406                 // Same alignment for source and dest
1407
1408                 if (dst_idx+n <= BITS_PER_LONG) {
1409                         // Single word
1410                         if (last)
1411                                 first &= last;
1412                         *dst = comp(*src, *dst, first);
1413                 } else {
1414                         // Multiple destination words
1415                         // Leading bits
1416                         if (first) {
1417                                 *dst = comp(*src, *dst, first);
1418                                 dst++;
1419                                 src++;
1420                                 n -= BITS_PER_LONG-dst_idx;
1421                         }
1422
1423                         // Main chunk
1424                         n /= BITS_PER_LONG;
1425                         while (n >= 8) {
1426                                 *dst++ = *src++;
1427                                 *dst++ = *src++;
1428                                 *dst++ = *src++;
1429                                 *dst++ = *src++;
1430                                 *dst++ = *src++;
1431                                 *dst++ = *src++;
1432                                 *dst++ = *src++;
1433                                 *dst++ = *src++;
1434                                 n -= 8;
1435                         }
1436                         while (n--)
1437                                 *dst++ = *src++;
1438
1439                         // Trailing bits
1440                         if (last)
1441                                 *dst = comp(*src, *dst, last);
1442                 }
1443         } else {
1444                 // Different alignment for source and dest
1445
1446                 right = shift & (BITS_PER_LONG-1);
1447                 left = -shift & (BITS_PER_LONG-1);
1448
1449                 if (dst_idx+n <= BITS_PER_LONG) {
1450                         // Single destination word
1451                         if (last)
1452                                 first &= last;
1453                         if (shift > 0) {
1454                                 // Single source word
1455                                 *dst = comp(*src >> right, *dst, first);
1456                         } else if (src_idx+n <= BITS_PER_LONG) {
1457                                 // Single source word
1458                                 *dst = comp(*src << left, *dst, first);
1459                         } else {
1460                                 // 2 source words
1461                                 d0 = *src++;
1462                                 d1 = *src;
1463                                 *dst = comp(d0 << left | d1 >> right, *dst,
1464                                             first);
1465                         }
1466                 } else {
1467                         // Multiple destination words
1468                         d0 = *src++;
1469                         // Leading bits
1470                         if (shift > 0) {
1471                                 // Single source word
1472                                 *dst = comp(d0 >> right, *dst, first);
1473                                 dst++;
1474                                 n -= BITS_PER_LONG-dst_idx;
1475                         } else {
1476                                 // 2 source words
1477                                 d1 = *src++;
1478                                 *dst = comp(d0 << left | d1 >> right, *dst,
1479                                             first);
1480                                 d0 = d1;
1481                                 dst++;
1482                                 n -= BITS_PER_LONG-dst_idx;
1483                         }
1484
1485                         // Main chunk
1486                         m = n % BITS_PER_LONG;
1487                         n /= BITS_PER_LONG;
1488                         while (n >= 4) {
1489                                 d1 = *src++;
1490                                 *dst++ = d0 << left | d1 >> right;
1491                                 d0 = d1;
1492                                 d1 = *src++;
1493                                 *dst++ = d0 << left | d1 >> right;
1494                                 d0 = d1;
1495                                 d1 = *src++;
1496                                 *dst++ = d0 << left | d1 >> right;
1497                                 d0 = d1;
1498                                 d1 = *src++;
1499                                 *dst++ = d0 << left | d1 >> right;
1500                                 d0 = d1;
1501                                 n -= 4;
1502                         }
1503                         while (n--) {
1504                                 d1 = *src++;
1505                                 *dst++ = d0 << left | d1 >> right;
1506                                 d0 = d1;
1507                         }
1508
1509                         // Trailing bits
1510                         if (last) {
1511                                 if (m <= right) {
1512                                         // Single source word
1513                                         *dst = comp(d0 << left, *dst, last);
1514                                 } else {
1515                                         // 2 source words
1516                                         d1 = *src;
1517                                         *dst = comp(d0 << left | d1 >> right,
1518                                                     *dst, last);
1519                                 }
1520                         }
1521                 }
1522         }
1523 }
1524
1525
1526     /*
1527      *  Unaligned reverse bit copy using 32-bit or 64-bit memory accesses
1528      */
1529
1530 static void bitcpy_rev(unsigned long *dst, int dst_idx,
1531                        const unsigned long *src, int src_idx, u32 n)
1532 {
1533         unsigned long first, last;
1534         int shift = dst_idx-src_idx, left, right;
1535         unsigned long d0, d1;
1536         int m;
1537
1538         if (!n)
1539                 return;
1540
1541         dst += (n-1)/BITS_PER_LONG;
1542         src += (n-1)/BITS_PER_LONG;
1543         if ((n-1) % BITS_PER_LONG) {
1544                 dst_idx += (n-1) % BITS_PER_LONG;
1545                 dst += dst_idx >> SHIFT_PER_LONG;
1546                 dst_idx &= BITS_PER_LONG-1;
1547                 src_idx += (n-1) % BITS_PER_LONG;
1548                 src += src_idx >> SHIFT_PER_LONG;
1549                 src_idx &= BITS_PER_LONG-1;
1550         }
1551
1552         shift = dst_idx-src_idx;
1553         first = ~0UL << (BITS_PER_LONG-1-dst_idx);
1554         last = ~(~0UL << (BITS_PER_LONG-1-((dst_idx-n) % BITS_PER_LONG)));
1555
1556         if (!shift) {
1557                 // Same alignment for source and dest
1558
1559                 if ((unsigned long)dst_idx+1 >= n) {
1560                         // Single word
1561                         if (last)
1562                                 first &= last;
1563                         *dst = comp(*src, *dst, first);
1564                 } else {
1565                         // Multiple destination words
1566                         // Leading bits
1567                         if (first) {
1568                                 *dst = comp(*src, *dst, first);
1569                                 dst--;
1570                                 src--;
1571                                 n -= dst_idx+1;
1572                         }
1573
1574                         // Main chunk
1575                         n /= BITS_PER_LONG;
1576                         while (n >= 8) {
1577                                 *dst-- = *src--;
1578                                 *dst-- = *src--;
1579                                 *dst-- = *src--;
1580                                 *dst-- = *src--;
1581                                 *dst-- = *src--;
1582                                 *dst-- = *src--;
1583                                 *dst-- = *src--;
1584                                 *dst-- = *src--;
1585                                 n -= 8;
1586                         }
1587                         while (n--)
1588                                 *dst-- = *src--;
1589
1590                         // Trailing bits
1591                         if (last)
1592                                 *dst = comp(*src, *dst, last);
1593                 }
1594         } else {
1595                 // Different alignment for source and dest
1596
1597                 right = shift & (BITS_PER_LONG-1);
1598                 left = -shift & (BITS_PER_LONG-1);
1599
1600                 if ((unsigned long)dst_idx+1 >= n) {
1601                         // Single destination word
1602                         if (last)
1603                                 first &= last;
1604                         if (shift < 0) {
1605                                 // Single source word
1606                                 *dst = comp(*src << left, *dst, first);
1607                         } else if (1+(unsigned long)src_idx >= n) {
1608                                 // Single source word
1609                                 *dst = comp(*src >> right, *dst, first);
1610                         } else {
1611                                 // 2 source words
1612                                 d0 = *src--;
1613                                 d1 = *src;
1614                                 *dst = comp(d0 >> right | d1 << left, *dst,
1615                                             first);
1616                         }
1617                 } else {
1618                         // Multiple destination words
1619                         d0 = *src--;
1620                         // Leading bits
1621                         if (shift < 0) {
1622                                 // Single source word
1623                                 *dst = comp(d0 << left, *dst, first);
1624                                 dst--;
1625                                 n -= dst_idx+1;
1626                         } else {
1627                                 // 2 source words
1628                                 d1 = *src--;
1629                                 *dst = comp(d0 >> right | d1 << left, *dst,
1630                                             first);
1631                                 d0 = d1;
1632                                 dst--;
1633                                 n -= dst_idx+1;
1634                         }
1635
1636                         // Main chunk
1637                         m = n % BITS_PER_LONG;
1638                         n /= BITS_PER_LONG;
1639                         while (n >= 4) {
1640                                 d1 = *src--;
1641                                 *dst-- = d0 >> right | d1 << left;
1642                                 d0 = d1;
1643                                 d1 = *src--;
1644                                 *dst-- = d0 >> right | d1 << left;
1645                                 d0 = d1;
1646                                 d1 = *src--;
1647                                 *dst-- = d0 >> right | d1 << left;
1648                                 d0 = d1;
1649                                 d1 = *src--;
1650                                 *dst-- = d0 >> right | d1 << left;
1651                                 d0 = d1;
1652                                 n -= 4;
1653                         }
1654                         while (n--) {
1655                                 d1 = *src--;
1656                                 *dst-- = d0 >> right | d1 << left;
1657                                 d0 = d1;
1658                         }
1659
1660                         // Trailing bits
1661                         if (last) {
1662                                 if (m <= left) {
1663                                         // Single source word
1664                                         *dst = comp(d0 >> right, *dst, last);
1665                                 } else {
1666                                         // 2 source words
1667                                         d1 = *src;
1668                                         *dst = comp(d0 >> right | d1 << left,
1669                                                     *dst, last);
1670                                 }
1671                         }
1672                 }
1673         }
1674 }
1675
1676
1677     /*
1678      *  Unaligned forward inverting bit copy using 32-bit or 64-bit memory
1679      *  accesses
1680      */
1681
1682 static void bitcpy_not(unsigned long *dst, int dst_idx,
1683                        const unsigned long *src, int src_idx, u32 n)
1684 {
1685         unsigned long first, last;
1686         int shift = dst_idx-src_idx, left, right;
1687         unsigned long d0, d1;
1688         int m;
1689
1690         if (!n)
1691                 return;
1692
1693         shift = dst_idx-src_idx;
1694         first = ~0UL >> dst_idx;
1695         last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
1696
1697         if (!shift) {
1698                 // Same alignment for source and dest
1699
1700                 if (dst_idx+n <= BITS_PER_LONG) {
1701                         // Single word
1702                         if (last)
1703                                 first &= last;
1704                         *dst = comp(~*src, *dst, first);
1705                 } else {
1706                         // Multiple destination words
1707                         // Leading bits
1708                         if (first) {
1709                                 *dst = comp(~*src, *dst, first);
1710                                 dst++;
1711                                 src++;
1712                                 n -= BITS_PER_LONG-dst_idx;
1713                         }
1714
1715                         // Main chunk
1716                         n /= BITS_PER_LONG;
1717                         while (n >= 8) {
1718                                 *dst++ = ~*src++;
1719                                 *dst++ = ~*src++;
1720                                 *dst++ = ~*src++;
1721                                 *dst++ = ~*src++;
1722                                 *dst++ = ~*src++;
1723                                 *dst++ = ~*src++;
1724                                 *dst++ = ~*src++;
1725                                 *dst++ = ~*src++;
1726                                 n -= 8;
1727                         }
1728                         while (n--)
1729                                 *dst++ = ~*src++;
1730
1731                         // Trailing bits
1732                         if (last)
1733                                 *dst = comp(~*src, *dst, last);
1734                 }
1735         } else {
1736                 // Different alignment for source and dest
1737
1738                 right = shift & (BITS_PER_LONG-1);
1739                 left = -shift & (BITS_PER_LONG-1);
1740
1741                 if (dst_idx+n <= BITS_PER_LONG) {
1742                         // Single destination word
1743                         if (last)
1744                                 first &= last;
1745                         if (shift > 0) {
1746                                 // Single source word
1747                                 *dst = comp(~*src >> right, *dst, first);
1748                         } else if (src_idx+n <= BITS_PER_LONG) {
1749                                 // Single source word
1750                                 *dst = comp(~*src << left, *dst, first);
1751                         } else {
1752                                 // 2 source words
1753                                 d0 = ~*src++;
1754                                 d1 = ~*src;
1755                                 *dst = comp(d0 << left | d1 >> right, *dst,
1756                                             first);
1757                         }
1758                 } else {
1759                         // Multiple destination words
1760                         d0 = ~*src++;
1761                         // Leading bits
1762                         if (shift > 0) {
1763                                 // Single source word
1764                                 *dst = comp(d0 >> right, *dst, first);
1765                                 dst++;
1766                                 n -= BITS_PER_LONG-dst_idx;
1767                         } else {
1768                                 // 2 source words
1769                                 d1 = ~*src++;
1770                                 *dst = comp(d0 << left | d1 >> right, *dst,
1771                                             first);
1772                                 d0 = d1;
1773                                 dst++;
1774                                 n -= BITS_PER_LONG-dst_idx;
1775                         }
1776
1777                         // Main chunk
1778                         m = n % BITS_PER_LONG;
1779                         n /= BITS_PER_LONG;
1780                         while (n >= 4) {
1781                                 d1 = ~*src++;
1782                                 *dst++ = d0 << left | d1 >> right;
1783                                 d0 = d1;
1784                                 d1 = ~*src++;
1785                                 *dst++ = d0 << left | d1 >> right;
1786                                 d0 = d1;
1787                                 d1 = ~*src++;
1788                                 *dst++ = d0 << left | d1 >> right;
1789                                 d0 = d1;
1790                                 d1 = ~*src++;
1791                                 *dst++ = d0 << left | d1 >> right;
1792                                 d0 = d1;
1793                                 n -= 4;
1794                         }
1795                         while (n--) {
1796                                 d1 = ~*src++;
1797                                 *dst++ = d0 << left | d1 >> right;
1798                                 d0 = d1;
1799                         }
1800
1801                         // Trailing bits
1802                         if (last) {
1803                                 if (m <= right) {
1804                                         // Single source word
1805                                         *dst = comp(d0 << left, *dst, last);
1806                                 } else {
1807                                         // 2 source words
1808                                         d1 = ~*src;
1809                                         *dst = comp(d0 << left | d1 >> right,
1810                                                     *dst, last);
1811                                 }
1812                         }
1813                 }
1814         }
1815 }
1816
1817
1818     /*
1819      *  Unaligned 32-bit pattern fill using 32/64-bit memory accesses
1820      */
1821
1822 static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
1823 {
1824         unsigned long val = pat;
1825         unsigned long first, last;
1826
1827         if (!n)
1828                 return;
1829
1830 #if BITS_PER_LONG == 64
1831         val |= val << 32;
1832 #endif
1833
1834         first = ~0UL >> dst_idx;
1835         last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
1836
1837         if (dst_idx+n <= BITS_PER_LONG) {
1838                 // Single word
1839                 if (last)
1840                         first &= last;
1841                 *dst = comp(val, *dst, first);
1842         } else {
1843                 // Multiple destination words
1844                 // Leading bits
1845                 if (first) {
1846                         *dst = comp(val, *dst, first);
1847                         dst++;
1848                         n -= BITS_PER_LONG-dst_idx;
1849                 }
1850
1851                 // Main chunk
1852                 n /= BITS_PER_LONG;
1853                 while (n >= 8) {
1854                         *dst++ = val;
1855                         *dst++ = val;
1856                         *dst++ = val;
1857                         *dst++ = val;
1858                         *dst++ = val;
1859                         *dst++ = val;
1860                         *dst++ = val;
1861                         *dst++ = val;
1862                         n -= 8;
1863                 }
1864                 while (n--)
1865                         *dst++ = val;
1866
1867                 // Trailing bits
1868                 if (last)
1869                         *dst = comp(val, *dst, last);
1870         }
1871 }
1872
1873
1874     /*
1875      *  Unaligned 32-bit pattern xor using 32/64-bit memory accesses
1876      */
1877
1878 static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
1879 {
1880         unsigned long val = pat;
1881         unsigned long first, last;
1882
1883         if (!n)
1884                 return;
1885
1886 #if BITS_PER_LONG == 64
1887         val |= val << 32;
1888 #endif
1889
1890         first = ~0UL >> dst_idx;
1891         last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
1892
1893         if (dst_idx+n <= BITS_PER_LONG) {
1894                 // Single word
1895                 if (last)
1896                         first &= last;
1897                 *dst = xor(val, *dst, first);
1898         } else {
1899                 // Multiple destination words
1900                 // Leading bits
1901                 if (first) {
1902                         *dst = xor(val, *dst, first);
1903                         dst++;
1904                         n -= BITS_PER_LONG-dst_idx;
1905                 }
1906
1907                 // Main chunk
1908                 n /= BITS_PER_LONG;
1909                 while (n >= 4) {
1910                         *dst++ ^= val;
1911                         *dst++ ^= val;
1912                         *dst++ ^= val;
1913                         *dst++ ^= val;
1914                         n -= 4;
1915                 }
1916                 while (n--)
1917                         *dst++ ^= val;
1918
1919                 // Trailing bits
1920                 if (last)
1921                         *dst = xor(val, *dst, last);
1922         }
1923 }
1924
1925 static inline void fill_one_line(int bpp, unsigned long next_plane,
1926                                  unsigned long *dst, int dst_idx, u32 n,
1927                                  u32 color)
1928 {
1929         while (1) {
1930                 dst += dst_idx >> SHIFT_PER_LONG;
1931                 dst_idx &= (BITS_PER_LONG-1);
1932                 bitfill32(dst, dst_idx, color & 1 ? ~0 : 0, n);
1933                 if (!--bpp)
1934                         break;
1935                 color >>= 1;
1936                 dst_idx += next_plane*8;
1937         }
1938 }
1939
1940 static inline void xor_one_line(int bpp, unsigned long next_plane,
1941                                 unsigned long *dst, int dst_idx, u32 n,
1942                                 u32 color)
1943 {
1944         while (color) {
1945                 dst += dst_idx >> SHIFT_PER_LONG;
1946                 dst_idx &= (BITS_PER_LONG-1);
1947                 bitxor32(dst, dst_idx, color & 1 ? ~0 : 0, n);
1948                 if (!--bpp)
1949                         break;
1950                 color >>= 1;
1951                 dst_idx += next_plane*8;
1952         }
1953 }
1954
1955
1956 static void amifb_fillrect(struct fb_info *info,
1957                            const struct fb_fillrect *rect)
1958 {
1959         struct amifb_par *par = (struct amifb_par *)info->par;
1960         int dst_idx, x2, y2;
1961         unsigned long *dst;
1962         u32 width, height;
1963
1964         if (!rect->width || !rect->height)
1965                 return;
1966
1967         /*
1968          * We could use hardware clipping but on many cards you get around
1969          * hardware clipping by writing to framebuffer directly.
1970          * */
1971         x2 = rect->dx + rect->width;
1972         y2 = rect->dy + rect->height;
1973         x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
1974         y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
1975         width = x2 - rect->dx;
1976         height = y2 - rect->dy;
1977
1978         dst = (unsigned long *)
1979                 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1));
1980         dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8;
1981         dst_idx += rect->dy*par->next_line*8+rect->dx;
1982         while (height--) {
1983                 switch (rect->rop) {
1984                     case ROP_COPY:
1985                         fill_one_line(info->var.bits_per_pixel,
1986                                       par->next_plane, dst, dst_idx, width,
1987                                       rect->color);
1988                         break;
1989
1990                     case ROP_XOR:
1991                         xor_one_line(info->var.bits_per_pixel, par->next_plane,
1992                                      dst, dst_idx, width, rect->color);
1993                         break;
1994                 }
1995                 dst_idx += par->next_line*8;
1996         }
1997 }
1998
1999 static inline void copy_one_line(int bpp, unsigned long next_plane,
2000                                  unsigned long *dst, int dst_idx,
2001                                  unsigned long *src, int src_idx, u32 n)
2002 {
2003         while (1) {
2004                 dst += dst_idx >> SHIFT_PER_LONG;
2005                 dst_idx &= (BITS_PER_LONG-1);
2006                 src += src_idx >> SHIFT_PER_LONG;
2007                 src_idx &= (BITS_PER_LONG-1);
2008                 bitcpy(dst, dst_idx, src, src_idx, n);
2009                 if (!--bpp)
2010                         break;
2011                 dst_idx += next_plane*8;
2012                 src_idx += next_plane*8;
2013         }
2014 }
2015
2016 static inline void copy_one_line_rev(int bpp, unsigned long next_plane,
2017                                      unsigned long *dst, int dst_idx,
2018                                      unsigned long *src, int src_idx, u32 n)
2019 {
2020         while (1) {
2021                 dst += dst_idx >> SHIFT_PER_LONG;
2022                 dst_idx &= (BITS_PER_LONG-1);
2023                 src += src_idx >> SHIFT_PER_LONG;
2024                 src_idx &= (BITS_PER_LONG-1);
2025                 bitcpy_rev(dst, dst_idx, src, src_idx, n);
2026                 if (!--bpp)
2027                         break;
2028                 dst_idx += next_plane*8;
2029                 src_idx += next_plane*8;
2030         }
2031 }
2032
2033
2034 static void amifb_copyarea(struct fb_info *info,
2035                            const struct fb_copyarea *area)
2036 {
2037         struct amifb_par *par = (struct amifb_par *)info->par;
2038         int x2, y2;
2039         u32 dx, dy, sx, sy, width, height;
2040         unsigned long *dst, *src;
2041         int dst_idx, src_idx;
2042         int rev_copy = 0;
2043
2044         /* clip the destination */
2045         x2 = area->dx + area->width;
2046         y2 = area->dy + area->height;
2047         dx = area->dx > 0 ? area->dx : 0;
2048         dy = area->dy > 0 ? area->dy : 0;
2049         x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2050         y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2051         width = x2 - dx;
2052         height = y2 - dy;
2053
2054         /* update sx,sy */
2055         sx = area->sx + (dx - area->dx);
2056         sy = area->sy + (dy - area->dy);
2057
2058         /* the source must be completely inside the virtual screen */
2059         if (sx < 0 || sy < 0 || (sx + width) > info->var.xres_virtual ||
2060             (sy + height) > info->var.yres_virtual)
2061                 return;
2062
2063         if (dy > sy || (dy == sy && dx > sx)) {
2064                 dy += height;
2065                 sy += height;
2066                 rev_copy = 1;
2067         }
2068         dst = (unsigned long *)
2069                 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1));
2070         src = dst;
2071         dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8;
2072         src_idx = dst_idx;
2073         dst_idx += dy*par->next_line*8+dx;
2074         src_idx += sy*par->next_line*8+sx;
2075         if (rev_copy) {
2076                 while (height--) {
2077                         dst_idx -= par->next_line*8;
2078                         src_idx -= par->next_line*8;
2079                         copy_one_line_rev(info->var.bits_per_pixel,
2080                                           par->next_plane, dst, dst_idx, src,
2081                                           src_idx, width);
2082                 }
2083         } else {
2084                 while (height--) {
2085                         copy_one_line(info->var.bits_per_pixel,
2086                                       par->next_plane, dst, dst_idx, src,
2087                                       src_idx, width);
2088                         dst_idx += par->next_line*8;
2089                         src_idx += par->next_line*8;
2090                 }
2091         }
2092 }
2093
2094
2095 static inline void expand_one_line(int bpp, unsigned long next_plane,
2096                                    unsigned long *dst, int dst_idx, u32 n,
2097                                    const u8 *data, u32 bgcolor, u32 fgcolor)
2098 {
2099     const unsigned long *src;
2100     int src_idx;
2101
2102     while (1) {
2103         dst += dst_idx >> SHIFT_PER_LONG;
2104         dst_idx &= (BITS_PER_LONG-1);
2105         if ((bgcolor ^ fgcolor) & 1) {
2106             src = (unsigned long *)((unsigned long)data & ~(BYTES_PER_LONG-1));
2107             src_idx = ((unsigned long)data & (BYTES_PER_LONG-1))*8;
2108             if (fgcolor & 1)
2109                 bitcpy(dst, dst_idx, src, src_idx, n);
2110             else
2111                 bitcpy_not(dst, dst_idx, src, src_idx, n);
2112             /* set or clear */
2113         } else
2114             bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n);
2115         if (!--bpp)
2116             break;
2117         bgcolor >>= 1;
2118         fgcolor >>= 1;
2119         dst_idx += next_plane*8;
2120     }
2121 }
2122
2123
2124 static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
2125 {
2126         struct amifb_par *par = (struct amifb_par *)info->par;
2127         int x2, y2;
2128         unsigned long *dst;
2129         int dst_idx;
2130         const char *src;
2131         u32 dx, dy, width, height, pitch;
2132
2133         /*
2134          * We could use hardware clipping but on many cards you get around
2135          * hardware clipping by writing to framebuffer directly like we are
2136          * doing here.
2137          */
2138         x2 = image->dx + image->width;
2139         y2 = image->dy + image->height;
2140         dx = image->dx;
2141         dy = image->dy;
2142         x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2143         y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2144         width  = x2 - dx;
2145         height = y2 - dy;
2146
2147         if (image->depth == 1) {
2148                 dst = (unsigned long *)
2149                         ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1));
2150                 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8;
2151                 dst_idx += dy*par->next_line*8+dx;
2152                 src = image->data;
2153                 pitch = (image->width+7)/8;
2154                 while (height--) {
2155                         expand_one_line(info->var.bits_per_pixel,
2156                                         par->next_plane, dst, dst_idx, width,
2157                                         src, image->bg_color,
2158                                         image->fg_color);
2159                         dst_idx += par->next_line*8;
2160                         src += pitch;
2161                 }
2162         } else {
2163                 c2p(info->screen_base, image->data, dx, dy, width, height,
2164                     par->next_line, par->next_plane, image->width,
2165                     info->var.bits_per_pixel);
2166         }
2167 }
2168
2169
2170         /*
2171          * Amiga Frame Buffer Specific ioctls
2172          */
2173
2174 static int amifb_ioctl(struct inode *inode, struct file *file,
2175                        unsigned int cmd, unsigned long arg,
2176                        struct fb_info *info)
2177 {
2178         union {
2179                 struct fb_fix_cursorinfo fix;
2180                 struct fb_var_cursorinfo var;
2181                 struct fb_cursorstate state;
2182         } crsr;
2183         int i;
2184
2185         switch (cmd) {
2186                 case FBIOGET_FCURSORINFO:
2187                         i = ami_get_fix_cursorinfo(&crsr.fix);
2188                         if (i)
2189                                 return i;
2190                         return copy_to_user((void *)arg, &crsr.fix,
2191                                             sizeof(crsr.fix)) ? -EFAULT : 0;
2192
2193                 case FBIOGET_VCURSORINFO:
2194                         i = ami_get_var_cursorinfo(&crsr.var,
2195                                 ((struct fb_var_cursorinfo *)arg)->data);
2196                         if (i)
2197                                 return i;
2198                         return copy_to_user((void *)arg, &crsr.var,
2199                                             sizeof(crsr.var)) ? -EFAULT : 0;
2200
2201                 case FBIOPUT_VCURSORINFO:
2202                         if (copy_from_user(&crsr.var, (void *)arg,
2203                                            sizeof(crsr.var)))
2204                                 return -EFAULT;
2205                         return ami_set_var_cursorinfo(&crsr.var,
2206                                 ((struct fb_var_cursorinfo *)arg)->data);
2207
2208                 case FBIOGET_CURSORSTATE:
2209                         i = ami_get_cursorstate(&crsr.state);
2210                         if (i)
2211                                 return i;
2212                         return copy_to_user((void *)arg, &crsr.state,
2213                                             sizeof(crsr.state)) ? -EFAULT : 0;
2214
2215                 case FBIOPUT_CURSORSTATE:
2216                         if (copy_from_user(&crsr.state, (void *)arg,
2217                                            sizeof(crsr.state)))
2218                                 return -EFAULT;
2219                         return ami_set_cursorstate(&crsr.state);
2220         }
2221         return -EINVAL;
2222 }
2223
2224
2225         /*
2226          * Allocate, Clear and Align a Block of Chip Memory
2227          */
2228
2229 static u_long unaligned_chipptr = 0;
2230
2231 static inline u_long __init chipalloc(u_long size)
2232 {
2233         size += PAGE_SIZE-1;
2234         if (!(unaligned_chipptr = (u_long)amiga_chip_alloc(size,
2235                                                            "amifb [RAM]")))
2236                 panic("No Chip RAM for frame buffer");
2237         memset((void *)unaligned_chipptr, 0, size);
2238         return PAGE_ALIGN(unaligned_chipptr);
2239 }
2240
2241 static inline void chipfree(void)
2242 {
2243         if (unaligned_chipptr)
2244                 amiga_chip_free((void *)unaligned_chipptr);
2245 }
2246
2247
2248         /*
2249          * Initialisation
2250          */
2251
2252 int __init amifb_init(void)
2253 {
2254         int tag, i, err = 0;
2255         u_long chipptr;
2256         u_int defmode;
2257
2258 #ifndef MODULE
2259         char *option = NULL;
2260
2261         if (fb_get_options("amifb", &option)) {
2262                 amifb_video_off();
2263                 return -ENODEV;
2264         }
2265         amifb_setup(option);
2266 #endif
2267         if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO))
2268                 return -ENXIO;
2269
2270         /*
2271          * We request all registers starting from bplpt[0]
2272          */
2273         if (!request_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120,
2274                                 "amifb [Denise/Lisa]"))
2275                 return -EBUSY;
2276
2277         custom.dmacon = DMAF_ALL | DMAF_MASTER;
2278
2279         switch (amiga_chipset) {
2280 #ifdef CONFIG_FB_AMIGA_OCS
2281                 case CS_OCS:
2282                         strcat(fb_info.fix.id, "OCS");
2283 default_chipset:
2284                         chipset = TAG_OCS;
2285                         maxdepth[TAG_SHRES] = 0;        /* OCS means no SHRES */
2286                         maxdepth[TAG_HIRES] = 4;
2287                         maxdepth[TAG_LORES] = 6;
2288                         maxfmode = TAG_FMODE_1;
2289                         defmode = amiga_vblank == 50 ? DEFMODE_PAL
2290                                                      : DEFMODE_NTSC;
2291                         fb_info.fix.smem_len = VIDEOMEMSIZE_OCS;
2292                         break;
2293 #endif /* CONFIG_FB_AMIGA_OCS */
2294
2295 #ifdef CONFIG_FB_AMIGA_ECS
2296                 case CS_ECS:
2297                         strcat(fb_info.fix.id, "ECS");
2298                         chipset = TAG_ECS;
2299                         maxdepth[TAG_SHRES] = 2;
2300                         maxdepth[TAG_HIRES] = 4;
2301                         maxdepth[TAG_LORES] = 6;
2302                         maxfmode = TAG_FMODE_1;
2303                         if (AMIGAHW_PRESENT(AMBER_FF))
2304                             defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL
2305                                                          : DEFMODE_AMBER_NTSC;
2306                         else
2307                             defmode = amiga_vblank == 50 ? DEFMODE_PAL
2308                                                          : DEFMODE_NTSC;
2309                         if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT >
2310                             VIDEOMEMSIZE_ECS_1M)
2311                                 fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_2M;
2312                         else
2313                                 fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_1M;
2314                         break;
2315 #endif /* CONFIG_FB_AMIGA_ECS */
2316
2317 #ifdef CONFIG_FB_AMIGA_AGA
2318                 case CS_AGA:
2319                         strcat(fb_info.fix.id, "AGA");
2320                         chipset = TAG_AGA;
2321                         maxdepth[TAG_SHRES] = 8;
2322                         maxdepth[TAG_HIRES] = 8;
2323                         maxdepth[TAG_LORES] = 8;
2324                         maxfmode = TAG_FMODE_4;
2325                         defmode = DEFMODE_AGA;
2326                         if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT >
2327                             VIDEOMEMSIZE_AGA_1M)
2328                                 fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_2M;
2329                         else
2330                                 fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_1M;
2331                         break;
2332 #endif /* CONFIG_FB_AMIGA_AGA */
2333
2334                 default:
2335 #ifdef CONFIG_FB_AMIGA_OCS
2336                         printk("Unknown graphics chipset, defaulting to OCS\n");
2337                         strcat(fb_info.fix.id, "Unknown");
2338                         goto default_chipset;
2339 #else /* CONFIG_FB_AMIGA_OCS */
2340                         err = -ENXIO;
2341                         goto amifb_error;
2342 #endif /* CONFIG_FB_AMIGA_OCS */
2343                         break;
2344         }
2345
2346         /*
2347          * Calculate the Pixel Clock Values for this Machine
2348          */
2349
2350         {
2351         u_long tmp = DIVUL(200000000000ULL, amiga_eclock);
2352
2353         pixclock[TAG_SHRES] = (tmp + 4) / 8;    /* SHRES:  35 ns / 28 MHz */
2354         pixclock[TAG_HIRES] = (tmp + 2) / 4;    /* HIRES:  70 ns / 14 MHz */
2355         pixclock[TAG_LORES] = (tmp + 1) / 2;    /* LORES: 140 ns /  7 MHz */
2356         }
2357
2358         /*
2359          * Replace the Tag Values with the Real Pixel Clock Values
2360          */
2361
2362         for (i = 0; i < NUM_TOTAL_MODES; i++) {
2363                 struct fb_videomode *mode = &ami_modedb[i];
2364                 tag = mode->pixclock;
2365                 if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) {
2366                         mode->pixclock = pixclock[tag];
2367                 }
2368         }
2369
2370         /*
2371          *  These monitor specs are for a typical Amiga monitor (e.g. A1960)
2372          */
2373         if (fb_info.monspecs.hfmin == 0) {
2374             fb_info.monspecs.hfmin = 15000;
2375             fb_info.monspecs.hfmax = 38000;
2376             fb_info.monspecs.vfmin = 49;
2377             fb_info.monspecs.vfmax = 90;
2378         }
2379
2380         fb_info.fbops = &amifb_ops;
2381         fb_info.par = &currentpar;
2382         fb_info.flags = FBINFO_DEFAULT;
2383
2384         if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb,
2385                           NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
2386                 err = -EINVAL;
2387                 goto amifb_error;
2388         }
2389
2390         round_down_bpp = 0;
2391         chipptr = chipalloc(fb_info.fix.smem_len+
2392                             SPRITEMEMSIZE+
2393                             DUMMYSPRITEMEMSIZE+
2394                             COPINITSIZE+
2395                             4*COPLISTSIZE);
2396
2397         assignchunk(videomemory, u_long, chipptr, fb_info.fix.smem_len);
2398         assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE);
2399         assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE);
2400         assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE);
2401         assignchunk(copdisplay.list[0][0], copins *, chipptr, COPLISTSIZE);
2402         assignchunk(copdisplay.list[0][1], copins *, chipptr, COPLISTSIZE);
2403         assignchunk(copdisplay.list[1][0], copins *, chipptr, COPLISTSIZE);
2404         assignchunk(copdisplay.list[1][1], copins *, chipptr, COPLISTSIZE);
2405
2406         /*
2407          * access the videomem with writethrough cache
2408          */
2409         fb_info.fix.smem_start = (u_long)ZTWO_PADDR(videomemory);
2410         videomemory = (u_long)ioremap_writethrough(fb_info.fix.smem_start,
2411                                                    fb_info.fix.smem_len);
2412         if (!videomemory) {
2413                 printk("amifb: WARNING! unable to map videomem cached writethrough\n");
2414                 videomemory = ZTWO_VADDR(fb_info.fix.smem_start);
2415         }
2416
2417         fb_info.screen_base = (char *)videomemory;
2418         memset(dummysprite, 0, DUMMYSPRITEMEMSIZE);
2419
2420         /*
2421          * Enable Display DMA
2422          */
2423
2424         custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
2425                         DMAF_BLITTER | DMAF_SPRITE;
2426
2427         /*
2428          * Make sure the Copper has something to do
2429          */
2430
2431         ami_init_copper();
2432
2433         if (request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0,
2434                         "fb vertb handler", &currentpar)) {
2435                 err = -EBUSY;
2436                 goto amifb_error;
2437         }
2438
2439         fb_alloc_cmap(&fb_info.cmap, 1<<fb_info.var.bits_per_pixel, 0);
2440
2441         if (register_framebuffer(&fb_info) < 0) {
2442                 err = -EINVAL;
2443                 goto amifb_error;
2444         }
2445
2446         printk("fb%d: %s frame buffer device, using %dK of video memory\n",
2447                fb_info.node, fb_info.fix.id, fb_info.fix.smem_len>>10);
2448
2449         return 0;
2450
2451 amifb_error:
2452         amifb_deinit();
2453         return err;
2454 }
2455
2456 static void amifb_deinit(void)
2457 {
2458         fb_dealloc_cmap(&fb_info.cmap);
2459         chipfree();
2460         release_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120);
2461         custom.dmacon = DMAF_ALL | DMAF_MASTER;
2462 }
2463
2464
2465         /*
2466          * Blank the display.
2467          */
2468
2469 static int amifb_blank(int blank, struct fb_info *info)
2470 {
2471         do_blank = blank ? blank : -1;
2472
2473         return 0;
2474 }
2475
2476         /*
2477          * Flash the cursor (called by VBlank interrupt)
2478          */
2479
2480 static int flash_cursor(void)
2481 {
2482         static int cursorcount = 1;
2483
2484         if (cursormode == FB_CURSOR_FLASH) {
2485                 if (!--cursorcount) {
2486                         cursorstate = -cursorstate;
2487                         cursorcount = cursorrate;
2488                         if (!is_blanked)
2489                                 return 1;
2490                 }
2491         }
2492         return 0;
2493 }
2494
2495         /*
2496          * VBlank Display Interrupt
2497          */
2498
2499 static irqreturn_t amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp)
2500 {
2501         if (do_vmode_pan || do_vmode_full)
2502                 ami_update_display();
2503
2504         if (do_vmode_full)
2505                 ami_init_display();
2506
2507         if (do_vmode_pan) {
2508                 flash_cursor();
2509                 ami_rebuild_copper();
2510                 do_cursor = do_vmode_pan = 0;
2511         } else if (do_cursor) {
2512                 flash_cursor();
2513                 ami_set_sprite();
2514                 do_cursor = 0;
2515         } else {
2516                 if (flash_cursor())
2517                         ami_set_sprite();
2518         }
2519
2520         if (do_blank) {
2521                 ami_do_blank();
2522                 do_blank = 0;
2523         }
2524
2525         if (do_vmode_full) {
2526                 ami_reinit_copper();
2527                 do_vmode_full = 0;
2528         }
2529         return IRQ_HANDLED;
2530 }
2531
2532 /* --------------------------- Hardware routines --------------------------- */
2533
2534         /*
2535          * Get the video params out of `var'. If a value doesn't fit, round
2536          * it up, if it's too big, return -EINVAL.
2537          */
2538
2539 static int ami_decode_var(struct fb_var_screeninfo *var,
2540                           struct amifb_par *par)
2541 {
2542         u_short clk_shift, line_shift;
2543         u_long maxfetchstop, fstrt, fsize, fconst, xres_n, yres_n;
2544         u_int htotal, vtotal;
2545
2546         /*
2547          * Find a matching Pixel Clock
2548          */
2549
2550         for (clk_shift = TAG_SHRES; clk_shift <= TAG_LORES; clk_shift++)
2551                 if (var->pixclock <= pixclock[clk_shift])
2552                         break;
2553         if (clk_shift > TAG_LORES) {
2554                 DPRINTK("pixclock too high\n");
2555                 return -EINVAL;
2556         }
2557         par->clk_shift = clk_shift;
2558
2559         /*
2560          * Check the Geometry Values
2561          */
2562
2563         if ((par->xres = var->xres) < 64)
2564                 par->xres = 64;
2565         if ((par->yres = var->yres) < 64)
2566                 par->yres = 64;
2567         if ((par->vxres = var->xres_virtual) < par->xres)
2568                 par->vxres = par->xres;
2569         if ((par->vyres = var->yres_virtual) < par->yres)
2570                 par->vyres = par->yres;
2571
2572         par->bpp = var->bits_per_pixel;
2573         if (!var->nonstd) {
2574                 if (par->bpp < 1)
2575                         par->bpp = 1;
2576                 if (par->bpp > maxdepth[clk_shift]) {
2577                         if (round_down_bpp && maxdepth[clk_shift])
2578                                 par->bpp = maxdepth[clk_shift];
2579                         else {
2580                                 DPRINTK("invalid bpp\n");
2581                                 return -EINVAL;
2582                         }
2583                 }
2584         } else if (var->nonstd == FB_NONSTD_HAM) {
2585                 if (par->bpp < 6)
2586                         par->bpp = 6;
2587                 if (par->bpp != 6) {
2588                         if (par->bpp < 8)
2589                                 par->bpp = 8;
2590                         if (par->bpp != 8 || !IS_AGA) {
2591                                 DPRINTK("invalid bpp for ham mode\n");
2592                                 return -EINVAL;
2593                         }
2594                 }
2595         } else {
2596                 DPRINTK("unknown nonstd mode\n");
2597                 return -EINVAL;
2598         }
2599
2600         /*
2601          * FB_VMODE_SMOOTH_XPAN will be cleared, if one of the folloing
2602          * checks failed and smooth scrolling is not possible
2603          */
2604
2605         par->vmode = var->vmode | FB_VMODE_SMOOTH_XPAN;
2606         switch (par->vmode & FB_VMODE_MASK) {
2607                 case FB_VMODE_INTERLACED:
2608                         line_shift = 0;
2609                         break;
2610                 case FB_VMODE_NONINTERLACED:
2611                         line_shift = 1;
2612                         break;
2613                 case FB_VMODE_DOUBLE:
2614                         if (!IS_AGA) {
2615                                 DPRINTK("double mode only possible with aga\n");
2616                                 return -EINVAL;
2617                         }
2618                         line_shift = 2;
2619                         break;
2620                 default:
2621                         DPRINTK("unknown video mode\n");
2622                         return -EINVAL;
2623                         break;
2624         }
2625         par->line_shift = line_shift;
2626
2627         /*
2628          * Vertical and Horizontal Timings
2629          */
2630
2631         xres_n = par->xres<<clk_shift;
2632         yres_n = par->yres<<line_shift;
2633         par->htotal = down8((var->left_margin+par->xres+var->right_margin+var->hsync_len)<<clk_shift);
2634         par->vtotal = down2(((var->upper_margin+par->yres+var->lower_margin+var->vsync_len)<<line_shift)+1);
2635
2636         if (IS_AGA)
2637                 par->bplcon3 = sprpixmode[clk_shift];
2638         else
2639                 par->bplcon3 = 0;
2640         if (var->sync & FB_SYNC_BROADCAST) {
2641                 par->diwstop_h = par->htotal-((var->right_margin-var->hsync_len)<<clk_shift);
2642                 if (IS_AGA)
2643                         par->diwstop_h += mod4(var->hsync_len);
2644                 else
2645                         par->diwstop_h = down4(par->diwstop_h);
2646
2647                 par->diwstrt_h = par->diwstop_h - xres_n;
2648                 par->diwstop_v = par->vtotal-((var->lower_margin-var->vsync_len)<<line_shift);
2649                 par->diwstrt_v = par->diwstop_v - yres_n;
2650                 if (par->diwstop_h >= par->htotal+8) {
2651                         DPRINTK("invalid diwstop_h\n");
2652                         return -EINVAL;
2653                 }
2654                 if (par->diwstop_v > par->vtotal) {
2655                         DPRINTK("invalid diwstop_v\n");
2656                         return -EINVAL;
2657                 }
2658
2659                 if (!IS_OCS) {
2660                         /* Initialize sync with some reasonable values for pwrsave */
2661                         par->hsstrt = 160;
2662                         par->hsstop = 320;
2663                         par->vsstrt = 30;
2664                         par->vsstop = 34;
2665                 } else {
2666                         par->hsstrt = 0;
2667                         par->hsstop = 0;
2668                         par->vsstrt = 0;
2669                         par->vsstop = 0;
2670                 }
2671                 if (par->vtotal > (PAL_VTOTAL+NTSC_VTOTAL)/2) {
2672                         /* PAL video mode */
2673                         if (par->htotal != PAL_HTOTAL) {
2674                                 DPRINTK("htotal invalid for pal\n");
2675                                 return -EINVAL;
2676                         }
2677                         if (par->diwstrt_h < PAL_DIWSTRT_H) {
2678                                 DPRINTK("diwstrt_h too low for pal\n");
2679                                 return -EINVAL;
2680                         }
2681                         if (par->diwstrt_v < PAL_DIWSTRT_V) {
2682                                 DPRINTK("diwstrt_v too low for pal\n");
2683                                 return -EINVAL;
2684                         }
2685                         htotal = PAL_HTOTAL>>clk_shift;
2686                         vtotal = PAL_VTOTAL>>1;
2687                         if (!IS_OCS) {
2688                                 par->beamcon0 = BMC0_PAL;
2689                                 par->bplcon3 |= BPC3_BRDRBLNK;
2690                         } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
2691                                    AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
2692                                 par->beamcon0 = BMC0_PAL;
2693                                 par->hsstop = 1;
2694                         } else if (amiga_vblank != 50) {
2695                                 DPRINTK("pal not supported by this chipset\n");
2696                                 return -EINVAL;
2697                         }
2698                 } else {
2699                         /* NTSC video mode
2700                          * In the AGA chipset seems to be hardware bug with BPC3_BRDRBLNK
2701                          * and NTSC activated, so than better let diwstop_h <= 1812
2702                          */
2703                         if (par->htotal != NTSC_HTOTAL) {
2704                                 DPRINTK("htotal invalid for ntsc\n");
2705                                 return -EINVAL;
2706                         }
2707                         if (par->diwstrt_h < NTSC_DIWSTRT_H) {
2708                                 DPRINTK("diwstrt_h too low for ntsc\n");
2709                                 return -EINVAL;
2710                         }
2711                         if (par->diwstrt_v < NTSC_DIWSTRT_V) {
2712                                 DPRINTK("diwstrt_v too low for ntsc\n");
2713                                 return -EINVAL;
2714                         }
2715                         htotal = NTSC_HTOTAL>>clk_shift;
2716                         vtotal = NTSC_VTOTAL>>1;
2717                         if (!IS_OCS) {
2718                                 par->beamcon0 = 0;
2719                                 par->bplcon3 |= BPC3_BRDRBLNK;
2720                         } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
2721                                    AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
2722                                 par->beamcon0 = 0;
2723                                 par->hsstop = 1;
2724                         } else if (amiga_vblank != 60) {
2725                                 DPRINTK("ntsc not supported by this chipset\n");
2726                                 return -EINVAL;
2727                         }
2728                 }
2729                 if (IS_OCS) {
2730                         if (par->diwstrt_h >= 1024 || par->diwstop_h < 1024 ||
2731                             par->diwstrt_v >=  512 || par->diwstop_v <  256) {
2732                                 DPRINTK("invalid position for display on ocs\n");
2733                                 return -EINVAL;
2734                         }
2735                 }
2736         } else if (!IS_OCS) {
2737                 /* Programmable video mode */
2738                 par->hsstrt = var->right_margin<<clk_shift;
2739                 par->hsstop = (var->right_margin+var->hsync_len)<<clk_shift;
2740                 par->diwstop_h = par->htotal - mod8(par->hsstrt) + 8 - (1 << clk_shift);
2741                 if (!IS_AGA)
2742                         par->diwstop_h = down4(par->diwstop_h) - 16;
2743                 par->diwstrt_h = par->diwstop_h - xres_n;
2744                 par->hbstop = par->diwstrt_h + 4;
2745                 par->hbstrt = par->diwstop_h + 4;
2746                 if (par->hbstrt >= par->htotal + 8)
2747                         par->hbstrt -= par->htotal;
2748                 par->hcenter = par->hsstrt + (par->htotal >> 1);
2749                 par->vsstrt = var->lower_margin<<line_shift;
2750                 par->vsstop = (var->lower_margin+var->vsync_len)<<line_shift;
2751                 par->diwstop_v = par->vtotal;
2752                 if ((par->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
2753                         par->diwstop_v -= 2;
2754                 par->diwstrt_v = par->diwstop_v - yres_n;
2755                 par->vbstop = par->diwstrt_v - 2;
2756                 par->vbstrt = par->diwstop_v - 2;
2757                 if (par->vtotal > 2048) {
2758                         DPRINTK("vtotal too high\n");
2759                         return -EINVAL;
2760                 }
2761                 if (par->htotal > 2048) {
2762                         DPRINTK("htotal too high\n");
2763                         return -EINVAL;
2764                 }
2765                 par->bplcon3 |= BPC3_EXTBLKEN;
2766                 par->beamcon0 = BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS |
2767                                 BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN |
2768                                 BMC0_PAL | BMC0_VARCSYEN;
2769                 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
2770                         par->beamcon0 |= BMC0_HSYTRUE;
2771                 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
2772                         par->beamcon0 |= BMC0_VSYTRUE;
2773                 if (var->sync & FB_SYNC_COMP_HIGH_ACT)
2774                         par->beamcon0 |= BMC0_CSYTRUE;
2775                 htotal = par->htotal>>clk_shift;
2776                 vtotal = par->vtotal>>1;
2777         } else {
2778                 DPRINTK("only broadcast modes possible for ocs\n");
2779                 return -EINVAL;
2780         }
2781
2782         /*
2783          * Checking the DMA timing
2784          */
2785
2786         fconst = 16<<maxfmode<<clk_shift;
2787
2788         /*
2789          * smallest window start value without turn off other dma cycles
2790          * than sprite1-7, unless you change min_fstrt
2791          */
2792
2793
2794         fsize = ((maxfmode+clk_shift <= 1) ? fconst : 64);
2795         fstrt = downx(fconst, par->diwstrt_h-4) - fsize;
2796         if (fstrt < min_fstrt) {
2797                 DPRINTK("fetch start too low\n");
2798                 return -EINVAL;
2799         }
2800
2801         /*
2802          * smallest window start value where smooth scrolling is possible
2803          */
2804
2805         fstrt = downx(fconst, par->diwstrt_h-fconst+(1<<clk_shift)-4) - fsize;
2806         if (fstrt < min_fstrt)
2807                 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
2808
2809         maxfetchstop = down16(par->htotal - 80);
2810
2811         fstrt = downx(fconst, par->diwstrt_h-4) - 64 - fconst;
2812         fsize = upx(fconst, xres_n + modx(fconst, downx(1<<clk_shift, par->diwstrt_h-4)));
2813         if (fstrt + fsize > maxfetchstop)
2814                 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
2815
2816         fsize = upx(fconst, xres_n);
2817         if (fstrt + fsize > maxfetchstop) {
2818                 DPRINTK("fetch stop too high\n");
2819                 return -EINVAL;
2820         }
2821
2822         if (maxfmode + clk_shift <= 1) {
2823                 fsize = up64(xres_n + fconst - 1);
2824                 if (min_fstrt + fsize - 64 > maxfetchstop)
2825                         par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
2826
2827                 fsize = up64(xres_n);
2828                 if (min_fstrt + fsize - 64 > maxfetchstop) {
2829                         DPRINTK("fetch size too high\n");
2830                         return -EINVAL;
2831                 }
2832
2833                 fsize -= 64;
2834         } else
2835                 fsize -= fconst;
2836
2837         /*
2838          * Check if there is enough time to update the bitplane pointers for ywrap
2839          */
2840
2841         if (par->htotal-fsize-64 < par->bpp*64)
2842                 par->vmode &= ~FB_VMODE_YWRAP;
2843
2844         /*
2845          * Bitplane calculations and check the Memory Requirements
2846          */
2847
2848         if (amifb_ilbm) {
2849                 par->next_plane = div8(upx(16<<maxfmode, par->vxres));
2850                 par->next_line = par->bpp*par->next_plane;
2851                 if (par->next_line * par->vyres > fb_info.fix.smem_len) {
2852                         DPRINTK("too few video mem\n");
2853                         return -EINVAL;
2854                 }
2855         } else {
2856                 par->next_line = div8(upx(16<<maxfmode, par->vxres));
2857                 par->next_plane = par->vyres*par->next_line;
2858                 if (par->next_plane * par->bpp > fb_info.fix.smem_len) {
2859                         DPRINTK("too few video mem\n");
2860                         return -EINVAL;
2861                 }
2862         }
2863
2864         /*
2865          * Hardware Register Values
2866          */
2867
2868         par->bplcon0 = BPC0_COLOR | bplpixmode[clk_shift];
2869         if (!IS_OCS)
2870                 par->bplcon0 |= BPC0_ECSENA;
2871         if (par->bpp == 8)
2872                 par->bplcon0 |= BPC0_BPU3;
2873         else
2874                 par->bplcon0 |= par->bpp<<12;
2875         if (var->nonstd == FB_NONSTD_HAM)
2876                 par->bplcon0 |= BPC0_HAM;
2877         if (var->sync & FB_SYNC_EXT)
2878                 par->bplcon0 |= BPC0_ERSY;
2879
2880         if (IS_AGA)
2881                 par->fmode = bplfetchmode[maxfmode];
2882
2883         switch (par->vmode & FB_VMODE_MASK) {
2884                 case FB_VMODE_INTERLACED:
2885                         par->bplcon0 |= BPC0_LACE;
2886                         break;
2887                 case FB_VMODE_DOUBLE:
2888                         if (IS_AGA)
2889                                 par->fmode |= FMODE_SSCAN2 | FMODE_BSCAN2;
2890                         break;
2891         }
2892
2893         if (!((par->vmode ^ var->vmode) & FB_VMODE_YWRAP)) {
2894                 par->xoffset = var->xoffset;
2895                 par->yoffset = var->yoffset;
2896                 if (par->vmode & FB_VMODE_YWRAP) {
2897                         if (par->xoffset || par->yoffset < 0 || par->yoffset >= par->vyres)
2898                                 par->xoffset = par->yoffset = 0;
2899                 } else {
2900                         if (par->xoffset < 0 || par->xoffset > upx(16<<maxfmode, par->vxres-par->xres) ||
2901                             par->yoffset < 0 || par->yoffset > par->vyres-par->yres)
2902                                 par->xoffset = par->yoffset = 0;
2903                 }
2904         } else
2905                 par->xoffset = par->yoffset = 0;
2906
2907         par->crsr.crsr_x = par->crsr.crsr_y = 0;
2908         par->crsr.spot_x = par->crsr.spot_y = 0;
2909         par->crsr.height = par->crsr.width = 0;
2910
2911 #if 0   /* fbmon not done.  uncomment for 2.5.x -brad */
2912         if (!fbmon_valid_timings(pixclock[clk_shift], htotal, vtotal,
2913                                  &fb_info)) {
2914                 DPRINTK("mode doesn't fit for monitor\n");
2915                 return -EINVAL;
2916         }
2917 #endif
2918
2919         return 0;
2920 }
2921
2922         /*
2923          * Fill the `var' structure based on the values in `par' and maybe
2924          * other values read out of the hardware.
2925          */
2926
2927 static int ami_encode_var(struct fb_var_screeninfo *var,
2928                           struct amifb_par *par)
2929 {
2930         u_short clk_shift, line_shift;
2931
2932         memset(var, 0, sizeof(struct fb_var_screeninfo));
2933
2934         clk_shift = par->clk_shift;
2935         line_shift = par->line_shift;
2936
2937         var->xres = par->xres;
2938         var->yres = par->yres;
2939         var->xres_virtual = par->vxres;
2940         var->yres_virtual = par->vyres;
2941         var->xoffset = par->xoffset;
2942         var->yoffset = par->yoffset;
2943
2944         var->bits_per_pixel = par->bpp;
2945         var->grayscale = 0;
2946
2947         var->red.offset = 0;
2948         var->red.msb_right = 0;
2949         var->red.length = par->bpp;
2950         if (par->bplcon0 & BPC0_HAM)
2951             var->red.length -= 2;
2952         var->blue = var->green = var->red;
2953         var->transp.offset = 0;
2954         var->transp.length = 0;
2955         var->transp.msb_right = 0;
2956
2957         if (par->bplcon0 & BPC0_HAM)
2958                 var->nonstd = FB_NONSTD_HAM;
2959         else
2960                 var->nonstd = 0;
2961         var->activate = 0;
2962
2963         var->height = -1;
2964         var->width = -1;
2965
2966         var->pixclock = pixclock[clk_shift];
2967
2968         if (IS_AGA && par->fmode & FMODE_BSCAN2)
2969                 var->vmode = FB_VMODE_DOUBLE;
2970         else if (par->bplcon0 & BPC0_LACE)
2971                 var->vmode = FB_VMODE_INTERLACED;
2972         else
2973                 var->vmode = FB_VMODE_NONINTERLACED;
2974
2975         if (!IS_OCS && par->beamcon0 & BMC0_VARBEAMEN) {
2976                 var->hsync_len = (par->hsstop-par->hsstrt)>>clk_shift;
2977                 var->right_margin = par->hsstrt>>clk_shift;
2978                 var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
2979                 var->vsync_len = (par->vsstop-par->vsstrt)>>line_shift;
2980                 var->lower_margin = par->vsstrt>>line_shift;
2981                 var->upper_margin = (par->vtotal>>line_shift) - var->yres - var->lower_margin - var->vsync_len;
2982                 var->sync = 0;
2983                 if (par->beamcon0 & BMC0_HSYTRUE)
2984                         var->sync |= FB_SYNC_HOR_HIGH_ACT;
2985                 if (par->beamcon0 & BMC0_VSYTRUE)
2986                         var->sync |= FB_SYNC_VERT_HIGH_ACT;
2987                 if (par->beamcon0 & BMC0_CSYTRUE)
2988                         var->sync |= FB_SYNC_COMP_HIGH_ACT;
2989         } else {
2990                 var->sync = FB_SYNC_BROADCAST;
2991                 var->hsync_len = (152>>clk_shift) + mod4(par->diwstop_h);
2992                 var->right_margin = ((par->htotal - down4(par->diwstop_h))>>clk_shift) + var->hsync_len;
2993                 var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
2994                 var->vsync_len = 4>>line_shift;
2995                 var->lower_margin = ((par->vtotal - par->diwstop_v)>>line_shift) + var->vsync_len;
2996                 var->upper_margin = (((par->vtotal - 2)>>line_shift) + 1) - var->yres -
2997                                     var->lower_margin - var->vsync_len;
2998         }
2999
3000         if (par->bplcon0 & BPC0_ERSY)
3001                 var->sync |= FB_SYNC_EXT;
3002         if (par->vmode & FB_VMODE_YWRAP)
3003                 var->vmode |= FB_VMODE_YWRAP;
3004
3005         return 0;
3006 }
3007
3008
3009         /*
3010          * Pan or Wrap the Display
3011          *
3012          * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
3013          * in `var'.
3014          */
3015
3016 static void ami_pan_var(struct fb_var_screeninfo *var)
3017 {
3018         struct amifb_par *par = &currentpar;
3019
3020         par->xoffset = var->xoffset;
3021         par->yoffset = var->yoffset;
3022         if (var->vmode & FB_VMODE_YWRAP)
3023                 par->vmode |= FB_VMODE_YWRAP;
3024         else
3025                 par->vmode &= ~FB_VMODE_YWRAP;
3026
3027         do_vmode_pan = 0;
3028         ami_update_par();
3029         do_vmode_pan = 1;
3030 }
3031
3032         /*
3033          * Update hardware
3034          */
3035
3036 static int ami_update_par(void)
3037 {
3038         struct amifb_par *par = &currentpar;
3039         short clk_shift, vshift, fstrt, fsize, fstop, fconst,  shift, move, mod;
3040
3041         clk_shift = par->clk_shift;
3042
3043         if (!(par->vmode & FB_VMODE_SMOOTH_XPAN))
3044                 par->xoffset = upx(16<<maxfmode, par->xoffset);
3045
3046         fconst = 16<<maxfmode<<clk_shift;
3047         vshift = modx(16<<maxfmode, par->xoffset);
3048         fstrt = par->diwstrt_h - (vshift<<clk_shift) - 4;
3049         fsize = (par->xres+vshift)<<clk_shift;
3050         shift = modx(fconst, fstrt);
3051         move = downx(2<<maxfmode, div8(par->xoffset));
3052         if (maxfmode + clk_shift > 1) {
3053                 fstrt = downx(fconst, fstrt) - 64;
3054                 fsize = upx(fconst, fsize);
3055                 fstop = fstrt + fsize - fconst;
3056         } else {
3057                 mod = fstrt = downx(fconst, fstrt) - fconst;
3058                 fstop = fstrt + upx(fconst, fsize) - 64;
3059                 fsize = up64(fsize);
3060                 fstrt = fstop - fsize + 64;
3061                 if (fstrt < min_fstrt) {
3062                         fstop += min_fstrt - fstrt;
3063                         fstrt = min_fstrt;
3064                 }
3065                 move = move - div8((mod-fstrt)>>clk_shift);
3066         }
3067         mod = par->next_line - div8(fsize>>clk_shift);
3068         par->ddfstrt = fstrt;
3069         par->ddfstop = fstop;
3070         par->bplcon1 = hscroll2hw(shift);
3071         par->bpl2mod = mod;
3072         if (par->bplcon0 & BPC0_LACE)
3073                 par->bpl2mod += par->next_line;
3074         if (IS_AGA && (par->fmode & FMODE_BSCAN2))
3075                 par->bpl1mod = -div8(fsize>>clk_shift);
3076         else
3077                 par->bpl1mod = par->bpl2mod;
3078
3079         if (par->yoffset) {
3080                 par->bplpt0 = fb_info.fix.smem_start + par->next_line*par->yoffset + move;
3081                 if (par->vmode & FB_VMODE_YWRAP) {
3082                         if (par->yoffset > par->vyres-par->yres) {
3083                                 par->bplpt0wrap = fb_info.fix.smem_start + move;
3084                                 if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v+par->vyres-par->yoffset))
3085                                         par->bplpt0wrap += par->next_line;
3086                         }
3087                 }
3088         } else
3089                 par->bplpt0 = fb_info.fix.smem_start + move;
3090
3091         if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v))
3092                 par->bplpt0 += par->next_line;
3093
3094         return 0;
3095 }
3096
3097
3098         /*
3099          * Set a single color register. The values supplied are already
3100          * rounded down to the hardware's capabilities (according to the
3101          * entries in the var structure). Return != 0 for invalid regno.
3102          */
3103
3104 static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
3105                            u_int transp, struct fb_info *info)
3106 {
3107         if (IS_AGA) {
3108                 if (regno > 255)
3109                         return 1;
3110         } else if (currentpar.bplcon0 & BPC0_SHRES) {
3111                 if (regno > 3)
3112                         return 1;
3113         } else {
3114                 if (regno > 31)
3115                         return 1;
3116         }
3117         red >>= 8;
3118         green >>= 8;
3119         blue >>= 8;
3120         if (!regno) {
3121                 red0 = red;
3122                 green0 = green;
3123                 blue0 = blue;
3124         }
3125
3126         /*
3127          * Update the corresponding Hardware Color Register, unless it's Color
3128          * Register 0 and the screen is blanked.
3129          *
3130          * VBlank is switched off to protect bplcon3 or ecs_palette[] from
3131          * being changed by ami_do_blank() during the VBlank.
3132          */
3133
3134         if (regno || !is_blanked) {
3135 #if defined(CONFIG_FB_AMIGA_AGA)
3136                 if (IS_AGA) {
3137                         u_short bplcon3 = currentpar.bplcon3;
3138                         VBlankOff();
3139                         custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000);
3140                         custom.color[regno&31] = rgb2hw8_high(red, green, blue);
3141                         custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000) | BPC3_LOCT;
3142                         custom.color[regno&31] = rgb2hw8_low(red, green, blue);
3143                         custom.bplcon3 = bplcon3;
3144                         VBlankOn();
3145                 } else
3146 #endif
3147 #if defined(CONFIG_FB_AMIGA_ECS)
3148                 if (currentpar.bplcon0 & BPC0_SHRES) {
3149                         u_short color, mask;
3150                         int i;
3151
3152                         mask = 0x3333;
3153                         color = rgb2hw2(red, green, blue);
3154                         VBlankOff();
3155                         for (i = regno+12; i >= (int)regno; i -= 4)
3156                                 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3157                         mask <<=2; color >>= 2;
3158                         regno = down16(regno)+mul4(mod4(regno));
3159                         for (i = regno+3; i >= (int)regno; i--)
3160                                 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3161                         VBlankOn();
3162                 } else
3163 #endif
3164                         custom.color[regno] = rgb2hw4(red, green, blue);
3165         }
3166         return 0;
3167 }
3168
3169 static void ami_update_display(void)
3170 {
3171         struct amifb_par *par = &currentpar;
3172
3173         custom.bplcon1 = par->bplcon1;
3174         custom.bpl1mod = par->bpl1mod;
3175         custom.bpl2mod = par->bpl2mod;
3176         custom.ddfstrt = ddfstrt2hw(par->ddfstrt);
3177         custom.ddfstop = ddfstop2hw(par->ddfstop);
3178 }
3179
3180         /*
3181          * Change the video mode (called by VBlank interrupt)
3182          */
3183
3184 static void ami_init_display(void)
3185 {
3186         struct amifb_par *par = &currentpar;
3187         int i;
3188
3189         custom.bplcon0 = par->bplcon0 & ~BPC0_LACE;
3190         custom.bplcon2 = (IS_OCS ? 0 : BPC2_KILLEHB) | BPC2_PF2P2 | BPC2_PF1P2;
3191         if (!IS_OCS) {
3192                 custom.bplcon3 = par->bplcon3;
3193                 if (IS_AGA)
3194                         custom.bplcon4 = BPC4_ESPRM4 | BPC4_OSPRM4;
3195                 if (par->beamcon0 & BMC0_VARBEAMEN) {
3196                         custom.htotal = htotal2hw(par->htotal);
3197                         custom.hbstrt = hbstrt2hw(par->hbstrt);
3198                         custom.hbstop = hbstop2hw(par->hbstop);
3199                         custom.hsstrt = hsstrt2hw(par->hsstrt);
3200                         custom.hsstop = hsstop2hw(par->hsstop);
3201                         custom.hcenter = hcenter2hw(par->hcenter);
3202                         custom.vtotal = vtotal2hw(par->vtotal);
3203                         custom.vbstrt = vbstrt2hw(par->vbstrt);
3204                         custom.vbstop = vbstop2hw(par->vbstop);
3205                         custom.vsstrt = vsstrt2hw(par->vsstrt);
3206                         custom.vsstop = vsstop2hw(par->vsstop);
3207                 }
3208         }
3209         if (!IS_OCS || par->hsstop)
3210                 custom.beamcon0 = par->beamcon0;
3211         if (IS_AGA)
3212                 custom.fmode = par->fmode;
3213
3214         /*
3215          * The minimum period for audio depends on htotal
3216          */
3217
3218         amiga_audio_min_period = div16(par->htotal);
3219
3220         is_lace = par->bplcon0 & BPC0_LACE ? 1 : 0;
3221 #if 1
3222         if (is_lace) {
3223                 i = custom.vposr >> 15;
3224         } else {
3225                 custom.vposw = custom.vposr | 0x8000;
3226                 i = 1;
3227         }
3228 #else
3229         i = 1;
3230         custom.vposw = custom.vposr | 0x8000;
3231 #endif
3232         custom.cop2lc = (u_short *)ZTWO_PADDR(copdisplay.list[currentcop][i]);
3233 }
3234
3235         /*
3236          * (Un)Blank the screen (called by VBlank interrupt)
3237          */
3238
3239 static void ami_do_blank(void)
3240 {
3241         struct amifb_par *par = &currentpar;
3242 #if defined(CONFIG_FB_AMIGA_AGA)
3243         u_short bplcon3 = par->bplcon3;
3244 #endif
3245         u_char red, green, blue;
3246
3247         if (do_blank > 0) {
3248                 custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
3249                 red = green = blue = 0;
3250                 if (!IS_OCS && do_blank > 1) {
3251                         switch (do_blank) {
3252                                 case FB_BLANK_VSYNC_SUSPEND:
3253                                         custom.hsstrt = hsstrt2hw(par->hsstrt);
3254                                         custom.hsstop = hsstop2hw(par->hsstop);
3255                                         custom.vsstrt = vsstrt2hw(par->vtotal+4);
3256                                         custom.vsstop = vsstop2hw(par->vtotal+4);
3257                                         break;
3258                                 case FB_BLANK_HSYNC_SUSPEND:
3259                                         custom.hsstrt = hsstrt2hw(par->htotal+16);
3260                                         custom.hsstop = hsstop2hw(par->htotal+16);
3261                                         custom.vsstrt = vsstrt2hw(par->vsstrt);
3262                                         custom.vsstop = vsstrt2hw(par->vsstop);
3263                                         break;
3264                                 case FB_BLANK_POWERDOWN:
3265                                         custom.hsstrt = hsstrt2hw(par->htotal+16);
3266                                         custom.hsstop = hsstop2hw(par->htotal+16);
3267                                         custom.vsstrt = vsstrt2hw(par->vtotal+4);
3268                                         custom.vsstop = vsstop2hw(par->vtotal+4);
3269                                         break;
3270                         }
3271                         if (!(par->beamcon0 & BMC0_VARBEAMEN)) {
3272                                 custom.htotal = htotal2hw(par->htotal);
3273                                 custom.vtotal = vtotal2hw(par->vtotal);
3274                                 custom.beamcon0 = BMC0_HARDDIS | BMC0_VARBEAMEN |
3275                                                   BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARCSYEN;
3276                         }
3277                 }
3278         } else {
3279                 custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_SPRITE;
3280                 red = red0;
3281                 green = green0;
3282                 blue = blue0;
3283                 if (!IS_OCS) {
3284                         custom.hsstrt = hsstrt2hw(par->hsstrt);
3285                         custom.hsstop = hsstop2hw(par->hsstop);
3286                         custom.vsstrt = vsstrt2hw(par->vsstrt);
3287                         custom.vsstop = vsstop2hw(par->vsstop);
3288                         custom.beamcon0 = par->beamcon0;
3289                 }
3290         }
3291 #if defined(CONFIG_FB_AMIGA_AGA)
3292         if (IS_AGA) {
3293                 custom.bplcon3 = bplcon3;
3294                 custom.color[0] = rgb2hw8_high(red, green, blue);
3295                 custom.bplcon3 = bplcon3 | BPC3_LOCT;
3296                 custom.color[0] = rgb2hw8_low(red, green, blue);
3297                 custom.bplcon3 = bplcon3;
3298         } else
3299 #endif
3300 #if defined(CONFIG_FB_AMIGA_ECS)
3301         if (par->bplcon0 & BPC0_SHRES) {
3302                 u_short color, mask;
3303                 int i;
3304
3305                 mask = 0x3333;
3306                 color = rgb2hw2(red, green, blue);
3307                 for (i = 12; i >= 0; i -= 4)
3308                         custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3309                 mask <<=2; color >>= 2;
3310                 for (i = 3; i >= 0; i--)
3311                         custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3312         } else
3313 #endif
3314                 custom.color[0] = rgb2hw4(red, green, blue);
3315         is_blanked = do_blank > 0 ? do_blank : 0;
3316 }
3317
3318 static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix)
3319 {
3320         struct amifb_par *par = &currentpar;
3321
3322         fix->crsr_width = fix->crsr_xsize = par->crsr.width;
3323         fix->crsr_height = fix->crsr_ysize = par->crsr.height;
3324         fix->crsr_color1 = 17;
3325         fix->crsr_color2 = 18;
3326         return 0;
3327 }
3328
3329 static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data)
3330 {
3331         struct amifb_par *par = &currentpar;
3332         register u_short *lspr, *sspr;
3333 #ifdef __mc68000__
3334         register u_long datawords asm ("d2");
3335 #else
3336         register u_long datawords;
3337 #endif
3338         register short delta;
3339         register u_char color;
3340         short height, width, bits, words;
3341         int size, alloc;
3342
3343         size = par->crsr.height*par->crsr.width;
3344         alloc = var->height*var->width;
3345         var->height = par->crsr.height;
3346         var->width = par->crsr.width;
3347         var->xspot = par->crsr.spot_x;
3348         var->yspot = par->crsr.spot_y;
3349         if (size > var->height*var->width)
3350                 return -ENAMETOOLONG;
3351         if (!access_ok(VERIFY_WRITE, (void *)data, size))
3352                 return -EFAULT;
3353         delta = 1<<par->crsr.fmode;
3354         lspr = lofsprite + (delta<<1);
3355         if (par->bplcon0 & BPC0_LACE)
3356                 sspr = shfsprite + (delta<<1);
3357         else
3358                 sspr = 0;
3359         for (height = (short)var->height-1; height >= 0; height--) {
3360                 bits = 0; words = delta; datawords = 0;
3361                 for (width = (short)var->width-1; width >= 0; width--) {
3362                         if (bits == 0) {
3363                                 bits = 16; --words;
3364 #ifdef __mc68000__
3365                                 asm volatile ("movew %1@(%3:w:2),%0 ; swap %0 ; movew %1@+,%0"
3366                                         : "=d" (datawords), "=a" (lspr) : "1" (lspr), "d" (delta));
3367 #else
3368                                 datawords = (*(lspr+delta) << 16) | (*lspr++);
3369 #endif
3370                         }
3371                         --bits;
3372 #ifdef __mc68000__
3373                         asm volatile (
3374                                 "clrb %0 ; swap %1 ; lslw #1,%1 ; roxlb #1,%0 ; "
3375                                 "swap %1 ; lslw #1,%1 ; roxlb #1,%0"
3376                                 : "=d" (color), "=d" (datawords) : "1" (datawords));
3377 #else
3378                         color = (((datawords >> 30) & 2)
3379                                  | ((datawords >> 15) & 1));
3380                         datawords <<= 1;
3381 #endif
3382                         put_user(color, data++);
3383                 }
3384                 if (bits > 0) {
3385                         --words; ++lspr;
3386                 }
3387                 while (--words >= 0)
3388                         ++lspr;
3389 #ifdef __mc68000__
3390                 asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
3391                         : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
3392 #else
3393                 lspr += delta;
3394                 if (sspr) {
3395                         u_short *tmp = lspr;
3396                         lspr = sspr;
3397                         sspr = tmp;
3398                 }
3399 #endif
3400         }
3401         return 0;
3402 }
3403
3404 static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data)
3405 {
3406         struct amifb_par *par = &currentpar;
3407         register u_short *lspr, *sspr;
3408 #ifdef __mc68000__
3409         register u_long datawords asm ("d2");
3410 #else
3411         register u_long datawords;
3412 #endif
3413         register short delta;
3414         u_short fmode;
3415         short height, width, bits, words;
3416
3417         if (!var->width)
3418                 return -EINVAL;
3419         else if (var->width <= 16)
3420                 fmode = TAG_FMODE_1;
3421         else if (var->width <= 32)
3422                 fmode = TAG_FMODE_2;
3423         else if (var->width <= 64)
3424                 fmode = TAG_FMODE_4;
3425         else
3426                 return -EINVAL;
3427         if (fmode > maxfmode)
3428                 return -EINVAL;
3429         if (!var->height)
3430                 return -EINVAL;
3431         if (!access_ok(VERIFY_READ, (void *)data, var->width*var->height))
3432                 return -EFAULT;
3433         delta = 1<<fmode;
3434         lofsprite = shfsprite = (u_short *)spritememory;
3435         lspr = lofsprite + (delta<<1);
3436         if (par->bplcon0 & BPC0_LACE) {
3437                 if (((var->height+4)<<fmode<<2) > SPRITEMEMSIZE)
3438                         return -EINVAL;
3439                 memset(lspr, 0, (var->height+4)<<fmode<<2);
3440                 shfsprite += ((var->height+5)&-2)<<fmode;
3441                 sspr = shfsprite + (delta<<1);
3442         } else {
3443                 if (((var->height+2)<<fmode<<2) > SPRITEMEMSIZE)
3444                         return -EINVAL;
3445                 memset(lspr, 0, (var->height+2)<<fmode<<2);
3446                 sspr = 0;
3447         }
3448         for (height = (short)var->height-1; height >= 0; height--) {
3449                 bits = 16; words = delta; datawords = 0;
3450                 for (width = (short)var->width-1; width >= 0; width--) {
3451                         unsigned long tdata = 0;
3452                         get_user(tdata, (char *)data);
3453                         data++;
3454 #ifdef __mc68000__
3455                         asm volatile (
3456                                 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0 ; "
3457                                 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0"
3458                                 : "=d" (datawords)
3459                                 : "0" (datawords), "d" (tdata));
3460 #else
3461                         datawords = ((datawords << 1) & 0xfffefffe);
3462                         datawords |= tdata & 1;
3463                         datawords |= (tdata & 2) << (16-1);
3464 #endif
3465                         if (--bits == 0) {
3466                                 bits = 16; --words;
3467 #ifdef __mc68000__
3468                                 asm volatile ("swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+"
3469                                         : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta));
3470 #else
3471                                 *(lspr+delta) = (u_short) (datawords >> 16);
3472                                 *lspr++ = (u_short) (datawords & 0xffff);
3473 #endif
3474                         }
3475                 }
3476                 if (bits < 16) {
3477                         --words;
3478 #ifdef __mc68000__
3479                         asm volatile (
3480                                 "swap %2 ; lslw %4,%2 ; movew %2,%0@(%3:w:2) ; "
3481                                 "swap %2 ; lslw %4,%2 ; movew %2,%0@+"
3482                                 : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta), "d" (bits));
3483 #else
3484                         *(lspr+delta) = (u_short) (datawords >> (16+bits));
3485                         *lspr++ = (u_short) ((datawords & 0x0000ffff) >> bits);
3486 #endif
3487                 }
3488                 while (--words >= 0) {
3489 #ifdef __mc68000__
3490                         asm volatile ("moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+"
3491                                 : "=a" (lspr) : "0" (lspr), "d" (delta) : "d0");
3492 #else
3493                         *(lspr+delta) = 0;
3494                         *lspr++ = 0;
3495 #endif
3496                 }
3497 #ifdef __mc68000__
3498                 asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
3499                         : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
3500 #else
3501                 lspr += delta;
3502                 if (sspr) {
3503                         u_short *tmp = lspr;
3504                         lspr = sspr;
3505                         sspr = tmp;
3506                 }
3507 #endif
3508         }
3509         par->crsr.height = var->height;
3510         par->crsr.width = var->width;
3511         par->crsr.spot_x = var->xspot;
3512         par->crsr.spot_y = var->yspot;
3513         par->crsr.fmode = fmode;
3514         if (IS_AGA) {
3515                 par->fmode &= ~(FMODE_SPAGEM | FMODE_SPR32);
3516                 par->fmode |= sprfetchmode[fmode];
3517                 custom.fmode = par->fmode;
3518         }
3519         return 0;
3520 }
3521
3522 static int ami_get_cursorstate(struct fb_cursorstate *state)
3523 {
3524         struct amifb_par *par = &currentpar;
3525
3526         state->xoffset = par->crsr.crsr_x;
3527         state->yoffset = par->crsr.crsr_y;
3528         state->mode = cursormode;
3529         return 0;
3530 }
3531
3532 static int ami_set_cursorstate(struct fb_cursorstate *state)
3533 {
3534         struct amifb_par *par = &currentpar;
3535
3536         par->crsr.crsr_x = state->xoffset;
3537         par->crsr.crsr_y = state->yoffset;
3538         if ((cursormode = state->mode) == FB_CURSOR_OFF)
3539                 cursorstate = -1;
3540         do_cursor = 1;
3541         return 0;
3542 }
3543
3544 static void ami_set_sprite(void)
3545 {
3546         struct amifb_par *par = &currentpar;
3547         copins *copl, *cops;
3548         u_short hs, vs, ve;
3549         u_long pl, ps, pt;
3550         short mx, my;
3551
3552         cops = copdisplay.list[currentcop][0];
3553         copl = copdisplay.list[currentcop][1];
3554         ps = pl = ZTWO_PADDR(dummysprite);
3555         mx = par->crsr.crsr_x-par->crsr.spot_x;
3556         my = par->crsr.crsr_y-par->crsr.spot_y;
3557         if (!(par->vmode & FB_VMODE_YWRAP)) {
3558                 mx -= par->xoffset;
3559                 my -= par->yoffset;
3560         }
3561         if (!is_blanked && cursorstate > 0 && par->crsr.height > 0 &&
3562             mx > -(short)par->crsr.width && mx < par->xres &&
3563             my > -(short)par->crsr.height && my < par->yres) {
3564                 pl = ZTWO_PADDR(lofsprite);
3565                 hs = par->diwstrt_h + (mx<<par->clk_shift) - 4;
3566                 vs = par->diwstrt_v + (my<<par->line_shift);
3567                 ve = vs + (par->crsr.height<<par->line_shift);
3568                 if (par->bplcon0 & BPC0_LACE) {
3569                         ps = ZTWO_PADDR(shfsprite);
3570                         lofsprite[0] = spr2hw_pos(vs, hs);
3571                         shfsprite[0] = spr2hw_pos(vs+1, hs);
3572                         if (mod2(vs)) {
3573                                 lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
3574                                 shfsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs+1, hs, ve+1);
3575                                 pt = pl; pl = ps; ps = pt;
3576                         } else {
3577                                 lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve+1);
3578                                 shfsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs+1, hs, ve);
3579                         }
3580                 } else {
3581                         lofsprite[0] = spr2hw_pos(vs, hs) | (IS_AGA && (par->fmode & FMODE_BSCAN2) ? 0x80 : 0);
3582                         lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
3583                 }
3584         }
3585         copl[cop_spr0ptrh].w[1] = highw(pl);
3586         copl[cop_spr0ptrl].w[1] = loww(pl);
3587         if (par->bplcon0 & BPC0_LACE) {
3588                 cops[cop_spr0ptrh].w[1] = highw(ps);
3589                 cops[cop_spr0ptrl].w[1] = loww(ps);
3590         }
3591 }
3592
3593
3594         /*
3595          * Initialise the Copper Initialisation List
3596          */
3597
3598 static void __init ami_init_copper(void)
3599 {
3600         copins *cop = copdisplay.init;
3601         u_long p;
3602         int i;
3603
3604         if (!IS_OCS) {
3605                 (cop++)->l = CMOVE(BPC0_COLOR | BPC0_SHRES | BPC0_ECSENA, bplcon0);
3606                 (cop++)->l = CMOVE(0x0181, diwstrt);
3607                 (cop++)->l = CMOVE(0x0281, diwstop);
3608                 (cop++)->l = CMOVE(0x0000, diwhigh);
3609         } else
3610                 (cop++)->l = CMOVE(BPC0_COLOR, bplcon0);
3611         p = ZTWO_PADDR(dummysprite);
3612         for (i = 0; i < 8; i++) {
3613                 (cop++)->l = CMOVE(0, spr[i].pos);
3614                 (cop++)->l = CMOVE(highw(p), sprpt[i]);
3615                 (cop++)->l = CMOVE2(loww(p), sprpt[i]);
3616         }
3617
3618         (cop++)->l = CMOVE(IF_SETCLR | IF_COPER, intreq);
3619         copdisplay.wait = cop;
3620         (cop++)->l = CEND;
3621         (cop++)->l = CMOVE(0, copjmp2);
3622         cop->l = CEND;
3623
3624         custom.cop1lc = (u_short *)ZTWO_PADDR(copdisplay.init);
3625         custom.copjmp1 = 0;
3626 }
3627
3628 static void ami_reinit_copper(void)
3629 {
3630         struct amifb_par *par = &currentpar;
3631
3632         copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0;
3633         copdisplay.wait->l = CWAIT(32, par->diwstrt_v-4);
3634 }
3635
3636         /*
3637          * Build the Copper List
3638          */
3639
3640 static void ami_build_copper(void)
3641 {
3642         struct amifb_par *par = &currentpar;
3643         copins *copl, *cops;
3644         u_long p;
3645
3646         currentcop = 1 - currentcop;
3647
3648         copl = copdisplay.list[currentcop][1];
3649
3650         (copl++)->l = CWAIT(0, 10);
3651         (copl++)->l = CMOVE(par->bplcon0, bplcon0);
3652         (copl++)->l = CMOVE(0, sprpt[0]);
3653         (copl++)->l = CMOVE2(0, sprpt[0]);
3654
3655         if (par->bplcon0 & BPC0_LACE) {
3656                 cops = copdisplay.list[currentcop][0];
3657
3658                 (cops++)->l = CWAIT(0, 10);
3659                 (cops++)->l = CMOVE(par->bplcon0, bplcon0);
3660                 (cops++)->l = CMOVE(0, sprpt[0]);
3661                 (cops++)->l = CMOVE2(0, sprpt[0]);
3662
3663                 (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v+1), diwstrt);
3664                 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v+1), diwstop);
3665                 (cops++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
3666                 (cops++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
3667                 if (!IS_OCS) {
3668                         (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v+1,
3669                                             par->diwstop_h, par->diwstop_v+1), diwhigh);
3670                         (cops++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
3671                                             par->diwstop_h, par->diwstop_v), diwhigh);
3672 #if 0
3673                         if (par->beamcon0 & BMC0_VARBEAMEN) {
3674                                 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
3675                                 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt+1), vbstrt);
3676                                 (copl++)->l = CMOVE(vbstop2hw(par->vbstop+1), vbstop);
3677                                 (cops++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
3678                                 (cops++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
3679                                 (cops++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
3680                         }
3681 #endif
3682                 }
3683                 p = ZTWO_PADDR(copdisplay.list[currentcop][0]);
3684                 (copl++)->l = CMOVE(highw(p), cop2lc);
3685                 (copl++)->l = CMOVE2(loww(p), cop2lc);
3686                 p = ZTWO_PADDR(copdisplay.list[currentcop][1]);
3687                 (cops++)->l = CMOVE(highw(p), cop2lc);
3688                 (cops++)->l = CMOVE2(loww(p), cop2lc);
3689                 copdisplay.rebuild[0] = cops;
3690         } else {
3691                 (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
3692                 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
3693                 if (!IS_OCS) {
3694                         (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
3695                                             par->diwstop_h, par->diwstop_v), diwhigh);
3696 #if 0
3697                         if (par->beamcon0 & BMC0_VARBEAMEN) {
3698                                 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
3699                                 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
3700                                 (copl++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
3701                         }
3702 #endif
3703                 }
3704         }
3705         copdisplay.rebuild[1] = copl;
3706
3707         ami_update_par();
3708         ami_rebuild_copper();
3709 }
3710
3711         /*
3712          * Rebuild the Copper List
3713          *
3714          * We only change the things that are not static
3715          */
3716
3717 static void ami_rebuild_copper(void)
3718 {
3719         struct amifb_par *par = &currentpar;
3720         copins *copl, *cops;
3721         u_short line, h_end1, h_end2;
3722         short i;
3723         u_long p;
3724
3725         if (IS_AGA && maxfmode + par->clk_shift == 0)
3726                 h_end1 = par->diwstrt_h-64;
3727         else
3728                 h_end1 = par->htotal-32;
3729         h_end2 = par->ddfstop+64;
3730
3731         ami_set_sprite();
3732
3733         copl = copdisplay.rebuild[1];
3734         p = par->bplpt0;
3735         if (par->vmode & FB_VMODE_YWRAP) {
3736                 if ((par->vyres-par->yoffset) != 1 || !mod2(par->diwstrt_v)) {
3737                         if (par->yoffset > par->vyres-par->yres) {
3738                                 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3739                                         (copl++)->l = CMOVE(highw(p), bplpt[i]);
3740                                         (copl++)->l = CMOVE2(loww(p), bplpt[i]);
3741                                 }
3742                                 line = par->diwstrt_v + ((par->vyres-par->yoffset)<<par->line_shift) - 1;
3743                                 while (line >= 512) {
3744                                         (copl++)->l = CWAIT(h_end1, 510);
3745                                         line -= 512;
3746                                 }
3747                                 if (line >= 510 && IS_AGA && maxfmode + par->clk_shift == 0)
3748                                         (copl++)->l = CWAIT(h_end1, line);
3749                                 else
3750                                         (copl++)->l = CWAIT(h_end2, line);
3751                                 p = par->bplpt0wrap;
3752                         }
3753                 } else p = par->bplpt0wrap;
3754         }
3755         for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3756                 (copl++)->l = CMOVE(highw(p), bplpt[i]);
3757                 (copl++)->l = CMOVE2(loww(p), bplpt[i]);
3758         }
3759         copl->l = CEND;
3760
3761         if (par->bplcon0 & BPC0_LACE) {
3762                 cops = copdisplay.rebuild[0];
3763                 p = par->bplpt0;
3764                 if (mod2(par->diwstrt_v))
3765                         p -= par->next_line;
3766                 else
3767                         p += par->next_line;
3768                 if (par->vmode & FB_VMODE_YWRAP) {
3769                         if ((par->vyres-par->yoffset) != 1 || mod2(par->diwstrt_v)) {
3770                                 if (par->yoffset > par->vyres-par->yres+1) {
3771                                         for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3772                                                 (cops++)->l = CMOVE(highw(p), bplpt[i]);
3773                                                 (cops++)->l = CMOVE2(loww(p), bplpt[i]);
3774                                         }
3775                                         line = par->diwstrt_v + ((par->vyres-par->yoffset)<<par->line_shift) - 2;
3776                                         while (line >= 512) {
3777                                                 (cops++)->l = CWAIT(h_end1, 510);
3778                                                 line -= 512;
3779                                         }
3780                                         if (line > 510 && IS_AGA && maxfmode + par->clk_shift == 0)
3781                                                 (cops++)->l = CWAIT(h_end1, line);
3782                                         else
3783                                                 (cops++)->l = CWAIT(h_end2, line);
3784                                         p = par->bplpt0wrap;
3785                                         if (mod2(par->diwstrt_v+par->vyres-par->yoffset))
3786                                                 p -= par->next_line;
3787                                         else
3788                                                 p += par->next_line;
3789                                 }
3790                         } else p = par->bplpt0wrap - par->next_line;
3791                 }
3792                 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3793                         (cops++)->l = CMOVE(highw(p), bplpt[i]);
3794                         (cops++)->l = CMOVE2(loww(p), bplpt[i]);
3795                 }
3796                 cops->l = CEND;
3797         }
3798 }
3799
3800
3801 module_init(amifb_init);
3802
3803 #ifdef MODULE
3804 MODULE_LICENSE("GPL");
3805
3806 void cleanup_module(void)
3807 {
3808         unregister_framebuffer(&fb_info);
3809         amifb_deinit();
3810         amifb_video_off();
3811 }
3812 #endif /* MODULE */