Merge branch 'acpica' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
[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_planar(info->screen_base, image->data, dx, dy, width,
2163                            height, par->next_line, par->next_plane,
2164                            image->width, 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         err = fb_alloc_cmap(&fb_info.cmap, 1<<fb_info.var.bits_per_pixel, 0);
2441         if (err)
2442                 goto amifb_error;
2443
2444         if (register_framebuffer(&fb_info) < 0) {
2445                 err = -EINVAL;
2446                 goto amifb_error;
2447         }
2448
2449         printk("fb%d: %s frame buffer device, using %dK of video memory\n",
2450                fb_info.node, fb_info.fix.id, fb_info.fix.smem_len>>10);
2451
2452         return 0;
2453
2454 amifb_error:
2455         amifb_deinit();
2456         return err;
2457 }
2458
2459 static void amifb_deinit(void)
2460 {
2461         if (fb_info.cmap.len)
2462                 fb_dealloc_cmap(&fb_info.cmap);
2463         chipfree();
2464         if (videomemory)
2465                 iounmap((void*)videomemory);
2466         release_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120);
2467         custom.dmacon = DMAF_ALL | DMAF_MASTER;
2468 }
2469
2470
2471         /*
2472          * Blank the display.
2473          */
2474
2475 static int amifb_blank(int blank, struct fb_info *info)
2476 {
2477         do_blank = blank ? blank : -1;
2478
2479         return 0;
2480 }
2481
2482         /*
2483          * Flash the cursor (called by VBlank interrupt)
2484          */
2485
2486 static int flash_cursor(void)
2487 {
2488         static int cursorcount = 1;
2489
2490         if (cursormode == FB_CURSOR_FLASH) {
2491                 if (!--cursorcount) {
2492                         cursorstate = -cursorstate;
2493                         cursorcount = cursorrate;
2494                         if (!is_blanked)
2495                                 return 1;
2496                 }
2497         }
2498         return 0;
2499 }
2500
2501         /*
2502          * VBlank Display Interrupt
2503          */
2504
2505 static irqreturn_t amifb_interrupt(int irq, void *dev_id)
2506 {
2507         if (do_vmode_pan || do_vmode_full)
2508                 ami_update_display();
2509
2510         if (do_vmode_full)
2511                 ami_init_display();
2512
2513         if (do_vmode_pan) {
2514                 flash_cursor();
2515                 ami_rebuild_copper();
2516                 do_cursor = do_vmode_pan = 0;
2517         } else if (do_cursor) {
2518                 flash_cursor();
2519                 ami_set_sprite();
2520                 do_cursor = 0;
2521         } else {
2522                 if (flash_cursor())
2523                         ami_set_sprite();
2524         }
2525
2526         if (do_blank) {
2527                 ami_do_blank();
2528                 do_blank = 0;
2529         }
2530
2531         if (do_vmode_full) {
2532                 ami_reinit_copper();
2533                 do_vmode_full = 0;
2534         }
2535         return IRQ_HANDLED;
2536 }
2537
2538 /* --------------------------- Hardware routines --------------------------- */
2539
2540         /*
2541          * Get the video params out of `var'. If a value doesn't fit, round
2542          * it up, if it's too big, return -EINVAL.
2543          */
2544
2545 static int ami_decode_var(struct fb_var_screeninfo *var,
2546                           struct amifb_par *par)
2547 {
2548         u_short clk_shift, line_shift;
2549         u_long maxfetchstop, fstrt, fsize, fconst, xres_n, yres_n;
2550         u_int htotal, vtotal;
2551
2552         /*
2553          * Find a matching Pixel Clock
2554          */
2555
2556         for (clk_shift = TAG_SHRES; clk_shift <= TAG_LORES; clk_shift++)
2557                 if (var->pixclock <= pixclock[clk_shift])
2558                         break;
2559         if (clk_shift > TAG_LORES) {
2560                 DPRINTK("pixclock too high\n");
2561                 return -EINVAL;
2562         }
2563         par->clk_shift = clk_shift;
2564
2565         /*
2566          * Check the Geometry Values
2567          */
2568
2569         if ((par->xres = var->xres) < 64)
2570                 par->xres = 64;
2571         if ((par->yres = var->yres) < 64)
2572                 par->yres = 64;
2573         if ((par->vxres = var->xres_virtual) < par->xres)
2574                 par->vxres = par->xres;
2575         if ((par->vyres = var->yres_virtual) < par->yres)
2576                 par->vyres = par->yres;
2577
2578         par->bpp = var->bits_per_pixel;
2579         if (!var->nonstd) {
2580                 if (par->bpp < 1)
2581                         par->bpp = 1;
2582                 if (par->bpp > maxdepth[clk_shift]) {
2583                         if (round_down_bpp && maxdepth[clk_shift])
2584                                 par->bpp = maxdepth[clk_shift];
2585                         else {
2586                                 DPRINTK("invalid bpp\n");
2587                                 return -EINVAL;
2588                         }
2589                 }
2590         } else if (var->nonstd == FB_NONSTD_HAM) {
2591                 if (par->bpp < 6)
2592                         par->bpp = 6;
2593                 if (par->bpp != 6) {
2594                         if (par->bpp < 8)
2595                                 par->bpp = 8;
2596                         if (par->bpp != 8 || !IS_AGA) {
2597                                 DPRINTK("invalid bpp for ham mode\n");
2598                                 return -EINVAL;
2599                         }
2600                 }
2601         } else {
2602                 DPRINTK("unknown nonstd mode\n");
2603                 return -EINVAL;
2604         }
2605
2606         /*
2607          * FB_VMODE_SMOOTH_XPAN will be cleared, if one of the folloing
2608          * checks failed and smooth scrolling is not possible
2609          */
2610
2611         par->vmode = var->vmode | FB_VMODE_SMOOTH_XPAN;
2612         switch (par->vmode & FB_VMODE_MASK) {
2613                 case FB_VMODE_INTERLACED:
2614                         line_shift = 0;
2615                         break;
2616                 case FB_VMODE_NONINTERLACED:
2617                         line_shift = 1;
2618                         break;
2619                 case FB_VMODE_DOUBLE:
2620                         if (!IS_AGA) {
2621                                 DPRINTK("double mode only possible with aga\n");
2622                                 return -EINVAL;
2623                         }
2624                         line_shift = 2;
2625                         break;
2626                 default:
2627                         DPRINTK("unknown video mode\n");
2628                         return -EINVAL;
2629                         break;
2630         }
2631         par->line_shift = line_shift;
2632
2633         /*
2634          * Vertical and Horizontal Timings
2635          */
2636
2637         xres_n = par->xres<<clk_shift;
2638         yres_n = par->yres<<line_shift;
2639         par->htotal = down8((var->left_margin+par->xres+var->right_margin+var->hsync_len)<<clk_shift);
2640         par->vtotal = down2(((var->upper_margin+par->yres+var->lower_margin+var->vsync_len)<<line_shift)+1);
2641
2642         if (IS_AGA)
2643                 par->bplcon3 = sprpixmode[clk_shift];
2644         else
2645                 par->bplcon3 = 0;
2646         if (var->sync & FB_SYNC_BROADCAST) {
2647                 par->diwstop_h = par->htotal-((var->right_margin-var->hsync_len)<<clk_shift);
2648                 if (IS_AGA)
2649                         par->diwstop_h += mod4(var->hsync_len);
2650                 else
2651                         par->diwstop_h = down4(par->diwstop_h);
2652
2653                 par->diwstrt_h = par->diwstop_h - xres_n;
2654                 par->diwstop_v = par->vtotal-((var->lower_margin-var->vsync_len)<<line_shift);
2655                 par->diwstrt_v = par->diwstop_v - yres_n;
2656                 if (par->diwstop_h >= par->htotal+8) {
2657                         DPRINTK("invalid diwstop_h\n");
2658                         return -EINVAL;
2659                 }
2660                 if (par->diwstop_v > par->vtotal) {
2661                         DPRINTK("invalid diwstop_v\n");
2662                         return -EINVAL;
2663                 }
2664
2665                 if (!IS_OCS) {
2666                         /* Initialize sync with some reasonable values for pwrsave */
2667                         par->hsstrt = 160;
2668                         par->hsstop = 320;
2669                         par->vsstrt = 30;
2670                         par->vsstop = 34;
2671                 } else {
2672                         par->hsstrt = 0;
2673                         par->hsstop = 0;
2674                         par->vsstrt = 0;
2675                         par->vsstop = 0;
2676                 }
2677                 if (par->vtotal > (PAL_VTOTAL+NTSC_VTOTAL)/2) {
2678                         /* PAL video mode */
2679                         if (par->htotal != PAL_HTOTAL) {
2680                                 DPRINTK("htotal invalid for pal\n");
2681                                 return -EINVAL;
2682                         }
2683                         if (par->diwstrt_h < PAL_DIWSTRT_H) {
2684                                 DPRINTK("diwstrt_h too low for pal\n");
2685                                 return -EINVAL;
2686                         }
2687                         if (par->diwstrt_v < PAL_DIWSTRT_V) {
2688                                 DPRINTK("diwstrt_v too low for pal\n");
2689                                 return -EINVAL;
2690                         }
2691                         htotal = PAL_HTOTAL>>clk_shift;
2692                         vtotal = PAL_VTOTAL>>1;
2693                         if (!IS_OCS) {
2694                                 par->beamcon0 = BMC0_PAL;
2695                                 par->bplcon3 |= BPC3_BRDRBLNK;
2696                         } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
2697                                    AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
2698                                 par->beamcon0 = BMC0_PAL;
2699                                 par->hsstop = 1;
2700                         } else if (amiga_vblank != 50) {
2701                                 DPRINTK("pal not supported by this chipset\n");
2702                                 return -EINVAL;
2703                         }
2704                 } else {
2705                         /* NTSC video mode
2706                          * In the AGA chipset seems to be hardware bug with BPC3_BRDRBLNK
2707                          * and NTSC activated, so than better let diwstop_h <= 1812
2708                          */
2709                         if (par->htotal != NTSC_HTOTAL) {
2710                                 DPRINTK("htotal invalid for ntsc\n");
2711                                 return -EINVAL;
2712                         }
2713                         if (par->diwstrt_h < NTSC_DIWSTRT_H) {
2714                                 DPRINTK("diwstrt_h too low for ntsc\n");
2715                                 return -EINVAL;
2716                         }
2717                         if (par->diwstrt_v < NTSC_DIWSTRT_V) {
2718                                 DPRINTK("diwstrt_v too low for ntsc\n");
2719                                 return -EINVAL;
2720                         }
2721                         htotal = NTSC_HTOTAL>>clk_shift;
2722                         vtotal = NTSC_VTOTAL>>1;
2723                         if (!IS_OCS) {
2724                                 par->beamcon0 = 0;
2725                                 par->bplcon3 |= BPC3_BRDRBLNK;
2726                         } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
2727                                    AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
2728                                 par->beamcon0 = 0;
2729                                 par->hsstop = 1;
2730                         } else if (amiga_vblank != 60) {
2731                                 DPRINTK("ntsc not supported by this chipset\n");
2732                                 return -EINVAL;
2733                         }
2734                 }
2735                 if (IS_OCS) {
2736                         if (par->diwstrt_h >= 1024 || par->diwstop_h < 1024 ||
2737                             par->diwstrt_v >=  512 || par->diwstop_v <  256) {
2738                                 DPRINTK("invalid position for display on ocs\n");
2739                                 return -EINVAL;
2740                         }
2741                 }
2742         } else if (!IS_OCS) {
2743                 /* Programmable video mode */
2744                 par->hsstrt = var->right_margin<<clk_shift;
2745                 par->hsstop = (var->right_margin+var->hsync_len)<<clk_shift;
2746                 par->diwstop_h = par->htotal - mod8(par->hsstrt) + 8 - (1 << clk_shift);
2747                 if (!IS_AGA)
2748                         par->diwstop_h = down4(par->diwstop_h) - 16;
2749                 par->diwstrt_h = par->diwstop_h - xres_n;
2750                 par->hbstop = par->diwstrt_h + 4;
2751                 par->hbstrt = par->diwstop_h + 4;
2752                 if (par->hbstrt >= par->htotal + 8)
2753                         par->hbstrt -= par->htotal;
2754                 par->hcenter = par->hsstrt + (par->htotal >> 1);
2755                 par->vsstrt = var->lower_margin<<line_shift;
2756                 par->vsstop = (var->lower_margin+var->vsync_len)<<line_shift;
2757                 par->diwstop_v = par->vtotal;
2758                 if ((par->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
2759                         par->diwstop_v -= 2;
2760                 par->diwstrt_v = par->diwstop_v - yres_n;
2761                 par->vbstop = par->diwstrt_v - 2;
2762                 par->vbstrt = par->diwstop_v - 2;
2763                 if (par->vtotal > 2048) {
2764                         DPRINTK("vtotal too high\n");
2765                         return -EINVAL;
2766                 }
2767                 if (par->htotal > 2048) {
2768                         DPRINTK("htotal too high\n");
2769                         return -EINVAL;
2770                 }
2771                 par->bplcon3 |= BPC3_EXTBLKEN;
2772                 par->beamcon0 = BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS |
2773                                 BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN |
2774                                 BMC0_PAL | BMC0_VARCSYEN;
2775                 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
2776                         par->beamcon0 |= BMC0_HSYTRUE;
2777                 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
2778                         par->beamcon0 |= BMC0_VSYTRUE;
2779                 if (var->sync & FB_SYNC_COMP_HIGH_ACT)
2780                         par->beamcon0 |= BMC0_CSYTRUE;
2781                 htotal = par->htotal>>clk_shift;
2782                 vtotal = par->vtotal>>1;
2783         } else {
2784                 DPRINTK("only broadcast modes possible for ocs\n");
2785                 return -EINVAL;
2786         }
2787
2788         /*
2789          * Checking the DMA timing
2790          */
2791
2792         fconst = 16<<maxfmode<<clk_shift;
2793
2794         /*
2795          * smallest window start value without turn off other dma cycles
2796          * than sprite1-7, unless you change min_fstrt
2797          */
2798
2799
2800         fsize = ((maxfmode+clk_shift <= 1) ? fconst : 64);
2801         fstrt = downx(fconst, par->diwstrt_h-4) - fsize;
2802         if (fstrt < min_fstrt) {
2803                 DPRINTK("fetch start too low\n");
2804                 return -EINVAL;
2805         }
2806
2807         /*
2808          * smallest window start value where smooth scrolling is possible
2809          */
2810
2811         fstrt = downx(fconst, par->diwstrt_h-fconst+(1<<clk_shift)-4) - fsize;
2812         if (fstrt < min_fstrt)
2813                 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
2814
2815         maxfetchstop = down16(par->htotal - 80);
2816
2817         fstrt = downx(fconst, par->diwstrt_h-4) - 64 - fconst;
2818         fsize = upx(fconst, xres_n + modx(fconst, downx(1<<clk_shift, par->diwstrt_h-4)));
2819         if (fstrt + fsize > maxfetchstop)
2820                 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
2821
2822         fsize = upx(fconst, xres_n);
2823         if (fstrt + fsize > maxfetchstop) {
2824                 DPRINTK("fetch stop too high\n");
2825                 return -EINVAL;
2826         }
2827
2828         if (maxfmode + clk_shift <= 1) {
2829                 fsize = up64(xres_n + fconst - 1);
2830                 if (min_fstrt + fsize - 64 > maxfetchstop)
2831                         par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
2832
2833                 fsize = up64(xres_n);
2834                 if (min_fstrt + fsize - 64 > maxfetchstop) {
2835                         DPRINTK("fetch size too high\n");
2836                         return -EINVAL;
2837                 }
2838
2839                 fsize -= 64;
2840         } else
2841                 fsize -= fconst;
2842
2843         /*
2844          * Check if there is enough time to update the bitplane pointers for ywrap
2845          */
2846
2847         if (par->htotal-fsize-64 < par->bpp*64)
2848                 par->vmode &= ~FB_VMODE_YWRAP;
2849
2850         /*
2851          * Bitplane calculations and check the Memory Requirements
2852          */
2853
2854         if (amifb_ilbm) {
2855                 par->next_plane = div8(upx(16<<maxfmode, par->vxres));
2856                 par->next_line = par->bpp*par->next_plane;
2857                 if (par->next_line * par->vyres > fb_info.fix.smem_len) {
2858                         DPRINTK("too few video mem\n");
2859                         return -EINVAL;
2860                 }
2861         } else {
2862                 par->next_line = div8(upx(16<<maxfmode, par->vxres));
2863                 par->next_plane = par->vyres*par->next_line;
2864                 if (par->next_plane * par->bpp > fb_info.fix.smem_len) {
2865                         DPRINTK("too few video mem\n");
2866                         return -EINVAL;
2867                 }
2868         }
2869
2870         /*
2871          * Hardware Register Values
2872          */
2873
2874         par->bplcon0 = BPC0_COLOR | bplpixmode[clk_shift];
2875         if (!IS_OCS)
2876                 par->bplcon0 |= BPC0_ECSENA;
2877         if (par->bpp == 8)
2878                 par->bplcon0 |= BPC0_BPU3;
2879         else
2880                 par->bplcon0 |= par->bpp<<12;
2881         if (var->nonstd == FB_NONSTD_HAM)
2882                 par->bplcon0 |= BPC0_HAM;
2883         if (var->sync & FB_SYNC_EXT)
2884                 par->bplcon0 |= BPC0_ERSY;
2885
2886         if (IS_AGA)
2887                 par->fmode = bplfetchmode[maxfmode];
2888
2889         switch (par->vmode & FB_VMODE_MASK) {
2890                 case FB_VMODE_INTERLACED:
2891                         par->bplcon0 |= BPC0_LACE;
2892                         break;
2893                 case FB_VMODE_DOUBLE:
2894                         if (IS_AGA)
2895                                 par->fmode |= FMODE_SSCAN2 | FMODE_BSCAN2;
2896                         break;
2897         }
2898
2899         if (!((par->vmode ^ var->vmode) & FB_VMODE_YWRAP)) {
2900                 par->xoffset = var->xoffset;
2901                 par->yoffset = var->yoffset;
2902                 if (par->vmode & FB_VMODE_YWRAP) {
2903                         if (par->xoffset || par->yoffset < 0 || par->yoffset >= par->vyres)
2904                                 par->xoffset = par->yoffset = 0;
2905                 } else {
2906                         if (par->xoffset < 0 || par->xoffset > upx(16<<maxfmode, par->vxres-par->xres) ||
2907                             par->yoffset < 0 || par->yoffset > par->vyres-par->yres)
2908                                 par->xoffset = par->yoffset = 0;
2909                 }
2910         } else
2911                 par->xoffset = par->yoffset = 0;
2912
2913         par->crsr.crsr_x = par->crsr.crsr_y = 0;
2914         par->crsr.spot_x = par->crsr.spot_y = 0;
2915         par->crsr.height = par->crsr.width = 0;
2916
2917         return 0;
2918 }
2919
2920         /*
2921          * Fill the `var' structure based on the values in `par' and maybe
2922          * other values read out of the hardware.
2923          */
2924
2925 static int ami_encode_var(struct fb_var_screeninfo *var,
2926                           struct amifb_par *par)
2927 {
2928         u_short clk_shift, line_shift;
2929
2930         memset(var, 0, sizeof(struct fb_var_screeninfo));
2931
2932         clk_shift = par->clk_shift;
2933         line_shift = par->line_shift;
2934
2935         var->xres = par->xres;
2936         var->yres = par->yres;
2937         var->xres_virtual = par->vxres;
2938         var->yres_virtual = par->vyres;
2939         var->xoffset = par->xoffset;
2940         var->yoffset = par->yoffset;
2941
2942         var->bits_per_pixel = par->bpp;
2943         var->grayscale = 0;
2944
2945         var->red.offset = 0;
2946         var->red.msb_right = 0;
2947         var->red.length = par->bpp;
2948         if (par->bplcon0 & BPC0_HAM)
2949             var->red.length -= 2;
2950         var->blue = var->green = var->red;
2951         var->transp.offset = 0;
2952         var->transp.length = 0;
2953         var->transp.msb_right = 0;
2954
2955         if (par->bplcon0 & BPC0_HAM)
2956                 var->nonstd = FB_NONSTD_HAM;
2957         else
2958                 var->nonstd = 0;
2959         var->activate = 0;
2960
2961         var->height = -1;
2962         var->width = -1;
2963
2964         var->pixclock = pixclock[clk_shift];
2965
2966         if (IS_AGA && par->fmode & FMODE_BSCAN2)
2967                 var->vmode = FB_VMODE_DOUBLE;
2968         else if (par->bplcon0 & BPC0_LACE)
2969                 var->vmode = FB_VMODE_INTERLACED;
2970         else
2971                 var->vmode = FB_VMODE_NONINTERLACED;
2972
2973         if (!IS_OCS && par->beamcon0 & BMC0_VARBEAMEN) {
2974                 var->hsync_len = (par->hsstop-par->hsstrt)>>clk_shift;
2975                 var->right_margin = par->hsstrt>>clk_shift;
2976                 var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
2977                 var->vsync_len = (par->vsstop-par->vsstrt)>>line_shift;
2978                 var->lower_margin = par->vsstrt>>line_shift;
2979                 var->upper_margin = (par->vtotal>>line_shift) - var->yres - var->lower_margin - var->vsync_len;
2980                 var->sync = 0;
2981                 if (par->beamcon0 & BMC0_HSYTRUE)
2982                         var->sync |= FB_SYNC_HOR_HIGH_ACT;
2983                 if (par->beamcon0 & BMC0_VSYTRUE)
2984                         var->sync |= FB_SYNC_VERT_HIGH_ACT;
2985                 if (par->beamcon0 & BMC0_CSYTRUE)
2986                         var->sync |= FB_SYNC_COMP_HIGH_ACT;
2987         } else {
2988                 var->sync = FB_SYNC_BROADCAST;
2989                 var->hsync_len = (152>>clk_shift) + mod4(par->diwstop_h);
2990                 var->right_margin = ((par->htotal - down4(par->diwstop_h))>>clk_shift) + var->hsync_len;
2991                 var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
2992                 var->vsync_len = 4>>line_shift;
2993                 var->lower_margin = ((par->vtotal - par->diwstop_v)>>line_shift) + var->vsync_len;
2994                 var->upper_margin = (((par->vtotal - 2)>>line_shift) + 1) - var->yres -
2995                                     var->lower_margin - var->vsync_len;
2996         }
2997
2998         if (par->bplcon0 & BPC0_ERSY)
2999                 var->sync |= FB_SYNC_EXT;
3000         if (par->vmode & FB_VMODE_YWRAP)
3001                 var->vmode |= FB_VMODE_YWRAP;
3002
3003         return 0;
3004 }
3005
3006
3007         /*
3008          * Pan or Wrap the Display
3009          *
3010          * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
3011          * in `var'.
3012          */
3013
3014 static void ami_pan_var(struct fb_var_screeninfo *var)
3015 {
3016         struct amifb_par *par = &currentpar;
3017
3018         par->xoffset = var->xoffset;
3019         par->yoffset = var->yoffset;
3020         if (var->vmode & FB_VMODE_YWRAP)
3021                 par->vmode |= FB_VMODE_YWRAP;
3022         else
3023                 par->vmode &= ~FB_VMODE_YWRAP;
3024
3025         do_vmode_pan = 0;
3026         ami_update_par();
3027         do_vmode_pan = 1;
3028 }
3029
3030         /*
3031          * Update hardware
3032          */
3033
3034 static int ami_update_par(void)
3035 {
3036         struct amifb_par *par = &currentpar;
3037         short clk_shift, vshift, fstrt, fsize, fstop, fconst,  shift, move, mod;
3038
3039         clk_shift = par->clk_shift;
3040
3041         if (!(par->vmode & FB_VMODE_SMOOTH_XPAN))
3042                 par->xoffset = upx(16<<maxfmode, par->xoffset);
3043
3044         fconst = 16<<maxfmode<<clk_shift;
3045         vshift = modx(16<<maxfmode, par->xoffset);
3046         fstrt = par->diwstrt_h - (vshift<<clk_shift) - 4;
3047         fsize = (par->xres+vshift)<<clk_shift;
3048         shift = modx(fconst, fstrt);
3049         move = downx(2<<maxfmode, div8(par->xoffset));
3050         if (maxfmode + clk_shift > 1) {
3051                 fstrt = downx(fconst, fstrt) - 64;
3052                 fsize = upx(fconst, fsize);
3053                 fstop = fstrt + fsize - fconst;
3054         } else {
3055                 mod = fstrt = downx(fconst, fstrt) - fconst;
3056                 fstop = fstrt + upx(fconst, fsize) - 64;
3057                 fsize = up64(fsize);
3058                 fstrt = fstop - fsize + 64;
3059                 if (fstrt < min_fstrt) {
3060                         fstop += min_fstrt - fstrt;
3061                         fstrt = min_fstrt;
3062                 }
3063                 move = move - div8((mod-fstrt)>>clk_shift);
3064         }
3065         mod = par->next_line - div8(fsize>>clk_shift);
3066         par->ddfstrt = fstrt;
3067         par->ddfstop = fstop;
3068         par->bplcon1 = hscroll2hw(shift);
3069         par->bpl2mod = mod;
3070         if (par->bplcon0 & BPC0_LACE)
3071                 par->bpl2mod += par->next_line;
3072         if (IS_AGA && (par->fmode & FMODE_BSCAN2))
3073                 par->bpl1mod = -div8(fsize>>clk_shift);
3074         else
3075                 par->bpl1mod = par->bpl2mod;
3076
3077         if (par->yoffset) {
3078                 par->bplpt0 = fb_info.fix.smem_start + par->next_line*par->yoffset + move;
3079                 if (par->vmode & FB_VMODE_YWRAP) {
3080                         if (par->yoffset > par->vyres-par->yres) {
3081                                 par->bplpt0wrap = fb_info.fix.smem_start + move;
3082                                 if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v+par->vyres-par->yoffset))
3083                                         par->bplpt0wrap += par->next_line;
3084                         }
3085                 }
3086         } else
3087                 par->bplpt0 = fb_info.fix.smem_start + move;
3088
3089         if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v))
3090                 par->bplpt0 += par->next_line;
3091
3092         return 0;
3093 }
3094
3095
3096         /*
3097          * Set a single color register. The values supplied are already
3098          * rounded down to the hardware's capabilities (according to the
3099          * entries in the var structure). Return != 0 for invalid regno.
3100          */
3101
3102 static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
3103                            u_int transp, struct fb_info *info)
3104 {
3105         if (IS_AGA) {
3106                 if (regno > 255)
3107                         return 1;
3108         } else if (currentpar.bplcon0 & BPC0_SHRES) {
3109                 if (regno > 3)
3110                         return 1;
3111         } else {
3112                 if (regno > 31)
3113                         return 1;
3114         }
3115         red >>= 8;
3116         green >>= 8;
3117         blue >>= 8;
3118         if (!regno) {
3119                 red0 = red;
3120                 green0 = green;
3121                 blue0 = blue;
3122         }
3123
3124         /*
3125          * Update the corresponding Hardware Color Register, unless it's Color
3126          * Register 0 and the screen is blanked.
3127          *
3128          * VBlank is switched off to protect bplcon3 or ecs_palette[] from
3129          * being changed by ami_do_blank() during the VBlank.
3130          */
3131
3132         if (regno || !is_blanked) {
3133 #if defined(CONFIG_FB_AMIGA_AGA)
3134                 if (IS_AGA) {
3135                         u_short bplcon3 = currentpar.bplcon3;
3136                         VBlankOff();
3137                         custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000);
3138                         custom.color[regno&31] = rgb2hw8_high(red, green, blue);
3139                         custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000) | BPC3_LOCT;
3140                         custom.color[regno&31] = rgb2hw8_low(red, green, blue);
3141                         custom.bplcon3 = bplcon3;
3142                         VBlankOn();
3143                 } else
3144 #endif
3145 #if defined(CONFIG_FB_AMIGA_ECS)
3146                 if (currentpar.bplcon0 & BPC0_SHRES) {
3147                         u_short color, mask;
3148                         int i;
3149
3150                         mask = 0x3333;
3151                         color = rgb2hw2(red, green, blue);
3152                         VBlankOff();
3153                         for (i = regno+12; i >= (int)regno; i -= 4)
3154                                 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3155                         mask <<=2; color >>= 2;
3156                         regno = down16(regno)+mul4(mod4(regno));
3157                         for (i = regno+3; i >= (int)regno; i--)
3158                                 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3159                         VBlankOn();
3160                 } else
3161 #endif
3162                         custom.color[regno] = rgb2hw4(red, green, blue);
3163         }
3164         return 0;
3165 }
3166
3167 static void ami_update_display(void)
3168 {
3169         struct amifb_par *par = &currentpar;
3170
3171         custom.bplcon1 = par->bplcon1;
3172         custom.bpl1mod = par->bpl1mod;
3173         custom.bpl2mod = par->bpl2mod;
3174         custom.ddfstrt = ddfstrt2hw(par->ddfstrt);
3175         custom.ddfstop = ddfstop2hw(par->ddfstop);
3176 }
3177
3178         /*
3179          * Change the video mode (called by VBlank interrupt)
3180          */
3181
3182 static void ami_init_display(void)
3183 {
3184         struct amifb_par *par = &currentpar;
3185         int i;
3186
3187         custom.bplcon0 = par->bplcon0 & ~BPC0_LACE;
3188         custom.bplcon2 = (IS_OCS ? 0 : BPC2_KILLEHB) | BPC2_PF2P2 | BPC2_PF1P2;
3189         if (!IS_OCS) {
3190                 custom.bplcon3 = par->bplcon3;
3191                 if (IS_AGA)
3192                         custom.bplcon4 = BPC4_ESPRM4 | BPC4_OSPRM4;
3193                 if (par->beamcon0 & BMC0_VARBEAMEN) {
3194                         custom.htotal = htotal2hw(par->htotal);
3195                         custom.hbstrt = hbstrt2hw(par->hbstrt);
3196                         custom.hbstop = hbstop2hw(par->hbstop);
3197                         custom.hsstrt = hsstrt2hw(par->hsstrt);
3198                         custom.hsstop = hsstop2hw(par->hsstop);
3199                         custom.hcenter = hcenter2hw(par->hcenter);
3200                         custom.vtotal = vtotal2hw(par->vtotal);
3201                         custom.vbstrt = vbstrt2hw(par->vbstrt);
3202                         custom.vbstop = vbstop2hw(par->vbstop);
3203                         custom.vsstrt = vsstrt2hw(par->vsstrt);
3204                         custom.vsstop = vsstop2hw(par->vsstop);
3205                 }
3206         }
3207         if (!IS_OCS || par->hsstop)
3208                 custom.beamcon0 = par->beamcon0;
3209         if (IS_AGA)
3210                 custom.fmode = par->fmode;
3211
3212         /*
3213          * The minimum period for audio depends on htotal
3214          */
3215
3216         amiga_audio_min_period = div16(par->htotal);
3217
3218         is_lace = par->bplcon0 & BPC0_LACE ? 1 : 0;
3219 #if 1
3220         if (is_lace) {
3221                 i = custom.vposr >> 15;
3222         } else {
3223                 custom.vposw = custom.vposr | 0x8000;
3224                 i = 1;
3225         }
3226 #else
3227         i = 1;
3228         custom.vposw = custom.vposr | 0x8000;
3229 #endif
3230         custom.cop2lc = (u_short *)ZTWO_PADDR(copdisplay.list[currentcop][i]);
3231 }
3232
3233         /*
3234          * (Un)Blank the screen (called by VBlank interrupt)
3235          */
3236
3237 static void ami_do_blank(void)
3238 {
3239         struct amifb_par *par = &currentpar;
3240 #if defined(CONFIG_FB_AMIGA_AGA)
3241         u_short bplcon3 = par->bplcon3;
3242 #endif
3243         u_char red, green, blue;
3244
3245         if (do_blank > 0) {
3246                 custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
3247                 red = green = blue = 0;
3248                 if (!IS_OCS && do_blank > 1) {
3249                         switch (do_blank) {
3250                                 case FB_BLANK_VSYNC_SUSPEND:
3251                                         custom.hsstrt = hsstrt2hw(par->hsstrt);
3252                                         custom.hsstop = hsstop2hw(par->hsstop);
3253                                         custom.vsstrt = vsstrt2hw(par->vtotal+4);
3254                                         custom.vsstop = vsstop2hw(par->vtotal+4);
3255                                         break;
3256                                 case FB_BLANK_HSYNC_SUSPEND:
3257                                         custom.hsstrt = hsstrt2hw(par->htotal+16);
3258                                         custom.hsstop = hsstop2hw(par->htotal+16);
3259                                         custom.vsstrt = vsstrt2hw(par->vsstrt);
3260                                         custom.vsstop = vsstrt2hw(par->vsstop);
3261                                         break;
3262                                 case FB_BLANK_POWERDOWN:
3263                                         custom.hsstrt = hsstrt2hw(par->htotal+16);
3264                                         custom.hsstop = hsstop2hw(par->htotal+16);
3265                                         custom.vsstrt = vsstrt2hw(par->vtotal+4);
3266                                         custom.vsstop = vsstop2hw(par->vtotal+4);
3267                                         break;
3268                         }
3269                         if (!(par->beamcon0 & BMC0_VARBEAMEN)) {
3270                                 custom.htotal = htotal2hw(par->htotal);
3271                                 custom.vtotal = vtotal2hw(par->vtotal);
3272                                 custom.beamcon0 = BMC0_HARDDIS | BMC0_VARBEAMEN |
3273                                                   BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARCSYEN;
3274                         }
3275                 }
3276         } else {
3277                 custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_SPRITE;
3278                 red = red0;
3279                 green = green0;
3280                 blue = blue0;
3281                 if (!IS_OCS) {
3282                         custom.hsstrt = hsstrt2hw(par->hsstrt);
3283                         custom.hsstop = hsstop2hw(par->hsstop);
3284                         custom.vsstrt = vsstrt2hw(par->vsstrt);
3285                         custom.vsstop = vsstop2hw(par->vsstop);
3286                         custom.beamcon0 = par->beamcon0;
3287                 }
3288         }
3289 #if defined(CONFIG_FB_AMIGA_AGA)
3290         if (IS_AGA) {
3291                 custom.bplcon3 = bplcon3;
3292                 custom.color[0] = rgb2hw8_high(red, green, blue);
3293                 custom.bplcon3 = bplcon3 | BPC3_LOCT;
3294                 custom.color[0] = rgb2hw8_low(red, green, blue);
3295                 custom.bplcon3 = bplcon3;
3296         } else
3297 #endif
3298 #if defined(CONFIG_FB_AMIGA_ECS)
3299         if (par->bplcon0 & BPC0_SHRES) {
3300                 u_short color, mask;
3301                 int i;
3302
3303                 mask = 0x3333;
3304                 color = rgb2hw2(red, green, blue);
3305                 for (i = 12; i >= 0; i -= 4)
3306                         custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3307                 mask <<=2; color >>= 2;
3308                 for (i = 3; i >= 0; i--)
3309                         custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3310         } else
3311 #endif
3312                 custom.color[0] = rgb2hw4(red, green, blue);
3313         is_blanked = do_blank > 0 ? do_blank : 0;
3314 }
3315
3316 static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix)
3317 {
3318         struct amifb_par *par = &currentpar;
3319
3320         fix->crsr_width = fix->crsr_xsize = par->crsr.width;
3321         fix->crsr_height = fix->crsr_ysize = par->crsr.height;
3322         fix->crsr_color1 = 17;
3323         fix->crsr_color2 = 18;
3324         return 0;
3325 }
3326
3327 static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data)
3328 {
3329         struct amifb_par *par = &currentpar;
3330         register u_short *lspr, *sspr;
3331 #ifdef __mc68000__
3332         register u_long datawords asm ("d2");
3333 #else
3334         register u_long datawords;
3335 #endif
3336         register short delta;
3337         register u_char color;
3338         short height, width, bits, words;
3339         int size, alloc;
3340
3341         size = par->crsr.height*par->crsr.width;
3342         alloc = var->height*var->width;
3343         var->height = par->crsr.height;
3344         var->width = par->crsr.width;
3345         var->xspot = par->crsr.spot_x;
3346         var->yspot = par->crsr.spot_y;
3347         if (size > var->height*var->width)
3348                 return -ENAMETOOLONG;
3349         if (!access_ok(VERIFY_WRITE, data, size))
3350                 return -EFAULT;
3351         delta = 1<<par->crsr.fmode;
3352         lspr = lofsprite + (delta<<1);
3353         if (par->bplcon0 & BPC0_LACE)
3354                 sspr = shfsprite + (delta<<1);
3355         else
3356                 sspr = NULL;
3357         for (height = (short)var->height-1; height >= 0; height--) {
3358                 bits = 0; words = delta; datawords = 0;
3359                 for (width = (short)var->width-1; width >= 0; width--) {
3360                         if (bits == 0) {
3361                                 bits = 16; --words;
3362 #ifdef __mc68000__
3363                                 asm volatile ("movew %1@(%3:w:2),%0 ; swap %0 ; movew %1@+,%0"
3364                                         : "=d" (datawords), "=a" (lspr) : "1" (lspr), "d" (delta));
3365 #else
3366                                 datawords = (*(lspr+delta) << 16) | (*lspr++);
3367 #endif
3368                         }
3369                         --bits;
3370 #ifdef __mc68000__
3371                         asm volatile (
3372                                 "clrb %0 ; swap %1 ; lslw #1,%1 ; roxlb #1,%0 ; "
3373                                 "swap %1 ; lslw #1,%1 ; roxlb #1,%0"
3374                                 : "=d" (color), "=d" (datawords) : "1" (datawords));
3375 #else
3376                         color = (((datawords >> 30) & 2)
3377                                  | ((datawords >> 15) & 1));
3378                         datawords <<= 1;
3379 #endif
3380                         put_user(color, data++);
3381                 }
3382                 if (bits > 0) {
3383                         --words; ++lspr;
3384                 }
3385                 while (--words >= 0)
3386                         ++lspr;
3387 #ifdef __mc68000__
3388                 asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
3389                         : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
3390 #else
3391                 lspr += delta;
3392                 if (sspr) {
3393                         u_short *tmp = lspr;
3394                         lspr = sspr;
3395                         sspr = tmp;
3396                 }
3397 #endif
3398         }
3399         return 0;
3400 }
3401
3402 static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data)
3403 {
3404         struct amifb_par *par = &currentpar;
3405         register u_short *lspr, *sspr;
3406 #ifdef __mc68000__
3407         register u_long datawords asm ("d2");
3408 #else
3409         register u_long datawords;
3410 #endif
3411         register short delta;
3412         u_short fmode;
3413         short height, width, bits, words;
3414
3415         if (!var->width)
3416                 return -EINVAL;
3417         else if (var->width <= 16)
3418                 fmode = TAG_FMODE_1;
3419         else if (var->width <= 32)
3420                 fmode = TAG_FMODE_2;
3421         else if (var->width <= 64)
3422                 fmode = TAG_FMODE_4;
3423         else
3424                 return -EINVAL;
3425         if (fmode > maxfmode)
3426                 return -EINVAL;
3427         if (!var->height)
3428                 return -EINVAL;
3429         if (!access_ok(VERIFY_READ, data, var->width*var->height))
3430                 return -EFAULT;
3431         delta = 1<<fmode;
3432         lofsprite = shfsprite = (u_short *)spritememory;
3433         lspr = lofsprite + (delta<<1);
3434         if (par->bplcon0 & BPC0_LACE) {
3435                 if (((var->height+4)<<fmode<<2) > SPRITEMEMSIZE)
3436                         return -EINVAL;
3437                 memset(lspr, 0, (var->height+4)<<fmode<<2);
3438                 shfsprite += ((var->height+5)&-2)<<fmode;
3439                 sspr = shfsprite + (delta<<1);
3440         } else {
3441                 if (((var->height+2)<<fmode<<2) > SPRITEMEMSIZE)
3442                         return -EINVAL;
3443                 memset(lspr, 0, (var->height+2)<<fmode<<2);
3444                 sspr = NULL;
3445         }
3446         for (height = (short)var->height-1; height >= 0; height--) {
3447                 bits = 16; words = delta; datawords = 0;
3448                 for (width = (short)var->width-1; width >= 0; width--) {
3449                         unsigned long tdata = 0;
3450                         get_user(tdata, data);
3451                         data++;
3452 #ifdef __mc68000__
3453                         asm volatile (
3454                                 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0 ; "
3455                                 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0"
3456                                 : "=d" (datawords)
3457                                 : "0" (datawords), "d" (tdata));
3458 #else
3459                         datawords = ((datawords << 1) & 0xfffefffe);
3460                         datawords |= tdata & 1;
3461                         datawords |= (tdata & 2) << (16-1);
3462 #endif
3463                         if (--bits == 0) {
3464                                 bits = 16; --words;
3465 #ifdef __mc68000__
3466                                 asm volatile ("swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+"
3467                                         : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta));
3468 #else
3469                                 *(lspr+delta) = (u_short) (datawords >> 16);
3470                                 *lspr++ = (u_short) (datawords & 0xffff);
3471 #endif
3472                         }
3473                 }
3474                 if (bits < 16) {
3475                         --words;
3476 #ifdef __mc68000__
3477                         asm volatile (
3478                                 "swap %2 ; lslw %4,%2 ; movew %2,%0@(%3:w:2) ; "
3479                                 "swap %2 ; lslw %4,%2 ; movew %2,%0@+"
3480                                 : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta), "d" (bits));
3481 #else
3482                         *(lspr+delta) = (u_short) (datawords >> (16+bits));
3483                         *lspr++ = (u_short) ((datawords & 0x0000ffff) >> bits);
3484 #endif
3485                 }
3486                 while (--words >= 0) {
3487 #ifdef __mc68000__
3488                         asm volatile ("moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+"
3489                                 : "=a" (lspr) : "0" (lspr), "d" (delta) : "d0");
3490 #else
3491                         *(lspr+delta) = 0;
3492                         *lspr++ = 0;
3493 #endif
3494                 }
3495 #ifdef __mc68000__
3496                 asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
3497                         : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
3498 #else
3499                 lspr += delta;
3500                 if (sspr) {
3501                         u_short *tmp = lspr;
3502                         lspr = sspr;
3503                         sspr = tmp;
3504                 }
3505 #endif
3506         }
3507         par->crsr.height = var->height;
3508         par->crsr.width = var->width;
3509         par->crsr.spot_x = var->xspot;
3510         par->crsr.spot_y = var->yspot;
3511         par->crsr.fmode = fmode;
3512         if (IS_AGA) {
3513                 par->fmode &= ~(FMODE_SPAGEM | FMODE_SPR32);
3514                 par->fmode |= sprfetchmode[fmode];
3515                 custom.fmode = par->fmode;
3516         }
3517         return 0;
3518 }
3519
3520 static int ami_get_cursorstate(struct fb_cursorstate *state)
3521 {
3522         struct amifb_par *par = &currentpar;
3523
3524         state->xoffset = par->crsr.crsr_x;
3525         state->yoffset = par->crsr.crsr_y;
3526         state->mode = cursormode;
3527         return 0;
3528 }
3529
3530 static int ami_set_cursorstate(struct fb_cursorstate *state)
3531 {
3532         struct amifb_par *par = &currentpar;
3533
3534         par->crsr.crsr_x = state->xoffset;
3535         par->crsr.crsr_y = state->yoffset;
3536         if ((cursormode = state->mode) == FB_CURSOR_OFF)
3537                 cursorstate = -1;
3538         do_cursor = 1;
3539         return 0;
3540 }
3541
3542 static void ami_set_sprite(void)
3543 {
3544         struct amifb_par *par = &currentpar;
3545         copins *copl, *cops;
3546         u_short hs, vs, ve;
3547         u_long pl, ps, pt;
3548         short mx, my;
3549
3550         cops = copdisplay.list[currentcop][0];
3551         copl = copdisplay.list[currentcop][1];
3552         ps = pl = ZTWO_PADDR(dummysprite);
3553         mx = par->crsr.crsr_x-par->crsr.spot_x;
3554         my = par->crsr.crsr_y-par->crsr.spot_y;
3555         if (!(par->vmode & FB_VMODE_YWRAP)) {
3556                 mx -= par->xoffset;
3557                 my -= par->yoffset;
3558         }
3559         if (!is_blanked && cursorstate > 0 && par->crsr.height > 0 &&
3560             mx > -(short)par->crsr.width && mx < par->xres &&
3561             my > -(short)par->crsr.height && my < par->yres) {
3562                 pl = ZTWO_PADDR(lofsprite);
3563                 hs = par->diwstrt_h + (mx<<par->clk_shift) - 4;
3564                 vs = par->diwstrt_v + (my<<par->line_shift);
3565                 ve = vs + (par->crsr.height<<par->line_shift);
3566                 if (par->bplcon0 & BPC0_LACE) {
3567                         ps = ZTWO_PADDR(shfsprite);
3568                         lofsprite[0] = spr2hw_pos(vs, hs);
3569                         shfsprite[0] = spr2hw_pos(vs+1, hs);
3570                         if (mod2(vs)) {
3571                                 lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
3572                                 shfsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs+1, hs, ve+1);
3573                                 pt = pl; pl = ps; ps = pt;
3574                         } else {
3575                                 lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve+1);
3576                                 shfsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs+1, hs, ve);
3577                         }
3578                 } else {
3579                         lofsprite[0] = spr2hw_pos(vs, hs) | (IS_AGA && (par->fmode & FMODE_BSCAN2) ? 0x80 : 0);
3580                         lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
3581                 }
3582         }
3583         copl[cop_spr0ptrh].w[1] = highw(pl);
3584         copl[cop_spr0ptrl].w[1] = loww(pl);
3585         if (par->bplcon0 & BPC0_LACE) {
3586                 cops[cop_spr0ptrh].w[1] = highw(ps);
3587                 cops[cop_spr0ptrl].w[1] = loww(ps);
3588         }
3589 }
3590
3591
3592         /*
3593          * Initialise the Copper Initialisation List
3594          */
3595
3596 static void __init ami_init_copper(void)
3597 {
3598         copins *cop = copdisplay.init;
3599         u_long p;
3600         int i;
3601
3602         if (!IS_OCS) {
3603                 (cop++)->l = CMOVE(BPC0_COLOR | BPC0_SHRES | BPC0_ECSENA, bplcon0);
3604                 (cop++)->l = CMOVE(0x0181, diwstrt);
3605                 (cop++)->l = CMOVE(0x0281, diwstop);
3606                 (cop++)->l = CMOVE(0x0000, diwhigh);
3607         } else
3608                 (cop++)->l = CMOVE(BPC0_COLOR, bplcon0);
3609         p = ZTWO_PADDR(dummysprite);
3610         for (i = 0; i < 8; i++) {
3611                 (cop++)->l = CMOVE(0, spr[i].pos);
3612                 (cop++)->l = CMOVE(highw(p), sprpt[i]);
3613                 (cop++)->l = CMOVE2(loww(p), sprpt[i]);
3614         }
3615
3616         (cop++)->l = CMOVE(IF_SETCLR | IF_COPER, intreq);
3617         copdisplay.wait = cop;
3618         (cop++)->l = CEND;
3619         (cop++)->l = CMOVE(0, copjmp2);
3620         cop->l = CEND;
3621
3622         custom.cop1lc = (u_short *)ZTWO_PADDR(copdisplay.init);
3623         custom.copjmp1 = 0;
3624 }
3625
3626 static void ami_reinit_copper(void)
3627 {
3628         struct amifb_par *par = &currentpar;
3629
3630         copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0;
3631         copdisplay.wait->l = CWAIT(32, par->diwstrt_v-4);
3632 }
3633
3634         /*
3635          * Build the Copper List
3636          */
3637
3638 static void ami_build_copper(void)
3639 {
3640         struct amifb_par *par = &currentpar;
3641         copins *copl, *cops;
3642         u_long p;
3643
3644         currentcop = 1 - currentcop;
3645
3646         copl = copdisplay.list[currentcop][1];
3647
3648         (copl++)->l = CWAIT(0, 10);
3649         (copl++)->l = CMOVE(par->bplcon0, bplcon0);
3650         (copl++)->l = CMOVE(0, sprpt[0]);
3651         (copl++)->l = CMOVE2(0, sprpt[0]);
3652
3653         if (par->bplcon0 & BPC0_LACE) {
3654                 cops = copdisplay.list[currentcop][0];
3655
3656                 (cops++)->l = CWAIT(0, 10);
3657                 (cops++)->l = CMOVE(par->bplcon0, bplcon0);
3658                 (cops++)->l = CMOVE(0, sprpt[0]);
3659                 (cops++)->l = CMOVE2(0, sprpt[0]);
3660
3661                 (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v+1), diwstrt);
3662                 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v+1), diwstop);
3663                 (cops++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
3664                 (cops++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
3665                 if (!IS_OCS) {
3666                         (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v+1,
3667                                             par->diwstop_h, par->diwstop_v+1), diwhigh);
3668                         (cops++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
3669                                             par->diwstop_h, par->diwstop_v), diwhigh);
3670 #if 0
3671                         if (par->beamcon0 & BMC0_VARBEAMEN) {
3672                                 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
3673                                 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt+1), vbstrt);
3674                                 (copl++)->l = CMOVE(vbstop2hw(par->vbstop+1), vbstop);
3675                                 (cops++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
3676                                 (cops++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
3677                                 (cops++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
3678                         }
3679 #endif
3680                 }
3681                 p = ZTWO_PADDR(copdisplay.list[currentcop][0]);
3682                 (copl++)->l = CMOVE(highw(p), cop2lc);
3683                 (copl++)->l = CMOVE2(loww(p), cop2lc);
3684                 p = ZTWO_PADDR(copdisplay.list[currentcop][1]);
3685                 (cops++)->l = CMOVE(highw(p), cop2lc);
3686                 (cops++)->l = CMOVE2(loww(p), cop2lc);
3687                 copdisplay.rebuild[0] = cops;
3688         } else {
3689                 (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
3690                 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
3691                 if (!IS_OCS) {
3692                         (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
3693                                             par->diwstop_h, par->diwstop_v), diwhigh);
3694 #if 0
3695                         if (par->beamcon0 & BMC0_VARBEAMEN) {
3696                                 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
3697                                 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
3698                                 (copl++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
3699                         }
3700 #endif
3701                 }
3702         }
3703         copdisplay.rebuild[1] = copl;
3704
3705         ami_update_par();
3706         ami_rebuild_copper();
3707 }
3708
3709         /*
3710          * Rebuild the Copper List
3711          *
3712          * We only change the things that are not static
3713          */
3714
3715 static void ami_rebuild_copper(void)
3716 {
3717         struct amifb_par *par = &currentpar;
3718         copins *copl, *cops;
3719         u_short line, h_end1, h_end2;
3720         short i;
3721         u_long p;
3722
3723         if (IS_AGA && maxfmode + par->clk_shift == 0)
3724                 h_end1 = par->diwstrt_h-64;
3725         else
3726                 h_end1 = par->htotal-32;
3727         h_end2 = par->ddfstop+64;
3728
3729         ami_set_sprite();
3730
3731         copl = copdisplay.rebuild[1];
3732         p = par->bplpt0;
3733         if (par->vmode & FB_VMODE_YWRAP) {
3734                 if ((par->vyres-par->yoffset) != 1 || !mod2(par->diwstrt_v)) {
3735                         if (par->yoffset > par->vyres-par->yres) {
3736                                 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3737                                         (copl++)->l = CMOVE(highw(p), bplpt[i]);
3738                                         (copl++)->l = CMOVE2(loww(p), bplpt[i]);
3739                                 }
3740                                 line = par->diwstrt_v + ((par->vyres-par->yoffset)<<par->line_shift) - 1;
3741                                 while (line >= 512) {
3742                                         (copl++)->l = CWAIT(h_end1, 510);
3743                                         line -= 512;
3744                                 }
3745                                 if (line >= 510 && IS_AGA && maxfmode + par->clk_shift == 0)
3746                                         (copl++)->l = CWAIT(h_end1, line);
3747                                 else
3748                                         (copl++)->l = CWAIT(h_end2, line);
3749                                 p = par->bplpt0wrap;
3750                         }
3751                 } else p = par->bplpt0wrap;
3752         }
3753         for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3754                 (copl++)->l = CMOVE(highw(p), bplpt[i]);
3755                 (copl++)->l = CMOVE2(loww(p), bplpt[i]);
3756         }
3757         copl->l = CEND;
3758
3759         if (par->bplcon0 & BPC0_LACE) {
3760                 cops = copdisplay.rebuild[0];
3761                 p = par->bplpt0;
3762                 if (mod2(par->diwstrt_v))
3763                         p -= par->next_line;
3764                 else
3765                         p += par->next_line;
3766                 if (par->vmode & FB_VMODE_YWRAP) {
3767                         if ((par->vyres-par->yoffset) != 1 || mod2(par->diwstrt_v)) {
3768                                 if (par->yoffset > par->vyres-par->yres+1) {
3769                                         for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3770                                                 (cops++)->l = CMOVE(highw(p), bplpt[i]);
3771                                                 (cops++)->l = CMOVE2(loww(p), bplpt[i]);
3772                                         }
3773                                         line = par->diwstrt_v + ((par->vyres-par->yoffset)<<par->line_shift) - 2;
3774                                         while (line >= 512) {
3775                                                 (cops++)->l = CWAIT(h_end1, 510);
3776                                                 line -= 512;
3777                                         }
3778                                         if (line > 510 && IS_AGA && maxfmode + par->clk_shift == 0)
3779                                                 (cops++)->l = CWAIT(h_end1, line);
3780                                         else
3781                                                 (cops++)->l = CWAIT(h_end2, line);
3782                                         p = par->bplpt0wrap;
3783                                         if (mod2(par->diwstrt_v+par->vyres-par->yoffset))
3784                                                 p -= par->next_line;
3785                                         else
3786                                                 p += par->next_line;
3787                                 }
3788                         } else p = par->bplpt0wrap - par->next_line;
3789                 }
3790                 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3791                         (cops++)->l = CMOVE(highw(p), bplpt[i]);
3792                         (cops++)->l = CMOVE2(loww(p), bplpt[i]);
3793                 }
3794                 cops->l = CEND;
3795         }
3796 }
3797
3798 static void __exit amifb_exit(void)
3799 {
3800         unregister_framebuffer(&fb_info);
3801         amifb_deinit();
3802         amifb_video_off();
3803 }
3804
3805 module_init(amifb_init);
3806 module_exit(amifb_exit);
3807
3808 MODULE_LICENSE("GPL");