File: /usr/src/linux/drivers/video/atafb.c

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