OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [m68k/] [amiga/] [amifb.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1623 jcastillo
/*
2
 * linux/arch/m68k/amiga/amifb.c -- Low level implementation of the Amiga frame
3
 *                                  buffer device
4
 *
5
 *    Copyright (C) 1995 Geert Uytterhoeven
6
 *
7
 *
8
 * This file is based on the Atari frame buffer device (atafb.c):
9
 *
10
 *    Copyright (C) 1994 Martin Schaller
11
 *                       Roman Hodek
12
 *
13
 *          with work by Andreas Schwab
14
 *                       Guenther Kelleter
15
 *
16
 * and on the original Amiga console driver (amicon.c):
17
 *
18
 *    Copyright (C) 1993 Hamish Macdonald
19
 *                       Greg Harp
20
 *    Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk]
21
 *
22
 *          with work by William Rucklidge (wjr@cs.cornell.edu)
23
 *                       Geert Uytterhoeven
24
 *                       Jes Sorensen (jds@kom.auc.dk)
25
 *
26
 *
27
 * History:
28
 *
29
 *   -  2 Dec 95: AGA version by Geert Uytterhoeven
30
 *
31
 *
32
 * This file is subject to the terms and conditions of the GNU General Public
33
 * License.  See the file COPYING in the main directory of this archive
34
 * for more details.
35
 */
36
 
37
 
38
#include <linux/kernel.h>
39
#include <linux/errno.h>
40
#include <linux/string.h>
41
#include <linux/mm.h>
42
#include <linux/tty.h>
43
#include <linux/malloc.h>
44
#include <linux/delay.h>
45
#include <linux/config.h>
46
#include <linux/interrupt.h>
47
#include <asm/segment.h>
48
#include <asm/system.h>
49
#include <asm/irq.h>
50
#include <asm/amigahw.h>
51
#include <asm/amigaints.h>
52
#include <asm/bootinfo.h>
53
#include <linux/fb.h>
54
 
55
 
56
#undef  CONFIG_AMIFB_OCS
57
#undef  CONFIG_AMIFB_ECS
58
#define CONFIG_AMIFB_AGA   /* Only AGA support at the moment */
59
 
60
#define USE_MONO_AMIFB_IF_NON_AGA
61
 
62
 
63
/* -------------------- BEGIN: TODO ----------------------------------------- **
64
 
65
 
66
   - scan the sources for `TODO'
67
 
68
   - timings and monspecs can be set via the kernel command line (cfr. Atari)
69
 
70
   - OCS and ECS
71
 
72
   - hardware cursor
73
 
74
   - Interlaced screen -> Interlaced sprite/hardware cursor
75
 
76
 
77
** -------------------- END: TODO ------------------------------------------- */
78
 
79
 
80
/*******************************************************************************
81
 
82
 
83
   Generic video timings
84
   ---------------------
85
 
86
   Timings used by the frame buffer interface:
87
 
88
   +----------+---------------------------------------------+----------+-------+
89
   |          |                ^                            |          |       |
90
   |          |                |upper_margin                |          |       |
91
   |          |                ¥                            |          |       |
92
   +----------###############################################----------+-------+
93
   |          #                ^                            #          |       |
94
   |          #                |                            #          |       |
95
   |          #                |                            #          |       |
96
   |          #                |                            #          |       |
97
   |   left   #                |                            #  right   | hsync |
98
   |  margin  #                |       xres                 #  margin  |  len  |
99
   |<-------->#<---------------+--------------------------->#<-------->|<----->|
100
   |          #                |                            #          |       |
101
   |          #                |                            #          |       |
102
   |          #                |                            #          |       |
103
   |          #                |yres                        #          |       |
104
   |          #                |                            #          |       |
105
   |          #                |                            #          |       |
106
   |          #                |                            #          |       |
107
   |          #                |                            #          |       |
108
   |          #                |                            #          |       |
109
   |          #                |                            #          |       |
110
   |          #                |                            #          |       |
111
   |          #                |                            #          |       |
112
   |          #                ¥                            #          |       |
113
   +----------###############################################----------+-------+
114
   |          |                ^                            |          |       |
115
   |          |                |lower_margin                |          |       |
116
   |          |                ¥                            |          |       |
117
   +----------+---------------------------------------------+----------+-------+
118
   |          |                ^                            |          |       |
119
   |          |                |vsync_len                   |          |       |
120
   |          |                ¥                            |          |       |
121
   +----------+---------------------------------------------+----------+-------+
122
 
123
 
124
   Amiga video timings
125
   -------------------
126
 
127
   The Amiga native chipsets uses another timing scheme:
128
 
129
      - hsstrt:   Start of horizontal synchronization pulse
130
      - hsstop:   End of horizontal synchronization pulse
131
      - htotal:   Last value on the line (i.e. line length = htotal+1)
132
      - vsstrt:   Start of vertical synchronization pulse
133
      - vsstop:   Start of vertical synchronization pulse
134
      - vtotal:   Last line value (i.e. number of lines = vtotal+1)
135
      - hcenter:  Start of vertical retrace for interlace
136
 
137
   You can specify the blanking timings independently. Currently I just set
138
   them equal to the respective synchronization values:
139
 
140
      - hbstrt:   Start of horizontal blank
141
      - hbstop:   End of horizontal blank
142
      - vbstrt:   Start of vertical blank
143
      - vbstop:   Start of vertical blank
144
 
145
   Horizontal values are in color clock cycles (280 ns), vertical values are in
146
   scanlines.
147
 
148
   (0, 0) is somewhere in the upper-left corner :-)
149
 
150
 
151
   Amiga visible window definitions
152
   --------------------------------
153
 
154
   Currently I only have values for AGA, SHRES (28 MHz dotclock). Feel free to
155
   make corrections and/or additions.
156
 
157
   Within the above synchronization specifications, the visible window is
158
   defined by the following parameters (actual register resolutions may be
159
   different; all horizontal values are normalized with respect to the pixel
160
   clock):
161
 
162
      - diwstrt_h:   Horizontal start of the visible window
163
      - diwstop_h:   Horizontal stop+1(*) of the visible window
164
      - diwstrt_v:   Vertical start of the visible window
165
      - diwstop_v:   Vertical stop of the visible window
166
      - ddfstrt:     Horizontal start of display DMA
167
      - ddfstop:     Horizontal stop of display DMA
168
      - hscroll:     Horizontal display output delay
169
 
170
   Sprite positioning:
171
 
172
      - sprstrt_h:   Horizontal start-4 of sprite
173
      - sprstrt_v:   Vertical start of sprite
174
 
175
   (*) Even Commodore did it wrong in the AGA monitor drivers by not adding 1.
176
 
177
   Horizontal values are in dotclock cycles (35 ns), vertical values are in
178
   scanlines.
179
 
180
   (0, 0) is somewhere in the upper-left corner :-)
181
 
182
 
183
   Dependencies (AGA, SHRES (35 ns dotclock))
184
   -------------------------------------------
185
 
186
   Since there are much more parameters for the Amiga display than for the
187
   frame buffer interface, there must be some dependencies among the Amiga display
188
   parameters. Here's what I found out:
189
 
190
      - ddfstrt and ddfstop are best aligned to 64 pixels.
191
      - the chipset needs 64+4 horizontal pixels after the DMA start before the
192
        first pixel is output, so diwstrt_h = ddfstrt+64+4 if you want to
193
        display the first pixel on the line too. Increase diwstrt_h for virtual
194
        screen panning.
195
      - the display DMA always fetches 64 pixels at a time (*).
196
      - ddfstop is ddfstrt+#pixels-64.
197
      - diwstop_h = diwstrt_h+xres+1. Because of the additional 1 this can be 1
198
        more than htotal.
199
      - hscroll simply adds a delay to the display output. Smooth horizontal
200
        panning needs an extra 64 pixels on the left to prefetch the pixels that
201
        `fall off' on the left.
202
      - if ddfstrt < 192, the sprite DMA cycles are all stolen by the bitplane
203
        DMA, so it's best to make the DMA start as late as possible.
204
      - you really don't want to make ddfstrt < 128, since this will steal DMA
205
        cycles from the other DMA channels (audio, floppy and Chip RAM refresh).
206
      - I make diwstop_h and diwstop_v as large as possible.
207
 
208
   (*) This is for fmode = 3. Lower fmodes allow for more freedom w.r.t. the
209
       timings, but they limit the maximum display depth, and cause more stress
210
       on the custom chip bus.
211
 
212
 
213
   DMA priorities
214
   --------------
215
 
216
   Since there are limits on the earliest start value for display DMA and the
217
   display of sprites, I use the following policy on horizontal panning and
218
   the hardware cursor:
219
 
220
      - if you want to start display DMA too early, you loose the ability to
221
        do smooth horizontal panning (xpanstep 1 -> 64).
222
      - if you want to go even further, you loose the hardware cursor too.
223
 
224
   IMHO a hardware cursor is more important for X than horizontal scrolling,
225
   so that's my motivation.
226
 
227
 
228
   Implementation
229
   --------------
230
 
231
   aga_decode_var() converts the frame buffer values to the Amiga values. It's
232
   just a `straightforward' implementation of the above rules.
233
 
234
 
235
   Standard VGA timings
236
   --------------------
237
 
238
               xres  yres    left  right  upper  lower    hsync    vsync
239
               ----  ----    ----  -----  -----  -----    -----    -----
240
      80x25     720   400      27     45     35     12      108        2
241
      80x30     720   480      27     45     30      9      108        2
242
 
243
   These were taken from a XFree86 configuration file, recalculated for a 28 MHz
244
   dotclock (Amigas don't have a 25 MHz dotclock) and converted to frame buffer
245
   generic timings.
246
 
247
   As a comparison, graphics/monitor.h suggests the following:
248
 
249
               xres  yres    left  right  upper  lower    hsync    vsync
250
               ----  ----    ----  -----  -----  -----    -----    -----
251
 
252
      VGA       640   480      52    112     24     19    112 -      2 +
253
      VGA70     640   400      52    112     27     21    112 -      2 -
254
 
255
 
256
   Sync polarities
257
   ---------------
258
 
259
      VSYNC    HSYNC    Vertical size    Vertical total
260
      -----    -----    -------------    --------------
261
        +        +           Reserved          Reserved
262
        +        -                400               414
263
        -        +                350               362
264
        -        -                480               496
265
 
266
   Source: CL-GD542X Technical Reference Manual, Cirrus Logic, Oct 1992
267
 
268
 
269
   Broadcast video timings
270
   -----------------------
271
 
272
   Since broadcast video timings are `fixed' and only depend on the video
273
   system (PAL/NTSC), hsync_len and vsync_len are not used and must be set to
274
   zero. All xres/yres and margin values are defined within the `visible
275
   rectangle' of the display.
276
 
277
   According to the CCIR and RETMA specifications, we have the following values:
278
 
279
   CCIR -> PAL
280
   -----------
281
 
282
      - a scanline is 64 µs long, of which 52.48 µs are visible. This is about
283
        736 visible 70 ns pixels per line.
284
      - we have 625 scanlines, of which 575 are visible (interlaced); after
285
        rounding this becomes 576.
286
 
287
   RETMA -> NTSC
288
   -------------
289
 
290
      - a scanline is 63.5 µs long, of which 53.5 µs are visible.  This is about
291
        736 visible 70 ns pixels per line.
292
      - we have 525 scanlines, of which 485 are visible (interlaced); after
293
        rounding this becomes 484.
294
 
295
   Thus if you want a PAL compatible display, you have to do the following:
296
 
297
      - set the FB_SYNC_BROADCAST flag to indicate that standard broadcast
298
        timings are to be used.
299
      - make sure upper_margin+yres+lower_margin = 576 for an interlaced, 288
300
        for a non-interlaced and 144 for a doublescanned display.
301
      - make sure (left_margin+xres+right_margin)*pixclock is a reasonable
302
        approximation to 52.48 µs.
303
 
304
   The settings for a NTSC compatible display are straightforward.
305
 
306
   Note that in a strict sense the PAL and NTSC standards only define the
307
   encoding of the color part (chrominance) of the video signal and don't say
308
   anything about horizontal/vertical synchronization nor refresh rates.
309
   But since Amigas have RGB output, this issue isn't of any importance here.
310
 
311
 
312
                                                            -- Geert --
313
 
314
*******************************************************************************/
315
 
316
 
317
   /*
318
    *    Custom Chipset Definitions
319
    */
320
 
321
#define CUSTOM_OFS(fld) ((long)&((struct CUSTOM*)0)->fld)
322
 
323
 
324
   /*
325
    *    BPLCON0 -- Bitplane Control Register 0
326
    */
327
 
328
#define BPC0_HIRES      (0x8000)
329
#define BPC0_BPU2       (0x4000) /* Bit plane used count */
330
#define BPC0_BPU1       (0x2000)
331
#define BPC0_BPU0       (0x1000)
332
#define BPC0_HAM        (0x0800) /* HAM mode */
333
#define BPC0_DPF        (0x0400) /* Double playfield */
334
#define BPC0_COLOR      (0x0200) /* Enable colorburst */
335
#define BPC0_GAUD       (0x0100) /* Genlock audio enable */
336
#define BPC0_UHRES      (0x0080) /* Ultrahi res enable */
337
#define BPC0_SHRES      (0x0040) /* Super hi res mode */
338
#define BPC0_BYPASS     (0x0020) /* Bypass LUT - AGA */
339
#define BPC0_BPU3       (0x0010) /* AGA */
340
#define BPC0_LPEN       (0x0008) /* Light pen enable */
341
#define BPC0_LACE       (0x0004) /* Interlace */
342
#define BPC0_ERSY       (0x0002) /* External resync */
343
#define BPC0_ECSENA     (0x0001) /* ECS emulation disable */
344
 
345
 
346
   /*
347
    *    BPLCON2 -- Bitplane Control Register 2
348
    */
349
 
350
#define BPC2_ZDBPSEL2   (0x4000) /* Bitplane to be used for ZD - AGA */
351
#define BPC2_ZDBPSEL1   (0x2000)
352
#define BPC2_ZDBPSEL0   (0x1000)
353
#define BPC2_ZDBPEN     (0x0800) /* Enable ZD with ZDBPSELx - AGA */
354
#define BPC2_ZDCTEN     (0x0400) /* Enable ZD with palette bit #31 - AGA */
355
#define BPC2_KILLEHB    (0x0200) /* Kill EHB mode - AGA */
356
#define BPC2_RDRAM      (0x0100) /* Color table accesses read, not write - AGA */
357
#define BPC2_SOGEN      (0x0080) /* SOG output pin high - AGA */
358
#define BPC2_PF2PRI     (0x0040) /* PF2 priority over PF1 */
359
#define BPC2_PF2P2      (0x0020) /* PF2 priority wrt sprites */
360
#define BPC2_PF2P1      (0x0010)
361
#define BPC2_PF2P0      (0x0008)
362
#define BPC2_PF1P2      (0x0004) /* ditto PF1 */
363
#define BPC2_PF1P1      (0x0002)
364
#define BPC2_PF1P0      (0x0001)
365
 
366
 
367
   /*
368
    *    BPLCON3 -- Bitplane Control Register 3 (AGA)
369
    */
370
 
371
#define BPC3_BANK2      (0x8000) /* Bits to select color register bank */
372
#define BPC3_BANK1      (0x4000)
373
#define BPC3_BANK0      (0x2000)
374
#define BPC3_PF2OF2     (0x1000) /* Bits for color table offset when PF2 */
375
#define BPC3_PF2OF1     (0x0800)
376
#define BPC3_PF2OF0     (0x0400)
377
#define BPC3_LOCT       (0x0200) /* Color register writes go to low bits */
378
#define BPC3_SPRES1     (0x0080) /* Sprite resolution bits */
379
#define BPC3_SPRES0     (0x0040)
380
#define BPC3_BRDRBLNK   (0x0020) /* Border blanked? */
381
#define BPC3_BRDRTRAN   (0x0010) /* Border transparent? */
382
#define BPC3_ZDCLKEN    (0x0004) /* ZD pin is 14 MHz (HIRES) clock output */
383
#define BPC3_BRDRSPRT   (0x0002) /* Sprites in border? */
384
#define BPC3_EXTBLKEN   (0x0001) /* BLANK programmable */
385
 
386
 
387
   /*
388
    *    BPLCON4 -- Bitplane Control Register 4 (AGA)
389
    */
390
 
391
#define BPC4_BPLAM7     (0x8000) /* bitplane color XOR field */
392
#define BPC4_BPLAM6     (0x4000)
393
#define BPC4_BPLAM5     (0x2000)
394
#define BPC4_BPLAM4     (0x1000)
395
#define BPC4_BPLAM3     (0x0800)
396
#define BPC4_BPLAM2     (0x0400)
397
#define BPC4_BPLAM1     (0x0200)
398
#define BPC4_BPLAM0     (0x0100)
399
#define BPC4_ESPRM7     (0x0080) /* 4 high bits for even sprite colors */
400
#define BPC4_ESPRM6     (0x0040)
401
#define BPC4_ESPRM5     (0x0020)
402
#define BPC4_ESPRM4     (0x0010)
403
#define BPC4_OSPRM7     (0x0008) /* 4 high bits for odd sprite colors */
404
#define BPC4_OSPRM6     (0x0004)
405
#define BPC4_OSPRM5     (0x0002)
406
#define BPC4_OSPRM4     (0x0001)
407
 
408
 
409
   /*
410
    *    BEAMCON0 -- Beam Control Register
411
    */
412
 
413
#define BMC0_HARDDIS    (0x4000) /* Disable hardware limits */
414
#define BMC0_LPENDIS    (0x2000) /* Disable light pen latch */
415
#define BMC0_VARVBEN    (0x1000) /* Enable variable vertical blank */
416
#define BMC0_LOLDIS     (0x0800) /* Disable long/short line toggle */
417
#define BMC0_CSCBEN     (0x0400) /* Composite sync/blank */
418
#define BMC0_VARVSYEN   (0x0200) /* Enable variable vertical sync */
419
#define BMC0_VARHSYEN   (0x0100) /* Enable variable horizontal sync */
420
#define BMC0_VARBEAMEN  (0x0080) /* Enable variable beam counters */
421
#define BMC0_DUAL       (0x0080) /* Enable alternate horizontal beam counter */
422
#define BMC0_PAL        (0x0020) /* Set decodes for PAL */
423
#define BMC0_VARCSYEN   (0x0010) /* Enable variable composite sync */
424
#define BMC0_BLANKEN    (0x0008) /* Blank enable (no longer used on AGA) */
425
#define BMC0_CSYTRUE    (0x0004) /* CSY polarity */
426
#define BMC0_VSYTRUE    (0x0002) /* VSY polarity */
427
#define BMC0_HSYTRUE    (0x0001) /* HSY polarity */
428
 
429
 
430
   /*
431
    *    FMODE -- Fetch Mode Control Register (AGA)
432
    */
433
 
434
#define FMODE_SSCAN2    (0x8000) /* Sprite scan-doubling */
435
#define FMODE_BSCAN2    (0x4000) /* Use PF2 modulus every other line */
436
#define FMODE_SPAGEM    (0x0008) /* Sprite page mode */
437
#define FMODE_SPR32     (0x0004) /* Sprite 32 bit fetch */
438
#define FMODE_BPAGEM    (0x0002) /* Bitplane page mode */
439
#define FMODE_BPL32     (0x0001) /* Bitplane 32 bit fetch */
440
 
441
 
442
   /*
443
    *    Tags used to indicate a specific Pixel Clock
444
    *
445
    *    clk_shift is the shift value to get the timings in 35 ns units
446
    */
447
 
448
#define TAG_SHRES       (1)      /* SHRES, clk_shift = TAG_SHRES-1 */
449
#define TAG_HIRES       (2)      /* HIRES, clk_shift = TAG_HIRES-1 */
450
#define TAG_LORES       (3)      /* LORES, clk_shift = TAG_LORES-1 */
451
 
452
 
453
   /*
454
    *    Clock Definitions, Maximum Display Depth
455
    *
456
    *    These depend on the E-Clock or the Chipset, so they are filled in
457
    *    dynamically
458
    */
459
 
460
static u_long pixclock[3];       /* SHRES/HIRES/LORES: index = clk_shift */
461
static u_short maxdepth[3];      /* SHRES/HIRES/LORES: index = clk_shift */
462
 
463
 
464
   /*
465
    *    Broadcast Video Timings
466
    *
467
    *    Horizontal values are in 35 ns (SHRES) units
468
    *    Vertical values are in non-interlaced scanlines
469
    */
470
 
471
#define PAL_WINDOW_H    (1472)   /* PAL Window Limits */
472
#define PAL_WINDOW_V    (288)
473
#define PAL_DIWSTRT_H   (360)
474
#define PAL_DIWSTRT_V   (24)
475
 
476
#define NTSC_WINDOW_H   (1472)   /* NTSC Window Limits */
477
#define NTSC_WINDOW_V   (242)
478
#define NTSC_DIWSTRT_H  (360)
479
#define NTSC_DIWSTRT_V  (20)
480
 
481
#define PAL_HTOTAL      (1816)   /* Total line length */
482
#define NTSC_HTOTAL     (1816)   /* Needed for YWRAP */
483
 
484
 
485
   /*
486
    *    Monitor Specifications
487
    *
488
    *    These are typical for a `generic' Amiga monitor (e.g. A1960)
489
    */
490
 
491
static long vfmin = 50, vfmax = 90, hfmin = 15000, hfmax = 38000;
492
 
493
static u_short pwrsave = 0;      /* VESA suspend mode (not for PAL/NTSC) */
494
 
495
 
496
   /*
497
    *    Various macros
498
    */
499
 
500
#define up8(x)          (((x)+7) & ~7)
501
#define down8(x)        ((x) & ~7)
502
#define div8(x)         ((x)>>3)
503
#define mod8(x)         ((x) & 7)
504
 
505
#define up16(x)         (((x)+15) & ~15)
506
#define down16(x)       ((x) & ~15)
507
#define div16(x)        ((x)>>4)
508
#define mod16(x)        ((x) & 15)
509
 
510
#define up32(x)         (((x)+31) & ~31)
511
#define down32(x)       ((x) & ~31)
512
#define div32(x)        ((x)>>5)
513
#define mod32(x)        ((x) & 31)
514
 
515
#define up64(x)         (((x)+63) & ~63)
516
#define down64(x)       ((x) & ~63)
517
#define div64(x)        ((x)>>6)
518
#define mod64(x)        ((x) & 63)
519
 
520
#define min(a, b)       ((a) < (b) ? (a) : (b))
521
#define max(a, b)       ((a) > (b) ? (a) : (b))
522
 
523
#define highw(x)        ((u_long)(x)>>16 & 0xffff)
524
#define loww(x)         ((u_long)(x) & 0xffff)
525
 
526
#define arraysize(x)    (sizeof(x)/sizeof(*(x)))
527
 
528
 
529
   /*
530
    *    Chip RAM we reserve for the Frame Buffer (must be a multiple of 4K!)
531
    *
532
    *    This defines the Maximum Virtual Screen Size
533
    */
534
 
535
#define VIDEOMEMSIZE_AGA_2M   (1310720)   /* AGA (2MB) : max 1280*1024*256 */
536
#define VIDEOMEMSIZE_AGA_1M    (393216)   /* AGA (1MB) : max 1024*768*256 */
537
#define VIDEOMEMSIZE_ECS_2M    (655360)   /* ECS (2MB) : max 1280*1024*16 */
538
#define VIDEOMEMSIZE_ECS_1M    (393216)   /* ECS (1MB) : max 1024*768*16 */
539
#define VIDEOMEMSIZE_OCS       (262144)   /* OCS       : max ca. 800*600*16 */
540
 
541
 
542
static u_long videomemory;
543
static u_long videomemorysize;
544
 
545
#define assignchunk(name, type, ptr, size) \
546
{ \
547
   (name) = (type)(ptr); \
548
   ptr += size; \
549
}
550
 
551
 
552
   /*
553
    *    Copper Instructions
554
    */
555
 
556
#define CMOVE(val, reg)       (CUSTOM_OFS(reg)<<16 | (val))
557
#define CMOVE2(val, reg)      ((CUSTOM_OFS(reg)+2)<<16 | (val))
558
#define CWAIT(x, y)           (((y) & 0xff)<<24 | ((x) & 0xfe)<<16 | 0x0001fffe)
559
#define CEND                  (0xfffffffe)
560
 
561
 
562
typedef union {
563
   u_long l;
564
   u_short w[2];
565
} copins;
566
 
567
 
568
   /*
569
    *    Frame Header Copper List
570
    */
571
 
572
struct clist_hdr {
573
   copins bplcon0;
574
   copins diwstrt;
575
   copins diwstop;
576
   copins diwhigh;
577
   copins sprfix[8];
578
   copins sprstrtup[16];
579
   copins wait;
580
   copins jump;
581
   copins wait_forever;
582
};
583
 
584
 
585
   /*
586
    *    Long Frame/Short Frame Copper List
587
    */
588
 
589
struct clist_dyn {
590
   copins diwstrt;
591
   copins diwstop;
592
   copins diwhigh;
593
   copins bplcon0;
594
   copins sprpt[2];              /* Sprite 0 */
595
   copins rest[64];
596
};
597
 
598
 
599
static struct clist_hdr *clist_hdr;
600
static struct clist_dyn *clist_lof;
601
static struct clist_dyn *clist_shf;    /* Only used for Interlace */
602
 
603
 
604
   /*
605
    *    Hardware Cursor
606
    */
607
 
608
#define CRSR_RATE       (20)     /* Number of frames/flash toggle */
609
 
610
static u_long *lofsprite, *shfsprite, *dummysprite;
611
static u_short cursormode = FB_CURSOR_FLASH;
612
 
613
 
614
   /*
615
    *    Current Video Mode
616
    */
617
 
618
struct amiga_fb_par {
619
 
620
   /* General Values */
621
 
622
   int xres;                     /* vmode */
623
   int yres;                     /* vmode */
624
   int vxres;                    /* vmode */
625
   int vyres;                    /* vmode */
626
   int xoffset;                  /* vmode */
627
   int yoffset;                  /* vmode */
628
   u_short bpp;                  /* vmode */
629
   u_short clk_shift;            /* vmode */
630
   int vmode;                    /* vmode */
631
   u_short diwstrt_h;            /* vmode */
632
   u_short diwstrt_v;            /* vmode */
633
   u_long next_line;             /* modulo for next line */
634
   u_long next_plane;            /* modulo for next plane */
635
   short crsr_x;                 /* movecursor */
636
   short crsr_y;                 /* movecursor */
637
 
638
   /* OCS Hardware Registers */
639
 
640
   u_long bplpt0;                /* vmode, pan (Note: physical address) */
641
   u_short bplcon0;              /* vmode */
642
   u_short bplcon1;              /* vmode, pan */
643
   u_short bpl1mod;              /* vmode, pan */
644
   u_short bpl2mod;              /* vmode, pan */
645
   u_short diwstrt;              /* vmode */
646
   u_short diwstop;              /* vmode */
647
   u_short ddfstrt;              /* vmode, pan */
648
   u_short ddfstop;              /* vmode, pan */
649
 
650
#if defined(CONFIG_AMIFB_ECS) || defined(CONFIG_AMIFB_AGA)
651
   /* Additional ECS Hardware Registers */
652
 
653
   u_short diwhigh;              /* vmode */
654
   u_short bplcon3;              /* vmode */
655
   u_short beamcon0;             /* vmode */
656
   u_short htotal;               /* vmode */
657
   u_short hsstrt;               /* vmode */
658
   u_short hsstop;               /* vmode */
659
   u_short vtotal;               /* vmode */
660
   u_short vsstrt;               /* vmode */
661
   u_short vsstop;               /* vmode */
662
   u_short hcenter;              /* vmode */
663
#endif /* defined(CONFIG_AMIFB_ECS) || defined(CONFIG_AMIFB_AGA) */
664
 
665
#if defined(CONFIG_AMIFB_AGA)
666
   /* Additional AGA Hardware Registers */
667
 
668
   u_short fmode;                /* vmode */
669
#endif /* defined(CONFIG_AMIFB_AGA) */
670
};
671
 
672
static struct amiga_fb_par current_par;
673
 
674
static int current_par_valid = 0;
675
static int currcon = 0;
676
 
677
static struct display disp[MAX_NR_CONSOLES];
678
static struct fb_info fb_info;
679
 
680
static int node;        /* node of the /dev/fb?current file */
681
 
682
 
683
   /*
684
    *    The minimum period for audio depends on htotal (for OCS/ECS/AGA)
685
    *    (Imported from arch/m68k/amiga/amisound.c)
686
    */
687
 
688
extern volatile u_short amiga_audio_min_period;
689
 
690
 
691
   /*
692
    *    Since we can't read the palette on OCS/ECS, and since reading one
693
    *    single color palette entry requires 5 expensive custom chip bus
694
    *    accesses on AGA, we keep a copy of the current palette.
695
    */
696
 
697
#ifdef CONFIG_AMIFB_AGA
698
static struct { u_char red, green, blue, pad; } palette[256];
699
#else /* CONFIG_AMIFB_AGA */
700
static struct { u_char red, green, blue, pad; } palette[32];
701
#endif /* CONFIG_AMIFB_AGA */
702
 
703
 
704
   /*
705
    *    Latches and Flags for display changes during VBlank
706
    */
707
 
708
static volatile u_short do_vmode = 0;           /* Change the Video Mode */
709
static volatile short do_blank = 0;             /* (Un)Blank the Screen (±1) */
710
static volatile u_short do_movecursor = 0;      /* Move the Cursor */
711
static volatile u_short full_vmode_change = 1;  /* Full Change or Only Pan */
712
static volatile u_short is_blanked = 0;         /* Screen is Blanked */
713
 
714
 
715
   /*
716
    *    Switch for Chipset Independency
717
    */
718
 
719
static struct fb_hwswitch {
720
 
721
   /* Initialization */
722
   int (*init)(void);
723
 
724
   /* Display Control */
725
   int (*encode_fix)(struct fb_fix_screeninfo *fix, struct amiga_fb_par *par);
726
   int (*decode_var)(struct fb_var_screeninfo *var, struct amiga_fb_par *par);
727
   int (*encode_var)(struct fb_var_screeninfo *var, struct amiga_fb_par *par);
728
   int (*getcolreg)(u_int regno, u_int *red, u_int *green, u_int *blue,
729
                    u_int *transp);
730
   int (*setcolreg)(u_int regno, u_int red, u_int green, u_int blue,
731
                    u_int transp);
732
   int (*pan_display)(struct fb_var_screeninfo *var, struct amiga_fb_par *par);
733
 
734
   /* Routines Called by VBlank Interrupt to minimize flicker */
735
   void (*do_vmode)(void);
736
   void (*do_blank)(int blank);
737
   void (*do_movecursor)(void);
738
   void (*do_flashcursor)(void);
739
} *fbhw;
740
 
741
 
742
   /*
743
    *    Frame Buffer Name
744
    *
745
    *    The rest of the name is filled in by amiga_fb_init
746
    */
747
 
748
static char amiga_fb_name[16] = "Amiga ";
749
 
750
 
751
   /*
752
    *    Predefined Video Mode Names
753
    *
754
    *    The a2024-?? modes don't work yet because there's no A2024 driver.
755
    */
756
 
757
static char *amiga_fb_modenames[] = {
758
 
759
   /*
760
    *    Autodetect (Default) Video Mode
761
    */
762
 
763
   "default",
764
 
765
   /*
766
    *    AmigaOS Video Modes
767
    */
768
 
769
   "ntsc",              /* 640x200, 15 kHz, 60 Hz (NTSC) */
770
   "ntsc-lace",         /* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */
771
   "pal",               /* 640x256, 15 kHz, 50 Hz (PAL) */
772
   "pal-lace",          /* 640x512, 15 kHz, 50 Hz interlaced (PAL) */
773
   "multiscan",         /* 640x480, 29 kHz, 57 Hz */
774
   "multiscan-lace",    /* 640x960, 29 kHz, 57 Hz interlaced */
775
   "a2024-10",          /* 1024x800, 10 Hz (Not yet supported) */
776
   "a2024-15",          /* 1024x800, 15 Hz (Not yet supported) */
777
   "euro36",            /* 640x200, 15 kHz, 72 Hz */
778
   "euro36-lace",       /* 640x400, 15 kHz, 72 Hz interlaced */
779
   "euro72",            /* 640x400, 29 kHz, 68 Hz */
780
   "euro72-lace",       /* 640x800, 29 kHz, 68 Hz interlaced */
781
   "super72",           /* 800x300, 23 kHz, 70 Hz */
782
   "super72-lace",      /* 800x600, 23 kHz, 70 Hz interlaced */
783
   "dblntsc",           /* 640x200, 27 kHz, 57 Hz doublescan */
784
   "dblntsc-ff",        /* 640x400, 27 kHz, 57 Hz */
785
   "dblntsc-lace",      /* 640x800, 27 kHz, 57 Hz interlaced */
786
   "dblpal",            /* 640x256, 27 kHz, 47 Hz doublescan */
787
   "dblpal-ff",         /* 640x512, 27 kHz, 47 Hz */
788
   "dblpal-lace",       /* 640x1024, 27 kHz, 47 Hz interlaced */
789
 
790
   /*
791
    *    VGA Video Modes
792
    */
793
 
794
   "vga",               /* 640x480, 31 kHz, 60 Hz (VGA) */
795
   "vga70",             /* 640x400, 31 kHz, 70 Hz (VGA) */
796
 
797
   /*
798
    *    User Defined Video Modes: to be set after boot up using e.g. fbset
799
    */
800
 
801
   "user0", "user1", "user2", "user3", "user4", "user5", "user6", "user7"
802
};
803
 
804
 
805
   /*
806
    *    Predefined Video Mode Definitions
807
    *
808
    *    Since the actual pixclock values depend on the E-Clock, we use the
809
    *    TAG_* values and fill in the real values during initialization.
810
    *    Thus we assume no one has pixel clocks of 333, 500 or 1000 GHz :-)
811
    */
812
 
813
static struct fb_var_screeninfo amiga_fb_predefined[] = {
814
 
815
   /*
816
    *    Autodetect (Default) Video Mode
817
    */
818
 
819
   { 0, },
820
 
821
   /*
822
    *    AmigaOS Video Modes
823
    */
824
 
825
   {
826
      /* ntsc */
827
      640, 200, 640, 200, 0, 0, 4, 0,
828
      {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
829
      0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 78, 18, 24, 18, 0, 0,
830
      FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
831
   }, {
832
      /* ntsc-lace */
833
      640, 400, 640, 400, 0, 0, 4, 0,
834
      {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
835
      0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 78, 18, 48, 36, 0, 0,
836
      FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
837
   }, {
838
      /* pal */
839
      640, 256, 640, 256, 0, 0, 4, 0,
840
      {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
841
      0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 78, 18, 20, 12, 0, 0,
842
      FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
843
   }, {
844
      /* pal-lace */
845
      640, 512, 640, 512, 0, 0, 4, 0,
846
      {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
847
      0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 78, 18, 40, 24, 0, 0,
848
      FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
849
   }, {
850
      /* multiscan */
851
      640, 480, 640, 480, 0, 0, 4, 0,
852
      {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
853
      0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 164, 92, 9, 9, 80, 8,
854
      0, FB_VMODE_NONINTERLACED
855
   }, {
856
      /* multiscan-lace */
857
      640, 960, 640, 960, 0, 0, 4, 0,
858
      {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
859
      0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 164, 92, 18, 18, 80, 16,
860
      0, FB_VMODE_INTERLACED
861
   }, {
862
      /* a2024-10 (Not yet supported) */
863
      1024, 800, 1024, 800, 0, 0, 2, 0,
864
      {0, 2, 0}, {0, 2, 0}, {0, 2, 0}, {0, 0, 0},
865
      0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 0, 0, 0, 0, 0, 0,
866
      0, FB_VMODE_NONINTERLACED
867
   }, {
868
      /* a2024-15 (Not yet supported) */
869
      1024, 800, 1024, 800, 0, 0, 2, 0,
870
      {0, 2, 0}, {0, 2, 0}, {0, 2, 0}, {0, 0, 0},
871
      0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 0, 0, 0, 0, 0, 0,
872
      0, FB_VMODE_NONINTERLACED
873
   }, {
874
      /* euro36 */
875
      640, 200, 640, 200, 0, 0, 4, 0,
876
      {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
877
      0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 92, 124, 6, 6, 52, 5,
878
      0, FB_VMODE_NONINTERLACED
879
   }, {
880
      /* euro36-lace */
881
      640, 400, 640, 400, 0, 0, 4, 0,
882
      {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
883
      0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 92, 124, 12, 12, 52, 10,
884
      0, FB_VMODE_INTERLACED
885
   }, {
886
      /* euro72 */
887
      640, 400, 640, 400, 0, 0, 4, 0,
888
      {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
889
      0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 164, 92, 9, 9, 80, 8,
890
      0, FB_VMODE_NONINTERLACED
891
   }, {
892
      /* euro72-lace */
893
      640, 800, 640, 800, 0, 0, 4, 0,
894
      {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
895
      0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 164, 92, 18, 18, 80, 16,
896
      0, FB_VMODE_INTERLACED
897
   }, {
898
      /* super72 */
899
      800, 300, 800, 300, 0, 0, 4, 0,
900
      {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
901
      0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 212, 140, 10, 11, 80, 7,
902
      0, FB_VMODE_NONINTERLACED
903
   }, {
904
      /* super72-lace */
905
      800, 600, 800, 600, 0, 0, 4, 0,
906
      {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
907
      0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 212, 140, 20, 22, 80, 14,
908
      0, FB_VMODE_INTERLACED
909
   }, {
910
      /* dblntsc */
911
      640, 200, 640, 200, 0, 0, 4, 0,
912
      {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
913
      0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 196, 124, 18, 17, 80, 4,
914
      0, FB_VMODE_DOUBLE
915
   }, {
916
      /* dblntsc-ff */
917
      640, 400, 640, 400, 0, 0, 4, 0,
918
      {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
919
      0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 196, 124, 36, 35, 80, 7,
920
      0, FB_VMODE_NONINTERLACED
921
   }, {
922
      /* dblntsc-lace */
923
      640, 800, 640, 800, 0, 0, 4, 0,
924
      {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
925
      0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 196, 124, 72, 70, 80, 14,
926
      0, FB_VMODE_INTERLACED
927
   }, {
928
      /* dblpal */
929
      640, 256, 640, 256, 0, 0, 4, 0,
930
      {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
931
      0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 196, 124, 14, 13, 80, 4,
932
      0, FB_VMODE_DOUBLE
933
   }, {
934
      /* dblpal-ff */
935
      640, 512, 640, 512, 0, 0, 4, 0,
936
      {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
937
      0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 196, 124, 28, 27, 80, 7,
938
      0, FB_VMODE_NONINTERLACED
939
   }, {
940
      /* dblpal-lace */
941
      640, 1024, 640, 1024, 0, 0, 4, 0,
942
      {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
943
      0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 196, 124, 56, 54, 80, 14,
944
      0, FB_VMODE_INTERLACED
945
   },
946
 
947
   /*
948
    *    VGA Video Modes
949
    */
950
 
951
   {
952
      /* vga */
953
      640, 480, 640, 480, 0, 0, 4, 0,
954
      {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
955
      0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 64, 96, 30, 9, 112, 2,
956
      0, FB_VMODE_NONINTERLACED
957
   }, {
958
      /* vga70 */
959
      640, 400, 640, 400, 0, 0, 4, 0,
960
      {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
961
      0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 64, 96, 35, 12, 112, 2,
962
      FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED
963
   },
964
 
965
   /*
966
    *    User Defined Video Modes
967
    */
968
 
969
   { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }
970
};
971
 
972
 
973
#define NUM_USER_MODES     (8)
974
#define NUM_TOTAL_MODES    arraysize(amiga_fb_predefined)
975
#define NUM_PREDEF_MODES   (NUM_TOTAL_MODES-NUM_USER_MODES)
976
 
977
 
978
static int amifb_ilbm = 0;       /* interleaved or normal bitplanes */
979
 
980
static int amifb_inverse = 0;
981
static int amifb_mode = 0;
982
 
983
 
984
   /*
985
    *    Support for Graphics Boards
986
    */
987
 
988
#ifdef CONFIG_FB_CYBER        /* Cybervision */
989
extern int Cyber_probe(void);
990
extern void Cyber_video_setup(char *options, int *ints);
991
extern struct fb_info *Cyber_fb_init(long *mem_start);
992
 
993
static int amifb_Cyber = 0;
994
#endif /* CONFIG_FB_CYBER */
995
 
996
 
997
   /*
998
    *    Some default modes
999
    */
1000
 
1001
#define DEFMODE_PAL        "pal"       /* for PAL OCS/ECS */
1002
#define DEFMODE_NTSC       "ntsc"      /* for NTSC OCS/ECS */
1003
#define DEFMODE_AMBER_PAL  "pal-lace"  /* for flicker fixed PAL (A3000) */
1004
#define DEFMODE_AMBER_NTSC "ntsc-lace" /* for flicker fixed NTSC (A3000) */
1005
#define DEFMODE_AGA        "vga70"     /* for AGA */
1006
 
1007
 
1008
   /*
1009
    *    Interface used by the world
1010
    */
1011
 
1012
void amiga_video_setup(char *options, int *ints);
1013
 
1014
static int amiga_fb_get_fix(struct fb_fix_screeninfo *fix, int con);
1015
static int amiga_fb_get_var(struct fb_var_screeninfo *var, int con);
1016
static int amiga_fb_set_var(struct fb_var_screeninfo *var, int con);
1017
static int amiga_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con);
1018
static int amiga_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con);
1019
static int amiga_fb_pan_display(struct fb_var_screeninfo *var, int con);
1020
 
1021
static int amiga_fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
1022
                          u_long arg, int con);
1023
 
1024
static int amiga_fb_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix, int con);
1025
static int amiga_fb_get_var_cursorinfo(struct fb_var_cursorinfo *var, int con);
1026
static int amiga_fb_set_var_cursorinfo(struct fb_var_cursorinfo *var, int con);
1027
static int amiga_fb_get_cursorstate(struct fb_cursorstate *state, int con);
1028
static int amiga_fb_set_cursorstate(struct fb_cursorstate *state, int con);
1029
 
1030
 
1031
   /*
1032
    *    Interface to the low level console driver
1033
    */
1034
 
1035
struct fb_info *amiga_fb_init(long *mem_start);
1036
static int amifb_switch(int con);
1037
static int amifb_updatevar(int con);
1038
static void amifb_blank(int blank);
1039
 
1040
 
1041
   /*
1042
    *    Support for OCS
1043
    */
1044
 
1045
#ifdef CONFIG_AMIFB_OCS
1046
#error "OCS support: not yet implemented"
1047
#endif /* CONFIG_AMIFB_OCS */
1048
 
1049
 
1050
   /*
1051
    *    Support for ECS
1052
    */
1053
 
1054
#ifdef CONFIG_AMIFB_ECS
1055
#error "ECS support: not yet implemented"
1056
#endif /* CONFIG_AMIFB_ECS */
1057
 
1058
 
1059
   /*
1060
    *    Support for AGA
1061
    */
1062
 
1063
#ifdef CONFIG_AMIFB_AGA
1064
static int aga_init(void);
1065
static int aga_encode_fix(struct fb_fix_screeninfo *fix,
1066
                          struct amiga_fb_par *par);
1067
static int aga_decode_var(struct fb_var_screeninfo *var,
1068
                          struct amiga_fb_par *par);
1069
static int aga_encode_var(struct fb_var_screeninfo *var,
1070
                          struct amiga_fb_par *par);
1071
static int aga_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
1072
                         u_int *transp);
1073
static int aga_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
1074
                         u_int transp);
1075
static int aga_pan_display(struct fb_var_screeninfo *var,
1076
                           struct amiga_fb_par *par);
1077
static void aga_do_vmode(void);
1078
static void aga_do_blank(int blank);
1079
static void aga_do_movecursor(void);
1080
static void aga_do_flashcursor(void);
1081
 
1082
static int aga_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix, int con);
1083
static int aga_get_var_cursorinfo(struct fb_var_cursorinfo *var, int con);
1084
static int aga_set_var_cursorinfo(struct fb_var_cursorinfo *var, int con);
1085
static int aga_get_cursorstate(struct fb_cursorstate *state, int con);
1086
static int aga_set_cursorstate(struct fb_cursorstate *state, int con);
1087
 
1088
static __inline__ void aga_build_clist_hdr(struct clist_hdr *cop);
1089
static __inline__ void aga_update_clist_hdr(struct clist_hdr *cop,
1090
                                            struct amiga_fb_par *par);
1091
static void aga_build_clist_dyn(struct clist_dyn *cop,
1092
                                struct clist_dyn *othercop, u_short shf,
1093
                                struct amiga_fb_par *par);
1094
#endif /* CONFIG_AMIFB_AGA */
1095
 
1096
 
1097
   /*
1098
    *    Internal routines
1099
    */
1100
 
1101
static u_long chipalloc(u_long size);
1102
static void amiga_fb_get_par(struct amiga_fb_par *par);
1103
static void amiga_fb_set_par(struct amiga_fb_par *par);
1104
static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
1105
static struct fb_cmap *get_default_colormap(int bpp);
1106
static int do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
1107
                          int kspc);
1108
static int do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
1109
                          int kspc);
1110
static void do_install_cmap(int con);
1111
static void memcpy_fs(int fsfromto, void *to, void *from, int len);
1112
static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto);
1113
static int alloc_cmap(struct fb_cmap *cmap, int len, int transp);
1114
static void amiga_fb_set_disp(int con);
1115
static void amifb_interrupt(int irq, struct pt_regs *fp, void *dummy);
1116
static char * strtoke(char * s,const char * ct);
1117
static int get_video_mode(const char *name);
1118
static void check_default_mode(void);
1119
 
1120
 
1121
#ifdef USE_MONO_AMIFB_IF_NON_AGA
1122
 
1123
/******************************************************************************
1124
*
1125
* This is the old monochrome frame buffer device. It's invoked if we're running
1126
* on a non-AGA machine, until the color support for OCS/ECS is finished.
1127
*
1128
******************************************************************************/
1129
 
1130
/*
1131
 * atari/atafb.c -- Low level implementation of Atari frame buffer device
1132
 * amiga/amifb.c -- Low level implementation of Amiga frame buffer device
1133
 *
1134
 *  Copyright (C) 1994 Martin Schaller & Roman Hodek & Geert Uytterhoeven
1135
 *
1136
 * This file is subject to the terms and conditions of the GNU General Public
1137
 * License.  See the file COPYING in the main directory of this archive
1138
 * for more details.
1139
 *
1140
 * History:
1141
 *   - 03 Jan 95: Original version my Martin Schaller: The TT driver and
1142
 *                all the device independent stuff
1143
 *   - 09 Jan 95: Roman: I've added the hardware abstraction (hw_switch)
1144
 *                and wrote the Falcon, ST(E), and External drivers
1145
 *                based on the original TT driver.
1146
 *   - 26 Jan 95: Geert: Amiga version
1147
 *   - 19 Feb 95: Hamish: added Jes Sorensen's ECS patches to the Amiga
1148
 *                frame buffer device.  This provides ECS support and the
1149
 *                following screen-modes: multiscan, multiscan-lace,
1150
 *                super72, super72-lace, dblntsc, dblpal & euro72.
1151
 *                He suggests that we remove the old AGA screenmodes,
1152
 *                as they are non-standard, and some of them doesn't work
1153
 *                under ECS.
1154
 */
1155
 
1156
static struct mono_mono_amiga_fb_par {
1157
        u_long smem_start;
1158
        u_long smem_len;
1159
        struct geometry *geometry;
1160
        ushort scr_max_height;                  /* screen dimensions */
1161
        ushort scr_max_width;
1162
        ushort scr_height;
1163
        ushort scr_width;
1164
        ushort scr_depth;
1165
        int bytes_per_row;                      /* offset to one line below */
1166
        ulong fgcol;
1167
        ulong bgcol;
1168
        ulong crsrcol;
1169
        ushort scroll_latch;                    /* Vblank support for hardware scroll */
1170
        ushort y_wrap;
1171
        ushort cursor_latch;                    /* Hardware cursor */
1172
        ushort *cursor, *dummy;
1173
        ushort cursor_flash;
1174
        ushort cursor_visible;
1175
        ushort diwstrt_v, diwstrt_h;            /* display window control */
1176
        ushort diwstop_v, diwstop_h;
1177
        ushort bplcon0;                         /* display mode */
1178
        ushort htotal;
1179
        u_char *bitplane[8];                    /* pointers to display bitplanes */
1180
        ulong plane_size;
1181
        ushort *coplist1hdr;                    /* List 1 static  component */
1182
        ushort *coplist1dyn;                    /* List 1 dynamic component */
1183
        ushort *coplist2hdr;                    /* List 2 static  component */
1184
        ushort *coplist2dyn;                    /* List 2 dynamic component */
1185
} mono_current_par;
1186
 
1187
 
1188
static ushort mono_cursor_data[] =
1189
{
1190
    0x2c81,0x2d00,
1191
    0xf000,0x0000,
1192
    0x0000,0x0000
1193
};
1194
 
1195
 
1196
/*
1197
 *  Color definitions
1198
 */
1199
 
1200
#define FG_COLOR                (0x000000)      /* black */
1201
#define BG_COLOR                (0xaaaaaa)      /* lt. grey */
1202
#define CRSR_COLOR              (0xff0000)      /* bright red */
1203
 
1204
#define FG_COLOR_INV            BG_COLOR
1205
#define BG_COLOR_INV            FG_COLOR
1206
#define CRSR_COLOR_INV          (0x6677aa)      /* a blue-ish color */
1207
 
1208
/*
1209
 *  Split 24-bit RGB colors in 12-bit MSB (for OCS/ECS/AGA) and LSB (for AGA)
1210
 */
1211
 
1212
#define COLOR_MSB(rgb)  (((rgb>>12)&0xf00)|((rgb>>8)&0x0f0)|((rgb>>4)&0x00f))
1213
#define COLOR_LSB(rgb)  (((rgb>>8) &0xf00)|((rgb>>4)&0x0f0)|((rgb)   &0x00f))
1214
 
1215
/* Cursor definitions */
1216
 
1217
#define CRSR_FLASH              1       /* Cursor flashing on(1)/off(0) */
1218
#define CRSR_BLOCK              1       /* Block(1) or line(0) cursor */
1219
 
1220
 
1221
/* controlling screen blanking (read in VBL handler) */
1222
static int mono_do_blank;
1223
static int mono_do_unblank;
1224
static unsigned short mono_save_bplcon3;
1225
 
1226
/*
1227
 * mono_ecs_color_zero is used to keep custom.color[0] for the special ECS color-
1228
 * table, as custom.color[0] is cleared at vblank interrupts.
1229
 * -Jes (jds@kom.auc.dk)
1230
 */
1231
 
1232
static ushort mono_ecs_color_zero;
1233
 
1234
static struct {
1235
        int right_count;
1236
        int done;
1237
} mono_vblank;
1238
 
1239
 
1240
static __inline__ void mono_init_vblank(void)
1241
{
1242
        mono_vblank.right_count = 0;
1243
        mono_vblank.done = 0;
1244
}
1245
 
1246
/* Geometry structure contains all useful information about given mode.
1247
 *
1248
 * Strictly speaking `scr_max_height' and `scr_max_width' is redundant
1249
 * information with DIWSTRT value provided. Might be useful if modes
1250
 * can be hotwired by user in future. It fits for the moment.
1251
 *
1252
 * At the moment, the code only distinguishes between OCS and AGA. ECS
1253
 * lies somewhere in between - someone more familiar with it could make
1254
 * appropriate modifications so that some advanced display modes are
1255
 * available, without confusing the poor chipset. OCS modes use only the
1256
 * bplcon0, diwstrt, diwstop, ddfstrt, ddfstop registers (a few others could
1257
 * be used as well). -wjr
1258
 *
1259
 * The code now supports ECS as well, except for FMODE all control registers
1260
 * are the same under ECS. A special color-table has to be generated though.
1261
 * -Jes
1262
 */
1263
struct geometry {
1264
    char *modename;     /* Name this thing */
1265
    char isOCS;         /* Is it OCS or ECS/AGA */
1266
    ushort bplcon0;     /* Values for bit plane control register 0 */
1267
    ushort scr_width;
1268
    ushort scr_height;
1269
    ushort scr_depth;
1270
    ushort scr_max_width;     /* Historical, might be useful still */
1271
    ushort scr_max_height;
1272
    ushort diwstrt_h;   /* Where the display window starts */
1273
    ushort diwstrt_v;
1274
    ushort alignment;   /* Pixels per scanline must be a multiple of this */
1275
    /* OCS doesn't need anything past here */
1276
    ushort bplcon2;
1277
    ushort bplcon3;
1278
    /* The rest of these control variable sync */
1279
    ushort htotal;      /* Total hclocks */
1280
    ushort hsstrt;      /* HSYNC start and stop */
1281
    ushort hsstop;
1282
    ushort hbstrt;      /* HBLANK start and stop */
1283
    ushort hbstop;
1284
    ushort vtotal;      /* Total vlines */
1285
    ushort vsstrt;      /* VSYNC, VBLANK ditto */
1286
    ushort vsstop;
1287
    ushort vbstrt;
1288
    ushort vbstop;
1289
    ushort hcenter;     /* Center of line, for interlaced modes */
1290
    ushort beamcon0;    /* Beam control */
1291
    ushort fmode;       /* Memory fetch mode */
1292
};
1293
 
1294
#define MAX_COP_LIST_ENTS 64
1295
#define COP_MEM_REQ       (MAX_COP_LIST_ENTS*4*2)
1296
#define SPR_MEM_REQ       (24)
1297
 
1298
 
1299
static struct geometry mono_modes[] = {
1300
        /* NTSC modes: !!! can't guarantee anything about overscan modes !!! */
1301
        {
1302
                "ntsc-lace", 1,
1303
                BPC0_HIRES | BPC0_LACE,
1304
                640, 400, 1,
1305
                704, 480,
1306
                0x71, 0x18,             /* diwstrt h,v */
1307
                16                      /* WORD aligned */
1308
        }, {
1309
                "ntsc", 1,
1310
                BPC0_HIRES,
1311
                640, 200, 1,
1312
                704, 240,
1313
                0x71, 0x18,
1314
                16                      /* WORD aligned */
1315
        }, {
1316
                "ntsc-lace-over", 1,
1317
                BPC0_HIRES | BPC0_LACE,
1318
                704, 480, 1,
1319
                704, 480,
1320
                0x71, 0x18,
1321
                16                      /* WORD aligned */
1322
        }, {
1323
                "ntsc-over", 1,
1324
                BPC0_HIRES,
1325
                704, 240, 1,
1326
                704, 240,
1327
                0x71, 0x18,
1328
                16                      /* WORD aligned */
1329
        },
1330
        /* PAL modes. Warning:
1331
         *
1332
         * PAL overscan causes problems on my machine because maximum diwstop_h
1333
         * value seems to be ~0x1c2, rather than 0x1e0+ inferred by RKM 1.1
1334
         * and 0x1d5 inferred by original `amicon.c' source. Is this a hardware
1335
         * limitation of OCS/pal or 1084?. Or am I doing something stupid here?
1336
         *
1337
         * Included a couple of overscan modes that DO work on my machine,
1338
         * although not particularly useful.
1339
         */
1340
        {
1341
                "pal-lace", 1,
1342
                BPC0_HIRES | BPC0_LACE,
1343
                640, 512, 1,
1344
                704, 592,
1345
                0x71, 0x18,
1346
                16                      /* WORD aligned */
1347
        }, {
1348
                "pal", 1,
1349
                BPC0_HIRES,
1350
                640, 256, 1,
1351
                704, 296,
1352
                0x71, 0x18,
1353
                16                      /* WORD aligned */
1354
        }, {
1355
                "pal-lace-over", 1,
1356
                BPC0_HIRES | BPC0_LACE,
1357
                704, 592, 1,
1358
                704, 582,
1359
                0x5b, 0x18,
1360
                16                      /* WORD aligned */
1361
        }, {
1362
                "pal-over", 1,
1363
                BPC0_HIRES,
1364
                704, 296, 1,
1365
                704, 296,
1366
                0x5b, 0x18,
1367
                16                      /* WORD aligned */
1368
 
1369
        },
1370
        /* ECS modes, these are real ECS modes */
1371
        {
1372
                "multiscan", 0,
1373
                BPC0_SHRES | BPC0_ECSENA,       /* bplcon0 */
1374
                640, 480, 1,
1375
                640, 480,
1376
                0x0041, 0x002c,                 /* diwstrt h,v */
1377
                64,                             /* 64-bit aligned */
1378
                BPC2_KILLEHB,                   /* bplcon2 */
1379
                BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1380
                        BPC3_BRDRBLNK | BPC3_EXTBLKEN,  /* bplcon3 */
1381
 
1382
                0x0072,                         /* htotal */
1383
                0x000a,                         /* hsstrt */
1384
                0x0013,                         /* hsstop */
1385
                0x0002,                         /* hbstrt */
1386
                0x001c,                         /* hbstop */
1387
                0x020c,                         /* vtotal */
1388
                0x0008,                         /* vsstrt */
1389
                0x0011,                         /* vsstop */
1390
                0x0000,                         /* vbstrt */
1391
                0x001c,                         /* vbstop */
1392
                0x0043,                         /* hcenter */
1393
                BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN |
1394
                        BMC0_VARHSYEN | BMC0_VARBEAMEN | BMC0_BLANKEN,
1395
                                                /* beamcon0 */
1396
                FMODE_BPAGEM | FMODE_BPL32      /* fmode */
1397
        },
1398
        {
1399
                "multiscan-lace", 0,
1400
                BPC0_SHRES | BPC0_LACE | BPC0_ECSENA,   /* bplcon0 */
1401
                640, 960, 1,
1402
                640, 960,
1403
                0x0041, 0x002c,                 /* diwstrt h,v */
1404
                64,                             /* 64-bit aligned */
1405
                BPC2_KILLEHB,                   /* bplcon2 */
1406
                BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1407
                        BPC3_BRDRBLNK | BPC3_EXTBLKEN,  /* bplcon3 */
1408
 
1409
                0x0072,                         /* htotal */
1410
                0x000a,                         /* hsstrt */
1411
                0x0013,                         /* hsstop */
1412
                0x0002,                         /* hbstrt */
1413
                0x001c,                         /* hbstop */
1414
                0x020c,                         /* vtotal */
1415
                0x0008,                         /* vsstrt */
1416
                0x0011,                         /* vsstop */
1417
                0x0000,                         /* vbstrt */
1418
                0x001c,                         /* vbstop */
1419
                0x0043,                         /* hcenter */
1420
                BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN |
1421
                        BMC0_VARHSYEN | BMC0_VARBEAMEN | BMC0_BLANKEN,
1422
                                                /* beamcon0 */
1423
                FMODE_BPAGEM | FMODE_BPL32      /* fmode */
1424
        },
1425
        /* Super 72 - 800x300 72Hz noninterlaced mode. */
1426
        {
1427
                "super72", 0,
1428
                BPC0_SHRES | BPC0_ECSENA,       /* bplcon0 */
1429
                800, 304, 1,                    /* need rows%8 == 0 */
1430
                800, 304,                       /* (cols too) */
1431
                0x0051, 0x0021,                 /* diwstrt h,v */
1432
                64,                             /* 64-bit aligned */
1433
                BPC2_KILLEHB,                   /* bplcon2 */
1434
                BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1435
                        BPC3_BRDRBLNK | BPC3_EXTBLKEN,  /* bplcon3 */
1436
                0x0091,                         /* htotal */
1437
                0x000a,                         /* hsstrt */
1438
                0x0013,                         /* hsstop */
1439
                0x0001,                         /* hbstrt */
1440
                0x001e,                         /* hbstop */
1441
                0x0156,                         /* vtotal */
1442
                0x0009,                         /* vsstrt */
1443
                0x0012,                         /* vsstop */
1444
                0x0000,                         /* vbstrt */
1445
                0x001c,                         /* vbstop */
1446
                0x0052,                         /* hcenter */
1447
                BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN |
1448
                        BMC0_VARHSYEN | BMC0_VARBEAMEN | BMC0_BLANKEN,
1449
                                                /* beamcon0 */
1450
                FMODE_BPAGEM | FMODE_BPL32      /* fmode */
1451
        },
1452
        /* Super 72 lace - 800x600 72Hz interlaced mode. */
1453
        {
1454
                "super72-lace", 0,
1455
                BPC0_SHRES | BPC0_LACE | BPC0_ECSENA,   /* bplcon0 */
1456
                800, 600, 1,                    /* need rows%8 == 0 */
1457
                800, 600,                       /* (cols too) */
1458
                0x0051, 0x0021,                 /* diwstrt h,v */
1459
                64,                             /* 64-bit aligned */
1460
                BPC2_KILLEHB,                   /* bplcon2 */
1461
                BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1462
                        BPC3_BRDRBLNK | BPC3_EXTBLKEN,
1463
                                                /* bplcon3 */
1464
                0x0091,                         /* htotal */
1465
                0x000a,                         /* hsstrt */
1466
                0x0013,                         /* hsstop */
1467
                0x0001,                         /* hbstrt */
1468
                0x001e,                         /* hbstop */
1469
                0x0150,                         /* vtotal */
1470
                0x0009,                         /* vsstrt */
1471
                0x0012,                         /* vsstop */
1472
                0x0000,                         /* vbstrt */
1473
                0x001c,                         /* vbstop */
1474
                0x0052,                         /* hcenter */
1475
                BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN |
1476
                        BMC0_VARHSYEN | BMC0_VARBEAMEN | BMC0_BLANKEN,
1477
                                                /* beamcon0 */
1478
                FMODE_BPAGEM | FMODE_BPL32      /* fmode */
1479
        },
1480
        /* DblNtsc - 640x400 59Hz noninterlaced mode. */
1481
        {
1482
                "dblntsc", 0,
1483
                BPC0_SHRES | BPC0_ECSENA,       /* bplcon0 */
1484
                640, 400, 1,                    /* need rows%8 == 0 */
1485
                640, 400,                       /* (cols too) */
1486
                0x0049, 0x0021,                 /* diwstrt h,v */
1487
                64,                             /* 64-bit aligned */
1488
                BPC2_KILLEHB,                   /* bplcon2 */
1489
                BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1490
                        BPC3_BRDRBLNK | BPC3_EXTBLKEN,
1491
                                                /* bplcon3 */
1492
                0x0079,                         /* htotal */
1493
                0x0007,                         /* hsstrt */
1494
                0x0013,                         /* hsstop */
1495
                0x0001,                         /* hbstrt */
1496
                0x001e,                         /* hbstop */
1497
                0x01ec,                         /* vtotal */
1498
                0x0008,                         /* vsstrt */
1499
                0x0010,                         /* vsstop */
1500
                0x0000,                         /* vbstrt */
1501
                0x0019,                         /* vbstop */
1502
                0x0046,                         /* hcenter */
1503
                BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN |
1504
                        BMC0_VARHSYEN | BMC0_VARBEAMEN | BMC0_BLANKEN,
1505
                                                /* beamcon0 */
1506
                FMODE_BPAGEM | FMODE_BPL32      /* fmode */
1507
        },
1508
        /* DblPal - 640x512 52Hz noninterlaced mode. */
1509
        {
1510
                "dblpal", 0,
1511
                BPC0_SHRES | BPC0_ECSENA,       /* bplcon0 */
1512
                640, 512, 1,                    /* need rows%8 == 0 */
1513
                640, 512,                       /* (cols too) */
1514
                0x0049, 0x0021,                 /* diwstrt h,v */
1515
                64,                             /* 64-bit aligned */
1516
                BPC2_KILLEHB,                   /* bplcon2 */
1517
                BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1518
                        BPC3_BRDRBLNK | BPC3_EXTBLKEN,
1519
                                                /* bplcon3 */
1520
                0x0079,                         /* htotal */
1521
                0x0007,                         /* hsstrt */
1522
                0x0013,                         /* hsstop */
1523
                0x0001,                         /* hbstrt */
1524
                0x001e,                         /* hbstop */
1525
                0x0234,                         /* vtotal */
1526
                0x0008,                         /* vsstrt */
1527
                0x0010,                         /* vsstop */
1528
                0x0000,                         /* vbstrt */
1529
                0x0019,                         /* vbstop */
1530
                0x0046,                         /* hcenter */
1531
                BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN |
1532
                        BMC0_VARHSYEN | BMC0_VARBEAMEN | BMC0_BLANKEN,
1533
                                                /* beamcon0 */
1534
                FMODE_BPAGEM | FMODE_BPL32      /* fmode */
1535
        },
1536
        /* Euro72 - productivity - 640x400 71Hz noninterlaced mode. */
1537
        {
1538
                "euro72", 0,
1539
                BPC0_SHRES | BPC0_ECSENA,       /* bplcon0 */
1540
                640, 400, 1,                    /* need rows%8 == 0 */
1541
                640, 400,                       /* (cols too) */
1542
                0x0041, 0x0021,                 /* diwstrt h,v */
1543
                64,                             /* 64-bit aligned */
1544
                BPC2_KILLEHB,                   /* bplcon2 */
1545
                BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1546
                        BPC3_BRDRBLNK | BPC3_EXTBLKEN,
1547
                                                /* bplcon3 */
1548
                0x0071,                         /* htotal */
1549
                0x0009,                         /* hsstrt */
1550
                0x0013,                         /* hsstop */
1551
                0x0001,                         /* hbstrt */
1552
                0x001e,                         /* hbstop */
1553
                0x01be,                         /* vtotal */
1554
                0x0008,                         /* vsstrt */
1555
                0x0016,                         /* vsstop */
1556
                0x0000,                         /* vbstrt */
1557
                0x001f,                         /* vbstop */
1558
                0x0041,                         /* hcenter */
1559
                BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN |
1560
                        BMC0_VARHSYEN | BMC0_VARBEAMEN | BMC0_BLANKEN,
1561
                                                /* beamcon0 */
1562
                FMODE_BPAGEM | FMODE_BPL32      /* fmode */
1563
        },
1564
        /* AGA modes */
1565
        {
1566
        /*
1567
         * A 640x480, 60Hz noninterlaced AGA mode. It would be nice to be
1568
         * able to have some of these values computed dynamically, but that
1569
         * requires more knowledge of AGA than I have. At the moment,
1570
         * the values make it centered on my 1960 monitor. -wjr
1571
         *
1572
         * For random reasons to do with the way arguments are parsed,
1573
         * these names can't start with a digit.
1574
         *
1575
         * Don't count on being able to reduce scr_width and scr_height
1576
         * and ending up with a smaller but well-formed screen - this
1577
         * doesn't seem to work well at the moment.
1578
         */
1579
                "aga640x480", 0,
1580
                BPC0_SHRES | BPC0_ECSENA,                       /* bplcon0 */
1581
                640, 480, 1,
1582
                640, 480,
1583
                0x0041, 0x002b,                                         /* diwstrt h,v */
1584
                64,                                                                             /* 64-bit aligned */
1585
                BPC2_KILLEHB,                                                   /* bplcon2 */
1586
                BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1587
                BPC3_BRDRBLNK | BPC3_EXTBLKEN,  /* bplcon3 */
1588
                0x0071,                                                                 /* htotal */
1589
                0x000c,                                                                 /* hsstrt */
1590
                0x001c,                                                                 /* hsstop */
1591
                0x0008,                                                                 /* hbstrt */
1592
                0x001e,                                                                 /* hbstop */
1593
                0x020c,                                                                 /* vtotal */
1594
                0x0001,                                                                 /* vsstrt */
1595
                0x0003,                                                                 /* vsstop */
1596
                0x0000,                                                                 /* vbstrt */
1597
                0x000f,                                                                 /* vbstop */
1598
                0x0046,                                                                 /* hcenter */
1599
                BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN |
1600
                        BMC0_VARHSYEN | BMC0_VARBEAMEN | BMC0_BLANKEN,  /* beamcon0 */
1601
                FMODE_BPAGEM | FMODE_BPL32                      /* fmode */
1602
        }, {
1603
                /* An 800x600 72Hz interlaced mode. */
1604
                "aga800x600", 0,
1605
                BPC0_SHRES | BPC0_LACE | BPC0_ECSENA,   /* bplcon0 */
1606
                896, 624, 1,                                                    /* need rows%8 == 0 */
1607
                896, 624,                                                               /* (cols too) */
1608
                0x0041, 0x001e,                                         /* diwstrt h,v */
1609
                64,                                             /* 64-bit aligned */
1610
                BPC2_KILLEHB,                                                   /* bplcon2 */
1611
                BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1612
                BPC3_BRDRBLNK | BPC3_EXTBLKEN,  /* bplcon3 */
1613
                0x0091,                                                                 /* htotal */
1614
                0x000e,                                                                 /* hsstrt */
1615
                0x001d,                                                                 /* hsstop */
1616
                0x000a,                                                                 /* hbstrt */
1617
                0x001e,                                                                 /* hbstop */
1618
                0x0156,                                                                 /* vtotal */
1619
                0x0001,                                                                 /* vsstrt */
1620
                0x0003,                                                                 /* vsstop */
1621
                0x0000,                                                                 /* vbstrt */
1622
                0x000f,                                                                 /* vbstop */
1623
                0x0050,                                                                 /* hcenter */
1624
                BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN |
1625
                BMC0_VARHSYEN | BMC0_VARBEAMEN | BMC0_BLANKEN,  /* beamcon0 */
1626
                FMODE_BPAGEM | FMODE_BPL32                      /* fmode */
1627
        },
1628
        /*
1629
         * Additional AGA modes by Geert Uytterhoeven
1630
         */
1631
        {
1632
                /*
1633
                 * A 720x400, 70 Hz noninterlaced AGA mode (29.27 kHz)
1634
                 */
1635
                "aga720x400", 0,
1636
                BPC0_SHRES | BPC0_ECSENA,                       /* bplcon0 */
1637
                720, 400, 1,
1638
                720, 400,
1639
                0x0041, 0x0013,                                         /* diwstrt h,v */
1640
                64,                                                                             /* 64-bit aligned */
1641
                BPC2_KILLEHB,                                                   /* bplcon2 */
1642
                BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1643
                BPC3_BRDRBLNK | BPC3_EXTBLKEN,  /* bplcon3 */
1644
                0x0079,                                                                 /* htotal */
1645
                0x000e,                                                                 /* hsstrt */
1646
                0x0018,                                                                 /* hsstop */
1647
                0x0001,                                                                 /* hbstrt */
1648
                0x0021,                                                                 /* hbstop */
1649
                0x01a2,                                                                 /* vtotal */
1650
                0x0003,                                                                 /* vsstrt */
1651
                0x0005,                                                                 /* vsstop */
1652
                0x0000,                                                                 /* vbstrt */
1653
                0x0012,                                                                 /* vbstop */
1654
                0x0046,                                                                 /* hcenter */
1655
                BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN | BMC0_VARHSYEN |
1656
                BMC0_VARBEAMEN | BMC0_PAL | BMC0_VARCSYEN | BMC0_CSYTRUE |
1657
                BMC0_VSYTRUE,                                                   /* beamcon0 */
1658
                FMODE_BPAGEM | FMODE_BPL32                      /* fmode */
1659
        }, {
1660
                /*
1661
                 * A 640x400, 76 Hz noninterlaced AGA mode (31.89 kHz)
1662
                 */
1663
                "aga640x400", 0,
1664
                BPC0_SHRES | BPC0_ECSENA,                       /* bplcon0 */
1665
                640, 400, 1,
1666
                640, 400,
1667
                0x0041, 0x0015,                                         /* diwstrt h,v */
1668
                64,                                                                             /* 64-bit aligned */
1669
                BPC2_KILLEHB,                                                   /* bplcon2 */
1670
                BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1671
                BPC3_BRDRBLNK | BPC3_EXTBLKEN,  /* bplcon3 */
1672
                0x006f,                                                                 /* htotal */
1673
                0x000d,                                                                 /* hsstrt */
1674
                0x0018,                                                                 /* hsstop */
1675
                0x0001,                                                                 /* hbstrt */
1676
                0x0021,                                                                 /* hbstop */
1677
                0x01a4,                                                                 /* vtotal */
1678
                0x0003,                                                                 /* vsstrt */
1679
                0x0005,                                                                 /* vsstop */
1680
                0x0000,                                                                 /* vbstrt */
1681
                0x0014,                                                                 /* vbstop */
1682
                0x0046,                                                                 /* hcenter */
1683
                BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN | BMC0_VARHSYEN |
1684
                BMC0_VARBEAMEN | BMC0_PAL | BMC0_VARCSYEN | BMC0_CSYTRUE |
1685
                BMC0_VSYTRUE,                                                   /* beamcon0 */
1686
                FMODE_BPAGEM | FMODE_BPL32                      /* fmode */
1687
        }, {
1688
                /*
1689
                 * A 640x480, 64 Hz noninterlaced AGA mode (31.89 kHz)
1690
                 */
1691
                "aga640x480a", 0,
1692
                BPC0_SHRES | BPC0_ECSENA,                       /* bplcon0 */
1693
                640, 480, 1,
1694
                640, 480,
1695
                0x0041, 0x0015,                                         /* diwstrt h,v */
1696
                64,                                                                             /* 64-bit aligned */
1697
                BPC2_KILLEHB,                                                   /* bplcon2 */
1698
                BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1699
                BPC3_BRDRBLNK | BPC3_EXTBLKEN,  /* bplcon3 */
1700
                0x006f,                                                                 /* htotal */
1701
                0x000e,                                                                 /* hsstrt */
1702
                0x0018,                                                                 /* hsstop */
1703
                0x0001,                                                                 /* hbstrt */
1704
                0x0021,                                                                 /* hbstop */
1705
                0x01f4,                                                                 /* vtotal */
1706
                0x0003,                                                                 /* vsstrt */
1707
                0x0005,                                                                 /* vsstop */
1708
                0x0000,                                                                 /* vbstrt */
1709
                0x0014,                                                                 /* vbstop */
1710
                0x0046,                                                                 /* hcenter */
1711
                BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN | BMC0_VARHSYEN |
1712
                BMC0_VARBEAMEN | BMC0_PAL | BMC0_VARCSYEN | BMC0_CSYTRUE |
1713
                BMC0_VSYTRUE,                                                   /* beamcon0 */
1714
                FMODE_BPAGEM | FMODE_BPL32                      /* fmode */
1715
        }
1716
};
1717
 
1718
#define NMODES  (sizeof(mono_modes) / sizeof(struct geometry))
1719
 
1720
static struct fb_var_screeninfo mono_mono_amiga_fb_predefined[] = {
1721
        { /* autodetect */
1722
                0, 0, 0, 0, 0, 0, 0, 0,                 /* xres-grayscale */
1723
                {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},         /* red green blue tran*/
1724
                0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }
1725
};
1726
 
1727
static int mono_num_mono_amiga_fb_predefined= sizeof(mono_mono_amiga_fb_predefined)/sizeof(struct fb_var_screeninfo);
1728
 
1729
 
1730
 
1731
/* Some default modes */
1732
#define OCS_PAL_LOWEND_DEFMODE  5       /* PAL non-laced for 500/2000 */
1733
#define OCS_PAL_3000_DEFMODE            4       /* PAL laced for 3000 */
1734
#define OCS_NTSC_LOWEND_DEFMODE 1       /* NTSC non-laced for 500/2000 */
1735
#define OCS_NTSC_3000_DEFMODE           0        /* NTSC laced for 3000 */
1736
#define AGA_DEFMODE                                     8       /* 640x480 non-laced for AGA */
1737
 
1738
static int mono_amifb_inverse = 0;
1739
static int mono_amifb_mode = -1;
1740
 
1741
static void mono_video_setup (char *options, int *ints)
1742
{
1743
        char *this_opt;
1744
        int i;
1745
 
1746
        fb_info.fontname[0] = '\0';
1747
 
1748
        if (!options || !*options)
1749
                return;
1750
 
1751
        for (this_opt = strtok(options,","); this_opt; this_opt = strtok(NULL,","))
1752
                if (!strcmp (this_opt, "inverse"))
1753
                        mono_amifb_inverse = 1;
1754
      else if (!strncmp(this_opt, "font:", 5))
1755
               strcpy(fb_info.fontname, this_opt+5);
1756
                else
1757
                        for (i = 0; i < NMODES; i++)
1758
                                if (!strcmp(this_opt, mono_modes[i].modename)) {
1759
                                        mono_amifb_mode = i;
1760
                                        break;
1761
                                }
1762
}
1763
 
1764
/* Notes about copper scrolling:
1765
 *
1766
 * 1. The VBLANK routine dynamically rewrites a LIVE copper list that is
1767
 *    currently being executed. Don't mess with it unless you know the
1768
 *    complications. Fairly sure that double buffered lists doesn't
1769
 *    make our life any easier.
1770
 *
1771
 * 2. The vblank code starts executing at logical line 0. Display must be
1772
 *    set up and ready to run by line DIWSTRT_V, typically 0x2c, minimum
1773
 *    value is 0x18 for maximum overscan.
1774
 *
1775
 *    Tests on my A500/030 for dynamically generating a 37 element copper
1776
 *    list during the VBLANK period under AmigaDos required between
1777
 *    0x10 and 0x14 scanlines. This should be pathological case, and
1778
 *    should do better under Linux/68k. It is however IMPERATIVE that I am
1779
 *    first in the VBLANK isr chain. Try to keep 'buildclist' as fast as
1780
 *    possible. Don't think that it justifies assembler thou'
1781
 *
1782
 * 3. PAL 640x256 display (no overscan) has copper-wait y positions in range
1783
 *    0x02c -> 0x12c. NTSC overscan uses values > 256 too. However counter
1784
 *    is 8 bit, will wrap. RKM 1.1 suggests use of a WAIT(0x00,0xff),
1785
 *    WAIT(x,y-0x100) pair to handle this case. This is WRONG - must use
1786
 *    WAIT(0xe2,0xff) to ensure that wrap occurred by next copper
1787
 *    instruction. Argghh!
1788
 *
1789
 * 4. RKM 1.1 suggests Copper-wait x positions are in range [0,0xe2].
1790
 *    Horizontal blanking occurs in range 0x0f -> 0x35. Black screen
1791
 *    shown in range 0x04 -> 0x47.
1792
 *
1793
 *    Experiments suggest that using WAIT(0x00,y), we can replace up to
1794
 *    7 bitplane pointers before display fetch start. Using a
1795
 *    WAIT(0xe0,y-1) instead, we can replace 8 pointers that should be
1796
 *    all that we need for a full AGA display. Should work because of
1797
 *    fetch latency with bitmapped display.
1798
 *
1799
 *    I think that this works. Someone please tell me if something breaks.
1800
 *
1801
 * Is diwstop_h the right value to use for "close to the end of line"?
1802
 * It seems to work for me, at least for the modes I've defined. -wjr
1803
 *
1804
 * I changed the Wait(diwstop_h, 0xff) for 256-line chunk skipping to
1805
 * Wait(diwstop_h-2, 0xff) to make it work with the additional
1806
 * `get-all-you-can-get-out-of-it' AGA modes. Maybe we should derive the
1807
 * wait position from the HTOTAL value? - G.U.
1808
 *
1809
 * The Wait(diwstop_h-2, 0xff) didn't work in Super72 under ECS, instead
1810
 * I changed it to Wait(htotal-4, 0xff). Dunno whether it works under AGA,
1811
 * and don't ask my why it works. I'm trying to get some facts on this issue
1812
 * from Commodore.
1813
 * -Jes
1814
 */
1815
 
1816
static __inline__ ushort *mono_build_clist_hdr(register struct display *p,
1817
                                                                                                                ushort *cop,
1818
                                                                                                                ushort *othercop)       /* Interlace: List for next frame */
1819
{
1820
        int i;
1821
        ushort diwstrt_v = mono_current_par.diwstrt_v;
1822
        ushort diwstop_h = mono_current_par.diwstop_h;
1823
 
1824
        if (othercop) {
1825
                *cop++ = CUSTOM_OFS(cop1lc);
1826
                *cop++ = (long)othercop >> 16;
1827
                *cop++ = CUSTOM_OFS(cop1lc) + 2;
1828
                *cop++ = (long)othercop;
1829
        }
1830
 
1831
        /* Point Sprite 0 at cursor sprite: */
1832
        *cop++ = CUSTOM_OFS(sprpt[0]);
1833
        *cop++ = (ushort)((long)mono_current_par.cursor >> 16);
1834
        *cop++ = CUSTOM_OFS(sprpt[0]) + 2;
1835
        *cop++ = (ushort)((long)mono_current_par.cursor & 0x0000ffff);
1836
 
1837
        /* Point Sprites 1-7 at dummy sprite: */
1838
        for (i=1; i<8; i++) {
1839
                *cop++ = CUSTOM_OFS(sprpt[i]);
1840
                *cop++ = (ushort)((long)mono_current_par.dummy >> 16);
1841
                *cop++ = CUSTOM_OFS(sprpt[i]) + 2;
1842
                *cop++ = (ushort)((long)mono_current_par.dummy & 0x0000ffff);
1843
        }
1844
 
1845
        /* Halt copper until we have rebuilt the display list */
1846
 
1847
        *cop++ = ((diwstrt_v - 2) << 8) | (diwstop_h >> 1) | 0x1;
1848
        *cop++ = 0xfffe;
1849
 
1850
        return(cop);
1851
}
1852
 
1853
static __inline__ ushort *mono_build_clist_dyn(register struct display *p,
1854
                                                                                                                ushort *cop,
1855
                                                                                                                int shf)                                /* Interlace: Short frame */
1856
{
1857
        ushort diwstrt_v = mono_current_par.diwstrt_v;
1858
        ushort diwstop_h = mono_current_par.diwstop_h;
1859
        ushort y_wrap = mono_current_par.y_wrap;
1860
        ulong offset = y_wrap * mono_current_par.bytes_per_row;
1861
        long scrmem;
1862
        int i;
1863
 
1864
        /* Set up initial bitplane ptrs */
1865
 
1866
        for (i = 0 ; i < mono_current_par.scr_depth ; i++) {
1867
                scrmem    = ((long)mono_current_par.bitplane[i]) + offset;
1868
 
1869
                if (shf)
1870
                        scrmem += mono_current_par.bytes_per_row;
1871
 
1872
                *cop++ = CUSTOM_OFS(bplpt[i]);
1873
                *cop++ = (long)scrmem >> 16;
1874
                *cop++ = CUSTOM_OFS(bplpt[i]) + 2;
1875
                *cop++ = (long)scrmem;
1876
        }
1877
 
1878
        /* If wrapped frame needed - wait for line then switch bitplXs */
1879
 
1880
        if (y_wrap) {
1881
                ushort line;
1882
 
1883
                if (mono_current_par.bplcon0 & BPC0_LACE)
1884
                        line = diwstrt_v + (mono_current_par.scr_height - y_wrap)/2;
1885
                else
1886
                        line = diwstrt_v + mono_current_par.scr_height - y_wrap;
1887
 
1888
                /* Handle skipping over 256-line chunks */
1889
                while (line > 256) {
1890
                        /* Hardware limitation - 8 bit counter    */
1891
                        /* Wait(diwstop_h-2, 0xff) */
1892
                        if (mono_current_par.bplcon0 & BPC0_SHRES)
1893
                                /*
1894
                                 * htotal-4 is used in SHRES-mode, as diwstop_h-2 doesn't work under ECS.
1895
                                 * Does this work under AGA?
1896
                                 * -Jes
1897
                                 */
1898
                                *cop++ = 0xff00 | ((mono_current_par.htotal-4) | 1);
1899
                        else
1900
                                *cop++ = 0xff00 | ((diwstop_h-2) >> 1) | 0x1;
1901
 
1902
                        *cop++ = 0xfffe;
1903
                        /* Wait(0, 0) - make sure we're in the new segment */
1904
                        *cop++ = 0x0001;
1905
                        *cop++ = 0xfffe;
1906
                        line -= 256;
1907
 
1908
                        /*
1909
                         * Under ECS we have to keep color[0], as it is part of a special color-table.
1910
                         */
1911
 
1912
                        if (boot_info.bi_amiga.chipset == CS_ECS && mono_current_par.bplcon0 & BPC0_ECSENA) {
1913
                                *cop++ = 0x0180;
1914
                                *cop++ = mono_ecs_color_zero;
1915
                        }
1916
                }
1917
 
1918
                /* Wait(diwstop_h, line - 1) */
1919
                *cop++ = ((line - 1)   << 8) | (diwstop_h >> 1) | 0x1;
1920
                *cop++ = 0xfffe;
1921
 
1922
                for (i = 0 ; i < mono_current_par.scr_depth ; i++) {
1923
                        scrmem = (long)mono_current_par.bitplane[i];
1924
                        if (shf)
1925
                                scrmem += mono_current_par.bytes_per_row;
1926
 
1927
                                *cop++ = CUSTOM_OFS(bplpt[i]);
1928
                                *cop++ = (long)scrmem >> 16;
1929
                                *cop++ = CUSTOM_OFS(bplpt[i]) + 2;
1930
                                *cop++ = (long)scrmem;
1931
                }
1932
        }
1933
 
1934
        /* End of Copper list */
1935
        *cop++ = 0xffff;
1936
        *cop++ = 0xfffe;
1937
 
1938
        return(cop);
1939
}
1940
 
1941
 
1942
static __inline__ void mono_build_cursor(register struct display *p)
1943
{
1944
        int vs, hs, ve;
1945
        ushort diwstrt_v = mono_current_par.diwstrt_v;
1946
        ushort diwstrt_h = mono_current_par.diwstrt_h;
1947
 
1948
        if (mono_current_par.bplcon0 & BPC0_LACE) {
1949
                vs = diwstrt_v + (p->cursor_y * p->fontheight)/2;
1950
                ve = vs + p->fontheight/2;
1951
        } else {
1952
                vs = diwstrt_v + (p->cursor_y * p->fontheight);
1953
                ve = vs + p->fontheight;
1954
        }
1955
 
1956
        if (mono_current_par.bplcon0 & BPC0_ECSENA)
1957
                /*
1958
                 * It's an AGA mode. We'll assume that the sprite was set
1959
                 * into 35ns resolution by the appropriate SPRES bits in bplcon3.
1960
                 */
1961
                hs = diwstrt_h  * 4 + (p->cursor_x * p->fontwidth) - 4;
1962
        else
1963
                hs = diwstrt_h + (p->cursor_x * p->fontwidth) / 2 - 1;
1964
 
1965
        if (mono_current_par.bplcon0 & BPC0_ECSENA) {
1966
                /* There are some high-order bits on the sprite position */
1967
                *((ulong *) mono_current_par.cursor) =
1968
                ((((vs & 0xff) << 24) | ((vs & 0x100) >> 6) |
1969
                ((vs & 0x200) >> 3)) |
1970
                (((hs & 0x7f8) << 13) | ((hs & 0x4) >> 2) |
1971
                ((hs & 0x3) << 3)) |
1972
                (((ve & 0xff) << 8) | ((ve & 0x100) >> 7) |
1973
                ((ve & 0x200) >> 4)));
1974
        } else {
1975
                *((ulong *) mono_current_par.cursor) =
1976
                ((vs << 24) | ((vs & 0x00000100) >> 6) |
1977
                ((hs & 0x000001fe) << 15) | (hs & 0x00000001) |
1978
                ((ve & 0x000000ff) << 8) | ((ve & 0x00000100) >> 7));
1979
        }
1980
}
1981
 
1982
static void mono_build_ecs_colors(ushort color1, ushort color2, ushort color3,
1983
                      ushort color4, ushort *table)
1984
{
1985
/*
1986
 * This function calculates the special ECS color-tables needed when running
1987
 * new screen-modes available under ECS. See the hardware reference manual
1988
 * 3rd edition for details.
1989
 * -Jes
1990
 */
1991
ushort  t;
1992
 
1993
        t = (color1 & 0x0ccc);
1994
        table[0] = t;
1995
        table[4] = t;
1996
        table[8] = t;
1997
        table[12] = t;
1998
        t = t >> 2;
1999
        table[0] = (table[0] | t);
2000
        table[1] = t;
2001
        table[2] = t;
2002
        table[3] = t;
2003
 
2004
        t = (color2 & 0x0ccc);
2005
        table[1] = (table[1] | t);
2006
        table[5] = t;
2007
        table[9] = t;
2008
        table[13] = t;
2009
        t = t >> 2;
2010
        table[4] = (table[4] | t);
2011
        table[5] = (table[5] | t);
2012
        table[6] = t;
2013
        table[7] = t;
2014
 
2015
        t = (color3 & 0x0ccc);
2016
        table[2] = (table[2] | t);
2017
        table[6] = (table[6] | t);
2018
        table[10] = t;
2019
        table[14] = t;
2020
        t = t >> 2;
2021
        table[8] = (table[8] | t);
2022
        table[9] = (table[9] | t);
2023
        table[10] = (table[10] | t);
2024
        table[11] = t;
2025
 
2026
        t = (color4 & 0x0ccc);
2027
        table[3] = (table[3] | t);
2028
        table[7] = (table[7] | t);
2029
        table[11] = (table[11] | t);
2030
        table[15] = t;
2031
        t = t >> 2;
2032
        table[12] = (table[12] | t);
2033
        table[13] = (table[13] | t);
2034
        table[14] = (table[14] | t);
2035
        table[15] = (table[15] | t);
2036
 
2037
}
2038
 
2039
/* mono_display_init():
2040
 *
2041
 *    Fills out (struct display *) given a geometry structure
2042
 */
2043
 
2044
static void mono_display_init(struct display *p,
2045
                         struct geometry *geom, ushort inverse)
2046
{
2047
        ushort ecs_table[16];
2048
        int    i;
2049
        char   *chipptr;
2050
        ushort diwstrt_v, diwstop_v;
2051
        ushort diwstrt_h, diwstop_h;
2052
        ushort diw_min_h, diw_min_v;
2053
        ushort bplmod, diwstrt, diwstop, diwhigh, ddfstrt, ddfstop;
2054
        ushort cursorheight, cursormask = 0;
2055
        u_long size;
2056
 
2057
        /* Decide colour scheme */
2058
 
2059
        if (inverse) {
2060
                mono_current_par.fgcol   = FG_COLOR_INV;
2061
                mono_current_par.bgcol   = BG_COLOR_INV;
2062
                mono_current_par.crsrcol = CRSR_COLOR_INV;
2063
        } else {
2064
                mono_current_par.fgcol   = FG_COLOR;
2065
                mono_current_par.bgcol   = BG_COLOR;
2066
                mono_current_par.crsrcol = CRSR_COLOR;
2067
        }
2068
 
2069
        /* Define screen geometry */
2070
 
2071
        mono_current_par.scr_max_height = geom->scr_max_height;
2072
        mono_current_par.scr_max_width  = geom->scr_max_width;
2073
        mono_current_par.scr_height     = geom->scr_height;
2074
        mono_current_par.scr_width      = geom->scr_width;
2075
        mono_current_par.scr_depth      = geom->scr_depth;
2076
        mono_current_par.bplcon0        = geom->bplcon0 | BPC0_COLOR;
2077
        mono_current_par.htotal         = geom->htotal;
2078
 
2079
        /* htotal was added, as I use it to calc the pal-line. -Jes */
2080
 
2081
        if (mono_current_par.scr_depth < 8)
2082
                mono_current_par.bplcon0 |= (mono_current_par.scr_depth << 12);
2083
        else {
2084
                /* must be exactly 8 */
2085
                mono_current_par.bplcon0 |= BPC0_BPU3;
2086
        }
2087
 
2088
        diw_min_v         = geom->diwstrt_v;
2089
        diw_min_h         = geom->diwstrt_h;
2090
 
2091
        /* We can derive everything else from this, at least for OCS */
2092
        /*
2093
         * For AGA: we don't use the finer position control available for
2094
         * diw* yet (could be set by 35ns increments).
2095
         */
2096
 
2097
        /* Calculate line and plane size while respecting the alignment restrictions */
2098
        mono_current_par.bytes_per_row  = ((mono_current_par.scr_width+geom->alignment-1)&~(geom->alignment-1)) >> 3;
2099
        mono_current_par.plane_size     = mono_current_par.bytes_per_row * mono_current_par.scr_height;
2100
 
2101
 
2102
        /*
2103
         *              Quick hack for frame buffer mmap():
2104
         *
2105
         *              plane_size must be a multiple of the page size
2106
         */
2107
 
2108
        mono_current_par.plane_size = PAGE_ALIGN(mono_current_par.plane_size);
2109
 
2110
 
2111
        mono_current_par.y_wrap   = 0;                  mono_current_par.scroll_latch = 1;
2112
        p->cursor_x = 0; p->cursor_y = 0; mono_current_par.cursor_latch = 1;
2113
 
2114
        if (mono_current_par.bplcon0 & BPC0_LACE) {
2115
                bplmod = mono_current_par.bytes_per_row;
2116
                diwstrt_v = diw_min_v + (mono_current_par.scr_max_height - mono_current_par.scr_height)/4;
2117
                diwstop_v = (diwstrt_v + mono_current_par.scr_height/2);
2118
        } else {
2119
                bplmod = 0;
2120
                diwstrt_v = diw_min_v + (mono_current_par.scr_max_height - mono_current_par.scr_height)/2;
2121
                diwstop_v = (diwstrt_v + mono_current_par.scr_height);
2122
        }
2123
 
2124
        if (mono_current_par.bplcon0 & BPC0_HIRES) {
2125
                diwstrt_h =  diw_min_h + (mono_current_par.scr_max_width - mono_current_par.scr_width)/4;
2126
                diwstop_h = (diwstrt_h + mono_current_par.scr_width/2);
2127
                /* ??? Where did 0x1d5 come from in original code ??? */
2128
        } else if (mono_current_par.bplcon0 & BPC0_SHRES) {
2129
                diwstrt_h =  diw_min_h + (mono_current_par.scr_max_width - mono_current_par.scr_width)/8;
2130
                diwstop_h = (diwstrt_h + mono_current_par.scr_width/4);
2131
        } else {
2132
                diwstrt_h =  diw_min_h + (mono_current_par.scr_max_width - mono_current_par.scr_width)/2;
2133
                diwstop_h = (diwstrt_h + mono_current_par.scr_width);
2134
        }
2135
 
2136
        if (mono_current_par.bplcon0 & BPC0_HIRES) {
2137
                ddfstrt = (diwstrt_h >> 1) - 4;
2138
                ddfstop = ddfstrt + (4 * (mono_current_par.bytes_per_row>>1)) - 8;
2139
        } else if (mono_current_par.bplcon0 & BPC0_SHRES && boot_info.bi_amiga.chipset == CS_AGA) {
2140
                /* There may be some interaction with FMODE here... -8 is magic. */
2141
 
2142
                /*
2143
                 * This should be fixed, so it supports all different
2144
                 * FMODE's.  FMODE varies the speed with 1,2 & 4 the
2145
                 * standard ECS speed.  Someone else has to do it, as
2146
                 * I don't have an AGA machine with MMU available
2147
                 * here.
2148
                 *
2149
                 * This particular speed looks like FMODE = 3 to me.
2150
                 * ddfstop should be changed so it depends on FMODE under AGA.
2151
                 * -Jes
2152
                 */
2153
                ddfstrt = (diwstrt_h >> 1) - 8;
2154
                ddfstop = ddfstrt + (2 * (mono_current_par.bytes_per_row>>1)) - 8;
2155
        } else if (mono_current_par.bplcon0 & BPC0_SHRES && boot_info.bi_amiga.chipset == CS_ECS){
2156
                /*
2157
                 * Normal speed for ECS, should be the same for FMODE = 0
2158
                 * -Jes
2159
                 */
2160
                ddfstrt = (diwstrt_h >> 1) - 2;
2161
                ddfstop = ddfstrt + (2 * (mono_current_par.bytes_per_row>>1)) - 8;
2162
        } else {
2163
                ddfstrt = (diwstrt_h >> 1) - 8;
2164
                ddfstop = ddfstrt + (8 * (mono_current_par.bytes_per_row>>1)) - 8;
2165
        }
2166
 
2167
        if (mono_current_par.bplcon0 & BPC0_LACE)
2168
                cursorheight = p->fontheight/2;
2169
        else
2170
                cursorheight = p->fontheight;
2171
 
2172
        /*
2173
         *              Quick hack for frame buffer mmap():
2174
         *
2175
         *              chipptr must be at a page boundary
2176
         */
2177
 
2178
        size = mono_current_par.scr_depth*mono_current_par.plane_size+COP_MEM_REQ+SPR_MEM_REQ+4*(cursorheight-1);
2179
        size += PAGE_SIZE-1;
2180
        chipptr = amiga_chip_alloc(size);
2181
        chipptr = (char *)PAGE_ALIGN((u_long)chipptr);
2182
 
2183
 
2184
        /* locate the bitplanes */
2185
        /* These MUST be 64 bit aligned for full AGA compatibility!! */
2186
 
2187
        mono_current_par.smem_start = (u_long)chipptr;
2188
        mono_current_par.smem_len = mono_current_par.plane_size*mono_current_par.scr_depth;
2189
        mono_current_par.geometry = geom;
2190
 
2191
        for (i = 0 ; i < mono_current_par.scr_depth ; i++, chipptr += mono_current_par.plane_size) {
2192
                mono_current_par.bitplane[i] = (u_char *) chipptr;
2193
                memset ((void *)chipptr, 0, mono_current_par.plane_size);  /* and clear */
2194
        }
2195
 
2196
        /* locate the copper lists */
2197
        mono_current_par.coplist1hdr = (ushort *) chipptr;  chipptr += MAX_COP_LIST_ENTS * 4;
2198
        mono_current_par.coplist2hdr = (ushort *) chipptr;  chipptr += MAX_COP_LIST_ENTS * 4;
2199
 
2200
        /* locate the sprite data */
2201
        mono_current_par.cursor      = (ushort *) chipptr;  chipptr += 8+4*cursorheight;
2202
        mono_current_par.dummy       = (ushort *) chipptr;  chipptr += 12;
2203
 
2204
        /* create the sprite data for the cursor image */
2205
        memset((void *)mono_current_par.cursor, 0, 8+4*cursorheight);
2206
        /*
2207
         * Only AGA supplies hires sprites.
2208
         */
2209
        if (mono_current_par.bplcon0 & BPC0_ECSENA && boot_info.bi_amiga.chipset == CS_AGA)
2210
                /* AGA cursor is SHIRES, ECS sprites differ */
2211
                for (i = 0; (i < p->fontwidth) && (i < 16); i++)
2212
                        cursormask |= 1<<(15-i);
2213
        else
2214
                /* For OCS & ECS sprites are pure LORES 8-< */
2215
                for (i = 0; (i < p->fontwidth/2) && (i < 8); i++)
2216
                        cursormask |= 1<<(15-i);
2217
 
2218
        mono_current_par.cursor[0] = mono_cursor_data[0];
2219
        mono_current_par.cursor[1] = mono_cursor_data[1];
2220
 
2221
#if (CRSR_BLOCK == 1)
2222
        for (i = 0; i < cursorheight; i++)
2223
#else
2224
        for (i = cursorheight-2; i < cursorheight; i++)
2225
#endif
2226
                mono_current_par.cursor[2+2*i] = cursormask;
2227
 
2228
        /* set dummy sprite data to a blank sprite */
2229
        memset((void *)mono_current_par.dummy, 0, 12);
2230
 
2231
        /* set cursor flashing */
2232
        mono_current_par.cursor_flash = CRSR_FLASH;
2233
 
2234
        /* Make the cursor invisible */
2235
        mono_current_par.cursor_visible = 0;
2236
 
2237
        /* Initialise the chipregs */
2238
        mono_current_par.diwstrt_v = diwstrt_v;
2239
        mono_current_par.diwstrt_h = diwstrt_h;
2240
        mono_current_par.diwstop_v = diwstop_v;
2241
        mono_current_par.diwstop_h = diwstop_h;
2242
        diwstrt = ((diwstrt_v << 8) | diwstrt_h);
2243
        diwstop = ((diwstop_v & 0xff) << 8) | (diwstop_h & 0xff);
2244
 
2245
        custom.bplcon0   = mono_current_par.bplcon0;    /* set the display mode */
2246
        custom.bplcon1   = 0;            /* Needed for horizontal scrolling */
2247
        custom.bplcon2   = 0;
2248
        custom.bpl1mod   = bplmod;
2249
        custom.bpl2mod   = bplmod;
2250
        custom.diwstrt   = diwstrt;
2251
        custom.diwstop   = diwstop;
2252
        custom.ddfstrt   = ddfstrt;
2253
        custom.ddfstop   = ddfstop;
2254
 
2255
        custom.color[0]  = COLOR_MSB(mono_current_par.bgcol);
2256
        custom.color[1]  = COLOR_MSB(mono_current_par.fgcol);
2257
        custom.color[17] = COLOR_MSB(mono_current_par.crsrcol); /* Sprite 0 color */
2258
 
2259
        if (boot_info.bi_amiga.chipset == CS_AGA) {
2260
                /* Fill in the LSB of the 24 bit color palette */
2261
                /* Must happen after MSB */
2262
                custom.bplcon3   = geom->bplcon3 | BPC3_LOCT;
2263
                custom.color[0]  = COLOR_LSB(mono_current_par.bgcol);
2264
                custom.color[1]  = COLOR_LSB(mono_current_par.fgcol);
2265
                custom.color[17] = COLOR_LSB(mono_current_par.crsrcol);
2266
                custom.bplcon3   = geom->bplcon3;
2267
        }
2268
 
2269
        if (boot_info.bi_amiga.chipset == CS_ECS && mono_current_par.bplcon0 & BPC0_ECSENA) {
2270
                /*
2271
                 * Calculation of the special ECS color-tables for
2272
                 * planes and sprites is done in the function
2273
                 * build_ecs_table
2274
                 */
2275
 
2276
                /*
2277
                 * Calcs a special ECS colortable for the bitplane,
2278
                 * and copies it to the custom registers
2279
                 */
2280
                mono_build_ecs_colors(COLOR_MSB(mono_current_par.bgcol), COLOR_MSB(mono_current_par.fgcol),
2281
                                 0, 0, ecs_table);
2282
 
2283
#if 0
2284
                for (i = 0; i < 8; i++){
2285
                        custom.color[i]   = ecs_table[i*2];
2286
                        custom.color[i+8] = ecs_table[i*2+1];
2287
                }
2288
#else
2289
                for (i = 0; i < 16; i++){
2290
                        custom.color[i]   = ecs_table[i];
2291
                }
2292
#endif
2293
 
2294
                mono_ecs_color_zero = ecs_table[0];
2295
 
2296
                /*
2297
                 * Calcs a special ECS colortable for the cursor
2298
                 * sprite, and copies it to the appropriate custom
2299
                 * registers
2300
                 */
2301
                mono_build_ecs_colors(0, COLOR_MSB(mono_current_par.crsrcol), 0, 0, ecs_table);
2302
 
2303
                for (i = 0; i < 16; i++){
2304
                        custom.color[i+16] = ecs_table[i];
2305
                }
2306
        }
2307
 
2308
        if (!(geom->isOCS)) {
2309
                /* Need to set up a bunch more regs */
2310
                /* Assumes that diwstrt is in the (0,0) sector, but stop might not be */
2311
                diwhigh = (diwstop_v & 0x700) | ((diwstop_h & 0x100) << 5);
2312
 
2313
                custom.bplcon2   = geom->bplcon2;
2314
                custom.bplcon3   = geom->bplcon3;
2315
                /* save bplcon3 for blanking */
2316
                mono_save_bplcon3 = geom->bplcon3;
2317
 
2318
                custom.diwhigh   = diwhigh;     /* must happen AFTER diwstrt, stop */
2319
 
2320
                custom.htotal   = geom->htotal;
2321
                custom.hsstrt   = geom->hsstrt;
2322
                custom.hsstop   = geom->hsstop;
2323
                custom.hbstrt   = geom->hbstrt;
2324
                custom.hbstop   = geom->hbstop;
2325
                custom.vtotal   = geom->vtotal;
2326
                custom.vsstrt   = geom->vsstrt;
2327
                custom.vsstop   = geom->vsstop;
2328
                custom.vbstrt   = geom->vbstrt;
2329
                custom.vbstop   = geom->vbstop;
2330
                custom.hcenter  = geom->hcenter;
2331
                custom.beamcon0 = geom->beamcon0;
2332
                if (boot_info.bi_amiga.chipset == CS_AGA) {
2333
                        custom.fmode    = geom->fmode;
2334
                }
2335
                /*
2336
                 * fmode does NOT! exist under ECS, weird things might happen
2337
                 */
2338
 
2339
                /* We could load 8-bit colors here, if we wanted */
2340
 
2341
                /*
2342
                 *    The minimum period for audio depends on htotal (for OCS/ECS/AGA)
2343
                 */
2344
                if (boot_info.bi_amiga.chipset != CS_STONEAGE)
2345
                        amiga_audio_min_period = (geom->htotal>>1)+1;
2346
        }
2347
 
2348
 
2349
        /* Build initial copper lists. sprites must be set up, and mono_current_par.diwstrt. */
2350
 
2351
        if (mono_current_par.bplcon0 & BPC0_LACE) {
2352
                mono_current_par.coplist1dyn = mono_build_clist_hdr(p,mono_current_par.coplist1hdr, mono_current_par.coplist2hdr),
2353
                mono_build_clist_dyn(p, mono_current_par.coplist1dyn, 0);
2354
 
2355
                mono_current_par.coplist2dyn = mono_build_clist_hdr(p,mono_current_par.coplist2hdr, mono_current_par.coplist1hdr),
2356
                mono_build_clist_dyn(p, mono_current_par.coplist2dyn, 1);
2357
        } else {
2358
                mono_current_par.coplist1dyn = mono_build_clist_hdr(p,mono_current_par.coplist1hdr, NULL),
2359
                mono_build_clist_dyn(p, mono_current_par.coplist1dyn, 0);
2360
        }
2361
 
2362
 
2363
        /* Get ready to run first copper list */
2364
        custom.cop1lc = mono_current_par.coplist1hdr;
2365
        custom.copjmp1 = 0;
2366
 
2367
        /* turn on DMA for bitplane and sprites */
2368
        custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_COPPER | DMAF_SPRITE;
2369
 
2370
        if (mono_current_par.bplcon0 & BPC0_LACE) {
2371
                /* Make sure we get the fields in the right order */
2372
 
2373
                /* wait for LOF frame bit to go low */
2374
                while (custom.vposr & 0x8000)
2375
                        ;
2376
 
2377
                /* wait for LOF frame bit to go high */
2378
                while (!(custom.vposr & 0x8000))
2379
                        ;
2380
 
2381
                /* start again at the beginning of copper list 1 */
2382
                custom.cop1lc = mono_current_par.coplist1hdr;
2383
                custom.copjmp1 = 0;
2384
        }
2385
}
2386
 
2387
 
2388
static void mono_amifb_interrupt(int irq, struct pt_regs *fp, void *data)
2389
{
2390
        register struct display *p = disp;
2391
 
2392
        static ushort cursorcount = 0;
2393
        static ushort cursorstate = 0;
2394
 
2395
        /* I *think* that you should only change display lists on long frame.
2396
         * At least it goes awfully peculiar on my A500 without the following
2397
         * test. Not really in a position to test this hypothesis, so sorry
2398
         * for the slow scrolling, all you flicker-fixed souls
2399
         */
2400
 
2401
        if (!(mono_current_par.bplcon0 & BPC0_LACE) || (custom.vposr & 0x8000)) {
2402
                if (mono_current_par.scroll_latch || mono_current_par.cursor_latch)
2403
                        mono_build_cursor(p);
2404
 
2405
                if (mono_current_par.scroll_latch)
2406
                        if (mono_current_par.bplcon0 & BPC0_LACE) {
2407
                                mono_build_clist_dyn(p, mono_current_par.coplist1dyn, 0);
2408
                                mono_build_clist_dyn(p, mono_current_par.coplist2dyn, 1);
2409
                        } else
2410
                                mono_build_clist_dyn(p, mono_current_par.coplist1dyn, 0);
2411
                        mono_current_par.scroll_latch = 0;
2412
                        mono_current_par.cursor_latch = 0;
2413
        }
2414
 
2415
        if (!(custom.potgor & (1<<10)))
2416
                mono_vblank.right_count++;
2417
 
2418
        if (mono_current_par.cursor_visible) {
2419
                if (mono_current_par.cursor_flash) {
2420
                        if (cursorcount)
2421
                                cursorcount--;
2422
                        else {
2423
                                cursorcount = CRSR_RATE;
2424
                                if ((cursorstate = !cursorstate))
2425
                                        custom.dmacon = DMAF_SETCLR | DMAF_SPRITE;
2426
                                else
2427
                                        custom.dmacon = DMAF_SPRITE;
2428
                        }
2429
                }
2430
        } else
2431
                custom.dmacon = DMAF_SPRITE;
2432
 
2433
        if (mono_do_blank) {
2434
                custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
2435
                custom.color[0] = 0;
2436
                if (boot_info.bi_amiga.chipset == CS_AGA) {
2437
                        /* Fill in the LSB of the 24 bit color palette */
2438
                        /* Must happen after MSB */
2439
                        custom.bplcon3 = mono_save_bplcon3 | BPC3_LOCT;
2440
                        custom.color[0]= 0;
2441
                        custom.bplcon3 = mono_save_bplcon3;
2442
                }
2443
                mono_do_blank = 0;
2444
        }
2445
 
2446
        if (mono_do_unblank) {
2447
                if (mono_current_par.cursor_visible)
2448
                        custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_SPRITE;
2449
                else
2450
                        custom.dmacon = DMAF_SETCLR | DMAF_RASTER;
2451
                custom.color[0] = COLOR_MSB(mono_current_par.bgcol);
2452
                if (boot_info.bi_amiga.chipset == CS_AGA) {
2453
                        /* Fill in the LSB of the 24 bit color palette */
2454
                        /* Must happen after MSB */
2455
                        custom.bplcon3 = mono_save_bplcon3 | BPC3_LOCT;
2456
                        custom.color[0] = COLOR_LSB(mono_current_par.bgcol);
2457
                        custom.bplcon3 = mono_save_bplcon3;
2458
                }
2459
                /* color[0] is set to mono_ecs_color_zero under ECS */
2460
                if (boot_info.bi_amiga.chipset == CS_ECS && mono_current_par.bplcon0 & BPC0_ECSENA) {
2461
                        custom.color[0]  = mono_ecs_color_zero;
2462
                }
2463
                mono_do_unblank = 0;
2464
        }
2465
 
2466
        mono_vblank.done = 1;
2467
}
2468
 
2469
 
2470
static int mono_amiga_fb_get_fix(struct fb_fix_screeninfo *fix, int con)
2471
{
2472
        int i;
2473
 
2474
        strcpy(fix->id, mono_current_par.geometry->modename);
2475
        fix->smem_start = mono_current_par.smem_start;
2476
        fix->smem_len = mono_current_par.smem_len;
2477
 
2478
        /*
2479
         *              Only monochrome bitmap at the moment
2480
         */
2481
 
2482
        fix->type = FB_TYPE_PACKED_PIXELS;
2483
 
2484
        fix->type_aux = 0;
2485
        if (mono_amifb_inverse)
2486
                fix->visual = FB_VISUAL_MONO10;
2487
        else
2488
                fix->visual = FB_VISUAL_MONO01;
2489
 
2490
        fix->xpanstep = 0;
2491
        fix->ypanstep = 0;
2492
        fix->ywrapstep = 1;
2493
 
2494
        fix->line_length = 0;
2495
        for (i = 0; i < arraysize(fix->reserved); i++)
2496
                fix->reserved[i] = 0;
2497
        return(0);
2498
}
2499
 
2500
 
2501
static int mono_amiga_fb_get_var(struct fb_var_screeninfo *var, int con)
2502
{
2503
        int i;
2504
 
2505
        var->xres = mono_current_par.geometry->scr_width;
2506
        var->yres = mono_current_par.geometry->scr_height;
2507
        var->xres_virtual = var->xres;
2508
        var->yres_virtual = var->yres;
2509
        var->xoffset = 0;
2510
        var->yoffset = 0;
2511
 
2512
        var->bits_per_pixel = mono_current_par.geometry->scr_depth;
2513
        var->grayscale = 0;
2514
 
2515
        if (boot_info.bi_amiga.chipset == CS_AGA) {
2516
                var->red.offset = 0;
2517
                var->red.length = 8;
2518
                var->red.msb_right = 0;
2519
                var->green = var->red;
2520
                var->blue = var->red;
2521
        } else {
2522
                var->red.offset = 0;
2523
                var->red.length = 4;
2524
                var->red.msb_right = 0;
2525
                var->green = var->red;
2526
                var->blue = var->red;
2527
        }
2528
 
2529
        var->nonstd = 0;
2530
        var->activate = 0;
2531
 
2532
        var->width = -1;
2533
        var->height = -1;
2534
 
2535
        var->accel = FB_ACCEL_NONE;
2536
 
2537
        var->pixclock = 35242;
2538
        var->left_margin = (mono_current_par.geometry->hbstop-mono_current_par.geometry->hsstrt)*8;
2539
        var->right_margin = (mono_current_par.geometry->hsstrt-mono_current_par.geometry->hbstrt)*8;
2540
        var->upper_margin = (mono_current_par.geometry->vbstop-mono_current_par.geometry->vsstrt)*8;
2541
        var->lower_margin = (mono_current_par.geometry->vsstrt-mono_current_par.geometry->vbstrt)*8;
2542
        var->hsync_len = (mono_current_par.geometry->hsstop-mono_current_par.geometry->hsstrt)*8;
2543
        var->vsync_len = (mono_current_par.geometry->vsstop-mono_current_par.geometry->vsstrt)*8;
2544
        var->sync = 0;
2545
        if (mono_current_par.geometry->bplcon0 & BPC0_LACE)
2546
                var->vmode = FB_VMODE_INTERLACED;
2547
        else if ((boot_info.bi_amiga.chipset == CS_AGA) && (mono_current_par.geometry->fmode & FMODE_BSCAN2))
2548
                var->vmode = FB_VMODE_DOUBLE;
2549
        else
2550
                var->vmode = FB_VMODE_NONINTERLACED;
2551
 
2552
        for (i = 0; i < arraysize(var->reserved); i++)
2553
                var->reserved[i] = 0;
2554
 
2555
        return(0);
2556
}
2557
 
2558
 
2559
static void mono_amiga_fb_set_disp(int con)
2560
{
2561
        struct fb_fix_screeninfo fix;
2562
 
2563
        mono_amiga_fb_get_fix(&fix, con);
2564
        if (con == -1)
2565
                con = 0;
2566
        disp[con].screen_base = (u_char *)fix.smem_start;
2567
        disp[con].visual = fix.visual;
2568
        disp[con].type = fix.type;
2569
        disp[con].type_aux = fix.type_aux;
2570
        disp[con].ypanstep = fix.ypanstep;
2571
        disp[con].ywrapstep = fix.ywrapstep;
2572
        disp[con].line_length = fix.line_length;
2573
        disp[con].can_soft_blank = 1;
2574
        disp[con].inverse = mono_amifb_inverse;
2575
}
2576
 
2577
 
2578
static int mono_amiga_fb_set_var(struct fb_var_screeninfo *var, int con)
2579
{
2580
        /*
2581
         *              Not yet implemented
2582
         */
2583
        return 0;                                /* The X server needs this */
2584
        return(-EINVAL);
2585
}
2586
 
2587
 
2588
static short mono_red_normal[] = {
2589
        ((BG_COLOR & 0xff0000)>>8) | ((BG_COLOR & 0xff0000)>>16),
2590
        ((FG_COLOR & 0xff0000)>>8) | ((FG_COLOR & 0xff0000)>>16)
2591
};
2592
static short mono_green_normal[] = {
2593
        ((BG_COLOR & 0x00ff00)) | ((BG_COLOR & 0x00ff00)>>8),
2594
        ((FG_COLOR & 0x00ff00)) | ((FG_COLOR & 0x00ff00)>>8)
2595
};
2596
static short mono_blue_normal[] = {
2597
        ((BG_COLOR & 0x0000ff)<<8) | ((BG_COLOR & 0x0000ff)),
2598
        ((FG_COLOR & 0x0000ff)<<8) | ((FG_COLOR & 0x0000ff))
2599
};
2600
 
2601
static short mono_red_inverse[] = {
2602
        ((BG_COLOR_INV & 0xff0000)>>8) | ((BG_COLOR_INV & 0xff0000)>>16),
2603
        ((FG_COLOR_INV & 0xff0000)>>8) | ((FG_COLOR_INV & 0xff0000)>>16)
2604
};
2605
static short mono_green_inverse[] = {
2606
        ((BG_COLOR_INV & 0x00ff00)) | ((BG_COLOR_INV & 0x00ff00)>>8),
2607
        ((FG_COLOR_INV & 0x00ff00)) | ((FG_COLOR_INV & 0x00ff00)>>8)
2608
};
2609
static short mono_blue_inverse[] = {
2610
        ((BG_COLOR_INV & 0x0000ff)<<8) | ((BG_COLOR_INV & 0x0000ff)),
2611
        ((FG_COLOR_INV & 0x0000ff)<<8) | ((FG_COLOR & 0x0000ff))
2612
};
2613
 
2614
static struct fb_cmap mono_default_cmap_normal = { 0, 2, mono_red_normal, mono_green_normal, mono_blue_normal, NULL };
2615
static struct fb_cmap mono_default_cmap_inverse = { 0, 2, mono_red_inverse, mono_green_inverse, mono_blue_inverse, NULL };
2616
 
2617
static int mono_amiga_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con)
2618
{
2619
        int i, start;
2620
        unsigned short *red, *green, *blue, *transp;
2621
        unsigned int hred, hgreen, hblue, htransp;
2622
        struct fb_cmap *def_cmap;
2623
 
2624
        red = cmap->red;
2625
        green = cmap->green;
2626
        blue = cmap->blue;
2627
        transp = cmap->transp;
2628
        start = cmap->start;
2629
        if (start < 0)
2630
                return(-EINVAL);
2631
 
2632
        if (mono_amifb_inverse)
2633
                def_cmap = &mono_default_cmap_inverse;
2634
        else
2635
                def_cmap = &mono_default_cmap_normal;
2636
 
2637
        for (i = 0; i < cmap->len; i++) {
2638
                if (i < def_cmap->len) {
2639
                        hred = def_cmap->red[i];
2640
                        hgreen = def_cmap->green[i];
2641
                        hblue = def_cmap->blue[i];
2642
                        if (def_cmap->transp)
2643
                                htransp = def_cmap->transp[i];
2644
                        else
2645
                                htransp = 0;
2646
                } else
2647
                        hred = hgreen = hblue = htransp = 0;
2648
                if (kspc) {
2649
                        *red = hred;
2650
                        *green = hgreen;
2651
                        *blue = hblue;
2652
                        if (transp)
2653
                                *transp = htransp;
2654
                } else {
2655
                        put_fs_word(hred, red);
2656
                        put_fs_word(hgreen, green);
2657
                        put_fs_word(hblue, blue);
2658
                        if (transp)
2659
                                put_fs_word(htransp, transp);
2660
                }
2661
                red++;
2662
                green++;
2663
                blue++;
2664
                if (transp)
2665
                        transp++;
2666
        }
2667
        return(0);
2668
}
2669
 
2670
 
2671
static int mono_amiga_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con)
2672
{
2673
        /*
2674
         *              Not yet implemented
2675
         */
2676
        return(-EINVAL);
2677
}
2678
 
2679
 
2680
static int mono_amiga_fb_pan_display(struct fb_var_screeninfo *var, int con)
2681
{
2682
        /*
2683
         *              Not yet implemented
2684
         */
2685
        return(-EINVAL);
2686
}
2687
 
2688
 
2689
static int mono_amiga_fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
2690
                                                                  unsigned long arg, int con)
2691
{
2692
        return(-EINVAL);
2693
}
2694
 
2695
static struct fb_ops mono_amiga_fb_ops = {
2696
        mono_amiga_fb_get_fix, mono_amiga_fb_get_var, mono_amiga_fb_set_var, mono_amiga_fb_get_cmap,
2697
        mono_amiga_fb_set_cmap, mono_amiga_fb_pan_display, mono_amiga_fb_ioctl
2698
};
2699
 
2700
 
2701
static int mono_amifb_switch (int con)
2702
{
2703
        mono_current_par.y_wrap = disp[con].var.yoffset;
2704
        mono_current_par.cursor_latch = 1;
2705
        mono_current_par.scroll_latch = 1;
2706
        return(0);
2707
}
2708
 
2709
 
2710
static int mono_amifb_updatevar(int con)
2711
{
2712
        mono_current_par.y_wrap = disp[con].var.yoffset;
2713
        mono_current_par.cursor_latch = 1;
2714
        mono_current_par.scroll_latch = 1;
2715
        return(0);
2716
}
2717
 
2718
 
2719
static void mono_amifb_blank(int blank)
2720
{
2721
        if (blank)
2722
                mono_do_blank = 1;
2723
        else
2724
                mono_do_unblank = 1;
2725
}
2726
 
2727
 
2728
static struct fb_info *mono_amiga_fb_init(long *mem_start)
2729
{
2730
        int mode = mono_amifb_mode;
2731
        ulong model;
2732
        int inverse_video = mono_amifb_inverse;
2733
        int err;
2734
 
2735
        err=register_framebuffer("Amiga Builtin", &node, &mono_amiga_fb_ops,  mono_num_mono_amiga_fb_predefined,
2736
                                                                         mono_mono_amiga_fb_predefined);
2737
 
2738
        model = boot_info.bi_un.bi_ami.model;
2739
        if (mode == -1)
2740
                if (boot_info.bi_amiga.chipset == CS_AGA)
2741
                        mode = AGA_DEFMODE;
2742
                else if (model == AMI_3000)
2743
                        mode = boot_info.bi_un.bi_ami.vblank == 50 ? OCS_PAL_3000_DEFMODE : OCS_NTSC_3000_DEFMODE;
2744
                else
2745
                        mode = boot_info.bi_un.bi_ami.vblank == 50 ? OCS_PAL_LOWEND_DEFMODE : OCS_NTSC_LOWEND_DEFMODE;
2746
 
2747
        mono_init_vblank();
2748
        mono_display_init(disp, &mono_modes[mode], inverse_video);
2749
        if (!add_isr(IRQ_AMIGA_VERTB, mono_amifb_interrupt, 0, NULL, "frame buffer"))
2750
                panic("Couldn't add vblank interrupt");
2751
 
2752
        mono_amiga_fb_get_var(&disp[0].var, 0);
2753
        if (mono_amifb_inverse)
2754
                disp[0].cmap = mono_default_cmap_inverse;
2755
        else
2756
                disp[0].cmap = mono_default_cmap_normal;
2757
        mono_amiga_fb_set_disp(-1);
2758
 
2759
        strcpy(fb_info.modename, "Amiga Builtin ");
2760
        fb_info.disp = disp;
2761
        fb_info.switch_con = &mono_amifb_switch;
2762
        fb_info.updatevar = &mono_amifb_updatevar;
2763
        fb_info.blank = &mono_amifb_blank;
2764
        strcat(fb_info.modename, mono_modes[mode].modename);
2765
 
2766
        return(&fb_info);
2767
}
2768
#endif /* USE_MONO_AMIFB_IF_NON_AGA */
2769
 
2770
 
2771
/* -------------------- OCS specific routines ------------------------------- */
2772
 
2773
 
2774
#ifdef CONFIG_AMIFB_OCS
2775
   /*
2776
    *    Initialization
2777
    *
2778
    *    Allocate the required chip memory.
2779
    *    Set the default video mode for this chipset. If a video mode was
2780
    *    specified on the command line, it will override the default mode.
2781
    */
2782
 
2783
static int ocs_init(void)
2784
{
2785
   u_long p;
2786
 
2787
   /*
2788
    *    Disable Display DMA
2789
    */
2790
 
2791
   custom.dmacon = DMAF_ALL | DMAF_MASTER;
2792
 
2793
   /*
2794
    *    Set the Default Video Mode
2795
    */
2796
 
2797
   if (!amifb_mode)
2798
      amifb_mode = get_video_mode(boot_info.bi_un.bi_ami.vblank == 50 ?
2799
                                  DEFMODE_PAL : DEFMODE_NTSC);
2800
 
2801
   /*
2802
    *    Allocate Chip RAM Structures
2803
    */
2804
 
2805
   videomemorysize = VIDEOMEMSIZE_OCS;
2806
 
2807
 
2808
   ...
2809
   ...
2810
   ...
2811
 
2812
 
2813
   /*
2814
    *    Enable Display DMA
2815
    */
2816
 
2817
   custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
2818
                   DMAF_SPRITE;
2819
 
2820
   return(0);
2821
}
2822
#endif /* CONFIG_AMIFB_OCS */
2823
 
2824
 
2825
/* -------------------- ECS specific routines ------------------------------- */
2826
 
2827
 
2828
#ifdef CONFIG_AMIFB_ECS
2829
   /*
2830
    *    Initialization
2831
    *
2832
    *    Allocate the required chip memory.
2833
    *    Set the default video mode for this chipset. If a video mode was
2834
    *    specified on the command line, it will override the default mode.
2835
    */
2836
 
2837
static int ecs_init(void)
2838
{
2839
   u_long p;
2840
 
2841
   /*
2842
    *    Disable Display DMA
2843
    */
2844
 
2845
   custom.dmacon = DMAF_ALL | DMAF_MASTER;
2846
 
2847
   /*
2848
    *    Set the Default Video Mode
2849
    */
2850
 
2851
   if (!amifb_mode)
2852
      if (AMIGAHW_PRESENT(AMBER_FF))
2853
         amifb_mode = get_video_mode(boot_info.bi_un.bi_ami.vblank == 50 ?
2854
                                     DEFMODE_AMBER_PAL : DEFMODE_AMBER_NTSC);
2855
      else
2856
         amifb_mode = get_video_mode(boot_info.bi_un.bi_ami.vblank == 50 ?
2857
                                     DEFMODE_PAL : DEFMODE_NTSC);
2858
 
2859
   /*
2860
    *    Allocate Chip RAM Structures
2861
    */
2862
 
2863
   if (boot_info.bi_amiga.chip_size > 1048576)
2864
      videomemorysize = VIDEOMEMSIZE_ECS_2M;
2865
   else
2866
      videomemorysize = VIDEOMEMSIZE_ECS_1M;
2867
 
2868
 
2869
   ...
2870
   ...
2871
   ...
2872
 
2873
 
2874
   /*
2875
    *    Enable Display DMA
2876
    */
2877
 
2878
   custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
2879
                   DMAF_SPRITE;
2880
 
2881
   return(0);
2882
}
2883
#endif /* CONFIG_AMIFB_ECS */
2884
 
2885
 
2886
/* -------------------- AGA specific routines ------------------------------- */
2887
 
2888
 
2889
#ifdef CONFIG_AMIFB_AGA
2890
   /*
2891
    *    Macros for the conversion from real world values to hardware register
2892
    *    values (and vice versa).
2893
    *
2894
    *    This helps us to keep our attention on the real stuff...
2895
    *
2896
    *    Hardware limits:
2897
    *
2898
    *       parameter     min      max     step
2899
    *       ---------     ---     ----     ----
2900
    *       diwstrt_h       0     2047        1
2901
    *       diwstrt_v       0     2047        1
2902
    *       diwstop_h       0     2047        1
2903
    *       diwstop_v       0     2047        1
2904
    *
2905
    *       ddfstrt         0     2032       16
2906
    *       ddfstop         0     2032       16
2907
    *
2908
    *       htotal          8     2048        8
2909
    *       hsstrt          0     2040        8
2910
    *       hsstop          0     2040        8
2911
    *       vtotal          1     2048        1
2912
    *       vsstrt          0     2047        1
2913
    *       vsstop          0     2047        1
2914
    *       hcenter         0     2040        8
2915
    *
2916
    *       hbstrt          0     2047        1
2917
    *       hbstop          0     2047        1
2918
    *       vbstrt          0     2047        1
2919
    *       vbstop          0     2047        1
2920
    *
2921
    *    Horizontal values are in 35 ns (SHRES) pixels
2922
    *    Vertical values are in scanlines
2923
    */
2924
 
2925
/* bplcon1 (smooth scrolling) */
2926
 
2927
#define hscroll2hw(hscroll) \
2928
   (((hscroll)<<12 & 0x3000) | ((hscroll)<<8 & 0xc300) | \
2929
    ((hscroll)<<4 & 0x0c00) | ((hscroll)<<2 & 0x00f0) | ((hscroll)>>2 & 0x000f))
2930
 
2931
#define hw2hscroll(hscroll) \
2932
   (((hscroll)>>8 & 0x00c3) | ((hscroll)<<2 & 0x003c))
2933
 
2934
/* diwstrt/diwstop/diwhigh (visible display window) */
2935
 
2936
#define diwstrt2hw(diwstrt_h, diwstrt_v) \
2937
   (((diwstrt_v)<<8 & 0xff00) | ((diwstrt_h)>>2 & 0x00ff))
2938
#define diwstop2hw(distop_h, diwstop_v) \
2939
   (((diwstop_v)<<8 & 0xff00) | ((diwstop_h)>>2 & 0x00ff))
2940
#define diw2hw_high(diwstrt_h, diwstrt_v, distop_h, diwstop_v) \
2941
   (((diwstop_h)<<3 & 0x2000) | ((diwstop_h)<<11 & 0x1800) | \
2942
    ((diwstop_v) & 0x0700) | ((diwstrt_h)>>5 & 0x0020) | \
2943
    ((diwstrt_h)<<3 & 0x0018) | ((diwstrt_v)>>8 & 0x0007))
2944
 
2945
#define hw2diwstrt_h(diwstrt, diwhigh) \
2946
   (((diwhigh)<<5 & 0x0400) | ((diwstrt)<<2 & 0x03fc) | ((diwhigh)>>3 & 0x0003))
2947
#define hw2diwstrt_v(diwstrt, diwhigh) \
2948
   (((diwhigh)<<8 & 0x0700) | ((diwstrt)>>8 & 0x00ff))
2949
#define hw2diwstop_h(diwstop, diwhigh) \
2950
   (((diwhigh)>>3 & 0x0400) | ((diwstop)<<2 & 0x03fc) | \
2951
    ((diwhigh)>>11 & 0x0003))
2952
#define hw2diwstop_v(diwstop, diwhigh) \
2953
   (((diwhigh) & 0x0700) | ((diwstop)>>8 & 0x00ff))
2954
 
2955
/* ddfstrt/ddfstop (display DMA) */
2956
 
2957
#define ddfstrt2hw(ddfstrt)   (div8(ddfstrt) & 0x00fe)
2958
#define ddfstop2hw(ddfstop)   (div8(ddfstop) & 0x00fe)
2959
 
2960
#define hw2ddfstrt(ddfstrt)   ((ddfstrt)<<3)
2961
#define hw2ddfstop(ddfstop)   ((ddfstop)<<3)
2962
 
2963
/* hsstrt/hsstop/htotal/vsstrt/vsstop/vtotal (sync timings) */
2964
 
2965
#define hsstrt2hw(hsstrt)     (div8(hsstrt))
2966
#define hsstop2hw(hsstop)     (div8(hsstop))
2967
#define htotal2hw(htotal)     (div8(htotal)-1)
2968
#define vsstrt2hw(vsstrt)     (vsstrt)
2969
#define vsstop2hw(vsstop)     (vsstop)
2970
#define vtotal2hw(vtotal)     ((vtotal)-1)
2971
 
2972
#define hw2hsstrt(hsstrt)     ((hsstrt)<<3)
2973
#define hw2hsstop(hsstop)     ((hsstop)<<3)
2974
#define hw2htotal(htotal)     (((htotal)+1)<<3)
2975
#define hw2vsstrt(vsstrt)     (vsstrt)
2976
#define hw2vsstop(vsstop)     (vsstop)
2977
#define hw2vtotal(vtotal)     ((vtotal)+1)
2978
 
2979
/* hbstrt/hbstop/vbstrt/vbstop (blanking timings) */
2980
 
2981
#define hbstrt2hw(hbstrt)     (((hbstrt)<<8 & 0x0700) | ((hbstrt)>>3 & 0x00ff))
2982
#define hbstop2hw(hbstop)     (((hbstop)<<8 & 0x0700) | ((hbstop)>>3 & 0x00ff))
2983
#define vbstrt2hw(vbstrt)     (vbstrt)
2984
#define vbstop2hw(vbstop)     (vbstop)
2985
 
2986
#define hw2hbstrt(hbstrt)     (((hbstrt)<<3 & 0x07f8) | ((hbstrt)>>8 & 0x0007))
2987
#define hw2hbstop(hbstop)     (((hbstop)<<3 & 0x07f8) | ((hbstop)>>8 & 0x0007))
2988
#define hw2vbstrt(vbstrt)     (vbstrt)
2989
#define hw2vbstop(vbstop)     (vbstop)
2990
 
2991
/* color */
2992
 
2993
#define rgb2hw_high(red, green, blue) \
2994
   (((red)<<4 & 0xf00) | ((green) & 0x0f0) | ((blue)>>4 & 0x00f))
2995
#define rgb2hw_low(red, green, blue) \
2996
   (((red)<<8 & 0xf00) | ((green)<<4 & 0x0f0) | ((blue) & 0x00f))
2997
 
2998
#define hw2red(high, low)     (((high)>>4 & 0xf0) | ((low)>>8 & 0x0f))
2999
#define hw2green(high, low)   (((high) & 0xf0) | ((low)>>4 & 0x0f))
3000
#define hw2blue(high, low)    (((high)<<4 & 0xf0) | ((low) & 0x0f))
3001
 
3002
/* sprpos/sprctl (sprite positioning) */
3003
 
3004
#define spr2hw_pos(start_v, start_h) \
3005
   (((start_v)<<8&0xff00) | ((start_h)>>3&0x00ff))
3006
#define spr2hw_ctl(start_v, start_h, stop_v) \
3007
   (((stop_v)<<8&0xff00) | ((start_v)>>3&0x0040) | ((stop_v)>>4&0x0020) | \
3008
    ((start_h)<<3&0x0018) | ((start_v)>>6&0x0004) | ((stop_v)>>7&0x0002) | \
3009
    ((start_h)>>2&0x0001))
3010
 
3011
 
3012
   /*
3013
    *    Hardware Cursor
3014
    */
3015
 
3016
struct aga_cursorsprite {
3017
   u_short sprpos;
3018
   u_short pad1[3];
3019
   u_short sprctl;
3020
   u_short pad2[3];
3021
   union {
3022
      struct {
3023
         u_long data[64*4];
3024
         u_long trailer[4];
3025
      } nonlaced;
3026
      struct {
3027
         u_long data[32*4];
3028
         u_long trailer[4];
3029
      } laced;
3030
   } u;
3031
};
3032
 
3033
struct aga_dummysprite {
3034
   u_short sprpos;
3035
   u_short pad1[3];
3036
   u_short sprctl;
3037
   u_short pad2[3];
3038
   u_long data[4];
3039
   u_long trailer[4];
3040
};
3041
 
3042
 
3043
   /*
3044
    *    Pixel modes for Bitplanes and Sprites
3045
    */
3046
 
3047
static u_short bplpixmode[3] = {
3048
   BPC0_SHRES,                   /*  35 ns / 28 MHz */
3049
   BPC0_HIRES,                   /*  70 ns / 14 MHz */
3050
 
3051
};
3052
 
3053
static u_short sprpixmode[3] = {
3054
   BPC3_SPRES1 | BPC3_SPRES0,    /*  35 ns / 28 MHz */
3055
   BPC3_SPRES1,                  /*  70 ns / 14 MHz */
3056
   BPC3_SPRES0                   /* 140 ns /  7 MHz */
3057
};
3058
 
3059
 
3060
   /*
3061
    *    Initialization
3062
    *
3063
    *    Allocate the required chip memory.
3064
    *    Set the default video mode for this chipset. If a video mode was
3065
    *    specified on the command line, it will override the default mode.
3066
    */
3067
 
3068
static int aga_init(void)
3069
{
3070
   u_long p;
3071
 
3072
   /*
3073
    *    Disable Display DMA
3074
    */
3075
 
3076
   custom.dmacon = DMAF_ALL | DMAF_MASTER;
3077
 
3078
   /*
3079
    *    Set the Default Video Mode
3080
    */
3081
 
3082
   if (!amifb_mode)
3083
      amifb_mode = get_video_mode(DEFMODE_AGA);
3084
 
3085
   /*
3086
    *    Allocate Chip RAM Structures
3087
    */
3088
 
3089
   if (boot_info.bi_amiga.chip_size > 1048576)
3090
      videomemorysize = VIDEOMEMSIZE_AGA_2M;
3091
   else
3092
      videomemorysize = VIDEOMEMSIZE_AGA_1M;
3093
 
3094
   p = chipalloc(videomemorysize+                     /* Bitplanes */
3095
                 sizeof(struct clist_hdr)+            /* Copper Lists */
3096
                 2*sizeof(struct clist_dyn)+
3097
                 2*sizeof(struct aga_cursorsprite)+   /* Sprites */
3098
                 sizeof(struct aga_dummysprite));
3099
 
3100
   assignchunk(videomemory, u_long, p, videomemorysize);
3101
   assignchunk(clist_hdr, struct clist_hdr *, p, sizeof(struct clist_hdr));
3102
   assignchunk(clist_lof, struct clist_dyn *, p, sizeof(struct clist_dyn));
3103
   assignchunk(clist_shf, struct clist_dyn *, p, sizeof(struct clist_dyn));
3104
   assignchunk(lofsprite, u_long *, p, sizeof(struct aga_cursorsprite));
3105
   assignchunk(shfsprite, u_long *, p, sizeof(struct aga_cursorsprite));
3106
   assignchunk(dummysprite, u_long *, p, sizeof(struct aga_dummysprite));
3107
 
3108
   /*
3109
    *    Make sure the Copper has something to do
3110
    */
3111
 
3112
   aga_build_clist_hdr(clist_hdr);
3113
 
3114
   custom.cop1lc = (u_short *)ZTWO_PADDR(clist_hdr);
3115
   custom.cop2lc = (u_short *)ZTWO_PADDR(&clist_hdr->wait_forever);
3116
   custom.copjmp1 = 0;
3117
 
3118
   /*
3119
    *    Enable Display DMA
3120
    */
3121
 
3122
   custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
3123
                   DMAF_SPRITE;
3124
 
3125
   /*
3126
    *    These hardware register values will never be changed later
3127
    */
3128
 
3129
   custom.bplcon2 = BPC2_KILLEHB | BPC2_PF2P2 | BPC2_PF1P2;
3130
   custom.bplcon4 = BPC4_ESPRM4 | BPC4_OSPRM4;
3131
 
3132
   return(0);
3133
}
3134
 
3135
 
3136
   /*
3137
    *    This function should fill in the `fix' structure based on the
3138
    *    values in the `par' structure.
3139
    */
3140
 
3141
static int aga_encode_fix(struct fb_fix_screeninfo *fix,
3142
                          struct amiga_fb_par *par)
3143
{
3144
   int i;
3145
 
3146
   strcpy(fix->id, amiga_fb_name);
3147
   fix->smem_start = videomemory;
3148
   fix->smem_len = videomemorysize;
3149
 
3150
   if (amifb_ilbm) {
3151
      fix->type = FB_TYPE_INTERLEAVED_PLANES;
3152
      fix->type_aux = par->next_line;
3153
   } else {
3154
      fix->type = FB_TYPE_PLANES;
3155
      fix->type_aux = 0;
3156
   }
3157
   fix->visual = FB_VISUAL_PSEUDOCOLOR;
3158
 
3159
   if (par->diwstrt_h >= 323)
3160
      fix->xpanstep = 1;
3161
   else
3162
      fix->xpanstep = 64;
3163
   fix->ypanstep = 1;
3164
 
3165
   if (hw2ddfstrt(par->ddfstrt) >= (par->bpp-1)*64)
3166
      fix->ywrapstep = 1;
3167
   else
3168
      fix->ywrapstep = 0;
3169
 
3170
   fix->line_length = 0;
3171
   for (i = 0; i < arraysize(fix->reserved); i++)
3172
      fix->reserved[i] = 0;
3173
 
3174
   return(0);
3175
}
3176
 
3177
 
3178
   /*
3179
    *    Get the video params out of `var'. If a value doesn't fit, round
3180
    *    it up, if it's too big, return -EINVAL.
3181
    */
3182
 
3183
static int aga_decode_var(struct fb_var_screeninfo *var,
3184
                          struct amiga_fb_par *par)
3185
{
3186
   u_short clk_shift, line_shift_incd;
3187
   u_long upper, lower, hslen, vslen;
3188
   int xres_n, yres_n, xoffset_n;                              /* normalized */
3189
   u_long left_n, right_n, upper_n, lower_n, hslen_n, vslen_n; /* normalized */
3190
   u_long diwstrt_h, diwstrt_v, diwstop_h, diwstop_v;
3191
   u_long hsstrt, vsstrt, hsstop, vsstop, htotal, vtotal;
3192
   u_long ddfmin, ddfmax, ddfstrt, ddfstop, hscroll;
3193
   u_long hrate, vrate;
3194
   u_short loopcnt = 0;
3195
 
3196
   /*
3197
    *    Find a matching Pixel Clock
3198
    */
3199
 
3200
   for (clk_shift = 0; clk_shift < 3; clk_shift++)
3201
      if (var->pixclock <= pixclock[clk_shift])
3202
         break;
3203
   if (clk_shift >= 3)
3204
      return(-EINVAL);
3205
   par->clk_shift = clk_shift;
3206
 
3207
   /*
3208
    *    Round up the Geometry Values (if necessary)
3209
    */
3210
 
3211
   par->xres = max(var->xres, 64);
3212
   par->yres = max(var->yres, 64);
3213
   par->vxres = up64(max(var->xres_virtual, par->xres));
3214
   par->vyres = max(var->yres_virtual, par->yres);
3215
 
3216
   par->bpp = var->bits_per_pixel;
3217
   if (par->bpp > 8)
3218
      return(-EINVAL);
3219
 
3220
   if (!var->nonstd) {
3221
      if (par->bpp < 1)
3222
         par->bpp = 1;
3223
   } else if (var->nonstd == FB_NONSTD_HAM)
3224
      par->bpp = par->bpp <= 6 ? 6 : 8;
3225
   else
3226
      return(-EINVAL);
3227
 
3228
   upper = var->upper_margin;
3229
   lower = var->lower_margin;
3230
   hslen = var->hsync_len;
3231
   vslen = var->vsync_len;
3232
 
3233
   par->vmode = var->vmode;
3234
   switch (par->vmode & FB_VMODE_MASK) {
3235
      case FB_VMODE_NONINTERLACED:
3236
         line_shift_incd = 1;
3237
         break;
3238
      case FB_VMODE_INTERLACED:
3239
         line_shift_incd = 0;
3240
         if (par->yres & 1)
3241
            par->yres++;               /* even */
3242
         if (upper & 1)
3243
            upper++;                   /* even */
3244
         if (!(lower & 1))
3245
            lower++;                   /* odd */
3246
         if (vslen & 1)
3247
            vslen++;                   /* even */
3248
         break;
3249
      case FB_VMODE_DOUBLE:
3250
         line_shift_incd = 2;
3251
         break;
3252
      default:
3253
         return(-EINVAL);
3254
         break;
3255
   }
3256
 
3257
   par->xoffset = var->xoffset;
3258
   par->yoffset = var->yoffset;
3259
   if (par->vmode & FB_VMODE_YWRAP) {
3260
      if (par->xoffset || par->yoffset < 0 || par->yoffset >= par->yres)
3261
         return(-EINVAL);
3262
   } else {
3263
      if (par->xoffset < 0 || par->xoffset+par->xres > par->vxres ||
3264
          par->yoffset < 0 || par->yoffset+par->yres > par->vyres)
3265
         return(-EINVAL);
3266
   }
3267
 
3268
   if (var->sync & FB_SYNC_BROADCAST) {
3269
      if (hslen || vslen)
3270
         return(-EINVAL);
3271
   } else {
3272
      hslen = hslen < 1 ? 1 : hslen;
3273
      vslen = vslen < 1 ? 1 : vslen;
3274
   }
3275
 
3276
   /*
3277
    *    Check the Memory Requirements
3278
    */
3279
 
3280
   if (par->vxres*par->vyres*par->bpp > videomemorysize<<3)
3281
      return(-EINVAL);
3282
 
3283
   /*
3284
    *    Normalize all values:
3285
    *
3286
    *      - horizontal: in 35 ns (SHRES) pixels
3287
    *      - vertical: in non-interlaced scanlines
3288
    */
3289
 
3290
   xres_n = par->xres<<clk_shift;
3291
   xoffset_n = par->xoffset<<clk_shift;
3292
   yres_n = par->yres<<line_shift_incd>>1;
3293
 
3294
   left_n = var->left_margin<<clk_shift;
3295
   right_n = var->right_margin<<clk_shift;
3296
   hslen_n = hslen<<clk_shift;
3297
   upper_n = upper<<line_shift_incd>>1;
3298
   lower_n = lower<<line_shift_incd>>1;
3299
   vslen_n = vslen<<line_shift_incd>>1;
3300
 
3301
   /*
3302
    *    Vertical and Horizontal Timings
3303
    */
3304
 
3305
   par->bplcon3 = sprpixmode[clk_shift];
3306
aga_calculate_timings:
3307
   if (var->sync & FB_SYNC_BROADCAST) {
3308
      if (upper_n+yres_n+lower_n == PAL_WINDOW_V) {
3309
         /* PAL video mode */
3310
         diwstrt_v = PAL_DIWSTRT_V+upper_n;
3311
         diwstop_v = diwstrt_v+yres_n;
3312
         diwstrt_h = PAL_DIWSTRT_H+left_n;
3313
         diwstop_h = diwstrt_h+xres_n+1;
3314
         par->htotal = htotal2hw(PAL_HTOTAL);
3315
         hrate = 15625;
3316
         vrate = 50;
3317
         par->beamcon0 = BMC0_PAL;
3318
      } else if (upper_n+yres_n+lower_n == NTSC_WINDOW_V) {
3319
         /* NTSC video mode */
3320
         diwstrt_v = NTSC_DIWSTRT_V+upper_n;
3321
         diwstop_v = diwstrt_v+yres_n;
3322
         diwstrt_h = NTSC_DIWSTRT_H+left_n;
3323
         diwstop_h = diwstrt_h+xres_n+1;
3324
         par->htotal = htotal2hw(NTSC_HTOTAL);
3325
         hrate = 15750;
3326
         vrate = 60;
3327
         par->beamcon0 = 0;
3328
      } else
3329
         return(-EINVAL);
3330
   } else {
3331
      /* Programmable video mode */
3332
      vsstrt = lower_n;
3333
      vsstop = vsstrt+vslen_n;
3334
      diwstrt_v = vsstop+upper_n;
3335
      diwstop_v = diwstrt_v+yres_n;
3336
      vtotal = diwstop_v;
3337
      hslen_n = up8(hslen_n);
3338
      htotal = up8(left_n+xres_n+right_n+hslen_n);
3339
      if (vtotal > 2048 || htotal > 2048)
3340
         return(-EINVAL);
3341
      right_n = htotal-left_n-xres_n-hslen_n;
3342
      hsstrt = down8(right_n+4);
3343
      hsstop = hsstrt+hslen_n;
3344
      diwstop_h = htotal+hsstrt-right_n+1;
3345
      diwstrt_h = diwstop_h-xres_n-1;
3346
      hrate = (amiga_masterclock+htotal/2)/htotal;
3347
      vrate = (amiga_masterclock+htotal*vtotal/2)/(htotal*vtotal);
3348
      par->bplcon3 |= BPC3_BRDRBLNK | BPC3_EXTBLKEN;
3349
      par->beamcon0 = BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS |
3350
                      BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN |
3351
                      BMC0_PAL | BMC0_VARCSYEN;
3352
      if (var->sync & FB_SYNC_HOR_HIGH_ACT)
3353
         par->beamcon0 |= BMC0_HSYTRUE;
3354
      if (var->sync & FB_SYNC_VERT_HIGH_ACT)
3355
         par->beamcon0 |= BMC0_VSYTRUE;
3356
      if (var->sync & FB_SYNC_COMP_HIGH_ACT)
3357
         par->beamcon0 |= BMC0_CSYTRUE;
3358
      par->htotal = htotal2hw(htotal);
3359
      par->hsstrt = hsstrt2hw(hsstrt);
3360
      par->hsstop = hsstop2hw(hsstop);
3361
      par->vtotal = vtotal2hw(vtotal);
3362
      par->vsstrt = vsstrt2hw(vsstrt);
3363
      par->vsstop = vsstop2hw(vsstop);
3364
      par->hcenter = par->hsstrt+(par->htotal>>1);
3365
   }
3366
   par->diwstrt_v = diwstrt_v;
3367
   par->diwstrt_h = diwstrt_h;
3368
   par->crsr_x = 0;
3369
   par->crsr_y = 0;
3370
 
3371
   /*
3372
    *    DMA Timings
3373
    */
3374
 
3375
   ddfmin = down64(xoffset_n);
3376
   ddfmax = up64(xoffset_n+xres_n);
3377
   hscroll = diwstrt_h-68-mod64(xoffset_n);
3378
   ddfstrt = down64(hscroll);
3379
   if (ddfstrt < 128) {
3380
      right_n += (128-hscroll);
3381
      /* Prevent an infinite loop */
3382
      if (loopcnt++)
3383
         return(-EINVAL);
3384
      goto aga_calculate_timings;
3385
   }
3386
   hscroll -= ddfstrt;
3387
   ddfstop = ddfstrt+ddfmax-ddfmin-(64<<clk_shift);
3388
 
3389
   /*
3390
    *    Bitplane calculations
3391
    */
3392
 
3393
   if (amifb_ilbm) {
3394
      par->next_plane = div8(par->vxres);
3395
      par->next_line = par->bpp*par->next_plane;
3396
   } else {
3397
      par->next_line = div8(par->vxres);
3398
      par->next_plane = par->vyres*par->next_line;
3399
   }
3400
   par->bplpt0 = ZTWO_PADDR((u_long)videomemory+div8(ddfmin>>clk_shift)+
3401
                            par->yoffset*par->next_line);
3402
   par->bpl1mod = par->next_line-div8((ddfmax-ddfmin)>>clk_shift);
3403
   par->bpl2mod = par->bpl1mod;
3404
 
3405
   /*
3406
    *    Hardware Register Values
3407
    */
3408
 
3409
   par->bplcon0 = BPC0_COLOR | BPC0_ECSENA | bplpixmode[clk_shift];
3410
   if (par->bpp == 8)
3411
      par->bplcon0 |= BPC0_BPU3;
3412
   else
3413
      par->bplcon0 |= par->bpp<<12;
3414
   if (var->nonstd == FB_NONSTD_HAM)
3415
      par->bplcon0 |= BPC0_HAM;
3416
   if (var->sync & FB_SYNC_EXT)
3417
      par->bplcon0 |= BPC0_ERSY;
3418
   par->bplcon1 = hscroll2hw(hscroll);
3419
   par->diwstrt = diwstrt2hw(diwstrt_h, diwstrt_v);
3420
   par->diwstop = diwstop2hw(diwstop_h, diwstop_v);
3421
   par->diwhigh = diw2hw_high(diwstrt_h, diwstrt_v, distop_h, diwstop_v);
3422
   par->ddfstrt = ddfstrt2hw(ddfstrt);
3423
   par->ddfstop = ddfstop2hw(ddfstop);
3424
   par->fmode = FMODE_SPAGEM | FMODE_SPR32 | FMODE_BPAGEM | FMODE_BPL32;
3425
 
3426
   switch (par->vmode & FB_VMODE_MASK) {
3427
      case FB_VMODE_INTERLACED:
3428
         par->bpl1mod += par->next_line;
3429
         par->bpl2mod += par->next_line;
3430
         par->bplcon0 |= BPC0_LACE;
3431
         break;
3432
      case FB_VMODE_DOUBLE:
3433
         par->bpl1mod -= par->next_line;
3434
         par->fmode |= FMODE_SSCAN2 | FMODE_BSCAN2;
3435
         break;
3436
   }
3437
 
3438
   if (hrate < hfmin || hrate > hfmax || vrate < vfmin || vrate > vfmax)
3439
      return(-EINVAL);
3440
 
3441
   return(0);
3442
}
3443
 
3444
 
3445
   /*
3446
    *    Fill the `var' structure based on the values in `par' and maybe
3447
    *    other values read out of the hardware.
3448
    */
3449
 
3450
static int aga_encode_var(struct fb_var_screeninfo *var,
3451
                          struct amiga_fb_par *par)
3452
{
3453
   u_short clk_shift, line_shift_incd;
3454
   u_long left, right, upper, lower, hslen, vslen;
3455
   u_short diwstop_h, diwstop_v;
3456
   u_short hsstrt, vsstrt, hsstop, vsstop, htotal;
3457
   int i;
3458
 
3459
   var->xres = par->xres;
3460
   var->yres = par->yres;
3461
   var->xres_virtual = par->vxres;
3462
   var->yres_virtual = par->vyres;
3463
   var->xoffset = par->xoffset;
3464
   var->yoffset = par->yoffset;
3465
 
3466
   var->bits_per_pixel = par->bpp;
3467
   var->grayscale = 0;
3468
 
3469
   var->red.offset = 0;
3470
   var->red.length = 8;
3471
   var->red.msb_right = 0;
3472
   var->blue = var->green = var->red;
3473
   var->transp.offset = 0;
3474
   var->transp.length = 0;
3475
   var->transp.msb_right = 0;
3476
 
3477
   if (par->bplcon0 & BPC0_HAM)
3478
      var->nonstd = FB_NONSTD_HAM;
3479
   else
3480
      var->nonstd = 0;
3481
   var->activate = 0;
3482
 
3483
   var->height = -1;
3484
   var->width = -1;
3485
   var->accel = FB_ACCEL_NONE;
3486
 
3487
   clk_shift = par->clk_shift;
3488
   var->pixclock = pixclock[clk_shift];
3489
 
3490
   diwstop_h = hw2diwstop_h(par->diwstop, par->diwhigh);
3491
   if (par->beamcon0 & BMC0_VARBEAMEN) {
3492
      hsstrt = hw2hsstrt(par->hsstrt);
3493
      vsstrt = hw2vsstrt(par->vsstrt);
3494
      hsstop = hw2hsstop(par->hsstop);
3495
      vsstop = hw2vsstop(par->vsstop);
3496
      htotal = hw2htotal(par->htotal);
3497
      left = par->diwstrt_h-hsstop;
3498
      right = htotal+hsstrt-diwstop_h+1;
3499
      hslen = hsstop-hsstrt;
3500
      upper = par->diwstrt_v-vsstop;
3501
      lower = vsstrt;
3502
      vslen = vsstop-vsstrt;
3503
      var->sync = 0;
3504
   } else {
3505
      diwstop_v = hw2diwstop_v(par->diwstop, par->diwhigh);
3506
      if (par->beamcon0 & BMC0_PAL) {
3507
         left = par->diwstrt_h-PAL_DIWSTRT_H;
3508
         right = PAL_DIWSTRT_H+PAL_WINDOW_H-diwstop_h+1;
3509
         upper = par->diwstrt_v-PAL_DIWSTRT_V;
3510
         lower = PAL_DIWSTRT_V+PAL_WINDOW_V-diwstop_v;
3511
      } else {
3512
         left = par->diwstrt_h-NTSC_DIWSTRT_H;
3513
         right = NTSC_DIWSTRT_H+NTSC_WINDOW_H-diwstop_h;
3514
         upper = par->diwstrt_v-NTSC_DIWSTRT_V;
3515
         lower = NTSC_DIWSTRT_V+NTSC_WINDOW_V-diwstop_v;
3516
      }
3517
      hslen = 0;
3518
      vslen = 0;
3519
      var->sync = FB_SYNC_BROADCAST;
3520
   }
3521
 
3522
   if (par->bplcon0 & BPC0_ERSY)
3523
      var->sync |= FB_SYNC_EXT;
3524
   if (par->beamcon0 & BMC0_HSYTRUE)
3525
      var->sync |= FB_SYNC_HOR_HIGH_ACT;
3526
   if (par->beamcon0 & BMC0_VSYTRUE)
3527
      var->sync |= FB_SYNC_VERT_HIGH_ACT;
3528
   if (par->beamcon0 & BMC0_CSYTRUE)
3529
      var->sync |= FB_SYNC_COMP_HIGH_ACT;
3530
 
3531
   switch (par->vmode & FB_VMODE_MASK) {
3532
      case FB_VMODE_NONINTERLACED:
3533
         line_shift_incd = 1;
3534
         break;
3535
      case FB_VMODE_INTERLACED:
3536
         line_shift_incd = 0;
3537
         break;
3538
      case FB_VMODE_DOUBLE:
3539
         line_shift_incd = 2;
3540
         break;
3541
   }
3542
 
3543
   var->left_margin = left>>clk_shift;
3544
   var->right_margin = right>>clk_shift;
3545
   var->upper_margin = upper<<1>>line_shift_incd;
3546
   var->lower_margin = lower<<1>>line_shift_incd;
3547
   var->hsync_len = hslen>>clk_shift;
3548
   var->vsync_len = vslen<<1>>line_shift_incd;
3549
   var->vmode = par->vmode;
3550
   for (i = 0; i < arraysize(var->reserved); i++)
3551
      var->reserved[i] = 0;
3552
 
3553
   return(0);
3554
}
3555
 
3556
 
3557
   /*
3558
    *    Read a single color register and split it into
3559
    *    colors/transparent. Return != 0 for invalid regno.
3560
    */
3561
 
3562
static int aga_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
3563
                         u_int *transp)
3564
{
3565
   if (regno > 255)
3566
      return(1);
3567
 
3568
   *red = palette[regno].red;
3569
   *green = palette[regno].green;
3570
   *blue = palette[regno].blue;
3571
   return(0);
3572
}
3573
 
3574
 
3575
   /*
3576
    *    Set a single color register. The values supplied are already
3577
    *    rounded down to the hardware's capabilities (according to the
3578
    *    entries in the var structure). Return != 0 for invalid regno.
3579
    */
3580
 
3581
static int aga_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
3582
                         u_int transp)
3583
{
3584
   u_short bplcon3 = current_par.bplcon3;
3585
 
3586
   if (regno > 255)
3587
      return(1);
3588
 
3589
   /*
3590
    *    Update the corresponding Hardware Color Register, unless it's Color
3591
    *    Register 0 and the screen is blanked.
3592
    *
3593
    *    The cli()/sti() pair is here to protect bplcon3 from being changed by
3594
    *    the VBlank interrupt routine.
3595
    */
3596
 
3597
   cli();
3598
   if (regno || !is_blanked) {
3599
      custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000);
3600
      custom.color[regno&31] = rgb2hw_high(red, green, blue);
3601
      custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000) | BPC3_LOCT;
3602
      custom.color[regno&31] = rgb2hw_low(red, green, blue);
3603
      custom.bplcon3 = bplcon3;
3604
   }
3605
   sti();
3606
 
3607
   palette[regno].red = red;
3608
   palette[regno].green = green;
3609
   palette[regno].blue = blue;
3610
 
3611
   return(0);
3612
}
3613
 
3614
 
3615
   /*
3616
    *    Pan or Wrap the Display
3617
    *
3618
    *    This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
3619
    *    in `var'.
3620
    */
3621
 
3622
static int aga_pan_display(struct fb_var_screeninfo *var,
3623
                           struct amiga_fb_par *par)
3624
{
3625
   int xoffset, yoffset, vmode, xres_n, xoffset_n;
3626
   u_short clk_shift, line_shift_incd;
3627
   u_long ddfmin, ddfmax, ddfstrt, ddfstop, hscroll;
3628
 
3629
   xoffset = var->xoffset;
3630
   yoffset = var->yoffset;
3631
   if (var->vmode & FB_VMODE_YWRAP) {
3632
      if (hw2ddfstrt(par->ddfstrt) < (par->bpp-1)*64 || xoffset ||
3633
          yoffset < 0 || yoffset >= par->yres)
3634
         return(-EINVAL);
3635
      vmode = par->vmode | FB_VMODE_YWRAP;
3636
   } else {
3637
      if (par->diwstrt_h < 323)
3638
         xoffset = up64(xoffset);
3639
      if (xoffset < 0 || xoffset+par->xres > par->vxres ||
3640
          yoffset < 0 || yoffset+par->yres > par->vyres)
3641
         return(-EINVAL);
3642
      vmode = par->vmode & ~FB_VMODE_YWRAP;
3643
   }
3644
 
3645
   clk_shift = par->clk_shift;
3646
   switch (vmode & FB_VMODE_MASK) {
3647
      case FB_VMODE_NONINTERLACED:
3648
         line_shift_incd = 1;
3649
         break;
3650
      case FB_VMODE_INTERLACED:
3651
         line_shift_incd = 0;
3652
         break;
3653
      case FB_VMODE_DOUBLE:
3654
         line_shift_incd = 2;
3655
         break;
3656
   }
3657
   xres_n = par->xres<<clk_shift;
3658
   xoffset_n = xoffset<<clk_shift;
3659
 
3660
   /*
3661
    *    DMA timings
3662
    */
3663
 
3664
   ddfmin = down64(xoffset_n);
3665
   ddfmax = up64(xoffset_n+xres_n);
3666
   hscroll = par->diwstrt_h-68-mod64(xoffset_n);
3667
   ddfstrt = down64(hscroll);
3668
   if (ddfstrt < 128)
3669
      return(-EINVAL);
3670
   hscroll -= ddfstrt;
3671
   ddfstop = ddfstrt+ddfmax-ddfmin-(64<<clk_shift);
3672
   par->bplcon1 = hscroll2hw(hscroll);
3673
   par->ddfstrt = ddfstrt2hw(ddfstrt);
3674
   par->ddfstop = ddfstop2hw(ddfstop);
3675
 
3676
   /*
3677
    *    Bitplane calculations
3678
    */
3679
 
3680
   par->bplpt0 = ZTWO_PADDR((u_long)videomemory+div8(ddfmin>>clk_shift)+
3681
                            yoffset*par->next_line);
3682
   par->bpl1mod = par->next_line-div8((ddfmax-ddfmin)>>clk_shift);
3683
   par->bpl2mod = par->bpl1mod;
3684
   switch (vmode & FB_VMODE_MASK) {
3685
      case FB_VMODE_INTERLACED:
3686
         par->bpl1mod += par->next_line;
3687
         par->bpl2mod += par->next_line;
3688
         break;
3689
      case FB_VMODE_DOUBLE:
3690
         par->bpl1mod -= par->next_line;
3691
         break;
3692
   }
3693
 
3694
   par->xoffset = var->xoffset = xoffset;
3695
   par->yoffset = var->yoffset = yoffset;
3696
   par->vmode = var->vmode = vmode;
3697
   return(0);
3698
}
3699
 
3700
 
3701
   /*
3702
    *    Change the video mode (called by VBlank interrupt)
3703
    */
3704
 
3705
void aga_do_vmode(void)
3706
{
3707
   struct amiga_fb_par *par = &current_par;
3708
 
3709
   /*
3710
    *    Rebuild the dynamic part of the Copper List and activate the right
3711
    *    Copper List as soon as possible
3712
    *
3713
    *    Make sure we're in a Long Frame if the video mode is interlaced.
3714
    *    This is always the case if we already were in an interlaced mode,
3715
    *    since then the VBlank only calls us during a Long Frame.
3716
    *    But this _is_ necessary if we're switching from a non-interlaced
3717
    *    to an interlaced mode.
3718
    */
3719
 
3720
   if ((par->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
3721
      custom.vposw = 0x8000;
3722
      aga_build_clist_dyn(clist_lof, clist_shf, 0, par);
3723
      custom.cop2lc = (u_short *)ZTWO_PADDR(clist_lof);
3724
      aga_build_clist_dyn(clist_shf, clist_lof, 1, par);
3725
   } else {
3726
      aga_build_clist_dyn(clist_lof, NULL, 0, par);
3727
      custom.cop2lc = (u_short *)ZTWO_PADDR(clist_lof);
3728
   }
3729
 
3730
   /*
3731
    *    Update the hardware registers
3732
    */
3733
 
3734
   if (full_vmode_change) {
3735
      custom.fmode = par->fmode;
3736
      custom.beamcon0 = par->beamcon0;
3737
      if (par->beamcon0 & BMC0_VARBEAMEN) {
3738
         custom.htotal = par->htotal;
3739
         custom.vtotal = par->vtotal;
3740
         custom.hsstrt = par->hsstrt;
3741
         custom.hsstop = par->hsstop;
3742
         custom.hbstrt = par->hsstrt;
3743
         custom.hbstop = par->hsstop;
3744
         custom.vsstrt = par->vsstrt;
3745
         custom.vsstop = par->vsstop;
3746
         custom.vbstrt = par->vsstrt;
3747
         custom.vbstop = par->vsstop;
3748
         custom.hcenter = par->hcenter;
3749
      }
3750
      custom.bplcon3 = par->bplcon3;
3751
      full_vmode_change = 0;
3752
 
3753
      /*
3754
       *    The minimum period for audio depends on htotal (for OCS/ECS/AGA)
3755
       */
3756
 
3757
      if (boot_info.bi_amiga.chipset != CS_STONEAGE)
3758
         amiga_audio_min_period = (par->htotal>>1)+1;
3759
   }
3760
   custom.ddfstrt = par->ddfstrt;
3761
   custom.ddfstop = par->ddfstop;
3762
   custom.bpl1mod = par->bpl1mod;
3763
   custom.bpl2mod = par->bpl2mod;
3764
   custom.bplcon1 = par->bplcon1;
3765
 
3766
   /*
3767
    *    Update the Frame Header Copper List
3768
    */
3769
 
3770
   aga_update_clist_hdr(clist_hdr, par);
3771
}
3772
 
3773
 
3774
   /*
3775
    *    (Un)Blank the screen (called by VBlank interrupt)
3776
    */
3777
 
3778
void aga_do_blank(int blank)
3779
{
3780
   struct amiga_fb_par *par = &current_par;
3781
   u_short bplcon3 = par->bplcon3;
3782
   u_char red, green, blue;
3783
 
3784
   if (blank) {
3785
      custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
3786
      red = green = blue = 0;
3787
      if (pwrsave && par->beamcon0 & BMC0_VARBEAMEN) {
3788
         /* VESA suspend mode, switch off HSYNC */
3789
         custom.hsstrt = par->htotal+2;
3790
         custom.hsstop = par->htotal+2;
3791
      }
3792
   } else {
3793
      custom.dmacon = DMAF_SETCLR | DMAF_RASTER;
3794
      red = palette[0].red;
3795
      green = palette[0].green;
3796
      blue = palette[0].blue;
3797
      if (pwrsave && par->beamcon0 & BMC0_VARBEAMEN) {
3798
         custom.hsstrt = par->hsstrt;
3799
         custom.hsstop = par->hsstop;
3800
      }
3801
   }
3802
   custom.bplcon3 = bplcon3;
3803
   custom.color[0] = rgb2hw_high(red, green, blue);
3804
   custom.bplcon3 = bplcon3 | BPC3_LOCT;
3805
   custom.color[0] = rgb2hw_low(red, green, blue);
3806
   custom.bplcon3 = bplcon3;
3807
 
3808
   is_blanked = blank;
3809
}
3810
 
3811
 
3812
   /*
3813
    *    Move the cursor (called by VBlank interrupt)
3814
    */
3815
 
3816
void aga_do_movecursor(void)
3817
{
3818
   struct amiga_fb_par *par = &current_par;
3819
   struct aga_cursorsprite *sprite = (struct aga_cursorsprite *)lofsprite;
3820
   long hs, vs, ve;
3821
   u_short s1, s2, is_double = 0;
3822
 
3823
   if (par->crsr_x <= -64 || par->crsr_x >= par->xres || par->crsr_y <= -64 ||
3824
       par->crsr_y >= par->yres)
3825
      hs = vs = ve = 0;
3826
   else {
3827
      hs = par->diwstrt_h-4+(par->crsr_x<<par->clk_shift);
3828
      vs = par->crsr_y;
3829
      ve = min(vs+64, par->yres);
3830
      switch (par->vmode & FB_VMODE_MASK) {
3831
         case FB_VMODE_INTERLACED:
3832
            vs >>= 1;
3833
            ve >>= 1;
3834
            break;
3835
         case FB_VMODE_DOUBLE:
3836
            vs <<= 1;
3837
            ve <<= 1;
3838
            is_double = 1;
3839
            break;
3840
      }
3841
      vs += par->diwstrt_v;
3842
      ve += par->diwstrt_v;
3843
   }
3844
   s1 = spr2hw_pos(vs, hs);
3845
   if (is_double)
3846
      s1 |= 0x80;
3847
   s2 = spr2hw_ctl(vs, hs, ve);
3848
   sprite->sprpos = s1;
3849
   sprite->sprctl = s2;
3850
 
3851
   /*
3852
    *    TODO: Special cases:
3853
    *
3854
    *      - Interlaced: fill position in in both lofsprite & shfsprite
3855
    *                    swap lofsprite & shfsprite on odd lines
3856
    *
3857
    *      - Doublescan: OK?
3858
    *
3859
    *      - ve <= bottom of display: OK?
3860
    */
3861
}
3862
 
3863
 
3864
   /*
3865
    *    Flash the cursor (called by VBlank interrupt)
3866
    */
3867
 
3868
void aga_do_flashcursor(void)
3869
{
3870
#if 1
3871
   static int cursorcount = 0;
3872
   static int cursorstate = 0;
3873
 
3874
   switch (cursormode) {
3875
      case FB_CURSOR_OFF:
3876
         custom.dmacon = DMAF_SPRITE;
3877
         break;
3878
      case FB_CURSOR_ON:
3879
         custom.dmacon = DMAF_SETCLR | DMAF_SPRITE;
3880
         break;
3881
      case FB_CURSOR_FLASH:
3882
         if (cursorcount)
3883
            cursorcount--;
3884
         else {
3885
            cursorcount = CRSR_RATE;
3886
            if ((cursorstate = !cursorstate))
3887
               custom.dmacon = DMAF_SETCLR | DMAF_SPRITE;
3888
            else
3889
               custom.dmacon = DMAF_SPRITE;
3890
         }
3891
         break;
3892
   }
3893
#endif
3894
}
3895
 
3896
 
3897
#if 1
3898
static int aga_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix, int con)
3899
{
3900
#if 0
3901
   if (ddfstrt >= 192) {
3902
#endif
3903
      fix->crsr_width = 64;
3904
      fix->crsr_height = 64;
3905
      fix->crsr_xsize = 64;
3906
      fix->crsr_ysize = 64;
3907
      fix->crsr_color1 = 17;
3908
      fix->crsr_color2 = 18;
3909
#if 0
3910
   } else {
3911
      fix->crsr_width = 0;
3912
      fix->crsr_height = 0;
3913
      fix->crsr_xsize = 0;
3914
      fix->crsr_ysize = 0;
3915
      fix->crsr_color1 = 0;
3916
      fix->crsr_color2 = 0;
3917
   }
3918
#endif
3919
   return(0);
3920
}
3921
 
3922
 
3923
static int aga_get_var_cursorinfo(struct fb_var_cursorinfo *var, int con)
3924
{
3925
   struct aga_cursorsprite *sprite = (struct aga_cursorsprite *)lofsprite;
3926
 
3927
   /* TODO: interlaced sprites */
3928
   memcpy(var->data, sprite->u.nonlaced.data, sizeof(var->data));
3929
   return(0);
3930
}
3931
 
3932
 
3933
static int aga_set_var_cursorinfo(struct fb_var_cursorinfo *var, int con)
3934
{
3935
   struct aga_cursorsprite *sprite = (struct aga_cursorsprite *)lofsprite;
3936
 
3937
   /* TODO: interlaced sprites */
3938
   memcpy(sprite->u.nonlaced.data, var->data, sizeof(var->data));
3939
   return(0);
3940
}
3941
 
3942
 
3943
static int aga_get_cursorstate(struct fb_cursorstate *state, int con)
3944
{
3945
   state->xoffset = current_par.crsr_x;
3946
   state->yoffset = current_par.crsr_y;
3947
   state->mode = cursormode;
3948
   return(0);
3949
}
3950
 
3951
 
3952
static int aga_set_cursorstate(struct fb_cursorstate *state, int con)
3953
{
3954
   current_par.crsr_x = state->xoffset;
3955
   current_par.crsr_y = state->yoffset;
3956
   cursormode = state->mode;
3957
   do_movecursor = 1;
3958
   return(0);
3959
}
3960
#endif
3961
 
3962
 
3963
   /*
3964
    *    Build the Frame Header Copper List
3965
    */
3966
 
3967
static __inline__ void aga_build_clist_hdr(struct clist_hdr *cop)
3968
{
3969
   int i, j;
3970
   u_long p;
3971
 
3972
   cop->bplcon0.l = CMOVE(BPC0_COLOR | BPC0_SHRES | BPC0_ECSENA, bplcon0);
3973
   cop->diwstrt.l = CMOVE(0x0181, diwstrt);
3974
   cop->diwstop.l = CMOVE(0x0281, diwstop);
3975
   cop->diwhigh.l = CMOVE(0x0000, diwhigh);
3976
   for (i = 0; i < 8; i++)
3977
      cop->sprfix[i].l = CMOVE(0, spr[i].pos);
3978
   for (i = 0, j = 0; i < 8; i++) {
3979
      p = ZTWO_PADDR(dummysprite);
3980
      cop->sprstrtup[j++].l = CMOVE(highw(p), sprpt[i]);
3981
      cop->sprstrtup[j++].l = CMOVE2(loww(p), sprpt[i]);
3982
   }
3983
   cop->wait.l = CWAIT(0, 12);         /* Initial value */
3984
   cop->jump.l = CMOVE(0, copjmp2);
3985
   cop->wait_forever.l = CEND;
3986
}
3987
 
3988
 
3989
   /*
3990
    *    Update the Frame Header Copper List
3991
    */
3992
 
3993
static __inline__ void aga_update_clist_hdr(struct clist_hdr *cop,
3994
                                            struct amiga_fb_par *par)
3995
{
3996
   cop->bplcon0.l = CMOVE(~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) &
3997
                          par->bplcon0, bplcon0);
3998
   cop->wait.l = CWAIT(0, par->diwstrt_v-2);
3999
}
4000
 
4001
 
4002
   /*
4003
    *    Build the Long Frame/Short Frame Copper List
4004
    */
4005
 
4006
static void aga_build_clist_dyn(struct clist_dyn *cop,
4007
                                struct clist_dyn *othercop, u_short shf,
4008
                                struct amiga_fb_par *par)
4009
{
4010
   u_long y_wrap, bplpt0, p, line;
4011
   int i, j = 0;
4012
 
4013
   cop->diwstrt.l = CMOVE(par->diwstrt, diwstrt);
4014
   cop->diwstop.l = CMOVE(par->diwstop, diwstop);
4015
   cop->diwhigh.l = CMOVE(par->diwhigh, diwhigh);
4016
   cop->bplcon0.l = CMOVE(par->bplcon0, bplcon0);
4017
 
4018
   /* Point Sprite 0 at cursor sprite */
4019
 
4020
   /* TODO: This should depend on the vertical sprite position too */
4021
   if (shf) {
4022
      p = ZTWO_PADDR(shfsprite);
4023
      cop->sprpt[0].l = CMOVE(highw(p), sprpt[0]);
4024
      cop->sprpt[1].l = CMOVE2(loww(p), sprpt[0]);
4025
   } else {
4026
      p = ZTWO_PADDR(lofsprite);
4027
      cop->sprpt[0].l = CMOVE(highw(p), sprpt[0]);
4028
      cop->sprpt[1].l = CMOVE2(loww(p), sprpt[0]);
4029
   }
4030
 
4031
   bplpt0 = par->bplpt0;
4032
   if (shf)
4033
      bplpt0 += par->next_line;
4034
   y_wrap = par->vmode & FB_VMODE_YWRAP ? par->yoffset : 0;
4035
 
4036
   /* Set up initial bitplane ptrs */
4037
 
4038
   for (i = 0, p = bplpt0; i < par->bpp; i++, p += par->next_plane) {
4039
      cop->rest[j++].l = CMOVE(highw(p), bplpt[i]);
4040
      cop->rest[j++].l = CMOVE2(loww(p), bplpt[i]);
4041
   }
4042
 
4043
   if (y_wrap) {
4044
      bplpt0 -= y_wrap*par->next_line;
4045
      line = par->yres-y_wrap;
4046
      switch (par->vmode & FB_VMODE_MASK) {
4047
         case FB_VMODE_INTERLACED:
4048
            line >>= 1;
4049
            break;
4050
         case FB_VMODE_DOUBLE:
4051
            line <<= 1;
4052
            break;
4053
      }
4054
      line += par->diwstrt_v;
4055
 
4056
      /* Handle skipping over 256-line chunks */
4057
 
4058
      while (line > 256) {
4059
         /* Hardware limitation - 8 bit counter */
4060
         cop->rest[j++].l = CWAIT(par->htotal-4, 255);
4061
         /* Wait(0, 0) - make sure we're in the new segment */
4062
         cop->rest[j++].l = CWAIT(0, 0);
4063
         line -= 256;
4064
      }
4065
      cop->rest[j++].l = CWAIT(par->htotal-11, line-1);
4066
 
4067
      for (i = 0, p = bplpt0; i < par->bpp; i++, p += par->next_plane) {
4068
         cop->rest[j++].l = CMOVE(highw(p), bplpt[i]);
4069
         cop->rest[j++].l = CMOVE2(loww(p), bplpt[i]);
4070
      }
4071
   }
4072
 
4073
   if (othercop) {
4074
      p = ZTWO_PADDR(othercop);
4075
      cop->rest[j++].l = CMOVE(highw(p), cop2lc);
4076
      cop->rest[j++].l = CMOVE2(loww(p), cop2lc);
4077
   }
4078
 
4079
   /* End of Copper list */
4080
   cop->rest[j++].l = CEND;
4081
 
4082
   if (j > arraysize(cop->rest))
4083
      printk("aga_build_clist_dyn: copper list overflow (%d entries)\n", j);
4084
}
4085
#endif /* CONFIG_AMIFB_AGA */
4086
 
4087
 
4088
/* -------------------- Interfaces to hardware functions -------------------- */
4089
 
4090
 
4091
#ifdef CONFIG_AMIFB_OCS
4092
static struct fb_hwswitch ocs_switch = {
4093
   ocs_init, ocs_encode_fix, ocs_decode_var, ocs_encode_var, ocs_getcolreg,
4094
   ocs_setcolreg, ocs_pan_display, ocs_do_vmode, ocs_do_blank,
4095
   ocs_do_movecursor, ocs_do_flashcursor
4096
};
4097
#endif /* CONFIG_AMIFB_OCS */
4098
 
4099
#ifdef CONFIG_AMIFB_ECS
4100
static struct fb_hwswitch ecs_switch = {
4101
   ecs_init, ecs_encode_fix, ecs_decode_var, ecs_encode_var, ecs_getcolreg,
4102
   ecs_setcolreg, ecs_pan_display, ecs_do_vmode, ecs_do_blank,
4103
   ecs_do_movecursor, ecs_do_flashcursor
4104
};
4105
#endif /* CONFIG_AMIFB_ECS */
4106
 
4107
#ifdef CONFIG_AMIFB_AGA
4108
static struct fb_hwswitch aga_switch = {
4109
   aga_init, aga_encode_fix, aga_decode_var, aga_encode_var, aga_getcolreg,
4110
   aga_setcolreg, aga_pan_display, aga_do_vmode, aga_do_blank,
4111
   aga_do_movecursor, aga_do_flashcursor
4112
};
4113
#endif /* CONFIG_AMIFB_AGA */
4114
 
4115
 
4116
/* -------------------- Generic routines ------------------------------------ */
4117
 
4118
 
4119
   /*
4120
    *    Allocate, Clear and Align a Block of Chip Memory
4121
    */
4122
 
4123
static u_long chipalloc(u_long size)
4124
{
4125
   u_long ptr;
4126
 
4127
   size += PAGE_SIZE-1;
4128
   if (!(ptr = (u_long)amiga_chip_alloc(size)))
4129
      panic("No Chip RAM for frame buffer");
4130
   memset((void *)ptr, 0, size);
4131
   ptr = PAGE_ALIGN(ptr);
4132
 
4133
   return(ptr);
4134
}
4135
 
4136
 
4137
   /*
4138
    *    Fill the hardware's `par' structure.
4139
    */
4140
 
4141
static void amiga_fb_get_par(struct amiga_fb_par *par)
4142
{
4143
   if (current_par_valid)
4144
      *par = current_par;
4145
   else
4146
      fbhw->decode_var(&amiga_fb_predefined[amifb_mode], par);
4147
}
4148
 
4149
 
4150
static void amiga_fb_set_par(struct amiga_fb_par *par)
4151
{
4152
   do_vmode = 0;
4153
   current_par = *par;
4154
   full_vmode_change = 1;
4155
   do_vmode = 1;
4156
   current_par_valid = 1;
4157
}
4158
 
4159
 
4160
static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
4161
{
4162
   int err, activate;
4163
   struct amiga_fb_par par;
4164
 
4165
   if ((err = fbhw->decode_var(var, &par)))
4166
      return(err);
4167
   activate = var->activate;
4168
   if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
4169
      amiga_fb_set_par(&par);
4170
   fbhw->encode_var(var, &par);
4171
   var->activate = activate;
4172
   return(0);
4173
}
4174
 
4175
 
4176
   /*
4177
    *    Default Colormaps
4178
    */
4179
 
4180
static u_short red2[] =
4181
   { 0x0000, 0xc000 };
4182
static u_short green2[] =
4183
   { 0x0000, 0xc000 };
4184
static u_short blue2[] =
4185
   { 0x0000, 0xc000 };
4186
 
4187
static u_short red4[] =
4188
   { 0x0000, 0xc000, 0x8000, 0xffff };
4189
static u_short green4[] =
4190
   { 0x0000, 0xc000, 0x8000, 0xffff };
4191
static u_short blue4[] =
4192
   { 0x0000, 0xc000, 0x8000, 0xffff };
4193
 
4194
static u_short red8[] =
4195
   { 0x0000, 0x0000, 0x0000, 0x0000, 0xc000, 0xc000, 0xc000, 0xc000 };
4196
static u_short green8[] =
4197
   { 0x0000, 0x0000, 0xc000, 0xc000, 0x0000, 0x0000, 0xc000, 0xc000 };
4198
static u_short blue8[] =
4199
   { 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000 };
4200
 
4201
static u_short red16[] =
4202
   { 0x0000, 0x0000, 0x0000, 0x0000, 0xc000, 0xc000, 0xc000, 0xc000,
4203
     0x8000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff };
4204
static u_short green16[] =
4205
   { 0x0000, 0x0000, 0xc000, 0xc000, 0x0000, 0x0000, 0xc000, 0xc000,
4206
     0x8000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff };
4207
static u_short blue16[] =
4208
   { 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000,
4209
     0x8000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff };
4210
 
4211
 
4212
static struct fb_cmap default_2_colors =
4213
   { 0, 2, red2, green2, blue2, NULL };
4214
static struct fb_cmap default_8_colors =
4215
   { 0, 8, red8, green8, blue8, NULL };
4216
static struct fb_cmap default_4_colors =
4217
   { 0, 4, red4, green4, blue4, NULL };
4218
static struct fb_cmap default_16_colors =
4219
   { 0, 16, red16, green16, blue16, NULL };
4220
 
4221
 
4222
static struct fb_cmap *get_default_colormap(int bpp)
4223
{
4224
   switch (bpp) {
4225
      case 1:
4226
         return(&default_2_colors);
4227
         break;
4228
      case 2:
4229
         return(&default_4_colors);
4230
         break;
4231
      case 3:
4232
         return(&default_8_colors);
4233
         break;
4234
      default:
4235
         return(&default_16_colors);
4236
         break;
4237
   }
4238
}
4239
 
4240
 
4241
#define CNVT_TOHW(val,width)     ((((val)<<(width))+0x7fff-(val))>>16)
4242
#define CNVT_FROMHW(val,width)   (((width) ? ((((val)<<16)-(val)) / \
4243
                                              ((1<<(width))-1)) : 0))
