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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [m68k/] [atari/] [atafb.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1623 jcastillo
/*
2
 * atari/atafb.c -- Low level implementation of Atari frame buffer device
3
 *
4
 *  Copyright (C) 1994 Martin Schaller & Roman Hodek
5
 *
6
 * This file is subject to the terms and conditions of the GNU General Public
7
 * License.  See the file COPYING in the main directory of this archive
8
 * for more details.
9
 *
10
 * History:
11
 *   - 03 Jan 95: Original version by Martin Schaller: The TT driver and
12
 *                all the device independent stuff
13
 *   - 09 Jan 95: Roman: I've added the hardware abstraction (hw_switch)
14
 *                and wrote the Falcon, ST(E), and External drivers
15
 *                based on the original TT driver.
16
 *   - 07 May 95: Martin: Added colormap operations for the external driver
17
 *   - 21 May 95: Martin: Added support for overscan
18
 *                Andreas: some bug fixes for this
19
 *   -    Jul 95: Guenther Kelleter <guenther@pool.informatik.rwth-aachen.de>:
20
 *                Programmable Falcon video modes
21
 *                (thanks to Christian Cartus for documentation
22
 *                of VIDEL registers).
23
 *   - 27 Dec 95: Guenther: Implemented user definable video modes "user[0-7]"
24
 *                on minor 24...31. "user0" may be set on commandline by
25
 *                "R<x>;<y>;<depth>". (Makes sense only on Falcon)
26
 *                Video mode switch on Falcon now done at next VBL interrupt
27
 *                to avoid the annoying right shift of the screen.
28
 *
29
 *
30
 * To do:
31
 *   - For the Falcon it is not possible to set random video modes on
32
 *     SM124 and SC/TV, only the bootup resolution is supported.
33
 *
34
 */
35
 
36
#define ATAFB_TT
37
#define ATAFB_STE
38
#define ATAFB_EXT
39
#define ATAFB_FALCON
40
 
41
#include <linux/kernel.h>
42
#include <linux/errno.h>
43
#include <linux/string.h>
44
#include <linux/mm.h>
45
#include <linux/tty.h>
46
#include <linux/malloc.h>
47
#include <linux/delay.h>
48
 
49
#include <asm/segment.h>
50
#include <asm/pgtable.h>
51
#include <asm/irq.h>
52
 
53
#include <asm/atarihw.h>
54
#include <asm/atariints.h>
55
#include <asm/bootinfo.h>
56
 
57
#include <linux/fb.h>
58
#include <asm/atarikb.h>
59
 
60
#define SWITCH_ACIA 0x01                /* modes for switch on OverScan */
61
#define SWITCH_SND6 0x40
62
#define SWITCH_SND7 0x80
63
#define SWITCH_NONE 0x00
64
 
65
 
66
#define arraysize(x)                    (sizeof(x)/sizeof(*(x)))
67
 
68
#define up(x, r) (((x) + (r) - 1) & ~((r)-1))
69
 
70
 
71
static int default_par=0;        /* default resolution (0=none) */
72
 
73
static int node;                /* node of the /dev/fb?current file */
74
 
75
static unsigned long default_mem_req=0;
76
 
77
static int hwscroll=-1;
78
 
79
static int use_hwscroll = 1;
80
 
81
static int sttt_xres=640,st_yres=400,tt_yres=480;
82
static int sttt_xres_virtual=640,sttt_yres_virtual=400;
83
static int ovsc_offset=0, ovsc_addlen=0;
84
int        ovsc_switchmode=0;
85
 
86
#ifdef ATAFB_FALCON
87
static int pwrsave = 0;  /* use VESA suspend mode instead of blanking only? */
88
#endif
89
 
90
static struct atari_fb_par {
91
        unsigned long screen_base;
92
        int vyres;
93
        union {
94
                struct {
95
                        int mode;
96
                        int sync;
97
                } tt, st;
98
                struct falcon_hw {
99
                        /* Here are fields for storing a video mode, as direct
100
                         * parameters for the hardware.
101
                         */
102
                        short sync;
103
                        short line_width;
104
                        short line_offset;
105
                        short st_shift;
106
                        short f_shift;
107
                        short vid_control;
108
                        short vid_mode;
109
                        short xoffset;
110
                        short hht, hbb, hbe, hdb, hde, hss;
111
                        short vft, vbb, vbe, vdb, vde, vss;
112
                        /* auxiliary information */
113
                        short mono;
114
                        short ste_mode;
115
                        short bpp;
116
                } falcon;
117
                /* Nothing needed for external mode */
118
        } hw;
119
} current_par;
120
 
121
/* Don't calculate an own resolution, and thus don't change the one found when
122
 * booting (currently used for the Falcon to keep settings for internal video
123
 * hardware extensions (e.g. ScreenBlaster)  */
124
static int DontCalcRes = 0;
125
 
126
#define HHT hw.falcon.hht
127
#define HBB hw.falcon.hbb
128
#define HBE hw.falcon.hbe
129
#define HDB hw.falcon.hdb
130
#define HDE hw.falcon.hde
131
#define HSS hw.falcon.hss
132
#define VFT hw.falcon.vft
133
#define VBB hw.falcon.vbb
134
#define VBE hw.falcon.vbe
135
#define VDB hw.falcon.vdb
136
#define VDE hw.falcon.vde
137
#define VSS hw.falcon.vss
138
#define VCO_CLOCK25             0x04
139
#define VCO_CSYPOS              0x10
140
#define VCO_VSYPOS              0x20
141
#define VCO_HSYPOS              0x40
142
#define VCO_SHORTOFFS   0x100
143
#define VMO_DOUBLE              0x01
144
#define VMO_INTER               0x02
145
#define VMO_PREMASK             0x0c
146
 
147
static struct fb_info fb_info;
148
 
149
static unsigned long screen_base;       /* base address of screen */
150
static unsigned long real_screen_base;  /* (only for Overscan) */
151
 
152
static int screen_len;
153
 
154
static int current_par_valid=0;
155
 
156
static int currcon=0;
157
 
158
static int mono_moni=0;
159
 
160
static struct display disp[MAX_NR_CONSOLES];
161
 
162
 
163
#ifdef ATAFB_EXT
164
/* external video handling */
165
 
166
static unsigned                 external_xres;
167
static unsigned                 external_yres;
168
static unsigned                 external_depth;
169
static int                              external_pmode;
170
static unsigned long    external_addr = 0;
171
static unsigned long    external_len;
172
static unsigned long    external_vgaiobase = 0;
173
static unsigned int             external_bitspercol = 6;
174
 
175
/*
176
++JOE <joe@amber.dinoco.de>:
177
added card type for external driver, is only needed for
178
colormap handling.
179
*/
180
 
181
enum cardtype { IS_VGA, IS_MV300 };
182
static enum cardtype external_card_type = IS_VGA;
183
 
184
/*
185
The MV300 mixes the color registers. So we need an array of munged
186
indices in order to acces the correct reg.
187
*/
188
static int MV300_reg_1bit[2]={0,1};
189
static int MV300_reg_4bit[16]={
190
0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 };
191
static int MV300_reg_8bit[256]={
192
0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
193
8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
194
4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
195
12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
196
2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
197
10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
198
6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
199
14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
200
1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
201
9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
202
5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
203
13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
204
3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
205
11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
206
7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
207
15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255 };
208
 
209
static int *MV300_reg = MV300_reg_8bit;
210
 
211
/*
212
And on the MV300 it's difficult to read out the hardware palette. So we
213
just keep track of the set colors in our own array here, and use that!
214
*/
215
 
216
struct { unsigned char red,green,blue,pad; } MV300_color[256];
217
#endif /* ATAFB_EXT */
218
 
219
 
220
int inverse=0;
221
 
222
extern int fontheight_8x8;
223
extern int fontwidth_8x8;
224
extern unsigned char fontdata_8x8[];
225
 
226
extern int fontheight_8x16;
227
extern int fontwidth_8x16;
228
extern unsigned char fontdata_8x16[];
229
 
230
/* import first 16 colors from fbcon.c */
231
extern unsigned short packed16_cmap[16];
232
 
233
 
234
/* ++roman: This structure abstracts from the underlying hardware (ST(e),
235
 * TT, or Falcon.
236
 *
237
 * int (*detect)( void )
238
 *   This function should detect the current video mode settings and
239
 *   store them in atari_fb_predefined[0] for later reference by the
240
 *   user. Return the index+1 of an equivalent predefined mode or 0
241
 *   if there is no such.
242
 *
243
 * int (*encode_fix)( struct fb_fix_screeninfo *fix,
244
 *                    struct atari_fb_par *par )
245
 *   This function should fill in the 'fix' structure based on the
246
 *   values in the 'par' structure.
247
 *
248
 * int (*decode_var)( struct fb_var_screeninfo *var,
249
 *                    struct atari_fb_par *par )
250
 *   Get the video params out of 'var'. If a value doesn't fit, round
251
 *   it up, if it's too big, return EINVAL.
252
 *   Round up in the following order: bits_per_pixel, xres, yres,
253
 *   xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
254
 *   horizontal timing, vertical timing.
255
 *
256
 * int (*encode_var)( struct fb_var_screeninfo *var,
257
 *                    struct atari_fb_par *par );
258
 *   Fill the 'var' structure based on the values in 'par' and maybe
259
 *   other values read out of the hardware.
260
 *
261
 * void (*get_par)( struct atari_fb_par *par )
262
 *   Fill the hardware's 'par' structure.
263
 *
264
 * void (*set_par)( struct atari_fb_par *par )
265
 *   Set the hardware according to 'par'.
266
 *
267
 * int (*setcolreg)( unsigned regno, unsigned red,
268
 *                   unsigned green, unsigned blue,
269
 *                   unsigned transp )
270
 *   Set a single color register. The values supplied are already
271
 *   rounded down to the hardware's capabilities (according to the
272
 *   entries in the var structure). Return != 0 for invalid regno.
273
 *
274
 * int (*getcolreg)( unsigned regno, unsigned *red,
275
 *                   unsigned *green, unsigned *blue,
276
 *                   unsigned *transp )
277
 *   Read a single color register and split it into
278
 *   colors/transparent. Return != 0 for invalid regno.
279
 *
280
 * void (*set_screen_base)( unsigned long s_base )
281
 *   Set the base address of the displayed frame buffer. Only called
282
 *   if yres_virtual > yres or xres_virtual > xres.
283
 *
284
 * int (*blank)( int blank_mode )
285
 *   Blank the screen if blank_mode != 0, else unblank. If NULL then blanking
286
 *   is done by setting the CLUT to black. Return != 0 if un-/blanking
287
 *   failed due to e.g. video mode which doesn't support it.
288
 */
289
 
290
static struct fb_hwswitch {
291
        int  (*detect)( void );
292
        int  (*encode_fix)( struct fb_fix_screeninfo *fix,
293
                                                struct atari_fb_par *par );
294
        int  (*decode_var)( struct fb_var_screeninfo *var,
295
                                                struct atari_fb_par *par );
296
        int  (*encode_var)( struct fb_var_screeninfo *var,
297
                                                struct atari_fb_par *par );
298
        void (*get_par)( struct atari_fb_par *par );
299
        void (*set_par)( struct atari_fb_par *par );
300
        int  (*getcolreg)( unsigned regno, unsigned *red,
301
                                           unsigned *green, unsigned *blue,
302
                                           unsigned *transp );
303
        int  (*setcolreg)( unsigned regno, unsigned red,
304
                                           unsigned green, unsigned blue,
305
                                           unsigned transp );
306
        void (*set_screen_base)( unsigned long s_base );
307
        int  (*blank)( int blank_mode );
308
        int  (*pan_display)( struct fb_var_screeninfo *var,
309
                                                 struct atari_fb_par *par);
310
} *fbhw;
311
 
312
static char *autodetect_names[] = {"autodetect", NULL};
313
static char *stlow_names[] = {"stlow", NULL};
314
static char *stmid_names[] = {"stmid", "default5", NULL};
315
static char *sthigh_names[] = {"sthigh", "default4", NULL};
316
static char *ttlow_names[] = {"ttlow", NULL};
317
static char *ttmid_names[]= {"ttmid", "default1", NULL};
318
static char *tthigh_names[]= {"tthigh", "default2", NULL};
319
static char *vga2_names[] = {"vga2", NULL};
320
static char *vga4_names[] = {"vga4", NULL};
321
static char *vga16_names[] = {"vga16", "default3", NULL};
322
static char *vga256_names[] = {"vga256", NULL};
323
static char *falh2_names[] = {"falh2", NULL};
324
static char *falh16_names[] = {"falh16", NULL};
325
static char *user0_names[] = {"user0", NULL};
326
static char *user1_names[] = {"user1", NULL};
327
static char *user2_names[] = {"user2", NULL};
328
static char *user3_names[] = {"user3", NULL};
329
static char *user4_names[] = {"user4", NULL};
330
static char *user5_names[] = {"user5", NULL};
331
static char *user6_names[] = {"user6", NULL};
332
static char *user7_names[] = {"user7", NULL};
333
static char *dummy_names[] = {"dummy", NULL};
334
 
335
char **fb_var_names[] = {
336
        /* Writing the name arrays directly in this array (via "(char *[]){...}")
337
         * crashes gcc 2.5.8 (sigsegv) if the inner array
338
         * contains more than two items. I've also seen that all elements
339
         * were identical to the last (my cross-gcc) :-(*/
340
        autodetect_names,
341
        stlow_names,
342
        stmid_names,
343
        sthigh_names,
344
        ttlow_names,
345
        ttmid_names,
346
        tthigh_names,
347
        vga2_names,
348
        vga4_names,
349
        vga16_names,
350
        vga256_names,
351
        falh2_names,
352
        falh16_names,
353
        dummy_names, dummy_names, dummy_names, dummy_names,
354
        dummy_names, dummy_names, dummy_names, dummy_names,
355
        dummy_names, dummy_names,
356
        user0_names,
357
        user1_names,
358
        user2_names,
359
        user3_names,
360
        user4_names,
361
        user5_names,
362
        user6_names,
363
        user7_names,
364
        NULL
365
        /* ,NULL */ /* this causes a sigsegv on my gcc-2.5.8 */
366
};
367
 
368
struct fb_var_screeninfo atari_fb_predefined[] = {
369
        { /* autodetect */
370
          0, 0, 0, 0, 0, 0, 0, 0,               /* xres-grayscale */
371
          {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},       /* red green blue tran*/
372
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
373
        { /* st low */
374
          320, 200, 320, 200, 0, 0, 4, 0,                  /* xres-grayscale */
375
          {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},    /* red green blue tran*/
376
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
377
        { /* st mid */
378
          640, 200, 640, 200, 0, 0, 2, 0,          /* xres-grayscale */
379
          {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},    /* red green blue tran*/
380
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
381
        { /* st high */
382
          640, 400, 640, 400, 0, 0, 1, 0,          /* xres-grayscale */
383
          {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},    /* red green blue tran*/
384
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
385
        { /* tt low */
386
          320, 480, 320, 480, 0, 0, 8, 0,          /* xres-grayscale */
387
          {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},    /* red green blue tran*/
388
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
389
        { /* tt mid */
390
          640, 480, 640, 480, 0, 0, 4, 0,          /* xres-grayscale */
391
          {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},    /* red green blue tran*/
392
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
393
        { /* tt high */
394
          1280, 960, 1280, 960, 0, 0, 1, 0,                /* xres-grayscale */
395
          {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},    /* red green blue tran*/
396
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
397
        { /* vga2 */
398
          640, 480, 640, 480, 0, 0, 1, 0,                  /* xres-grayscale */
399
          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},    /* red green blue tran*/
400
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
401
        { /* vga4 */
402
          640, 480, 640, 480, 0, 0, 2, 0,          /* xres-grayscale */
403
          {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},    /* red green blue tran*/
404
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
405
        { /* vga16 */
406
          640, 480, 640, 480, 0, 0, 4, 0,          /* xres-grayscale */
407
          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},    /* red green blue tran*/
408
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
409
        { /* vga256 */
410
          640, 480, 640, 480, 0, 0, 8, 0,          /* xres-grayscale */
411
          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},    /* red green blue tran*/
412
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
413
        { /* falh2 */
414
          896, 608, 896, 608, 0, 0, 1, 0,          /* xres-grayscale */
415
          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},    /* red green blue tran*/
416
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
417
        { /* falh16 */
418
          896, 608, 896, 608, 0, 0, 4, 0,          /* xres-grayscale */
419
          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},    /* red green blue tran*/
420
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
421
        /* Minor 14..23 free for more standard video modes */
422
        { 0, },
423
        { 0, },
424
        { 0, },
425
        { 0, },
426
        { 0, },
427
        { 0, },
428
        { 0, },
429
        { 0, },
430
        { 0, },
431
        { 0, },
432
        /* Minor 24..31 reserved for user defined video modes */
433
        { /* user0, initialized to Rx;y;d from commandline, if supplied */
434
          0, 0, 0, 0, 0, 0, 0, 0,
435
          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
436
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
437
        { /* user1 */
438
          0, 0, 0, 0, 0, 0, 0, 0,
439
          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
440
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
441
        { /* user2 */
442
          0, 0, 0, 0, 0, 0, 0, 0,
443
          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
444
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
445
        { /* user3 */
446
          0, 0, 0, 0, 0, 0, 0, 0,
447
          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
448
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
449
        { /* user4 */
450
          0, 0, 0, 0, 0, 0, 0, 0,
451
          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
452
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
453
        { /* user5 */
454
          0, 0, 0, 0, 0, 0, 0, 0,
455
          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
456
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
457
        { /* user6 */
458
          0, 0, 0, 0, 0, 0, 0, 0,
459
          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
460
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
461
        { /* user7 */
462
          0, 0, 0, 0, 0, 0, 0, 0,
463
          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
464
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }
465
};
466
 
467
int num_atari_fb_predefined=arraysize(atari_fb_predefined);
468
 
469
 
470
static int
471
get_video_mode(char *vname)
472
{
473
    char ***name_list;
474
    char **name;
475
    int i;
476
    name_list=fb_var_names;
477
    for (i = 0 ; i < num_atari_fb_predefined ; i++) {
478
        name=*(name_list++);
479
        if (! name || ! *name)
480
            break;
481
        while (*name) {
482
            if (! strcmp(vname, *name))
483
                return i+1;
484
            name++;
485
        }
486
    }
487
    return 0;
488
}
489
 
490
 
491
 
492
/* ------------------- TT specific functions ---------------------- */
493
 
494
#ifdef ATAFB_TT
495
 
496
static int tt_encode_fix( struct fb_fix_screeninfo *fix,
497
                                                  struct atari_fb_par *par )
498
 
499
{
500
        int mode, i;
501
 
502
        strcpy(fix->id,"Atari Builtin");
503
        fix->smem_start=real_screen_base;
504
        fix->smem_len = screen_len;
505
        fix->type=FB_TYPE_INTERLEAVED_PLANES;
506
        fix->type_aux=2;
507
        fix->visual=FB_VISUAL_PSEUDOCOLOR;
508
        mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK;
509
        if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) {
510
                fix->type=FB_TYPE_PACKED_PIXELS;
511
                fix->type_aux=0;
512
                if (mode == TT_SHIFTER_TTHIGH)
513
                        fix->visual=FB_VISUAL_MONO01;
514
        }
515
        fix->xpanstep=0;
516
        fix->ypanstep=1;
517
        fix->ywrapstep=0;
518
        fix->line_length = 0;
519
        for (i=0; i<arraysize(fix->reserved); i++)
520
                fix->reserved[i]=0;
521
        return 0;
522
}
523
 
524
 
525
static int tt_decode_var( struct fb_var_screeninfo *var,
526
                                                  struct atari_fb_par *par )
527
{
528
        int xres=var->xres;
529
        int yres=var->yres;
530
        int bpp=var->bits_per_pixel;
531
        int linelen;
532
 
533
        if (mono_moni) {
534
                if (bpp > 1 || xres > sttt_xres*2 || yres >tt_yres*2)
535
                        return -EINVAL;
536
                par->hw.tt.mode=TT_SHIFTER_TTHIGH;
537
                xres=sttt_xres*2;
538
                yres=tt_yres*2;
539
                bpp=1;
540
        } else {
541
                if (bpp > 8 || xres > sttt_xres || yres > tt_yres)
542
                        return -EINVAL;
543
                if (bpp > 4) {
544
                        if (xres > sttt_xres/2 || yres > tt_yres)
545
                                return -EINVAL;
546
                        par->hw.tt.mode=TT_SHIFTER_TTLOW;
547
                        xres=sttt_xres/2;
548
                        yres=tt_yres;
549
                        bpp=8;
550
                }
551
                else if (bpp > 2) {
552
                        if (xres > sttt_xres || yres > tt_yres)
553
                                return -EINVAL;
554
                        if (xres > sttt_xres/2 || yres > st_yres/2) {
555
                                par->hw.tt.mode=TT_SHIFTER_TTMID;
556
                                xres=sttt_xres;
557
                                yres=tt_yres;
558
                                bpp=4;
559
                        }
560
                        else {
561
                                par->hw.tt.mode=TT_SHIFTER_STLOW;
562
                                xres=sttt_xres/2;
563
                                yres=st_yres/2;
564
                                bpp=4;
565
                        }
566
                }
567
                else if (bpp > 1) {
568
                        if (xres > sttt_xres || yres > st_yres/2)
569
                                return -EINVAL;
570
                        par->hw.tt.mode=TT_SHIFTER_STMID;
571
                        xres=sttt_xres;
572
                        yres=st_yres/2;
573
                        bpp=2;
574
                }
575
                else if (var->xres > sttt_xres || var->yres > st_yres) {
576
                        return -EINVAL;
577
                }
578
                else {
579
                        par->hw.tt.mode=TT_SHIFTER_STHIGH;
580
                        xres=sttt_xres;
581
                        yres=st_yres;
582
                        bpp=1;
583
                }
584
        }
585
        if (var->sync & FB_SYNC_EXT)
586
                par->hw.tt.sync=0;
587
        else
588
                par->hw.tt.sync=1;
589
        linelen=xres*bpp/8;
590
        if ((var->yoffset + yres)*linelen > screen_len && screen_len)
591
                return -EINVAL;
592
        par->screen_base=screen_base+ var->yoffset*linelen;
593
        return 0;
594
}
595
 
596
static int tt_encode_var( struct fb_var_screeninfo *var,
597
                                                  struct atari_fb_par *par )
598
{
599
        int linelen, i;
600
        var->red.offset=0;
601
        var->red.length=4;
602
        var->red.msb_right=0;
603
        var->grayscale=0;
604
 
605
        var->pixclock=31041;
606
        var->left_margin=120;           /* these may be incorrect       */
607
        var->right_margin=100;
608
        var->upper_margin=8;
609
        var->lower_margin=16;
610
        var->hsync_len=140;
611
        var->vsync_len=30;
612
 
613
        var->height=-1;
614
        var->width=-1;
615
 
616
        if (par->hw.tt.sync & 1)
617
                var->sync=0;
618
        else
619
                var->sync=FB_SYNC_EXT;
620
 
621
        switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) {
622
        case TT_SHIFTER_STLOW:
623
                var->xres=sttt_xres/2;
624
                var->xres_virtual=sttt_xres_virtual/2;
625
                var->yres=st_yres/2;
626
                var->bits_per_pixel=4;
627
                break;
628
        case TT_SHIFTER_STMID:
629
                var->xres=sttt_xres;
630
                var->xres_virtual=sttt_xres_virtual;
631
                var->yres=st_yres/2;
632
                var->bits_per_pixel=2;
633
                break;
634
        case TT_SHIFTER_STHIGH:
635
                var->xres=sttt_xres;
636
                var->xres_virtual=sttt_xres_virtual;
637
                var->yres=st_yres;
638
                var->bits_per_pixel=1;
639
                break;
640
        case TT_SHIFTER_TTLOW:
641
                var->xres=sttt_xres/2;
642
                var->xres_virtual=sttt_xres_virtual/2;
643
                var->yres=tt_yres;
644
                var->bits_per_pixel=8;
645
                break;
646
        case TT_SHIFTER_TTMID:
647
                var->xres=sttt_xres;
648
                var->xres_virtual=sttt_xres_virtual;
649
                var->yres=tt_yres;
650
                var->bits_per_pixel=4;
651
                break;
652
        case TT_SHIFTER_TTHIGH:
653
                var->red.length=0;
654
                var->xres=sttt_xres*2;
655
                var->xres_virtual=sttt_xres_virtual*2;
656
                var->yres=tt_yres*2;
657
                var->bits_per_pixel=1;
658
                break;
659
        }
660
        var->blue=var->green=var->red;
661
        var->transp.offset=0;
662
        var->transp.length=0;
663
        var->transp.msb_right=0;
664
        linelen=var->xres_virtual * var->bits_per_pixel / 8;
665
        if (! use_hwscroll)
666
                var->yres_virtual=var->yres;
667
        else if (screen_len)
668
                var->yres_virtual=screen_len/linelen;
669
        else {
670
                if (hwscroll < 0)
671
                        var->yres_virtual = 2 * var->yres;
672
                else
673
                        var->yres_virtual=var->yres+hwscroll * 16;
674
        }
675
        var->xoffset=0;
676
        if (screen_base)
677
                var->yoffset=(par->screen_base - screen_base)/linelen;
678
        else
679
                var->yoffset=0;
680
        var->nonstd=0;
681
        var->activate=0;
682
        var->vmode=FB_VMODE_NONINTERLACED;
683
        for (i=0; i<arraysize(var->reserved); i++)
684
                var->reserved[i]=0;
685
        return 0;
686
}
687
 
688
 
689
static void tt_get_par( struct atari_fb_par *par )
690
{
691
        unsigned long addr;
692
        par->hw.tt.mode=shifter_tt.tt_shiftmode;
693
        par->hw.tt.sync=shifter.syncmode;
694
        addr = ((shifter.bas_hi & 0xff) << 16) |
695
               ((shifter.bas_md & 0xff) << 8)  |
696
               ((shifter.bas_lo & 0xff));
697
        par->screen_base = PTOV(addr);
698
}
699
 
700
static void tt_set_par( struct atari_fb_par *par )
701
{
702
        shifter_tt.tt_shiftmode=par->hw.tt.mode;
703
        shifter.syncmode=par->hw.tt.sync;
704
        /* only set screen_base if really necessary */
705
        if (current_par.screen_base != par->screen_base)
706
                fbhw->set_screen_base(par->screen_base);
707
}
708
 
709
 
710
static int tt_getcolreg( unsigned regno, unsigned *red,
711
                                                 unsigned *green, unsigned *blue,
712
                                                 unsigned *transp )
713
{
714
        if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
715
                regno += 254;
716
        if (regno > 255)
717
                return 1;
718
        *blue = tt_palette[regno];
719
        *green = (*blue >> 4) & 0xf;
720
        *red = (*blue >> 8) & 0xf;
721
        *blue &= 0xf;
722
        *transp = 0;
723
        return 0;
724
}
725
 
726
 
727
static int tt_setcolreg( unsigned regno, unsigned red,
728
                                                 unsigned green, unsigned blue,
729
                                                 unsigned transp )
730
{
731
        if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
732
                regno += 254;
733
        if (regno > 255)
734
                return 1;
735
        tt_palette[regno] = (red << 8) | (green << 4) | blue;
736
        if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
737
                TT_SHIFTER_STHIGH && regno == 254)
738
                tt_palette[0] = 0;
739
        return 0;
740
}
741
 
742
 
743
static int tt_detect( void )
744
 
745
{       struct atari_fb_par par;
746
 
747
        /* Determine the connected monitor: The DMA sound must be
748
         * disabled before reading the MFP GPIP, because the Sound
749
         * Done Signal and the Monochrome Detect are XORed together!
750
         *
751
         * Even on a TT, we should look if there is a DMA sound. It was
752
         * announced that the Eagle is TT compatible, but only the PCM is
753
         * missing...
754
         */
755
        if (ATARIHW_PRESENT(PCM_8BIT)) {
756
                tt_dmasnd.ctrl = DMASND_CTRL_OFF;
757
                udelay(20);     /* wait a while for things to settle down */
758
        }
759
        mono_moni = (mfp.par_dt_reg & 0x80) == 0;
760
 
761
        tt_get_par(&par);
762
        tt_encode_var(&atari_fb_predefined[0], &par);
763
 
764
        return 1;
765
}
766
 
767
#endif /* ATAFB_TT */
768
 
769
/* ------------------- Falcon specific functions ---------------------- */
770
 
771
#ifdef ATAFB_FALCON
772
 
773
static int mon_type;            /* Falcon connected monitor */
774
static int f030_bus_width;      /* Falcon ram bus width (for vid_control) */
775
#define F_MON_SM        0
776
#define F_MON_SC        1
777
#define F_MON_VGA       2
778
#define F_MON_TV        3
779
 
780
/* Multisync monitor capabilities */
781
/* Atari-TOS defaults if no boot option present */
782
static long vfmin=58, vfmax=62, hfmin=31000, hfmax=32000;
783
 
784
static struct pixel_clock {
785
        unsigned long f;        /* f/[Hz] */
786
        unsigned long t;        /* t/[ps] (=1/f) */
787
        short right, hsync, left;       /* standard timing in clock cycles, not pixel */
788
                /* hsync initialized in falcon_detect() */
789
        short sync_mask;        /* or-mask for hw.falcon.sync to set this clock */
790
        short control_mask; /* ditto, for hw.falcon.vid_control */
791
}
792
f25  = {25175000, 39722, 18, 0, 42, 0x0, VCO_CLOCK25},
793
f32  = {32000000, 31250, 18, 0, 42, 0x0, 0},
794
fext = {       0,     0, 18, 0, 42, 0x1, 0};
795
 
796
/* VIDEL-prescale values [mon_type][pixel_length from VCO] */
797
static short vdl_prescale[4][3] = {{4,2,1}, {4,2,1}, {4,2,2}, {4,2,1}};
798
 
799
/* Default hsync timing [mon_type] in picoseconds */
800
static long h_syncs[4] = {3000000, 4700000, 4000000, 4700000};
801
 
802
 
803
static inline int hxx_prescale(struct falcon_hw *hw)
804
{
805
        return hw->ste_mode ? 16 :
806
                   vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
807
}
808
 
809
static int falcon_encode_fix( struct fb_fix_screeninfo *fix,
810
                                                          struct atari_fb_par *par )
811
{
812
        int i;
813
 
814
        strcpy(fix->id, "Atari Builtin");
815
        fix->smem_start = real_screen_base;
816
        fix->smem_len = screen_len;
817
        fix->type = FB_TYPE_INTERLEAVED_PLANES;
818
        fix->type_aux = 2;
819
        fix->visual = FB_VISUAL_PSEUDOCOLOR;
820
        if (par->hw.falcon.mono) {
821
                fix->type = FB_TYPE_PACKED_PIXELS;
822
                fix->type_aux = 0;
823
        }
824
        else if (par->hw.falcon.f_shift & 0x100) {
825
                fix->type = FB_TYPE_PACKED_PIXELS;
826
                fix->type_aux = 0;
827
                fix->visual = FB_VISUAL_TRUECOLOR;  /* is this ok or should this be DIRECTCOLOR? */
828
        }
829
        if (par->hw.falcon.mono)
830
                /* no smooth scrolling possible with longword aligned video mem */
831
                fix->xpanstep = 32;
832
        else
833
                fix->xpanstep = 1;
834
        fix->ypanstep = 1;
835
        fix->ywrapstep = 0;
836
        fix->line_length = 0;
837
        for (i=0; i<arraysize(fix->reserved); i++)
838
                fix->reserved[i]=0;
839
        return 0;
840
}
841
 
842
 
843
static int falcon_decode_var( struct fb_var_screeninfo *var,
844
                                                          struct atari_fb_par *par )
845
{
846
        int use_default_timing = 0;
847
        int bpp = var->bits_per_pixel;
848
        int xres = var->xres;
849
        int yres = var->yres;
850
        int xres_virtual = var->xres_virtual;
851
        int yres_virtual = var->yres_virtual;
852
        int left_margin, right_margin, hsync_len;
853
        int upper_margin, lower_margin, vsync_len;
854
        int linelen;
855
        int interlace = 0, doubleline = 0;
856
        struct pixel_clock *pclock;
857
        int plen; /* width of pixel in clock cycles */
858
        int xstretch;
859
        int prescale;
860
        int longoffset = 0;
861
        int hfreq, vfreq;
862
 
863
/*
864
        Get the video params out of 'var'. If a value doesn't fit, round
865
        it up, if it's too big, return EINVAL.
866
        Round up in the following order: bits_per_pixel, xres, yres,
867
        xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
868
        horizontal timing, vertical timing.
869
 
870
        There is a maximum of screen resolution determined by pixelclock
871
        and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock.
872
        In interlace mode this is     "     *    "     *vfmin <= pixelclock.
873
        Additional constraints: hfreq.
874
        Frequency range for multisync monitors is given via command line.
875
        For TV and SM124 both frequencies are fixed.
876
 
877
        X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32==0)
878
        Y % 16 == 0 to fit 8x16 font
879
        Y % 8 == 0 if Y<400
880
 
881
        Currently interlace and doubleline mode in var are ignored.
882
        On SM124 and TV only the standard resolutions can be used.
883
*/
884
 
885
        /* Reject uninitialized mode */
886
        if (!xres || !yres || !bpp)
887
                return -EINVAL;
888
 
889
        if (mon_type == F_MON_SM && bpp != 1) {
890
                return -EINVAL;
891
        }
892
        else if (bpp <= 1) {
893
                bpp = 1;
894
                par->hw.falcon.f_shift = 0x400;
895
                par->hw.falcon.st_shift = 0x200;
896
        }
897
        else if (bpp <= 2) {
898
                bpp = 2;
899
                par->hw.falcon.f_shift = 0x000;
900
                par->hw.falcon.st_shift = 0x100;
901
        }
902
        else if (bpp <= 4) {
903
                bpp = 4;
904
                par->hw.falcon.f_shift = 0x000;
905
                par->hw.falcon.st_shift = 0x000;
906
        }
907
        else if (bpp <= 8) {
908
                bpp = 8;
909
                par->hw.falcon.f_shift = 0x010;
910
        }
911
        else if (bpp <= 16) {
912
                bpp = 16; /* packed pixel mode */
913
                par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */
914
        }
915
        else
916
                return -EINVAL;
917
        par->hw.falcon.bpp = bpp;
918
 
919
        if (mon_type != F_MON_VGA || DontCalcRes) {
920
                /* Skip all calculations, VGA multisync only yet */
921
                struct fb_var_screeninfo *myvar = &atari_fb_predefined[0];
922
 
923
                if (bpp > myvar->bits_per_pixel ||
924
                        var->xres > myvar->xres ||
925
                        var->yres > myvar->yres)
926
                        return -EINVAL;
927
                fbhw->get_par(par);     /* Current par will be new par */
928
                goto set_screen_base;   /* Don't forget this */
929
        }
930
 
931
        /* Only some fixed resolutions < 640x480 */
932
        if (xres <= 320)
933
                xres = 320;
934
        else if (xres <= 640 && bpp != 16)
935
                xres = 640;
936
        if (yres <= 200)
937
                yres = 200;
938
        else if (yres <= 240)
939
                yres = 240;
940
        else if (yres <= 400)
941
                yres = 400;
942
        else if (yres <= 480)
943
                yres = 480;
944
 
945
        /* 2 planes must use STE compatibility mode */
946
        par->hw.falcon.ste_mode = bpp==2;
947
        par->hw.falcon.mono = bpp==1;
948
 
949
        /* Total and visible scanline length must be a multiple of one longword,
950
         * this and the console fontwidth yields the alignment for xres and
951
         * xres_virtual.
952
         *
953
         * Special case in STE mode: blank and graphic positions don't align,
954
         * avoid trash at right margin
955
         */
956
        if (par->hw.falcon.ste_mode)
957
                xres = (xres + 63) & ~63;
958
        else if (bpp == 1)
959
                xres = (xres + 31) & ~31;
960
        else
961
                xres = (xres + 15) & ~15;
962
        if (yres >= 400)
963
                yres = (yres + 15) & ~15;
964
        else
965
                yres = (yres + 7) & ~7;
966
 
967
        if (xres_virtual < xres)
968
                xres_virtual = xres;
969
        else if (bpp == 1)
970
                xres_virtual = (xres_virtual + 31) & ~31;
971
        else
972
                xres_virtual = (xres_virtual + 15) & ~15;
973
        /* <=0 : yres_virtual determined by screensize */
974
        if (yres_virtual < yres && yres_virtual > 0)
975
                yres_virtual = yres;
976
 
977
        par->hw.falcon.line_width = bpp * xres / 16;
978
        par->hw.falcon.line_offset = bpp * (xres_virtual - xres) / 16;
979
 
980
        /* single or double pixel width */
981
        xstretch = (xres == 320) ? 2 : 1;
982
 
983
        /* Default values are used for vert./hor. timing if no pixelclock given. */
984
        if (var->pixclock == 0)
985
                use_default_timing = 1;
986
 
987
#if 0 /* currently unused */
988
        if (mon_type == F_MON_SM) {
989
                if (xres != 640 && yres != 400)
990
                        return -EINVAL;
991
                plen = 1;
992
                pclock = &f32;
993
                /* SM124-mode is special */
994
                par->hw.falcon.ste_mode = 1;
995
                par->hw.falcon.f_shift = 0x000;
996
                par->hw.falcon.st_shift = 0x200;
997
                left_margin = hsync_len = 128 / plen;
998
                right_margin = 0;
999
                /* TODO set all margins */
1000
        }
1001
        else if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
1002
                plen = 2 * xstretch;
1003
                pclock = &f32;
1004
                hsync_len = 150 / plen;
1005
                if (yres > 240)
1006
                        interlace = 1;
1007
                /* TODO set margins */
1008
        }
1009
        else
1010
#endif
1011
        {       /* F_MON_VGA */
1012
                if (bpp == 16)
1013
                        xstretch = 2; /* hicolor only double pixel width */
1014
                if (use_default_timing) {
1015
                        int linesize;
1016
 
1017
                        /* Choose master pixelclock depending on hor. timing */
1018
                        plen = 1 * xstretch;
1019
                        if ((plen * xres + f25.right+f25.hsync+f25.left) * hfmin < f25.f)
1020
                                pclock = &f25;
1021
                        else if ((plen * xres + f32.right+f32.hsync+f32.left) * hfmin < f32.f)
1022
                                pclock = &f32;
1023
                        else if ((plen * xres + fext.right+fext.hsync+fext.left) * hfmin < fext.f
1024
                                 && fext.f)
1025
                                pclock = &fext;
1026
                        else
1027
                                return -EINVAL;
1028
 
1029
                        left_margin = pclock->left / plen;
1030
                        right_margin = pclock->right / plen;
1031
                        hsync_len = pclock->hsync / plen;
1032
                        linesize = left_margin + xres + right_margin + hsync_len;
1033
                        upper_margin = 31;
1034
                        lower_margin = 11;
1035
                        vsync_len = 3;
1036
                }
1037
                else {
1038
#if 0 /* TODO enable this (untested yet) */
1039
                        /* Round down pixelclock */
1040
                        int i; unsigned long pcl=0;
1041
                        for (i=1; i<=4; i*=2) {
1042
                                if (f25.t*i<=var->pixclock && pcl<f25.t*i) {
1043
                                        pcl=f25.t*i; pclock=&f25;
1044
                                }
1045
                                if (f32.t*i<=var->pixclock && pcl<f32.t*i) {
1046
                                        pcl=f32.t*i; pclock=&f32;
1047
                                }
1048
                                if (fext.t && fext.t*i<=var->pixclock && pcl<fext.t*i) {
1049
                                        pcl=fext.t*i; pclock=&fext;
1050
                                }
1051
                        }
1052
                        if (!pcl)
1053
                                return -EINVAL;
1054
                        plen = pcl / pclock->t;
1055
 
1056
#else
1057
                        if (var->pixclock == f25.t || var->pixclock == 2*f25.t)
1058
                                pclock = &f25;
1059
                        else if (var->pixclock == f32.t || var->pixclock == 2*f32.t)
1060
                                pclock = &f32;
1061
                        else if ((var->pixclock == fext.t || var->pixclock == 2*fext.t) && fext.t) {
1062
                                pclock = &fext;
1063
                        }
1064
                        else
1065
                                return -EINVAL;
1066
                        plen = var->pixclock / pclock->t;
1067
#endif
1068
 
1069
                        left_margin = var->left_margin;
1070
                        right_margin = var->right_margin;
1071
                        hsync_len = var->hsync_len;
1072
                        upper_margin = var->upper_margin;
1073
                        lower_margin = var->lower_margin;
1074
                        vsync_len = var->vsync_len;
1075
                        if (var->vmode & FB_VMODE_INTERLACED) {
1076
                                /* # lines in half frame */
1077
                                upper_margin = (upper_margin + 1) / 2;
1078
                                lower_margin = (lower_margin + 1) / 2;
1079
                                vsync_len = (vsync_len + 1) / 2;
1080
                        }
1081
                }
1082
                if (pclock == &fext)
1083
                        longoffset = 1; /* VIDEL doesn't synchronize on short offset */
1084
        }
1085
        /* Is video bus bandwidth (32MB/s) too low for this resolution? */
1086
        /* this is definitely wrong if bus clock != 32MHz */
1087
        if (pclock->f / plen / 8 * bpp > 32000000L)
1088
                return -EINVAL;
1089
 
1090
        if (vsync_len < 1)
1091
                vsync_len = 1;
1092
 
1093
        /* include sync lengths in right/lower margin for all calculations */
1094
        right_margin += hsync_len;
1095
        lower_margin += vsync_len;
1096
 
1097
        /* ! In all calculations of margins we use # of lines in half frame
1098
         * (which is a full frame in non-interlace mode), so we can switch
1099
         * between interlace and non-interlace without messing around
1100
         * with these.
1101
         */
1102
  again:
1103
        /* Set base_offset 128 and video bus width */
1104
        par->hw.falcon.vid_control = mon_type | f030_bus_width;
1105
        if (!longoffset)
1106
                par->hw.falcon.vid_control |= VCO_SHORTOFFS;    /* base_offset 64 */
1107
        if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1108
                par->hw.falcon.vid_control |= VCO_HSYPOS;
1109
        if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1110
                par->hw.falcon.vid_control |= VCO_VSYPOS;
1111
        /* Pixelclock */
1112
        par->hw.falcon.vid_control |= pclock->control_mask;
1113
        /* External or internal clock */
1114
        par->hw.falcon.sync = pclock->sync_mask | 0x2;
1115
        /* Pixellength and prescale */
1116
        par->hw.falcon.vid_mode = (2/plen) << 2;
1117
        if (doubleline)
1118
                par->hw.falcon.vid_mode |= VMO_DOUBLE;
1119
        if (interlace)
1120
                par->hw.falcon.vid_mode |= VMO_INTER;
1121
 
1122
        /*********************
1123
        Horizontal timing: unit = [master clock cycles]
1124
        unit of hxx-registers: [master clock cycles * prescale]
1125
        Hxx-registers are 9-bit wide
1126
 
1127
        1 line = ((hht + 2) * 2 * prescale) clock cycles
1128
 
1129
        graphic output = hdb & 0x200 ?
1130
               ((hht+2)*2 - hdb + hde) * prescale - hdboff + hdeoff:
1131
               ( hht + 2  - hdb + hde) * prescale - hdboff + hdeoff
1132
        (this must be a multiple of plen*128/bpp, on VGA pixels
1133
         to the right may be cut off with a bigger right margin)
1134
 
1135
        start of graphics relative to start of 1st halfline = hdb & 0x200 ?
1136
               (hdb - hht - 2) * prescale + hdboff :
1137
               hdb * prescale + hdboff
1138
 
1139
        end of graphics relative to start of 1st halfline =
1140
               (hde + hht + 2) * prescale + hdeoff
1141
        *********************/
1142
        /* Calculate VIDEL registers */
1143
        {
1144
        int hdb_off, hde_off, base_off;
1145
        int gstart, gend1, gend2, align;
1146
 
1147
        prescale = hxx_prescale(&par->hw.falcon);
1148
        base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128;
1149
 
1150
        /* Offsets depend on video mode */
1151
        /* Offsets are in clock cycles, divide by prescale to
1152
         * calculate hd[be]-registers
1153
         */
1154
        if (par->hw.falcon.f_shift & 0x100) {
1155
                align = 1;
1156
                hde_off = 0;
1157
                hdb_off = (base_off + 16 * plen) + prescale;
1158
        }
1159
        else {
1160
                align = 128 / bpp;
1161
                hde_off = ((128 / bpp + 2) * plen);
1162
                if (par->hw.falcon.ste_mode)
1163
                        hdb_off = (64 + base_off + (128 / bpp + 2) * plen) + prescale;
1164
                else
1165
                        hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale;
1166
        }
1167
 
1168
        gstart = (prescale/2 + plen * left_margin) / prescale;
1169
        /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
1170
        gend1 = gstart + ((xres + align-1) / align)*align * plen / prescale;
1171
        /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
1172
        gend2 = gstart + xres * plen / prescale;
1173
        par->HHT = plen * (left_margin + xres + right_margin) /
1174
                           (2 * prescale) - 2;
1175
/*      par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
1176
 
1177
        par->HDB = gstart - hdb_off/prescale;
1178
        par->HBE = gstart;
1179
        if (par->HDB < 0) par->HDB += par->HHT + 2 + 0x200;
1180
        par->HDE = gend1 - par->HHT - 2 - hde_off/prescale;
1181
        par->HBB = gend2 - par->HHT - 2;
1182
#if 0
1183
        /* One more Videl constraint: data fetch of two lines must not overlap */
1184
        if (par->HDB & 0x200  &&  par->HDB & ~0x200 - par->HDE <= 5) {
1185
                /* if this happens increase margins, decrease hfreq. */
1186
        }
1187
#endif
1188
        if (hde_off % prescale)
1189
                par->HBB++;             /* compensate for non matching hde and hbb */
1190
        par->HSS = par->HHT + 2 - plen * hsync_len / prescale;
1191
        if (par->HSS < par->HBB)
1192
                par->HSS = par->HBB;
1193
        }
1194
 
1195
        /*  check hor. frequency */
1196
        hfreq = pclock->f / ((par->HHT+2)*prescale*2);
1197
        if (hfreq > hfmax && mon_type!=F_MON_VGA) {
1198
                /* ++guenther:   ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
1199
                /* Too high -> enlarge margin */
1200
                left_margin += 1;
1201
                right_margin += 1;
1202
                goto again;
1203
        }
1204
        if (hfreq > hfmax || hfreq < hfmin)
1205
                return -EINVAL;
1206
 
1207
        /* Vxx-registers */
1208
        /* All Vxx must be odd in non-interlace, since frame starts in the middle
1209
         * of the first displayed line!
1210
         * One frame consists of VFT+1 half lines. VFT+1 must be even in
1211
         * non-interlace, odd in interlace mode for synchronisation.
1212
         * Vxx-registers are 11-bit wide
1213
         */
1214
        par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */
1215
        par->VDB = par->VBE;
1216
        par->VDE = yres;
1217
        if (!interlace) par->VDE <<= 1;
1218
        if (doubleline) par->VDE <<= 1;  /* VDE now half lines per (half-)frame */
1219
        par->VDE += par->VDB;
1220
        par->VBB = par->VDE;
1221
        par->VFT = par->VBB + (lower_margin * 2 - 1) - 1;
1222
        par->VSS = par->VFT+1 - (vsync_len * 2 - 1);
1223
        /* vbb,vss,vft must be even in interlace mode */
1224
        if (interlace) {
1225
                par->VBB++;
1226
                par->VSS++;
1227
                par->VFT++;
1228
        }
1229
 
1230
        /* V-frequency check, hope I didn't create any loop here. */
1231
        /* Interlace and doubleline are mutually exclusive. */
1232
        vfreq = (hfreq * 2) / (par->VFT + 1);
1233
        if      (vfreq > vfmax && !doubleline && !interlace) {
1234
                /* Too high -> try again with doubleline */
1235
                doubleline = 1;
1236
                goto again;
1237
        }
1238
        else if (vfreq < vfmin && !interlace && !doubleline) {
1239
                /* Too low -> try again with interlace */
1240
                interlace = 1;
1241
                goto again;
1242
        }
1243
        else if (vfreq < vfmin && doubleline) {
1244
                /* Doubleline too low -> clear doubleline and enlarge margins */
1245
                int lines;
1246
                doubleline = 0;
1247
                for (lines=0; (hfreq*2)/(par->VFT+1+4*lines-2*yres)>vfmax; lines++)
1248
                        ;
1249
                upper_margin += lines;
1250
                lower_margin += lines;
1251
                goto again;
1252
        }
1253
        else if (vfreq > vfmax && interlace) {
1254
                /* Interlace, too high -> enlarge margins */
1255
                int lines;
1256
                for (lines=0; (hfreq*2)/(par->VFT+1+4*lines)>vfmax; lines++)
1257
                        ;
1258
                upper_margin += lines;
1259
                lower_margin += lines;
1260
                goto again;
1261
        }
1262
        else if (vfreq < vfmin || vfreq > vfmax)
1263
                return -EINVAL;
1264
 
1265
  set_screen_base:
1266
        linelen = xres_virtual * bpp / 8;
1267
        if ((var->yoffset + yres)*linelen > screen_len && screen_len)
1268
                return -EINVAL;
1269
        if (var->yres_virtual * linelen > screen_len && screen_len)
1270
                return -EINVAL;
1271
        if (var->yres * linelen > screen_len && screen_len)
1272
                return -EINVAL;
1273
        par->vyres = yres_virtual;
1274
        par->screen_base = screen_base + var->yoffset * linelen;
1275
        par->hw.falcon.xoffset = 0;
1276
 
1277
        return 0;
1278
}
1279
 
1280
static int falcon_encode_var( struct fb_var_screeninfo *var,
1281
                                                          struct atari_fb_par *par )
1282
{
1283
/* !!! only for VGA !!! */
1284
        int linelen, i;
1285
        int prescale, plen;
1286
        int hdb_off, hde_off, base_off;
1287
        struct falcon_hw *hw = &par->hw.falcon;
1288
 
1289
        /* possible frequencies: 25.175 or 32MHz */
1290
        var->pixclock = hw->sync & 0x1 ? fext.t :
1291
                        hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t;
1292
 
1293
        var->height=-1;
1294
        var->width=-1;
1295
 
1296
        var->sync=0;
1297
        if (hw->vid_control & VCO_HSYPOS)
1298
                var->sync |= FB_SYNC_HOR_HIGH_ACT;
1299
        if (hw->vid_control & VCO_VSYPOS)
1300
                var->sync |= FB_SYNC_VERT_HIGH_ACT;
1301
 
1302
        var->vmode = FB_VMODE_NONINTERLACED;
1303
        if (hw->vid_mode & VMO_INTER)
1304
                var->vmode |= FB_VMODE_INTERLACED;
1305
        if (hw->vid_mode & VMO_DOUBLE)
1306
                var->vmode |= FB_VMODE_DOUBLE;
1307
 
1308
        /* visible y resolution:
1309
         * Graphics display starts at line VDB and ends at line
1310
         * VDE. If interlace mode off unit of VC-registers is
1311
         * half lines, else lines.
1312
         */
1313
        var->yres = hw->vde - hw->vdb;
1314
        if (!(var->vmode & FB_VMODE_INTERLACED))
1315
                var->yres >>= 1;
1316
        if (var->vmode & FB_VMODE_DOUBLE)
1317
                var->yres >>= 1;
1318
 
1319
        /* to get bpp, we must examine f_shift and st_shift.
1320
         * f_shift is valid if any of bits no. 10, 8 or 4
1321
         * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
1322
         * if bit 10 set then bit 8 and bit 4 don't care...
1323
         * If all these bits are 0 get display depth from st_shift
1324
         * (as for ST and STE)
1325
         */
1326
        if (hw->f_shift & 0x400)                /* 2 colors */
1327
                var->bits_per_pixel = 1;
1328
        else if (hw->f_shift & 0x100)   /* hicolor */
1329
                var->bits_per_pixel = 16;
1330
        else if (hw->f_shift & 0x010)   /* 8 bitplanes */
1331
                var->bits_per_pixel = 8;
1332
        else if (hw->st_shift == 0)
1333
                var->bits_per_pixel = 4;
1334
        else if (hw->st_shift == 0x100)
1335
                var->bits_per_pixel = 2;
1336
        else /* if (hw->st_shift == 0x200) */
1337
                var->bits_per_pixel = 1;
1338
 
1339
        var->xres = hw->line_width * 16 / var->bits_per_pixel;
1340
        var->xres_virtual = var->xres + hw->line_offset * 16 / var->bits_per_pixel;
1341
        if (hw->xoffset)
1342
                var->xres_virtual += 16;
1343
 
1344
        if (var->bits_per_pixel == 16) {
1345
                var->red.offset=11;
1346
                var->red.length=5;
1347
                var->red.msb_right=0;
1348
                var->green.offset=5;
1349
                var->green.length=6;
1350
                var->green.msb_right=0;
1351
                var->blue.offset=0;
1352
                var->blue.length=5;
1353
                var->blue.msb_right=0;
1354
        }
1355
        else {
1356
                var->red.offset=0;
1357
                var->red.length = hw->ste_mode ? 4 : 6;
1358
                var->red.msb_right=0;
1359
                var->grayscale=0;
1360
                var->blue=var->green=var->red;
1361
        }
1362
        var->transp.offset=0;
1363
        var->transp.length=0;
1364
        var->transp.msb_right=0;
1365
 
1366
        linelen = var->xres_virtual * var->bits_per_pixel / 8;
1367
        if (screen_len)
1368
                if (par->vyres)
1369
                        var->yres_virtual = par->vyres;
1370
                else
1371
                        var->yres_virtual=screen_len/linelen;
1372
        else {
1373
                if (hwscroll < 0)
1374
                        var->yres_virtual = 2 * var->yres;
1375
                else
1376
                        var->yres_virtual=var->yres+hwscroll * 16;
1377
        }
1378
        var->xoffset=0; /* TODO change this */
1379
 
1380
        /* hdX-offsets */
1381
        prescale = hxx_prescale(hw);
1382
        plen = 4 >> (hw->vid_mode >> 2 & 0x3);
1383
        base_off = hw->vid_control & VCO_SHORTOFFS ? 64 : 128;
1384
        if (hw->f_shift & 0x100) {
1385
                hde_off = 0;
1386
                hdb_off = (base_off + 16 * plen) + prescale;
1387
        }
1388
        else {
1389
                hde_off = ((128 / var->bits_per_pixel + 2) * plen);
1390
                if (hw->ste_mode)
1391
                        hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)
1392
                                         + prescale;
1393
                else
1394
                        hdb_off = (base_off + (128 / var->bits_per_pixel + 18) * plen)
1395
                                         + prescale;
1396
        }
1397
 
1398
        /* Right margin includes hsync */
1399
        var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) -
1400
                                           (hw->hdb & 0x200 ? 2+hw->hht : 0));
1401
        if (hw->ste_mode || mon_type!=F_MON_VGA)
1402
                var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off;
1403
        else
1404
                /* can't use this in ste_mode, because hbb is +1 off */
1405
                var->right_margin = prescale * (hw->hht + 2 - hw->hbb);
1406
        var->hsync_len = prescale * (hw->hht + 2 - hw->hss);
1407
 
1408
        /* Lower margin includes vsync */
1409
        var->upper_margin = hw->vdb / 2 ;  /* round down to full lines */
1410
        var->lower_margin = (hw->vft+1 - hw->vde + 1) / 2; /* round up */
1411
        var->vsync_len    = (hw->vft+1 - hw->vss + 1) / 2; /* round up */
1412
        if (var->vmode & FB_VMODE_INTERLACED) {
1413
                var->upper_margin *= 2;
1414
                var->lower_margin *= 2;
1415
                var->vsync_len *= 2;
1416
        }
1417
 
1418
        var->pixclock *= plen;
1419
        var->left_margin /= plen;
1420
        var->right_margin /= plen;
1421
        var->hsync_len /= plen;
1422
 
1423
        var->right_margin -= var->hsync_len;
1424
        var->lower_margin -= var->vsync_len;
1425
 
1426
        if (screen_base)
1427
                var->yoffset=(par->screen_base - screen_base)/linelen;
1428
        else
1429
                var->yoffset=0;
1430
        var->nonstd=0;   /* what is this for? */
1431
        var->activate=0;
1432
        for (i=0; i<arraysize(var->reserved); i++)
1433
                var->reserved[i]=0;
1434
        return 0;
1435
}
1436
 
1437
 
1438
static int f_change_mode = 0;
1439
static struct falcon_hw f_new_mode;
1440
static int f_pan_display = 0;
1441
 
1442
static void falcon_get_par( struct atari_fb_par *par )
1443
{
1444
        unsigned long addr;
1445
        struct falcon_hw *hw = &par->hw.falcon;
1446
 
1447
        hw->line_width = shifter_f030.scn_width;
1448
        hw->line_offset = shifter_f030.off_next;
1449
        hw->st_shift = videl.st_shift & 0x300;
1450
        hw->f_shift = videl.f_shift;
1451
        hw->vid_control = videl.control;
1452
        hw->vid_mode = videl.mode;
1453
        hw->sync = shifter.syncmode & 0x1;
1454
        hw->xoffset = videl.xoffset & 0xf;
1455
        hw->hht = videl.hht;
1456
        hw->hbb = videl.hbb;
1457
        hw->hbe = videl.hbe;
1458
        hw->hdb = videl.hdb;
1459
        hw->hde = videl.hde;
1460
        hw->hss = videl.hss;
1461
        hw->vft = videl.vft;
1462
        hw->vbb = videl.vbb;
1463
        hw->vbe = videl.vbe;
1464
        hw->vdb = videl.vdb;
1465
        hw->vde = videl.vde;
1466
        hw->vss = videl.vss;
1467
 
1468
        addr = (shifter.bas_hi & 0xff) << 16 |
1469
               (shifter.bas_md & 0xff) << 8  |
1470
               (shifter.bas_lo & 0xff);
1471
        par->screen_base = PTOV(addr);
1472
 
1473
        /* derived parameters */
1474
        hw->ste_mode = (hw->f_shift & 0x510)==0 && hw->st_shift==0x100;
1475
        hw->mono = (hw->f_shift & 0x400) ||
1476
                   ((hw->f_shift & 0x510)==0 && hw->st_shift==0x200);
1477
}
1478
 
1479
static void falcon_set_par( struct atari_fb_par *par )
1480
{
1481
        f_change_mode = 0;
1482
 
1483
        /* only set screen_base if really necessary */
1484
        if (current_par.screen_base != par->screen_base)
1485
                fbhw->set_screen_base(par->screen_base);
1486
 
1487
        /* Don't touch any other registers if we keep the default resolution */
1488
        if (DontCalcRes)
1489
                return;
1490
 
1491
        /* Tell vbl-handler to change video mode.
1492
         * We change modes only on next VBL, to avoid desynchronisation
1493
         * (a shift to the right and wrap around by a random number of pixels
1494
         * in all monochrome modes).
1495
         * This seems to work on my Falcon.
1496
         */
1497
        f_new_mode = par->hw.falcon;
1498
        f_change_mode = 1;
1499
}
1500
 
1501
 
1502
static void falcon_vbl_switcher( int irq, struct pt_regs *fp, void *dummy )
1503
{
1504
        struct falcon_hw *hw = &f_new_mode;
1505
 
1506
        if (f_change_mode) {
1507
                f_change_mode = 0;
1508
 
1509
                if (hw->sync & 0x1) {
1510
                        /* Enable external pixelclock. This code only for ScreenWonder */
1511
                        *(volatile unsigned short*)0xffff9202 = 0xffbf;
1512
                }
1513
                else {
1514
                        /* Turn off external clocks. Read sets all output bits to 1. */
1515
                        *(volatile unsigned short*)0xffff9202;
1516
                }
1517
                shifter.syncmode = hw->sync;
1518
 
1519
                videl.hht = hw->hht;
1520
                videl.hbb = hw->hbb;
1521
                videl.hbe = hw->hbe;
1522
                videl.hdb = hw->hdb;
1523
                videl.hde = hw->hde;
1524
                videl.hss = hw->hss;
1525
                videl.vft = hw->vft;
1526
                videl.vbb = hw->vbb;
1527
                videl.vbe = hw->vbe;
1528
                videl.vdb = hw->vdb;
1529
                videl.vde = hw->vde;
1530
                videl.vss = hw->vss;
1531
 
1532
                /*f030_sreg[2] = 0;*/
1533
 
1534
                videl.f_shift = 0; /* write enables Falcon palette, 0: 4 planes */
1535
                if (hw->ste_mode) {
1536
                        videl.st_shift = hw->st_shift; /* write enables STE palette */
1537
                }
1538
                else {
1539
                        /* IMPORTANT:
1540
                         * set st_shift 0, so we can tell the screen-depth if f_shift==0.
1541
                         * Writing 0 to f_shift enables 4 plane Falcon mode but
1542
                         * doesn't set st_shift. st_shift!=0 (!=4planes) is impossible
1543
                         * with Falcon palette.
1544
                         */
1545
                        videl.st_shift = 0;
1546
                        /* now back to Falcon palette mode */
1547
                        videl.f_shift = hw->f_shift;
1548
                }
1549
                /* writing to st_shift changed scn_width and vid_mode */
1550
                videl.xoffset = hw->xoffset;
1551
                shifter_f030.scn_width = hw->line_width;
1552
                shifter_f030.off_next = hw->line_offset;
1553
                videl.control = hw->vid_control;
1554
                videl.mode = hw->vid_mode;
1555
        }
1556
        if (f_pan_display) {
1557
                f_pan_display = 0;
1558
                videl.xoffset = current_par.hw.falcon.xoffset;
1559
                shifter_f030.off_next = current_par.hw.falcon.line_offset;
1560
        }
1561
}
1562
 
1563
 
1564
static int falcon_pan_display( struct fb_var_screeninfo *var,
1565
                                                           struct atari_fb_par *par )
1566
{
1567
        int xoffset;
1568
 
1569
        if (disp[currcon].var.bits_per_pixel == 1)
1570
                var->xoffset = up(var->xoffset, 32);
1571
        par->hw.falcon.xoffset = var->xoffset & 15;
1572
        par->hw.falcon.line_offset = disp[currcon].var.bits_per_pixel *
1573
                  (disp[currcon].var.xres_virtual - disp[currcon].var.xres) / 16;
1574
        if (par->hw.falcon.xoffset)
1575
                par->hw.falcon.line_offset -= disp[currcon].var.bits_per_pixel;
1576
        xoffset = var->xoffset - par->hw.falcon.xoffset;
1577
 
1578
        par->screen_base
1579
                = screen_base + (var->yoffset * disp[currcon].var.xres_virtual +
1580
                                xoffset) * disp[currcon].var.bits_per_pixel / 8;
1581
        if (fbhw->set_screen_base)
1582
                fbhw->set_screen_base (par->screen_base);
1583
        else
1584
                return -EINVAL; /* shouldn't happen */
1585
        f_pan_display = 1;
1586
        return 0;
1587
}
1588
 
1589
 
1590
static int falcon_getcolreg( unsigned regno, unsigned *red,
1591
                                 unsigned *green, unsigned *blue,
1592
                                 unsigned *transp )
1593
{       unsigned long col;
1594
 
1595
        if (regno > 255)
1596
                return 1;
1597
        /* This works in STE-mode (with 4bit/color) since f030_col-registers
1598
         * hold up to 6bit/color.
1599
         * Even with hicolor r/g/b=5/6/5 bit!
1600
         */
1601
        col = f030_col[regno];
1602
        *red = (col >> 26) & 0x3f;
1603
        *green = (col >> 18) & 0x3f;
1604
        *blue = (col >> 2) & 0x3f;
1605
        *transp = 0;
1606
        return 0;
1607
}
1608
 
1609
 
1610
static int falcon_setcolreg( unsigned regno, unsigned red,
1611
                                                         unsigned green, unsigned blue,
1612
                                                         unsigned transp )
1613
{
1614
        if (regno > 255)
1615
                return 1;
1616
        f030_col[regno] = (red << 26) | (green << 18) | (blue << 2);
1617
        if (regno < 16) {
1618
                shifter_tt.color_reg[regno] =
1619
                        (((red & 0xe) >> 1) | ((red & 1) << 3) << 8) |
1620
                        (((green & 0xe) >> 1) | ((green & 1) << 3) << 4) |
1621
                        ((blue & 0xe) >> 1) | ((blue & 1) << 3);
1622
                packed16_cmap[regno] = (red << 11) | (green << 5) | blue;
1623
        }
1624
        return 0;
1625
}
1626
 
1627
 
1628
static int falcon_blank( int blank_mode )
1629
{
1630
/* ++guenther: we can switch off graphics by changing VDB and VDE,
1631
 * so VIDEL doesn't hog the bus while saving.
1632
 * (this affects usleep()).
1633
 */
1634
        if (mon_type == F_MON_SM)       /* this doesn't work on SM124 */
1635
                return 1;
1636
        if (blank_mode) {
1637
                /* disable graphics output (this speeds up the CPU) ... */
1638
                videl.vdb = current_par.VFT + 1;
1639
                /* ... and blank all lines */
1640
                videl.hbe = current_par.HHT + 2;
1641
                /* VESA suspend mode, switch off HSYNC */
1642
                if (pwrsave && mon_type == F_MON_VGA)
1643
                        videl.hss = current_par.HHT + 2;
1644
        }
1645
        else {
1646
                videl.vdb = current_par.VDB;
1647
                videl.hbe = current_par.HBE;
1648
                videl.hss = current_par.HSS;
1649
        }
1650
        return 0;
1651
}
1652
 
1653
 
1654
static int falcon_detect( void )
1655
{
1656
        struct atari_fb_par par;
1657
        unsigned char fhw;
1658
 
1659
        /* Determine connected monitor and set monitor parameters */
1660
        fhw = *(unsigned char*)0xffff8006;
1661
        mon_type = fhw >> 6 & 0x3;
1662
        /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
1663
        f030_bus_width = fhw << 6 & 0x80;
1664
        switch (mon_type) {
1665
        case F_MON_SM:
1666
                vfmin = 70;
1667
                vfmax = 72;
1668
                hfmin = 35713;
1669
                hfmax = 35715;
1670
                break;
1671
        case F_MON_SC:
1672
        case F_MON_TV:
1673
                vfmin = 50;
1674
                vfmax = 60;
1675
                hfmin = 15624;
1676
                hfmax = 15626;
1677
                break;
1678
        }
1679
        /* initialize hsync-len */
1680
        f25.hsync = h_syncs[mon_type] / f25.t;
1681
        f32.hsync = h_syncs[mon_type] / f32.t;
1682
        if (fext.t)
1683
                fext.hsync = h_syncs[mon_type] / fext.t;
1684
 
1685
        falcon_get_par(&par);
1686
        falcon_encode_var(&atari_fb_predefined[0], &par);
1687
 
1688
        /* Detected mode is always the "autodetect" slot */
1689
        return 1;
1690
}
1691
 
1692
#endif /* ATAFB_FALCON */
1693
 
1694
/* ------------------- ST(E) specific functions ---------------------- */
1695
 
1696
#ifdef ATAFB_STE
1697
 
1698
static int stste_encode_fix( struct fb_fix_screeninfo *fix,
1699
                                                         struct atari_fb_par *par )
1700
 
1701
{
1702
        int mode, i;
1703
 
1704
        strcpy(fix->id,"Atari Builtin");
1705
        fix->smem_start=real_screen_base;
1706
        fix->smem_len=screen_len;
1707
        fix->type=FB_TYPE_INTERLEAVED_PLANES;
1708
        fix->type_aux=2;
1709
        fix->visual=FB_VISUAL_PSEUDOCOLOR;
1710
        mode = par->hw.st.mode & 3;
1711
        if (mode == ST_HIGH) {
1712
                fix->type=FB_TYPE_PACKED_PIXELS;
1713
                fix->type_aux=0;
1714
                fix->visual=FB_VISUAL_MONO10;
1715
        }
1716
        fix->xpanstep = 0;
1717
        if (ATARIHW_PRESENT(EXTD_SHIFTER))
1718
                fix->ypanstep = 1;
1719
        else
1720
                fix->ypanstep = 0;
1721
        fix->ywrapstep = 0;
1722
        fix->line_length = 0;
1723
        for (i=0; i<arraysize(fix->reserved); i++)
1724
                fix->reserved[i]=0;
1725
        return 0;
1726
}
1727
 
1728
 
1729
static int stste_decode_var( struct fb_var_screeninfo *var,
1730
                                                  struct atari_fb_par *par )
1731
{
1732
        int xres=var->xres;
1733
        int yres=var->yres;
1734
        int bpp=var->bits_per_pixel;
1735
        int linelen;
1736
 
1737
        if (mono_moni) {
1738
                if (bpp > 1 || xres > sttt_xres || yres > st_yres)
1739
                        return -EINVAL;
1740
                par->hw.st.mode=ST_HIGH;
1741
                xres=sttt_xres;
1742
                yres=st_yres;
1743
                bpp=1;
1744
        } else {
1745
                if (bpp > 4 || xres > sttt_xres || yres > st_yres)
1746
                        return -EINVAL;
1747
                if (bpp > 2) {
1748
                        if (xres > sttt_xres/2 || yres > st_yres/2)
1749
                                return -EINVAL;
1750
                        par->hw.st.mode=ST_LOW;
1751
                        xres=sttt_xres/2;
1752
                        yres=st_yres/2;
1753
                        bpp=4;
1754
                }
1755
                else if (bpp > 1) {
1756
                        if (xres > sttt_xres || yres > st_yres/2)
1757
                                return -EINVAL;
1758
                        par->hw.st.mode=ST_MID;
1759
                        xres=sttt_xres;
1760
                        yres=st_yres/2;
1761
                        bpp=2;
1762
                }
1763
                else
1764
                        return -EINVAL;
1765
        }
1766
        if (var->sync & FB_SYNC_EXT)
1767
                par->hw.st.sync=(par->hw.st.sync & ~1) | 1;
1768
        else
1769
                par->hw.st.sync=(par->hw.st.sync & ~1);
1770
        linelen=xres*bpp/8;
1771
        if ((var->yoffset + yres)*linelen > screen_len && screen_len)
1772
                return -EINVAL;
1773
        par->screen_base=screen_base+ var->yoffset*linelen;
1774
        return 0;
1775
}
1776
 
1777
static int stste_encode_var( struct fb_var_screeninfo *var,
1778
                                                  struct atari_fb_par *par )
1779
{
1780
        int linelen, i;
1781
        var->red.offset=0;
1782
        var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
1783
        var->red.msb_right=0;
1784
        var->grayscale=0;
1785
 
1786
        var->pixclock=31041;
1787
        var->left_margin=120;           /* these are incorrect */
1788
        var->right_margin=100;
1789
        var->upper_margin=8;
1790
        var->lower_margin=16;
1791
        var->hsync_len=140;
1792
        var->vsync_len=30;
1793
 
1794
        var->height=-1;
1795
        var->width=-1;
1796
 
1797
        if (!(par->hw.st.sync & 1))
1798
                var->sync=0;
1799
        else
1800
                var->sync=FB_SYNC_EXT;
1801
 
1802
        switch (par->hw.st.mode & 3) {
1803
        case ST_LOW:
1804
                var->xres=sttt_xres/2;
1805
                var->yres=st_yres/2;
1806
                var->bits_per_pixel=4;
1807
                break;
1808
        case ST_MID:
1809
                var->xres=sttt_xres;
1810
                var->yres=st_yres/2;
1811
                var->bits_per_pixel=2;
1812
                break;
1813
        case ST_HIGH:
1814
                var->xres=sttt_xres;
1815
                var->yres=st_yres;
1816
                var->bits_per_pixel=1;
1817
                break;
1818
        }
1819
        var->blue=var->green=var->red;
1820
        var->transp.offset=0;
1821
        var->transp.length=0;
1822
        var->transp.msb_right=0;
1823
        var->xres_virtual=sttt_xres_virtual;
1824
        linelen=var->xres_virtual * var->bits_per_pixel / 8;
1825
        ovsc_addlen=linelen*(sttt_yres_virtual - st_yres);
1826
 
1827
        if (! use_hwscroll)
1828
                var->yres_virtual=var->yres;
1829
        else if (screen_len)
1830
                var->yres_virtual=screen_len/linelen;
1831
        else {
1832
                if (hwscroll < 0)
1833
                        var->yres_virtual = 2 * var->yres;
1834
                else
1835
                        var->yres_virtual=var->yres+hwscroll * 16;
1836
        }
1837
        var->xoffset=0;
1838
        if (screen_base)
1839
                var->yoffset=(par->screen_base - screen_base)/linelen;
1840
        else
1841
                var->yoffset=0;
1842
        var->nonstd=0;
1843
        var->activate=0;
1844
        var->vmode=FB_VMODE_NONINTERLACED;
1845
        for (i=0; i<arraysize(var->reserved); i++)
1846
                var->reserved[i]=0;
1847
        return 0;
1848
}
1849
 
1850
 
1851
static void stste_get_par( struct atari_fb_par *par )
1852
{
1853
        unsigned long addr;
1854
        par->hw.st.mode=shifter_tt.st_shiftmode;
1855
        par->hw.st.sync=shifter.syncmode;
1856
        addr = ((shifter.bas_hi & 0xff) << 16) |
1857
               ((shifter.bas_md & 0xff) << 8);
1858
        if (ATARIHW_PRESENT(EXTD_SHIFTER))
1859
                addr |= (shifter.bas_lo & 0xff);
1860
        par->screen_base = PTOV(addr);
1861
}
1862
 
1863
static void stste_set_par( struct atari_fb_par *par )
1864
{
1865
        shifter_tt.st_shiftmode=par->hw.st.mode;
1866
        shifter.syncmode=par->hw.st.sync;
1867
        /* only set screen_base if really necessary */
1868
        if (current_par.screen_base != par->screen_base)
1869
                fbhw->set_screen_base(par->screen_base);
1870
}
1871
 
1872
 
1873
static int stste_getcolreg( unsigned regno, unsigned *red,
1874
                                                        unsigned *green, unsigned *blue,
1875
                                                        unsigned *transp )
1876
{       unsigned col;
1877
 
1878
        if (regno > 15)
1879
                return 1;
1880
        col = shifter_tt.color_reg[regno];
1881
        if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
1882
                *red = ((col >> 7) & 0xe) | ((col >> 11) & 1);
1883
                *green = ((col >> 3) & 0xe) | ((col >> 7) & 1);
1884
                *blue = ((col << 1) & 0xe) | ((col >> 3) & 1);
1885
        }
1886
        else {
1887
                *red = (col >> 8) & 0x7;
1888
                *green = (col >> 4) & 0x7;
1889
                *blue = col & 0x7;
1890
        }
1891
        *transp = 0;
1892
        return 0;
1893
}
1894
 
1895
 
1896
static int stste_setcolreg( unsigned regno, unsigned red,
1897
                                                 unsigned green, unsigned blue,
1898
                                                 unsigned transp )
1899
{
1900
        if (regno > 15)
1901
                return 1;
1902
        if (ATARIHW_PRESENT(EXTD_SHIFTER))
1903
                shifter_tt.color_reg[regno] =
1904
                        (((red & 0xe) >> 1) | ((red & 1) << 3) << 8) |
1905
                        (((green & 0xe) >> 1) | ((green & 1) << 3) << 4) |
1906
                        ((blue & 0xe) >> 1) | ((blue & 1) << 3);
1907
        else
1908
                shifter_tt.color_reg[regno] =
1909
                        ((red & 0x7) << 8) |
1910
                        ((green & 0x7) << 4) |
1911
                        (blue & 0x7);
1912
        return 0;
1913
}
1914
 
1915
 
1916
static int stste_detect( void )
1917
 
1918
{       struct atari_fb_par par;
1919
 
1920
        /* Determine the connected monitor: The DMA sound must be
1921
         * disabled before reading the MFP GPIP, because the Sound
1922
         * Done Signal and the Monochrome Detect are XORed together!
1923
         */
1924
        if (ATARIHW_PRESENT(PCM_8BIT)) {
1925
                tt_dmasnd.ctrl = DMASND_CTRL_OFF;
1926
                udelay(20);     /* wait a while for things to settle down */
1927
        }
1928
        mono_moni = (mfp.par_dt_reg & 0x80) == 0;
1929
 
1930
        stste_get_par(&par);
1931
        stste_encode_var(&atari_fb_predefined[0], &par);
1932
 
1933
        if (!ATARIHW_PRESENT(EXTD_SHIFTER))
1934
                use_hwscroll = 0;
1935
        return 1;
1936
}
1937
 
1938
static void stste_set_screen_base(unsigned long s_base)
1939
{
1940
        unsigned long addr;
1941
        addr= VTOP(s_base);
1942
        /* Setup Screen Memory */
1943
        shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
1944
        shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
1945
        if (ATARIHW_PRESENT(EXTD_SHIFTER))
1946
                shifter.bas_lo=(unsigned char)  (addr & 0x0000ff);
1947
}
1948
 
1949
#endif /* ATAFB_STE */
1950
 
1951
/* Switching the screen size should be done during vsync, otherwise
1952
 * the margins may get messed up. This is a well known problem of
1953
 * the ST's video system.
1954
 *
1955
 * Unfortunately there is hardly any way to find the vsync, as the
1956
 * vertical blank interrupt is no longer in time on machines with
1957
 * overscan type modifications.
1958
 *
1959
 * We can, however, use Timer B to safely detect the black shoulder,
1960
 * but then we've got to guess an appropriate delay to find the vsync.
1961
 * This might not work on every machine.
1962
 *
1963
 * martin_rogge @ ki.maus.de, 8th Aug 1995
1964
 */
1965
 
1966
#define LINE_DELAY  (mono_moni ? 30 : 70)
1967
#define SYNC_DELAY  (mono_moni ? 1500 : 2000)
1968
 
1969
/* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
1970
static void st_ovsc_switch(int switchmode)
1971
{
1972
    unsigned long flags;
1973
    register unsigned char old, new;
1974
 
1975
    if ((switchmode & (SWITCH_ACIA | SWITCH_SND6 | SWITCH_SND7)) == 0)
1976
        return;
1977
    save_flags(flags);
1978
    cli();
1979
 
1980
    mfp.tim_ct_b = 0x10;
1981
    mfp.active_edge |= 8;
1982
    mfp.tim_ct_b = 0;
1983
    mfp.tim_dt_b = 0xf0;
1984
    mfp.tim_ct_b = 8;
1985
    while (mfp.tim_dt_b > 1)    /* TOS does it this way, don't ask why */
1986
        ;
1987
    new = mfp.tim_dt_b;
1988
    do {
1989
        udelay(LINE_DELAY);
1990
        old = new;
1991
        new = mfp.tim_dt_b;
1992
    } while (old != new);
1993
    mfp.tim_ct_b = 0x10;
1994
    udelay(SYNC_DELAY);
1995
 
1996
    if (switchmode == SWITCH_ACIA)
1997
        acia.key_ctrl = (ACIA_DIV64|ACIA_D8N1S|ACIA_RHTID|ACIA_RIE);
1998
    else {
1999
        sound_ym.rd_data_reg_sel = 14;
2000
        sound_ym.wd_data = sound_ym.rd_data_reg_sel | switchmode;
2001
    }
2002
    restore_flags(flags);
2003
}
2004
 
2005
/* ------------------- External Video ---------------------- */
2006
 
2007
#ifdef ATAFB_EXT
2008
 
2009
static int ext_encode_fix( struct fb_fix_screeninfo *fix,
2010
                                                   struct atari_fb_par *par )
2011
 
2012
{
2013
        int i;
2014
 
2015
        strcpy(fix->id,"Unknown Extern");
2016
        fix->smem_start=external_addr;
2017
        fix->smem_len=(external_len + PAGE_SIZE -1) & PAGE_MASK;
2018
        if (external_depth == 1) {
2019
                fix->type = FB_TYPE_PACKED_PIXELS;
2020
                /* The letters 'n' and 'i' in the "atavideo=external:" stand
2021
                 * for "normal" and "inverted", rsp., in the monochrome case */
2022
                fix->visual =
2023
                        (external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
2024
                         external_pmode == FB_TYPE_PACKED_PIXELS) ?
2025
                                FB_VISUAL_MONO10 :
2026
                                        FB_VISUAL_MONO01;
2027
        }
2028
        else {
2029
                switch (external_pmode) {
2030
                        /* All visuals are STATIC, because we don't know how to change
2031
                         * colors :-(
2032
                         */
2033
                    case -1:              /* truecolor */
2034
                        fix->type=FB_TYPE_PACKED_PIXELS;
2035
                        fix->visual=FB_VISUAL_TRUECOLOR;
2036
                        break;
2037
                    case FB_TYPE_PACKED_PIXELS:
2038
                        fix->type=FB_TYPE_PACKED_PIXELS;
2039
                        fix->visual=FB_VISUAL_STATIC_PSEUDOCOLOR;
2040
                        break;
2041
                    case FB_TYPE_PLANES:
2042
                        fix->type=FB_TYPE_PLANES;
2043
                        fix->visual=FB_VISUAL_STATIC_PSEUDOCOLOR;
2044
                        break;
2045
                    case FB_TYPE_INTERLEAVED_PLANES:
2046
                        fix->type=FB_TYPE_INTERLEAVED_PLANES;
2047
                        fix->type_aux=2;
2048
                        fix->visual=FB_VISUAL_STATIC_PSEUDOCOLOR;
2049
                        break;
2050
                }
2051
        }
2052
        fix->xpanstep = 0;
2053
        fix->ypanstep = 0;
2054
        fix->ywrapstep = 0;
2055
        fix->line_length = 0;
2056
        for (i=0; i<arraysize(fix->reserved); i++)
2057
                fix->reserved[i]=0;
2058
        return 0;
2059
}
2060
 
2061
 
2062
static int ext_decode_var( struct fb_var_screeninfo *var,
2063
                                                   struct atari_fb_par *par )
2064
{
2065
        struct fb_var_screeninfo *myvar = &atari_fb_predefined[0];
2066
 
2067
        if (var->bits_per_pixel > myvar->bits_per_pixel ||
2068
                var->xres > myvar->xres ||
2069
                var->yres > myvar->yres ||
2070
                var->xoffset > 0 ||
2071
                var->yoffset > 0)
2072
                return -EINVAL;
2073
        return 0;
2074
}
2075
 
2076
 
2077
static int ext_encode_var( struct fb_var_screeninfo *var,
2078
                                                   struct atari_fb_par *par )
2079
{
2080
        int i;
2081
 
2082
        var->red.offset=0;
2083
        var->red.length=(external_pmode == -1) ? external_depth/3 :
2084
                        (external_vgaiobase ? external_bitspercol : 0);
2085
        var->red.msb_right=0;
2086
        var->grayscale=0;
2087
 
2088
        var->pixclock=31041;
2089
        var->left_margin=120;           /* these are surely incorrect   */
2090
        var->right_margin=100;
2091
        var->upper_margin=8;
2092
        var->lower_margin=16;
2093
        var->hsync_len=140;
2094
        var->vsync_len=30;
2095
 
2096
        var->height=-1;
2097
        var->width=-1;
2098
 
2099
        var->sync=0;
2100
 
2101
        var->xres = external_xres;
2102
        var->yres = external_yres;
2103
        var->bits_per_pixel = external_depth;
2104
 
2105
        var->blue=var->green=var->red;
2106
        var->transp.offset=0;
2107
        var->transp.length=0;
2108
        var->transp.msb_right=0;
2109
        var->xres_virtual=var->xres;
2110
        var->yres_virtual=var->yres;
2111
        var->xoffset=0;
2112
        var->yoffset=0;
2113
        var->nonstd=0;
2114
        var->activate=0;
2115
        var->vmode=FB_VMODE_NONINTERLACED;
2116
        for (i=0; i<arraysize(var->reserved); i++)
2117
                var->reserved[i]=0;
2118
        return 0;
2119
}
2120
 
2121
 
2122
static void ext_get_par( struct atari_fb_par *par )
2123
{
2124
        par->screen_base = external_addr;
2125
}
2126
 
2127
static void ext_set_par( struct atari_fb_par *par )
2128
{
2129
}
2130
 
2131
#define OUTB(port,val) \
2132
        *((unsigned volatile char *) ((port)+external_vgaiobase))=(val)
2133
#define INB(port) \
2134
        (*((unsigned volatile char *) ((port)+external_vgaiobase)))
2135
#define DACDelay                                \
2136
        do {                                    \
2137
                unsigned char tmp=INB(0x3da);   \
2138
                tmp=INB(0x3da);                 \
2139
        } while (0)
2140
 
2141
static int ext_getcolreg( unsigned regno, unsigned *red,
2142
                                                  unsigned *green, unsigned *blue,
2143
                                                  unsigned *transp )
2144
 
2145
{       unsigned char colmask = (1 << external_bitspercol) - 1;
2146
 
2147
        if (! external_vgaiobase)
2148
                return 1;
2149
 
2150
        switch (external_card_type) {
2151
          case IS_VGA:
2152
            OUTB(0x3c7, regno);
2153
            DACDelay;
2154
            *red=INB(0x3c9) & colmask;
2155
            DACDelay;
2156
            *green=INB(0x3c9) & colmask;
2157
            DACDelay;
2158
            *blue=INB(0x3c9) & colmask;
2159
            DACDelay;
2160
            return 0;
2161
 
2162
          case IS_MV300:
2163
            *red = MV300_color[regno].red;
2164
            *green = MV300_color[regno].green;
2165
            *blue = MV300_color[regno].blue;
2166
            *transp=0;
2167
            return 0;
2168
 
2169
          default:
2170
            return 1;
2171
          }
2172
}
2173
 
2174
static int ext_setcolreg( unsigned regno, unsigned red,
2175
                                                  unsigned green, unsigned blue,
2176
                                                  unsigned transp )
2177
 
2178
{       unsigned char colmask = (1 << external_bitspercol) - 1;
2179
 
2180
        if (! external_vgaiobase)
2181
                return 1;
2182
 
2183
        switch (external_card_type) {
2184
          case IS_VGA:
2185
            OUTB(0x3c8, regno);
2186
            DACDelay;
2187
            OUTB(0x3c9, red & colmask);
2188
            DACDelay;
2189
            OUTB(0x3c9, green & colmask);
2190
            DACDelay;
2191
            OUTB(0x3c9, blue & colmask);
2192
            DACDelay;
2193
            return 0;
2194
 
2195
          case IS_MV300:
2196
            MV300_color[regno].red = red;
2197
            MV300_color[regno].green = green;
2198
            MV300_color[regno].blue = blue;
2199
            OUTB((MV300_reg[regno] << 2)+1, red);
2200
            OUTB((MV300_reg[regno] << 2)+1, green);
2201
            OUTB((MV300_reg[regno] << 2)+1, blue);
2202
            return 0;
2203
 
2204
          default:
2205
            return 1;
2206
          }
2207
}
2208
 
2209
 
2210
static int ext_detect( void )
2211
 
2212
{
2213
        struct fb_var_screeninfo *myvar = &atari_fb_predefined[0];
2214
        struct atari_fb_par dummy_par;
2215
 
2216
        myvar->xres = external_xres;
2217
        myvar->yres = external_yres;
2218
        myvar->bits_per_pixel = external_depth;
2219
        ext_encode_var(myvar, &dummy_par);
2220
        return 1;
2221
}
2222
 
2223
#endif /* ATAFB_EXT */
2224
 
2225
/* ------ This is the same for most hardware types -------- */
2226
 
2227
static void set_screen_base(unsigned long s_base)
2228
{
2229
        unsigned long addr;
2230
        addr= VTOP(s_base);
2231
        /* Setup Screen Memory */
2232
        shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
2233
        shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
2234
        shifter.bas_lo=(unsigned char)  (addr & 0x0000ff);
2235
}
2236
 
2237
 
2238
static int pan_display( struct fb_var_screeninfo *var,
2239
                        struct atari_fb_par *par )
2240
{
2241
        if (var->xoffset)
2242
                return -EINVAL;
2243
        par->screen_base
2244
                = screen_base + (var->yoffset * disp[currcon].var.xres_virtual
2245
                                                 * disp[currcon].var.bits_per_pixel / 8);
2246
        if (fbhw->set_screen_base)
2247
                fbhw->set_screen_base (par->screen_base);
2248
        else
2249
                return -EINVAL;
2250
        return 0;
2251
}
2252
 
2253
 
2254
/* ------------ Interfaces to hardware functions ------------ */
2255
 
2256
 
2257
#ifdef ATAFB_TT
2258
struct fb_hwswitch tt_switch = {
2259
        tt_detect, tt_encode_fix, tt_decode_var, tt_encode_var,
2260
        tt_get_par, tt_set_par, tt_getcolreg, tt_setcolreg,
2261
        set_screen_base, NULL, pan_display
2262
};
2263
#endif
2264
 
2265
#ifdef ATAFB_FALCON
2266
struct fb_hwswitch falcon_switch = {
2267
        falcon_detect, falcon_encode_fix, falcon_decode_var, falcon_encode_var,
2268
        falcon_get_par, falcon_set_par, falcon_getcolreg,
2269
        falcon_setcolreg, set_screen_base, falcon_blank, falcon_pan_display
2270
};
2271
#endif
2272
 
2273
#ifdef ATAFB_STE
2274
struct fb_hwswitch st_switch = {
2275
        stste_detect, stste_encode_fix, stste_decode_var, stste_encode_var,
2276
        stste_get_par, stste_set_par, stste_getcolreg, stste_setcolreg,
2277
        stste_set_screen_base, NULL, pan_display
2278
};
2279
#endif
2280
 
2281
#ifdef ATAFB_EXT
2282
struct fb_hwswitch ext_switch = {
2283
        ext_detect, ext_encode_fix, ext_decode_var, ext_encode_var,
2284
        ext_get_par, ext_set_par, ext_getcolreg, ext_setcolreg, NULL, NULL, NULL
2285
};
2286
#endif
2287
 
2288
 
2289
 
2290
static void atari_fb_get_par( struct atari_fb_par *par )
2291
{
2292
        if (current_par_valid) {
2293
                *par=current_par;
2294
        }
2295
        else
2296
                fbhw->get_par(par);
2297
}
2298
 
2299
 
2300
static void atari_fb_set_par( struct atari_fb_par *par )
2301
{
2302
        fbhw->set_par(par);
2303
        current_par=*par;
2304
        current_par_valid=1;
2305
}
2306
 
2307
 
2308
 
2309
/* =========================================================== */
2310
/* ============== Hardware Independent Functions ============= */
2311
/* =========================================================== */
2312
 
2313
 
2314
/* used for hardware scrolling */
2315
 
2316
static int
2317
fb_update_var(int con)
2318
{
2319
        int off=disp[con].var.yoffset*disp[con].var.xres_virtual*
2320
                        disp[con].var.bits_per_pixel>>3;
2321
 
2322
        current_par.screen_base=screen_base + off;
2323
 
2324
        if (fbhw->set_screen_base)
2325
                fbhw->set_screen_base(current_par.screen_base);
2326
        return 0;
2327
}
2328
 
2329
static int
2330
do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
2331
{
2332
        int err,activate;
2333
        struct atari_fb_par par;
2334
        if ((err=fbhw->decode_var(var, &par)))
2335
                return err;
2336
        activate=var->activate;
2337
        if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
2338
                atari_fb_set_par(&par);
2339
        fbhw->encode_var(var, &par);
2340
        var->activate=activate;
2341
        return 0;
2342
}
2343
 
2344
/* Functions for handling colormap */
2345
 
2346
/* there seems to be a bug in gcc 2.5.8 which inhibits using an other solution */
2347
/* I always get a sigsegv */
2348
 
2349
static short red16[]=
2350
        { 0x0000,0x0000,0x0000,0x0000,0xc000,0xc000,0xc000,0xc000,
2351
          0x8000,0x0000,0x0000,0x0000,0xffff,0xffff,0xffff,0xffff};
2352
static short green16[]=
2353
        { 0x0000,0x0000,0xc000,0xc000,0x0000,0x0000,0xc000,0xc000,
2354
          0x8000,0x0000,0xffff,0xffff,0x0000,0x0000,0xffff,0xffff};
2355
static short blue16[]=
2356
        { 0x0000,0xc000,0x0000,0xc000,0x0000,0xc000,0x0000,0xc000,
2357
          0x8000,0xffff,0x0000,0xffff,0x0000,0xffff,0x0000,0xffff};
2358
 
2359
static short red4[]=
2360
        { 0x0000,0xc000,0x8000,0xffff};
2361
static short green4[]=
2362
        { 0x0000,0xc000,0x8000,0xffff};
2363
static short blue4[]=
2364
        { 0x0000,0xc000,0x8000,0xffff};
2365
 
2366
static short red2[]=
2367
        { 0x0000,0xffff};
2368
static short green2[]=
2369
        { 0x0000,0xffff};
2370
static short blue2[]=
2371
        { 0x0000,0xffff};
2372
 
2373
struct fb_cmap default_16_colors = { 0, 16, red16, green16, blue16, NULL };
2374
struct fb_cmap default_4_colors = { 0, 4, red4, green4, blue4, NULL };
2375
struct fb_cmap default_2_colors = { 0, 2, red2, green2, blue2, NULL };
2376
 
2377
static struct fb_cmap *
2378
get_default_colormap(int bpp)
2379
{
2380
        if (bpp == 1)
2381
                return &default_2_colors;
2382
        if (bpp == 2)
2383
                return &default_4_colors;
2384
        return &default_16_colors;
2385
}
2386
 
2387
#define CNVT_TOHW(val,width)    (((val) << (width)) + 0x7fff - (val)) >> 16
2388
#define CNVT_FROMHW(val,width) ((width)?((((val) << 16) - (val)) / ((1<<(width))-1)):0)
2389
 
2390
 
2391
static int
2392
do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, int kspc)
2393
{
2394
        int i,start;
2395
        unsigned short *red,*green,*blue,*transp;
2396
        unsigned int hred,hgreen,hblue,htransp;
2397
 
2398
        red=cmap->red;
2399
        green=cmap->green;
2400
        blue=cmap->blue;
2401
        transp=cmap->transp;
2402
        start=cmap->start;
2403
        if (start < 0)
2404
                return EINVAL;
2405
        for (i=0 ; i < cmap->len ; i++) {
2406
                if (fbhw->getcolreg(start++, &hred, &hgreen, &hblue, &htransp))
2407
                        return 0;
2408
                hred=CNVT_FROMHW(hred,var->red.length);
2409
                hgreen=CNVT_FROMHW(hgreen,var->green.length);
2410
                hblue=CNVT_FROMHW(hblue,var->blue.length);
2411
                htransp=CNVT_FROMHW(htransp,var->transp.length);
2412
                if (kspc) {
2413
                        *red=hred;
2414
                        *green=hgreen;
2415
                        *blue=hblue;
2416
                        if (transp) *transp=htransp;
2417
                }
2418
                else {
2419
                        put_fs_word(hred, red);
2420
                        put_fs_word(hgreen, green);
2421
                        put_fs_word(hblue, blue);
2422
                        if (transp) put_fs_word(htransp, transp);
2423
                }
2424
                red++;
2425
                green++;
2426
                blue++;
2427
                if (transp) transp++;
2428
        }
2429
        return 0;
2430
}
2431
 
2432
static int
2433
do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, int kspc)
2434
{
2435
        int i,start;
2436
        unsigned short *red,*green,*blue,*transp;
2437
        unsigned int hred,hgreen,hblue,htransp;
2438
 
2439
        red=cmap->red;
2440
        green=cmap->green;
2441
        blue=cmap->blue;
2442
        transp=cmap->transp;
2443
        start=cmap->start;
2444
 
2445
        if (start < 0)
2446
                return -EINVAL;
2447
        for (i=0 ; i < cmap->len ; i++) {
2448
                if (kspc) {
2449
                        hred=*red;
2450
                        hgreen=*green;
2451
                        hblue=*blue;
2452
                        htransp=(transp) ? *transp : 0;
2453
                }
2454
                else {
2455
                        hred=get_fs_word(red);
2456
                        hgreen=get_fs_word(green);
2457
                        hblue=get_fs_word(blue);
2458
                        htransp=(transp)?get_fs_word(transp):0;
2459
                }
2460
                hred=CNVT_TOHW(hred,var->red.length);
2461
                hgreen=CNVT_TOHW(hgreen,var->green.length);
2462
                hblue=CNVT_TOHW(hblue,var->blue.length);
2463
                htransp=CNVT_TOHW(htransp,var->transp.length);
2464
                red++;
2465
                green++;
2466
                blue++;
2467
                if (transp) transp++;
2468
                if (fbhw->setcolreg(start++, hred, hgreen, hblue, htransp))
2469
                        return 0;
2470
        }
2471
        return 0;
2472
}
2473
 
2474
static void
2475
do_install_cmap(int con)
2476
{
2477
        if (con != currcon)
2478
                return;
2479
        if (disp[con].cmap.len)
2480
                do_fb_set_cmap(&disp[con].cmap, &(disp[con].var), 1);
2481
        else
2482
                do_fb_set_cmap(get_default_colormap(
2483
                                disp[con].var.bits_per_pixel), &(disp[con].var), 1);
2484
}
2485
 
2486
static void
2487
memcpy_fs(int fsfromto, void *to, void *from, int len)
2488
{
2489
        switch (fsfromto) {
2490
        case 0:
2491
                memcpy(to,from,len);
2492
                return;
2493
        case 1:
2494
                memcpy_fromfs(to,from,len);
2495
                return;
2496
        case 2:
2497
                memcpy_tofs(to,from,len);
2498
                return;
2499
        }
2500
}
2501
 
2502
static void
2503
copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
2504
{
2505
        int size;
2506
        int tooff=0, fromoff=0;
2507
 
2508
        if (to->start > from->start)
2509
                fromoff=to->start-from->start;
2510
        else
2511
                tooff=from->start-to->start;
2512
        size=to->len-tooff;
2513
        if (size > from->len-fromoff)
2514
                size=from->len-fromoff;
2515
        if (size < 0)
2516
                return;
2517
        size*=sizeof(unsigned short);
2518
        memcpy_fs(fsfromto, to->red+tooff, from->red+fromoff, size);
2519
        memcpy_fs(fsfromto, to->green+tooff, from->green+fromoff, size);
2520
        memcpy_fs(fsfromto, to->blue+tooff, from->blue+fromoff, size);
2521
        if (from->transp && to->transp)
2522
                memcpy_fs(fsfromto, to->transp+tooff, from->transp+fromoff, size);
2523
}
2524
 
2525
static int
2526
alloc_cmap(struct fb_cmap *cmap,int len,int transp)
2527
{
2528
        int size=len*sizeof(unsigned short);
2529
        if (cmap->len != len) {
2530
                if (cmap->red)
2531
                        kfree(cmap->red);
2532
                if (cmap->green)
2533
                        kfree(cmap->green);
2534
                if (cmap->blue)
2535
                        kfree(cmap->blue);
2536
                if (cmap->transp)
2537
                        kfree(cmap->transp);
2538
                cmap->red=cmap->green=cmap->blue=cmap->transp=NULL;
2539
                cmap->len=0;
2540
                if (! len)
2541
                        return 0;
2542
                if (! (cmap->red=kmalloc(size, GFP_ATOMIC)))
2543
                        return -1;
2544
                if (! (cmap->green=kmalloc(size, GFP_ATOMIC)))
2545
                        return -1;
2546
                if (! (cmap->blue=kmalloc(size, GFP_ATOMIC)))
2547
                        return -1;
2548
                if (transp) {
2549
                        if (! (cmap->transp=kmalloc(size, GFP_ATOMIC)))
2550
                                return -1;
2551
                }
2552
                else
2553
                        cmap->transp=NULL;
2554
        }
2555
        cmap->start=0;
2556
        cmap->len=len;
2557
        copy_cmap(get_default_colormap(len), cmap, 0);
2558
        return 0;
2559
}
2560
 
2561
static int
2562
atari_fb_get_fix(struct fb_fix_screeninfo *fix, int con)
2563
{
2564
        struct atari_fb_par par;
2565
        if (con == -1)
2566
                atari_fb_get_par(&par);
2567
        else
2568
                fbhw->decode_var(&disp[con].var,&par);
2569
        return fbhw->encode_fix(fix, &par);
2570
}
2571
 
2572
static int
2573
atari_fb_get_var(struct fb_var_screeninfo *var, int con)
2574
{
2575
        struct atari_fb_par par;
2576
        if (con == -1) {
2577
                atari_fb_get_par(&par);
2578
                fbhw->encode_var(var, &par);
2579
        }
2580
        else
2581
                *var=disp[con].var;
2582
        return 0;
2583
}
2584
 
2585
static void
2586
atari_fb_set_disp(int con)
2587
{
2588
        struct fb_fix_screeninfo fix;
2589
 
2590
        atari_fb_get_fix(&fix, con);
2591
        if (con == -1)
2592
                con=0;
2593
        disp[con].screen_base = (u_char *)fix.smem_start;
2594
        disp[con].visual = fix.visual;
2595
        disp[con].type = fix.type;
2596
        disp[con].type_aux = fix.type_aux;
2597
        disp[con].ypanstep = fix.ypanstep;
2598
        disp[con].ywrapstep = fix.ywrapstep;
2599
        disp[con].line_length = fix.line_length;
2600
        if (fix.visual != FB_VISUAL_PSEUDOCOLOR &&
2601
                fix.visual != FB_VISUAL_DIRECTCOLOR)
2602
                disp[con].can_soft_blank = 0;
2603
        else
2604
                disp[con].can_soft_blank = 1;
2605
        disp[con].inverse =
2606
            (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse);
2607
}
2608
 
2609
static int
2610
atari_fb_set_var(struct fb_var_screeninfo *var, int con)
2611
{
2612
        int err,oldxres,oldyres,oldbpp,oldxres_virtual,oldyoffset;
2613
        if ((err=do_fb_set_var(var, con==currcon)))
2614
                return err;
2615
        if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
2616
                oldxres=disp[con].var.xres;
2617
                oldyres=disp[con].var.yres;
2618
                oldxres_virtual=disp[con].var.xres_virtual;
2619
                oldbpp=disp[con].var.bits_per_pixel;
2620
                oldyoffset=disp[con].var.yoffset;
2621
                disp[con].var=*var;
2622
                if (oldxres != var->xres || oldyres != var->yres
2623
                    || oldxres_virtual != var->xres_virtual
2624
                    || oldbpp != var->bits_per_pixel
2625
                    || oldyoffset != var->yoffset) {
2626
                        atari_fb_set_disp(con);
2627
                        (*fb_info.changevar)(con);
2628
                        alloc_cmap(&disp[con].cmap, 0, 0);
2629
                        do_install_cmap(con);
2630
                }
2631
        }
2632
        var->activate=0;
2633
        return 0;
2634
}
2635
 
2636
 
2637
 
2638
static int
2639
atari_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con)
2640
{
2641
        if (con == currcon) /* current console ? */
2642
                return do_fb_get_cmap(cmap, &(disp[con].var), kspc);
2643
        else
2644
                if (disp[con].cmap.len) /* non default colormap ? */
2645
                        copy_cmap(&disp[con].cmap, cmap, kspc ? 0 : 2);
2646
                else
2647
                        copy_cmap(get_default_colormap(
2648
                            disp[con].var.bits_per_pixel), cmap, kspc ? 0 : 2);
2649
        return 0;
2650
}
2651
 
2652
static int
2653
atari_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con)
2654
{
2655
        int err;
2656
        if (! disp[con].cmap.len) { /* no colormap allocated ? */
2657
                if ((err = alloc_cmap(&disp[con].cmap,
2658
                                        1 << disp[con].var.bits_per_pixel, 0)))
2659
                return err;
2660
        }
2661
        if (con == currcon) /* current console ? */
2662
                return do_fb_set_cmap(cmap, &(disp[con].var), kspc);
2663
        else
2664
                copy_cmap(cmap, &disp[con].cmap, kspc ? 0 : 1);
2665
        return 0;
2666
}
2667
 
2668
static int
2669
atari_fb_pan_display(struct fb_var_screeninfo *var, int con)
2670
{
2671
        int xoffset = var->xoffset;
2672
        int yoffset = var->yoffset;
2673
        int err;
2674
 
2675
        if (   xoffset < 0 || xoffset + disp[con].var.xres > disp[con].var.xres_virtual
2676
            || yoffset < 0 || yoffset + disp[con].var.yres > disp[con].var.yres_virtual)
2677
                return -EINVAL;
2678
 
2679
        if (con == currcon) {
2680
                if (fbhw->pan_display) {
2681
                        if ((err = fbhw->pan_display(var, &current_par)))
2682
                                return err;
2683
                }
2684
                else
2685
                        return -EINVAL;
2686
        }
2687
        disp[con].var.xoffset = var->xoffset;
2688
        disp[con].var.yoffset = var->yoffset;
2689
        return 0;
2690
}
2691
 
2692
static int
2693
atari_fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
2694
               unsigned long arg, int con)
2695
{
2696
        int i;
2697
 
2698
        switch (cmd) {
2699
#ifdef FBCMD_GET_CURRENTPAR
2700
        case FBCMD_GET_CURRENTPAR:
2701
                if ((i = verify_area(VERIFY_WRITE, (void *)arg,
2702
                                                         sizeof(struct atari_fb_par))))
2703
                        return i;
2704
                memcpy_tofs((void *)arg, (void *)&current_par,
2705
                                        sizeof(struct atari_fb_par));
2706
                return 0;
2707
#endif
2708
#ifdef FBCMD_SET_CURRENTPAR
2709
        case FBCMD_SET_CURRENTPAR:
2710
                if ((i = verify_area(VERIFY_READ, (void *)arg,
2711
                                                         sizeof(struct atari_fb_par))))
2712
                        return i;
2713
                memcpy_fromfs((void *)&current_par, (void *)arg,
2714
                                        sizeof(struct atari_fb_par));
2715
                atari_fb_set_par(&current_par);
2716
                return 0;
2717
#endif
2718
        }
2719
        return -EINVAL;
2720
}
2721
 
2722
static struct fb_ops atari_fb_ops = {
2723
        atari_fb_get_fix, atari_fb_get_var, atari_fb_set_var, atari_fb_get_cmap,
2724
        atari_fb_set_cmap, atari_fb_pan_display, atari_fb_ioctl
2725
};
2726
 
2727
static void
2728
check_default_par( int detected_mode )
2729
{
2730
        char default_name[10];
2731
        int i;
2732
        struct fb_var_screeninfo var;
2733
        unsigned long min_mem;
2734
 
2735
        /* First try the user supplied mode */
2736
        if (default_par) {
2737
                var=atari_fb_predefined[default_par-1];
2738
                var.activate = FB_ACTIVATE_TEST;
2739
                if (do_fb_set_var(&var,1))
2740
                        default_par=0;           /* failed */
2741
        }
2742
        /* Next is the autodetected one */
2743
        if (! default_par) {
2744
                var=atari_fb_predefined[detected_mode-1]; /* autodetect */
2745
                var.activate = FB_ACTIVATE_TEST;
2746
                if (!do_fb_set_var(&var,1))
2747
                        default_par=detected_mode;
2748
        }
2749
        /* If that also failed, try some default modes... */
2750
        if (! default_par) {
2751
                /* try default1, default2... */
2752
                for (i=1 ; i < 10 ; i++) {
2753
                        sprintf(default_name,"default%d",i);
2754
                        default_par=get_video_mode(default_name);
2755
                        if (! default_par)
2756
                                panic("can't set default video mode\n");
2757
                        var=atari_fb_predefined[default_par-1];
2758
                        var.activate = FB_ACTIVATE_TEST;
2759
                        if (! do_fb_set_var(&var,1))
2760
                                break;  /* ok */
2761
                }
2762
        }
2763
        min_mem=var.xres_virtual * var.yres_virtual * var.bits_per_pixel/8;
2764
        if (default_mem_req < min_mem)
2765
                default_mem_req=min_mem;
2766
}
2767
 
2768
static int
2769
atafb_switch(int con)
2770
{
2771
        /* Do we have to save the colormap ? */
2772
        if (disp[currcon].cmap.len)
2773
                do_fb_get_cmap(&disp[currcon].cmap, &(disp[currcon].var), 1);
2774
        do_fb_set_var(&disp[con].var,1);
2775
        currcon=con;
2776
        /* Install new colormap */
2777
        do_install_cmap(con);
2778
        return 0;
2779
}
2780
 
2781
static void
2782
atafb_blank(int blank)
2783
{
2784
        unsigned short black[16];
2785
        struct fb_cmap cmap;
2786
        if (fbhw->blank && !fbhw->blank(blank))
2787
                return;
2788
        if (blank) {
2789
                memset(black, 0, 16*sizeof(unsigned short));
2790
                cmap.red=black;
2791
                cmap.green=black;
2792
                cmap.blue=black;
2793
                cmap.transp=NULL;
2794
                cmap.start=0;
2795
                cmap.len=16;
2796
                do_fb_set_cmap(&cmap, &(disp[currcon].var), 1);
2797
        }
2798
        else
2799
                do_install_cmap(currcon);
2800
}
2801
 
2802
struct fb_info *
2803
atari_fb_init(long *mem_start)
2804
{
2805
        int err;
2806
        int pad;
2807
        int detected_mode;
2808
        unsigned long mem_req;
2809
        struct fb_var_screeninfo *var;
2810
 
2811
        err=register_framebuffer("Atari Builtin", &node, &atari_fb_ops,
2812
                        num_atari_fb_predefined, atari_fb_predefined);
2813
        if (err < 0)
2814
                panic ("Cannot register frame buffer\n");
2815
        do {
2816
#ifdef ATAFB_EXT
2817
                if (external_addr) {
2818
                        fbhw = &ext_switch;
2819
                        break;
2820
                }
2821
#endif
2822
#ifdef ATAFB_TT
2823
                if (ATARIHW_PRESENT(TT_SHIFTER)) {
2824
                        fbhw = &tt_switch;
2825
                        break;
2826
                }
2827
#endif
2828
#ifdef ATAFB_FALCON
2829
                if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
2830
                        fbhw = &falcon_switch;
2831
                        add_isr(IRQ_AUTO_4, falcon_vbl_switcher, IRQ_TYPE_PRIO, NULL,
2832
                                        "framebuffer/modeswitch");
2833
                        break;
2834
                }
2835
#endif
2836
#ifdef ATAFB_STE
2837
                if (ATARIHW_PRESENT(STND_SHIFTER) ||
2838
                    ATARIHW_PRESENT(EXTD_SHIFTER)) {
2839
                        fbhw = &st_switch;
2840
                        break;
2841
                }
2842
                fbhw = &st_switch;
2843
                printk("Cannot determine video hardware; defaulting to ST(e)\n");
2844
#else /* ATAFB_STE */
2845
                /* no default driver included */
2846
                /* Nobody will ever see this message :-) */
2847
                panic("Cannot initialize video hardware\n");
2848
#endif
2849
        } while (0);
2850
        detected_mode = fbhw->detect();
2851
        check_default_par(detected_mode);
2852
#ifdef ATAFB_EXT
2853
        if (!external_addr) {
2854
#endif /* ATAFB_EXT */
2855
                mem_req = default_mem_req + ovsc_offset +
2856
                        ovsc_addlen;
2857
                mem_req = ((mem_req + PAGE_SIZE - 1) & PAGE_MASK) + PAGE_SIZE;
2858
                screen_base = (unsigned long) atari_stram_alloc(mem_req, mem_start);
2859
                memset((char *) screen_base, 0, mem_req);
2860
                pad = ((screen_base + PAGE_SIZE-1) & PAGE_MASK) - screen_base;
2861
                screen_base+=pad;
2862
                real_screen_base=screen_base+ovsc_offset;
2863
                screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
2864
                st_ovsc_switch(ovsc_switchmode);
2865
                if (m68k_is040or060) {
2866
                        /* On a '040+, the cache mode of video RAM must be set to
2867
                         * write-through also for internal video hardware! */
2868
                        cache_push( VTOP(screen_base), screen_len );
2869
                        kernel_set_cachemode( screen_base, screen_len,
2870
                                                                  KERNELMAP_NO_COPYBACK );
2871
                }
2872
#ifdef ATAFB_EXT
2873
        }
2874
        else {
2875
                /* Map the video memory (physical address given) to somewhere
2876
                 * in the kernel address space.
2877
                 */
2878
                *mem_start = (*mem_start+PAGE_SIZE-1) & ~(PAGE_SIZE-1);
2879
                external_addr = kernel_map(external_addr, external_len,
2880
                                                                        KERNELMAP_NO_COPYBACK, mem_start);
2881
                if (external_vgaiobase)
2882
                        external_vgaiobase = kernel_map(external_vgaiobase,
2883
                                0x10000, KERNELMAP_NOCACHE_SER, mem_start);
2884
                screen_base      =
2885
                real_screen_base = external_addr;
2886
                screen_len       = external_len & PAGE_MASK;
2887
                memset ((char *) screen_base, 0, external_len);
2888
        }
2889
#endif /* ATAFB_EXT */
2890
 
2891
        strcpy(fb_info.modename, "Atari Builtin ");
2892
        fb_info.disp=disp;
2893
        fb_info.switch_con=&atafb_switch;
2894
        fb_info.updatevar=&fb_update_var;
2895
        fb_info.blank=&atafb_blank;
2896
        var=atari_fb_predefined+default_par-1;
2897
        do_fb_set_var(var,1);
2898
        strcat(fb_info.modename,fb_var_names[default_par-1][0]);
2899
 
2900
        atari_fb_get_var(&disp[0].var, -1);
2901
        atari_fb_set_disp(-1);
2902
        printk("Determined %dx%d, depth %d\n",
2903
               disp[0].var.xres, disp[0].var.yres, disp[0].var.bits_per_pixel );
2904
        do_install_cmap(0);
2905
        return &fb_info;
2906
}
2907
 
