[go: nahoru, domu]

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