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