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