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