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