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