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