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