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