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