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
get_video_mode(char * vname)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 
tt_encode_fix(struct fb_fix_screeninfo * fix,struct atafb_par * par)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 
tt_decode_var(struct fb_var_screeninfo * var,struct atafb_par * par)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 
tt_encode_var(struct fb_var_screeninfo * var,struct atafb_par * par)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 
tt_get_par(struct atafb_par * par)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 
tt_set_par(struct atafb_par * par)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 
tt_getcolreg(unsigned regno,unsigned * red,unsigned * green,unsigned * blue,unsigned * transp,struct fb_info * info)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 
tt_setcolreg(unsigned regno,unsigned red,unsigned green,unsigned blue,unsigned transp,struct fb_info * info)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 
tt_detect(void)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 
hxx_prescale(struct falcon_hw * hw)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 
falcon_encode_fix(struct fb_fix_screeninfo * fix,struct atafb_par * par)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 
falcon_decode_var(struct fb_var_screeninfo * var,struct atafb_par * par)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 
falcon_encode_var(struct fb_var_screeninfo * var,struct atafb_par * par)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 
falcon_get_par(struct atafb_par * par)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 
falcon_set_par(struct atafb_par * par)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 
falcon_vbl_switcher(int irq,void * dummy,struct pt_regs * fp)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 
falcon_pan_display(struct fb_var_screeninfo * var,struct atafb_par * par)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 
falcon_getcolreg(unsigned regno,unsigned * red,unsigned * green,unsigned * blue,unsigned * transp,struct fb_info * info)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 
falcon_setcolreg(unsigned regno,unsigned red,unsigned green,unsigned blue,unsigned transp,struct fb_info * info)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 
falcon_blank(int blank_mode)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 
falcon_detect(void)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 
stste_encode_fix(struct fb_fix_screeninfo * fix,struct atafb_par * par)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 
stste_decode_var(struct fb_var_screeninfo * var,struct atafb_par * par)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 
stste_encode_var(struct fb_var_screeninfo * var,struct atafb_par * par)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 
stste_get_par(struct atafb_par * par)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 
stste_set_par(struct atafb_par * par)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 
stste_getcolreg(unsigned regno,unsigned * red,unsigned * green,unsigned * blue,unsigned * transp,struct fb_info * info)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 
stste_setcolreg(unsigned regno,unsigned red,unsigned green,unsigned blue,unsigned transp,struct fb_info * info)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 
stste_detect(void)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 
stste_set_screen_base(void * s_base)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!) */
st_ovsc_switch(void)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 
ext_encode_fix(struct fb_fix_screeninfo * fix,struct atafb_par * par)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 
ext_decode_var(struct fb_var_screeninfo * var,struct atafb_par * par)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 
ext_encode_var(struct fb_var_screeninfo * var,struct atafb_par * par)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 
ext_get_par(struct atafb_par * par)2209 static void ext_get_par( struct atafb_par *par )
2210 {
2211 	par->screen_base = external_addr;
2212 }
2213 
ext_set_par(struct atafb_par * par)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 
ext_getcolreg(unsigned regno,unsigned * red,unsigned * green,unsigned * blue,unsigned * transp,struct fb_info * info)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 
ext_setcolreg(unsigned regno,unsigned red,unsigned green,unsigned blue,unsigned transp,struct fb_info * info)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 
ext_detect(void)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 
set_screen_base(void * s_base)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 
pan_display(struct fb_var_screeninfo * var,struct atafb_par * par)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 
atafb_get_par(struct atafb_par * par)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 
atafb_set_par(struct atafb_par * par)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
fb_update_var(int con,struct fb_info * info)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
do_fb_set_var(struct fb_var_screeninfo * var,int isactive)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
do_install_cmap(int con,struct fb_info * info)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
atafb_get_fix(struct fb_fix_screeninfo * fix,int con,struct fb_info * info)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
atafb_get_var(struct fb_var_screeninfo * var,int con,struct fb_info * info)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
atafb_set_disp(int con,struct fb_info * info)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
atafb_set_var(struct fb_var_screeninfo * var,int con,struct fb_info * info)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
atafb_get_cmap(struct fb_cmap * cmap,int kspc,int con,struct fb_info * info)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
atafb_set_cmap(struct fb_cmap * cmap,int kspc,int con,struct fb_info * info)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
atafb_pan_display(struct fb_var_screeninfo * var,int con,struct fb_info * info)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
atafb_ioctl(struct inode * inode,struct file * file,unsigned int cmd,unsigned long arg,int con,struct fb_info * info)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
check_default_par(int detected_mode)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
atafb_switch(int con,struct fb_info * info)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
atafb_blank(int blank,struct fb_info * info)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 
atafb_init(void)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 
strtoke(char * s,const char * ct)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 
atafb_setup(char * options)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 
init_module(void)3142 int init_module(void)
3143 {
3144 	return atafb_init();
3145 }
3146 
cleanup_module(void)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