4244
 
4245
static int do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
4246
                          int kspc)
4247
{
4248
   int i, start;
4249
   u_short *red, *green, *blue, *transp;
4250
   u_int hred, hgreen, hblue, htransp;
4251
 
4252
   red = cmap->red;
4253
   green = cmap->green;
4254
   blue = cmap->blue;
4255
   transp = cmap->transp;
4256
   start = cmap->start;
4257
   if (start < 0)
4258
      return(-EINVAL);
4259
   for (i = 0; i < cmap->len; i++) {
4260
      if (fbhw->getcolreg(start++, &hred, &hgreen, &hblue, &htransp))
4261
         return(0);
4262
      hred = CNVT_FROMHW(hred, var->red.length);
4263
      hgreen = CNVT_FROMHW(hgreen, var->green.length);
4264
      hblue = CNVT_FROMHW(hblue, var->blue.length);
4265
      htransp = CNVT_FROMHW(htransp, var->transp.length);
4266
      if (kspc) {
4267
         *red = hred;
4268
         *green = hgreen;
4269
         *blue = hblue;
4270
         if (transp)
4271
            *transp = htransp;
4272
      } else {
4273
         put_fs_word(hred, red);
4274
         put_fs_word(hgreen, green);
4275
         put_fs_word(hblue, blue);
4276
         if (transp)
4277
            put_fs_word(htransp, transp);
4278
      }
4279
      red++;
4280
      green++;
4281
      blue++;
4282
      if (transp)
4283
         transp++;
4284
   }
4285
   return(0);
4286
}
4287
 
