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