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