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