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