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