root/drivers/video/fbdev/atafb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_video_mode
  2. tt_encode_fix
  3. tt_decode_var
  4. tt_encode_var
  5. tt_get_par
  6. tt_set_par
  7. tt_setcolreg
  8. tt_detect
  9. hxx_prescale
  10. falcon_encode_fix
  11. falcon_decode_var
  12. falcon_encode_var
  13. falcon_get_par
  14. falcon_set_par
  15. falcon_vbl_switcher
  16. falcon_pan_display
  17. falcon_setcolreg
  18. falcon_blank
  19. falcon_detect
  20. stste_encode_fix
  21. stste_decode_var
  22. stste_encode_var
  23. stste_get_par
  24. stste_set_par
  25. stste_setcolreg
  26. stste_detect
  27. stste_set_screen_base
  28. st_ovsc_switch
  29. ext_encode_fix
  30. ext_decode_var
  31. ext_encode_var
  32. ext_get_par
  33. ext_set_par
  34. ext_setcolreg
  35. ext_detect
  36. set_screen_base
  37. pan_display
  38. ata_get_par
  39. ata_set_par
  40. do_fb_set_var
  41. atafb_get_fix
  42. atafb_get_var
  43. atafb_set_disp
  44. atafb_setcolreg
  45. atafb_pan_display
  46. atafb_fillrect
  47. atafb_copyarea
  48. atafb_imageblit
  49. atafb_ioctl
  50. atafb_blank
  51. atafb_check_var
  52. atafb_set_par
  53. check_default_par
  54. atafb_setup_ext
  55. atafb_setup_int
  56. atafb_setup_mcap
  57. atafb_setup_user
  58. atafb_setup
  59. atafb_probe
  60. atafb_shutdown
  61. atafb_init

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

/* [<][>][^][v][top][bottom][index][help] */