4288
 
4289
static int do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
4290
                          int kspc)
4291
{
4292
   int i, start;
4293
   u_short *red, *green, *blue, *transp;
4294
   u_int hred, hgreen, hblue, htransp;
4295
 
4296
   red = cmap->red;
4297
   green = cmap->green;
4298
   blue = cmap->blue;
4299
   transp = cmap->transp;
4300
   start = cmap->start;
4301
 
4302
   if (start < 0)
4303
      return(-EINVAL);
4304
   for (i = 0; i < cmap->len; i++) {
4305
      if (kspc) {
4306
         hred = *red;
4307
         hgreen = *green;
4308
         hblue = *blue;
4309
         htransp = transp ? *transp : 0;
4310
      } else {
4311
         hred = get_fs_word(red);
4312
         hgreen = get_fs_word(green);
4313
         hblue = get_fs_word(blue);
4314
         htransp = transp ? get_fs_word(transp) : 0;
4315
      }
4316
      hred = CNVT_TOHW(hred, var->red.length);
4317
      hgreen = CNVT_TOHW(hgreen, var->green.length);
4318
      hblue = CNVT_TOHW(hblue, var->blue.length);
4319
      htransp = CNVT_TOHW(htransp, var->transp.length);
4320
      red++;
4321
      green++;
4322
      blue++;
4323
      if (transp)
4324
         transp++;
4325
      if (fbhw->setcolreg(start++, hred, hgreen, hblue, htransp))
4326
         return(0);
4327
   }
4328
   return(0);
4329
}
4330
 
