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