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