Back to home page

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