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