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