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