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