2908
/* a strtok which returns empty strings, too */
2909
 
2910
static char * strtoke(char * s,const char * ct)
2911
{
2912
  char *sbegin, *send;
2913
  static char *ssave = NULL;
2914
 
2915
  sbegin  = s ? s : ssave;
2916
  if (!sbegin) {
2917
          return NULL;
2918
  }
2919
  if (*sbegin == '\0') {
2920
    ssave = NULL;
2921
    return NULL;
2922
  }
2923
  send = strpbrk(sbegin, ct);
2924
  if (send && *send != '\0')
2925
    *send++ = '\0';
2926
  ssave = send;
2927
  return sbegin;
2928
}
2929
 
2930
void atari_video_setup( char *options, int *ints )
2931
{
2932
    char *this_opt;
2933
    int temp;
2934
    char ext_str[80], int_str[100];
2935
    char mcap_spec[80];
2936
    char user_mode[80];
2937
 
2938
        ext_str[0]          =
2939
        int_str[0]          =
2940
        mcap_spec[0]        =
2941
        user_mode[0]        =
2942
        fb_info.fontname[0] = '\0';
2943
 
2944
    if (!options || !*options)
2945
                return;
2946
 
2947
    for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) {
2948
        if (!*this_opt) continue;
2949
        if ((temp=get_video_mode(this_opt)))
2950
                default_par=temp;
2951
        else if (! strcmp(this_opt, "inverse"))
2952
                inverse=1;
2953
        else if (!strncmp(this_opt, "font:", 5))
2954
           strcpy(fb_info.fontname, this_opt+5);
2955
        else if (! strncmp(this_opt, "hwscroll_",9)) {
2956
                hwscroll=simple_strtoul(this_opt+9, NULL, 10);
2957
                if (hwscroll < 0)
2958
                        hwscroll = 0;
2959
                if (hwscroll > 200)
2960
                        hwscroll = 200;
2961
        }
2962
        else if (! strncmp(this_opt, "sw_",3)) {
2963
                if (! strcmp(this_opt+3, "acia"))
2964
                        ovsc_switchmode = SWITCH_ACIA;
2965
                else if (! strcmp(this_opt+3, "snd6"))
2966
                        ovsc_switchmode = SWITCH_SND6;
2967
                else if (! strcmp(this_opt+3, "snd7"))
2968
                        ovsc_switchmode = SWITCH_SND7;
2969
                else ovsc_switchmode = SWITCH_NONE;
2970
        }
2971
#ifdef ATAFB_EXT
2972
        else if (!strcmp(this_opt,"mv300")) {
2973
                external_bitspercol = 8;
2974
                external_card_type = IS_MV300;
2975
        }
2976
        else if (!strncmp(this_opt,"external:",9))
2977
                strcpy(ext_str, this_opt+9);
2978
#endif
2979
        else if (!strncmp(this_opt,"internal:",9))
2980
                strcpy(int_str, this_opt+9);
2981
#ifdef ATAFB_FALCON
2982
        else if (!strcmp(this_opt, "pwrsave"))
2983
                pwrsave = 1;
2984
        else if (!strncmp(this_opt, "eclock:", 7)) {
2985
                fext.f = simple_strtoul(this_opt+7, NULL, 10);
2986
                /* external pixelclock in kHz --> ps */
2987
                fext.t = (2000000000UL/fext.f+1)/2;
2988
                fext.f *= 1000;
2989
        }
2990
        else if (!strncmp(this_opt, "monitorcap:", 11))
2991
                strcpy(mcap_spec, this_opt+11);
2992
#endif
2993
        else if (!strcmp(this_opt, "keep"))
2994
                DontCalcRes = 1;
2995
        else if (!strncmp(this_opt, "R", 1))
2996
                strcpy(user_mode, this_opt+1);
2997
    }