4331
 
4332
static void do_install_cmap(int con)
4333
{
4334
   if (con != currcon)
4335
      return;
4336
   if (disp[con].cmap.len)
4337
      do_fb_set_cmap(&disp[con].cmap, &disp[con].var, 1);
4338
   else
4339
      do_fb_set_cmap(get_default_colormap(disp[con].var.bits_per_pixel),
4340
                                          &disp[con].var, 1);
4341
}
4342
 
4343
 
4344
static void memcpy_fs(int fsfromto, void *to, void *from, int len)
4345
{
4346
   switch (fsfromto) {
4347
      case 0:
4348
         memcpy(to, from, len);
4349
         return;
4350
      case 1:
4351
         memcpy_fromfs(to, from, len);
4352
         return;
4353
      case 2:
4354
         memcpy_tofs(to, from, len);
4355
         return;
4356
   }
4357
}
4358
 
4359
 
4360
static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
4361
{
4362
   int size;
4363
   int tooff = 0, fromoff = 0;
4364
 
4365
   if (to->start > from->start)
4366
      fromoff = to->start-from->start;
4367
   else
4368
      tooff = from->start-to->start;
4369
   size = to->len-tooff;
4370
   if (size > from->len-fromoff)
4371
      size = from->len-fromoff;
4372
   if (size < 0)
4373
      return;
4374
   size *= sizeof(u_short);
4375
   memcpy_fs(fsfromto, to->red+tooff, from->red+fromoff, size);
4376
   memcpy_fs(fsfromto, to->green+tooff, from->green+fromoff, size);
4377
   memcpy_fs(fsfromto, to->blue+tooff, from->blue+fromoff, size);
4378
   if (from->transp && to->transp)
4379
      memcpy_fs(fsfromto, to->transp+tooff, from->transp+fromoff, size);
4380
}
4381
 
