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