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