Back to home page

LXR

 
 

    


0001 /*
0002  * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device
0003  *
0004  *  Copyright (C) 1994 Martin Schaller & Roman Hodek
0005  *
0006  * This file is subject to the terms and conditions of the GNU General Public
0007  * License.  See the file COPYING in the main directory of this archive
0008  * for more details.
0009  *
0010  * History:
0011  *   - 03 Jan 95: Original version by Martin Schaller: The TT driver and
0012  *                all the device independent stuff
0013  *   - 09 Jan 95: Roman: I've added the hardware abstraction (hw_switch)
0014  *                and wrote the Falcon, ST(E), and External drivers
0015  *                based on the original TT driver.
0016  *   - 07 May 95: Martin: Added colormap operations for the external driver
0017  *   - 21 May 95: Martin: Added support for overscan
0018  *        Andreas: some bug fixes for this
0019  *   -    Jul 95: Guenther Kelleter <guenther@pool.informatik.rwth-aachen.de>:
0020  *                Programmable Falcon video modes
0021  *                (thanks to Christian Cartus for documentation
0022  *                of VIDEL registers).
0023  *   - 27 Dec 95: Guenther: Implemented user definable video modes "user[0-7]"
0024  *                on minor 24...31. "user0" may be set on commandline by
0025  *                "R<x>;<y>;<depth>". (Makes sense only on Falcon)
0026  *                Video mode switch on Falcon now done at next VBL interrupt
0027  *                to avoid the annoying right shift of the screen.
0028  *   - 23 Sep 97: Juergen: added xres_virtual for cards like ProMST
0029  *                The external-part is legacy, therefore hardware-specific
0030  *                functions like panning/hardwarescrolling/blanking isn't
0031  *                supported.
0032  *   - 29 Sep 97: Juergen: added Romans suggestion for pan_display
0033  *                (var->xoffset was changed even if no set_screen_base avail.)
0034  *   - 05 Oct 97: Juergen: extfb (PACKED_PIXEL) is FB_PSEUDOCOLOR 'cause
0035  *                we know how to set the colors
0036  *                ext_*palette: read from ext_colors (former MV300_colors)
0037  *                              write to ext_colors and RAMDAC
0038  *
0039  * To do:
0040  *   - For the Falcon it is not possible to set random video modes on
0041  *     SM124 and SC/TV, only the bootup resolution is supported.
0042  *
0043  */
0044 
0045 #define ATAFB_TT
0046 #define ATAFB_STE
0047 #define ATAFB_EXT
0048 #define ATAFB_FALCON
0049 
0050 #include <linux/module.h>
0051 #include <linux/kernel.h>
0052 #include <linux/errno.h>
0053 #include <linux/string.h>
0054 #include <linux/mm.h>
0055 #include <linux/delay.h>
0056 #include <linux/init.h>
0057 #include <linux/interrupt.h>
0058 
0059 #include <asm/setup.h>
0060 #include <linux/uaccess.h>
0061 #include <asm/pgtable.h>
0062 #include <asm/irq.h>
0063 #include <asm/io.h>
0064 
0065 #include <asm/atarihw.h>
0066 #include <asm/atariints.h>
0067 #include <asm/atari_stram.h>
0068 
0069 #include <linux/fb.h>
0070 #include <asm/atarikb.h>
0071 
0072 #include "c2p.h"
0073 #include "atafb.h"
0074 
0075 #define SWITCH_ACIA 0x01        /* modes for switch on OverScan */
0076 #define SWITCH_SND6 0x40
0077 #define SWITCH_SND7 0x80
0078 #define SWITCH_NONE 0x00
0079 
0080 
0081 #define up(x, r) (((x) + (r) - 1) & ~((r)-1))
0082 
0083     /*
0084      * Interface to the world
0085      */
0086 
0087 static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
0088 static int atafb_set_par(struct fb_info *info);
0089 static int atafb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
0090                unsigned int blue, unsigned int transp,
0091                struct fb_info *info);
0092 static int atafb_blank(int blank, struct fb_info *info);
0093 static int atafb_pan_display(struct fb_var_screeninfo *var,
0094                  struct fb_info *info);
0095 static void atafb_fillrect(struct fb_info *info,
0096                const struct fb_fillrect *rect);
0097 static void atafb_copyarea(struct fb_info *info,
0098                const struct fb_copyarea *region);
0099 static void atafb_imageblit(struct fb_info *info, const struct fb_image *image);
0100 static int atafb_ioctl(struct fb_info *info, unsigned int cmd,
0101                unsigned long arg);
0102 
0103 
0104 static int default_par;     /* default resolution (0=none) */
0105 
0106 static unsigned long default_mem_req;
0107 
0108 static int hwscroll = -1;
0109 
0110 static int use_hwscroll = 1;
0111 
0112 static int sttt_xres = 640, st_yres = 400, tt_yres = 480;
0113 static int sttt_xres_virtual = 640, sttt_yres_virtual = 400;
0114 static int ovsc_offset, ovsc_addlen;
0115 
0116     /*
0117      * Hardware parameters for current mode
0118      */
0119 
0120 static struct atafb_par {
0121     void *screen_base;
0122     int yres_virtual;
0123     u_long next_line;
0124 #if defined ATAFB_TT || defined ATAFB_STE
0125     union {
0126         struct {
0127             int mode;
0128             int sync;
0129         } tt, st;
0130 #endif
0131 #ifdef ATAFB_FALCON
0132         struct falcon_hw {
0133             /* Here are fields for storing a video mode, as direct
0134              * parameters for the hardware.
0135              */
0136             short sync;
0137             short line_width;
0138             short line_offset;
0139             short st_shift;
0140             short f_shift;
0141             short vid_control;
0142             short vid_mode;
0143             short xoffset;
0144             short hht, hbb, hbe, hdb, hde, hss;
0145             short vft, vbb, vbe, vdb, vde, vss;
0146             /* auxiliary information */
0147             short mono;
0148             short ste_mode;
0149             short bpp;
0150             u32 pseudo_palette[16];
0151         } falcon;
0152 #endif
0153         /* Nothing needed for external mode */
0154     } hw;
0155 } current_par;
0156 
0157 /* Don't calculate an own resolution, and thus don't change the one found when
0158  * booting (currently used for the Falcon to keep settings for internal video
0159  * hardware extensions (e.g. ScreenBlaster)  */
0160 static int DontCalcRes = 0;
0161 
0162 #ifdef ATAFB_FALCON
0163 #define HHT hw.falcon.hht
0164 #define HBB hw.falcon.hbb
0165 #define HBE hw.falcon.hbe
0166 #define HDB hw.falcon.hdb
0167 #define HDE hw.falcon.hde
0168 #define HSS hw.falcon.hss
0169 #define VFT hw.falcon.vft
0170 #define VBB hw.falcon.vbb
0171 #define VBE hw.falcon.vbe
0172 #define VDB hw.falcon.vdb
0173 #define VDE hw.falcon.vde
0174 #define VSS hw.falcon.vss
0175 #define VCO_CLOCK25     0x04
0176 #define VCO_CSYPOS      0x10
0177 #define VCO_VSYPOS      0x20
0178 #define VCO_HSYPOS      0x40
0179 #define VCO_SHORTOFFS   0x100
0180 #define VMO_DOUBLE      0x01
0181 #define VMO_INTER       0x02
0182 #define VMO_PREMASK     0x0c
0183 #endif
0184 
0185 static struct fb_info fb_info = {
0186     .fix = {
0187         .id = "Atari ",
0188         .visual = FB_VISUAL_PSEUDOCOLOR,
0189         .accel  = FB_ACCEL_NONE,
0190     }
0191 };
0192 
0193 static void *screen_base;   /* base address of screen */
0194 static unsigned long phys_screen_base;  /* (only for Overscan) */
0195 
0196 static int screen_len;
0197 
0198 static int current_par_valid;
0199 
0200 static int mono_moni;
0201 
0202 
0203 #ifdef ATAFB_EXT
0204 
0205 /* external video handling */
0206 static unsigned int external_xres;
0207 static unsigned int external_xres_virtual;
0208 static unsigned int external_yres;
0209 
0210 /*
0211  * not needed - atafb will never support panning/hardwarescroll with external
0212  * static unsigned int external_yres_virtual;
0213  */
0214 static unsigned int external_depth;
0215 static int external_pmode;
0216 static void *external_screen_base;
0217 static unsigned long external_addr;
0218 static unsigned long external_len;
0219 static unsigned long external_vgaiobase;
0220 static unsigned int external_bitspercol = 6;
0221 
0222 /*
0223  * JOE <joe@amber.dinoco.de>:
0224  * added card type for external driver, is only needed for
0225  * colormap handling.
0226  */
0227 enum cardtype { IS_VGA, IS_MV300 };
0228 static enum cardtype external_card_type = IS_VGA;
0229 
0230 /*
0231  * The MV300 mixes the color registers. So we need an array of munged
0232  * indices in order to access the correct reg.
0233  */
0234 static int MV300_reg_1bit[2] = {
0235     0, 1
0236 };
0237 static int MV300_reg_4bit[16] = {
0238     0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
0239 };
0240 static int MV300_reg_8bit[256] = {
0241     0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
0242     8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
0243     4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
0244     12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
0245     2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
0246     10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
0247     6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
0248     14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
0249     1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
0250     9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
0251     5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
0252     13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
0253     3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
0254     11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
0255     7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
0256     15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
0257 };
0258 
0259 static int *MV300_reg = MV300_reg_8bit;
0260 #endif /* ATAFB_EXT */
0261 
0262 
0263 static int inverse;
0264 
0265 extern int fontheight_8x8;
0266 extern int fontwidth_8x8;
0267 extern unsigned char fontdata_8x8[];
0268 
0269 extern int fontheight_8x16;
0270 extern int fontwidth_8x16;
0271 extern unsigned char fontdata_8x16[];
0272 
0273 /*
0274  * struct fb_ops {
0275  *  * open/release and usage marking
0276  *  struct module *owner;
0277  *  int (*fb_open)(struct fb_info *info, int user);
0278  *  int (*fb_release)(struct fb_info *info, int user);
0279  *
0280  *  * For framebuffers with strange non linear layouts or that do not
0281  *  * work with normal memory mapped access
0282  *  ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos);
0283  *  ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
0284  *
0285  *  * checks var and eventually tweaks it to something supported,
0286  *  * DOES NOT MODIFY PAR *
0287  *  int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
0288  *
0289  *  * set the video mode according to info->var *
0290  *  int (*fb_set_par)(struct fb_info *info);
0291  *
0292  *  * set color register *
0293  *  int (*fb_setcolreg)(unsigned int regno, unsigned int red, unsigned int green,
0294  *              unsigned int blue, unsigned int transp, struct fb_info *info);
0295  *
0296  *  * set color registers in batch *
0297  *  int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
0298  *
0299  *  * blank display *
0300  *  int (*fb_blank)(int blank, struct fb_info *info);
0301  *
0302  *  * pan display *
0303  *  int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
0304  *
0305  *  *** The meat of the drawing engine ***
0306  *  * Draws a rectangle *
0307  *  void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
0308  *  * Copy data from area to another *
0309  *  void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
0310  *  * Draws a image to the display *
0311  *  void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
0312  *
0313  *  * Draws cursor *
0314  *  int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
0315  *
0316  *  * wait for blit idle, optional *
0317  *  int (*fb_sync)(struct fb_info *info);
0318  *
0319  *  * perform fb specific ioctl (optional) *
0320  *  int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
0321  *          unsigned long arg);
0322  *
0323  *  * Handle 32bit compat ioctl (optional) *
0324  *  int (*fb_compat_ioctl)(struct fb_info *info, unsigned int cmd,
0325  *          unsigned long arg);
0326  *
0327  *  * perform fb specific mmap *
0328  *  int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
0329  * } ;
0330  */
0331 
0332 
0333 /* ++roman: This structure abstracts from the underlying hardware (ST(e),
0334  * TT, or Falcon.
0335  *
0336  * int (*detect)(void)
0337  *   This function should detect the current video mode settings and
0338  *   store them in atafb_predefined[0] for later reference by the
0339  *   user. Return the index+1 of an equivalent predefined mode or 0
0340  *   if there is no such.
0341  *
0342  * int (*encode_fix)(struct fb_fix_screeninfo *fix,
0343  *                   struct atafb_par *par)
0344  *   This function should fill in the 'fix' structure based on the
0345  *   values in the 'par' structure.
0346  * !!! Obsolete, perhaps !!!
0347  *
0348  * int (*decode_var)(struct fb_var_screeninfo *var,
0349  *                   struct atafb_par *par)
0350  *   Get the video params out of 'var'. If a value doesn't fit, round
0351  *   it up, if it's too big, return EINVAL.
0352  *   Round up in the following order: bits_per_pixel, xres, yres,
0353  *   xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
0354  *   horizontal timing, vertical timing.
0355  *
0356  * int (*encode_var)(struct fb_var_screeninfo *var,
0357  *                   struct atafb_par *par);
0358  *   Fill the 'var' structure based on the values in 'par' and maybe
0359  *   other values read out of the hardware.
0360  *
0361  * void (*get_par)(struct atafb_par *par)
0362  *   Fill the hardware's 'par' structure.
0363  *   !!! Used only by detect() !!!
0364  *
0365  * void (*set_par)(struct atafb_par *par)
0366  *   Set the hardware according to 'par'.
0367  *
0368  * void (*set_screen_base)(void *s_base)
0369  *   Set the base address of the displayed frame buffer. Only called
0370  *   if yres_virtual > yres or xres_virtual > xres.
0371  *
0372  * int (*blank)(int blank_mode)
0373  *   Blank the screen if blank_mode != 0, else unblank. If blank == NULL then
0374  *   the caller blanks by setting the CLUT to all black. Return 0 if blanking
0375  *   succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
0376  *   doesn't support it. Implements VESA suspend and powerdown modes on
0377  *   hardware that supports disabling hsync/vsync:
0378  *       blank_mode == 2: suspend vsync, 3:suspend hsync, 4: powerdown.
0379  */
0380 
0381 static struct fb_hwswitch {
0382     int (*detect)(void);
0383     int (*encode_fix)(struct fb_fix_screeninfo *fix,
0384               struct atafb_par *par);
0385     int (*decode_var)(struct fb_var_screeninfo *var,
0386               struct atafb_par *par);
0387     int (*encode_var)(struct fb_var_screeninfo *var,
0388               struct atafb_par *par);
0389     void (*get_par)(struct atafb_par *par);
0390     void (*set_par)(struct atafb_par *par);
0391     void (*set_screen_base)(void *s_base);
0392     int (*blank)(int blank_mode);
0393     int (*pan_display)(struct fb_var_screeninfo *var,
0394                struct fb_info *info);
0395 } *fbhw;
0396 
0397 static char *autodetect_names[] = { "autodetect", NULL };
0398 static char *stlow_names[] = { "stlow", NULL };
0399 static char *stmid_names[] = { "stmid", "default5", NULL };
0400 static char *sthigh_names[] = { "sthigh", "default4", NULL };
0401 static char *ttlow_names[] = { "ttlow", NULL };
0402 static char *ttmid_names[] = { "ttmid", "default1", NULL };
0403 static char *tthigh_names[] = { "tthigh", "default2", NULL };
0404 static char *vga2_names[] = { "vga2", NULL };
0405 static char *vga4_names[] = { "vga4", NULL };
0406 static char *vga16_names[] = { "vga16", "default3", NULL };
0407 static char *vga256_names[] = { "vga256", NULL };
0408 static char *falh2_names[] = { "falh2", NULL };
0409 static char *falh16_names[] = { "falh16", NULL };
0410 
0411 static char **fb_var_names[] = {
0412     autodetect_names,
0413     stlow_names,
0414     stmid_names,
0415     sthigh_names,
0416     ttlow_names,
0417     ttmid_names,
0418     tthigh_names,
0419     vga2_names,
0420     vga4_names,
0421     vga16_names,
0422     vga256_names,
0423     falh2_names,
0424     falh16_names,
0425     NULL
0426 };
0427 
0428 static struct fb_var_screeninfo atafb_predefined[] = {
0429     /*
0430      * yres_virtual == 0 means use hw-scrolling if possible, else yres
0431      */
0432     { /* autodetect */
0433       0, 0, 0, 0, 0, 0, 0, 0,       /* xres-grayscale */
0434       {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},   /* red green blue tran*/
0435       0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
0436     { /* st low */
0437       320, 200, 320, 0, 0, 0, 4, 0,
0438       {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
0439       0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
0440     { /* st mid */
0441       640, 200, 640, 0, 0, 0, 2, 0,
0442       {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
0443       0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
0444     { /* st high */
0445       640, 400, 640, 0, 0, 0, 1, 0,
0446       {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
0447       0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
0448     { /* tt low */
0449       320, 480, 320, 0, 0, 0, 8, 0,
0450       {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
0451       0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
0452     { /* tt mid */
0453       640, 480, 640, 0, 0, 0, 4, 0,
0454       {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
0455       0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
0456     { /* tt high */
0457       1280, 960, 1280, 0, 0, 0, 1, 0,
0458       {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
0459       0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
0460     { /* vga2 */
0461       640, 480, 640, 0, 0, 0, 1, 0,
0462       {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
0463       0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
0464     { /* vga4 */
0465       640, 480, 640, 0, 0, 0, 2, 0,
0466       {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
0467       0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
0468     { /* vga16 */
0469       640, 480, 640, 0, 0, 0, 4, 0,
0470       {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
0471       0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
0472     { /* vga256 */
0473       640, 480, 640, 0, 0, 0, 8, 0,
0474       {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
0475       0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
0476     { /* falh2 */
0477       896, 608, 896, 0, 0, 0, 1, 0,
0478       {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
0479       0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
0480     { /* falh16 */
0481       896, 608, 896, 0, 0, 0, 4, 0,
0482       {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
0483       0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
0484 };
0485 
0486 static int num_atafb_predefined = ARRAY_SIZE(atafb_predefined);
0487 
0488 static struct fb_videomode atafb_modedb[] __initdata = {
0489     /*
0490      *  Atari Video Modes
0491      *
0492      *  If you change these, make sure to update DEFMODE_* as well!
0493      */
0494 
0495     /*
0496      *  ST/TT Video Modes
0497      */
0498 
0499     {
0500         /* 320x200, 15 kHz, 60 Hz (ST low) */
0501         "st-low", 60, 320, 200, 32000, 32, 16, 31, 14, 96, 4,
0502         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0503     }, {
0504         /* 640x200, 15 kHz, 60 Hz (ST medium) */
0505         "st-mid", 60, 640, 200, 32000, 32, 16, 31, 14, 96, 4,
0506         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0507     }, {
0508         /* 640x400, 30.25 kHz, 63.5 Hz (ST high) */
0509         "st-high", 63, 640, 400, 32000, 128, 0, 40, 14, 128, 4,
0510         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0511     }, {
0512         /* 320x480, 15 kHz, 60 Hz (TT low) */
0513         "tt-low", 60, 320, 480, 31041, 120, 100, 8, 16, 140, 30,
0514         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0515     }, {
0516         /* 640x480, 29 kHz, 57 Hz (TT medium) */
0517         "tt-mid", 60, 640, 480, 31041, 120, 100, 8, 16, 140, 30,
0518         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0519     }, {
0520         /* 1280x960, 29 kHz, 60 Hz (TT high) */
0521         "tt-high", 57, 640, 960, 31041, 120, 100, 8, 16, 140, 30,
0522         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0523     },
0524 
0525     /*
0526      *  VGA Video Modes
0527      */
0528 
0529     {
0530         /* 640x480, 31 kHz, 60 Hz (VGA) */
0531         "vga", 63.5, 640, 480, 32000, 18, 42, 31, 11, 96, 3,
0532         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0533     }, {
0534         /* 640x400, 31 kHz, 70 Hz (VGA) */
0535         "vga70", 70, 640, 400, 32000, 18, 42, 31, 11, 96, 3,
0536         FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0537     },
0538 
0539     /*
0540      *  Falcon HiRes Video Modes
0541      */
0542 
0543     {
0544         /* 896x608, 31 kHz, 60 Hz (Falcon High) */
0545         "falh", 60, 896, 608, 32000, 18, 42, 31, 1, 96,3,
0546         0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0547     },
0548 };
0549 
0550 #define NUM_TOTAL_MODES  ARRAY_SIZE(atafb_modedb)
0551 
0552 static char *mode_option __initdata = NULL;
0553 
0554  /* default modes */
0555 
0556 #define DEFMODE_TT  5       /* "tt-high" for TT */
0557 #define DEFMODE_F30 7       /* "vga70" for Falcon */
0558 #define DEFMODE_STE 2       /* "st-high" for ST/E */
0559 #define DEFMODE_EXT 6       /* "vga" for external */
0560 
0561 
0562 static int get_video_mode(char *vname)
0563 {
0564     char ***name_list;
0565     char **name;
0566     int i;
0567 
0568     name_list = fb_var_names;
0569     for (i = 0; i < num_atafb_predefined; i++) {
0570         name = *name_list++;
0571         if (!name || !*name)
0572             break;
0573         while (*name) {
0574             if (!strcmp(vname, *name))
0575                 return i + 1;
0576             name++;
0577         }
0578     }
0579     return 0;
0580 }
0581 
0582 
0583 
0584 /* ------------------- TT specific functions ---------------------- */
0585 
0586 #ifdef ATAFB_TT
0587 
0588 static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
0589 {
0590     int mode;
0591 
0592     strcpy(fix->id, "Atari Builtin");
0593     fix->smem_start = phys_screen_base;
0594     fix->smem_len = screen_len;
0595     fix->type = FB_TYPE_INTERLEAVED_PLANES;
0596     fix->type_aux = 2;
0597     fix->visual = FB_VISUAL_PSEUDOCOLOR;
0598     mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK;
0599     if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) {
0600         fix->type = FB_TYPE_PACKED_PIXELS;
0601         fix->type_aux = 0;
0602         if (mode == TT_SHIFTER_TTHIGH)
0603             fix->visual = FB_VISUAL_MONO01;
0604     }
0605     fix->xpanstep = 0;
0606     fix->ypanstep = 1;
0607     fix->ywrapstep = 0;
0608     fix->line_length = par->next_line;
0609     fix->accel = FB_ACCEL_ATARIBLITT;
0610     return 0;
0611 }
0612 
0613 static int tt_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
0614 {
0615     int xres = var->xres;
0616     int yres = var->yres;
0617     int bpp = var->bits_per_pixel;
0618     int linelen;
0619     int yres_virtual = var->yres_virtual;
0620 
0621     if (mono_moni) {
0622         if (bpp > 1 || xres > sttt_xres * 2 || yres > tt_yres * 2)
0623             return -EINVAL;
0624         par->hw.tt.mode = TT_SHIFTER_TTHIGH;
0625         xres = sttt_xres * 2;
0626         yres = tt_yres * 2;
0627         bpp = 1;
0628     } else {
0629         if (bpp > 8 || xres > sttt_xres || yres > tt_yres)
0630             return -EINVAL;
0631         if (bpp > 4) {
0632             if (xres > sttt_xres / 2 || yres > tt_yres)
0633                 return -EINVAL;
0634             par->hw.tt.mode = TT_SHIFTER_TTLOW;
0635             xres = sttt_xres / 2;
0636             yres = tt_yres;
0637             bpp = 8;
0638         } else if (bpp > 2) {
0639             if (xres > sttt_xres || yres > tt_yres)
0640                 return -EINVAL;
0641             if (xres > sttt_xres / 2 || yres > st_yres / 2) {
0642                 par->hw.tt.mode = TT_SHIFTER_TTMID;
0643                 xres = sttt_xres;
0644                 yres = tt_yres;
0645                 bpp = 4;
0646             } else {
0647                 par->hw.tt.mode = TT_SHIFTER_STLOW;
0648                 xres = sttt_xres / 2;
0649                 yres = st_yres / 2;
0650                 bpp = 4;
0651             }
0652         } else if (bpp > 1) {
0653             if (xres > sttt_xres || yres > st_yres / 2)
0654                 return -EINVAL;
0655             par->hw.tt.mode = TT_SHIFTER_STMID;
0656             xres = sttt_xres;
0657             yres = st_yres / 2;
0658             bpp = 2;
0659         } else if (var->xres > sttt_xres || var->yres > st_yres) {
0660             return -EINVAL;
0661         } else {
0662             par->hw.tt.mode = TT_SHIFTER_STHIGH;
0663             xres = sttt_xres;
0664             yres = st_yres;
0665             bpp = 1;
0666         }
0667     }
0668     if (yres_virtual <= 0)
0669         yres_virtual = 0;
0670     else if (yres_virtual < yres)
0671         yres_virtual = yres;
0672     if (var->sync & FB_SYNC_EXT)
0673         par->hw.tt.sync = 0;
0674     else
0675         par->hw.tt.sync = 1;
0676     linelen = xres * bpp / 8;
0677     if (yres_virtual * linelen > screen_len && screen_len)
0678         return -EINVAL;
0679     if (yres * linelen > screen_len && screen_len)
0680         return -EINVAL;
0681     if (var->yoffset + yres > yres_virtual && yres_virtual)
0682         return -EINVAL;
0683     par->yres_virtual = yres_virtual;
0684     par->screen_base = screen_base + var->yoffset * linelen;
0685     par->next_line = linelen;
0686     return 0;
0687 }
0688 
0689 static int tt_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
0690 {
0691     int linelen;
0692     memset(var, 0, sizeof(struct fb_var_screeninfo));
0693     var->red.offset = 0;
0694     var->red.length = 4;
0695     var->red.msb_right = 0;
0696     var->grayscale = 0;
0697 
0698     var->pixclock = 31041;
0699     var->left_margin = 120;     /* these may be incorrect */
0700     var->right_margin = 100;
0701     var->upper_margin = 8;
0702     var->lower_margin = 16;
0703     var->hsync_len = 140;
0704     var->vsync_len = 30;
0705 
0706     var->height = -1;
0707     var->width = -1;
0708 
0709     if (par->hw.tt.sync & 1)
0710         var->sync = 0;
0711     else
0712         var->sync = FB_SYNC_EXT;
0713 
0714     switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) {
0715     case TT_SHIFTER_STLOW:
0716         var->xres = sttt_xres / 2;
0717         var->xres_virtual = sttt_xres_virtual / 2;
0718         var->yres = st_yres / 2;
0719         var->bits_per_pixel = 4;
0720         break;
0721     case TT_SHIFTER_STMID:
0722         var->xres = sttt_xres;
0723         var->xres_virtual = sttt_xres_virtual;
0724         var->yres = st_yres / 2;
0725         var->bits_per_pixel = 2;
0726         break;
0727     case TT_SHIFTER_STHIGH:
0728         var->xres = sttt_xres;
0729         var->xres_virtual = sttt_xres_virtual;
0730         var->yres = st_yres;
0731         var->bits_per_pixel = 1;
0732         break;
0733     case TT_SHIFTER_TTLOW:
0734         var->xres = sttt_xres / 2;
0735         var->xres_virtual = sttt_xres_virtual / 2;
0736         var->yres = tt_yres;
0737         var->bits_per_pixel = 8;
0738         break;
0739     case TT_SHIFTER_TTMID:
0740         var->xres = sttt_xres;
0741         var->xres_virtual = sttt_xres_virtual;
0742         var->yres = tt_yres;
0743         var->bits_per_pixel = 4;
0744         break;
0745     case TT_SHIFTER_TTHIGH:
0746         var->red.length = 0;
0747         var->xres = sttt_xres * 2;
0748         var->xres_virtual = sttt_xres_virtual * 2;
0749         var->yres = tt_yres * 2;
0750         var->bits_per_pixel = 1;
0751         break;
0752     }
0753     var->blue = var->green = var->red;
0754     var->transp.offset = 0;
0755     var->transp.length = 0;
0756     var->transp.msb_right = 0;
0757     linelen = var->xres_virtual * var->bits_per_pixel / 8;
0758     if (!use_hwscroll)
0759         var->yres_virtual = var->yres;
0760     else if (screen_len) {
0761         if (par->yres_virtual)
0762             var->yres_virtual = par->yres_virtual;
0763         else
0764             /* yres_virtual == 0 means use maximum */
0765             var->yres_virtual = screen_len / linelen;
0766     } else {
0767         if (hwscroll < 0)
0768             var->yres_virtual = 2 * var->yres;
0769         else
0770             var->yres_virtual = var->yres + hwscroll * 16;
0771     }
0772     var->xoffset = 0;
0773     if (screen_base)
0774         var->yoffset = (par->screen_base - screen_base) / linelen;
0775     else
0776         var->yoffset = 0;
0777     var->nonstd = 0;
0778     var->activate = 0;
0779     var->vmode = FB_VMODE_NONINTERLACED;
0780     return 0;
0781 }
0782 
0783 static void tt_get_par(struct atafb_par *par)
0784 {
0785     unsigned long addr;
0786     par->hw.tt.mode = shifter_tt.tt_shiftmode;
0787     par->hw.tt.sync = shifter.syncmode;
0788     addr = ((shifter.bas_hi & 0xff) << 16) |
0789            ((shifter.bas_md & 0xff) << 8)  |
0790            ((shifter.bas_lo & 0xff));
0791     par->screen_base = atari_stram_to_virt(addr);
0792 }
0793 
0794 static void tt_set_par(struct atafb_par *par)
0795 {
0796     shifter_tt.tt_shiftmode = par->hw.tt.mode;
0797     shifter.syncmode = par->hw.tt.sync;
0798     /* only set screen_base if really necessary */
0799     if (current_par.screen_base != par->screen_base)
0800         fbhw->set_screen_base(par->screen_base);
0801 }
0802 
0803 static int tt_setcolreg(unsigned int regno, unsigned int red,
0804             unsigned int green, unsigned int blue,
0805             unsigned int transp, struct fb_info *info)
0806 {
0807     if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
0808         regno += 254;
0809     if (regno > 255)
0810         return 1;
0811     tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) |
0812                  (blue >> 12));
0813     if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
0814         TT_SHIFTER_STHIGH && regno == 254)
0815         tt_palette[0] = 0;
0816     return 0;
0817 }
0818 
0819 static int tt_detect(void)
0820 {
0821     struct atafb_par par;
0822 
0823     /* Determine the connected monitor: The DMA sound must be
0824      * disabled before reading the MFP GPIP, because the Sound
0825      * Done Signal and the Monochrome Detect are XORed together!
0826      *
0827      * Even on a TT, we should look if there is a DMA sound. It was
0828      * announced that the Eagle is TT compatible, but only the PCM is
0829      * missing...
0830      */
0831     if (ATARIHW_PRESENT(PCM_8BIT)) {
0832         tt_dmasnd.ctrl = DMASND_CTRL_OFF;
0833         udelay(20);     /* wait a while for things to settle down */
0834     }
0835     mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
0836 
0837     tt_get_par(&par);
0838     tt_encode_var(&atafb_predefined[0], &par);
0839 
0840     return 1;
0841 }
0842 
0843 #endif /* ATAFB_TT */
0844 
0845 /* ------------------- Falcon specific functions ---------------------- */
0846 
0847 #ifdef ATAFB_FALCON
0848 
0849 static int mon_type;        /* Falcon connected monitor */
0850 static int f030_bus_width;  /* Falcon ram bus width (for vid_control) */
0851 #define F_MON_SM    0
0852 #define F_MON_SC    1
0853 #define F_MON_VGA   2
0854 #define F_MON_TV    3
0855 
0856 static struct pixel_clock {
0857     unsigned long f;    /* f/[Hz] */
0858     unsigned long t;    /* t/[ps] (=1/f) */
0859     int right, hsync, left; /* standard timing in clock cycles, not pixel */
0860     /* hsync initialized in falcon_detect() */
0861     int sync_mask;      /* or-mask for hw.falcon.sync to set this clock */
0862     int control_mask;   /* ditto, for hw.falcon.vid_control */
0863 } f25 = {
0864     25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25
0865 }, f32 = {
0866     32000000, 31250, 18, 0, 42, 0x0, 0
0867 }, fext = {
0868     0, 0, 18, 0, 42, 0x1, 0
0869 };
0870 
0871 /* VIDEL-prescale values [mon_type][pixel_length from VCO] */
0872 static int vdl_prescale[4][3] = {
0873     { 4,2,1 }, { 4,2,1 }, { 4,2,2 }, { 4,2,1 }
0874 };
0875 
0876 /* Default hsync timing [mon_type] in picoseconds */
0877 static long h_syncs[4] = { 3000000, 4875000, 4000000, 4875000 };
0878 
0879 static inline int hxx_prescale(struct falcon_hw *hw)
0880 {
0881     return hw->ste_mode ? 16
0882                 : vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
0883 }
0884 
0885 static int falcon_encode_fix(struct fb_fix_screeninfo *fix,
0886                  struct atafb_par *par)
0887 {
0888     strcpy(fix->id, "Atari Builtin");
0889     fix->smem_start = phys_screen_base;
0890     fix->smem_len = screen_len;
0891     fix->type = FB_TYPE_INTERLEAVED_PLANES;
0892     fix->type_aux = 2;
0893     fix->visual = FB_VISUAL_PSEUDOCOLOR;
0894     fix->xpanstep = 1;
0895     fix->ypanstep = 1;
0896     fix->ywrapstep = 0;
0897     if (par->hw.falcon.mono) {
0898         fix->type = FB_TYPE_PACKED_PIXELS;
0899         fix->type_aux = 0;
0900         /* no smooth scrolling with longword aligned video mem */
0901         fix->xpanstep = 32;
0902     } else if (par->hw.falcon.f_shift & 0x100) {
0903         fix->type = FB_TYPE_PACKED_PIXELS;
0904         fix->type_aux = 0;
0905         /* Is this ok or should it be DIRECTCOLOR? */
0906         fix->visual = FB_VISUAL_TRUECOLOR;
0907         fix->xpanstep = 2;
0908     }
0909     fix->line_length = par->next_line;
0910     fix->accel = FB_ACCEL_ATARIBLITT;
0911     return 0;
0912 }
0913 
0914 static int falcon_decode_var(struct fb_var_screeninfo *var,
0915                  struct atafb_par *par)
0916 {
0917     int bpp = var->bits_per_pixel;
0918     int xres = var->xres;
0919     int yres = var->yres;
0920     int xres_virtual = var->xres_virtual;
0921     int yres_virtual = var->yres_virtual;
0922     int left_margin, right_margin, hsync_len;
0923     int upper_margin, lower_margin, vsync_len;
0924     int linelen;
0925     int interlace = 0, doubleline = 0;
0926     struct pixel_clock *pclock;
0927     int plen;           /* width of pixel in clock cycles */
0928     int xstretch;
0929     int prescale;
0930     int longoffset = 0;
0931     int hfreq, vfreq;
0932     int hdb_off, hde_off, base_off;
0933     int gstart, gend1, gend2, align;
0934 
0935 /*
0936     Get the video params out of 'var'. If a value doesn't fit, round
0937     it up, if it's too big, return EINVAL.
0938     Round up in the following order: bits_per_pixel, xres, yres,
0939     xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
0940     horizontal timing, vertical timing.
0941 
0942     There is a maximum of screen resolution determined by pixelclock
0943     and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock.
0944     In interlace mode this is     "     *    "     *vfmin <= pixelclock.
0945     Additional constraints: hfreq.
0946     Frequency range for multisync monitors is given via command line.
0947     For TV and SM124 both frequencies are fixed.
0948 
0949     X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32 == 0)
0950     Y % 16 == 0 to fit 8x16 font
0951     Y % 8 == 0 if Y<400
0952 
0953     Currently interlace and doubleline mode in var are ignored.
0954     On SM124 and TV only the standard resolutions can be used.
0955 */
0956 
0957     /* Reject uninitialized mode */
0958     if (!xres || !yres || !bpp)
0959         return -EINVAL;
0960 
0961     if (mon_type == F_MON_SM && bpp != 1)
0962         return -EINVAL;
0963 
0964     if (bpp <= 1) {
0965         bpp = 1;
0966         par->hw.falcon.f_shift = 0x400;
0967         par->hw.falcon.st_shift = 0x200;
0968     } else if (bpp <= 2) {
0969         bpp = 2;
0970         par->hw.falcon.f_shift = 0x000;
0971         par->hw.falcon.st_shift = 0x100;
0972     } else if (bpp <= 4) {
0973         bpp = 4;
0974         par->hw.falcon.f_shift = 0x000;
0975         par->hw.falcon.st_shift = 0x000;
0976     } else if (bpp <= 8) {
0977         bpp = 8;
0978         par->hw.falcon.f_shift = 0x010;
0979     } else if (bpp <= 16) {
0980         bpp = 16;       /* packed pixel mode */
0981         par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */
0982     } else
0983         return -EINVAL;
0984     par->hw.falcon.bpp = bpp;
0985 
0986     if (mon_type == F_MON_SM || DontCalcRes) {
0987         /* Skip all calculations. VGA/TV/SC1224 only supported. */
0988         struct fb_var_screeninfo *myvar = &atafb_predefined[0];
0989 
0990         if (bpp > myvar->bits_per_pixel ||
0991             var->xres > myvar->xres ||
0992             var->yres > myvar->yres)
0993             return -EINVAL;
0994         fbhw->get_par(par); /* Current par will be new par */
0995         goto set_screen_base;   /* Don't forget this */
0996     }
0997 
0998     /* Only some fixed resolutions < 640x400 */
0999     if (xres <= 320)
1000         xres = 320;
1001     else if (xres <= 640 && bpp != 16)
1002         xres = 640;
1003     if (yres <= 200)
1004         yres = 200;
1005     else if (yres <= 240)
1006         yres = 240;
1007     else if (yres <= 400)
1008         yres = 400;
1009 
1010     /* 2 planes must use STE compatibility mode */
1011     par->hw.falcon.ste_mode = bpp == 2;
1012     par->hw.falcon.mono = bpp == 1;
1013 
1014     /* Total and visible scanline length must be a multiple of one longword,
1015      * this and the console fontwidth yields the alignment for xres and
1016      * xres_virtual.
1017      * TODO: this way "odd" fontheights are not supported
1018      *
1019      * Special case in STE mode: blank and graphic positions don't align,
1020      * avoid trash at right margin
1021      */
1022     if (par->hw.falcon.ste_mode)
1023         xres = (xres + 63) & ~63;
1024     else if (bpp == 1)
1025         xres = (xres + 31) & ~31;
1026     else
1027         xres = (xres + 15) & ~15;
1028     if (yres >= 400)
1029         yres = (yres + 15) & ~15;
1030     else
1031         yres = (yres + 7) & ~7;
1032 
1033     if (xres_virtual < xres)
1034         xres_virtual = xres;
1035     else if (bpp == 1)
1036         xres_virtual = (xres_virtual + 31) & ~31;
1037     else
1038         xres_virtual = (xres_virtual + 15) & ~15;
1039 
1040     if (yres_virtual <= 0)
1041         yres_virtual = 0;
1042     else if (yres_virtual < yres)
1043         yres_virtual = yres;
1044 
1045     /* backward bug-compatibility */
1046     if (var->pixclock > 1)
1047         var->pixclock -= 1;
1048 
1049     par->hw.falcon.line_width = bpp * xres / 16;
1050     par->hw.falcon.line_offset = bpp * (xres_virtual - xres) / 16;
1051 
1052     /* single or double pixel width */
1053     xstretch = (xres < 640) ? 2 : 1;
1054 
1055 #if 0 /* SM124 supports only 640x400, this is rejected above */
1056     if (mon_type == F_MON_SM) {
1057         if (xres != 640 && yres != 400)
1058             return -EINVAL;
1059         plen = 1;
1060         pclock = &f32;
1061         /* SM124-mode is special */
1062         par->hw.falcon.ste_mode = 1;
1063         par->hw.falcon.f_shift = 0x000;
1064         par->hw.falcon.st_shift = 0x200;
1065         left_margin = hsync_len = 128 / plen;
1066         right_margin = 0;
1067         /* TODO set all margins */
1068     } else
1069 #endif
1070     if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
1071         plen = 2 * xstretch;
1072         if (var->pixclock > f32.t * plen)
1073             return -EINVAL;
1074         pclock = &f32;
1075         if (yres > 240)
1076             interlace = 1;
1077         if (var->pixclock == 0) {
1078             /* set some minimal margins which center the screen */
1079             left_margin = 32;
1080             right_margin = 18;
1081             hsync_len = pclock->hsync / plen;
1082             upper_margin = 31;
1083             lower_margin = 14;
1084             vsync_len = interlace ? 3 : 4;
1085         } else {
1086             left_margin = var->left_margin;
1087             right_margin = var->right_margin;
1088             hsync_len = var->hsync_len;
1089             upper_margin = var->upper_margin;
1090             lower_margin = var->lower_margin;
1091             vsync_len = var->vsync_len;
1092             if (var->vmode & FB_VMODE_INTERLACED) {
1093                 upper_margin = (upper_margin + 1) / 2;
1094                 lower_margin = (lower_margin + 1) / 2;
1095                 vsync_len = (vsync_len + 1) / 2;
1096             } else if (var->vmode & FB_VMODE_DOUBLE) {
1097                 upper_margin *= 2;
1098                 lower_margin *= 2;
1099                 vsync_len *= 2;
1100             }
1101         }
1102     } else {            /* F_MON_VGA */
1103         if (bpp == 16)
1104             xstretch = 2;   /* Double pixel width only for hicolor */
1105         /* Default values are used for vert./hor. timing if no pixelclock given. */
1106         if (var->pixclock == 0) {
1107             int linesize;
1108 
1109             /* Choose master pixelclock depending on hor. timing */
1110             plen = 1 * xstretch;
1111             if ((plen * xres + f25.right + f25.hsync + f25.left) *
1112                 fb_info.monspecs.hfmin < f25.f)
1113                 pclock = &f25;
1114             else if ((plen * xres + f32.right + f32.hsync +
1115                   f32.left) * fb_info.monspecs.hfmin < f32.f)
1116                 pclock = &f32;
1117             else if ((plen * xres + fext.right + fext.hsync +
1118                   fext.left) * fb_info.monspecs.hfmin < fext.f &&
1119                      fext.f)
1120                 pclock = &fext;
1121             else
1122                 return -EINVAL;
1123 
1124             left_margin = pclock->left / plen;
1125             right_margin = pclock->right / plen;
1126             hsync_len = pclock->hsync / plen;
1127             linesize = left_margin + xres + right_margin + hsync_len;
1128             upper_margin = 31;
1129             lower_margin = 11;
1130             vsync_len = 3;
1131         } else {
1132             /* Choose largest pixelclock <= wanted clock */
1133             int i;
1134             unsigned long pcl = ULONG_MAX;
1135             pclock = 0;
1136             for (i = 1; i <= 4; i *= 2) {
1137                 if (f25.t * i >= var->pixclock &&
1138                     f25.t * i < pcl) {
1139                     pcl = f25.t * i;
1140                     pclock = &f25;
1141                 }
1142                 if (f32.t * i >= var->pixclock &&
1143                     f32.t * i < pcl) {
1144                     pcl = f32.t * i;
1145                     pclock = &f32;
1146                 }
1147                 if (fext.t && fext.t * i >= var->pixclock &&
1148                     fext.t * i < pcl) {
1149                     pcl = fext.t * i;
1150                     pclock = &fext;
1151                 }
1152             }
1153             if (!pclock)
1154                 return -EINVAL;
1155             plen = pcl / pclock->t;
1156 
1157             left_margin = var->left_margin;
1158             right_margin = var->right_margin;
1159             hsync_len = var->hsync_len;
1160             upper_margin = var->upper_margin;
1161             lower_margin = var->lower_margin;
1162             vsync_len = var->vsync_len;
1163             /* Internal unit is [single lines per (half-)frame] */
1164             if (var->vmode & FB_VMODE_INTERLACED) {
1165                 /* # lines in half frame */
1166                 /* External unit is [lines per full frame] */
1167                 upper_margin = (upper_margin + 1) / 2;
1168                 lower_margin = (lower_margin + 1) / 2;
1169                 vsync_len = (vsync_len + 1) / 2;
1170             } else if (var->vmode & FB_VMODE_DOUBLE) {
1171                 /* External unit is [double lines per frame] */
1172                 upper_margin *= 2;
1173                 lower_margin *= 2;
1174                 vsync_len *= 2;
1175             }
1176         }
1177         if (pclock == &fext)
1178             longoffset = 1; /* VIDEL doesn't synchronize on short offset */
1179     }
1180     /* Is video bus bandwidth (32MB/s) too low for this resolution? */
1181     /* this is definitely wrong if bus clock != 32MHz */
1182     if (pclock->f / plen / 8 * bpp > 32000000L)
1183         return -EINVAL;
1184 
1185     if (vsync_len < 1)
1186         vsync_len = 1;
1187 
1188     /* include sync lengths in right/lower margin for all calculations */
1189     right_margin += hsync_len;
1190     lower_margin += vsync_len;
1191 
1192     /* ! In all calculations of margins we use # of lines in half frame
1193      * (which is a full frame in non-interlace mode), so we can switch
1194      * between interlace and non-interlace without messing around
1195      * with these.
1196      */
1197 again:
1198     /* Set base_offset 128 and video bus width */
1199     par->hw.falcon.vid_control = mon_type | f030_bus_width;
1200     if (!longoffset)
1201         par->hw.falcon.vid_control |= VCO_SHORTOFFS;    /* base_offset 64 */
1202     if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1203         par->hw.falcon.vid_control |= VCO_HSYPOS;
1204     if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1205         par->hw.falcon.vid_control |= VCO_VSYPOS;
1206     /* Pixelclock */
1207     par->hw.falcon.vid_control |= pclock->control_mask;
1208     /* External or internal clock */
1209     par->hw.falcon.sync = pclock->sync_mask | 0x2;
1210     /* Pixellength and prescale */
1211     par->hw.falcon.vid_mode = (2 / plen) << 2;
1212     if (doubleline)
1213         par->hw.falcon.vid_mode |= VMO_DOUBLE;
1214     if (interlace)
1215         par->hw.falcon.vid_mode |= VMO_INTER;
1216 
1217     /*********************
1218      * Horizontal timing: unit = [master clock cycles]
1219      * unit of hxx-registers: [master clock cycles * prescale]
1220      * Hxx-registers are 9 bit wide
1221      *
1222      * 1 line = ((hht + 2) * 2 * prescale) clock cycles
1223      *
1224      * graphic output = hdb & 0x200 ?
1225      *        ((hht + 2) * 2 - hdb + hde) * prescale - hdboff + hdeoff:
1226      *        (hht + 2  - hdb + hde) * prescale - hdboff + hdeoff
1227      * (this must be a multiple of plen*128/bpp, on VGA pixels
1228      *  to the right may be cut off with a bigger right margin)
1229      *
1230      * start of graphics relative to start of 1st halfline = hdb & 0x200 ?
1231      *        (hdb - hht - 2) * prescale + hdboff :
1232      *        hdb * prescale + hdboff
1233      *
1234      * end of graphics relative to start of 1st halfline =
1235      *        (hde + hht + 2) * prescale + hdeoff
1236      *********************/
1237     /* Calculate VIDEL registers */
1238 {
1239     prescale = hxx_prescale(&par->hw.falcon);
1240     base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128;
1241 
1242     /* Offsets depend on video mode */
1243     /* Offsets are in clock cycles, divide by prescale to
1244      * calculate hd[be]-registers
1245      */
1246     if (par->hw.falcon.f_shift & 0x100) {
1247         align = 1;
1248         hde_off = 0;
1249         hdb_off = (base_off + 16 * plen) + prescale;
1250     } else {
1251         align = 128 / bpp;
1252         hde_off = ((128 / bpp + 2) * plen);
1253         if (par->hw.falcon.ste_mode)
1254             hdb_off = (64 + base_off + (128 / bpp + 2) * plen) + prescale;
1255         else
1256             hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale;
1257     }
1258 
1259     gstart = (prescale / 2 + plen * left_margin) / prescale;
1260     /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
1261     gend1 = gstart + roundup(xres, align) * plen / prescale;
1262     /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
1263     gend2 = gstart + xres * plen / prescale;
1264     par->HHT = plen * (left_margin + xres + right_margin) /
1265                (2 * prescale) - 2;
1266 /*  par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
1267 
1268     par->HDB = gstart - hdb_off / prescale;
1269     par->HBE = gstart;
1270     if (par->HDB < 0)
1271         par->HDB += par->HHT + 2 + 0x200;
1272     par->HDE = gend1 - par->HHT - 2 - hde_off / prescale;
1273     par->HBB = gend2 - par->HHT - 2;
1274 #if 0
1275     /* One more Videl constraint: data fetch of two lines must not overlap */
1276     if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) {
1277         /* if this happens increase margins, decrease hfreq. */
1278     }
1279 #endif
1280     if (hde_off % prescale)
1281         par->HBB++;     /* compensate for non matching hde and hbb */
1282     par->HSS = par->HHT + 2 - plen * hsync_len / prescale;
1283     if (par->HSS < par->HBB)
1284         par->HSS = par->HBB;
1285 }
1286 
1287     /*  check hor. frequency */
1288     hfreq = pclock->f / ((par->HHT + 2) * prescale * 2);
1289     if (hfreq > fb_info.monspecs.hfmax && mon_type != F_MON_VGA) {
1290         /* ++guenther:   ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
1291         /* Too high -> enlarge margin */
1292         left_margin += 1;
1293         right_margin += 1;
1294         goto again;
1295     }
1296     if (hfreq > fb_info.monspecs.hfmax || hfreq < fb_info.monspecs.hfmin)
1297         return -EINVAL;
1298 
1299     /* Vxx-registers */
1300     /* All Vxx must be odd in non-interlace, since frame starts in the middle
1301      * of the first displayed line!
1302      * One frame consists of VFT+1 half lines. VFT+1 must be even in
1303      * non-interlace, odd in interlace mode for synchronisation.
1304      * Vxx-registers are 11 bit wide
1305      */
1306     par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */
1307     par->VDB = par->VBE;
1308     par->VDE = yres;
1309     if (!interlace)
1310         par->VDE <<= 1;
1311     if (doubleline)
1312         par->VDE <<= 1;     /* VDE now half lines per (half-)frame */
1313     par->VDE += par->VDB;
1314     par->VBB = par->VDE;
1315     par->VFT = par->VBB + (lower_margin * 2 - 1) - 1;
1316     par->VSS = par->VFT + 1 - (vsync_len * 2 - 1);
1317     /* vbb,vss,vft must be even in interlace mode */
1318     if (interlace) {
1319         par->VBB++;
1320         par->VSS++;
1321         par->VFT++;
1322     }
1323 
1324     /* V-frequency check, hope I didn't create any loop here. */
1325     /* Interlace and doubleline are mutually exclusive. */
1326     vfreq = (hfreq * 2) / (par->VFT + 1);
1327     if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
1328         /* Too high -> try again with doubleline */
1329         doubleline = 1;
1330         goto again;
1331     } else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
1332         /* Too low -> try again with interlace */
1333         interlace = 1;
1334         goto again;
1335     } else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
1336         /* Doubleline too low -> clear doubleline and enlarge margins */
1337         int lines;
1338         doubleline = 0;
1339         for (lines = 0;
1340              (hfreq * 2) / (par->VFT + 1 + 4 * lines - 2 * yres) >
1341              fb_info.monspecs.vfmax;
1342              lines++)
1343             ;
1344         upper_margin += lines;
1345         lower_margin += lines;
1346         goto again;
1347     } else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
1348         /* Doubleline too high -> enlarge margins */
1349         int lines;
1350         for (lines = 0;
1351              (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
1352              fb_info.monspecs.vfmax;
1353              lines += 2)
1354             ;
1355         upper_margin += lines;
1356         lower_margin += lines;
1357         goto again;
1358     } else if (vfreq > fb_info.monspecs.vfmax && interlace) {
1359         /* Interlace, too high -> enlarge margins */
1360         int lines;
1361         for (lines = 0;
1362              (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
1363              fb_info.monspecs.vfmax;
1364              lines++)
1365             ;
1366         upper_margin += lines;
1367         lower_margin += lines;
1368         goto again;
1369     } else if (vfreq < fb_info.monspecs.vfmin ||
1370            vfreq > fb_info.monspecs.vfmax)
1371         return -EINVAL;
1372 
1373 set_screen_base:
1374     linelen = xres_virtual * bpp / 8;
1375     if (yres_virtual * linelen > screen_len && screen_len)
1376         return -EINVAL;
1377     if (yres * linelen > screen_len && screen_len)
1378         return -EINVAL;
1379     if (var->yoffset + yres > yres_virtual && yres_virtual)
1380         return -EINVAL;
1381     par->yres_virtual = yres_virtual;
1382     par->screen_base = screen_base + var->yoffset * linelen;
1383     par->hw.falcon.xoffset = 0;
1384 
1385     par->next_line = linelen;
1386 
1387     return 0;
1388 }
1389 
1390 static int falcon_encode_var(struct fb_var_screeninfo *var,
1391                  struct atafb_par *par)
1392 {
1393 /* !!! only for VGA !!! */
1394     int linelen;
1395     int prescale, plen;
1396     int hdb_off, hde_off, base_off;
1397     struct falcon_hw *hw = &par->hw.falcon;
1398 
1399     memset(var, 0, sizeof(struct fb_var_screeninfo));
1400     /* possible frequencies: 25.175 or 32MHz */
1401     var->pixclock = hw->sync & 0x1 ? fext.t :
1402                     hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t;
1403 
1404     var->height = -1;
1405     var->width = -1;
1406 
1407     var->sync = 0;
1408     if (hw->vid_control & VCO_HSYPOS)
1409         var->sync |= FB_SYNC_HOR_HIGH_ACT;
1410     if (hw->vid_control & VCO_VSYPOS)
1411         var->sync |= FB_SYNC_VERT_HIGH_ACT;
1412 
1413     var->vmode = FB_VMODE_NONINTERLACED;
1414     if (hw->vid_mode & VMO_INTER)
1415         var->vmode |= FB_VMODE_INTERLACED;
1416     if (hw->vid_mode & VMO_DOUBLE)
1417         var->vmode |= FB_VMODE_DOUBLE;
1418 
1419     /* visible y resolution:
1420      * Graphics display starts at line VDB and ends at line
1421      * VDE. If interlace mode off unit of VC-registers is
1422      * half lines, else lines.
1423      */
1424     var->yres = hw->vde - hw->vdb;
1425     if (!(var->vmode & FB_VMODE_INTERLACED))
1426         var->yres >>= 1;
1427     if (var->vmode & FB_VMODE_DOUBLE)
1428         var->yres >>= 1;
1429 
1430     /*
1431      * to get bpp, we must examine f_shift and st_shift.
1432      * f_shift is valid if any of bits no. 10, 8 or 4
1433      * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
1434      * if bit 10 set then bit 8 and bit 4 don't care...
1435      * If all these bits are 0 get display depth from st_shift
1436      * (as for ST and STE)
1437      */
1438     if (hw->f_shift & 0x400)    /* 2 colors */
1439         var->bits_per_pixel = 1;
1440     else if (hw->f_shift & 0x100)   /* hicolor */
1441         var->bits_per_pixel = 16;
1442     else if (hw->f_shift & 0x010)   /* 8 bitplanes */
1443         var->bits_per_pixel = 8;
1444     else if (hw->st_shift == 0)
1445         var->bits_per_pixel = 4;
1446     else if (hw->st_shift == 0x100)
1447         var->bits_per_pixel = 2;
1448     else                /* if (hw->st_shift == 0x200) */
1449         var->bits_per_pixel = 1;
1450 
1451     var->xres = hw->line_width * 16 / var->bits_per_pixel;
1452     var->xres_virtual = var->xres + hw->line_offset * 16 / var->bits_per_pixel;
1453     if (hw->xoffset)
1454         var->xres_virtual += 16;
1455 
1456     if (var->bits_per_pixel == 16) {
1457         var->red.offset = 11;
1458         var->red.length = 5;
1459         var->red.msb_right = 0;
1460         var->green.offset = 5;
1461         var->green.length = 6;
1462         var->green.msb_right = 0;
1463         var->blue.offset = 0;
1464         var->blue.length = 5;
1465         var->blue.msb_right = 0;
1466     } else {
1467         var->red.offset = 0;
1468         var->red.length = hw->ste_mode ? 4 : 6;
1469         if (var->red.length > var->bits_per_pixel)
1470             var->red.length = var->bits_per_pixel;
1471         var->red.msb_right = 0;
1472         var->grayscale = 0;
1473         var->blue = var->green = var->red;
1474     }
1475     var->transp.offset = 0;
1476     var->transp.length = 0;
1477     var->transp.msb_right = 0;
1478 
1479     linelen = var->xres_virtual * var->bits_per_pixel / 8;
1480     if (screen_len) {
1481         if (par->yres_virtual)
1482             var->yres_virtual = par->yres_virtual;
1483         else
1484             /* yres_virtual == 0 means use maximum */
1485             var->yres_virtual = screen_len / linelen;
1486     } else {
1487         if (hwscroll < 0)
1488             var->yres_virtual = 2 * var->yres;
1489         else
1490             var->yres_virtual = var->yres + hwscroll * 16;
1491     }
1492     var->xoffset = 0;       /* TODO change this */
1493 
1494     /* hdX-offsets */
1495     prescale = hxx_prescale(hw);
1496     plen = 4 >> (hw->vid_mode >> 2 & 0x3);
1497     base_off = hw->vid_control & VCO_SHORTOFFS ? 64 : 128;
1498     if (hw->f_shift & 0x100) {
1499         hde_off = 0;
1500         hdb_off = (base_off + 16 * plen) + prescale;
1501     } else {
1502         hde_off = ((128 / var->bits_per_pixel + 2) * plen);
1503         if (hw->ste_mode)
1504             hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)
1505                      + prescale;
1506         else
1507             hdb_off = (base_off + (128 / var->bits_per_pixel + 18) * plen)
1508                      + prescale;
1509     }
1510 
1511     /* Right margin includes hsync */
1512     var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) -
1513                        (hw->hdb & 0x200 ? 2 + hw->hht : 0));
1514     if (hw->ste_mode || mon_type != F_MON_VGA)
1515         var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off;
1516     else
1517         /* can't use this in ste_mode, because hbb is +1 off */
1518         var->right_margin = prescale * (hw->hht + 2 - hw->hbb);
1519     var->hsync_len = prescale * (hw->hht + 2 - hw->hss);
1520 
1521     /* Lower margin includes vsync */
1522     var->upper_margin = hw->vdb / 2;    /* round down to full lines */
1523     var->lower_margin = (hw->vft + 1 - hw->vde + 1) / 2;    /* round up */
1524     var->vsync_len = (hw->vft + 1 - hw->vss + 1) / 2;   /* round up */
1525     if (var->vmode & FB_VMODE_INTERLACED) {
1526         var->upper_margin *= 2;
1527         var->lower_margin *= 2;
1528         var->vsync_len *= 2;
1529     } else if (var->vmode & FB_VMODE_DOUBLE) {
1530         var->upper_margin = (var->upper_margin + 1) / 2;
1531         var->lower_margin = (var->lower_margin + 1) / 2;
1532         var->vsync_len = (var->vsync_len + 1) / 2;
1533     }
1534 
1535     var->pixclock *= plen;
1536     var->left_margin /= plen;
1537     var->right_margin /= plen;
1538     var->hsync_len /= plen;
1539 
1540     var->right_margin -= var->hsync_len;
1541     var->lower_margin -= var->vsync_len;
1542 
1543     if (screen_base)
1544         var->yoffset = (par->screen_base - screen_base) / linelen;
1545     else
1546         var->yoffset = 0;
1547     var->nonstd = 0;        /* what is this for? */
1548     var->activate = 0;
1549     return 0;
1550 }
1551 
1552 static int f_change_mode;
1553 static struct falcon_hw f_new_mode;
1554 static int f_pan_display;
1555 
1556 static void falcon_get_par(struct atafb_par *par)
1557 {
1558     unsigned long addr;
1559     struct falcon_hw *hw = &par->hw.falcon;
1560 
1561     hw->line_width = shifter_f030.scn_width;
1562     hw->line_offset = shifter_f030.off_next;
1563     hw->st_shift = videl.st_shift & 0x300;
1564     hw->f_shift = videl.f_shift;
1565     hw->vid_control = videl.control;
1566     hw->vid_mode = videl.mode;
1567     hw->sync = shifter.syncmode & 0x1;
1568     hw->xoffset = videl.xoffset & 0xf;
1569     hw->hht = videl.hht;
1570     hw->hbb = videl.hbb;
1571     hw->hbe = videl.hbe;
1572     hw->hdb = videl.hdb;
1573     hw->hde = videl.hde;
1574     hw->hss = videl.hss;
1575     hw->vft = videl.vft;
1576     hw->vbb = videl.vbb;
1577     hw->vbe = videl.vbe;
1578     hw->vdb = videl.vdb;
1579     hw->vde = videl.vde;
1580     hw->vss = videl.vss;
1581 
1582     addr = (shifter.bas_hi & 0xff) << 16 |
1583            (shifter.bas_md & 0xff) << 8  |
1584            (shifter.bas_lo & 0xff);
1585     par->screen_base = atari_stram_to_virt(addr);
1586 
1587     /* derived parameters */
1588     hw->ste_mode = (hw->f_shift & 0x510) == 0 && hw->st_shift == 0x100;
1589     hw->mono = (hw->f_shift & 0x400) ||
1590                ((hw->f_shift & 0x510) == 0 && hw->st_shift == 0x200);
1591 }
1592 
1593 static void falcon_set_par(struct atafb_par *par)
1594 {
1595     f_change_mode = 0;
1596 
1597     /* only set screen_base if really necessary */
1598     if (current_par.screen_base != par->screen_base)
1599         fbhw->set_screen_base(par->screen_base);
1600 
1601     /* Don't touch any other registers if we keep the default resolution */
1602     if (DontCalcRes)
1603         return;
1604 
1605     /* Tell vbl-handler to change video mode.
1606      * We change modes only on next VBL, to avoid desynchronisation
1607      * (a shift to the right and wrap around by a random number of pixels
1608      * in all monochrome modes).
1609      * This seems to work on my Falcon.
1610      */
1611     f_new_mode = par->hw.falcon;
1612     f_change_mode = 1;
1613 }
1614 
1615 static irqreturn_t falcon_vbl_switcher(int irq, void *dummy)
1616 {
1617     struct falcon_hw *hw = &f_new_mode;
1618 
1619     if (f_change_mode) {
1620         f_change_mode = 0;
1621 
1622         if (hw->sync & 0x1) {
1623             /* Enable external pixelclock. This code only for ScreenWonder */
1624             *(volatile unsigned short *)0xffff9202 = 0xffbf;
1625         } else {
1626             /* Turn off external clocks. Read sets all output bits to 1. */
1627             *(volatile unsigned short *)0xffff9202;
1628         }
1629         shifter.syncmode = hw->sync;
1630 
1631         videl.hht = hw->hht;
1632         videl.hbb = hw->hbb;
1633         videl.hbe = hw->hbe;
1634         videl.hdb = hw->hdb;
1635         videl.hde = hw->hde;
1636         videl.hss = hw->hss;
1637         videl.vft = hw->vft;
1638         videl.vbb = hw->vbb;
1639         videl.vbe = hw->vbe;
1640         videl.vdb = hw->vdb;
1641         videl.vde = hw->vde;
1642         videl.vss = hw->vss;
1643 
1644         videl.f_shift = 0;  /* write enables Falcon palette, 0: 4 planes */
1645         if (hw->ste_mode) {
1646             videl.st_shift = hw->st_shift;  /* write enables STE palette */
1647         } else {
1648             /* IMPORTANT:
1649              * set st_shift 0, so we can tell the screen-depth if f_shift == 0.
1650              * Writing 0 to f_shift enables 4 plane Falcon mode but
1651              * doesn't set st_shift. st_shift != 0 (!= 4planes) is impossible
1652              * with Falcon palette.
1653              */
1654             videl.st_shift = 0;
1655             /* now back to Falcon palette mode */
1656             videl.f_shift = hw->f_shift;
1657         }
1658         /* writing to st_shift changed scn_width and vid_mode */
1659         videl.xoffset = hw->xoffset;
1660         shifter_f030.scn_width = hw->line_width;
1661         shifter_f030.off_next = hw->line_offset;
1662         videl.control = hw->vid_control;
1663         videl.mode = hw->vid_mode;
1664     }
1665     if (f_pan_display) {
1666         f_pan_display = 0;
1667         videl.xoffset = current_par.hw.falcon.xoffset;
1668         shifter_f030.off_next = current_par.hw.falcon.line_offset;
1669     }
1670     return IRQ_HANDLED;
1671 }
1672 
1673 static int falcon_pan_display(struct fb_var_screeninfo *var,
1674                   struct fb_info *info)
1675 {
1676     struct atafb_par *par = (struct atafb_par *)info->par;
1677 
1678     int xoffset;
1679     int bpp = info->var.bits_per_pixel;
1680 
1681     if (bpp == 1)
1682         var->xoffset = up(var->xoffset, 32);
1683     if (bpp != 16)
1684         par->hw.falcon.xoffset = var->xoffset & 15;
1685     else {
1686         par->hw.falcon.xoffset = 0;
1687         var->xoffset = up(var->xoffset, 2);
1688     }
1689     par->hw.falcon.line_offset = bpp *
1690         (info->var.xres_virtual - info->var.xres) / 16;
1691     if (par->hw.falcon.xoffset)
1692         par->hw.falcon.line_offset -= bpp;
1693     xoffset = var->xoffset - par->hw.falcon.xoffset;
1694 
1695     par->screen_base = screen_base +
1696             (var->yoffset * info->var.xres_virtual + xoffset) * bpp / 8;
1697     if (fbhw->set_screen_base)
1698         fbhw->set_screen_base(par->screen_base);
1699     else
1700         return -EINVAL;     /* shouldn't happen */
1701     f_pan_display = 1;
1702     return 0;
1703 }
1704 
1705 static int falcon_setcolreg(unsigned int regno, unsigned int red,
1706                 unsigned int green, unsigned int blue,
1707                 unsigned int transp, struct fb_info *info)
1708 {
1709     if (regno > 255)
1710         return 1;
1711     f030_col[regno] = (((red & 0xfc00) << 16) |
1712                ((green & 0xfc00) << 8) |
1713                ((blue & 0xfc00) >> 8));
1714     if (regno < 16) {
1715         shifter_tt.color_reg[regno] =
1716             (((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
1717             (((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
1718             ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
1719         ((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) |
1720                                ((green & 0xfc00) >> 5) |
1721                                ((blue & 0xf800) >> 11));
1722     }
1723     return 0;
1724 }
1725 
1726 static int falcon_blank(int blank_mode)
1727 {
1728     /* ++guenther: we can switch off graphics by changing VDB and VDE,
1729      * so VIDEL doesn't hog the bus while saving.
1730      * (this may affect usleep()).
1731      */
1732     int vdb, vss, hbe, hss;
1733 
1734     if (mon_type == F_MON_SM)   /* this doesn't work on SM124 */
1735         return 1;
1736 
1737     vdb = current_par.VDB;
1738     vss = current_par.VSS;
1739     hbe = current_par.HBE;
1740     hss = current_par.HSS;
1741 
1742     if (blank_mode >= 1) {
1743         /* disable graphics output (this speeds up the CPU) ... */
1744         vdb = current_par.VFT + 1;
1745         /* ... and blank all lines */
1746         hbe = current_par.HHT + 2;
1747     }
1748     /* use VESA suspend modes on VGA monitors */
1749     if (mon_type == F_MON_VGA) {
1750         if (blank_mode == 2 || blank_mode == 4)
1751             vss = current_par.VFT + 1;
1752         if (blank_mode == 3 || blank_mode == 4)
1753             hss = current_par.HHT + 2;
1754     }
1755 
1756     videl.vdb = vdb;
1757     videl.vss = vss;
1758     videl.hbe = hbe;
1759     videl.hss = hss;
1760 
1761     return 0;
1762 }
1763 
1764 static int falcon_detect(void)
1765 {
1766     struct atafb_par par;
1767     unsigned char fhw;
1768 
1769     /* Determine connected monitor and set monitor parameters */
1770     fhw = *(unsigned char *)0xffff8006;
1771     mon_type = fhw >> 6 & 0x3;
1772     /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
1773     f030_bus_width = fhw << 6 & 0x80;
1774     switch (mon_type) {
1775     case F_MON_SM:
1776         fb_info.monspecs.vfmin = 70;
1777         fb_info.monspecs.vfmax = 72;
1778         fb_info.monspecs.hfmin = 35713;
1779         fb_info.monspecs.hfmax = 35715;
1780         break;
1781     case F_MON_SC:
1782     case F_MON_TV:
1783         /* PAL...NTSC */
1784         fb_info.monspecs.vfmin = 49;    /* not 50, since TOS defaults to 49.9x Hz */
1785         fb_info.monspecs.vfmax = 60;
1786         fb_info.monspecs.hfmin = 15620;
1787         fb_info.monspecs.hfmax = 15755;
1788         break;
1789     }
1790     /* initialize hsync-len */
1791     f25.hsync = h_syncs[mon_type] / f25.t;
1792     f32.hsync = h_syncs[mon_type] / f32.t;
1793     if (fext.t)
1794         fext.hsync = h_syncs[mon_type] / fext.t;
1795 
1796     falcon_get_par(&par);
1797     falcon_encode_var(&atafb_predefined[0], &par);
1798 
1799     /* Detected mode is always the "autodetect" slot */
1800     return 1;
1801 }
1802 
1803 #endif /* ATAFB_FALCON */
1804 
1805 /* ------------------- ST(E) specific functions ---------------------- */
1806 
1807 #ifdef ATAFB_STE
1808 
1809 static int stste_encode_fix(struct fb_fix_screeninfo *fix,
1810                 struct atafb_par *par)
1811 {
1812     int mode;
1813 
1814     strcpy(fix->id, "Atari Builtin");
1815     fix->smem_start = phys_screen_base;
1816     fix->smem_len = screen_len;
1817     fix->type = FB_TYPE_INTERLEAVED_PLANES;
1818     fix->type_aux = 2;
1819     fix->visual = FB_VISUAL_PSEUDOCOLOR;
1820     mode = par->hw.st.mode & 3;
1821     if (mode == ST_HIGH) {
1822         fix->type = FB_TYPE_PACKED_PIXELS;
1823         fix->type_aux = 0;
1824         fix->visual = FB_VISUAL_MONO10;
1825     }
1826     if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
1827         fix->xpanstep = 16;
1828         fix->ypanstep = 1;
1829     } else {
1830         fix->xpanstep = 0;
1831         fix->ypanstep = 0;
1832     }
1833     fix->ywrapstep = 0;
1834     fix->line_length = par->next_line;
1835     fix->accel = FB_ACCEL_ATARIBLITT;
1836     return 0;
1837 }
1838 
1839 static int stste_decode_var(struct fb_var_screeninfo *var,
1840                 struct atafb_par *par)
1841 {
1842     int xres = var->xres;
1843     int yres = var->yres;
1844     int bpp = var->bits_per_pixel;
1845     int linelen;
1846     int yres_virtual = var->yres_virtual;
1847 
1848     if (mono_moni) {
1849         if (bpp > 1 || xres > sttt_xres || yres > st_yres)
1850             return -EINVAL;
1851         par->hw.st.mode = ST_HIGH;
1852         xres = sttt_xres;
1853         yres = st_yres;
1854         bpp = 1;
1855     } else {
1856         if (bpp > 4 || xres > sttt_xres || yres > st_yres)
1857             return -EINVAL;
1858         if (bpp > 2) {
1859             if (xres > sttt_xres / 2 || yres > st_yres / 2)
1860                 return -EINVAL;
1861             par->hw.st.mode = ST_LOW;
1862             xres = sttt_xres / 2;
1863             yres = st_yres / 2;
1864             bpp = 4;
1865         } else if (bpp > 1) {
1866             if (xres > sttt_xres || yres > st_yres / 2)
1867                 return -EINVAL;
1868             par->hw.st.mode = ST_MID;
1869             xres = sttt_xres;
1870             yres = st_yres / 2;
1871             bpp = 2;
1872         } else
1873             return -EINVAL;
1874     }
1875     if (yres_virtual <= 0)
1876         yres_virtual = 0;
1877     else if (yres_virtual < yres)
1878         yres_virtual = yres;
1879     if (var->sync & FB_SYNC_EXT)
1880         par->hw.st.sync = (par->hw.st.sync & ~1) | 1;
1881     else
1882         par->hw.st.sync = (par->hw.st.sync & ~1);
1883     linelen = xres * bpp / 8;
1884     if (yres_virtual * linelen > screen_len && screen_len)
1885         return -EINVAL;
1886     if (yres * linelen > screen_len && screen_len)
1887         return -EINVAL;
1888     if (var->yoffset + yres > yres_virtual && yres_virtual)
1889         return -EINVAL;
1890     par->yres_virtual = yres_virtual;
1891     par->screen_base = screen_base + var->yoffset * linelen;
1892     par->next_line = linelen;
1893     return 0;
1894 }
1895 
1896 static int stste_encode_var(struct fb_var_screeninfo *var,
1897                 struct atafb_par *par)
1898 {
1899     int linelen;
1900     memset(var, 0, sizeof(struct fb_var_screeninfo));
1901     var->red.offset = 0;
1902     var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
1903     var->red.msb_right = 0;
1904     var->grayscale = 0;
1905 
1906     var->pixclock = 31041;
1907     var->left_margin = 120;     /* these are incorrect */
1908     var->right_margin = 100;
1909     var->upper_margin = 8;
1910     var->lower_margin = 16;
1911     var->hsync_len = 140;
1912     var->vsync_len = 30;
1913 
1914     var->height = -1;
1915     var->width = -1;
1916 
1917     if (!(par->hw.st.sync & 1))
1918         var->sync = 0;
1919     else
1920         var->sync = FB_SYNC_EXT;
1921 
1922     switch (par->hw.st.mode & 3) {
1923     case ST_LOW:
1924         var->xres = sttt_xres / 2;
1925         var->yres = st_yres / 2;
1926         var->bits_per_pixel = 4;
1927         break;
1928     case ST_MID:
1929         var->xres = sttt_xres;
1930         var->yres = st_yres / 2;
1931         var->bits_per_pixel = 2;
1932         break;
1933     case ST_HIGH:
1934         var->xres = sttt_xres;
1935         var->yres = st_yres;
1936         var->bits_per_pixel = 1;
1937         break;
1938     }
1939     var->blue = var->green = var->red;
1940     var->transp.offset = 0;
1941     var->transp.length = 0;
1942     var->transp.msb_right = 0;
1943     var->xres_virtual = sttt_xres_virtual;
1944     linelen = var->xres_virtual * var->bits_per_pixel / 8;
1945     ovsc_addlen = linelen * (sttt_yres_virtual - st_yres);
1946 
1947     if (!use_hwscroll)
1948         var->yres_virtual = var->yres;
1949     else if (screen_len) {
1950         if (par->yres_virtual)
1951             var->yres_virtual = par->yres_virtual;
1952         else
1953             /* yres_virtual == 0 means use maximum */
1954             var->yres_virtual = screen_len / linelen;
1955     } else {
1956         if (hwscroll < 0)
1957             var->yres_virtual = 2 * var->yres;
1958         else
1959             var->yres_virtual = var->yres + hwscroll * 16;
1960     }
1961     var->xoffset = 0;
1962     if (screen_base)
1963         var->yoffset = (par->screen_base - screen_base) / linelen;
1964     else
1965         var->yoffset = 0;
1966     var->nonstd = 0;
1967     var->activate = 0;
1968     var->vmode = FB_VMODE_NONINTERLACED;
1969     return 0;
1970 }
1971 
1972 static void stste_get_par(struct atafb_par *par)
1973 {
1974     unsigned long addr;
1975     par->hw.st.mode = shifter_tt.st_shiftmode;
1976     par->hw.st.sync = shifter.syncmode;
1977     addr = ((shifter.bas_hi & 0xff) << 16) |
1978            ((shifter.bas_md & 0xff) << 8);
1979     if (ATARIHW_PRESENT(EXTD_SHIFTER))
1980         addr |= (shifter.bas_lo & 0xff);
1981     par->screen_base = atari_stram_to_virt(addr);
1982 }
1983 
1984 static void stste_set_par(struct atafb_par *par)
1985 {
1986     shifter_tt.st_shiftmode = par->hw.st.mode;
1987     shifter.syncmode = par->hw.st.sync;
1988     /* only set screen_base if really necessary */
1989     if (current_par.screen_base != par->screen_base)
1990         fbhw->set_screen_base(par->screen_base);
1991 }
1992 
1993 static int stste_setcolreg(unsigned int regno, unsigned int red,
1994                unsigned int green, unsigned int blue,
1995                unsigned int transp, struct fb_info *info)
1996 {
1997     if (regno > 15)
1998         return 1;
1999     red >>= 12;
2000     blue >>= 12;
2001     green >>= 12;
2002     if (ATARIHW_PRESENT(EXTD_SHIFTER))
2003         shifter_tt.color_reg[regno] =
2004             (((red & 0xe) >> 1) | ((red & 1) << 3) << 8) |
2005             (((green & 0xe) >> 1) | ((green & 1) << 3) << 4) |
2006             ((blue & 0xe) >> 1) | ((blue & 1) << 3);
2007     else
2008         shifter_tt.color_reg[regno] =
2009             ((red & 0xe) << 7) |
2010             ((green & 0xe) << 3) |
2011             ((blue & 0xe) >> 1);
2012     return 0;
2013 }
2014 
2015 static int stste_detect(void)
2016 {
2017     struct atafb_par par;
2018 
2019     /* Determine the connected monitor: The DMA sound must be
2020      * disabled before reading the MFP GPIP, because the Sound
2021      * Done Signal and the Monochrome Detect are XORed together!
2022      */
2023     if (ATARIHW_PRESENT(PCM_8BIT)) {
2024         tt_dmasnd.ctrl = DMASND_CTRL_OFF;
2025         udelay(20);     /* wait a while for things to settle down */
2026     }
2027     mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
2028 
2029     stste_get_par(&par);
2030     stste_encode_var(&atafb_predefined[0], &par);
2031 
2032     if (!ATARIHW_PRESENT(EXTD_SHIFTER))
2033         use_hwscroll = 0;
2034     return 1;
2035 }
2036 
2037 static void stste_set_screen_base(void *s_base)
2038 {
2039     unsigned long addr;
2040     addr = atari_stram_to_phys(s_base);
2041     /* Setup Screen Memory */
2042     shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
2043     shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
2044     if (ATARIHW_PRESENT(EXTD_SHIFTER))
2045         shifter.bas_lo = (unsigned char)(addr & 0x0000ff);
2046 }
2047 
2048 #endif /* ATAFB_STE */
2049 
2050 /* Switching the screen size should be done during vsync, otherwise
2051  * the margins may get messed up. This is a well known problem of
2052  * the ST's video system.
2053  *
2054  * Unfortunately there is hardly any way to find the vsync, as the
2055  * vertical blank interrupt is no longer in time on machines with
2056  * overscan type modifications.
2057  *
2058  * We can, however, use Timer B to safely detect the black shoulder,
2059  * but then we've got to guess an appropriate delay to find the vsync.
2060  * This might not work on every machine.
2061  *
2062  * martin_rogge @ ki.maus.de, 8th Aug 1995
2063  */
2064 
2065 #define LINE_DELAY  (mono_moni ? 30 : 70)
2066 #define SYNC_DELAY  (mono_moni ? 1500 : 2000)
2067 
2068 /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
2069 static void st_ovsc_switch(void)
2070 {
2071     unsigned long flags;
2072     register unsigned char old, new;
2073 
2074     if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
2075         return;
2076     local_irq_save(flags);
2077 
2078     st_mfp.tim_ct_b = 0x10;
2079     st_mfp.active_edge |= 8;
2080     st_mfp.tim_ct_b = 0;
2081     st_mfp.tim_dt_b = 0xf0;
2082     st_mfp.tim_ct_b = 8;
2083     while (st_mfp.tim_dt_b > 1) /* TOS does it this way, don't ask why */
2084         ;
2085     new = st_mfp.tim_dt_b;
2086     do {
2087         udelay(LINE_DELAY);
2088         old = new;
2089         new = st_mfp.tim_dt_b;
2090     } while (old != new);
2091     st_mfp.tim_ct_b = 0x10;
2092     udelay(SYNC_DELAY);
2093 
2094     if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
2095         acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
2096     if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
2097         acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
2098     if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
2099         sound_ym.rd_data_reg_sel = 14;
2100         sound_ym.wd_data = sound_ym.rd_data_reg_sel |
2101                    ((atari_switches & ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
2102                    ((atari_switches & ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
2103     }
2104     local_irq_restore(flags);
2105 }
2106 
2107 /* ------------------- External Video ---------------------- */
2108 
2109 #ifdef ATAFB_EXT
2110 
2111 static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
2112 {
2113     strcpy(fix->id, "Unknown Extern");
2114     fix->smem_start = external_addr;
2115     fix->smem_len = PAGE_ALIGN(external_len);
2116     if (external_depth == 1) {
2117         fix->type = FB_TYPE_PACKED_PIXELS;
2118         /* The letters 'n' and 'i' in the "atavideo=external:" stand
2119          * for "normal" and "inverted", rsp., in the monochrome case */
2120         fix->visual =
2121             (external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
2122              external_pmode == FB_TYPE_PACKED_PIXELS) ?
2123                 FB_VISUAL_MONO10 : FB_VISUAL_MONO01;
2124     } else {
2125         /* Use STATIC if we don't know how to access color registers */
2126         int visual = external_vgaiobase ?
2127                      FB_VISUAL_PSEUDOCOLOR :
2128                      FB_VISUAL_STATIC_PSEUDOCOLOR;
2129         switch (external_pmode) {
2130         case -1:        /* truecolor */
2131             fix->type = FB_TYPE_PACKED_PIXELS;
2132             fix->visual = FB_VISUAL_TRUECOLOR;
2133             break;
2134         case FB_TYPE_PACKED_PIXELS:
2135             fix->type = FB_TYPE_PACKED_PIXELS;
2136             fix->visual = visual;
2137             break;
2138         case FB_TYPE_PLANES:
2139             fix->type = FB_TYPE_PLANES;
2140             fix->visual = visual;
2141             break;
2142         case FB_TYPE_INTERLEAVED_PLANES:
2143             fix->type = FB_TYPE_INTERLEAVED_PLANES;
2144             fix->type_aux = 2;
2145             fix->visual = visual;
2146             break;
2147         }
2148     }
2149     fix->xpanstep = 0;
2150     fix->ypanstep = 0;
2151     fix->ywrapstep = 0;
2152     fix->line_length = par->next_line;
2153     return 0;
2154 }
2155 
2156 static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
2157 {
2158     struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2159 
2160     if (var->bits_per_pixel > myvar->bits_per_pixel ||
2161         var->xres > myvar->xres ||
2162         var->xres_virtual > myvar->xres_virtual ||
2163         var->yres > myvar->yres ||
2164         var->xoffset > 0 ||
2165         var->yoffset > 0)
2166         return -EINVAL;
2167 
2168     par->next_line = external_xres_virtual * external_depth / 8;
2169     return 0;
2170 }
2171 
2172 static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
2173 {
2174     memset(var, 0, sizeof(struct fb_var_screeninfo));
2175     var->red.offset = 0;
2176     var->red.length = (external_pmode == -1) ? external_depth / 3 :
2177             (external_vgaiobase ? external_bitspercol : 0);
2178     var->red.msb_right = 0;
2179     var->grayscale = 0;
2180 
2181     var->pixclock = 31041;
2182     var->left_margin = 120;     /* these are surely incorrect */
2183     var->right_margin = 100;
2184     var->upper_margin = 8;
2185     var->lower_margin = 16;
2186     var->hsync_len = 140;
2187     var->vsync_len = 30;
2188 
2189     var->height = -1;
2190     var->width = -1;
2191 
2192     var->sync = 0;
2193 
2194     var->xres = external_xres;
2195     var->yres = external_yres;
2196     var->xres_virtual = external_xres_virtual;
2197     var->bits_per_pixel = external_depth;
2198 
2199     var->blue = var->green = var->red;
2200     var->transp.offset = 0;
2201     var->transp.length = 0;
2202     var->transp.msb_right = 0;
2203     var->yres_virtual = var->yres;
2204     var->xoffset = 0;
2205     var->yoffset = 0;
2206     var->nonstd = 0;
2207     var->activate = 0;
2208     var->vmode = FB_VMODE_NONINTERLACED;
2209     return 0;
2210 }
2211 
2212 static void ext_get_par(struct atafb_par *par)
2213 {
2214     par->screen_base = external_screen_base;
2215 }
2216 
2217 static void ext_set_par(struct atafb_par *par)
2218 {
2219 }
2220 
2221 #define OUTB(port,val) \
2222     *((unsigned volatile char *) ((port)+external_vgaiobase)) = (val)
2223 #define INB(port) \
2224     (*((unsigned volatile char *) ((port)+external_vgaiobase)))
2225 #define DACDelay                \
2226     do {                    \
2227         unsigned char tmp = INB(0x3da); \
2228         tmp = INB(0x3da);           \
2229     } while (0)
2230 
2231 static int ext_setcolreg(unsigned int regno, unsigned int red,
2232              unsigned int green, unsigned int blue,
2233              unsigned int transp, struct fb_info *info)
2234 {
2235     unsigned char colmask = (1 << external_bitspercol) - 1;
2236 
2237     if (!external_vgaiobase)
2238         return 1;
2239 
2240     if (regno > 255)
2241         return 1;
2242 
2243     switch (external_card_type) {
2244     case IS_VGA:
2245         OUTB(0x3c8, regno);
2246         DACDelay;
2247         OUTB(0x3c9, red & colmask);
2248         DACDelay;
2249         OUTB(0x3c9, green & colmask);
2250         DACDelay;
2251         OUTB(0x3c9, blue & colmask);
2252         DACDelay;
2253         return 0;
2254 
2255     case IS_MV300:
2256         OUTB((MV300_reg[regno] << 2) + 1, red);
2257         OUTB((MV300_reg[regno] << 2) + 1, green);
2258         OUTB((MV300_reg[regno] << 2) + 1, blue);
2259         return 0;
2260 
2261     default:
2262         return 1;
2263     }
2264 }
2265 
2266 static int ext_detect(void)
2267 {
2268     struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2269     struct atafb_par dummy_par;
2270 
2271     myvar->xres = external_xres;
2272     myvar->xres_virtual = external_xres_virtual;
2273     myvar->yres = external_yres;
2274     myvar->bits_per_pixel = external_depth;
2275     ext_encode_var(myvar, &dummy_par);
2276     return 1;
2277 }
2278 
2279 #endif /* ATAFB_EXT */
2280 
2281 /* ------ This is the same for most hardware types -------- */
2282 
2283 static void set_screen_base(void *s_base)
2284 {
2285     unsigned long addr;
2286 
2287     addr = atari_stram_to_phys(s_base);
2288     /* Setup Screen Memory */
2289     shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
2290     shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
2291     shifter.bas_lo = (unsigned char)(addr & 0x0000ff);
2292 }
2293 
2294 static int pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
2295 {
2296     struct atafb_par *par = (struct atafb_par *)info->par;
2297 
2298     if (!fbhw->set_screen_base ||
2299         (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
2300         return -EINVAL;
2301     var->xoffset = up(var->xoffset, 16);
2302     par->screen_base = screen_base +
2303             (var->yoffset * info->var.xres_virtual + var->xoffset)
2304             * info->var.bits_per_pixel / 8;
2305     fbhw->set_screen_base(par->screen_base);
2306     return 0;
2307 }
2308 
2309 /* ------------ Interfaces to hardware functions ------------ */
2310 
2311 #ifdef ATAFB_TT
2312 static struct fb_hwswitch tt_switch = {
2313     .detect     = tt_detect,
2314     .encode_fix = tt_encode_fix,
2315     .decode_var = tt_decode_var,
2316     .encode_var = tt_encode_var,
2317     .get_par    = tt_get_par,
2318     .set_par    = tt_set_par,
2319     .set_screen_base = set_screen_base,
2320     .pan_display    = pan_display,
2321 };
2322 #endif
2323 
2324 #ifdef ATAFB_FALCON
2325 static struct fb_hwswitch falcon_switch = {
2326     .detect     = falcon_detect,
2327     .encode_fix = falcon_encode_fix,
2328     .decode_var = falcon_decode_var,
2329     .encode_var = falcon_encode_var,
2330     .get_par    = falcon_get_par,
2331     .set_par    = falcon_set_par,
2332     .set_screen_base = set_screen_base,
2333     .blank      = falcon_blank,
2334     .pan_display    = falcon_pan_display,
2335 };
2336 #endif
2337 
2338 #ifdef ATAFB_STE
2339 static struct fb_hwswitch st_switch = {
2340     .detect     = stste_detect,
2341     .encode_fix = stste_encode_fix,
2342     .decode_var = stste_decode_var,
2343     .encode_var = stste_encode_var,
2344     .get_par    = stste_get_par,
2345     .set_par    = stste_set_par,
2346     .set_screen_base = stste_set_screen_base,
2347     .pan_display    = pan_display
2348 };
2349 #endif
2350 
2351 #ifdef ATAFB_EXT
2352 static struct fb_hwswitch ext_switch = {
2353     .detect     = ext_detect,
2354     .encode_fix = ext_encode_fix,
2355     .decode_var = ext_decode_var,
2356     .encode_var = ext_encode_var,
2357     .get_par    = ext_get_par,
2358     .set_par    = ext_set_par,
2359 };
2360 #endif
2361 
2362 static void ata_get_par(struct atafb_par *par)
2363 {
2364     if (current_par_valid)
2365         *par = current_par;
2366     else
2367         fbhw->get_par(par);
2368 }
2369 
2370 static void ata_set_par(struct atafb_par *par)
2371 {
2372     fbhw->set_par(par);
2373     current_par = *par;
2374     current_par_valid = 1;
2375 }
2376 
2377 
2378 /* =========================================================== */
2379 /* ============== Hardware Independent Functions ============= */
2380 /* =========================================================== */
2381 
2382 /* used for hardware scrolling */
2383 
2384 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
2385 {
2386     int err, activate;
2387     struct atafb_par par;
2388 
2389     err = fbhw->decode_var(var, &par);
2390     if (err)
2391         return err;
2392     activate = var->activate;
2393     if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
2394         ata_set_par(&par);
2395     fbhw->encode_var(var, &par);
2396     var->activate = activate;
2397     return 0;
2398 }
2399 
2400 /* fbhw->encode_fix() must be called with fb_info->mm_lock held
2401  * if it is called after the register_framebuffer() - not a case here
2402  */
2403 static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
2404 {
2405     struct atafb_par par;
2406     int err;
2407     // Get fix directly (case con == -1 before)??
2408     err = fbhw->decode_var(&info->var, &par);
2409     if (err)
2410         return err;
2411     memset(fix, 0, sizeof(struct fb_fix_screeninfo));
2412     err = fbhw->encode_fix(fix, &par);
2413     return err;
2414 }
2415 
2416 static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info)
2417 {
2418     struct atafb_par par;
2419 
2420     ata_get_par(&par);
2421     fbhw->encode_var(var, &par);
2422 
2423     return 0;
2424 }
2425 
2426 // No longer called by fbcon!
2427 // Still called by set_var internally
2428 
2429 static void atafb_set_disp(struct fb_info *info)
2430 {
2431     atafb_get_var(&info->var, info);
2432     atafb_get_fix(&info->fix, info);
2433 
2434     /* Note: smem_start derives from phys_screen_base, not screen_base! */
2435     info->screen_base = (external_addr ? external_screen_base :
2436                 atari_stram_to_virt(info->fix.smem_start));
2437 }
2438 
2439 static int atafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
2440                u_int transp, struct fb_info *info)
2441 {
2442     red >>= 8;
2443     green >>= 8;
2444     blue >>= 8;
2445 
2446     return info->fbops->fb_setcolreg(regno, red, green, blue, transp, info);
2447 }
2448 
2449 static int
2450 atafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
2451 {
2452     int xoffset = var->xoffset;
2453     int yoffset = var->yoffset;
2454     int err;
2455 
2456     if (var->vmode & FB_VMODE_YWRAP) {
2457         if (yoffset < 0 || yoffset >= info->var.yres_virtual || xoffset)
2458             return -EINVAL;
2459     } else {
2460         if (xoffset + info->var.xres > info->var.xres_virtual ||
2461             yoffset + info->var.yres > info->var.yres_virtual)
2462             return -EINVAL;
2463     }
2464 
2465     if (fbhw->pan_display) {
2466         err = fbhw->pan_display(var, info);
2467         if (err)
2468             return err;
2469     } else
2470         return -EINVAL;
2471 
2472     info->var.xoffset = xoffset;
2473     info->var.yoffset = yoffset;
2474 
2475     if (var->vmode & FB_VMODE_YWRAP)
2476         info->var.vmode |= FB_VMODE_YWRAP;
2477     else
2478         info->var.vmode &= ~FB_VMODE_YWRAP;
2479 
2480     return 0;
2481 }
2482 
2483 /*
2484  * generic drawing routines; imageblit needs updating for image depth > 1
2485  */
2486 
2487 #if BITS_PER_LONG == 32
2488 #define BYTES_PER_LONG  4
2489 #define SHIFT_PER_LONG  5
2490 #elif BITS_PER_LONG == 64
2491 #define BYTES_PER_LONG  8
2492 #define SHIFT_PER_LONG  6
2493 #else
2494 #define Please update me
2495 #endif
2496 
2497 
2498 static void atafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
2499 {
2500     struct atafb_par *par = (struct atafb_par *)info->par;
2501     int x2, y2;
2502     u32 width, height;
2503 
2504     if (!rect->width || !rect->height)
2505         return;
2506 
2507 #ifdef ATAFB_FALCON
2508     if (info->var.bits_per_pixel == 16) {
2509         cfb_fillrect(info, rect);
2510         return;
2511     }
2512 #endif
2513 
2514     /*
2515      * We could use hardware clipping but on many cards you get around
2516      * hardware clipping by writing to framebuffer directly.
2517      * */
2518     x2 = rect->dx + rect->width;
2519     y2 = rect->dy + rect->height;
2520     x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2521     y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2522     width = x2 - rect->dx;
2523     height = y2 - rect->dy;
2524 
2525     if (info->var.bits_per_pixel == 1)
2526         atafb_mfb_fillrect(info, par->next_line, rect->color,
2527                    rect->dy, rect->dx, height, width);
2528     else if (info->var.bits_per_pixel == 2)
2529         atafb_iplan2p2_fillrect(info, par->next_line, rect->color,
2530                     rect->dy, rect->dx, height, width);
2531     else if (info->var.bits_per_pixel == 4)
2532         atafb_iplan2p4_fillrect(info, par->next_line, rect->color,
2533                     rect->dy, rect->dx, height, width);
2534     else
2535         atafb_iplan2p8_fillrect(info, par->next_line, rect->color,
2536                     rect->dy, rect->dx, height, width);
2537 
2538     return;
2539 }
2540 
2541 static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
2542 {
2543     struct atafb_par *par = (struct atafb_par *)info->par;
2544     int x2, y2;
2545     u32 dx, dy, sx, sy, width, height;
2546     int rev_copy = 0;
2547 
2548 #ifdef ATAFB_FALCON
2549     if (info->var.bits_per_pixel == 16) {
2550         cfb_copyarea(info, area);
2551         return;
2552     }
2553 #endif
2554 
2555     /* clip the destination */
2556     x2 = area->dx + area->width;
2557     y2 = area->dy + area->height;
2558     dx = area->dx > 0 ? area->dx : 0;
2559     dy = area->dy > 0 ? area->dy : 0;
2560     x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2561     y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2562     width = x2 - dx;
2563     height = y2 - dy;
2564 
2565     if (area->sx + dx < area->dx || area->sy + dy < area->dy)
2566         return;
2567 
2568     /* update sx,sy */
2569     sx = area->sx + (dx - area->dx);
2570     sy = area->sy + (dy - area->dy);
2571 
2572     /* the source must be completely inside the virtual screen */
2573     if (sx + width > info->var.xres_virtual ||
2574             sy + height > info->var.yres_virtual)
2575         return;
2576 
2577     if (dy > sy || (dy == sy && dx > sx)) {
2578         dy += height;
2579         sy += height;
2580         rev_copy = 1;
2581     }
2582 
2583     if (info->var.bits_per_pixel == 1)
2584         atafb_mfb_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2585     else if (info->var.bits_per_pixel == 2)
2586         atafb_iplan2p2_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2587     else if (info->var.bits_per_pixel == 4)
2588         atafb_iplan2p4_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2589     else
2590         atafb_iplan2p8_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2591 
2592     return;
2593 }
2594 
2595 static void atafb_imageblit(struct fb_info *info, const struct fb_image *image)
2596 {
2597     struct atafb_par *par = (struct atafb_par *)info->par;
2598     int x2, y2;
2599     unsigned long *dst;
2600     int dst_idx;
2601     const char *src;
2602     u32 dx, dy, width, height, pitch;
2603 
2604 #ifdef ATAFB_FALCON
2605     if (info->var.bits_per_pixel == 16) {
2606         cfb_imageblit(info, image);
2607         return;
2608     }
2609 #endif
2610 
2611     /*
2612      * We could use hardware clipping but on many cards you get around
2613      * hardware clipping by writing to framebuffer directly like we are
2614      * doing here.
2615      */
2616     x2 = image->dx + image->width;
2617     y2 = image->dy + image->height;
2618     dx = image->dx;
2619     dy = image->dy;
2620     x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2621     y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2622     width = x2 - dx;
2623     height = y2 - dy;
2624 
2625     if (image->depth == 1) {
2626         // used for font data
2627         dst = (unsigned long *)
2628             ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
2629         dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
2630         dst_idx += dy * par->next_line * 8 + dx;
2631         src = image->data;
2632         pitch = (image->width + 7) / 8;
2633         while (height--) {
2634 
2635             if (info->var.bits_per_pixel == 1)
2636                 atafb_mfb_linefill(info, par->next_line,
2637                            dy, dx, width, src,
2638                            image->bg_color, image->fg_color);
2639             else if (info->var.bits_per_pixel == 2)
2640                 atafb_iplan2p2_linefill(info, par->next_line,
2641                             dy, dx, width, src,
2642                             image->bg_color, image->fg_color);
2643             else if (info->var.bits_per_pixel == 4)
2644                 atafb_iplan2p4_linefill(info, par->next_line,
2645                             dy, dx, width, src,
2646                             image->bg_color, image->fg_color);
2647             else
2648                 atafb_iplan2p8_linefill(info, par->next_line,
2649                             dy, dx, width, src,
2650                             image->bg_color, image->fg_color);
2651             dy++;
2652             src += pitch;
2653         }
2654     } else {
2655         c2p_iplan2(info->screen_base, image->data, dx, dy, width,
2656                height, par->next_line, image->width,
2657                info->var.bits_per_pixel);
2658     }
2659 }
2660 
2661 static int
2662 atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
2663 {
2664     switch (cmd) {
2665 #ifdef FBCMD_GET_CURRENTPAR
2666     case FBCMD_GET_CURRENTPAR:
2667         if (copy_to_user((void *)arg, (void *)&current_par,
2668                  sizeof(struct atafb_par)))
2669             return -EFAULT;
2670         return 0;
2671 #endif
2672 #ifdef FBCMD_SET_CURRENTPAR
2673     case FBCMD_SET_CURRENTPAR:
2674         if (copy_from_user((void *)&current_par, (void *)arg,
2675                    sizeof(struct atafb_par)))
2676             return -EFAULT;
2677         ata_set_par(&current_par);
2678         return 0;
2679 #endif
2680     }
2681     return -EINVAL;
2682 }
2683 
2684 /* (un)blank/poweroff
2685  * 0 = unblank
2686  * 1 = blank
2687  * 2 = suspend vsync
2688  * 3 = suspend hsync
2689  * 4 = off
2690  */
2691 static int atafb_blank(int blank, struct fb_info *info)
2692 {
2693     unsigned short black[16];
2694     struct fb_cmap cmap;
2695     if (fbhw->blank && !fbhw->blank(blank))
2696         return 1;
2697     if (blank) {
2698         memset(black, 0, 16 * sizeof(unsigned short));
2699         cmap.red = black;
2700         cmap.green = black;
2701         cmap.blue = black;
2702         cmap.transp = NULL;
2703         cmap.start = 0;
2704         cmap.len = 16;
2705         fb_set_cmap(&cmap, info);
2706     }
2707 #if 0
2708     else
2709         do_install_cmap(info);
2710 #endif
2711     return 0;
2712 }
2713 
2714     /*
2715      * New fbcon interface ...
2716      */
2717 
2718      /* check var by decoding var into hw par, rounding if necessary,
2719       * then encoding hw par back into new, validated var */
2720 static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
2721 {
2722     int err;
2723     struct atafb_par par;
2724 
2725     /* Validate wanted screen parameters */
2726     // if ((err = ata_decode_var(var, &par)))
2727     err = fbhw->decode_var(var, &par);
2728     if (err)
2729         return err;
2730 
2731     /* Encode (possibly rounded) screen parameters */
2732     fbhw->encode_var(var, &par);
2733     return 0;
2734 }
2735 
2736     /* actually set hw par by decoding var, then setting hardware from
2737      * hw par just decoded */
2738 static int atafb_set_par(struct fb_info *info)
2739 {
2740     struct atafb_par *par = (struct atafb_par *)info->par;
2741 
2742     /* Decode wanted screen parameters */
2743     fbhw->decode_var(&info->var, par);
2744     mutex_lock(&info->mm_lock);
2745     fbhw->encode_fix(&info->fix, par);
2746     mutex_unlock(&info->mm_lock);
2747 
2748     /* Set new videomode */
2749     ata_set_par(par);
2750 
2751     return 0;
2752 }
2753 
2754 
2755 static struct fb_ops atafb_ops = {
2756     .owner =    THIS_MODULE,
2757     .fb_check_var   = atafb_check_var,
2758     .fb_set_par = atafb_set_par,
2759     .fb_setcolreg   = atafb_setcolreg,
2760     .fb_blank = atafb_blank,
2761     .fb_pan_display = atafb_pan_display,
2762     .fb_fillrect    = atafb_fillrect,
2763     .fb_copyarea    = atafb_copyarea,
2764     .fb_imageblit   = atafb_imageblit,
2765     .fb_ioctl = atafb_ioctl,
2766 };
2767 
2768 static void check_default_par(int detected_mode)
2769 {
2770     char default_name[10];
2771     int i;
2772     struct fb_var_screeninfo var;
2773     unsigned long min_mem;
2774 
2775     /* First try the user supplied mode */
2776     if (default_par) {
2777         var = atafb_predefined[default_par - 1];
2778         var.activate = FB_ACTIVATE_TEST;
2779         if (do_fb_set_var(&var, 1))
2780             default_par = 0;    /* failed */
2781     }
2782     /* Next is the autodetected one */
2783     if (!default_par) {
2784         var = atafb_predefined[detected_mode - 1]; /* autodetect */
2785         var.activate = FB_ACTIVATE_TEST;
2786         if (!do_fb_set_var(&var, 1))
2787             default_par = detected_mode;
2788     }
2789     /* If that also failed, try some default modes... */
2790     if (!default_par) {
2791         /* try default1, default2... */
2792         for (i = 1; i < 10; i++) {
2793             sprintf(default_name,"default%d", i);
2794             default_par = get_video_mode(default_name);
2795             if (!default_par)
2796                 panic("can't set default video mode");
2797             var = atafb_predefined[default_par - 1];
2798             var.activate = FB_ACTIVATE_TEST;
2799             if (!do_fb_set_var(&var,1))
2800                 break;  /* ok */
2801         }
2802     }
2803     min_mem = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8;
2804     if (default_mem_req < min_mem)
2805         default_mem_req = min_mem;
2806 }
2807 
2808 #ifdef ATAFB_EXT
2809 static void __init atafb_setup_ext(char *spec)
2810 {
2811     int xres, xres_virtual, yres, depth, planes;
2812     unsigned long addr, len;
2813     char *p;
2814 
2815     /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
2816      *            <screen mem addr>
2817      *        [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
2818      *        [;<xres-virtual>]]]]]
2819      *
2820      * 09/23/97 Juergen
2821      * <xres_virtual>:  hardware's x-resolution (f.e. ProMST)
2822      *
2823      * Even xres_virtual is available, we neither support panning nor hw-scrolling!
2824      */
2825     p = strsep(&spec, ";");
2826     if (!p || !*p)
2827         return;
2828     xres_virtual = xres = simple_strtoul(p, NULL, 10);
2829     if (xres <= 0)
2830         return;
2831 
2832     p = strsep(&spec, ";");
2833     if (!p || !*p)
2834         return;
2835     yres = simple_strtoul(p, NULL, 10);
2836     if (yres <= 0)
2837         return;
2838 
2839     p = strsep(&spec, ";");
2840     if (!p || !*p)
2841         return;
2842     depth = simple_strtoul(p, NULL, 10);
2843     if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
2844         depth != 16 && depth != 24)
2845         return;
2846 
2847     p = strsep(&spec, ";");
2848     if (!p || !*p)
2849         return;
2850     if (*p == 'i')
2851         planes = FB_TYPE_INTERLEAVED_PLANES;
2852     else if (*p == 'p')
2853         planes = FB_TYPE_PACKED_PIXELS;
2854     else if (*p == 'n')
2855         planes = FB_TYPE_PLANES;
2856     else if (*p == 't')
2857         planes = -1;        /* true color */
2858     else
2859         return;
2860 
2861     p = strsep(&spec, ";");
2862     if (!p || !*p)
2863         return;
2864     addr = simple_strtoul(p, NULL, 0);
2865 
2866     p = strsep(&spec, ";");
2867     if (!p || !*p)
2868         len = xres * yres * depth / 8;
2869     else
2870         len = simple_strtoul(p, NULL, 0);
2871 
2872     p = strsep(&spec, ";");
2873     if (p && *p)
2874         external_vgaiobase = simple_strtoul(p, NULL, 0);
2875 
2876     p = strsep(&spec, ";");
2877     if (p && *p) {
2878         external_bitspercol = simple_strtoul(p, NULL, 0);
2879         if (external_bitspercol > 8)
2880             external_bitspercol = 8;
2881         else if (external_bitspercol < 1)
2882             external_bitspercol = 1;
2883     }
2884 
2885     p = strsep(&spec, ";");
2886     if (p && *p) {
2887         if (!strcmp(p, "vga"))
2888             external_card_type = IS_VGA;
2889         if (!strcmp(p, "mv300"))
2890             external_card_type = IS_MV300;
2891     }
2892 
2893     p = strsep(&spec, ";");
2894     if (p && *p) {
2895         xres_virtual = simple_strtoul(p, NULL, 10);
2896         if (xres_virtual < xres)
2897             xres_virtual = xres;
2898         if (xres_virtual * yres * depth / 8 > len)
2899             len = xres_virtual * yres * depth / 8;
2900     }
2901 
2902     external_xres = xres;
2903     external_xres_virtual = xres_virtual;
2904     external_yres = yres;
2905     external_depth = depth;
2906     external_pmode = planes;
2907     external_addr = addr;
2908     external_len = len;
2909 
2910     if (external_card_type == IS_MV300) {
2911         switch (external_depth) {
2912         case 1:
2913             MV300_reg = MV300_reg_1bit;
2914             break;
2915         case 4:
2916             MV300_reg = MV300_reg_4bit;
2917             break;
2918         case 8:
2919             MV300_reg = MV300_reg_8bit;
2920             break;
2921         }
2922     }
2923 }
2924 #endif /* ATAFB_EXT */
2925 
2926 static void __init atafb_setup_int(char *spec)
2927 {
2928     /* Format to config extended internal video hardware like OverScan:
2929      * "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
2930      * Explanation:
2931      * <xres>: x-resolution
2932      * <yres>: y-resolution
2933      * The following are only needed if you have an overscan which
2934      * needs a black border:
2935      * <xres_max>: max. length of a line in pixels your OverScan hardware would allow
2936      * <yres_max>: max. number of lines your OverScan hardware would allow
2937      * <offset>: Offset from physical beginning to visible beginning
2938      *    of screen in bytes
2939      */
2940     int xres;
2941     char *p;
2942 
2943     if (!(p = strsep(&spec, ";")) || !*p)
2944         return;
2945     xres = simple_strtoul(p, NULL, 10);
2946     if (!(p = strsep(&spec, ";")) || !*p)
2947         return;
2948     sttt_xres = xres;
2949     tt_yres = st_yres = simple_strtoul(p, NULL, 10);
2950     if ((p = strsep(&spec, ";")) && *p)
2951         sttt_xres_virtual = simple_strtoul(p, NULL, 10);
2952     if ((p = strsep(&spec, ";")) && *p)
2953         sttt_yres_virtual = simple_strtoul(p, NULL, 0);
2954     if ((p = strsep(&spec, ";")) && *p)
2955         ovsc_offset = simple_strtoul(p, NULL, 0);
2956 
2957     if (ovsc_offset || (sttt_yres_virtual != st_yres))
2958         use_hwscroll = 0;
2959 }
2960 
2961 #ifdef ATAFB_FALCON
2962 static void __init atafb_setup_mcap(char *spec)
2963 {
2964     char *p;
2965     int vmin, vmax, hmin, hmax;
2966 
2967     /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
2968      * <V*> vertical freq. in Hz
2969      * <H*> horizontal freq. in kHz
2970      */
2971     if (!(p = strsep(&spec, ";")) || !*p)
2972         return;
2973     vmin = simple_strtoul(p, NULL, 10);
2974     if (vmin <= 0)
2975         return;
2976     if (!(p = strsep(&spec, ";")) || !*p)
2977         return;
2978     vmax = simple_strtoul(p, NULL, 10);
2979     if (vmax <= 0 || vmax <= vmin)
2980         return;
2981     if (!(p = strsep(&spec, ";")) || !*p)
2982         return;
2983     hmin = 1000 * simple_strtoul(p, NULL, 10);
2984     if (hmin <= 0)
2985         return;
2986     if (!(p = strsep(&spec, "")) || !*p)
2987         return;
2988     hmax = 1000 * simple_strtoul(p, NULL, 10);
2989     if (hmax <= 0 || hmax <= hmin)
2990         return;
2991 
2992     fb_info.monspecs.vfmin = vmin;
2993     fb_info.monspecs.vfmax = vmax;
2994     fb_info.monspecs.hfmin = hmin;
2995     fb_info.monspecs.hfmax = hmax;
2996 }
2997 #endif /* ATAFB_FALCON */
2998 
2999 static void __init atafb_setup_user(char *spec)
3000 {
3001     /* Format of user defined video mode is: <xres>;<yres>;<depth>
3002      */
3003     char *p;
3004     int xres, yres, depth, temp;
3005 
3006     p = strsep(&spec, ";");
3007     if (!p || !*p)
3008         return;
3009     xres = simple_strtoul(p, NULL, 10);
3010     p = strsep(&spec, ";");
3011     if (!p || !*p)
3012         return;
3013     yres = simple_strtoul(p, NULL, 10);
3014     p = strsep(&spec, "");
3015     if (!p || !*p)
3016         return;
3017     depth = simple_strtoul(p, NULL, 10);
3018     temp = get_video_mode("user0");
3019     if (temp) {
3020         default_par = temp;
3021         atafb_predefined[default_par - 1].xres = xres;
3022         atafb_predefined[default_par - 1].yres = yres;
3023         atafb_predefined[default_par - 1].bits_per_pixel = depth;
3024     }
3025 }
3026 
3027 int __init atafb_setup(char *options)
3028 {
3029     char *this_opt;
3030     int temp;
3031 
3032     if (!options || !*options)
3033         return 0;
3034 
3035     while ((this_opt = strsep(&options, ",")) != NULL) {
3036         if (!*this_opt)
3037             continue;
3038         if ((temp = get_video_mode(this_opt))) {
3039             default_par = temp;
3040             mode_option = this_opt;
3041         } else if (!strcmp(this_opt, "inverse"))
3042             inverse = 1;
3043         else if (!strncmp(this_opt, "hwscroll_", 9)) {
3044             hwscroll = simple_strtoul(this_opt + 9, NULL, 10);
3045             if (hwscroll < 0)
3046                 hwscroll = 0;
3047             if (hwscroll > 200)
3048                 hwscroll = 200;
3049         }
3050 #ifdef ATAFB_EXT
3051         else if (!strcmp(this_opt, "mv300")) {
3052             external_bitspercol = 8;
3053             external_card_type = IS_MV300;
3054         } else if (!strncmp(this_opt, "external:", 9))
3055             atafb_setup_ext(this_opt + 9);
3056 #endif
3057         else if (!strncmp(this_opt, "internal:", 9))
3058             atafb_setup_int(this_opt + 9);
3059 #ifdef ATAFB_FALCON
3060         else if (!strncmp(this_opt, "eclock:", 7)) {
3061             fext.f = simple_strtoul(this_opt + 7, NULL, 10);
3062             /* external pixelclock in kHz --> ps */
3063             fext.t = 1000000000 / fext.f;
3064             fext.f *= 1000;
3065         } else if (!strncmp(this_opt, "monitorcap:", 11))
3066             atafb_setup_mcap(this_opt + 11);
3067 #endif
3068         else if (!strcmp(this_opt, "keep"))
3069             DontCalcRes = 1;
3070         else if (!strncmp(this_opt, "R", 1))
3071             atafb_setup_user(this_opt + 1);
3072     }
3073     return 0;
3074 }
3075 
3076 int __init atafb_init(void)
3077 {
3078     int pad, detected_mode, error;
3079     unsigned int defmode = 0;
3080     unsigned long mem_req;
3081 
3082 #ifndef MODULE
3083     char *option = NULL;
3084 
3085     if (fb_get_options("atafb", &option))
3086         return -ENODEV;
3087     atafb_setup(option);
3088 #endif
3089     printk("atafb_init: start\n");
3090 
3091     if (!MACH_IS_ATARI)
3092         return -ENODEV;
3093 
3094     do {
3095 #ifdef ATAFB_EXT
3096         if (external_addr) {
3097             printk("atafb_init: initializing external hw\n");
3098             fbhw = &ext_switch;
3099             atafb_ops.fb_setcolreg = &ext_setcolreg;
3100             defmode = DEFMODE_EXT;
3101             break;
3102         }
3103 #endif
3104 #ifdef ATAFB_TT
3105         if (ATARIHW_PRESENT(TT_SHIFTER)) {
3106             printk("atafb_init: initializing TT hw\n");
3107             fbhw = &tt_switch;
3108             atafb_ops.fb_setcolreg = &tt_setcolreg;
3109             defmode = DEFMODE_TT;
3110             break;
3111         }
3112 #endif
3113 #ifdef ATAFB_FALCON
3114         if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
3115             printk("atafb_init: initializing Falcon hw\n");
3116             fbhw = &falcon_switch;
3117             atafb_ops.fb_setcolreg = &falcon_setcolreg;
3118             error = request_irq(IRQ_AUTO_4, falcon_vbl_switcher, 0,
3119                         "framebuffer:modeswitch",
3120                         falcon_vbl_switcher);
3121             if (error)
3122                 return error;
3123             defmode = DEFMODE_F30;
3124             break;
3125         }
3126 #endif
3127 #ifdef ATAFB_STE
3128         if (ATARIHW_PRESENT(STND_SHIFTER) ||
3129             ATARIHW_PRESENT(EXTD_SHIFTER)) {
3130             printk("atafb_init: initializing ST/E hw\n");
3131             fbhw = &st_switch;
3132             atafb_ops.fb_setcolreg = &stste_setcolreg;
3133             defmode = DEFMODE_STE;
3134             break;
3135         }
3136         fbhw = &st_switch;
3137         atafb_ops.fb_setcolreg = &stste_setcolreg;
3138         printk("Cannot determine video hardware; defaulting to ST(e)\n");
3139 #else /* ATAFB_STE */
3140         /* no default driver included */
3141         /* Nobody will ever see this message :-) */
3142         panic("Cannot initialize video hardware");
3143 #endif
3144     } while (0);
3145 
3146     /* Multisync monitor capabilities */
3147     /* Atari-TOS defaults if no boot option present */
3148     if (fb_info.monspecs.hfmin == 0) {
3149         fb_info.monspecs.hfmin = 31000;
3150         fb_info.monspecs.hfmax = 32000;
3151         fb_info.monspecs.vfmin = 58;
3152         fb_info.monspecs.vfmax = 62;
3153     }
3154 
3155     detected_mode = fbhw->detect();
3156     check_default_par(detected_mode);
3157 #ifdef ATAFB_EXT
3158     if (!external_addr) {
3159 #endif /* ATAFB_EXT */
3160         mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
3161         mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
3162         screen_base = atari_stram_alloc(mem_req, "atafb");
3163         if (!screen_base)
3164             panic("Cannot allocate screen memory");
3165         memset(screen_base, 0, mem_req);
3166         pad = -(unsigned long)screen_base & (PAGE_SIZE - 1);
3167         screen_base += pad;
3168         phys_screen_base = atari_stram_to_phys(screen_base + ovsc_offset);
3169         screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
3170         st_ovsc_switch();
3171         if (CPU_IS_040_OR_060) {
3172             /* On a '040+, the cache mode of video RAM must be set to
3173              * write-through also for internal video hardware! */
3174             cache_push(atari_stram_to_phys(screen_base), screen_len);
3175             kernel_set_cachemode(screen_base, screen_len,
3176                          IOMAP_WRITETHROUGH);
3177         }
3178         printk("atafb: screen_base %p phys_screen_base %lx screen_len %d\n",
3179             screen_base, phys_screen_base, screen_len);
3180 #ifdef ATAFB_EXT
3181     } else {
3182         /* Map the video memory (physical address given) to somewhere
3183          * in the kernel address space.
3184          */
3185         external_screen_base = ioremap_wt(external_addr, external_len);
3186         if (external_vgaiobase)
3187             external_vgaiobase =
3188               (unsigned long)ioremap(external_vgaiobase, 0x10000);
3189         screen_base = external_screen_base;
3190         phys_screen_base = external_addr;
3191         screen_len = external_len & PAGE_MASK;
3192         memset (screen_base, 0, external_len);
3193     }
3194 #endif /* ATAFB_EXT */
3195 
3196 //  strcpy(fb_info.mode->name, "Atari Builtin ");
3197     fb_info.fbops = &atafb_ops;
3198     // try to set default (detected; requested) var
3199     do_fb_set_var(&atafb_predefined[default_par - 1], 1);
3200     // reads hw state into current par, which may not be sane yet
3201     ata_get_par(&current_par);
3202     fb_info.par = &current_par;
3203     // tries to read from HW which may not be initialized yet
3204     // so set sane var first, then call atafb_set_par
3205     atafb_get_var(&fb_info.var, &fb_info);
3206 
3207 #ifdef ATAFB_FALCON
3208     fb_info.pseudo_palette = current_par.hw.falcon.pseudo_palette;
3209 #endif
3210     fb_info.flags = FBINFO_FLAG_DEFAULT;
3211 
3212     if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb,
3213               NUM_TOTAL_MODES, &atafb_modedb[defmode],
3214               fb_info.var.bits_per_pixel)) {
3215         return -EINVAL;
3216     }
3217 
3218     fb_videomode_to_modelist(atafb_modedb, NUM_TOTAL_MODES,
3219                  &fb_info.modelist);
3220 
3221     atafb_set_disp(&fb_info);
3222 
3223     fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0);
3224 
3225 
3226     printk("Determined %dx%d, depth %d\n",
3227            fb_info.var.xres, fb_info.var.yres, fb_info.var.bits_per_pixel);
3228     if ((fb_info.var.xres != fb_info.var.xres_virtual) ||
3229         (fb_info.var.yres != fb_info.var.yres_virtual))
3230         printk("   virtual %dx%d\n", fb_info.var.xres_virtual,
3231                fb_info.var.yres_virtual);
3232 
3233     if (register_framebuffer(&fb_info) < 0) {
3234 #ifdef ATAFB_EXT
3235         if (external_addr) {
3236             iounmap(external_screen_base);
3237             external_addr = 0;
3238         }
3239         if (external_vgaiobase) {
3240             iounmap((void*)external_vgaiobase);
3241             external_vgaiobase = 0;
3242         }
3243 #endif
3244         return -EINVAL;
3245     }
3246 
3247     fb_info(&fb_info, "frame buffer device, using %dK of video memory\n",
3248         screen_len >> 10);
3249 
3250     /* TODO: This driver cannot be unloaded yet */
3251     return 0;
3252 }
3253 
3254 module_init(atafb_init);
3255 
3256 #ifdef MODULE
3257 MODULE_LICENSE("GPL");
3258 
3259 int cleanup_module(void)
3260 {
3261     unregister_framebuffer(&fb_info);
3262     return atafb_deinit();
3263 }
3264 #endif /* MODULE */