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