2998
 
2999
    if (*int_str) {
3000
        /* Format to config extended internal video hardware like OverScan:
3001
        "<switch-type>,internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
3002
        Explanation:
3003
        <switch-type> type to switch on higher resolution
3004
                        sw_acia : via keyboard ACIA
3005
                        sw_snd6 : via bit 6 of the soundchip port
3006
                        sw_snd7 : via bit 7 of the soundchip port
3007
        <xres>: x-resolution
3008
        <yres>: y-resolution
3009
        The following are only needed if you have an overscan which
3010
        needs a black border:
3011
        <xres_max>: max. length of a line in pixels your OverScan hardware would allow
3012
        <yres_max>: max. number of lines your OverScan hardware would allow
3013
        <offset>: Offset from physical beginning to visible beginning
3014
                  of screen in bytes
3015
        */
3016
        int xres;
3017
        char *p;
3018
 
3019
        if (!(p = strtoke(int_str, ";")) ||!*p) goto int_invalid;
3020
        xres = simple_strtoul(p, NULL, 10);
3021
        if (!(p = strtoke(NULL, ";")) || !*p) goto int_invalid;
3022
        sttt_xres=xres;
3023
        tt_yres=st_yres=simple_strtoul(p, NULL, 10);
3024
        if ((p=strtoke(NULL, ";")) && *p) {
3025
                sttt_xres_virtual=simple_strtoul(p, NULL, 10);
3026
        }
3027
        if ((p=strtoke(NULL, ";")) && *p) {
3028
                sttt_yres_virtual=simple_strtoul(p, NULL, 0);
3029
        }
3030
        if ((p=strtoke(NULL, ";")) && *p) {
3031
                ovsc_offset=simple_strtoul(p, NULL, 0);
3032
        }
3033
 
3034
        if (ovsc_offset || (sttt_yres_virtual != st_yres))
3035
                use_hwscroll=0;
3036
    }
