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