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