i2c: tegra: Add stub runtime power management
[linux-2.6.git] / drivers / video / atafb.c
1 /*
2  * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device
3  *
4  *  Copyright (C) 1994 Martin Schaller & Roman Hodek
5  *
6  * This file is subject to the terms and conditions of the GNU General Public
7  * License.  See the file COPYING in the main directory of this archive
8  * for more details.
9  *
10  * History:
11  *   - 03 Jan 95: Original version by Martin Schaller: The TT driver and
12  *                all the device independent stuff
13  *   - 09 Jan 95: Roman: I've added the hardware abstraction (hw_switch)
14  *                and wrote the Falcon, ST(E), and External drivers
15  *                based on the original TT driver.
16  *   - 07 May 95: Martin: Added colormap operations for the external driver
17  *   - 21 May 95: Martin: Added support for overscan
18  *                Andreas: some bug fixes for this
19  *   -    Jul 95: Guenther Kelleter <guenther@pool.informatik.rwth-aachen.de>:
20  *                Programmable Falcon video modes
21  *                (thanks to Christian Cartus for documentation
22  *                of VIDEL registers).
23  *   - 27 Dec 95: Guenther: Implemented user definable video modes "user[0-7]"
24  *                on minor 24...31. "user0" may be set on commandline by
25  *                "R<x>;<y>;<depth>". (Makes sense only on Falcon)
26  *                Video mode switch on Falcon now done at next VBL interrupt
27  *                to avoid the annoying right shift of the screen.
28  *   - 23 Sep 97: Juergen: added xres_virtual for cards like ProMST
29  *                The external-part is legacy, therefore hardware-specific
30  *                functions like panning/hardwarescrolling/blanking isn't
31  *                                supported.
32  *   - 29 Sep 97: Juergen: added Romans suggestion for pan_display
33  *                                (var->xoffset was changed even if no set_screen_base avail.)
34  *       - 05 Oct 97: Juergen: extfb (PACKED_PIXEL) is FB_PSEUDOCOLOR 'cause
35  *                                we know how to set the colors
36  *                                ext_*palette: read from ext_colors (former MV300_colors)
37  *                                                          write to ext_colors and RAMDAC
38  *
39  * To do:
40  *   - For the Falcon it is not possible to set random video modes on
41  *     SM124 and SC/TV, only the bootup resolution is supported.
42  *
43  */
44
45 #define ATAFB_TT
46 #define ATAFB_STE
47 #define ATAFB_EXT
48 #define ATAFB_FALCON
49
50 #include <linux/module.h>
51 #include <linux/kernel.h>
52 #include <linux/errno.h>
53 #include <linux/string.h>
54 #include <linux/mm.h>
55 #include <linux/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                 ((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) |
1722                                                        ((green & 0xfc00) >> 5) |
1723                                                        ((blue & 0xf800) >> 11));
1724         }
1725         return 0;
1726 }
1727
1728 static int falcon_blank(int blank_mode)
1729 {
1730         /* ++guenther: we can switch off graphics by changing VDB and VDE,
1731          * so VIDEL doesn't hog the bus while saving.
1732          * (this may affect usleep()).
1733          */
1734         int vdb, vss, hbe, hss;
1735
1736         if (mon_type == F_MON_SM)       /* this doesn't work on SM124 */
1737                 return 1;
1738
1739         vdb = current_par.VDB;
1740         vss = current_par.VSS;
1741         hbe = current_par.HBE;
1742         hss = current_par.HSS;
1743
1744         if (blank_mode >= 1) {
1745                 /* disable graphics output (this speeds up the CPU) ... */
1746                 vdb = current_par.VFT + 1;
1747                 /* ... and blank all lines */
1748                 hbe = current_par.HHT + 2;
1749         }
1750         /* use VESA suspend modes on VGA monitors */
1751         if (mon_type == F_MON_VGA) {
1752                 if (blank_mode == 2 || blank_mode == 4)
1753                         vss = current_par.VFT + 1;
1754                 if (blank_mode == 3 || blank_mode == 4)
1755                         hss = current_par.HHT + 2;
1756         }
1757
1758         videl.vdb = vdb;
1759         videl.vss = vss;
1760         videl.hbe = hbe;
1761         videl.hss = hss;
1762
1763         return 0;
1764 }
1765
1766 static int falcon_detect(void)
1767 {
1768         struct atafb_par par;
1769         unsigned char fhw;
1770
1771         /* Determine connected monitor and set monitor parameters */
1772         fhw = *(unsigned char *)0xffff8006;
1773         mon_type = fhw >> 6 & 0x3;
1774         /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
1775         f030_bus_width = fhw << 6 & 0x80;
1776         switch (mon_type) {
1777         case F_MON_SM:
1778                 fb_info.monspecs.vfmin = 70;
1779                 fb_info.monspecs.vfmax = 72;
1780                 fb_info.monspecs.hfmin = 35713;
1781                 fb_info.monspecs.hfmax = 35715;
1782                 break;
1783         case F_MON_SC:
1784         case F_MON_TV:
1785                 /* PAL...NTSC */
1786                 fb_info.monspecs.vfmin = 49;    /* not 50, since TOS defaults to 49.9x Hz */
1787                 fb_info.monspecs.vfmax = 60;
1788                 fb_info.monspecs.hfmin = 15620;
1789                 fb_info.monspecs.hfmax = 15755;
1790                 break;
1791         }
1792         /* initialize hsync-len */
1793         f25.hsync = h_syncs[mon_type] / f25.t;
1794         f32.hsync = h_syncs[mon_type] / f32.t;
1795         if (fext.t)
1796                 fext.hsync = h_syncs[mon_type] / fext.t;
1797
1798         falcon_get_par(&par);
1799         falcon_encode_var(&atafb_predefined[0], &par);
1800
1801         /* Detected mode is always the "autodetect" slot */
1802         return 1;
1803 }
1804
1805 #endif /* ATAFB_FALCON */
1806
1807 /* ------------------- ST(E) specific functions ---------------------- */
1808
1809 #ifdef ATAFB_STE
1810
1811 static int stste_encode_fix(struct fb_fix_screeninfo *fix,
1812                             struct atafb_par *par)
1813 {
1814         int mode;
1815
1816         strcpy(fix->id, "Atari Builtin");
1817         fix->smem_start = (unsigned long)real_screen_base;
1818         fix->smem_len = screen_len;
1819         fix->type = FB_TYPE_INTERLEAVED_PLANES;
1820         fix->type_aux = 2;
1821         fix->visual = FB_VISUAL_PSEUDOCOLOR;
1822         mode = par->hw.st.mode & 3;
1823         if (mode == ST_HIGH) {
1824                 fix->type = FB_TYPE_PACKED_PIXELS;
1825                 fix->type_aux = 0;
1826                 fix->visual = FB_VISUAL_MONO10;
1827         }
1828         if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
1829                 fix->xpanstep = 16;
1830                 fix->ypanstep = 1;
1831         } else {
1832                 fix->xpanstep = 0;
1833                 fix->ypanstep = 0;
1834         }
1835         fix->ywrapstep = 0;
1836         fix->line_length = par->next_line;
1837         fix->accel = FB_ACCEL_ATARIBLITT;
1838         return 0;
1839 }
1840
1841 static int stste_decode_var(struct fb_var_screeninfo *var,
1842                             struct atafb_par *par)
1843 {
1844         int xres = var->xres;
1845         int yres = var->yres;
1846         int bpp = var->bits_per_pixel;
1847         int linelen;
1848         int yres_virtual = var->yres_virtual;
1849
1850         if (mono_moni) {
1851                 if (bpp > 1 || xres > sttt_xres || yres > st_yres)
1852                         return -EINVAL;
1853                 par->hw.st.mode = ST_HIGH;
1854                 xres = sttt_xres;
1855                 yres = st_yres;
1856                 bpp = 1;
1857         } else {
1858                 if (bpp > 4 || xres > sttt_xres || yres > st_yres)
1859                         return -EINVAL;
1860                 if (bpp > 2) {
1861                         if (xres > sttt_xres / 2 || yres > st_yres / 2)
1862                                 return -EINVAL;
1863                         par->hw.st.mode = ST_LOW;
1864                         xres = sttt_xres / 2;
1865                         yres = st_yres / 2;
1866                         bpp = 4;
1867                 } else if (bpp > 1) {
1868                         if (xres > sttt_xres || yres > st_yres / 2)
1869                                 return -EINVAL;
1870                         par->hw.st.mode = ST_MID;
1871                         xres = sttt_xres;
1872                         yres = st_yres / 2;
1873                         bpp = 2;
1874                 } else
1875                         return -EINVAL;
1876         }
1877         if (yres_virtual <= 0)
1878                 yres_virtual = 0;
1879         else if (yres_virtual < yres)
1880                 yres_virtual = yres;
1881         if (var->sync & FB_SYNC_EXT)
1882                 par->hw.st.sync = (par->hw.st.sync & ~1) | 1;
1883         else
1884                 par->hw.st.sync = (par->hw.st.sync & ~1);
1885         linelen = xres * bpp / 8;
1886         if (yres_virtual * linelen > screen_len && screen_len)
1887                 return -EINVAL;
1888         if (yres * linelen > screen_len && screen_len)
1889                 return -EINVAL;
1890         if (var->yoffset + yres > yres_virtual && yres_virtual)
1891                 return -EINVAL;
1892         par->yres_virtual = yres_virtual;
1893         par->screen_base = screen_base + var->yoffset * linelen;
1894         par->next_line = linelen;
1895         return 0;
1896 }
1897
1898 static int stste_encode_var(struct fb_var_screeninfo *var,
1899                             struct atafb_par *par)
1900 {
1901         int linelen;
1902         memset(var, 0, sizeof(struct fb_var_screeninfo));
1903         var->red.offset = 0;
1904         var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
1905         var->red.msb_right = 0;
1906         var->grayscale = 0;
1907
1908         var->pixclock = 31041;
1909         var->left_margin = 120;         /* these are incorrect */
1910         var->right_margin = 100;
1911         var->upper_margin = 8;
1912         var->lower_margin = 16;
1913         var->hsync_len = 140;
1914         var->vsync_len = 30;
1915
1916         var->height = -1;
1917         var->width = -1;
1918
1919         if (!(par->hw.st.sync & 1))
1920                 var->sync = 0;
1921         else
1922                 var->sync = FB_SYNC_EXT;
1923
1924         switch (par->hw.st.mode & 3) {
1925         case ST_LOW:
1926                 var->xres = sttt_xres / 2;
1927                 var->yres = st_yres / 2;
1928                 var->bits_per_pixel = 4;
1929                 break;
1930         case ST_MID:
1931                 var->xres = sttt_xres;
1932                 var->yres = st_yres / 2;
1933                 var->bits_per_pixel = 2;
1934                 break;
1935         case ST_HIGH:
1936                 var->xres = sttt_xres;
1937                 var->yres = st_yres;
1938                 var->bits_per_pixel = 1;
1939                 break;
1940         }
1941         var->blue = var->green = var->red;
1942         var->transp.offset = 0;
1943         var->transp.length = 0;
1944         var->transp.msb_right = 0;
1945         var->xres_virtual = sttt_xres_virtual;
1946         linelen = var->xres_virtual * var->bits_per_pixel / 8;
1947         ovsc_addlen = linelen * (sttt_yres_virtual - st_yres);
1948
1949         if (!use_hwscroll)
1950                 var->yres_virtual = var->yres;
1951         else if (screen_len) {
1952                 if (par->yres_virtual)
1953                         var->yres_virtual = par->yres_virtual;
1954                 else
1955                         /* yres_virtual == 0 means use maximum */
1956                         var->yres_virtual = screen_len / linelen;
1957         } else {
1958                 if (hwscroll < 0)
1959                         var->yres_virtual = 2 * var->yres;
1960                 else
1961                         var->yres_virtual = var->yres + hwscroll * 16;
1962         }
1963         var->xoffset = 0;
1964         if (screen_base)
1965                 var->yoffset = (par->screen_base - screen_base) / linelen;
1966         else
1967                 var->yoffset = 0;
1968         var->nonstd = 0;
1969         var->activate = 0;
1970         var->vmode = FB_VMODE_NONINTERLACED;
1971         return 0;
1972 }
1973
1974 static void stste_get_par(struct atafb_par *par)
1975 {
1976         unsigned long addr;
1977         par->hw.st.mode = shifter_tt.st_shiftmode;
1978         par->hw.st.sync = shifter.syncmode;
1979         addr = ((shifter.bas_hi & 0xff) << 16) |
1980                ((shifter.bas_md & 0xff) << 8);
1981         if (ATARIHW_PRESENT(EXTD_SHIFTER))
1982                 addr |= (shifter.bas_lo & 0xff);
1983         par->screen_base = phys_to_virt(addr);
1984 }
1985
1986 static void stste_set_par(struct atafb_par *par)
1987 {
1988         shifter_tt.st_shiftmode = par->hw.st.mode;
1989         shifter.syncmode = par->hw.st.sync;
1990         /* only set screen_base if really necessary */
1991         if (current_par.screen_base != par->screen_base)
1992                 fbhw->set_screen_base(par->screen_base);
1993 }
1994
1995 static int stste_setcolreg(unsigned int regno, unsigned int red,
1996                            unsigned int green, unsigned int blue,
1997                            unsigned int transp, struct fb_info *info)
1998 {
1999         if (regno > 15)
2000                 return 1;
2001         red >>= 12;
2002         blue >>= 12;
2003         green >>= 12;
2004         if (ATARIHW_PRESENT(EXTD_SHIFTER))
2005                 shifter_tt.color_reg[regno] =
2006                         (((red & 0xe) >> 1) | ((red & 1) << 3) << 8) |
2007                         (((green & 0xe) >> 1) | ((green & 1) << 3) << 4) |
2008                         ((blue & 0xe) >> 1) | ((blue & 1) << 3);
2009         else
2010                 shifter_tt.color_reg[regno] =
2011                         ((red & 0xe) << 7) |
2012                         ((green & 0xe) << 3) |
2013                         ((blue & 0xe) >> 1);
2014         return 0;
2015 }
2016
2017 static int stste_detect(void)
2018 {
2019         struct atafb_par par;
2020
2021         /* Determine the connected monitor: The DMA sound must be
2022          * disabled before reading the MFP GPIP, because the Sound
2023          * Done Signal and the Monochrome Detect are XORed together!
2024          */
2025         if (ATARIHW_PRESENT(PCM_8BIT)) {
2026                 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
2027                 udelay(20);             /* wait a while for things to settle down */
2028         }
2029         mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
2030
2031         stste_get_par(&par);
2032         stste_encode_var(&atafb_predefined[0], &par);
2033
2034         if (!ATARIHW_PRESENT(EXTD_SHIFTER))
2035                 use_hwscroll = 0;
2036         return 1;
2037 }
2038
2039 static void stste_set_screen_base(void *s_base)
2040 {
2041         unsigned long addr;
2042         addr = virt_to_phys(s_base);
2043         /* Setup Screen Memory */
2044         shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
2045         shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
2046         if (ATARIHW_PRESENT(EXTD_SHIFTER))
2047                 shifter.bas_lo = (unsigned char)(addr & 0x0000ff);
2048 }
2049
2050 #endif /* ATAFB_STE */
2051
2052 /* Switching the screen size should be done during vsync, otherwise
2053  * the margins may get messed up. This is a well known problem of
2054  * the ST's video system.
2055  *
2056  * Unfortunately there is hardly any way to find the vsync, as the
2057  * vertical blank interrupt is no longer in time on machines with
2058  * overscan type modifications.
2059  *
2060  * We can, however, use Timer B to safely detect the black shoulder,
2061  * but then we've got to guess an appropriate delay to find the vsync.
2062  * This might not work on every machine.
2063  *
2064  * martin_rogge @ ki.maus.de, 8th Aug 1995
2065  */
2066
2067 #define LINE_DELAY  (mono_moni ? 30 : 70)
2068 #define SYNC_DELAY  (mono_moni ? 1500 : 2000)
2069
2070 /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
2071 static void st_ovsc_switch(void)
2072 {
2073         unsigned long flags;
2074         register unsigned char old, new;
2075
2076         if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
2077                 return;
2078         local_irq_save(flags);
2079
2080         st_mfp.tim_ct_b = 0x10;
2081         st_mfp.active_edge |= 8;
2082         st_mfp.tim_ct_b = 0;
2083         st_mfp.tim_dt_b = 0xf0;
2084         st_mfp.tim_ct_b = 8;
2085         while (st_mfp.tim_dt_b > 1)     /* TOS does it this way, don't ask why */
2086                 ;
2087         new = st_mfp.tim_dt_b;
2088         do {
2089                 udelay(LINE_DELAY);
2090                 old = new;
2091                 new = st_mfp.tim_dt_b;
2092         } while (old != new);
2093         st_mfp.tim_ct_b = 0x10;
2094         udelay(SYNC_DELAY);
2095
2096         if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
2097                 acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
2098         if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
2099                 acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
2100         if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
2101                 sound_ym.rd_data_reg_sel = 14;
2102                 sound_ym.wd_data = sound_ym.rd_data_reg_sel |
2103                                    ((atari_switches & ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
2104                                    ((atari_switches & ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
2105         }
2106         local_irq_restore(flags);
2107 }
2108
2109 /* ------------------- External Video ---------------------- */
2110
2111 #ifdef ATAFB_EXT
2112
2113 static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
2114 {
2115         strcpy(fix->id, "Unknown Extern");
2116         fix->smem_start = (unsigned long)external_addr;
2117         fix->smem_len = PAGE_ALIGN(external_len);
2118         if (external_depth == 1) {
2119                 fix->type = FB_TYPE_PACKED_PIXELS;
2120                 /* The letters 'n' and 'i' in the "atavideo=external:" stand
2121                  * for "normal" and "inverted", rsp., in the monochrome case */
2122                 fix->visual =
2123                         (external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
2124                          external_pmode == FB_TYPE_PACKED_PIXELS) ?
2125                                 FB_VISUAL_MONO10 : FB_VISUAL_MONO01;
2126         } else {
2127                 /* Use STATIC if we don't know how to access color registers */
2128                 int visual = external_vgaiobase ?
2129                                          FB_VISUAL_PSEUDOCOLOR :
2130                                          FB_VISUAL_STATIC_PSEUDOCOLOR;
2131                 switch (external_pmode) {
2132                 case -1:                /* truecolor */
2133                         fix->type = FB_TYPE_PACKED_PIXELS;
2134                         fix->visual = FB_VISUAL_TRUECOLOR;
2135                         break;
2136                 case FB_TYPE_PACKED_PIXELS:
2137                         fix->type = FB_TYPE_PACKED_PIXELS;
2138                         fix->visual = visual;
2139                         break;
2140                 case FB_TYPE_PLANES:
2141                         fix->type = FB_TYPE_PLANES;
2142                         fix->visual = visual;
2143                         break;
2144                 case FB_TYPE_INTERLEAVED_PLANES:
2145                         fix->type = FB_TYPE_INTERLEAVED_PLANES;
2146                         fix->type_aux = 2;
2147                         fix->visual = visual;
2148                         break;
2149                 }
2150         }
2151         fix->xpanstep = 0;
2152         fix->ypanstep = 0;
2153         fix->ywrapstep = 0;
2154         fix->line_length = par->next_line;
2155         return 0;
2156 }
2157
2158 static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
2159 {
2160         struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2161
2162         if (var->bits_per_pixel > myvar->bits_per_pixel ||
2163             var->xres > myvar->xres ||
2164             var->xres_virtual > myvar->xres_virtual ||
2165             var->yres > myvar->yres ||
2166             var->xoffset > 0 ||
2167             var->yoffset > 0)
2168                 return -EINVAL;
2169
2170         par->next_line = external_xres_virtual * external_depth / 8;
2171         return 0;
2172 }
2173
2174 static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
2175 {
2176         memset(var, 0, sizeof(struct fb_var_screeninfo));
2177         var->red.offset = 0;
2178         var->red.length = (external_pmode == -1) ? external_depth / 3 :
2179                         (external_vgaiobase ? external_bitspercol : 0);
2180         var->red.msb_right = 0;
2181         var->grayscale = 0;
2182
2183         var->pixclock = 31041;
2184         var->left_margin = 120;         /* these are surely incorrect */
2185         var->right_margin = 100;
2186         var->upper_margin = 8;
2187         var->lower_margin = 16;
2188         var->hsync_len = 140;
2189         var->vsync_len = 30;
2190
2191         var->height = -1;
2192         var->width = -1;
2193
2194         var->sync = 0;
2195
2196         var->xres = external_xres;
2197         var->yres = external_yres;
2198         var->xres_virtual = external_xres_virtual;
2199         var->bits_per_pixel = external_depth;
2200
2201         var->blue = var->green = var->red;
2202         var->transp.offset = 0;
2203         var->transp.length = 0;
2204         var->transp.msb_right = 0;
2205         var->yres_virtual = var->yres;
2206         var->xoffset = 0;
2207         var->yoffset = 0;
2208         var->nonstd = 0;
2209         var->activate = 0;
2210         var->vmode = FB_VMODE_NONINTERLACED;
2211         return 0;
2212 }
2213
2214 static void ext_get_par(struct atafb_par *par)
2215 {
2216         par->screen_base = external_addr;
2217 }
2218
2219 static void ext_set_par(struct atafb_par *par)
2220 {
2221 }
2222
2223 #define OUTB(port,val) \
2224         *((unsigned volatile char *) ((port)+external_vgaiobase)) = (val)
2225 #define INB(port) \
2226         (*((unsigned volatile char *) ((port)+external_vgaiobase)))
2227 #define DACDelay                                \
2228         do {                                    \
2229                 unsigned char tmp = INB(0x3da); \
2230                 tmp = INB(0x3da);                       \
2231         } while (0)
2232
2233 static int ext_setcolreg(unsigned int regno, unsigned int red,
2234                          unsigned int green, unsigned int blue,
2235                          unsigned int transp, struct fb_info *info)
2236 {
2237         unsigned char colmask = (1 << external_bitspercol) - 1;
2238
2239         if (!external_vgaiobase)
2240                 return 1;
2241
2242         if (regno > 255)
2243                 return 1;
2244
2245         switch (external_card_type) {
2246         case IS_VGA:
2247                 OUTB(0x3c8, regno);
2248                 DACDelay;
2249                 OUTB(0x3c9, red & colmask);
2250                 DACDelay;
2251                 OUTB(0x3c9, green & colmask);
2252                 DACDelay;
2253                 OUTB(0x3c9, blue & colmask);
2254                 DACDelay;
2255                 return 0;
2256
2257         case IS_MV300:
2258                 OUTB((MV300_reg[regno] << 2) + 1, red);
2259                 OUTB((MV300_reg[regno] << 2) + 1, green);
2260                 OUTB((MV300_reg[regno] << 2) + 1, blue);
2261                 return 0;
2262
2263         default:
2264                 return 1;
2265         }
2266 }
2267
2268 static int ext_detect(void)
2269 {
2270         struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2271         struct atafb_par dummy_par;
2272
2273         myvar->xres = external_xres;
2274         myvar->xres_virtual = external_xres_virtual;
2275         myvar->yres = external_yres;
2276         myvar->bits_per_pixel = external_depth;
2277         ext_encode_var(myvar, &dummy_par);
2278         return 1;
2279 }
2280
2281 #endif /* ATAFB_EXT */
2282
2283 /* ------ This is the same for most hardware types -------- */
2284
2285 static void set_screen_base(void *s_base)
2286 {
2287         unsigned long addr;
2288
2289         addr = virt_to_phys(s_base);
2290         /* Setup Screen Memory */
2291         shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
2292         shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
2293         shifter.bas_lo = (unsigned char)(addr & 0x0000ff);
2294 }
2295
2296 static int pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
2297 {
2298         struct atafb_par *par = (struct atafb_par *)info->par;
2299
2300         if (!fbhw->set_screen_base ||
2301             (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
2302                 return -EINVAL;
2303         var->xoffset = up(var->xoffset, 16);
2304         par->screen_base = screen_base +
2305                 (var->yoffset * info->var.xres_virtual + var->xoffset)
2306                 * info->var.bits_per_pixel / 8;
2307         fbhw->set_screen_base(par->screen_base);
2308         return 0;
2309 }
2310
2311 /* ------------ Interfaces to hardware functions ------------ */
2312
2313 #ifdef ATAFB_TT
2314 static struct fb_hwswitch tt_switch = {
2315         .detect         = tt_detect,
2316         .encode_fix     = tt_encode_fix,
2317         .decode_var     = tt_decode_var,
2318         .encode_var     = tt_encode_var,
2319         .get_par        = tt_get_par,
2320         .set_par        = tt_set_par,
2321         .set_screen_base = set_screen_base,
2322         .pan_display    = pan_display,
2323 };
2324 #endif
2325
2326 #ifdef ATAFB_FALCON
2327 static struct fb_hwswitch falcon_switch = {
2328         .detect         = falcon_detect,
2329         .encode_fix     = falcon_encode_fix,
2330         .decode_var     = falcon_decode_var,
2331         .encode_var     = falcon_encode_var,
2332         .get_par        = falcon_get_par,
2333         .set_par        = falcon_set_par,
2334         .set_screen_base = set_screen_base,
2335         .blank          = falcon_blank,
2336         .pan_display    = falcon_pan_display,
2337 };
2338 #endif
2339
2340 #ifdef ATAFB_STE
2341 static struct fb_hwswitch st_switch = {
2342         .detect         = stste_detect,
2343         .encode_fix     = stste_encode_fix,
2344         .decode_var     = stste_decode_var,
2345         .encode_var     = stste_encode_var,
2346         .get_par        = stste_get_par,
2347         .set_par        = stste_set_par,
2348         .set_screen_base = stste_set_screen_base,
2349         .pan_display    = pan_display
2350 };
2351 #endif
2352
2353 #ifdef ATAFB_EXT
2354 static struct fb_hwswitch ext_switch = {
2355         .detect         = ext_detect,
2356         .encode_fix     = ext_encode_fix,
2357         .decode_var     = ext_decode_var,
2358         .encode_var     = ext_encode_var,
2359         .get_par        = ext_get_par,
2360         .set_par        = ext_set_par,
2361 };
2362 #endif
2363
2364 static void ata_get_par(struct atafb_par *par)
2365 {
2366         if (current_par_valid)
2367                 *par = current_par;
2368         else
2369                 fbhw->get_par(par);
2370 }
2371
2372 static void ata_set_par(struct atafb_par *par)
2373 {
2374         fbhw->set_par(par);
2375         current_par = *par;
2376         current_par_valid = 1;
2377 }
2378
2379
2380 /* =========================================================== */
2381 /* ============== Hardware Independent Functions ============= */
2382 /* =========================================================== */
2383
2384 /* used for hardware scrolling */
2385
2386 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
2387 {
2388         int err, activate;
2389         struct atafb_par par;
2390
2391         err = fbhw->decode_var(var, &par);
2392         if (err)
2393                 return err;
2394         activate = var->activate;
2395         if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
2396                 ata_set_par(&par);
2397         fbhw->encode_var(var, &par);
2398         var->activate = activate;
2399         return 0;
2400 }
2401
2402 /* fbhw->encode_fix() must be called with fb_info->mm_lock held
2403  * if it is called after the register_framebuffer() - not a case here
2404  */
2405 static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
2406 {
2407         struct atafb_par par;
2408         int err;
2409         // Get fix directly (case con == -1 before)??
2410         err = fbhw->decode_var(&info->var, &par);
2411         if (err)
2412                 return err;
2413         memset(fix, 0, sizeof(struct fb_fix_screeninfo));
2414         err = fbhw->encode_fix(fix, &par);
2415         return err;
2416 }
2417
2418 static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info)
2419 {
2420         struct atafb_par par;
2421
2422         ata_get_par(&par);
2423         fbhw->encode_var(var, &par);
2424
2425         return 0;
2426 }
2427
2428 // No longer called by fbcon!
2429 // Still called by set_var internally
2430
2431 static void atafb_set_disp(struct fb_info *info)
2432 {
2433         atafb_get_var(&info->var, info);
2434         atafb_get_fix(&info->fix, info);
2435
2436         info->screen_base = (void *)info->fix.smem_start;
2437 }
2438
2439 static int atafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
2440                            u_int transp, struct fb_info *info)
2441 {
2442         red >>= 8;
2443         green >>= 8;
2444         blue >>= 8;
2445
2446         return info->fbops->fb_setcolreg(regno, red, green, blue, transp, info);
2447 }
2448
2449 static int
2450 atafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
2451 {
2452         int xoffset = var->xoffset;
2453         int yoffset = var->yoffset;
2454         int err;
2455
2456         if (var->vmode & FB_VMODE_YWRAP) {
2457                 if (yoffset < 0 || yoffset >= info->var.yres_virtual || xoffset)
2458                         return -EINVAL;
2459         } else {
2460                 if (xoffset + info->var.xres > info->var.xres_virtual ||
2461                     yoffset + info->var.yres > info->var.yres_virtual)
2462                         return -EINVAL;
2463         }
2464
2465         if (fbhw->pan_display) {
2466                 err = fbhw->pan_display(var, info);
2467                 if (err)
2468                         return err;
2469         } else
2470                 return -EINVAL;
2471
2472         info->var.xoffset = xoffset;
2473         info->var.yoffset = yoffset;
2474
2475         if (var->vmode & FB_VMODE_YWRAP)
2476                 info->var.vmode |= FB_VMODE_YWRAP;
2477         else
2478                 info->var.vmode &= ~FB_VMODE_YWRAP;
2479
2480         return 0;
2481 }
2482
2483 /*
2484  * generic drawing routines; imageblit needs updating for image depth > 1
2485  */
2486
2487 #if BITS_PER_LONG == 32
2488 #define BYTES_PER_LONG  4
2489 #define SHIFT_PER_LONG  5
2490 #elif BITS_PER_LONG == 64
2491 #define BYTES_PER_LONG  8
2492 #define SHIFT_PER_LONG  6
2493 #else
2494 #define Please update me
2495 #endif
2496
2497
2498 static void atafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
2499 {
2500         struct atafb_par *par = (struct atafb_par *)info->par;
2501         int x2, y2;
2502         u32 width, height;
2503
2504         if (!rect->width || !rect->height)
2505                 return;
2506
2507 #ifdef ATAFB_FALCON
2508         if (info->var.bits_per_pixel == 16) {
2509                 cfb_fillrect(info, rect);
2510                 return;
2511         }
2512 #endif
2513
2514         /*
2515          * We could use hardware clipping but on many cards you get around
2516          * hardware clipping by writing to framebuffer directly.
2517          * */
2518         x2 = rect->dx + rect->width;
2519         y2 = rect->dy + rect->height;
2520         x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2521         y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2522         width = x2 - rect->dx;
2523         height = y2 - rect->dy;
2524
2525         if (info->var.bits_per_pixel == 1)
2526                 atafb_mfb_fillrect(info, par->next_line, rect->color,
2527                                    rect->dy, rect->dx, height, width);
2528         else if (info->var.bits_per_pixel == 2)
2529                 atafb_iplan2p2_fillrect(info, par->next_line, rect->color,
2530                                         rect->dy, rect->dx, height, width);
2531         else if (info->var.bits_per_pixel == 4)
2532                 atafb_iplan2p4_fillrect(info, par->next_line, rect->color,
2533                                         rect->dy, rect->dx, height, width);
2534         else
2535                 atafb_iplan2p8_fillrect(info, par->next_line, rect->color,
2536                                         rect->dy, rect->dx, height, width);
2537
2538         return;
2539 }
2540
2541 static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
2542 {
2543         struct atafb_par *par = (struct atafb_par *)info->par;
2544         int x2, y2;
2545         u32 dx, dy, sx, sy, width, height;
2546         int rev_copy = 0;
2547
2548 #ifdef ATAFB_FALCON
2549         if (info->var.bits_per_pixel == 16) {
2550                 cfb_copyarea(info, area);
2551                 return;
2552         }
2553 #endif
2554
2555         /* clip the destination */
2556         x2 = area->dx + area->width;
2557         y2 = area->dy + area->height;
2558         dx = area->dx > 0 ? area->dx : 0;
2559         dy = area->dy > 0 ? area->dy : 0;
2560         x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2561         y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2562         width = x2 - dx;
2563         height = y2 - dy;
2564
2565         if (area->sx + dx < area->dx || area->sy + dy < area->dy)
2566                 return;
2567
2568         /* update sx,sy */
2569         sx = area->sx + (dx - area->dx);
2570         sy = area->sy + (dy - area->dy);
2571
2572         /* the source must be completely inside the virtual screen */
2573         if (sx + width > info->var.xres_virtual ||
2574                         sy + height > info->var.yres_virtual)
2575                 return;
2576
2577         if (dy > sy || (dy == sy && dx > sx)) {
2578                 dy += height;
2579                 sy += height;
2580                 rev_copy = 1;
2581         }
2582
2583         if (info->var.bits_per_pixel == 1)
2584                 atafb_mfb_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2585         else if (info->var.bits_per_pixel == 2)
2586                 atafb_iplan2p2_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2587         else if (info->var.bits_per_pixel == 4)
2588                 atafb_iplan2p4_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2589         else
2590                 atafb_iplan2p8_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2591
2592         return;
2593 }
2594
2595 static void atafb_imageblit(struct fb_info *info, const struct fb_image *image)
2596 {
2597         struct atafb_par *par = (struct atafb_par *)info->par;
2598         int x2, y2;
2599         unsigned long *dst;
2600         int dst_idx;
2601         const char *src;
2602         u32 dx, dy, width, height, pitch;
2603
2604 #ifdef ATAFB_FALCON
2605         if (info->var.bits_per_pixel == 16) {
2606                 cfb_imageblit(info, image);
2607                 return;
2608         }
2609 #endif
2610
2611         /*
2612          * We could use hardware clipping but on many cards you get around
2613          * hardware clipping by writing to framebuffer directly like we are
2614          * doing here.
2615          */
2616         x2 = image->dx + image->width;
2617         y2 = image->dy + image->height;
2618         dx = image->dx;
2619         dy = image->dy;
2620         x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2621         y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2622         width = x2 - dx;
2623         height = y2 - dy;
2624
2625         if (image->depth == 1) {
2626                 // used for font data
2627                 dst = (unsigned long *)
2628                         ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
2629                 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
2630                 dst_idx += dy * par->next_line * 8 + dx;
2631                 src = image->data;
2632                 pitch = (image->width + 7) / 8;
2633                 while (height--) {
2634
2635                         if (info->var.bits_per_pixel == 1)
2636                                 atafb_mfb_linefill(info, par->next_line,
2637                                                    dy, dx, width, src,
2638                                                    image->bg_color, image->fg_color);
2639                         else if (info->var.bits_per_pixel == 2)
2640                                 atafb_iplan2p2_linefill(info, par->next_line,
2641                                                         dy, dx, width, src,
2642                                                         image->bg_color, image->fg_color);
2643                         else if (info->var.bits_per_pixel == 4)
2644                                 atafb_iplan2p4_linefill(info, par->next_line,
2645                                                         dy, dx, width, src,
2646                                                         image->bg_color, image->fg_color);
2647                         else
2648                                 atafb_iplan2p8_linefill(info, par->next_line,
2649                                                         dy, dx, width, src,
2650                                                         image->bg_color, image->fg_color);
2651                         dy++;
2652                         src += pitch;
2653                 }
2654         } else {
2655                 c2p_iplan2(info->screen_base, image->data, dx, dy, width,
2656                            height, par->next_line, image->width,
2657                            info->var.bits_per_pixel);
2658         }
2659 }
2660
2661 static int
2662 atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
2663 {
2664         switch (cmd) {
2665 #ifdef FBCMD_GET_CURRENTPAR
2666         case FBCMD_GET_CURRENTPAR:
2667                 if (copy_to_user((void *)arg, (void *)&current_par,
2668                                  sizeof(struct atafb_par)))
2669                         return -EFAULT;
2670                 return 0;
2671 #endif
2672 #ifdef FBCMD_SET_CURRENTPAR
2673         case FBCMD_SET_CURRENTPAR:
2674                 if (copy_from_user((void *)&current_par, (void *)arg,
2675                                    sizeof(struct atafb_par)))
2676                         return -EFAULT;
2677                 ata_set_par(&current_par);
2678                 return 0;
2679 #endif
2680         }
2681         return -EINVAL;
2682 }
2683
2684 /* (un)blank/poweroff
2685  * 0 = unblank
2686  * 1 = blank
2687  * 2 = suspend vsync
2688  * 3 = suspend hsync
2689  * 4 = off
2690  */
2691 static int atafb_blank(int blank, struct fb_info *info)
2692 {
2693         unsigned short black[16];
2694         struct fb_cmap cmap;
2695         if (fbhw->blank && !fbhw->blank(blank))
2696                 return 1;
2697         if (blank) {
2698                 memset(black, 0, 16 * sizeof(unsigned short));
2699                 cmap.red = black;
2700                 cmap.green = black;
2701                 cmap.blue = black;
2702                 cmap.transp = NULL;
2703                 cmap.start = 0;
2704                 cmap.len = 16;
2705                 fb_set_cmap(&cmap, info);
2706         }
2707 #if 0
2708         else
2709                 do_install_cmap(info);
2710 #endif
2711         return 0;
2712 }
2713
2714         /*
2715          * New fbcon interface ...
2716          */
2717
2718          /* check var by decoding var into hw par, rounding if necessary,
2719           * then encoding hw par back into new, validated var */
2720 static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
2721 {
2722         int err;
2723         struct atafb_par par;
2724
2725         /* Validate wanted screen parameters */
2726         // if ((err = ata_decode_var(var, &par)))
2727         err = fbhw->decode_var(var, &par);
2728         if (err)
2729                 return err;
2730
2731         /* Encode (possibly rounded) screen parameters */
2732         fbhw->encode_var(var, &par);
2733         return 0;
2734 }
2735
2736         /* actually set hw par by decoding var, then setting hardware from
2737          * hw par just decoded */
2738 static int atafb_set_par(struct fb_info *info)
2739 {
2740         struct atafb_par *par = (struct atafb_par *)info->par;
2741
2742         /* Decode wanted screen parameters */
2743         fbhw->decode_var(&info->var, par);
2744         mutex_lock(&info->mm_lock);
2745         fbhw->encode_fix(&info->fix, par);
2746         mutex_unlock(&info->mm_lock);
2747
2748         /* Set new videomode */
2749         ata_set_par(par);
2750
2751         return 0;
2752 }
2753
2754
2755 static struct fb_ops atafb_ops = {
2756         .owner =        THIS_MODULE,
2757         .fb_check_var   = atafb_check_var,
2758         .fb_set_par     = atafb_set_par,
2759         .fb_setcolreg   = atafb_setcolreg,
2760         .fb_blank =     atafb_blank,
2761         .fb_pan_display = atafb_pan_display,
2762         .fb_fillrect    = atafb_fillrect,
2763         .fb_copyarea    = atafb_copyarea,
2764         .fb_imageblit   = atafb_imageblit,
2765         .fb_ioctl =     atafb_ioctl,
2766 };
2767
2768 static void check_default_par(int detected_mode)
2769 {
2770         char default_name[10];
2771         int i;
2772         struct fb_var_screeninfo var;
2773         unsigned long min_mem;
2774
2775         /* First try the user supplied mode */
2776         if (default_par) {
2777                 var = atafb_predefined[default_par - 1];
2778                 var.activate = FB_ACTIVATE_TEST;
2779                 if (do_fb_set_var(&var, 1))
2780                         default_par = 0;        /* failed */
2781         }
2782         /* Next is the autodetected one */
2783         if (!default_par) {
2784                 var = atafb_predefined[detected_mode - 1]; /* autodetect */
2785                 var.activate = FB_ACTIVATE_TEST;
2786                 if (!do_fb_set_var(&var, 1))
2787                         default_par = detected_mode;
2788         }
2789         /* If that also failed, try some default modes... */
2790         if (!default_par) {
2791                 /* try default1, default2... */
2792                 for (i = 1; i < 10; i++) {
2793                         sprintf(default_name,"default%d", i);
2794                         default_par = get_video_mode(default_name);
2795                         if (!default_par)
2796                                 panic("can't set default video mode");
2797                         var = atafb_predefined[default_par - 1];
2798                         var.activate = FB_ACTIVATE_TEST;
2799                         if (!do_fb_set_var(&var,1))
2800                                 break;  /* ok */
2801                 }
2802         }
2803         min_mem = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8;
2804         if (default_mem_req < min_mem)
2805                 default_mem_req = min_mem;
2806 }
2807
2808 #ifdef ATAFB_EXT
2809 static void __init atafb_setup_ext(char *spec)
2810 {
2811         int xres, xres_virtual, yres, depth, planes;
2812         unsigned long addr, len;
2813         char *p;
2814
2815         /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
2816          *            <screen mem addr>
2817          *            [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
2818          *            [;<xres-virtual>]]]]]
2819          *
2820          * 09/23/97     Juergen
2821          * <xres_virtual>:      hardware's x-resolution (f.e. ProMST)
2822          *
2823          * Even xres_virtual is available, we neither support panning nor hw-scrolling!
2824          */
2825         p = strsep(&spec, ";");
2826         if (!p || !*p)
2827                 return;
2828         xres_virtual = xres = simple_strtoul(p, NULL, 10);
2829         if (xres <= 0)
2830                 return;
2831
2832         p = strsep(&spec, ";");
2833         if (!p || !*p)
2834                 return;
2835         yres = simple_strtoul(p, NULL, 10);
2836         if (yres <= 0)
2837                 return;
2838
2839         p = strsep(&spec, ";");
2840         if (!p || !*p)
2841                 return;
2842         depth = simple_strtoul(p, NULL, 10);
2843         if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
2844             depth != 16 && depth != 24)
2845                 return;
2846
2847         p = strsep(&spec, ";");
2848         if (!p || !*p)
2849                 return;
2850         if (*p == 'i')
2851                 planes = FB_TYPE_INTERLEAVED_PLANES;
2852         else if (*p == 'p')
2853                 planes = FB_TYPE_PACKED_PIXELS;
2854         else if (*p == 'n')
2855                 planes = FB_TYPE_PLANES;
2856         else if (*p == 't')
2857                 planes = -1;            /* true color */
2858         else
2859                 return;
2860
2861         p = strsep(&spec, ";");
2862         if (!p || !*p)
2863                 return;
2864         addr = simple_strtoul(p, NULL, 0);
2865
2866         p = strsep(&spec, ";");
2867         if (!p || !*p)
2868                 len = xres * yres * depth / 8;
2869         else
2870                 len = simple_strtoul(p, NULL, 0);
2871
2872         p = strsep(&spec, ";");
2873         if (p && *p)
2874                 external_vgaiobase = simple_strtoul(p, NULL, 0);
2875
2876         p = strsep(&spec, ";");
2877         if (p && *p) {
2878                 external_bitspercol = simple_strtoul(p, NULL, 0);
2879                 if (external_bitspercol > 8)
2880                         external_bitspercol = 8;
2881                 else if (external_bitspercol < 1)
2882                         external_bitspercol = 1;
2883         }
2884
2885         p = strsep(&spec, ";");
2886         if (p && *p) {
2887                 if (!strcmp(p, "vga"))
2888                         external_card_type = IS_VGA;
2889                 if (!strcmp(p, "mv300"))
2890                         external_card_type = IS_MV300;
2891         }
2892
2893         p = strsep(&spec, ";");
2894         if (p && *p) {
2895                 xres_virtual = simple_strtoul(p, NULL, 10);
2896                 if (xres_virtual < xres)
2897                         xres_virtual = xres;
2898                 if (xres_virtual * yres * depth / 8 > len)
2899                         len = xres_virtual * yres * depth / 8;
2900         }
2901
2902         external_xres = xres;
2903         external_xres_virtual = xres_virtual;
2904         external_yres = yres;
2905         external_depth = depth;
2906         external_pmode = planes;
2907         external_addr = (void *)addr;
2908         external_len = len;
2909
2910         if (external_card_type == IS_MV300) {
2911                 switch (external_depth) {
2912                 case 1:
2913                         MV300_reg = MV300_reg_1bit;
2914                         break;
2915                 case 4:
2916                         MV300_reg = MV300_reg_4bit;
2917                         break;
2918                 case 8:
2919                         MV300_reg = MV300_reg_8bit;
2920                         break;
2921                 }
2922         }
2923 }
2924 #endif /* ATAFB_EXT */
2925
2926 static void __init atafb_setup_int(char *spec)
2927 {
2928         /* Format to config extended internal video hardware like OverScan:
2929          * "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
2930          * Explanation:
2931          * <xres>: x-resolution
2932          * <yres>: y-resolution
2933          * The following are only needed if you have an overscan which
2934          * needs a black border:
2935          * <xres_max>: max. length of a line in pixels your OverScan hardware would allow
2936          * <yres_max>: max. number of lines your OverScan hardware would allow
2937          * <offset>: Offset from physical beginning to visible beginning
2938          *        of screen in bytes
2939          */
2940         int xres;
2941         char *p;
2942
2943         if (!(p = strsep(&spec, ";")) || !*p)
2944                 return;
2945         xres = simple_strtoul(p, NULL, 10);
2946         if (!(p = strsep(&spec, ";")) || !*p)
2947                 return;
2948         sttt_xres = xres;
2949         tt_yres = st_yres = simple_strtoul(p, NULL, 10);
2950         if ((p = strsep(&spec, ";")) && *p)
2951                 sttt_xres_virtual = simple_strtoul(p, NULL, 10);
2952         if ((p = strsep(&spec, ";")) && *p)
2953                 sttt_yres_virtual = simple_strtoul(p, NULL, 0);
2954         if ((p = strsep(&spec, ";")) && *p)
2955                 ovsc_offset = simple_strtoul(p, NULL, 0);
2956
2957         if (ovsc_offset || (sttt_yres_virtual != st_yres))
2958                 use_hwscroll = 0;
2959 }
2960
2961 #ifdef ATAFB_FALCON
2962 static void __init atafb_setup_mcap(char *spec)
2963 {
2964         char *p;
2965         int vmin, vmax, hmin, hmax;
2966
2967         /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
2968          * <V*> vertical freq. in Hz
2969          * <H*> horizontal freq. in kHz
2970          */
2971         if (!(p = strsep(&spec, ";")) || !*p)
2972                 return;
2973         vmin = simple_strtoul(p, NULL, 10);
2974         if (vmin <= 0)
2975                 return;
2976         if (!(p = strsep(&spec, ";")) || !*p)
2977                 return;
2978         vmax = simple_strtoul(p, NULL, 10);
2979         if (vmax <= 0 || vmax <= vmin)
2980                 return;
2981         if (!(p = strsep(&spec, ";")) || !*p)
2982                 return;
2983         hmin = 1000 * simple_strtoul(p, NULL, 10);
2984         if (hmin <= 0)
2985                 return;
2986         if (!(p = strsep(&spec, "")) || !*p)
2987                 return;
2988         hmax = 1000 * simple_strtoul(p, NULL, 10);
2989         if (hmax <= 0 || hmax <= hmin)
2990                 return;
2991
2992         fb_info.monspecs.vfmin = vmin;
2993         fb_info.monspecs.vfmax = vmax;
2994         fb_info.monspecs.hfmin = hmin;
2995         fb_info.monspecs.hfmax = hmax;
2996 }
2997 #endif /* ATAFB_FALCON */
2998
2999 static void __init atafb_setup_user(char *spec)
3000 {
3001         /* Format of user defined video mode is: <xres>;<yres>;<depth>
3002          */
3003         char *p;
3004         int xres, yres, depth, temp;
3005
3006         p = strsep(&spec, ";");
3007         if (!p || !*p)
3008                 return;
3009         xres = simple_strtoul(p, NULL, 10);
3010         p = strsep(&spec, ";");
3011         if (!p || !*p)
3012                 return;
3013         yres = simple_strtoul(p, NULL, 10);
3014         p = strsep(&spec, "");
3015         if (!p || !*p)
3016                 return;
3017         depth = simple_strtoul(p, NULL, 10);
3018         temp = get_video_mode("user0");
3019         if (temp) {
3020                 default_par = temp;
3021                 atafb_predefined[default_par - 1].xres = xres;
3022                 atafb_predefined[default_par - 1].yres = yres;
3023                 atafb_predefined[default_par - 1].bits_per_pixel = depth;
3024         }
3025 }
3026
3027 int __init atafb_setup(char *options)
3028 {
3029         char *this_opt;
3030         int temp;
3031
3032         if (!options || !*options)
3033                 return 0;
3034
3035         while ((this_opt = strsep(&options, ",")) != NULL) {
3036                 if (!*this_opt)
3037                         continue;
3038                 if ((temp = get_video_mode(this_opt))) {
3039                         default_par = temp;
3040                         mode_option = this_opt;
3041                 } else if (!strcmp(this_opt, "inverse"))
3042                         inverse = 1;
3043                 else if (!strncmp(this_opt, "hwscroll_", 9)) {
3044                         hwscroll = simple_strtoul(this_opt + 9, NULL, 10);
3045                         if (hwscroll < 0)
3046                                 hwscroll = 0;
3047                         if (hwscroll > 200)
3048                                 hwscroll = 200;
3049                 }
3050 #ifdef ATAFB_EXT
3051                 else if (!strcmp(this_opt, "mv300")) {
3052                         external_bitspercol = 8;
3053                         external_card_type = IS_MV300;
3054                 } else if (!strncmp(this_opt, "external:", 9))
3055                         atafb_setup_ext(this_opt + 9);
3056 #endif
3057                 else if (!strncmp(this_opt, "internal:", 9))
3058                         atafb_setup_int(this_opt + 9);
3059 #ifdef ATAFB_FALCON
3060                 else if (!strncmp(this_opt, "eclock:", 7)) {
3061                         fext.f = simple_strtoul(this_opt + 7, NULL, 10);
3062                         /* external pixelclock in kHz --> ps */
3063                         fext.t = 1000000000 / fext.f;
3064                         fext.f *= 1000;
3065                 } else if (!strncmp(this_opt, "monitorcap:", 11))
3066                         atafb_setup_mcap(this_opt + 11);
3067 #endif
3068                 else if (!strcmp(this_opt, "keep"))
3069                         DontCalcRes = 1;
3070                 else if (!strncmp(this_opt, "R", 1))
3071                         atafb_setup_user(this_opt + 1);
3072         }
3073         return 0;
3074 }
3075
3076 int __init atafb_init(void)
3077 {
3078         int pad, detected_mode, error;
3079         unsigned int defmode = 0;
3080         unsigned long mem_req;
3081
3082 #ifndef MODULE
3083         char *option = NULL;
3084
3085         if (fb_get_options("atafb", &option))
3086                 return -ENODEV;
3087         atafb_setup(option);
3088 #endif
3089         printk("atafb_init: start\n");
3090
3091         if (!MACH_IS_ATARI)
3092                 return -ENODEV;
3093
3094         do {
3095 #ifdef ATAFB_EXT
3096                 if (external_addr) {
3097                         printk("atafb_init: initializing external hw\n");
3098                         fbhw = &ext_switch;
3099                         atafb_ops.fb_setcolreg = &ext_setcolreg;
3100                         defmode = DEFMODE_EXT;
3101                         break;
3102                 }
3103 #endif
3104 #ifdef ATAFB_TT
3105                 if (ATARIHW_PRESENT(TT_SHIFTER)) {
3106                         printk("atafb_init: initializing TT hw\n");
3107                         fbhw = &tt_switch;
3108                         atafb_ops.fb_setcolreg = &tt_setcolreg;
3109                         defmode = DEFMODE_TT;
3110                         break;
3111                 }
3112 #endif
3113 #ifdef ATAFB_FALCON
3114                 if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
3115                         printk("atafb_init: initializing Falcon hw\n");
3116                         fbhw = &falcon_switch;
3117                         atafb_ops.fb_setcolreg = &falcon_setcolreg;
3118                         error = request_irq(IRQ_AUTO_4, falcon_vbl_switcher,
3119                                             IRQ_TYPE_PRIO,
3120                                             "framebuffer:modeswitch",
3121                                             falcon_vbl_switcher);
3122                         if (error)
3123                                 return error;
3124                         defmode = DEFMODE_F30;
3125                         break;
3126                 }
3127 #endif
3128 #ifdef ATAFB_STE
3129                 if (ATARIHW_PRESENT(STND_SHIFTER) ||
3130                     ATARIHW_PRESENT(EXTD_SHIFTER)) {
3131                         printk("atafb_init: initializing ST/E hw\n");
3132                         fbhw = &st_switch;
3133                         atafb_ops.fb_setcolreg = &stste_setcolreg;
3134                         defmode = DEFMODE_STE;
3135                         break;
3136                 }
3137                 fbhw = &st_switch;
3138                 atafb_ops.fb_setcolreg = &stste_setcolreg;
3139                 printk("Cannot determine video hardware; defaulting to ST(e)\n");
3140 #else /* ATAFB_STE */
3141                 /* no default driver included */
3142                 /* Nobody will ever see this message :-) */
3143                 panic("Cannot initialize video hardware");
3144 #endif
3145         } while (0);
3146
3147         /* Multisync monitor capabilities */
3148         /* Atari-TOS defaults if no boot option present */
3149         if (fb_info.monspecs.hfmin == 0) {
3150                 fb_info.monspecs.hfmin = 31000;
3151                 fb_info.monspecs.hfmax = 32000;
3152                 fb_info.monspecs.vfmin = 58;
3153                 fb_info.monspecs.vfmax = 62;
3154         }
3155
3156         detected_mode = fbhw->detect();
3157         check_default_par(detected_mode);
3158 #ifdef ATAFB_EXT
3159         if (!external_addr) {
3160 #endif /* ATAFB_EXT */
3161                 mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
3162                 mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
3163                 screen_base = atari_stram_alloc(mem_req, "atafb");
3164                 if (!screen_base)
3165                         panic("Cannot allocate screen memory");
3166                 memset(screen_base, 0, mem_req);
3167                 pad = -(unsigned long)screen_base & (PAGE_SIZE - 1);
3168                 screen_base += pad;
3169                 real_screen_base = screen_base + ovsc_offset;
3170                 screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
3171                 st_ovsc_switch();
3172                 if (CPU_IS_040_OR_060) {
3173                         /* On a '040+, the cache mode of video RAM must be set to
3174                          * write-through also for internal video hardware! */
3175                         cache_push(virt_to_phys(screen_base), screen_len);
3176                         kernel_set_cachemode(screen_base, screen_len,
3177                                              IOMAP_WRITETHROUGH);
3178                 }
3179                 printk("atafb: screen_base %p real_screen_base %p screen_len %d\n",
3180                         screen_base, real_screen_base, screen_len);
3181 #ifdef ATAFB_EXT
3182         } else {
3183                 /* Map the video memory (physical address given) to somewhere
3184                  * in the kernel address space.
3185                  */
3186                 external_addr = ioremap_writethrough((unsigned long)external_addr,
3187                                                      external_len);
3188                 if (external_vgaiobase)
3189                         external_vgaiobase =
3190                           (unsigned long)ioremap(external_vgaiobase, 0x10000);
3191                 screen_base =
3192                 real_screen_base = external_addr;
3193                 screen_len = external_len & PAGE_MASK;
3194                 memset (screen_base, 0, external_len);
3195         }
3196 #endif /* ATAFB_EXT */
3197
3198 //      strcpy(fb_info.mode->name, "Atari Builtin ");
3199         fb_info.fbops = &atafb_ops;
3200         // try to set default (detected; requested) var
3201         do_fb_set_var(&atafb_predefined[default_par - 1], 1);
3202         // reads hw state into current par, which may not be sane yet
3203         ata_get_par(&current_par);
3204         fb_info.par = &current_par;
3205         // tries to read from HW which may not be initialized yet
3206         // so set sane var first, then call atafb_set_par
3207         atafb_get_var(&fb_info.var, &fb_info);
3208
3209 #ifdef ATAFB_FALCON
3210         fb_info.pseudo_palette = current_par.hw.falcon.pseudo_palette;
3211 #endif
3212         fb_info.flags = FBINFO_FLAG_DEFAULT;
3213
3214         if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb,
3215                           NUM_TOTAL_MODES, &atafb_modedb[defmode],
3216                           fb_info.var.bits_per_pixel)) {
3217                 return -EINVAL;
3218         }
3219
3220         fb_videomode_to_modelist(atafb_modedb, NUM_TOTAL_MODES,
3221                                  &fb_info.modelist);
3222
3223         atafb_set_disp(&fb_info);
3224
3225         fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0);
3226
3227
3228         printk("Determined %dx%d, depth %d\n",
3229                fb_info.var.xres, fb_info.var.yres, fb_info.var.bits_per_pixel);
3230         if ((fb_info.var.xres != fb_info.var.xres_virtual) ||
3231             (fb_info.var.yres != fb_info.var.yres_virtual))
3232                 printk("   virtual %dx%d\n", fb_info.var.xres_virtual,
3233                        fb_info.var.yres_virtual);
3234
3235         if (register_framebuffer(&fb_info) < 0) {
3236 #ifdef ATAFB_EXT
3237                 if (external_addr) {
3238                         iounmap(external_addr);
3239                         external_addr = NULL;
3240                 }
3241                 if (external_vgaiobase) {
3242                         iounmap((void*)external_vgaiobase);
3243                         external_vgaiobase = 0;
3244                 }
3245 #endif
3246                 return -EINVAL;
3247         }
3248
3249         // FIXME: mode needs setting!
3250         //printk("fb%d: %s frame buffer device, using %dK of video memory\n",
3251         //       fb_info.node, fb_info.mode->name, screen_len>>10);
3252         printk("fb%d: frame buffer device, using %dK of video memory\n",
3253                fb_info.node, screen_len >> 10);
3254
3255         /* TODO: This driver cannot be unloaded yet */
3256         return 0;
3257 }
3258
3259 module_init(atafb_init);
3260
3261 #ifdef MODULE
3262 MODULE_LICENSE("GPL");
3263
3264 int cleanup_module(void)
3265 {
3266         unregister_framebuffer(&fb_info);
3267         return atafb_deinit();
3268 }
3269 #endif /* MODULE */