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