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