3037
    else
3038
      int_invalid:      ovsc_switchmode = SWITCH_NONE;
3039
 
3040
#ifdef ATAFB_EXT
3041
    if (*ext_str) {
3042
        int             xres, yres, depth, planes;
3043
        unsigned long addr, len;
3044
        char *p;
3045
 
3046
        /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
3047
         *            <screen mem addr>
3048
         *            [;<screen mem length>[;<vgaiobase>[;<colorreg-type>]]]
3049
         */
3050
        if (!(p = strtoke(ext_str, ";")) ||!*p) goto ext_invalid;
3051
        xres = simple_strtoul(p, NULL, 10);
3052
        if (xres <= 0) goto ext_invalid;
3053
 
3054
        if (!(p = strtoke(NULL, ";")) ||!*p) goto ext_invalid;
3055
        yres = simple_strtoul(p, NULL, 10);
3056
        if (yres <= 0) goto ext_invalid;
3057
 
3058
        if (!(p = strtoke(NULL, ";")) ||!*p) goto ext_invalid;
3059
        depth = simple_strtoul(p, NULL, 10);
3060
        if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
3061
                depth != 16 && depth != 24) goto ext_invalid;
3062
 
3063
        if (!(p = strtoke(NULL, ";")) ||!*p) goto ext_invalid;
