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