4382
 
4383
static int alloc_cmap(struct fb_cmap *cmap, int len, int transp)
4384
{
4385
   int size = len*sizeof(u_short);
4386
 
4387
   if (cmap->len != len) {
4388
      if (cmap->red)
4389
         kfree(cmap->red);
4390
      if (cmap->green)
4391
         kfree(cmap->green);
4392
      if (cmap->blue)
4393
         kfree(cmap->blue);
4394
      if (cmap->transp)
4395
         kfree(cmap->transp);
4396
      cmap->red = cmap->green = cmap->blue = cmap->transp = NULL;
4397
      cmap->len = 0;
4398
      if (!len)
4399
         return(0);
4400
      if (!(cmap->red = kmalloc(size, GFP_ATOMIC)))
4401
         return(-1);
4402
      if (!(cmap->green = kmalloc(size, GFP_ATOMIC)))
4403
         return(-1);
4404
      if (!(cmap->blue = kmalloc(size, GFP_ATOMIC)))
4405
         return(-1);
4406
      if (transp) {
4407
         if (!(cmap->transp = kmalloc(size, GFP_ATOMIC)))
4408
            return(-1);
4409
      } else
4410
         cmap->transp = NULL;
4411
   }
4412
   cmap->start = 0;
4413
   cmap->len = len;
4414
   copy_cmap(get_default_colormap(len), cmap, 0);
4415
   return(0);
4416
}
4417
 
