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