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