4418
 
4419
   /*
4420
    *    Get the Fixed Part of the Display
4421
    */
4422
 
4423
static int amiga_fb_get_fix(struct fb_fix_screeninfo *fix, int con)
4424
{
4425
   struct amiga_fb_par par;
4426
   int error = 0;
4427
 
4428
   if (con == -1)
4429
      amiga_fb_get_par(&par);
4430
   else
4431
      error = fbhw->decode_var(&disp[con].var, &par);
4432
   return(error ? error : fbhw->encode_fix(fix, &par));
4433
}
4434
 
4435
 
4436
   /*
4437
    *    Get the User Defined Part of the Display
4438
    */
4439
 
4440
static int amiga_fb_get_var(struct fb_var_screeninfo *var, int con)
4441
{
4442
   struct amiga_fb_par par;
4443
   int error = 0;
4444
 
4445
   if (con == -1) {
4446
      amiga_fb_get_par(&par);
4447
      error = fbhw->encode_var(var, &par);
4448
   } else
4449
      *var = disp[con].var;
4450
   return(error);
4451
}
4452
 
4453
 
4454
static void amiga_fb_set_disp(int con)
4455
{
4456
   struct fb_fix_screeninfo fix;
4457
 
4458
   amiga_fb_get_fix(&fix, con);
4459
   if (con == -1)
4460
      con = 0;
4461
   disp[con].screen_base = (u_char *)fix.smem_start;
4462
   disp[con].visual = fix.visual;
4463
   disp[con].type = fix.type;
4464
   disp[con].type_aux = fix.type_aux;
4465
   disp[con].ypanstep = fix.ypanstep;
4466
   disp[con].ywrapstep = fix.ywrapstep;
4467
   disp[con].line_length = fix.line_length;
4468
   disp[con].can_soft_blank = 1;
4469
   disp[con].inverse = amifb_inverse;
4470
}
4471
 