3064
        if (*p == 'i')
3065
                planes = FB_TYPE_INTERLEAVED_PLANES;
3066
        else if (*p == 'p')
3067
                planes = FB_TYPE_PACKED_PIXELS;
3068
        else if (*p == 'n')
3069
                planes = FB_TYPE_PLANES;
3070
        else if (*p == 't')
3071
                planes = -1; /* true color */
3072
        else
3073
                goto ext_invalid;
3074
 
3075
 
3076
        if (!(p = strtoke(NULL, ";")) ||!*p) goto ext_invalid;
3077
        addr = simple_strtoul(p, NULL, 0);
3078
 
3079
        if (!(p = strtoke(NULL, ";")) ||!*p)
3080
                len = xres*yres*depth/8;
3081
        else
3082
                len = simple_strtoul(p, NULL, 0);
3083
 
3084
        if ((p = strtoke(NULL, ";")) && *p)
3085
                external_vgaiobase=simple_strtoul(p, NULL, 0);
3086
 
3087
        if ((p = strtoke(NULL, ";")) && *p) {
3088
                external_bitspercol = simple_strtoul(p, NULL, 0);
3089
                if (external_bitspercol > 8)
3090
                        external_bitspercol = 8;
3091
                else if (external_bitspercol < 1)
3092
                        external_bitspercol = 1;
3093
        }
