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