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