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