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