2 * linux/drivers/video/amifb.c -- Amiga builtin chipset frame buffer device
4 * Copyright (C) 1995-2003 Geert Uytterhoeven
6 * with work by Roman Zippel
9 * This file is based on the Atari frame buffer device (atafb.c):
11 * Copyright (C) 1994 Martin Schaller
14 * with work by Andreas Schwab
17 * and on the original Amiga console driver (amicon.c):
19 * Copyright (C) 1993 Hamish Macdonald
21 * Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk]
23 * with work by William Rucklidge (wjr@cs.cornell.edu)
25 * Jes Sorensen (jds@kom.auc.dk)
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
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
43 #include <linux/module.h>
44 #include <linux/kernel.h>
45 #include <linux/errno.h>
46 #include <linux/string.h>
48 #include <linux/tty.h>
49 #include <linux/slab.h>
50 #include <linux/delay.h>
51 #include <linux/interrupt.h>
53 #include <linux/init.h>
54 #include <linux/ioport.h>
56 #include <asm/uaccess.h>
57 #include <asm/system.h>
59 #include <asm/amigahw.h>
60 #include <asm/amigaints.h>
61 #include <asm/setup.h>
68 #if !defined(CONFIG_FB_AMIGA_OCS) && !defined(CONFIG_FB_AMIGA_ECS) && !defined(CONFIG_FB_AMIGA_AGA)
69 #define CONFIG_FB_AMIGA_OCS /* define at least one fb driver, this will change later */
72 #if !defined(CONFIG_FB_AMIGA_OCS)
74 #elif defined(CONFIG_FB_AMIGA_ECS) || defined(CONFIG_FB_AMIGA_AGA)
75 # define IS_OCS (chipset == TAG_OCS)
77 # define CONFIG_FB_AMIGA_OCS_ONLY
81 #if !defined(CONFIG_FB_AMIGA_ECS)
83 #elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_AGA)
84 # define IS_ECS (chipset == TAG_ECS)
86 # define CONFIG_FB_AMIGA_ECS_ONLY
90 #if !defined(CONFIG_FB_AMIGA_AGA)
92 #elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_ECS)
93 # define IS_AGA (chipset == TAG_AGA)
95 # define CONFIG_FB_AMIGA_AGA_ONLY
100 # define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
102 # define DPRINTK(fmt, args...)
105 /*******************************************************************************
108 Generic video timings
109 ---------------------
111 Timings used by the frame buffer interface:
113 +----------+---------------------------------------------+----------+-------+
115 | | |upper_margin | | |
117 +----------###############################################----------+-------+
122 | left # | # right | hsync |
123 | margin # | xres # margin | len |
124 |<-------->#<---------------+--------------------------->#<-------->|<----->|
138 +----------###############################################----------+-------+
140 | | |lower_margin | | |
142 +----------+---------------------------------------------+----------+-------+
146 +----------+---------------------------------------------+----------+-------+
152 The Amiga native chipsets uses another timing scheme:
154 - hsstrt: Start of horizontal synchronization pulse
155 - hsstop: End of horizontal synchronization pulse
156 - htotal: Last value on the line (i.e. line length = htotal+1)
157 - vsstrt: Start of vertical synchronization pulse
158 - vsstop: End of vertical synchronization pulse
159 - vtotal: Last line value (i.e. number of lines = vtotal+1)
160 - hcenter: Start of vertical retrace for interlace
162 You can specify the blanking timings independently. Currently I just set
163 them equal to the respective synchronization values:
165 - hbstrt: Start of horizontal blank
166 - hbstop: End of horizontal blank
167 - vbstrt: Start of vertical blank
168 - vbstop: End of vertical blank
170 Horizontal values are in color clock cycles (280 ns), vertical values are in
173 (0, 0) is somewhere in the upper-left corner :-)
176 Amiga visible window definitions
177 --------------------------------
179 Currently I only have values for AGA, SHRES (28 MHz dotclock). Feel free to
180 make corrections and/or additions.
182 Within the above synchronization specifications, the visible window is
183 defined by the following parameters (actual register resolutions may be
184 different; all horizontal values are normalized with respect to the pixel
187 - diwstrt_h: Horizontal start of the visible window
188 - diwstop_h: Horizontal stop+1(*) of the visible window
189 - diwstrt_v: Vertical start of the visible window
190 - diwstop_v: Vertical stop of the visible window
191 - ddfstrt: Horizontal start of display DMA
192 - ddfstop: Horizontal stop of display DMA
193 - hscroll: Horizontal display output delay
197 - sprstrt_h: Horizontal start-4 of sprite
198 - sprstrt_v: Vertical start of sprite
200 (*) Even Commodore did it wrong in the AGA monitor drivers by not adding 1.
202 Horizontal values are in dotclock cycles (35 ns), vertical values are in
205 (0, 0) is somewhere in the upper-left corner :-)
208 Dependencies (AGA, SHRES (35 ns dotclock))
209 -------------------------------------------
211 Since there are much more parameters for the Amiga display than for the
212 frame buffer interface, there must be some dependencies among the Amiga
213 display parameters. Here's what I found out:
215 - ddfstrt and ddfstop are best aligned to 64 pixels.
216 - the chipset needs 64+4 horizontal pixels after the DMA start before the
217 first pixel is output, so diwstrt_h = ddfstrt+64+4 if you want to
218 display the first pixel on the line too. Increase diwstrt_h for virtual
220 - the display DMA always fetches 64 pixels at a time (fmode = 3).
221 - ddfstop is ddfstrt+#pixels-64.
222 - diwstop_h = diwstrt_h+xres+1. Because of the additional 1 this can be 1
224 - hscroll simply adds a delay to the display output. Smooth horizontal
225 panning needs an extra 64 pixels on the left to prefetch the pixels that
226 `fall off' on the left.
227 - if ddfstrt < 192, the sprite DMA cycles are all stolen by the bitplane
228 DMA, so it's best to make the DMA start as late as possible.
229 - you really don't want to make ddfstrt < 128, since this will steal DMA
230 cycles from the other DMA channels (audio, floppy and Chip RAM refresh).
231 - I make diwstop_h and diwstop_v as large as possible.
236 - all values are SHRES pixel (35ns)
238 table 1:fetchstart table 2:prefetch table 3:fetchsize
239 ------------------ ---------------- -----------------
240 Pixclock # SHRES|HIRES|LORES # SHRES|HIRES|LORES # SHRES|HIRES|LORES
241 -------------#------+-----+------#------+-----+------#------+-----+------
242 Bus width 1x # 16 | 32 | 64 # 16 | 32 | 64 # 64 | 64 | 64
243 Bus width 2x # 32 | 64 | 128 # 32 | 64 | 64 # 64 | 64 | 128
244 Bus width 4x # 64 | 128 | 256 # 64 | 64 | 64 # 64 | 128 | 256
246 - chipset needs 4 pixels before the first pixel is output
247 - ddfstrt must be aligned to fetchstart (table 1)
248 - chipset needs also prefetch (table 2) to get first pixel data, so
249 ddfstrt = ((diwstrt_h-4) & -fetchstart) - prefetch
250 - for horizontal panning decrease diwstrt_h
251 - the length of a fetchline must be aligned to fetchsize (table 3)
252 - if fetchstart is smaller than fetchsize, then ddfstrt can a little bit
253 moved to optimize use of dma (useful for OCS/ECS overscan displays)
254 - ddfstop is ddfstrt+ddfsize-fetchsize
255 - If C= didn't change anything for AGA, then at following positions the
256 dma bus is already used:
257 ddfstrt < 48 -> memory refresh
260 < 192 -> sprite 0 dma
261 < 416 -> sprite dma (32 per sprite)
262 - in accordance with the hardware reference manual a hardware stop is at
263 192, but AGA (ECS?) can go below this.
268 Since there are limits on the earliest start value for display DMA and the
269 display of sprites, I use the following policy on horizontal panning and
272 - if you want to start display DMA too early, you lose the ability to
273 do smooth horizontal panning (xpanstep 1 -> 64).
274 - if you want to go even further, you lose the hardware cursor too.
276 IMHO a hardware cursor is more important for X than horizontal scrolling,
277 so that's my motivation.
283 ami_decode_var() converts the frame buffer values to the Amiga values. It's
284 just a `straightforward' implementation of the above rules.
290 xres yres left right upper lower hsync vsync
291 ---- ---- ---- ----- ----- ----- ----- -----
292 80x25 720 400 27 45 35 12 108 2
293 80x30 720 480 27 45 30 9 108 2
295 These were taken from a XFree86 configuration file, recalculated for a 28 MHz
296 dotclock (Amigas don't have a 25 MHz dotclock) and converted to frame buffer
299 As a comparison, graphics/monitor.h suggests the following:
301 xres yres left right upper lower hsync vsync
302 ---- ---- ---- ----- ----- ----- ----- -----
304 VGA 640 480 52 112 24 19 112 - 2 +
305 VGA70 640 400 52 112 27 21 112 - 2 -
311 VSYNC HSYNC Vertical size Vertical total
312 ----- ----- ------------- --------------
313 + + Reserved Reserved
318 Source: CL-GD542X Technical Reference Manual, Cirrus Logic, Oct 1992
321 Broadcast video timings
322 -----------------------
324 According to the CCIR and RETMA specifications, we have the following values:
329 - a scanline is 64 µs long, of which 52.48 µs are visible. This is about
330 736 visible 70 ns pixels per line.
331 - we have 625 scanlines, of which 575 are visible (interlaced); after
332 rounding this becomes 576.
337 - a scanline is 63.5 µs long, of which 53.5 µs are visible. This is about
338 736 visible 70 ns pixels per line.
339 - we have 525 scanlines, of which 485 are visible (interlaced); after
340 rounding this becomes 484.
342 Thus if you want a PAL compatible display, you have to do the following:
344 - set the FB_SYNC_BROADCAST flag to indicate that standard broadcast
345 timings are to be used.
346 - make sure upper_margin+yres+lower_margin+vsync_len = 625 for an
347 interlaced, 312 for a non-interlaced and 156 for a doublescanned
349 - make sure left_margin+xres+right_margin+hsync_len = 1816 for a SHRES,
350 908 for a HIRES and 454 for a LORES display.
351 - the left visible part begins at 360 (SHRES; HIRES:180, LORES:90),
352 left_margin+2*hsync_len must be greater or equal.
353 - the upper visible part begins at 48 (interlaced; non-interlaced:24,
354 doublescanned:12), upper_margin+2*vsync_len must be greater or equal.
355 - ami_encode_var() calculates margins with a hsync of 5320 ns and a vsync
358 The settings for a NTSC compatible display are straightforward.
360 Note that in a strict sense the PAL and NTSC standards only define the
361 encoding of the color part (chrominance) of the video signal and don't say
362 anything about horizontal/vertical synchronization nor refresh rates.
367 *******************************************************************************/
371 * Custom Chipset Definitions
374 #define CUSTOM_OFS(fld) ((long)&((struct CUSTOM*)0)->fld)
377 * BPLCON0 -- Bitplane Control Register 0
380 #define BPC0_HIRES (0x8000)
381 #define BPC0_BPU2 (0x4000) /* Bit plane used count */
382 #define BPC0_BPU1 (0x2000)
383 #define BPC0_BPU0 (0x1000)
384 #define BPC0_HAM (0x0800) /* HAM mode */
385 #define BPC0_DPF (0x0400) /* Double playfield */
386 #define BPC0_COLOR (0x0200) /* Enable colorburst */
387 #define BPC0_GAUD (0x0100) /* Genlock audio enable */
388 #define BPC0_UHRES (0x0080) /* Ultrahi res enable */
389 #define BPC0_SHRES (0x0040) /* Super hi res mode */
390 #define BPC0_BYPASS (0x0020) /* Bypass LUT - AGA */
391 #define BPC0_BPU3 (0x0010) /* AGA */
392 #define BPC0_LPEN (0x0008) /* Light pen enable */
393 #define BPC0_LACE (0x0004) /* Interlace */
394 #define BPC0_ERSY (0x0002) /* External resync */
395 #define BPC0_ECSENA (0x0001) /* ECS enable */
398 * BPLCON2 -- Bitplane Control Register 2
401 #define BPC2_ZDBPSEL2 (0x4000) /* Bitplane to be used for ZD - AGA */
402 #define BPC2_ZDBPSEL1 (0x2000)
403 #define BPC2_ZDBPSEL0 (0x1000)
404 #define BPC2_ZDBPEN (0x0800) /* Enable ZD with ZDBPSELx - AGA */
405 #define BPC2_ZDCTEN (0x0400) /* Enable ZD with palette bit #31 - AGA */
406 #define BPC2_KILLEHB (0x0200) /* Kill EHB mode - AGA */
407 #define BPC2_RDRAM (0x0100) /* Color table accesses read, not write - AGA */
408 #define BPC2_SOGEN (0x0080) /* SOG output pin high - AGA */
409 #define BPC2_PF2PRI (0x0040) /* PF2 priority over PF1 */
410 #define BPC2_PF2P2 (0x0020) /* PF2 priority wrt sprites */
411 #define BPC2_PF2P1 (0x0010)
412 #define BPC2_PF2P0 (0x0008)
413 #define BPC2_PF1P2 (0x0004) /* ditto PF1 */
414 #define BPC2_PF1P1 (0x0002)
415 #define BPC2_PF1P0 (0x0001)
418 * BPLCON3 -- Bitplane Control Register 3 (AGA)
421 #define BPC3_BANK2 (0x8000) /* Bits to select color register bank */
422 #define BPC3_BANK1 (0x4000)
423 #define BPC3_BANK0 (0x2000)
424 #define BPC3_PF2OF2 (0x1000) /* Bits for color table offset when PF2 */
425 #define BPC3_PF2OF1 (0x0800)
426 #define BPC3_PF2OF0 (0x0400)
427 #define BPC3_LOCT (0x0200) /* Color register writes go to low bits */
428 #define BPC3_SPRES1 (0x0080) /* Sprite resolution bits */
429 #define BPC3_SPRES0 (0x0040)
430 #define BPC3_BRDRBLNK (0x0020) /* Border blanked? */
431 #define BPC3_BRDRTRAN (0x0010) /* Border transparent? */
432 #define BPC3_ZDCLKEN (0x0004) /* ZD pin is 14 MHz (HIRES) clock output */
433 #define BPC3_BRDRSPRT (0x0002) /* Sprites in border? */
434 #define BPC3_EXTBLKEN (0x0001) /* BLANK programmable */
437 * BPLCON4 -- Bitplane Control Register 4 (AGA)
440 #define BPC4_BPLAM7 (0x8000) /* bitplane color XOR field */
441 #define BPC4_BPLAM6 (0x4000)
442 #define BPC4_BPLAM5 (0x2000)
443 #define BPC4_BPLAM4 (0x1000)
444 #define BPC4_BPLAM3 (0x0800)
445 #define BPC4_BPLAM2 (0x0400)
446 #define BPC4_BPLAM1 (0x0200)
447 #define BPC4_BPLAM0 (0x0100)
448 #define BPC4_ESPRM7 (0x0080) /* 4 high bits for even sprite colors */
449 #define BPC4_ESPRM6 (0x0040)
450 #define BPC4_ESPRM5 (0x0020)
451 #define BPC4_ESPRM4 (0x0010)
452 #define BPC4_OSPRM7 (0x0008) /* 4 high bits for odd sprite colors */
453 #define BPC4_OSPRM6 (0x0004)
454 #define BPC4_OSPRM5 (0x0002)
455 #define BPC4_OSPRM4 (0x0001)
458 * BEAMCON0 -- Beam Control Register
461 #define BMC0_HARDDIS (0x4000) /* Disable hardware limits */
462 #define BMC0_LPENDIS (0x2000) /* Disable light pen latch */
463 #define BMC0_VARVBEN (0x1000) /* Enable variable vertical blank */
464 #define BMC0_LOLDIS (0x0800) /* Disable long/short line toggle */
465 #define BMC0_CSCBEN (0x0400) /* Composite sync/blank */
466 #define BMC0_VARVSYEN (0x0200) /* Enable variable vertical sync */
467 #define BMC0_VARHSYEN (0x0100) /* Enable variable horizontal sync */
468 #define BMC0_VARBEAMEN (0x0080) /* Enable variable beam counters */
469 #define BMC0_DUAL (0x0040) /* Enable alternate horizontal beam counter */
470 #define BMC0_PAL (0x0020) /* Set decodes for PAL */
471 #define BMC0_VARCSYEN (0x0010) /* Enable variable composite sync */
472 #define BMC0_BLANKEN (0x0008) /* Blank enable (no longer used on AGA) */
473 #define BMC0_CSYTRUE (0x0004) /* CSY polarity */
474 #define BMC0_VSYTRUE (0x0002) /* VSY polarity */
475 #define BMC0_HSYTRUE (0x0001) /* HSY polarity */
479 * FMODE -- Fetch Mode Control Register (AGA)
482 #define FMODE_SSCAN2 (0x8000) /* Sprite scan-doubling */
483 #define FMODE_BSCAN2 (0x4000) /* Use PF2 modulus every other line */
484 #define FMODE_SPAGEM (0x0008) /* Sprite page mode */
485 #define FMODE_SPR32 (0x0004) /* Sprite 32 bit fetch */
486 #define FMODE_BPAGEM (0x0002) /* Bitplane page mode */
487 #define FMODE_BPL32 (0x0001) /* Bitplane 32 bit fetch */
490 * Tags used to indicate a specific Pixel Clock
492 * clk_shift is the shift value to get the timings in 35 ns units
495 enum { TAG_SHRES, TAG_HIRES, TAG_LORES };
498 * Tags used to indicate the specific chipset
501 enum { TAG_OCS, TAG_ECS, TAG_AGA };
504 * Tags used to indicate the memory bandwidth
507 enum { TAG_FMODE_1, TAG_FMODE_2, TAG_FMODE_4 };
511 * Clock Definitions, Maximum Display Depth
513 * These depend on the E-Clock or the Chipset, so they are filled in
517 static u_long pixclock[3]; /* SHRES/HIRES/LORES: index = clk_shift */
518 static u_short maxdepth[3]; /* SHRES/HIRES/LORES: index = clk_shift */
519 static u_short maxfmode, chipset;
523 * Broadcast Video Timings
525 * Horizontal values are in 35 ns (SHRES) units
526 * Vertical values are in interlaced scanlines
529 #define PAL_DIWSTRT_H (360) /* PAL Window Limits */
530 #define PAL_DIWSTRT_V (48)
531 #define PAL_HTOTAL (1816)
532 #define PAL_VTOTAL (625)
534 #define NTSC_DIWSTRT_H (360) /* NTSC Window Limits */
535 #define NTSC_DIWSTRT_V (40)
536 #define NTSC_HTOTAL (1816)
537 #define NTSC_VTOTAL (525)
544 #define up2(v) (((v)+1) & -2)
545 #define down2(v) ((v) & -2)
546 #define div2(v) ((v)>>1)
547 #define mod2(v) ((v) & 1)
549 #define up4(v) (((v)+3) & -4)
550 #define down4(v) ((v) & -4)
551 #define mul4(v) ((v)<<2)
552 #define div4(v) ((v)>>2)
553 #define mod4(v) ((v) & 3)
555 #define up8(v) (((v)+7) & -8)
556 #define down8(v) ((v) & -8)
557 #define div8(v) ((v)>>3)
558 #define mod8(v) ((v) & 7)
560 #define up16(v) (((v)+15) & -16)
561 #define down16(v) ((v) & -16)
562 #define div16(v) ((v)>>4)
563 #define mod16(v) ((v) & 15)
565 #define up32(v) (((v)+31) & -32)
566 #define down32(v) ((v) & -32)
567 #define div32(v) ((v)>>5)
568 #define mod32(v) ((v) & 31)
570 #define up64(v) (((v)+63) & -64)
571 #define down64(v) ((v) & -64)
572 #define div64(v) ((v)>>6)
573 #define mod64(v) ((v) & 63)
575 #define upx(x,v) (((v)+(x)-1) & -(x))
576 #define downx(x,v) ((v) & -(x))
577 #define modx(x,v) ((v) & ((x)-1))
579 /* if x1 is not a constant, this macro won't make real sense :-) */
581 #define DIVUL(x1, x2) ({int res; asm("divul %1,%2,%3": "=d" (res): \
582 "d" (x2), "d" ((long)((x1)/0x100000000ULL)), "0" ((long)(x1))); res;})
584 /* We know a bit about the numbers, so we can do it this way */
585 #define DIVUL(x1, x2) ((((long)((unsigned long long)x1 >> 8) / x2) << 8) + \
586 ((((long)((unsigned long long)x1 >> 8) % x2) << 8) / x2))
589 #define highw(x) ((u_long)(x)>>16 & 0xffff)
590 #define loww(x) ((u_long)(x) & 0xffff)
592 #define custom amiga_custom
594 #define VBlankOn() custom.intena = IF_SETCLR|IF_COPER
595 #define VBlankOff() custom.intena = IF_COPER
599 * Chip RAM we reserve for the Frame Buffer
601 * This defines the Maximum Virtual Screen Size
602 * (Setable per kernel options?)
605 #define VIDEOMEMSIZE_AGA_2M (1310720) /* AGA (2MB) : max 1280*1024*256 */
606 #define VIDEOMEMSIZE_AGA_1M (786432) /* AGA (1MB) : max 1024*768*256 */
607 #define VIDEOMEMSIZE_ECS_2M (655360) /* ECS (2MB) : max 1280*1024*16 */
608 #define VIDEOMEMSIZE_ECS_1M (393216) /* ECS (1MB) : max 1024*768*16 */
609 #define VIDEOMEMSIZE_OCS (262144) /* OCS : max ca. 800*600*16 */
611 #define SPRITEMEMSIZE (64*64/4) /* max 64*64*4 */
612 #define DUMMYSPRITEMEMSIZE (8)
613 static u_long spritememory;
615 #define CHIPRAM_SAFETY_LIMIT (16384)
617 static u_long videomemory;
620 * This is the earliest allowed start of fetching display data.
621 * Only if you really want no hardware cursor and audio,
622 * set this to 128, but let it better at 192
625 static u_long min_fstrt = 192;
627 #define assignchunk(name, type, ptr, size) \
629 (name) = (type)(ptr); \
635 * Copper Instructions
638 #define CMOVE(val, reg) (CUSTOM_OFS(reg)<<16 | (val))
639 #define CMOVE2(val, reg) ((CUSTOM_OFS(reg)+2)<<16 | (val))
640 #define CWAIT(x, y) (((y) & 0x1fe)<<23 | ((x) & 0x7f0)<<13 | 0x0001fffe)
641 #define CEND (0xfffffffe)
649 static struct copdisplay {
656 static u_short currentcop = 0;
659 * Hardware Cursor API Definitions
660 * These used to be in linux/fb.h, but were preliminary and used by
664 #define FBIOGET_FCURSORINFO 0x4607
665 #define FBIOGET_VCURSORINFO 0x4608
666 #define FBIOPUT_VCURSORINFO 0x4609
667 #define FBIOGET_CURSORSTATE 0x460A
668 #define FBIOPUT_CURSORSTATE 0x460B
671 struct fb_fix_cursorinfo {
672 __u16 crsr_width; /* width and height of the cursor in */
673 __u16 crsr_height; /* pixels (zero if no cursor) */
674 __u16 crsr_xsize; /* cursor size in display pixels */
676 __u16 crsr_color1; /* colormap entry for cursor color1 */
677 __u16 crsr_color2; /* colormap entry for cursor color2 */
680 struct fb_var_cursorinfo {
685 __u8 data[1]; /* field with [height][width] */
688 struct fb_cursorstate {
694 #define FB_CURSOR_OFF 0
695 #define FB_CURSOR_ON 1
696 #define FB_CURSOR_FLASH 2
703 static int cursorrate = 20; /* Number of frames/flash toggle */
704 static u_short cursorstate = -1;
705 static u_short cursormode = FB_CURSOR_OFF;
707 static u_short *lofsprite, *shfsprite, *dummysprite;
713 static struct amifb_par {
717 int xres; /* vmode */
718 int yres; /* vmode */
719 int vxres; /* vmode */
720 int vyres; /* vmode */
721 int xoffset; /* vmode */
722 int yoffset; /* vmode */
723 u_short bpp; /* vmode */
724 u_short clk_shift; /* vmode */
725 u_short line_shift; /* vmode */
726 int vmode; /* vmode */
727 u_short diwstrt_h; /* vmode */
728 u_short diwstop_h; /* vmode */
729 u_short diwstrt_v; /* vmode */
730 u_short diwstop_v; /* vmode */
731 u_long next_line; /* modulo for next line */
732 u_long next_plane; /* modulo for next plane */
737 short crsr_x; /* movecursor */
738 short crsr_y; /* movecursor */
746 /* OCS Hardware Registers */
748 u_long bplpt0; /* vmode, pan (Note: physical address) */
749 u_long bplpt0wrap; /* vmode, pan (Note: physical address) */
754 u_short bplcon0; /* vmode */
755 u_short bplcon1; /* vmode */
756 u_short htotal; /* vmode */
757 u_short vtotal; /* vmode */
759 /* Additional ECS Hardware Registers */
761 u_short bplcon3; /* vmode */
762 u_short beamcon0; /* vmode */
763 u_short hsstrt; /* vmode */
764 u_short hsstop; /* vmode */
765 u_short hbstrt; /* vmode */
766 u_short hbstop; /* vmode */
767 u_short vsstrt; /* vmode */
768 u_short vsstop; /* vmode */
769 u_short vbstrt; /* vmode */
770 u_short vbstop; /* vmode */
771 u_short hcenter; /* vmode */
773 /* Additional AGA Hardware Registers */
775 u_short fmode; /* vmode */
779 static struct fb_info fb_info = {
782 .visual = FB_VISUAL_PSEUDOCOLOR,
783 .accel = FB_ACCEL_AMIGABLITT
789 * Saved color entry 0 so we can restore it when unblanking
792 static u_char red0, green0, blue0;
795 #if defined(CONFIG_FB_AMIGA_ECS)
796 static u_short ecs_palette[32];
801 * Latches for Display Changes during VBlank
804 static u_short do_vmode_full = 0; /* Change the Video Mode */
805 static u_short do_vmode_pan = 0; /* Update the Video Mode */
806 static short do_blank = 0; /* (Un)Blank the Screen (±1) */
807 static u_short do_cursor = 0; /* Move the Cursor */
814 static u_short is_blanked = 0; /* Screen is Blanked */
815 static u_short is_lace = 0; /* Screen is laced */
818 * Predefined Video Modes
822 static struct fb_videomode ami_modedb[] __initdata = {
825 * AmigaOS Video Modes
827 * If you change these, make sure to update DEFMODE_* as well!
831 /* 640x200, 15 kHz, 60 Hz (NTSC) */
832 "ntsc", 60, 640, 200, TAG_HIRES, 106, 86, 44, 16, 76, 2,
833 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
835 /* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */
836 "ntsc-lace", 60, 640, 400, TAG_HIRES, 106, 86, 88, 33, 76, 4,
837 FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
839 /* 640x256, 15 kHz, 50 Hz (PAL) */
840 "pal", 50, 640, 256, TAG_HIRES, 106, 86, 40, 14, 76, 2,
841 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
843 /* 640x512, 15 kHz, 50 Hz interlaced (PAL) */
844 "pal-lace", 50, 640, 512, TAG_HIRES, 106, 86, 80, 29, 76, 4,
845 FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
847 /* 640x480, 29 kHz, 57 Hz */
848 "multiscan", 57, 640, 480, TAG_SHRES, 96, 112, 29, 8, 72, 8,
849 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
851 /* 640x960, 29 kHz, 57 Hz interlaced */
852 "multiscan-lace", 57, 640, 960, TAG_SHRES, 96, 112, 58, 16, 72, 16,
853 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
855 /* 640x200, 15 kHz, 72 Hz */
856 "euro36", 72, 640, 200, TAG_HIRES, 92, 124, 6, 6, 52, 5,
857 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
859 /* 640x400, 15 kHz, 72 Hz interlaced */
860 "euro36-lace", 72, 640, 400, TAG_HIRES, 92, 124, 12, 12, 52, 10,
861 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
863 /* 640x400, 29 kHz, 68 Hz */
864 "euro72", 68, 640, 400, TAG_SHRES, 164, 92, 9, 9, 80, 8,
865 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
867 /* 640x800, 29 kHz, 68 Hz interlaced */
868 "euro72-lace", 68, 640, 800, TAG_SHRES, 164, 92, 18, 18, 80, 16,
869 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
871 /* 800x300, 23 kHz, 70 Hz */
872 "super72", 70, 800, 300, TAG_SHRES, 212, 140, 10, 11, 80, 7,
873 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
875 /* 800x600, 23 kHz, 70 Hz interlaced */
876 "super72-lace", 70, 800, 600, TAG_SHRES, 212, 140, 20, 22, 80, 14,
877 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
879 /* 640x200, 27 kHz, 57 Hz doublescan */
880 "dblntsc", 57, 640, 200, TAG_SHRES, 196, 124, 18, 17, 80, 4,
881 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
883 /* 640x400, 27 kHz, 57 Hz */
884 "dblntsc-ff", 57, 640, 400, TAG_SHRES, 196, 124, 36, 35, 80, 7,
885 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
887 /* 640x800, 27 kHz, 57 Hz interlaced */
888 "dblntsc-lace", 57, 640, 800, TAG_SHRES, 196, 124, 72, 70, 80, 14,
889 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
891 /* 640x256, 27 kHz, 47 Hz doublescan */
892 "dblpal", 47, 640, 256, TAG_SHRES, 196, 124, 14, 13, 80, 4,
893 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
895 /* 640x512, 27 kHz, 47 Hz */
896 "dblpal-ff", 47, 640, 512, TAG_SHRES, 196, 124, 28, 27, 80, 7,
897 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
899 /* 640x1024, 27 kHz, 47 Hz interlaced */
900 "dblpal-lace", 47, 640, 1024, TAG_SHRES, 196, 124, 56, 54, 80, 14,
901 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
909 /* 640x480, 31 kHz, 60 Hz (VGA) */
910 "vga", 60, 640, 480, TAG_SHRES, 64, 96, 30, 9, 112, 2,
911 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
913 /* 640x400, 31 kHz, 70 Hz (VGA) */
914 "vga70", 70, 640, 400, TAG_SHRES, 64, 96, 35, 12, 112, 2,
915 FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
922 * These modes don't work yet because there's no A2024 driver.
926 /* 1024x800, 10 Hz */
927 "a2024-10", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
928 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
930 /* 1024x800, 15 Hz */
931 "a2024-15", 15, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
932 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
937 #define NUM_TOTAL_MODES ARRAY_SIZE(ami_modedb)
939 static char *mode_option __initdata = NULL;
940 static int round_down_bpp = 1; /* for mode probing */
947 #define DEFMODE_PAL 2 /* "pal" for PAL OCS/ECS */
948 #define DEFMODE_NTSC 0 /* "ntsc" for NTSC OCS/ECS */
949 #define DEFMODE_AMBER_PAL 3 /* "pal-lace" for flicker fixed PAL (A3000) */
950 #define DEFMODE_AMBER_NTSC 1 /* "ntsc-lace" for flicker fixed NTSC (A3000) */
951 #define DEFMODE_AGA 19 /* "vga70" for AGA */
954 static int amifb_ilbm = 0; /* interleaved or normal bitplanes */
955 static int amifb_inverse = 0;
959 * Macros for the conversion from real world values to hardware register
962 * This helps us to keep our attention on the real stuff...
964 * Hardware limits for AGA:
966 * parameter min max step
967 * --------- --- ---- ----
989 * Horizontal values are in 35 ns (SHRES) pixels
990 * Vertical values are in half scanlines
993 /* bplcon1 (smooth scrolling) */
995 #define hscroll2hw(hscroll) \
996 (((hscroll)<<12 & 0x3000) | ((hscroll)<<8 & 0xc300) | \
997 ((hscroll)<<4 & 0x0c00) | ((hscroll)<<2 & 0x00f0) | ((hscroll)>>2 & 0x000f))
999 /* diwstrt/diwstop/diwhigh (visible display window) */
1001 #define diwstrt2hw(diwstrt_h, diwstrt_v) \
1002 (((diwstrt_v)<<7 & 0xff00) | ((diwstrt_h)>>2 & 0x00ff))
1003 #define diwstop2hw(diwstop_h, diwstop_v) \
1004 (((diwstop_v)<<7 & 0xff00) | ((diwstop_h)>>2 & 0x00ff))
1005 #define diwhigh2hw(diwstrt_h, diwstrt_v, diwstop_h, diwstop_v) \
1006 (((diwstop_h)<<3 & 0x2000) | ((diwstop_h)<<11 & 0x1800) | \
1007 ((diwstop_v)>>1 & 0x0700) | ((diwstrt_h)>>5 & 0x0020) | \
1008 ((diwstrt_h)<<3 & 0x0018) | ((diwstrt_v)>>9 & 0x0007))
1010 /* ddfstrt/ddfstop (display DMA) */
1012 #define ddfstrt2hw(ddfstrt) div8(ddfstrt)
1013 #define ddfstop2hw(ddfstop) div8(ddfstop)
1015 /* hsstrt/hsstop/htotal/vsstrt/vsstop/vtotal/hcenter (sync timings) */
1017 #define hsstrt2hw(hsstrt) (div8(hsstrt))
1018 #define hsstop2hw(hsstop) (div8(hsstop))
1019 #define htotal2hw(htotal) (div8(htotal)-1)
1020 #define vsstrt2hw(vsstrt) (div2(vsstrt))
1021 #define vsstop2hw(vsstop) (div2(vsstop))
1022 #define vtotal2hw(vtotal) (div2(vtotal)-1)
1023 #define hcenter2hw(htotal) (div8(htotal))
1025 /* hbstrt/hbstop/vbstrt/vbstop (blanking timings) */
1027 #define hbstrt2hw(hbstrt) (((hbstrt)<<8 & 0x0700) | ((hbstrt)>>3 & 0x00ff))
1028 #define hbstop2hw(hbstop) (((hbstop)<<8 & 0x0700) | ((hbstop)>>3 & 0x00ff))
1029 #define vbstrt2hw(vbstrt) (div2(vbstrt))
1030 #define vbstop2hw(vbstop) (div2(vbstop))
1034 #define rgb2hw8_high(red, green, blue) \
1035 (((red & 0xf0)<<4) | (green & 0xf0) | ((blue & 0xf0)>>4))
1036 #define rgb2hw8_low(red, green, blue) \
1037 (((red & 0x0f)<<8) | ((green & 0x0f)<<4) | (blue & 0x0f))
1038 #define rgb2hw4(red, green, blue) \
1039 (((red & 0xf0)<<4) | (green & 0xf0) | ((blue & 0xf0)>>4))
1040 #define rgb2hw2(red, green, blue) \
1041 (((red & 0xc0)<<4) | (green & 0xc0) | ((blue & 0xc0)>>4))
1043 /* sprpos/sprctl (sprite positioning) */
1045 #define spr2hw_pos(start_v, start_h) \
1046 (((start_v)<<7&0xff00) | ((start_h)>>3&0x00ff))
1047 #define spr2hw_ctl(start_v, start_h, stop_v) \
1048 (((stop_v)<<7&0xff00) | ((start_v)>>4&0x0040) | ((stop_v)>>5&0x0020) | \
1049 ((start_h)<<3&0x0018) | ((start_v)>>7&0x0004) | ((stop_v)>>8&0x0002) | \
1050 ((start_h)>>2&0x0001))
1052 /* get current vertical position of beam */
1053 #define get_vbpos() ((u_short)((*(u_long volatile *)&custom.vposr >> 7) & 0xffe))
1056 * Copper Initialisation List
1059 #define COPINITSIZE (sizeof(copins)*40)
1066 * Long Frame/Short Frame Copper List
1067 * Don't change the order, build_copper()/rebuild_copper() rely on this
1070 #define COPLISTSIZE (sizeof(copins)*64)
1073 cop_wait, cop_bplcon0,
1074 cop_spr0ptrh, cop_spr0ptrl,
1075 cop_diwstrt, cop_diwstop,
1080 * Pixel modes for Bitplanes and Sprites
1083 static u_short bplpixmode[3] = {
1084 BPC0_SHRES, /* 35 ns */
1085 BPC0_HIRES, /* 70 ns */
1089 static u_short sprpixmode[3] = {
1090 BPC3_SPRES1 | BPC3_SPRES0, /* 35 ns */
1091 BPC3_SPRES1, /* 70 ns */
1092 BPC3_SPRES0 /* 140 ns */
1096 * Fetch modes for Bitplanes and Sprites
1099 static u_short bplfetchmode[3] = {
1101 FMODE_BPL32, /* 2x */
1102 FMODE_BPAGEM | FMODE_BPL32 /* 4x */
1105 static u_short sprfetchmode[3] = {
1107 FMODE_SPR32, /* 2x */
1108 FMODE_SPAGEM | FMODE_SPR32 /* 4x */
1113 * Interface used by the world
1116 int amifb_setup(char*);
1118 static int amifb_check_var(struct fb_var_screeninfo *var,
1119 struct fb_info *info);
1120 static int amifb_set_par(struct fb_info *info);
1121 static int amifb_setcolreg(unsigned regno, unsigned red, unsigned green,
1122 unsigned blue, unsigned transp,
1123 struct fb_info *info);
1124 static int amifb_blank(int blank, struct fb_info *info);
1125 static int amifb_pan_display(struct fb_var_screeninfo *var,
1126 struct fb_info *info);
1127 static void amifb_fillrect(struct fb_info *info,
1128 const struct fb_fillrect *rect);
1129 static void amifb_copyarea(struct fb_info *info,
1130 const struct fb_copyarea *region);
1131 static void amifb_imageblit(struct fb_info *info,
1132 const struct fb_image *image);
1133 static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg);
1137 * Interface to the low level console driver
1140 int amifb_init(void);
1141 static void amifb_deinit(void);
1147 static int flash_cursor(void);
1148 static irqreturn_t amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp);
1149 static u_long chipalloc(u_long size);
1150 static void chipfree(void);
1156 static int ami_decode_var(struct fb_var_screeninfo *var,
1157 struct amifb_par *par);
1158 static int ami_encode_var(struct fb_var_screeninfo *var,
1159 struct amifb_par *par);
1160 static void ami_pan_var(struct fb_var_screeninfo *var);
1161 static int ami_update_par(void);
1162 static void ami_update_display(void);
1163 static void ami_init_display(void);
1164 static void ami_do_blank(void);
1165 static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix);
1166 static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data);
1167 static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data);
1168 static int ami_get_cursorstate(struct fb_cursorstate *state);
1169 static int ami_set_cursorstate(struct fb_cursorstate *state);
1170 static void ami_set_sprite(void);
1171 static void ami_init_copper(void);
1172 static void ami_reinit_copper(void);
1173 static void ami_build_copper(void);
1174 static void ami_rebuild_copper(void);
1177 static struct fb_ops amifb_ops = {
1178 .owner = THIS_MODULE,
1179 .fb_check_var = amifb_check_var,
1180 .fb_set_par = amifb_set_par,
1181 .fb_setcolreg = amifb_setcolreg,
1182 .fb_blank = amifb_blank,
1183 .fb_pan_display = amifb_pan_display,
1184 .fb_fillrect = amifb_fillrect,
1185 .fb_copyarea = amifb_copyarea,
1186 .fb_imageblit = amifb_imageblit,
1187 .fb_ioctl = amifb_ioctl,
1190 static void __init amifb_setup_mcap(char *spec)
1193 int vmin, vmax, hmin, hmax;
1195 /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
1196 * <V*> vertical freq. in Hz
1197 * <H*> horizontal freq. in kHz
1200 if (!(p = strsep(&spec, ";")) || !*p)
1202 vmin = simple_strtoul(p, NULL, 10);
1205 if (!(p = strsep(&spec, ";")) || !*p)
1207 vmax = simple_strtoul(p, NULL, 10);
1208 if (vmax <= 0 || vmax <= vmin)
1210 if (!(p = strsep(&spec, ";")) || !*p)
1212 hmin = 1000 * simple_strtoul(p, NULL, 10);
1215 if (!(p = strsep(&spec, "")) || !*p)
1217 hmax = 1000 * simple_strtoul(p, NULL, 10);
1218 if (hmax <= 0 || hmax <= hmin)
1221 fb_info.monspecs.vfmin = vmin;
1222 fb_info.monspecs.vfmax = vmax;
1223 fb_info.monspecs.hfmin = hmin;
1224 fb_info.monspecs.hfmax = hmax;
1227 int __init amifb_setup(char *options)
1231 if (!options || !*options)
1234 while ((this_opt = strsep(&options, ",")) != NULL) {
1237 if (!strcmp(this_opt, "inverse")) {
1240 } else if (!strcmp(this_opt, "ilbm"))
1242 else if (!strncmp(this_opt, "monitorcap:", 11))
1243 amifb_setup_mcap(this_opt+11);
1244 else if (!strncmp(this_opt, "fstart:", 7))
1245 min_fstrt = simple_strtoul(this_opt+7, NULL, 0);
1247 mode_option = this_opt;
1257 static int amifb_check_var(struct fb_var_screeninfo *var,
1258 struct fb_info *info)
1261 struct amifb_par par;
1263 /* Validate wanted screen parameters */
1264 if ((err = ami_decode_var(var, &par)))
1267 /* Encode (possibly rounded) screen parameters */
1268 ami_encode_var(var, &par);
1273 static int amifb_set_par(struct fb_info *info)
1275 struct amifb_par *par = (struct amifb_par *)info->par;
1280 /* Decode wanted screen parameters */
1281 ami_decode_var(&info->var, par);
1283 /* Set new videomode */
1286 /* Set VBlank trigger */
1289 /* Update fix for new screen parameters */
1290 if (par->bpp == 1) {
1291 info->fix.type = FB_TYPE_PACKED_PIXELS;
1292 info->fix.type_aux = 0;
1293 } else if (amifb_ilbm) {
1294 info->fix.type = FB_TYPE_INTERLEAVED_PLANES;
1295 info->fix.type_aux = par->next_line;
1297 info->fix.type = FB_TYPE_PLANES;
1298 info->fix.type_aux = 0;
1300 info->fix.line_length = div8(upx(16<<maxfmode, par->vxres));
1302 if (par->vmode & FB_VMODE_YWRAP) {
1303 info->fix.ywrapstep = 1;
1304 info->fix.xpanstep = 0;
1305 info->fix.ypanstep = 0;
1306 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP |
1307 FBINFO_READS_FAST; /* override SCROLL_REDRAW */
1309 info->fix.ywrapstep = 0;
1310 if (par->vmode & FB_VMODE_SMOOTH_XPAN)
1311 info->fix.xpanstep = 1;
1313 info->fix.xpanstep = 16<<maxfmode;
1314 info->fix.ypanstep = 1;
1315 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1322 * Pan or Wrap the Display
1324 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
1327 static int amifb_pan_display(struct fb_var_screeninfo *var,
1328 struct fb_info *info)
1330 if (var->vmode & FB_VMODE_YWRAP) {
1331 if (var->yoffset < 0 ||
1332 var->yoffset >= info->var.yres_virtual || var->xoffset)
1336 * TODO: There will be problems when xpan!=1, so some columns
1337 * on the right side will never be seen
1339 if (var->xoffset+info->var.xres > upx(16<<maxfmode, info->var.xres_virtual) ||
1340 var->yoffset+info->var.yres > info->var.yres_virtual)
1344 info->var.xoffset = var->xoffset;
1345 info->var.yoffset = var->yoffset;
1346 if (var->vmode & FB_VMODE_YWRAP)
1347 info->var.vmode |= FB_VMODE_YWRAP;
1349 info->var.vmode &= ~FB_VMODE_YWRAP;
1354 #if BITS_PER_LONG == 32
1355 #define BYTES_PER_LONG 4
1356 #define SHIFT_PER_LONG 5
1357 #elif BITS_PER_LONG == 64
1358 #define BYTES_PER_LONG 8
1359 #define SHIFT_PER_LONG 6
1361 #define Please update me
1366 * Compose two values, using a bitmask as decision value
1367 * This is equivalent to (a & mask) | (b & ~mask)
1370 static inline unsigned long comp(unsigned long a, unsigned long b,
1373 return ((a ^ b) & mask) ^ b;
1377 static inline unsigned long xor(unsigned long a, unsigned long b,
1380 return (a & mask) ^ b;
1385 * Unaligned forward bit copy using 32-bit or 64-bit memory accesses
1388 static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
1391 unsigned long first, last;
1392 int shift = dst_idx-src_idx, left, right;
1393 unsigned long d0, d1;
1399 shift = dst_idx-src_idx;
1400 first = ~0UL >> dst_idx;
1401 last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
1404 // Same alignment for source and dest
1406 if (dst_idx+n <= BITS_PER_LONG) {
1410 *dst = comp(*src, *dst, first);
1412 // Multiple destination words
1415 *dst = comp(*src, *dst, first);
1418 n -= BITS_PER_LONG-dst_idx;
1439 *dst = comp(*src, *dst, last);
1442 // Different alignment for source and dest
1444 right = shift & (BITS_PER_LONG-1);
1445 left = -shift & (BITS_PER_LONG-1);
1447 if (dst_idx+n <= BITS_PER_LONG) {
1448 // Single destination word
1452 // Single source word
1453 *dst = comp(*src >> right, *dst, first);
1454 } else if (src_idx+n <= BITS_PER_LONG) {
1455 // Single source word
1456 *dst = comp(*src << left, *dst, first);
1461 *dst = comp(d0 << left | d1 >> right, *dst,
1465 // Multiple destination words
1469 // Single source word
1470 *dst = comp(d0 >> right, *dst, first);
1472 n -= BITS_PER_LONG-dst_idx;
1476 *dst = comp(d0 << left | d1 >> right, *dst,
1480 n -= BITS_PER_LONG-dst_idx;
1484 m = n % BITS_PER_LONG;
1488 *dst++ = d0 << left | d1 >> right;
1491 *dst++ = d0 << left | d1 >> right;
1494 *dst++ = d0 << left | d1 >> right;
1497 *dst++ = d0 << left | d1 >> right;
1503 *dst++ = d0 << left | d1 >> right;
1510 // Single source word
1511 *dst = comp(d0 << left, *dst, last);
1515 *dst = comp(d0 << left | d1 >> right,
1525 * Unaligned reverse bit copy using 32-bit or 64-bit memory accesses
1528 static void bitcpy_rev(unsigned long *dst, int dst_idx,
1529 const unsigned long *src, int src_idx, u32 n)
1531 unsigned long first, last;
1532 int shift = dst_idx-src_idx, left, right;
1533 unsigned long d0, d1;
1539 dst += (n-1)/BITS_PER_LONG;
1540 src += (n-1)/BITS_PER_LONG;
1541 if ((n-1) % BITS_PER_LONG) {
1542 dst_idx += (n-1) % BITS_PER_LONG;
1543 dst += dst_idx >> SHIFT_PER_LONG;
1544 dst_idx &= BITS_PER_LONG-1;
1545 src_idx += (n-1) % BITS_PER_LONG;
1546 src += src_idx >> SHIFT_PER_LONG;
1547 src_idx &= BITS_PER_LONG-1;
1550 shift = dst_idx-src_idx;
1551 first = ~0UL << (BITS_PER_LONG-1-dst_idx);
1552 last = ~(~0UL << (BITS_PER_LONG-1-((dst_idx-n) % BITS_PER_LONG)));
1555 // Same alignment for source and dest
1557 if ((unsigned long)dst_idx+1 >= n) {
1561 *dst = comp(*src, *dst, first);
1563 // Multiple destination words
1566 *dst = comp(*src, *dst, first);
1590 *dst = comp(*src, *dst, last);
1593 // Different alignment for source and dest
1595 right = shift & (BITS_PER_LONG-1);
1596 left = -shift & (BITS_PER_LONG-1);
1598 if ((unsigned long)dst_idx+1 >= n) {
1599 // Single destination word
1603 // Single source word
1604 *dst = comp(*src << left, *dst, first);
1605 } else if (1+(unsigned long)src_idx >= n) {
1606 // Single source word
1607 *dst = comp(*src >> right, *dst, first);
1612 *dst = comp(d0 >> right | d1 << left, *dst,
1616 // Multiple destination words
1620 // Single source word
1621 *dst = comp(d0 << left, *dst, first);
1627 *dst = comp(d0 >> right | d1 << left, *dst,
1635 m = n % BITS_PER_LONG;
1639 *dst-- = d0 >> right | d1 << left;
1642 *dst-- = d0 >> right | d1 << left;
1645 *dst-- = d0 >> right | d1 << left;
1648 *dst-- = d0 >> right | d1 << left;
1654 *dst-- = d0 >> right | d1 << left;
1661 // Single source word
1662 *dst = comp(d0 >> right, *dst, last);
1666 *dst = comp(d0 >> right | d1 << left,
1676 * Unaligned forward inverting bit copy using 32-bit or 64-bit memory
1680 static void bitcpy_not(unsigned long *dst, int dst_idx,
1681 const unsigned long *src, int src_idx, u32 n)
1683 unsigned long first, last;
1684 int shift = dst_idx-src_idx, left, right;
1685 unsigned long d0, d1;
1691 shift = dst_idx-src_idx;
1692 first = ~0UL >> dst_idx;
1693 last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
1696 // Same alignment for source and dest
1698 if (dst_idx+n <= BITS_PER_LONG) {
1702 *dst = comp(~*src, *dst, first);
1704 // Multiple destination words
1707 *dst = comp(~*src, *dst, first);
1710 n -= BITS_PER_LONG-dst_idx;
1731 *dst = comp(~*src, *dst, last);
1734 // Different alignment for source and dest
1736 right = shift & (BITS_PER_LONG-1);
1737 left = -shift & (BITS_PER_LONG-1);
1739 if (dst_idx+n <= BITS_PER_LONG) {
1740 // Single destination word
1744 // Single source word
1745 *dst = comp(~*src >> right, *dst, first);
1746 } else if (src_idx+n <= BITS_PER_LONG) {
1747 // Single source word
1748 *dst = comp(~*src << left, *dst, first);
1753 *dst = comp(d0 << left | d1 >> right, *dst,
1757 // Multiple destination words
1761 // Single source word
1762 *dst = comp(d0 >> right, *dst, first);
1764 n -= BITS_PER_LONG-dst_idx;
1768 *dst = comp(d0 << left | d1 >> right, *dst,
1772 n -= BITS_PER_LONG-dst_idx;
1776 m = n % BITS_PER_LONG;
1780 *dst++ = d0 << left | d1 >> right;
1783 *dst++ = d0 << left | d1 >> right;
1786 *dst++ = d0 << left | d1 >> right;
1789 *dst++ = d0 << left | d1 >> right;
1795 *dst++ = d0 << left | d1 >> right;
1802 // Single source word
1803 *dst = comp(d0 << left, *dst, last);
1807 *dst = comp(d0 << left | d1 >> right,
1817 * Unaligned 32-bit pattern fill using 32/64-bit memory accesses
1820 static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
1822 unsigned long val = pat;
1823 unsigned long first, last;
1828 #if BITS_PER_LONG == 64
1832 first = ~0UL >> dst_idx;
1833 last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
1835 if (dst_idx+n <= BITS_PER_LONG) {
1839 *dst = comp(val, *dst, first);
1841 // Multiple destination words
1844 *dst = comp(val, *dst, first);
1846 n -= BITS_PER_LONG-dst_idx;
1867 *dst = comp(val, *dst, last);
1873 * Unaligned 32-bit pattern xor using 32/64-bit memory accesses
1876 static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
1878 unsigned long val = pat;
1879 unsigned long first, last;
1884 #if BITS_PER_LONG == 64
1888 first = ~0UL >> dst_idx;
1889 last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
1891 if (dst_idx+n <= BITS_PER_LONG) {
1895 *dst = xor(val, *dst, first);
1897 // Multiple destination words
1900 *dst = xor(val, *dst, first);
1902 n -= BITS_PER_LONG-dst_idx;
1919 *dst = xor(val, *dst, last);
1923 static inline void fill_one_line(int bpp, unsigned long next_plane,
1924 unsigned long *dst, int dst_idx, u32 n,
1928 dst += dst_idx >> SHIFT_PER_LONG;
1929 dst_idx &= (BITS_PER_LONG-1);
1930 bitfill32(dst, dst_idx, color & 1 ? ~0 : 0, n);
1934 dst_idx += next_plane*8;
1938 static inline void xor_one_line(int bpp, unsigned long next_plane,
1939 unsigned long *dst, int dst_idx, u32 n,
1943 dst += dst_idx >> SHIFT_PER_LONG;
1944 dst_idx &= (BITS_PER_LONG-1);
1945 bitxor32(dst, dst_idx, color & 1 ? ~0 : 0, n);
1949 dst_idx += next_plane*8;
1954 static void amifb_fillrect(struct fb_info *info,
1955 const struct fb_fillrect *rect)
1957 struct amifb_par *par = (struct amifb_par *)info->par;
1958 int dst_idx, x2, y2;
1962 if (!rect->width || !rect->height)
1966 * We could use hardware clipping but on many cards you get around
1967 * hardware clipping by writing to framebuffer directly.
1969 x2 = rect->dx + rect->width;
1970 y2 = rect->dy + rect->height;
1971 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
1972 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
1973 width = x2 - rect->dx;
1974 height = y2 - rect->dy;
1976 dst = (unsigned long *)
1977 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1));
1978 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8;
1979 dst_idx += rect->dy*par->next_line*8+rect->dx;
1981 switch (rect->rop) {
1983 fill_one_line(info->var.bits_per_pixel,
1984 par->next_plane, dst, dst_idx, width,
1989 xor_one_line(info->var.bits_per_pixel, par->next_plane,
1990 dst, dst_idx, width, rect->color);
1993 dst_idx += par->next_line*8;
1997 static inline void copy_one_line(int bpp, unsigned long next_plane,
1998 unsigned long *dst, int dst_idx,
1999 unsigned long *src, int src_idx, u32 n)
2002 dst += dst_idx >> SHIFT_PER_LONG;
2003 dst_idx &= (BITS_PER_LONG-1);
2004 src += src_idx >> SHIFT_PER_LONG;
2005 src_idx &= (BITS_PER_LONG-1);
2006 bitcpy(dst, dst_idx, src, src_idx, n);
2009 dst_idx += next_plane*8;
2010 src_idx += next_plane*8;
2014 static inline void copy_one_line_rev(int bpp, unsigned long next_plane,
2015 unsigned long *dst, int dst_idx,
2016 unsigned long *src, int src_idx, u32 n)
2019 dst += dst_idx >> SHIFT_PER_LONG;
2020 dst_idx &= (BITS_PER_LONG-1);
2021 src += src_idx >> SHIFT_PER_LONG;
2022 src_idx &= (BITS_PER_LONG-1);
2023 bitcpy_rev(dst, dst_idx, src, src_idx, n);
2026 dst_idx += next_plane*8;
2027 src_idx += next_plane*8;
2032 static void amifb_copyarea(struct fb_info *info,
2033 const struct fb_copyarea *area)
2035 struct amifb_par *par = (struct amifb_par *)info->par;
2037 u32 dx, dy, sx, sy, width, height;
2038 unsigned long *dst, *src;
2039 int dst_idx, src_idx;
2042 /* clip the destination */
2043 x2 = area->dx + area->width;
2044 y2 = area->dy + area->height;
2045 dx = area->dx > 0 ? area->dx : 0;
2046 dy = area->dy > 0 ? area->dy : 0;
2047 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2048 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2053 sx = area->sx + (dx - area->dx);
2054 sy = area->sy + (dy - area->dy);
2056 /* the source must be completely inside the virtual screen */
2057 if (sx < 0 || sy < 0 || (sx + width) > info->var.xres_virtual ||
2058 (sy + height) > info->var.yres_virtual)
2061 if (dy > sy || (dy == sy && dx > sx)) {
2066 dst = (unsigned long *)
2067 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1));
2069 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8;
2071 dst_idx += dy*par->next_line*8+dx;
2072 src_idx += sy*par->next_line*8+sx;
2075 dst_idx -= par->next_line*8;
2076 src_idx -= par->next_line*8;
2077 copy_one_line_rev(info->var.bits_per_pixel,
2078 par->next_plane, dst, dst_idx, src,
2083 copy_one_line(info->var.bits_per_pixel,
2084 par->next_plane, dst, dst_idx, src,
2086 dst_idx += par->next_line*8;
2087 src_idx += par->next_line*8;
2093 static inline void expand_one_line(int bpp, unsigned long next_plane,
2094 unsigned long *dst, int dst_idx, u32 n,
2095 const u8 *data, u32 bgcolor, u32 fgcolor)
2097 const unsigned long *src;
2101 dst += dst_idx >> SHIFT_PER_LONG;
2102 dst_idx &= (BITS_PER_LONG-1);
2103 if ((bgcolor ^ fgcolor) & 1) {
2104 src = (unsigned long *)((unsigned long)data & ~(BYTES_PER_LONG-1));
2105 src_idx = ((unsigned long)data & (BYTES_PER_LONG-1))*8;
2107 bitcpy(dst, dst_idx, src, src_idx, n);
2109 bitcpy_not(dst, dst_idx, src, src_idx, n);
2112 bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n);
2117 dst_idx += next_plane*8;
2122 static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
2124 struct amifb_par *par = (struct amifb_par *)info->par;
2129 u32 dx, dy, width, height, pitch;
2132 * We could use hardware clipping but on many cards you get around
2133 * hardware clipping by writing to framebuffer directly like we are
2136 x2 = image->dx + image->width;
2137 y2 = image->dy + image->height;
2140 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2141 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2145 if (image->depth == 1) {
2146 dst = (unsigned long *)
2147 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1));
2148 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8;
2149 dst_idx += dy*par->next_line*8+dx;
2151 pitch = (image->width+7)/8;
2153 expand_one_line(info->var.bits_per_pixel,
2154 par->next_plane, dst, dst_idx, width,
2155 src, image->bg_color,
2157 dst_idx += par->next_line*8;
2161 c2p(info->screen_base, image->data, dx, dy, width, height,
2162 par->next_line, par->next_plane, image->width,
2163 info->var.bits_per_pixel);
2169 * Amiga Frame Buffer Specific ioctls
2172 static int amifb_ioctl(struct fb_info *info,
2173 unsigned int cmd, unsigned long arg)
2176 struct fb_fix_cursorinfo fix;
2177 struct fb_var_cursorinfo var;
2178 struct fb_cursorstate state;
2180 void __user *argp = (void __user *)arg;
2184 case FBIOGET_FCURSORINFO:
2185 i = ami_get_fix_cursorinfo(&crsr.fix);
2188 return copy_to_user(argp, &crsr.fix,
2189 sizeof(crsr.fix)) ? -EFAULT : 0;
2191 case FBIOGET_VCURSORINFO:
2192 i = ami_get_var_cursorinfo(&crsr.var,
2193 ((struct fb_var_cursorinfo __user *)arg)->data);
2196 return copy_to_user(argp, &crsr.var,
2197 sizeof(crsr.var)) ? -EFAULT : 0;
2199 case FBIOPUT_VCURSORINFO:
2200 if (copy_from_user(&crsr.var, argp, sizeof(crsr.var)))
2202 return ami_set_var_cursorinfo(&crsr.var,
2203 ((struct fb_var_cursorinfo __user *)arg)->data);
2205 case FBIOGET_CURSORSTATE:
2206 i = ami_get_cursorstate(&crsr.state);
2209 return copy_to_user(argp, &crsr.state,
2210 sizeof(crsr.state)) ? -EFAULT : 0;
2212 case FBIOPUT_CURSORSTATE:
2213 if (copy_from_user(&crsr.state, argp,
2214 sizeof(crsr.state)))
2216 return ami_set_cursorstate(&crsr.state);
2223 * Allocate, Clear and Align a Block of Chip Memory
2226 static u_long unaligned_chipptr = 0;
2228 static inline u_long __init chipalloc(u_long size)
2230 size += PAGE_SIZE-1;
2231 if (!(unaligned_chipptr = (u_long)amiga_chip_alloc(size,
2233 panic("No Chip RAM for frame buffer");
2234 memset((void *)unaligned_chipptr, 0, size);
2235 return PAGE_ALIGN(unaligned_chipptr);
2238 static inline void chipfree(void)
2240 if (unaligned_chipptr)
2241 amiga_chip_free((void *)unaligned_chipptr);
2249 int __init amifb_init(void)
2251 int tag, i, err = 0;
2256 char *option = NULL;
2258 if (fb_get_options("amifb", &option)) {
2262 amifb_setup(option);
2264 if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO))
2268 * We request all registers starting from bplpt[0]
2270 if (!request_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120,
2271 "amifb [Denise/Lisa]"))
2274 custom.dmacon = DMAF_ALL | DMAF_MASTER;
2276 switch (amiga_chipset) {
2277 #ifdef CONFIG_FB_AMIGA_OCS
2279 strcat(fb_info.fix.id, "OCS");
2282 maxdepth[TAG_SHRES] = 0; /* OCS means no SHRES */
2283 maxdepth[TAG_HIRES] = 4;
2284 maxdepth[TAG_LORES] = 6;
2285 maxfmode = TAG_FMODE_1;
2286 defmode = amiga_vblank == 50 ? DEFMODE_PAL
2288 fb_info.fix.smem_len = VIDEOMEMSIZE_OCS;
2290 #endif /* CONFIG_FB_AMIGA_OCS */
2292 #ifdef CONFIG_FB_AMIGA_ECS
2294 strcat(fb_info.fix.id, "ECS");
2296 maxdepth[TAG_SHRES] = 2;
2297 maxdepth[TAG_HIRES] = 4;
2298 maxdepth[TAG_LORES] = 6;
2299 maxfmode = TAG_FMODE_1;
2300 if (AMIGAHW_PRESENT(AMBER_FF))
2301 defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL
2302 : DEFMODE_AMBER_NTSC;
2304 defmode = amiga_vblank == 50 ? DEFMODE_PAL
2306 if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT >
2307 VIDEOMEMSIZE_ECS_1M)
2308 fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_2M;
2310 fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_1M;
2312 #endif /* CONFIG_FB_AMIGA_ECS */
2314 #ifdef CONFIG_FB_AMIGA_AGA
2316 strcat(fb_info.fix.id, "AGA");
2318 maxdepth[TAG_SHRES] = 8;
2319 maxdepth[TAG_HIRES] = 8;
2320 maxdepth[TAG_LORES] = 8;
2321 maxfmode = TAG_FMODE_4;
2322 defmode = DEFMODE_AGA;
2323 if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT >
2324 VIDEOMEMSIZE_AGA_1M)
2325 fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_2M;
2327 fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_1M;
2329 #endif /* CONFIG_FB_AMIGA_AGA */
2332 #ifdef CONFIG_FB_AMIGA_OCS
2333 printk("Unknown graphics chipset, defaulting to OCS\n");
2334 strcat(fb_info.fix.id, "Unknown");
2335 goto default_chipset;
2336 #else /* CONFIG_FB_AMIGA_OCS */
2339 #endif /* CONFIG_FB_AMIGA_OCS */
2344 * Calculate the Pixel Clock Values for this Machine
2348 u_long tmp = DIVUL(200000000000ULL, amiga_eclock);
2350 pixclock[TAG_SHRES] = (tmp + 4) / 8; /* SHRES: 35 ns / 28 MHz */
2351 pixclock[TAG_HIRES] = (tmp + 2) / 4; /* HIRES: 70 ns / 14 MHz */
2352 pixclock[TAG_LORES] = (tmp + 1) / 2; /* LORES: 140 ns / 7 MHz */
2356 * Replace the Tag Values with the Real Pixel Clock Values
2359 for (i = 0; i < NUM_TOTAL_MODES; i++) {
2360 struct fb_videomode *mode = &ami_modedb[i];
2361 tag = mode->pixclock;
2362 if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) {
2363 mode->pixclock = pixclock[tag];
2368 * These monitor specs are for a typical Amiga monitor (e.g. A1960)
2370 if (fb_info.monspecs.hfmin == 0) {
2371 fb_info.monspecs.hfmin = 15000;
2372 fb_info.monspecs.hfmax = 38000;
2373 fb_info.monspecs.vfmin = 49;
2374 fb_info.monspecs.vfmax = 90;
2377 fb_info.fbops = &amifb_ops;
2378 fb_info.par = ¤tpar;
2379 fb_info.flags = FBINFO_DEFAULT;
2381 if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb,
2382 NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
2388 chipptr = chipalloc(fb_info.fix.smem_len+
2394 assignchunk(videomemory, u_long, chipptr, fb_info.fix.smem_len);
2395 assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE);
2396 assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE);
2397 assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE);
2398 assignchunk(copdisplay.list[0][0], copins *, chipptr, COPLISTSIZE);
2399 assignchunk(copdisplay.list[0][1], copins *, chipptr, COPLISTSIZE);
2400 assignchunk(copdisplay.list[1][0], copins *, chipptr, COPLISTSIZE);
2401 assignchunk(copdisplay.list[1][1], copins *, chipptr, COPLISTSIZE);
2404 * access the videomem with writethrough cache
2406 fb_info.fix.smem_start = (u_long)ZTWO_PADDR(videomemory);
2407 videomemory = (u_long)ioremap_writethrough(fb_info.fix.smem_start,
2408 fb_info.fix.smem_len);
2410 printk("amifb: WARNING! unable to map videomem cached writethrough\n");
2411 videomemory = ZTWO_VADDR(fb_info.fix.smem_start);
2414 fb_info.screen_base = (char *)videomemory;
2415 memset(dummysprite, 0, DUMMYSPRITEMEMSIZE);
2418 * Enable Display DMA
2421 custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
2422 DMAF_BLITTER | DMAF_SPRITE;
2425 * Make sure the Copper has something to do
2430 if (request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0,
2431 "fb vertb handler", ¤tpar)) {
2436 fb_alloc_cmap(&fb_info.cmap, 1<<fb_info.var.bits_per_pixel, 0);
2438 if (register_framebuffer(&fb_info) < 0) {
2443 printk("fb%d: %s frame buffer device, using %dK of video memory\n",
2444 fb_info.node, fb_info.fix.id, fb_info.fix.smem_len>>10);
2453 static void amifb_deinit(void)
2455 fb_dealloc_cmap(&fb_info.cmap);
2457 release_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120);
2458 custom.dmacon = DMAF_ALL | DMAF_MASTER;
2463 * Blank the display.
2466 static int amifb_blank(int blank, struct fb_info *info)
2468 do_blank = blank ? blank : -1;
2474 * Flash the cursor (called by VBlank interrupt)
2477 static int flash_cursor(void)
2479 static int cursorcount = 1;
2481 if (cursormode == FB_CURSOR_FLASH) {
2482 if (!--cursorcount) {
2483 cursorstate = -cursorstate;
2484 cursorcount = cursorrate;
2493 * VBlank Display Interrupt
2496 static irqreturn_t amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp)
2498 if (do_vmode_pan || do_vmode_full)
2499 ami_update_display();
2506 ami_rebuild_copper();
2507 do_cursor = do_vmode_pan = 0;
2508 } else if (do_cursor) {
2522 if (do_vmode_full) {
2523 ami_reinit_copper();
2529 /* --------------------------- Hardware routines --------------------------- */
2532 * Get the video params out of `var'. If a value doesn't fit, round
2533 * it up, if it's too big, return -EINVAL.
2536 static int ami_decode_var(struct fb_var_screeninfo *var,
2537 struct amifb_par *par)
2539 u_short clk_shift, line_shift;
2540 u_long maxfetchstop, fstrt, fsize, fconst, xres_n, yres_n;
2541 u_int htotal, vtotal;
2544 * Find a matching Pixel Clock
2547 for (clk_shift = TAG_SHRES; clk_shift <= TAG_LORES; clk_shift++)
2548 if (var->pixclock <= pixclock[clk_shift])
2550 if (clk_shift > TAG_LORES) {
2551 DPRINTK("pixclock too high\n");
2554 par->clk_shift = clk_shift;
2557 * Check the Geometry Values
2560 if ((par->xres = var->xres) < 64)
2562 if ((par->yres = var->yres) < 64)
2564 if ((par->vxres = var->xres_virtual) < par->xres)
2565 par->vxres = par->xres;
2566 if ((par->vyres = var->yres_virtual) < par->yres)
2567 par->vyres = par->yres;
2569 par->bpp = var->bits_per_pixel;
2573 if (par->bpp > maxdepth[clk_shift]) {
2574 if (round_down_bpp && maxdepth[clk_shift])
2575 par->bpp = maxdepth[clk_shift];
2577 DPRINTK("invalid bpp\n");
2581 } else if (var->nonstd == FB_NONSTD_HAM) {
2584 if (par->bpp != 6) {
2587 if (par->bpp != 8 || !IS_AGA) {
2588 DPRINTK("invalid bpp for ham mode\n");
2593 DPRINTK("unknown nonstd mode\n");
2598 * FB_VMODE_SMOOTH_XPAN will be cleared, if one of the folloing
2599 * checks failed and smooth scrolling is not possible
2602 par->vmode = var->vmode | FB_VMODE_SMOOTH_XPAN;
2603 switch (par->vmode & FB_VMODE_MASK) {
2604 case FB_VMODE_INTERLACED:
2607 case FB_VMODE_NONINTERLACED:
2610 case FB_VMODE_DOUBLE:
2612 DPRINTK("double mode only possible with aga\n");
2618 DPRINTK("unknown video mode\n");
2622 par->line_shift = line_shift;
2625 * Vertical and Horizontal Timings
2628 xres_n = par->xres<<clk_shift;
2629 yres_n = par->yres<<line_shift;
2630 par->htotal = down8((var->left_margin+par->xres+var->right_margin+var->hsync_len)<<clk_shift);
2631 par->vtotal = down2(((var->upper_margin+par->yres+var->lower_margin+var->vsync_len)<<line_shift)+1);
2634 par->bplcon3 = sprpixmode[clk_shift];
2637 if (var->sync & FB_SYNC_BROADCAST) {
2638 par->diwstop_h = par->htotal-((var->right_margin-var->hsync_len)<<clk_shift);
2640 par->diwstop_h += mod4(var->hsync_len);
2642 par->diwstop_h = down4(par->diwstop_h);
2644 par->diwstrt_h = par->diwstop_h - xres_n;
2645 par->diwstop_v = par->vtotal-((var->lower_margin-var->vsync_len)<<line_shift);
2646 par->diwstrt_v = par->diwstop_v - yres_n;
2647 if (par->diwstop_h >= par->htotal+8) {
2648 DPRINTK("invalid diwstop_h\n");
2651 if (par->diwstop_v > par->vtotal) {
2652 DPRINTK("invalid diwstop_v\n");
2657 /* Initialize sync with some reasonable values for pwrsave */
2668 if (par->vtotal > (PAL_VTOTAL+NTSC_VTOTAL)/2) {
2669 /* PAL video mode */
2670 if (par->htotal != PAL_HTOTAL) {
2671 DPRINTK("htotal invalid for pal\n");
2674 if (par->diwstrt_h < PAL_DIWSTRT_H) {
2675 DPRINTK("diwstrt_h too low for pal\n");
2678 if (par->diwstrt_v < PAL_DIWSTRT_V) {
2679 DPRINTK("diwstrt_v too low for pal\n");
2682 htotal = PAL_HTOTAL>>clk_shift;
2683 vtotal = PAL_VTOTAL>>1;
2685 par->beamcon0 = BMC0_PAL;
2686 par->bplcon3 |= BPC3_BRDRBLNK;
2687 } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
2688 AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
2689 par->beamcon0 = BMC0_PAL;
2691 } else if (amiga_vblank != 50) {
2692 DPRINTK("pal not supported by this chipset\n");
2697 * In the AGA chipset seems to be hardware bug with BPC3_BRDRBLNK
2698 * and NTSC activated, so than better let diwstop_h <= 1812
2700 if (par->htotal != NTSC_HTOTAL) {
2701 DPRINTK("htotal invalid for ntsc\n");
2704 if (par->diwstrt_h < NTSC_DIWSTRT_H) {
2705 DPRINTK("diwstrt_h too low for ntsc\n");
2708 if (par->diwstrt_v < NTSC_DIWSTRT_V) {
2709 DPRINTK("diwstrt_v too low for ntsc\n");
2712 htotal = NTSC_HTOTAL>>clk_shift;
2713 vtotal = NTSC_VTOTAL>>1;
2716 par->bplcon3 |= BPC3_BRDRBLNK;
2717 } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
2718 AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
2721 } else if (amiga_vblank != 60) {
2722 DPRINTK("ntsc not supported by this chipset\n");
2727 if (par->diwstrt_h >= 1024 || par->diwstop_h < 1024 ||
2728 par->diwstrt_v >= 512 || par->diwstop_v < 256) {
2729 DPRINTK("invalid position for display on ocs\n");
2733 } else if (!IS_OCS) {
2734 /* Programmable video mode */
2735 par->hsstrt = var->right_margin<<clk_shift;
2736 par->hsstop = (var->right_margin+var->hsync_len)<<clk_shift;
2737 par->diwstop_h = par->htotal - mod8(par->hsstrt) + 8 - (1 << clk_shift);
2739 par->diwstop_h = down4(par->diwstop_h) - 16;
2740 par->diwstrt_h = par->diwstop_h - xres_n;
2741 par->hbstop = par->diwstrt_h + 4;
2742 par->hbstrt = par->diwstop_h + 4;
2743 if (par->hbstrt >= par->htotal + 8)
2744 par->hbstrt -= par->htotal;
2745 par->hcenter = par->hsstrt + (par->htotal >> 1);
2746 par->vsstrt = var->lower_margin<<line_shift;
2747 par->vsstop = (var->lower_margin+var->vsync_len)<<line_shift;
2748 par->diwstop_v = par->vtotal;
2749 if ((par->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
2750 par->diwstop_v -= 2;
2751 par->diwstrt_v = par->diwstop_v - yres_n;
2752 par->vbstop = par->diwstrt_v - 2;
2753 par->vbstrt = par->diwstop_v - 2;
2754 if (par->vtotal > 2048) {
2755 DPRINTK("vtotal too high\n");
2758 if (par->htotal > 2048) {
2759 DPRINTK("htotal too high\n");
2762 par->bplcon3 |= BPC3_EXTBLKEN;
2763 par->beamcon0 = BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS |
2764 BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN |
2765 BMC0_PAL | BMC0_VARCSYEN;
2766 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
2767 par->beamcon0 |= BMC0_HSYTRUE;
2768 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
2769 par->beamcon0 |= BMC0_VSYTRUE;
2770 if (var->sync & FB_SYNC_COMP_HIGH_ACT)
2771 par->beamcon0 |= BMC0_CSYTRUE;
2772 htotal = par->htotal>>clk_shift;
2773 vtotal = par->vtotal>>1;
2775 DPRINTK("only broadcast modes possible for ocs\n");
2780 * Checking the DMA timing
2783 fconst = 16<<maxfmode<<clk_shift;
2786 * smallest window start value without turn off other dma cycles
2787 * than sprite1-7, unless you change min_fstrt
2791 fsize = ((maxfmode+clk_shift <= 1) ? fconst : 64);
2792 fstrt = downx(fconst, par->diwstrt_h-4) - fsize;
2793 if (fstrt < min_fstrt) {
2794 DPRINTK("fetch start too low\n");
2799 * smallest window start value where smooth scrolling is possible
2802 fstrt = downx(fconst, par->diwstrt_h-fconst+(1<<clk_shift)-4) - fsize;
2803 if (fstrt < min_fstrt)
2804 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
2806 maxfetchstop = down16(par->htotal - 80);
2808 fstrt = downx(fconst, par->diwstrt_h-4) - 64 - fconst;
2809 fsize = upx(fconst, xres_n + modx(fconst, downx(1<<clk_shift, par->diwstrt_h-4)));
2810 if (fstrt + fsize > maxfetchstop)
2811 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
2813 fsize = upx(fconst, xres_n);
2814 if (fstrt + fsize > maxfetchstop) {
2815 DPRINTK("fetch stop too high\n");
2819 if (maxfmode + clk_shift <= 1) {
2820 fsize = up64(xres_n + fconst - 1);
2821 if (min_fstrt + fsize - 64 > maxfetchstop)
2822 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
2824 fsize = up64(xres_n);
2825 if (min_fstrt + fsize - 64 > maxfetchstop) {
2826 DPRINTK("fetch size too high\n");
2835 * Check if there is enough time to update the bitplane pointers for ywrap
2838 if (par->htotal-fsize-64 < par->bpp*64)
2839 par->vmode &= ~FB_VMODE_YWRAP;
2842 * Bitplane calculations and check the Memory Requirements
2846 par->next_plane = div8(upx(16<<maxfmode, par->vxres));
2847 par->next_line = par->bpp*par->next_plane;
2848 if (par->next_line * par->vyres > fb_info.fix.smem_len) {
2849 DPRINTK("too few video mem\n");
2853 par->next_line = div8(upx(16<<maxfmode, par->vxres));
2854 par->next_plane = par->vyres*par->next_line;
2855 if (par->next_plane * par->bpp > fb_info.fix.smem_len) {
2856 DPRINTK("too few video mem\n");
2862 * Hardware Register Values
2865 par->bplcon0 = BPC0_COLOR | bplpixmode[clk_shift];
2867 par->bplcon0 |= BPC0_ECSENA;
2869 par->bplcon0 |= BPC0_BPU3;
2871 par->bplcon0 |= par->bpp<<12;
2872 if (var->nonstd == FB_NONSTD_HAM)
2873 par->bplcon0 |= BPC0_HAM;
2874 if (var->sync & FB_SYNC_EXT)
2875 par->bplcon0 |= BPC0_ERSY;
2878 par->fmode = bplfetchmode[maxfmode];
2880 switch (par->vmode & FB_VMODE_MASK) {
2881 case FB_VMODE_INTERLACED:
2882 par->bplcon0 |= BPC0_LACE;
2884 case FB_VMODE_DOUBLE:
2886 par->fmode |= FMODE_SSCAN2 | FMODE_BSCAN2;
2890 if (!((par->vmode ^ var->vmode) & FB_VMODE_YWRAP)) {
2891 par->xoffset = var->xoffset;
2892 par->yoffset = var->yoffset;
2893 if (par->vmode & FB_VMODE_YWRAP) {
2894 if (par->xoffset || par->yoffset < 0 || par->yoffset >= par->vyres)
2895 par->xoffset = par->yoffset = 0;
2897 if (par->xoffset < 0 || par->xoffset > upx(16<<maxfmode, par->vxres-par->xres) ||
2898 par->yoffset < 0 || par->yoffset > par->vyres-par->yres)
2899 par->xoffset = par->yoffset = 0;
2902 par->xoffset = par->yoffset = 0;
2904 par->crsr.crsr_x = par->crsr.crsr_y = 0;
2905 par->crsr.spot_x = par->crsr.spot_y = 0;
2906 par->crsr.height = par->crsr.width = 0;
2908 #if 0 /* fbmon not done. uncomment for 2.5.x -brad */
2909 if (!fbmon_valid_timings(pixclock[clk_shift], htotal, vtotal,
2911 DPRINTK("mode doesn't fit for monitor\n");
2920 * Fill the `var' structure based on the values in `par' and maybe
2921 * other values read out of the hardware.
2924 static int ami_encode_var(struct fb_var_screeninfo *var,
2925 struct amifb_par *par)
2927 u_short clk_shift, line_shift;
2929 memset(var, 0, sizeof(struct fb_var_screeninfo));
2931 clk_shift = par->clk_shift;
2932 line_shift = par->line_shift;
2934 var->xres = par->xres;
2935 var->yres = par->yres;
2936 var->xres_virtual = par->vxres;
2937 var->yres_virtual = par->vyres;
2938 var->xoffset = par->xoffset;
2939 var->yoffset = par->yoffset;
2941 var->bits_per_pixel = par->bpp;
2944 var->red.offset = 0;
2945 var->red.msb_right = 0;
2946 var->red.length = par->bpp;
2947 if (par->bplcon0 & BPC0_HAM)
2948 var->red.length -= 2;
2949 var->blue = var->green = var->red;
2950 var->transp.offset = 0;
2951 var->transp.length = 0;
2952 var->transp.msb_right = 0;
2954 if (par->bplcon0 & BPC0_HAM)
2955 var->nonstd = FB_NONSTD_HAM;
2963 var->pixclock = pixclock[clk_shift];
2965 if (IS_AGA && par->fmode & FMODE_BSCAN2)
2966 var->vmode = FB_VMODE_DOUBLE;
2967 else if (par->bplcon0 & BPC0_LACE)
2968 var->vmode = FB_VMODE_INTERLACED;
2970 var->vmode = FB_VMODE_NONINTERLACED;
2972 if (!IS_OCS && par->beamcon0 & BMC0_VARBEAMEN) {
2973 var->hsync_len = (par->hsstop-par->hsstrt)>>clk_shift;
2974 var->right_margin = par->hsstrt>>clk_shift;
2975 var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
2976 var->vsync_len = (par->vsstop-par->vsstrt)>>line_shift;
2977 var->lower_margin = par->vsstrt>>line_shift;
2978 var->upper_margin = (par->vtotal>>line_shift) - var->yres - var->lower_margin - var->vsync_len;
2980 if (par->beamcon0 & BMC0_HSYTRUE)
2981 var->sync |= FB_SYNC_HOR_HIGH_ACT;
2982 if (par->beamcon0 & BMC0_VSYTRUE)
2983 var->sync |= FB_SYNC_VERT_HIGH_ACT;
2984 if (par->beamcon0 & BMC0_CSYTRUE)
2985 var->sync |= FB_SYNC_COMP_HIGH_ACT;
2987 var->sync = FB_SYNC_BROADCAST;
2988 var->hsync_len = (152>>clk_shift) + mod4(par->diwstop_h);
2989 var->right_margin = ((par->htotal - down4(par->diwstop_h))>>clk_shift) + var->hsync_len;
2990 var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
2991 var->vsync_len = 4>>line_shift;
2992 var->lower_margin = ((par->vtotal - par->diwstop_v)>>line_shift) + var->vsync_len;
2993 var->upper_margin = (((par->vtotal - 2)>>line_shift) + 1) - var->yres -
2994 var->lower_margin - var->vsync_len;
2997 if (par->bplcon0 & BPC0_ERSY)
2998 var->sync |= FB_SYNC_EXT;
2999 if (par->vmode & FB_VMODE_YWRAP)
3000 var->vmode |= FB_VMODE_YWRAP;
3007 * Pan or Wrap the Display
3009 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
3013 static void ami_pan_var(struct fb_var_screeninfo *var)
3015 struct amifb_par *par = ¤tpar;
3017 par->xoffset = var->xoffset;
3018 par->yoffset = var->yoffset;
3019 if (var->vmode & FB_VMODE_YWRAP)
3020 par->vmode |= FB_VMODE_YWRAP;
3022 par->vmode &= ~FB_VMODE_YWRAP;
3033 static int ami_update_par(void)
3035 struct amifb_par *par = ¤tpar;
3036 short clk_shift, vshift, fstrt, fsize, fstop, fconst, shift, move, mod;
3038 clk_shift = par->clk_shift;
3040 if (!(par->vmode & FB_VMODE_SMOOTH_XPAN))
3041 par->xoffset = upx(16<<maxfmode, par->xoffset);
3043 fconst = 16<<maxfmode<<clk_shift;
3044 vshift = modx(16<<maxfmode, par->xoffset);
3045 fstrt = par->diwstrt_h - (vshift<<clk_shift) - 4;
3046 fsize = (par->xres+vshift)<<clk_shift;
3047 shift = modx(fconst, fstrt);
3048 move = downx(2<<maxfmode, div8(par->xoffset));
3049 if (maxfmode + clk_shift > 1) {
3050 fstrt = downx(fconst, fstrt) - 64;
3051 fsize = upx(fconst, fsize);
3052 fstop = fstrt + fsize - fconst;
3054 mod = fstrt = downx(fconst, fstrt) - fconst;
3055 fstop = fstrt + upx(fconst, fsize) - 64;
3056 fsize = up64(fsize);
3057 fstrt = fstop - fsize + 64;
3058 if (fstrt < min_fstrt) {
3059 fstop += min_fstrt - fstrt;
3062 move = move - div8((mod-fstrt)>>clk_shift);
3064 mod = par->next_line - div8(fsize>>clk_shift);
3065 par->ddfstrt = fstrt;
3066 par->ddfstop = fstop;
3067 par->bplcon1 = hscroll2hw(shift);
3069 if (par->bplcon0 & BPC0_LACE)
3070 par->bpl2mod += par->next_line;
3071 if (IS_AGA && (par->fmode & FMODE_BSCAN2))
3072 par->bpl1mod = -div8(fsize>>clk_shift);
3074 par->bpl1mod = par->bpl2mod;
3077 par->bplpt0 = fb_info.fix.smem_start + par->next_line*par->yoffset + move;
3078 if (par->vmode & FB_VMODE_YWRAP) {
3079 if (par->yoffset > par->vyres-par->yres) {
3080 par->bplpt0wrap = fb_info.fix.smem_start + move;
3081 if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v+par->vyres-par->yoffset))
3082 par->bplpt0wrap += par->next_line;
3086 par->bplpt0 = fb_info.fix.smem_start + move;
3088 if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v))
3089 par->bplpt0 += par->next_line;
3096 * Set a single color register. The values supplied are already
3097 * rounded down to the hardware's capabilities (according to the
3098 * entries in the var structure). Return != 0 for invalid regno.
3101 static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
3102 u_int transp, struct fb_info *info)
3107 } else if (currentpar.bplcon0 & BPC0_SHRES) {
3124 * Update the corresponding Hardware Color Register, unless it's Color
3125 * Register 0 and the screen is blanked.
3127 * VBlank is switched off to protect bplcon3 or ecs_palette[] from
3128 * being changed by ami_do_blank() during the VBlank.
3131 if (regno || !is_blanked) {
3132 #if defined(CONFIG_FB_AMIGA_AGA)
3134 u_short bplcon3 = currentpar.bplcon3;
3136 custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000);
3137 custom.color[regno&31] = rgb2hw8_high(red, green, blue);
3138 custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000) | BPC3_LOCT;
3139 custom.color[regno&31] = rgb2hw8_low(red, green, blue);
3140 custom.bplcon3 = bplcon3;
3144 #if defined(CONFIG_FB_AMIGA_ECS)
3145 if (currentpar.bplcon0 & BPC0_SHRES) {
3146 u_short color, mask;
3150 color = rgb2hw2(red, green, blue);
3152 for (i = regno+12; i >= (int)regno; i -= 4)
3153 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3154 mask <<=2; color >>= 2;
3155 regno = down16(regno)+mul4(mod4(regno));
3156 for (i = regno+3; i >= (int)regno; i--)
3157 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3161 custom.color[regno] = rgb2hw4(red, green, blue);
3166 static void ami_update_display(void)
3168 struct amifb_par *par = ¤tpar;
3170 custom.bplcon1 = par->bplcon1;
3171 custom.bpl1mod = par->bpl1mod;
3172 custom.bpl2mod = par->bpl2mod;
3173 custom.ddfstrt = ddfstrt2hw(par->ddfstrt);
3174 custom.ddfstop = ddfstop2hw(par->ddfstop);
3178 * Change the video mode (called by VBlank interrupt)
3181 static void ami_init_display(void)
3183 struct amifb_par *par = ¤tpar;
3186 custom.bplcon0 = par->bplcon0 & ~BPC0_LACE;
3187 custom.bplcon2 = (IS_OCS ? 0 : BPC2_KILLEHB) | BPC2_PF2P2 | BPC2_PF1P2;
3189 custom.bplcon3 = par->bplcon3;
3191 custom.bplcon4 = BPC4_ESPRM4 | BPC4_OSPRM4;
3192 if (par->beamcon0 & BMC0_VARBEAMEN) {
3193 custom.htotal = htotal2hw(par->htotal);
3194 custom.hbstrt = hbstrt2hw(par->hbstrt);
3195 custom.hbstop = hbstop2hw(par->hbstop);
3196 custom.hsstrt = hsstrt2hw(par->hsstrt);
3197 custom.hsstop = hsstop2hw(par->hsstop);
3198 custom.hcenter = hcenter2hw(par->hcenter);
3199 custom.vtotal = vtotal2hw(par->vtotal);
3200 custom.vbstrt = vbstrt2hw(par->vbstrt);
3201 custom.vbstop = vbstop2hw(par->vbstop);
3202 custom.vsstrt = vsstrt2hw(par->vsstrt);
3203 custom.vsstop = vsstop2hw(par->vsstop);
3206 if (!IS_OCS || par->hsstop)
3207 custom.beamcon0 = par->beamcon0;
3209 custom.fmode = par->fmode;
3212 * The minimum period for audio depends on htotal
3215 amiga_audio_min_period = div16(par->htotal);
3217 is_lace = par->bplcon0 & BPC0_LACE ? 1 : 0;
3220 i = custom.vposr >> 15;
3222 custom.vposw = custom.vposr | 0x8000;
3227 custom.vposw = custom.vposr | 0x8000;
3229 custom.cop2lc = (u_short *)ZTWO_PADDR(copdisplay.list[currentcop][i]);
3233 * (Un)Blank the screen (called by VBlank interrupt)
3236 static void ami_do_blank(void)
3238 struct amifb_par *par = ¤tpar;
3239 #if defined(CONFIG_FB_AMIGA_AGA)
3240 u_short bplcon3 = par->bplcon3;
3242 u_char red, green, blue;
3245 custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
3246 red = green = blue = 0;
3247 if (!IS_OCS && do_blank > 1) {
3249 case FB_BLANK_VSYNC_SUSPEND:
3250 custom.hsstrt = hsstrt2hw(par->hsstrt);
3251 custom.hsstop = hsstop2hw(par->hsstop);
3252 custom.vsstrt = vsstrt2hw(par->vtotal+4);
3253 custom.vsstop = vsstop2hw(par->vtotal+4);
3255 case FB_BLANK_HSYNC_SUSPEND:
3256 custom.hsstrt = hsstrt2hw(par->htotal+16);
3257 custom.hsstop = hsstop2hw(par->htotal+16);
3258 custom.vsstrt = vsstrt2hw(par->vsstrt);
3259 custom.vsstop = vsstrt2hw(par->vsstop);
3261 case FB_BLANK_POWERDOWN:
3262 custom.hsstrt = hsstrt2hw(par->htotal+16);
3263 custom.hsstop = hsstop2hw(par->htotal+16);
3264 custom.vsstrt = vsstrt2hw(par->vtotal+4);
3265 custom.vsstop = vsstop2hw(par->vtotal+4);
3268 if (!(par->beamcon0 & BMC0_VARBEAMEN)) {
3269 custom.htotal = htotal2hw(par->htotal);
3270 custom.vtotal = vtotal2hw(par->vtotal);
3271 custom.beamcon0 = BMC0_HARDDIS | BMC0_VARBEAMEN |
3272 BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARCSYEN;
3276 custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_SPRITE;
3281 custom.hsstrt = hsstrt2hw(par->hsstrt);
3282 custom.hsstop = hsstop2hw(par->hsstop);
3283 custom.vsstrt = vsstrt2hw(par->vsstrt);
3284 custom.vsstop = vsstop2hw(par->vsstop);
3285 custom.beamcon0 = par->beamcon0;
3288 #if defined(CONFIG_FB_AMIGA_AGA)
3290 custom.bplcon3 = bplcon3;
3291 custom.color[0] = rgb2hw8_high(red, green, blue);
3292 custom.bplcon3 = bplcon3 | BPC3_LOCT;
3293 custom.color[0] = rgb2hw8_low(red, green, blue);
3294 custom.bplcon3 = bplcon3;
3297 #if defined(CONFIG_FB_AMIGA_ECS)
3298 if (par->bplcon0 & BPC0_SHRES) {
3299 u_short color, mask;
3303 color = rgb2hw2(red, green, blue);
3304 for (i = 12; i >= 0; i -= 4)
3305 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3306 mask <<=2; color >>= 2;
3307 for (i = 3; i >= 0; i--)
3308 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3311 custom.color[0] = rgb2hw4(red, green, blue);
3312 is_blanked = do_blank > 0 ? do_blank : 0;
3315 static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix)
3317 struct amifb_par *par = ¤tpar;
3319 fix->crsr_width = fix->crsr_xsize = par->crsr.width;
3320 fix->crsr_height = fix->crsr_ysize = par->crsr.height;
3321 fix->crsr_color1 = 17;
3322 fix->crsr_color2 = 18;
3326 static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data)
3328 struct amifb_par *par = ¤tpar;
3329 register u_short *lspr, *sspr;
3331 register u_long datawords asm ("d2");
3333 register u_long datawords;
3335 register short delta;
3336 register u_char color;
3337 short height, width, bits, words;
3340 size = par->crsr.height*par->crsr.width;
3341 alloc = var->height*var->width;
3342 var->height = par->crsr.height;
3343 var->width = par->crsr.width;
3344 var->xspot = par->crsr.spot_x;
3345 var->yspot = par->crsr.spot_y;
3346 if (size > var->height*var->width)
3347 return -ENAMETOOLONG;
3348 if (!access_ok(VERIFY_WRITE, data, size))
3350 delta = 1<<par->crsr.fmode;
3351 lspr = lofsprite + (delta<<1);
3352 if (par->bplcon0 & BPC0_LACE)
3353 sspr = shfsprite + (delta<<1);
3356 for (height = (short)var->height-1; height >= 0; height--) {
3357 bits = 0; words = delta; datawords = 0;
3358 for (width = (short)var->width-1; width >= 0; width--) {
3362 asm volatile ("movew %1@(%3:w:2),%0 ; swap %0 ; movew %1@+,%0"
3363 : "=d" (datawords), "=a" (lspr) : "1" (lspr), "d" (delta));
3365 datawords = (*(lspr+delta) << 16) | (*lspr++);
3371 "clrb %0 ; swap %1 ; lslw #1,%1 ; roxlb #1,%0 ; "
3372 "swap %1 ; lslw #1,%1 ; roxlb #1,%0"
3373 : "=d" (color), "=d" (datawords) : "1" (datawords));
3375 color = (((datawords >> 30) & 2)
3376 | ((datawords >> 15) & 1));
3379 put_user(color, data++);
3384 while (--words >= 0)
3387 asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
3388 : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
3392 u_short *tmp = lspr;
3401 static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data)
3403 struct amifb_par *par = ¤tpar;
3404 register u_short *lspr, *sspr;
3406 register u_long datawords asm ("d2");
3408 register u_long datawords;
3410 register short delta;
3412 short height, width, bits, words;
3416 else if (var->width <= 16)
3417 fmode = TAG_FMODE_1;
3418 else if (var->width <= 32)
3419 fmode = TAG_FMODE_2;
3420 else if (var->width <= 64)
3421 fmode = TAG_FMODE_4;
3424 if (fmode > maxfmode)
3428 if (!access_ok(VERIFY_READ, data, var->width*var->height))
3431 lofsprite = shfsprite = (u_short *)spritememory;
3432 lspr = lofsprite + (delta<<1);
3433 if (par->bplcon0 & BPC0_LACE) {
3434 if (((var->height+4)<<fmode<<2) > SPRITEMEMSIZE)
3436 memset(lspr, 0, (var->height+4)<<fmode<<2);
3437 shfsprite += ((var->height+5)&-2)<<fmode;
3438 sspr = shfsprite + (delta<<1);
3440 if (((var->height+2)<<fmode<<2) > SPRITEMEMSIZE)
3442 memset(lspr, 0, (var->height+2)<<fmode<<2);
3445 for (height = (short)var->height-1; height >= 0; height--) {
3446 bits = 16; words = delta; datawords = 0;
3447 for (width = (short)var->width-1; width >= 0; width--) {
3448 unsigned long tdata = 0;
3449 get_user(tdata, data);
3453 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0 ; "
3454 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0"
3456 : "0" (datawords), "d" (tdata));
3458 datawords = ((datawords << 1) & 0xfffefffe);
3459 datawords |= tdata & 1;
3460 datawords |= (tdata & 2) << (16-1);
3465 asm volatile ("swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+"
3466 : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta));
3468 *(lspr+delta) = (u_short) (datawords >> 16);
3469 *lspr++ = (u_short) (datawords & 0xffff);
3477 "swap %2 ; lslw %4,%2 ; movew %2,%0@(%3:w:2) ; "
3478 "swap %2 ; lslw %4,%2 ; movew %2,%0@+"
3479 : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta), "d" (bits));
3481 *(lspr+delta) = (u_short) (datawords >> (16+bits));
3482 *lspr++ = (u_short) ((datawords & 0x0000ffff) >> bits);
3485 while (--words >= 0) {
3487 asm volatile ("moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+"
3488 : "=a" (lspr) : "0" (lspr), "d" (delta) : "d0");
3495 asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
3496 : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
3500 u_short *tmp = lspr;
3506 par->crsr.height = var->height;
3507 par->crsr.width = var->width;
3508 par->crsr.spot_x = var->xspot;
3509 par->crsr.spot_y = var->yspot;
3510 par->crsr.fmode = fmode;
3512 par->fmode &= ~(FMODE_SPAGEM | FMODE_SPR32);
3513 par->fmode |= sprfetchmode[fmode];
3514 custom.fmode = par->fmode;
3519 static int ami_get_cursorstate(struct fb_cursorstate *state)
3521 struct amifb_par *par = ¤tpar;
3523 state->xoffset = par->crsr.crsr_x;
3524 state->yoffset = par->crsr.crsr_y;
3525 state->mode = cursormode;
3529 static int ami_set_cursorstate(struct fb_cursorstate *state)
3531 struct amifb_par *par = ¤tpar;
3533 par->crsr.crsr_x = state->xoffset;
3534 par->crsr.crsr_y = state->yoffset;
3535 if ((cursormode = state->mode) == FB_CURSOR_OFF)
3541 static void ami_set_sprite(void)
3543 struct amifb_par *par = ¤tpar;
3544 copins *copl, *cops;
3549 cops = copdisplay.list[currentcop][0];
3550 copl = copdisplay.list[currentcop][1];
3551 ps = pl = ZTWO_PADDR(dummysprite);
3552 mx = par->crsr.crsr_x-par->crsr.spot_x;
3553 my = par->crsr.crsr_y-par->crsr.spot_y;
3554 if (!(par->vmode & FB_VMODE_YWRAP)) {
3558 if (!is_blanked && cursorstate > 0 && par->crsr.height > 0 &&
3559 mx > -(short)par->crsr.width && mx < par->xres &&
3560 my > -(short)par->crsr.height && my < par->yres) {
3561 pl = ZTWO_PADDR(lofsprite);
3562 hs = par->diwstrt_h + (mx<<par->clk_shift) - 4;
3563 vs = par->diwstrt_v + (my<<par->line_shift);
3564 ve = vs + (par->crsr.height<<par->line_shift);
3565 if (par->bplcon0 & BPC0_LACE) {
3566 ps = ZTWO_PADDR(shfsprite);
3567 lofsprite[0] = spr2hw_pos(vs, hs);
3568 shfsprite[0] = spr2hw_pos(vs+1, hs);
3570 lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
3571 shfsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs+1, hs, ve+1);
3572 pt = pl; pl = ps; ps = pt;
3574 lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve+1);
3575 shfsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs+1, hs, ve);
3578 lofsprite[0] = spr2hw_pos(vs, hs) | (IS_AGA && (par->fmode & FMODE_BSCAN2) ? 0x80 : 0);
3579 lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
3582 copl[cop_spr0ptrh].w[1] = highw(pl);
3583 copl[cop_spr0ptrl].w[1] = loww(pl);
3584 if (par->bplcon0 & BPC0_LACE) {
3585 cops[cop_spr0ptrh].w[1] = highw(ps);
3586 cops[cop_spr0ptrl].w[1] = loww(ps);
3592 * Initialise the Copper Initialisation List
3595 static void __init ami_init_copper(void)
3597 copins *cop = copdisplay.init;
3602 (cop++)->l = CMOVE(BPC0_COLOR | BPC0_SHRES | BPC0_ECSENA, bplcon0);
3603 (cop++)->l = CMOVE(0x0181, diwstrt);
3604 (cop++)->l = CMOVE(0x0281, diwstop);
3605 (cop++)->l = CMOVE(0x0000, diwhigh);
3607 (cop++)->l = CMOVE(BPC0_COLOR, bplcon0);
3608 p = ZTWO_PADDR(dummysprite);
3609 for (i = 0; i < 8; i++) {
3610 (cop++)->l = CMOVE(0, spr[i].pos);
3611 (cop++)->l = CMOVE(highw(p), sprpt[i]);
3612 (cop++)->l = CMOVE2(loww(p), sprpt[i]);
3615 (cop++)->l = CMOVE(IF_SETCLR | IF_COPER, intreq);
3616 copdisplay.wait = cop;
3618 (cop++)->l = CMOVE(0, copjmp2);
3621 custom.cop1lc = (u_short *)ZTWO_PADDR(copdisplay.init);
3625 static void ami_reinit_copper(void)
3627 struct amifb_par *par = ¤tpar;
3629 copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0;
3630 copdisplay.wait->l = CWAIT(32, par->diwstrt_v-4);
3634 * Build the Copper List
3637 static void ami_build_copper(void)
3639 struct amifb_par *par = ¤tpar;
3640 copins *copl, *cops;
3643 currentcop = 1 - currentcop;
3645 copl = copdisplay.list[currentcop][1];
3647 (copl++)->l = CWAIT(0, 10);
3648 (copl++)->l = CMOVE(par->bplcon0, bplcon0);
3649 (copl++)->l = CMOVE(0, sprpt[0]);
3650 (copl++)->l = CMOVE2(0, sprpt[0]);
3652 if (par->bplcon0 & BPC0_LACE) {
3653 cops = copdisplay.list[currentcop][0];
3655 (cops++)->l = CWAIT(0, 10);
3656 (cops++)->l = CMOVE(par->bplcon0, bplcon0);
3657 (cops++)->l = CMOVE(0, sprpt[0]);
3658 (cops++)->l = CMOVE2(0, sprpt[0]);
3660 (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v+1), diwstrt);
3661 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v+1), diwstop);
3662 (cops++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
3663 (cops++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
3665 (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v+1,
3666 par->diwstop_h, par->diwstop_v+1), diwhigh);
3667 (cops++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
3668 par->diwstop_h, par->diwstop_v), diwhigh);
3670 if (par->beamcon0 & BMC0_VARBEAMEN) {
3671 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
3672 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt+1), vbstrt);
3673 (copl++)->l = CMOVE(vbstop2hw(par->vbstop+1), vbstop);
3674 (cops++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
3675 (cops++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
3676 (cops++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
3680 p = ZTWO_PADDR(copdisplay.list[currentcop][0]);
3681 (copl++)->l = CMOVE(highw(p), cop2lc);
3682 (copl++)->l = CMOVE2(loww(p), cop2lc);
3683 p = ZTWO_PADDR(copdisplay.list[currentcop][1]);
3684 (cops++)->l = CMOVE(highw(p), cop2lc);
3685 (cops++)->l = CMOVE2(loww(p), cop2lc);
3686 copdisplay.rebuild[0] = cops;
3688 (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
3689 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
3691 (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
3692 par->diwstop_h, par->diwstop_v), diwhigh);
3694 if (par->beamcon0 & BMC0_VARBEAMEN) {
3695 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
3696 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
3697 (copl++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
3702 copdisplay.rebuild[1] = copl;
3705 ami_rebuild_copper();
3709 * Rebuild the Copper List
3711 * We only change the things that are not static
3714 static void ami_rebuild_copper(void)
3716 struct amifb_par *par = ¤tpar;
3717 copins *copl, *cops;
3718 u_short line, h_end1, h_end2;
3722 if (IS_AGA && maxfmode + par->clk_shift == 0)
3723 h_end1 = par->diwstrt_h-64;
3725 h_end1 = par->htotal-32;
3726 h_end2 = par->ddfstop+64;
3730 copl = copdisplay.rebuild[1];
3732 if (par->vmode & FB_VMODE_YWRAP) {
3733 if ((par->vyres-par->yoffset) != 1 || !mod2(par->diwstrt_v)) {
3734 if (par->yoffset > par->vyres-par->yres) {
3735 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3736 (copl++)->l = CMOVE(highw(p), bplpt[i]);
3737 (copl++)->l = CMOVE2(loww(p), bplpt[i]);
3739 line = par->diwstrt_v + ((par->vyres-par->yoffset)<<par->line_shift) - 1;
3740 while (line >= 512) {
3741 (copl++)->l = CWAIT(h_end1, 510);
3744 if (line >= 510 && IS_AGA && maxfmode + par->clk_shift == 0)
3745 (copl++)->l = CWAIT(h_end1, line);
3747 (copl++)->l = CWAIT(h_end2, line);
3748 p = par->bplpt0wrap;
3750 } else p = par->bplpt0wrap;
3752 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3753 (copl++)->l = CMOVE(highw(p), bplpt[i]);
3754 (copl++)->l = CMOVE2(loww(p), bplpt[i]);
3758 if (par->bplcon0 & BPC0_LACE) {
3759 cops = copdisplay.rebuild[0];
3761 if (mod2(par->diwstrt_v))
3762 p -= par->next_line;
3764 p += par->next_line;
3765 if (par->vmode & FB_VMODE_YWRAP) {
3766 if ((par->vyres-par->yoffset) != 1 || mod2(par->diwstrt_v)) {
3767 if (par->yoffset > par->vyres-par->yres+1) {
3768 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3769 (cops++)->l = CMOVE(highw(p), bplpt[i]);
3770 (cops++)->l = CMOVE2(loww(p), bplpt[i]);
3772 line = par->diwstrt_v + ((par->vyres-par->yoffset)<<par->line_shift) - 2;
3773 while (line >= 512) {
3774 (cops++)->l = CWAIT(h_end1, 510);
3777 if (line > 510 && IS_AGA && maxfmode + par->clk_shift == 0)
3778 (cops++)->l = CWAIT(h_end1, line);
3780 (cops++)->l = CWAIT(h_end2, line);
3781 p = par->bplpt0wrap;
3782 if (mod2(par->diwstrt_v+par->vyres-par->yoffset))
3783 p -= par->next_line;
3785 p += par->next_line;
3787 } else p = par->bplpt0wrap - par->next_line;
3789 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3790 (cops++)->l = CMOVE(highw(p), bplpt[i]);
3791 (cops++)->l = CMOVE2(loww(p), bplpt[i]);
3798 module_init(amifb_init);
3801 MODULE_LICENSE("GPL");
3803 void cleanup_module(void)
3805 unregister_framebuffer(&fb_info);