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