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