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