4472
 
4473
   /*
4474
    *    Set the User Defined Part of the Display
4475
    */
4476
 
4477
static int amiga_fb_set_var(struct fb_var_screeninfo *var, int con)
4478
{
4479
   int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp;
4480
 
4481
   if ((err = do_fb_set_var(var, con == currcon)))
4482
      return(err);
4483
   if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
4484
      oldxres = disp[con].var.xres;
4485
      oldyres = disp[con].var.yres;
4486
      oldvxres = disp[con].var.xres_virtual;
4487
      oldvyres = disp[con].var.yres_virtual;
4488
      oldbpp = disp[con].var.bits_per_pixel;
4489
      disp[con].var = *var;
4490
      if (oldxres != var->xres || oldyres != var->yres ||
4491
          oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
4492
          oldbpp != var->bits_per_pixel) {
4493
         amiga_fb_set_disp(con);
4494
         (*fb_info.changevar)(con);
4495
         alloc_cmap(&disp[con].cmap, 0, 0);
4496
         do_install_cmap(con);
4497
      }
4498
   }
4499
   var->activate = 0;
4500
   return(0);
4501
}
4502
 
4503
 
4504
   /*
4505
    *    Get the Colormap
4506
    */
4507
 
4508
static int amiga_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con)
4509
{
4510
   if (con == currcon) /* current console? */
4511
      return(do_fb_get_cmap(cmap, &disp[con].var, kspc));
4512
   else if (disp[con].cmap.len) /* non default colormap? */
4513
      copy_cmap(&disp[con].cmap, cmap, kspc ? 0 : 2);
4514
   else
4515
      copy_cmap(get_default_colormap(disp[con].var.bits_per_pixel), cmap,
4516
                kspc ? 0 : 2);
4517
   return(0);
4518
}
4519
 
