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