3094
 
3095
        if ((p = strtoke(NULL, ";")) && *p) {
3096
                if (!strcmp(this_opt, "vga"))
3097
                        external_card_type = IS_VGA;
3098
                if (!strcmp(this_opt, "mv300"))
3099
                        external_card_type = IS_MV300;
3100
        }
3101
 
3102
        external_xres  = xres;
3103
        external_yres  = yres;
3104
        external_depth = depth;
3105
        external_pmode = planes;
3106
        external_addr  = addr;
3107
        external_len   = len;
3108
 
3109
        if (external_card_type == IS_MV300)
3110
          switch (external_depth) {
3111
            case 1:
3112
              MV300_reg = MV300_reg_1bit;
3113
              break;
3114
            case 4:
3115
              MV300_reg = MV300_reg_4bit;
3116
              break;
3117
            case 8:
3118
              MV300_reg = MV300_reg_8bit;
3119
              break;
3120
            }
3121
 
3122
      ext_invalid:
3123
        ;
3124
    }
3125
#endif /* ATAFB_EXT */
3126
 
3127
#ifdef ATAFB_FALCON
3128
    if (*mcap_spec) {
3129
        char *p;
3130
        int vmin, vmax, hmin, hmax;
3131
 
3132
        /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
3133
         * <V*> vertical freq. in Hz
3134
         * <H*> horizontal freq. in kHz
3135
         */
3136
        if (!(p = strtoke(mcap_spec, ";")) || !*p) goto cap_invalid;
3137
        vmin = simple_strtoul(p, NULL, 10);
3138
        if (vmin <= 0) goto cap_invalid;
3139
        if (!(p = strtoke(NULL, ";")) || !*p) goto cap_invalid;
3140
        vmax = simple_strtoul(p, NULL, 10);
3141
        if (vmax <= 0 || vmax <= vmin) goto cap_invalid;
3142
        if (!(p = strtoke(NULL, ";")) || !*p) goto cap_invalid;
3143
        hmin = 1000 * simple_strtoul(p, NULL, 10);
3144
        if (hmin <= 0) goto cap_invalid;
3145
        if (!(p = strtoke(NULL, "")) || !*p) goto cap_invalid;
3146
        hmax = 1000 * simple_strtoul(p, NULL, 10);
3147
        if (hmax <= 0 || hmax <= hmin) goto cap_invalid;
3148
 
3149
        vfmin = vmin;
3150
        vfmax = vmax;
3151
        hfmin = hmin;
3152
        hfmax = hmax;
3153
      cap_invalid:
3154
        ;
3155
    }
3156
#endif
3157
 
3158
        if (*user_mode) {
3159
                /* Format of user defined video mode is: <xres>;<yres>;<depth>
3160
                 */
3161
                char *p;
3162
                int xres, yres, depth, temp;
3163
 
3164
                if (!(p = strtoke(user_mode, ";")) || !*p) goto user_invalid;
3165
                xres = simple_strtoul(p, NULL, 10);
3166
                if (!(p = strtoke(NULL, ";")) || !*p) goto user_invalid;
3167
                yres = simple_strtoul(p, NULL, 10);
3168
                if (!(p = strtoke(NULL, "")) || !*p) goto user_invalid;
3169
                depth = simple_strtoul(p, NULL, 10);
3170
                if ((temp=get_video_mode("user0"))) {
3171
                        default_par=temp;
3172
                        atari_fb_predefined[default_par-1].xres = xres;
3173
                        atari_fb_predefined[default_par-1].yres = yres;
3174
                        atari_fb_predefined[default_par-1].bits_per_pixel = depth;
3175
                }
3176
 
3177
          user_invalid:
3178
                ;
3179
        }
3180
}

powered by: WebSVN 2.1.0

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