4520
 
4521
   /*
4522
    *    Set the Colormap
4523
    */
4524
 
4525
static int amiga_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con)
4526
{
4527
   int err;
4528
 
4529
   if (!disp[con].cmap.len) {       /* no colormap allocated? */
4530
      if ((err = alloc_cmap(&disp[con].cmap, 1<<disp[con].var.bits_per_pixel,
4531
                            0)))
4532
         return(err);
4533
   }
4534
   if (con == currcon)              /* current console? */
4535
      return(do_fb_set_cmap(cmap, &disp[con].var, kspc));
4536
   else
4537
      copy_cmap(cmap, &disp[con].cmap, kspc ? 0 : 1);
4538
   return(0);
4539
}
4540
 
4541
 
4542
   /*
4543
    *    Pan or Wrap the Display
4544
    *
4545
    *    This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
4546
    */
4547
 
4548
static int amiga_fb_pan_display(struct fb_var_screeninfo *var, int con)
4549
{
4550
   int err;
4551
   u_short oldlatch;
4552
 
4553
   if (var->vmode & FB_VMODE_YWRAP) {
4554
      if (var->xoffset || var->yoffset >= disp[con].var.yres)
4555
         return(-EINVAL);
4556
   } else {
4557
      if (var->xoffset+disp[con].var.xres > disp[con].var.xres_virtual ||
4558
          var->yoffset+disp[con].var.yres > disp[con].var.yres_virtual)
4559
    return(-EINVAL);
4560
   }
4561
   if (con == currcon) {
4562
      cli();
4563
      oldlatch = do_vmode;
4564
      do_vmode = 0;
4565
      sti();
4566
      if ((err = fbhw->pan_display(var, &current_par))) {
4567
         if (oldlatch)
4568
            do_vmode = 1;
4569
         return(err);
4570
      }
4571
      do_vmode = 1;
4572
   }
4573
   disp[con].var.xoffset = var->xoffset;
4574
   disp[con].var.yoffset = var->yoffset;
4575
   if (var->vmode & FB_VMODE_YWRAP)
4576
      disp[con].var.vmode |= FB_VMODE_YWRAP;
4577
   else
4578
      disp[con].var.vmode &= ~FB_VMODE_YWRAP;
4579
   return(0);
4580
}
4581
 
4582
 
4583
   /*
4584
    *    Amiga Frame Buffer Specific ioctls
4585
    */
4586
 
4587
static int amiga_fb_ioctl(struct inode *inode, struct file *file,
4588
                          u_int cmd, u_long arg, int con)
4589
{
4590
   int i;
4591
   struct fb_fix_cursorinfo crsrfix;
4592
   struct fb_var_cursorinfo crsrvar;
4593
   struct fb_cursorstate crsrstate;
4594
 
4595
   switch (cmd) {
4596
#ifdef CONFIG_AMIFB_AGA
4597
      case FBIOGET_FCURSORINFO:
4598
         i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(crsrfix));
4599
         if (i)
4600
            return(i);
4601
         i = amiga_fb_get_fix_cursorinfo(&crsrfix, con);
4602
         memcpy_tofs((void *)arg, &crsrfix, sizeof(crsrfix));
4603
         return(i);
4604
      case FBIOGET_VCURSORINFO:
4605
         i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(crsrvar));
4606
         if (i)
4607
            return(i);
4608
         i = amiga_fb_get_var_cursorinfo(&crsrvar, con);
4609
         memcpy_tofs((void *)arg, &crsrvar, sizeof(crsrvar));
4610
         return(i);
4611
      case FBIOPUT_VCURSORINFO:
4612
         i = verify_area(VERIFY_READ, (void *)arg, sizeof(crsrvar));
4613
         if (i)
4614
            return(i);
4615
         memcpy_fromfs(&crsrvar, (void *)arg, sizeof(crsrvar));
4616
         i = amiga_fb_set_var_cursorinfo(&crsrvar, con);
4617
         return(i);
4618
      case FBIOGET_CURSORSTATE:
4619
         i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(crsrstate));
4620
         if (i)
4621
            return(i);
4622
         i = amiga_fb_get_cursorstate(&crsrstate, con);
4623
         memcpy_tofs((void *)arg, &crsrstate, sizeof(crsrstate));
4624
         return(i);
4625
      case FBIOPUT_CURSORSTATE:
4626
         i = verify_area(VERIFY_READ, (void *)arg, sizeof(crsrstate));
4627
         if (i)
4628
            return(i);
4629
         memcpy_fromfs(&crsrstate, (void *)arg, sizeof(crsrstate));
4630
         i = amiga_fb_set_cursorstate(&crsrstate, con);
4631
         return(i);
4632
#endif /* CONFIG_AMIFB_AGA */
4633
#if 1
4634
      case FBCMD_GET_CURRENTPAR:
4635
         if ((i = verify_area(VERIFY_WRITE, (void *)arg,
4636
                              sizeof(struct amiga_fb_par))))
4637
            return(i);
4638
         memcpy_tofs((void *)arg, (void *)&current_par,
4639
                     sizeof(struct amiga_fb_par));
4640
         return(0);
4641
         break;
4642
      case FBCMD_SET_CURRENTPAR:
4643
         if ((i = verify_area(VERIFY_READ, (void *)arg,
4644
                              sizeof(struct amiga_fb_par))))
4645
            return(i);
4646
         memcpy_fromfs((void *)&current_par, (void *)arg,
4647
                       sizeof(struct amiga_fb_par));
4648
         return(0);
4649
         break;
4650
#endif
4651
   }
4652
   return(-EINVAL);
4653
}
4654
 
4655
 
4656
#ifdef CONFIG_AMIFB_AGA
4657
   /*
4658
    *    Hardware Cursor
4659
    */
4660
 
4661
static int amiga_fb_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix, int con)
4662
{
4663
   if (boot_info.bi_amiga.chipset == CS_AGA)
4664
      return(aga_get_fix_cursorinfo(fix, con));
4665
   return(-EINVAL);
4666
}
4667
 
4668
 
4669
static int amiga_fb_get_var_cursorinfo(struct fb_var_cursorinfo *var, int con)
4670
{
4671
   if (boot_info.bi_amiga.chipset == CS_AGA)
4672
      return(aga_get_var_cursorinfo(var, con));
4673
   return(-EINVAL);
4674
}
4675
 
4676
 
4677
static int amiga_fb_set_var_cursorinfo(struct fb_var_cursorinfo *var, int con)
4678
{
4679
   if (boot_info.bi_amiga.chipset == CS_AGA)
4680
      return(aga_set_var_cursorinfo(var, con));
4681
   return(-EINVAL);
4682
}
4683
 
4684
 
4685
static int amiga_fb_get_cursorstate(struct fb_cursorstate *state, int con)
4686
{
4687
   if (boot_info.bi_amiga.chipset == CS_AGA)
4688
      return(aga_get_cursorstate(state, con));
4689
   return(-EINVAL);
4690
}
4691
 
4692
 
4693
static int amiga_fb_set_cursorstate(struct fb_cursorstate *state, int con)
4694
{
4695
   if (boot_info.bi_amiga.chipset == CS_AGA)
4696
      return(aga_set_cursorstate(state, con));
4697
   return(-EINVAL);
4698
}
4699
#endif /* CONFIG_AMIFB_AGA */
4700
 
4701
 
4702
static struct fb_ops amiga_fb_ops = {
4703
   amiga_fb_get_fix, amiga_fb_get_var, amiga_fb_set_var, amiga_fb_get_cmap,
4704
   amiga_fb_set_cmap, amiga_fb_pan_display, amiga_fb_ioctl
4705
};
4706
 
4707
 
4708
void amiga_video_setup(char *options, int *ints)
4709
{
4710
   char *this_opt;
4711
   int i;
4712
   char mcap_spec[80];
4713
 
4714
   /*
4715
    *    Check for a Graphics Board
4716
    */
4717
 
4718
#ifdef CONFIG_FB_CYBER
4719
   if (options && *options)
4720
      if (!strncmp(options, "cyber", 5) && Cyber_probe()) {
4721
         amifb_Cyber = 1;
4722
         Cyber_video_setup(options, ints);
4723
         return;
4724
      }
4725
#endif /* CONFIG_FB_CYBER */
4726
 
4727
#ifdef USE_MONO_AMIFB_IF_NON_AGA
4728
   if (boot_info.bi_amiga.chipset != CS_AGA) {
4729
      mono_video_setup(options, ints);
4730
      return;
4731
   }
4732
#endif /* USE_MONO_AMIFB_IF_NON_AGA */
4733
 
4734
   mcap_spec[0] = '\0';
4735
   fb_info.fontname[0] = '\0';
4736
 
4737
   if (!options || !*options)
4738
      return;
4739
 
4740
   for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ","))
4741
      if (!strcmp(this_opt, "inverse")) {
4742
         amifb_inverse = 1;
4743
         for (i = 0; i < 16; i++) {
4744
            red16[i] = ~red16[i];
4745
            green16[i] = ~green16[i];
4746
            blue16[i] = ~blue16[i];
4747
         }
4748
         for (i = 0; i < 8; i++) {
4749
            red8[i] = ~red8[i];
4750
            green8[i] = ~green8[i];
4751
            blue8[i] = ~blue8[i];
4752
         }
4753
         for (i = 0; i < 4; i++) {
4754
            red4[i] = ~red4[i];
4755
            green4[i] = ~green4[i];
4756
            blue4[i] = ~blue4[i];
4757
         }
4758
         for (i = 0; i < 2; i++) {
4759
            red2[i] = ~red2[i];
4760
            green2[i] = ~green2[i];
4761
            blue2[i] = ~blue2[i];
4762
         }
4763
      } else if (!strcmp(this_opt, "ilbm"))
4764
         amifb_ilbm = 1;
4765
      else if (!strcmp(this_opt, "pwrsave"))
4766
         pwrsave = 1;
4767
      else if (!strncmp(this_opt, "monitorcap:", 11))
4768
         strcpy(mcap_spec, this_opt+11);
4769
      else if (!strncmp(this_opt, "font:", 5))
4770
         strcpy(fb_info.fontname, this_opt+5);
4771
      else
4772
         amifb_mode = get_video_mode(this_opt);
4773
 
4774
   if (*mcap_spec) {
4775
      char *p;
4776
      int vmin, vmax, hmin, hmax;
4777
 
4778
      /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
4779
       * <V*> vertical freq. in Hz
4780
       * <H*> horizontal freq. in kHz
4781
       */
4782
 
4783
      if (!(p = strtoke(mcap_spec, ";")) || !*p)
4784
         goto cap_invalid;
4785
      vmin = simple_strtoul(p, NULL, 10);
4786
      if (vmin <= 0)
4787
         goto cap_invalid;
4788
      if (!(p = strtoke(NULL, ";")) || !*p)
4789
         goto cap_invalid;
4790
      vmax = simple_strtoul(p, NULL, 10);
4791
      if (vmax <= 0 || vmax <= vmin)
4792
         goto cap_invalid;
4793
      if (!(p = strtoke(NULL, ";")) || !*p)
4794
         goto cap_invalid;
4795
      hmin = 1000 * simple_strtoul(p, NULL, 10);
4796
      if (hmin <= 0)
4797
         goto cap_invalid;
4798
      if (!(p = strtoke(NULL, "")) || !*p)
4799
         goto cap_invalid;
4800
      hmax = 1000 * simple_strtoul(p, NULL, 10);
4801
      if (hmax <= 0 || hmax <= hmin)
4802
         goto cap_invalid;
4803
 
4804
      vfmin = vmin;
4805
      vfmax = vmax;
4806
      hfmin = hmin;
4807
      hfmax = hmax;
4808
cap_invalid:
4809
      ;
4810
   }
4811
}
4812
 
4813
 
4814
   /*
4815
    *    Initialization
4816
    */
4817
 
4818
struct fb_info *amiga_fb_init(long *mem_start)
4819
{
4820
   int err, tag, i;
4821
   struct fb_var_screeninfo *var;
4822
 
4823
   /*
4824
    *    Check for a Graphics Board
4825
    */
4826
 
4827
#ifdef CONFIG_FB_CYBER
4828
   if (amifb_Cyber)
4829
      return(Cyber_fb_init(mem_start));
4830
#endif /* CONFIG_FB_CYBER */
4831
 
4832
   /*
4833
    *    Use the Builtin Chipset
4834
    */
4835
 
4836
   if (!AMIGAHW_PRESENT(AMI_VIDEO))
4837
      return(NULL);
4838
 
4839
#ifdef USE_MONO_AMIFB_IF_NON_AGA
4840
   if (boot_info.bi_amiga.chipset != CS_AGA)
4841
      return(mono_amiga_fb_init(mem_start));
4842
#endif /* USE_MONO_AMIFB_IF_NON_AGA */
4843
 
4844
   switch (boot_info.bi_amiga.chipset) {
4845
#ifdef CONFIG_AMIFB_OCS
4846
      case CS_OCS:
4847
         strcat(amiga_fb_name, "OCS");
4848
default_chipset:
4849
         fbhw = &ocs_switch;
4850
         maxdepth[TAG_SHRES-1] = 0;       /* OCS means no SHRES */
4851
         maxdepth[TAG_HIRES-1] = 4;
4852
         maxdepth[TAG_LORES-1] = 6;
4853
         break;
4854
#endif /* CONFIG_AMIFB_OCS */
4855
 
4856
#ifdef CONFIG_AMIFB_ECS
4857
      case CS_ECS:
4858
         strcat(amiga_fb_name, "ECS");
4859
         fbhw = &ecs_switch;
4860
         maxdepth[TAG_SHRES-1] = 2;
4861
         maxdepth[TAG_HIRES-1] = 4;
4862
         maxdepth[TAG_LORES-1] = 6;
4863
         break;
4864
#endif /* CONFIG_AMIFB_ECS */
4865
 
4866
#ifdef CONFIG_AMIFB_AGA
4867
      case CS_AGA:
4868
         strcat(amiga_fb_name, "AGA");
4869
         fbhw = &aga_switch;
4870
         maxdepth[TAG_SHRES-1] = 8;
4871
         maxdepth[TAG_HIRES-1] = 8;
4872
         maxdepth[TAG_LORES-1] = 8;
4873
         break;
4874
#endif /* CONFIG_AMIFB_AGA */
4875
 
4876
      default:
4877
#ifdef CONFIG_AMIFB_OCS
4878
         printk("Unknown graphics chipset, defaulting to OCS\n");
4879
         strcat(amiga_fb_name, "Unknown");
4880
         goto default_chipset;
4881
#else /* CONFIG_AMIFB_OCS */
4882
         panic("Unknown graphics chipset, no default driver");
4883
#endif /* CONFIG_AMIFB_OCS */
4884
         break;
4885
   }
4886
 
4887
   /*
4888
    *    Calculate the Pixel Clock Values for this Machine
4889
    */
4890
 
4891
   __asm("movel %3,%%d0;"
4892
         "movel #0x00000005,%%d1;"     /*  25E9: SHRES:  35 ns / 28 MHz */
4893
         "movel #0xd21dba00,%%d2;"
4894
         "divul %%d0,%%d1,%%d2;"
4895
         "movel %%d2,%0;"
4896
         "movel #0x0000000b,%%d1;"     /*  50E9: HIRES:  70 ns / 14 MHz */
4897
         "movel #0xa43b7400,%%d2;"
4898
         "divul %%d0,%%d1,%%d2;"
4899
         "movel %%d2,%1;"
4900
         "movel #0x00000017,%%d1;"     /* 100E9: LORES: 140 ns /  7 MHz */
4901
         "movel #0x4876e800,%%d2;"
4902
         "divul %%d0,%%d1,%%d2;"
4903
         "movel %%d2,%2"
4904
         : "=r" (pixclock[TAG_SHRES-1]), "=r" (pixclock[TAG_HIRES-1]),
4905
           "=r" (pixclock[TAG_LORES-1])
4906
         : "r" (amiga_eclock)
4907
         : "%%d0", "%%d1", "%%d2");
4908
 
4909
   /*
4910
    *    Replace the Tag Values with the Real Pixel Clock Values
4911
    */
4912
 
4913
   for (i = 0; i < NUM_PREDEF_MODES; i++) {
4914
      tag = amiga_fb_predefined[i].pixclock;
4915
      if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) {
4916
         amiga_fb_predefined[i].pixclock = pixclock[tag-1];
4917
         if (amiga_fb_predefined[i].bits_per_pixel > maxdepth[tag-1])
4918
            amiga_fb_predefined[i].bits_per_pixel = maxdepth[tag-1];
4919
      }
4920
   }
4921
 
4922
   err = register_framebuffer(amiga_fb_name, &node, &amiga_fb_ops,
4923
                              NUM_TOTAL_MODES, amiga_fb_predefined);
4924
   if (err < 0)
4925
      panic("Cannot register frame buffer");
4926
 
4927
   fbhw->init();
4928
   check_default_mode();
4929
 
4930
   if (!add_isr(IRQ_AMIGA_VERTB, amifb_interrupt, 0, NULL, "frame buffer"))
4931
      panic("Couldn't add vblank interrupt");
4932
 
4933
   strcpy(fb_info.modename, amiga_fb_name);
4934
   fb_info.disp = disp;
4935
   fb_info.switch_con = &amifb_switch;
4936
   fb_info.updatevar = &amifb_updatevar;
4937
   fb_info.blank = &amifb_blank;
4938
 
4939
   var = &amiga_fb_predefined[amifb_mode];
4940
   do_fb_set_var(var, 1);
4941
   strcat(fb_info.modename, " ");
4942
   strcat(fb_info.modename, amiga_fb_modenames[amifb_mode]);
4943
 
4944
   amiga_fb_get_var(&disp[0].var, -1);
4945
   amiga_fb_set_disp(-1);
4946
   do_install_cmap(0);
4947
   return(&fb_info);
4948
}
4949
 
4950
 
4951
static int amifb_switch(int con)
4952
{
4953
   /* Do we have to save the colormap? */
4954
   if (disp[currcon].cmap.len)
4955
      do_fb_get_cmap(&disp[currcon].cmap, &disp[currcon].var, 1);
4956
 
4957
   do_fb_set_var(&disp[con].var, 1);
4958
   currcon = con;
4959
   /* Install new colormap */
4960
   do_install_cmap(con);
4961
   return(0);
4962
}
4963
 
4964
 
4965
   /*
4966
    *    Update the `var' structure (called by fbcon.c)
4967
    *
4968
    *    This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
4969
    *    Since it's called by a kernel driver, no range checking is done.
4970
    */
4971
 
4972
static int amifb_updatevar(int con)
4973
{
4974
   do_vmode = 0;
4975
   current_par.yoffset = disp[con].var.yoffset;
4976
   current_par.vmode = disp[con].var.vmode;
4977
   current_par.bplpt0 = ZTWO_PADDR((u_long)videomemory+
4978
                                   current_par.yoffset*current_par.next_line);
4979
   do_vmode = 1;
4980
   return(0);
4981
}
4982
 
4983
 
4984
   /*
4985
    *    Blank the display.
4986
    */
4987
 
4988
static void amifb_blank(int blank)
4989
{
4990
   do_blank = blank ? 1 : -1;
4991
}
4992
 
4993
 
4994
   /*
4995
    *    VBlank Display Interrupt
4996
    */
4997
 
4998
static void amifb_interrupt(int irq, struct pt_regs *fp, void *dummy)
4999
{
5000
   static int is_laced = 0;
5001
 
5002
#if 0
5003
   /*
5004
    *    This test should be here, in case current_par isn't initialized yet
5005
    *
5006
    *    Fortunately only do_flashcursor() will be called in that case, and
5007
    *    currently that function doesn't use current_par. But this may change
5008
    *    in future...
5009
    */
5010
   if (!current_par_valid)
5011
      return;
5012
#endif
5013
 
5014
   /*
5015
    *    If interlaced, only change the display on a long frame
5016
    */
5017
 
5018
   if (!is_laced || custom.vposr & 0x8000) {
5019
      if (do_vmode) {
5020
         fbhw->do_vmode();
5021
         do_vmode = 0;
5022
         is_laced = (current_par.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED;
5023
      }
5024
      if (do_movecursor) {
5025
         fbhw->do_movecursor();
5026
         do_movecursor = 0;
5027
      }
5028
   }
5029
   if (do_blank) {
5030
      fbhw->do_blank(do_blank > 0 ? 1 : 0);
5031
      do_blank = 0;
5032
   }
5033
   if (!is_blanked)
5034
      fbhw->do_flashcursor();
5035
}
5036
 
5037
 
5038
   /*
5039
    *    A strtok which returns empty strings, too
5040
    */
5041
 
5042
static char * strtoke(char * s,const char * ct)
5043
{
5044
   char *sbegin, *send;
5045
   static char *ssave = NULL;
5046
 
5047
   sbegin  = s ? s : ssave;
5048
   if (!sbegin)
5049
      return(NULL);
5050
   if (*sbegin == '\0') {
5051
      ssave = NULL;
5052
      return(NULL);
5053
   }
5054
   send = strpbrk(sbegin, ct);
5055
   if (send && *send != '\0')
5056
      *send++ = '\0';
5057
   ssave = send;
5058
   return(sbegin);
5059
}
5060
 
5061
 
5062
   /*
5063
    *    Get a Video Modes
5064
    */
5065
 
5066
static int get_video_mode(const char *name)
5067
{
5068
   int i;
5069
 
5070
   for (i = 1; i < NUM_PREDEF_MODES; i++)
5071
      if (!strcmp(name, amiga_fb_modenames[i]))
5072
         return(i);
5073
   return(0);
5074
}
5075
 
5076
 
5077
   /*
5078
    *    Check the Default Video Mode
5079
    */
5080
 
5081
static void check_default_mode(void)
5082
{
5083
   struct fb_var_screeninfo var;
5084
 
5085
   /* First check the user supplied or system default video mode */
5086
   if (amifb_mode) {
5087
      var = amiga_fb_predefined[amifb_mode];
5088
      var.activate = FB_ACTIVATE_TEST;
5089
      if (!do_fb_set_var(&var, 1))
5090
         goto found_video_mode;
5091
   }
5092
 
5093
   /* Try some other modes... */
5094
   printk("Can't use default video mode. Probing video modes...\n");
5095
   for (amifb_mode = 1; amifb_mode < NUM_PREDEF_MODES; amifb_mode++) {
5096
      var = amiga_fb_predefined[amifb_mode];
5097
      var.activate = FB_ACTIVATE_TEST;
5098
      if (!do_fb_set_var(&var, 1))
5099
         goto found_video_mode;
5100
   }
5101
   panic("Can't find any usable video mode");
5102
 
5103
found_video_mode:
5104
   amiga_fb_predefined[0] = var;
5105
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.