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