2  * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device
 
   4  *  Copyright (C) 1994 Martin Schaller & Roman Hodek
 
   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
 
  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
 
  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
 
  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.
 
  50 #include <linux/module.h>
 
  51 #include <linux/kernel.h>
 
  52 #include <linux/errno.h>
 
  53 #include <linux/string.h>
 
  55 #include <linux/slab.h>
 
  56 #include <linux/delay.h>
 
  57 #include <linux/init.h>
 
  58 #include <linux/interrupt.h>
 
  60 #include <asm/setup.h>
 
  61 #include <linux/uaccess.h>
 
  62 #include <asm/pgtable.h>
 
  66 #include <asm/atarihw.h>
 
  67 #include <asm/atariints.h>
 
  68 #include <asm/atari_stram.h>
 
  71 #include <asm/atarikb.h>
 
  76 #define SWITCH_ACIA 0x01                /* modes for switch on OverScan */
 
  77 #define SWITCH_SND6 0x40
 
  78 #define SWITCH_SND7 0x80
 
  79 #define SWITCH_NONE 0x00
 
  82 #define up(x, r) (((x) + (r) - 1) & ~((r)-1))
 
  85          * Interface to the world
 
  88 static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
 
  89 static int atafb_set_par(struct fb_info *info);
 
  90 static int atafb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
 
  91                            unsigned int blue, unsigned int transp,
 
  92                            struct fb_info *info);
 
  93 static int atafb_blank(int blank, struct fb_info *info);
 
  94 static int atafb_pan_display(struct fb_var_screeninfo *var,
 
  95                              struct fb_info *info);
 
  96 static void atafb_fillrect(struct fb_info *info,
 
  97                            const struct fb_fillrect *rect);
 
  98 static void atafb_copyarea(struct fb_info *info,
 
  99                            const struct fb_copyarea *region);
 
 100 static void atafb_imageblit(struct fb_info *info, const struct fb_image *image);
 
 101 static int atafb_ioctl(struct fb_info *info, unsigned int cmd,
 
 105 static int default_par;         /* default resolution (0=none) */
 
 107 static unsigned long default_mem_req;
 
 109 static int hwscroll = -1;
 
 111 static int use_hwscroll = 1;
 
 113 static int sttt_xres = 640, st_yres = 400, tt_yres = 480;
 
 114 static int sttt_xres_virtual = 640, sttt_yres_virtual = 400;
 
 115 static int ovsc_offset, ovsc_addlen;
 
 118          * Hardware parameters for current mode
 
 121 static struct atafb_par {
 
 126 #if defined ATAFB_TT || defined ATAFB_STE
 
 135                         /* Here are fields for storing a video mode, as direct
 
 136                          * parameters for the hardware.
 
 146                         short hht, hbb, hbe, hdb, hde, hss;
 
 147                         short vft, vbb, vbe, vdb, vde, vss;
 
 148                         /* auxiliary information */
 
 154                 /* Nothing needed for external mode */
 
 158 /* Don't calculate an own resolution, and thus don't change the one found when
 
 159  * booting (currently used for the Falcon to keep settings for internal video
 
 160  * hardware extensions (e.g. ScreenBlaster)  */
 
 161 static int DontCalcRes = 0;
 
 164 #define HHT hw.falcon.hht
 
 165 #define HBB hw.falcon.hbb
 
 166 #define HBE hw.falcon.hbe
 
 167 #define HDB hw.falcon.hdb
 
 168 #define HDE hw.falcon.hde
 
 169 #define HSS hw.falcon.hss
 
 170 #define VFT hw.falcon.vft
 
 171 #define VBB hw.falcon.vbb
 
 172 #define VBE hw.falcon.vbe
 
 173 #define VDB hw.falcon.vdb
 
 174 #define VDE hw.falcon.vde
 
 175 #define VSS hw.falcon.vss
 
 176 #define VCO_CLOCK25             0x04
 
 177 #define VCO_CSYPOS              0x10
 
 178 #define VCO_VSYPOS              0x20
 
 179 #define VCO_HSYPOS              0x40
 
 180 #define VCO_SHORTOFFS   0x100
 
 181 #define VMO_DOUBLE              0x01
 
 182 #define VMO_INTER               0x02
 
 183 #define VMO_PREMASK             0x0c
 
 186 static struct fb_info fb_info = {
 
 189                 .visual = FB_VISUAL_PSEUDOCOLOR,
 
 190                 .accel  = FB_ACCEL_NONE,
 
 194 static void *screen_base;       /* base address of screen */
 
 195 static void *real_screen_base;  /* (only for Overscan) */
 
 197 static int screen_len;
 
 199 static int current_par_valid;
 
 201 static int mono_moni;
 
 206 /* external video handling */
 
 207 static unsigned int external_xres;
 
 208 static unsigned int external_xres_virtual;
 
 209 static unsigned int external_yres;
 
 212  * not needed - atafb will never support panning/hardwarescroll with external
 
 213  * static unsigned int external_yres_virtual;
 
 215 static unsigned int external_depth;
 
 216 static int external_pmode;
 
 217 static void *external_addr;
 
 218 static unsigned long external_len;
 
 219 static unsigned long external_vgaiobase;
 
 220 static unsigned int external_bitspercol = 6;
 
 223  * JOE <joe@amber.dinoco.de>:
 
 224  * added card type for external driver, is only needed for
 
 227 enum cardtype { IS_VGA, IS_MV300 };
 
 228 static enum cardtype external_card_type = IS_VGA;
 
 231  * The MV300 mixes the color registers. So we need an array of munged
 
 232  * indices in order to access the correct reg.
 
 234 static int MV300_reg_1bit[2] = {
 
 237 static int MV300_reg_4bit[16] = {
 
 238         0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
 
 240 static int MV300_reg_8bit[256] = {
 
 241         0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
 
 242         8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
 
 243         4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
 
 244         12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
 
 245         2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
 
 246         10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
 
 247         6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
 
 248         14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
 
 249         1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
 
 250         9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
 
 251         5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
 
 252         13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
 
 253         3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
 
 254         11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
 
 255         7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
 
 256         15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
 
 259 static int *MV300_reg = MV300_reg_8bit;
 
 260 #endif /* ATAFB_EXT */
 
 265 extern int fontheight_8x8;
 
 266 extern int fontwidth_8x8;
 
 267 extern unsigned char fontdata_8x8[];
 
 269 extern int fontheight_8x16;
 
 270 extern int fontwidth_8x16;
 
 271 extern unsigned char fontdata_8x16[];
 
 275  *      * open/release and usage marking
 
 276  *      struct module *owner;
 
 277  *      int (*fb_open)(struct fb_info *info, int user);
 
 278  *      int (*fb_release)(struct fb_info *info, int user);
 
 280  *      * For framebuffers with strange non linear layouts or that do not
 
 281  *      * work with normal memory mapped access
 
 282  *      ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos);
 
 283  *      ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
 
 285  *      * checks var and eventually tweaks it to something supported,
 
 286  *      * DOES NOT MODIFY PAR *
 
 287  *      int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
 
 289  *      * set the video mode according to info->var *
 
 290  *      int (*fb_set_par)(struct fb_info *info);
 
 292  *      * set color register *
 
 293  *      int (*fb_setcolreg)(unsigned int regno, unsigned int red, unsigned int green,
 
 294  *                          unsigned int blue, unsigned int transp, struct fb_info *info);
 
 296  *      * set color registers in batch *
 
 297  *      int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
 
 300  *      int (*fb_blank)(int blank, struct fb_info *info);
 
 303  *      int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
 
 305  *      *** The meat of the drawing engine ***
 
 306  *      * Draws a rectangle *
 
 307  *      void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
 
 308  *      * Copy data from area to another *
 
 309  *      void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
 
 310  *      * Draws a image to the display *
 
 311  *      void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
 
 314  *      int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
 
 316  *      * Rotates the display *
 
 317  *      void (*fb_rotate)(struct fb_info *info, int angle);
 
 319  *      * wait for blit idle, optional *
 
 320  *      int (*fb_sync)(struct fb_info *info);
 
 322  *      * perform fb specific ioctl (optional) *
 
 323  *      int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
 
 324  *                      unsigned long arg);
 
 326  *      * Handle 32bit compat ioctl (optional) *
 
 327  *      int (*fb_compat_ioctl)(struct fb_info *info, unsigned int cmd,
 
 328  *                      unsigned long arg);
 
 330  *      * perform fb specific mmap *
 
 331  *      int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
 
 333  *      * save current hardware state *
 
 334  *      void (*fb_save_state)(struct fb_info *info);
 
 336  *      * restore saved state *
 
 337  *      void (*fb_restore_state)(struct fb_info *info);
 
 342 /* ++roman: This structure abstracts from the underlying hardware (ST(e),
 
 345  * int (*detect)(void)
 
 346  *   This function should detect the current video mode settings and
 
 347  *   store them in atafb_predefined[0] for later reference by the
 
 348  *   user. Return the index+1 of an equivalent predefined mode or 0
 
 349  *   if there is no such.
 
 351  * int (*encode_fix)(struct fb_fix_screeninfo *fix,
 
 352  *                   struct atafb_par *par)
 
 353  *   This function should fill in the 'fix' structure based on the
 
 354  *   values in the 'par' structure.
 
 355  * !!! Obsolete, perhaps !!!
 
 357  * int (*decode_var)(struct fb_var_screeninfo *var,
 
 358  *                   struct atafb_par *par)
 
 359  *   Get the video params out of 'var'. If a value doesn't fit, round
 
 360  *   it up, if it's too big, return EINVAL.
 
 361  *   Round up in the following order: bits_per_pixel, xres, yres,
 
 362  *   xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
 
 363  *   horizontal timing, vertical timing.
 
 365  * int (*encode_var)(struct fb_var_screeninfo *var,
 
 366  *                   struct atafb_par *par);
 
 367  *   Fill the 'var' structure based on the values in 'par' and maybe
 
 368  *   other values read out of the hardware.
 
 370  * void (*get_par)(struct atafb_par *par)
 
 371  *   Fill the hardware's 'par' structure.
 
 372  *   !!! Used only by detect() !!!
 
 374  * void (*set_par)(struct atafb_par *par)
 
 375  *   Set the hardware according to 'par'.
 
 377  * void (*set_screen_base)(void *s_base)
 
 378  *   Set the base address of the displayed frame buffer. Only called
 
 379  *   if yres_virtual > yres or xres_virtual > xres.
 
 381  * int (*blank)(int blank_mode)
 
 382  *   Blank the screen if blank_mode != 0, else unblank. If blank == NULL then
 
 383  *   the caller blanks by setting the CLUT to all black. Return 0 if blanking
 
 384  *   succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
 
 385  *   doesn't support it. Implements VESA suspend and powerdown modes on
 
 386  *   hardware that supports disabling hsync/vsync:
 
 387  *       blank_mode == 2: suspend vsync, 3:suspend hsync, 4: powerdown.
 
 390 static struct fb_hwswitch {
 
 392         int (*encode_fix)(struct fb_fix_screeninfo *fix,
 
 393                           struct atafb_par *par);
 
 394         int (*decode_var)(struct fb_var_screeninfo *var,
 
 395                           struct atafb_par *par);
 
 396         int (*encode_var)(struct fb_var_screeninfo *var,
 
 397                           struct atafb_par *par);
 
 398         void (*get_par)(struct atafb_par *par);
 
 399         void (*set_par)(struct atafb_par *par);
 
 400         void (*set_screen_base)(void *s_base);
 
 401         int (*blank)(int blank_mode);
 
 402         int (*pan_display)(struct fb_var_screeninfo *var,
 
 403                            struct fb_info *info);
 
 406 static char *autodetect_names[] = { "autodetect", NULL };
 
 407 static char *stlow_names[] = { "stlow", NULL };
 
 408 static char *stmid_names[] = { "stmid", "default5", NULL };
 
 409 static char *sthigh_names[] = { "sthigh", "default4", NULL };
 
 410 static char *ttlow_names[] = { "ttlow", NULL };
 
 411 static char *ttmid_names[] = { "ttmid", "default1", NULL };
 
 412 static char *tthigh_names[] = { "tthigh", "default2", NULL };
 
 413 static char *vga2_names[] = { "vga2", NULL };
 
 414 static char *vga4_names[] = { "vga4", NULL };
 
 415 static char *vga16_names[] = { "vga16", "default3", NULL };
 
 416 static char *vga256_names[] = { "vga256", NULL };
 
 417 static char *falh2_names[] = { "falh2", NULL };
 
 418 static char *falh16_names[] = { "falh16", NULL };
 
 420 static char **fb_var_names[] = {
 
 437 static struct fb_var_screeninfo atafb_predefined[] = {
 
 439          * yres_virtual == 0 means use hw-scrolling if possible, else yres
 
 442           0, 0, 0, 0, 0, 0, 0, 0,               /* xres-grayscale */
 
 443           {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},   /* red green blue tran*/
 
 444           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 446           320, 200, 320, 0, 0, 0, 4, 0,
 
 447           {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
 
 448           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 450           640, 200, 640, 0, 0, 0, 2, 0,
 
 451           {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
 
 452           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 454           640, 400, 640, 0, 0, 0, 1, 0,
 
 455           {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
 
 456           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 458           320, 480, 320, 0, 0, 0, 8, 0,
 
 459           {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
 
 460           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 462           640, 480, 640, 0, 0, 0, 4, 0,
 
 463           {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
 
 464           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 466           1280, 960, 1280, 0, 0, 0, 1, 0,
 
 467           {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
 
 468           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 470           640, 480, 640, 0, 0, 0, 1, 0,
 
 471           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 
 472           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 474           640, 480, 640, 0, 0, 0, 2, 0,
 
 475           {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
 
 476           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 478           640, 480, 640, 0, 0, 0, 4, 0,
 
 479           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 
 480           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 482           640, 480, 640, 0, 0, 0, 8, 0,
 
 483           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 
 484           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 486           896, 608, 896, 0, 0, 0, 1, 0,
 
 487           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 
 488           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 490           896, 608, 896, 0, 0, 0, 4, 0,
 
 491           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 
 492           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 495 static int num_atafb_predefined = ARRAY_SIZE(atafb_predefined);
 
 497 static struct fb_videomode atafb_modedb[] __initdata = {
 
 501          *  If you change these, make sure to update DEFMODE_* as well!
 
 509                 /* 320x200, 15 kHz, 60 Hz (ST low) */
 
 510                 "st-low", 60, 320, 200, 32000, 32, 16, 31, 14, 96, 4,
 
 511                 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 
 513                 /* 640x200, 15 kHz, 60 Hz (ST medium) */
 
 514                 "st-mid", 60, 640, 200, 32000, 32, 16, 31, 14, 96, 4,
 
 515                 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 
 517                 /* 640x400, 30.25 kHz, 63.5 Hz (ST high) */
 
 518                 "st-high", 63, 640, 400, 32000, 128, 0, 40, 14, 128, 4,
 
 519                 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 
 521                 /* 320x480, 15 kHz, 60 Hz (TT low) */
 
 522                 "tt-low", 60, 320, 480, 31041, 120, 100, 8, 16, 140, 30,
 
 523                 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 
 525                 /* 640x480, 29 kHz, 57 Hz (TT medium) */
 
 526                 "tt-mid", 60, 640, 480, 31041, 120, 100, 8, 16, 140, 30,
 
 527                 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 
 529                 /* 1280x960, 29 kHz, 60 Hz (TT high) */
 
 530                 "tt-high", 57, 640, 960, 31041, 120, 100, 8, 16, 140, 30,
 
 531                 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 
 539                 /* 640x480, 31 kHz, 60 Hz (VGA) */
 
 540                 "vga", 63.5, 640, 480, 32000, 18, 42, 31, 11, 96, 3,
 
 541                 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 
 543                 /* 640x400, 31 kHz, 70 Hz (VGA) */
 
 544                 "vga70", 70, 640, 400, 32000, 18, 42, 31, 11, 96, 3,
 
 545                 FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 
 549          *  Falcon HiRes Video Modes
 
 553                 /* 896x608, 31 kHz, 60 Hz (Falcon High) */
 
 554                 "falh", 60, 896, 608, 32000, 18, 42, 31, 1, 96,3,
 
 555                 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 
 559 #define NUM_TOTAL_MODES  ARRAY_SIZE(atafb_modedb)
 
 561 static char *mode_option __initdata = NULL;
 
 565 #define DEFMODE_TT      5               /* "tt-high" for TT */
 
 566 #define DEFMODE_F30     7               /* "vga70" for Falcon */
 
 567 #define DEFMODE_STE     2               /* "st-high" for ST/E */
 
 568 #define DEFMODE_EXT     6               /* "vga" for external */
 
 571 static int get_video_mode(char *vname)
 
 577         name_list = fb_var_names;
 
 578         for (i = 0; i < num_atafb_predefined; i++) {
 
 583                         if (!strcmp(vname, *name))
 
 593 /* ------------------- TT specific functions ---------------------- */
 
 597 static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
 
 601         strcpy(fix->id, "Atari Builtin");
 
 602         fix->smem_start = (unsigned long)real_screen_base;
 
 603         fix->smem_len = screen_len;
 
 604         fix->type = FB_TYPE_INTERLEAVED_PLANES;
 
 606         fix->visual = FB_VISUAL_PSEUDOCOLOR;
 
 607         mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK;
 
 608         if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) {
 
 609                 fix->type = FB_TYPE_PACKED_PIXELS;
 
 611                 if (mode == TT_SHIFTER_TTHIGH)
 
 612                         fix->visual = FB_VISUAL_MONO01;
 
 617         fix->line_length = 0;
 
 618         fix->accel = FB_ACCEL_ATARIBLITT;
 
 622 static int tt_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
 
 624         int xres = var->xres;
 
 625         int yres = var->yres;
 
 626         int bpp = var->bits_per_pixel;
 
 628         int yres_virtual = var->yres_virtual;
 
 631                 if (bpp > 1 || xres > sttt_xres * 2 || yres > tt_yres * 2)
 
 633                 par->hw.tt.mode = TT_SHIFTER_TTHIGH;
 
 634                 xres = sttt_xres * 2;
 
 638                 if (bpp > 8 || xres > sttt_xres || yres > tt_yres)
 
 641                         if (xres > sttt_xres / 2 || yres > tt_yres)
 
 643                         par->hw.tt.mode = TT_SHIFTER_TTLOW;
 
 644                         xres = sttt_xres / 2;
 
 647                 } else if (bpp > 2) {
 
 648                         if (xres > sttt_xres || yres > tt_yres)
 
 650                         if (xres > sttt_xres / 2 || yres > st_yres / 2) {
 
 651                                 par->hw.tt.mode = TT_SHIFTER_TTMID;
 
 656                                 par->hw.tt.mode = TT_SHIFTER_STLOW;
 
 657                                 xres = sttt_xres / 2;
 
 661                 } else if (bpp > 1) {
 
 662                         if (xres > sttt_xres || yres > st_yres / 2)
 
 664                         par->hw.tt.mode = TT_SHIFTER_STMID;
 
 668                 } else if (var->xres > sttt_xres || var->yres > st_yres) {
 
 671                         par->hw.tt.mode = TT_SHIFTER_STHIGH;
 
 677         if (yres_virtual <= 0)
 
 679         else if (yres_virtual < yres)
 
 681         if (var->sync & FB_SYNC_EXT)
 
 685         linelen = xres * bpp / 8;
 
 686         if (yres_virtual * linelen > screen_len && screen_len)
 
 688         if (yres * linelen > screen_len && screen_len)
 
 690         if (var->yoffset + yres > yres_virtual && yres_virtual)
 
 692         par->yres_virtual = yres_virtual;
 
 693         par->screen_base = screen_base + var->yoffset * linelen;
 
 697 static int tt_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
 
 700         memset(var, 0, sizeof(struct fb_var_screeninfo));
 
 703         var->red.msb_right = 0;
 
 706         var->pixclock = 31041;
 
 707         var->left_margin = 120;         /* these may be incorrect */
 
 708         var->right_margin = 100;
 
 709         var->upper_margin = 8;
 
 710         var->lower_margin = 16;
 
 711         var->hsync_len = 140;
 
 717         if (par->hw.tt.sync & 1)
 
 720                 var->sync = FB_SYNC_EXT;
 
 722         switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) {
 
 723         case TT_SHIFTER_STLOW:
 
 724                 var->xres = sttt_xres / 2;
 
 725                 var->xres_virtual = sttt_xres_virtual / 2;
 
 726                 var->yres = st_yres / 2;
 
 727                 var->bits_per_pixel = 4;
 
 729         case TT_SHIFTER_STMID:
 
 730                 var->xres = sttt_xres;
 
 731                 var->xres_virtual = sttt_xres_virtual;
 
 732                 var->yres = st_yres / 2;
 
 733                 var->bits_per_pixel = 2;
 
 735         case TT_SHIFTER_STHIGH:
 
 736                 var->xres = sttt_xres;
 
 737                 var->xres_virtual = sttt_xres_virtual;
 
 739                 var->bits_per_pixel = 1;
 
 741         case TT_SHIFTER_TTLOW:
 
 742                 var->xres = sttt_xres / 2;
 
 743                 var->xres_virtual = sttt_xres_virtual / 2;
 
 745                 var->bits_per_pixel = 8;
 
 747         case TT_SHIFTER_TTMID:
 
 748                 var->xres = sttt_xres;
 
 749                 var->xres_virtual = sttt_xres_virtual;
 
 751                 var->bits_per_pixel = 4;
 
 753         case TT_SHIFTER_TTHIGH:
 
 755                 var->xres = sttt_xres * 2;
 
 756                 var->xres_virtual = sttt_xres_virtual * 2;
 
 757                 var->yres = tt_yres * 2;
 
 758                 var->bits_per_pixel = 1;
 
 761         var->blue = var->green = var->red;
 
 762         var->transp.offset = 0;
 
 763         var->transp.length = 0;
 
 764         var->transp.msb_right = 0;
 
 765         linelen = var->xres_virtual * var->bits_per_pixel / 8;
 
 767                 var->yres_virtual = var->yres;
 
 768         else if (screen_len) {
 
 769                 if (par->yres_virtual)
 
 770                         var->yres_virtual = par->yres_virtual;
 
 772                         /* yres_virtual == 0 means use maximum */
 
 773                         var->yres_virtual = screen_len / linelen;
 
 776                         var->yres_virtual = 2 * var->yres;
 
 778                         var->yres_virtual = var->yres + hwscroll * 16;
 
 782                 var->yoffset = (par->screen_base - screen_base) / linelen;
 
 787         var->vmode = FB_VMODE_NONINTERLACED;
 
 791 static void tt_get_par(struct atafb_par *par)
 
 794         par->hw.tt.mode = shifter_tt.tt_shiftmode;
 
 795         par->hw.tt.sync = shifter.syncmode;
 
 796         addr = ((shifter.bas_hi & 0xff) << 16) |
 
 797                ((shifter.bas_md & 0xff) << 8)  |
 
 798                ((shifter.bas_lo & 0xff));
 
 799         par->screen_base = phys_to_virt(addr);
 
 802 static void tt_set_par(struct atafb_par *par)
 
 804         shifter_tt.tt_shiftmode = par->hw.tt.mode;
 
 805         shifter.syncmode = par->hw.tt.sync;
 
 806         /* only set screen_base if really necessary */
 
 807         if (current_par.screen_base != par->screen_base)
 
 808                 fbhw->set_screen_base(par->screen_base);
 
 811 static int tt_setcolreg(unsigned int regno, unsigned int red,
 
 812                         unsigned int green, unsigned int blue,
 
 813                         unsigned int transp, struct fb_info *info)
 
 815         if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
 
 819         tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) |
 
 821         if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
 
 822             TT_SHIFTER_STHIGH && regno == 254)
 
 827 static int tt_detect(void)
 
 829         struct atafb_par par;
 
 831         /* Determine the connected monitor: The DMA sound must be
 
 832          * disabled before reading the MFP GPIP, because the Sound
 
 833          * Done Signal and the Monochrome Detect are XORed together!
 
 835          * Even on a TT, we should look if there is a DMA sound. It was
 
 836          * announced that the Eagle is TT compatible, but only the PCM is
 
 839         if (ATARIHW_PRESENT(PCM_8BIT)) {
 
 840                 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
 
 841                 udelay(20);             /* wait a while for things to settle down */
 
 843         mono_moni = (mfp.par_dt_reg & 0x80) == 0;
 
 846         tt_encode_var(&atafb_predefined[0], &par);
 
 851 #endif /* ATAFB_TT */
 
 853 /* ------------------- Falcon specific functions ---------------------- */
 
 857 static int mon_type;            /* Falcon connected monitor */
 
 858 static int f030_bus_width;      /* Falcon ram bus width (for vid_control) */
 
 864 static struct pixel_clock {
 
 865         unsigned long f;        /* f/[Hz] */
 
 866         unsigned long t;        /* t/[ps] (=1/f) */
 
 867         int right, hsync, left; /* standard timing in clock cycles, not pixel */
 
 868         /* hsync initialized in falcon_detect() */
 
 869         int sync_mask;          /* or-mask for hw.falcon.sync to set this clock */
 
 870         int control_mask;       /* ditto, for hw.falcon.vid_control */
 
 872         25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25
 
 874         32000000, 31250, 18, 0, 42, 0x0, 0
 
 876         0, 0, 18, 0, 42, 0x1, 0
 
 879 /* VIDEL-prescale values [mon_type][pixel_length from VCO] */
 
 880 static int vdl_prescale[4][3] = {
 
 881         { 4,2,1 }, { 4,2,1 }, { 4,2,2 }, { 4,2,1 }
 
 884 /* Default hsync timing [mon_type] in picoseconds */
 
 885 static long h_syncs[4] = { 3000000, 4875000, 4000000, 4875000 };
 
 887 #ifdef FBCON_HAS_CFB16
 
 888 static u16 fbcon_cfb16_cmap[16];
 
 891 static inline int hxx_prescale(struct falcon_hw *hw)
 
 893         return hw->ste_mode ? 16
 
 894                             : vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
 
 897 static int falcon_encode_fix(struct fb_fix_screeninfo *fix,
 
 898                              struct atafb_par *par)
 
 900         strcpy(fix->id, "Atari Builtin");
 
 901         fix->smem_start = (unsigned long)real_screen_base;
 
 902         fix->smem_len = screen_len;
 
 903         fix->type = FB_TYPE_INTERLEAVED_PLANES;
 
 905         fix->visual = FB_VISUAL_PSEUDOCOLOR;
 
 909         if (par->hw.falcon.mono) {
 
 910                 fix->type = FB_TYPE_PACKED_PIXELS;
 
 912                 /* no smooth scrolling with longword aligned video mem */
 
 914         } else if (par->hw.falcon.f_shift & 0x100) {
 
 915                 fix->type = FB_TYPE_PACKED_PIXELS;
 
 917                 /* Is this ok or should it be DIRECTCOLOR? */
 
 918                 fix->visual = FB_VISUAL_TRUECOLOR;
 
 921         fix->line_length = 0;
 
 922         fix->accel = FB_ACCEL_ATARIBLITT;
 
 926 static int falcon_decode_var(struct fb_var_screeninfo *var,
 
 927                              struct atafb_par *par)
 
 929         int bpp = var->bits_per_pixel;
 
 930         int xres = var->xres;
 
 931         int yres = var->yres;
 
 932         int xres_virtual = var->xres_virtual;
 
 933         int yres_virtual = var->yres_virtual;
 
 934         int left_margin, right_margin, hsync_len;
 
 935         int upper_margin, lower_margin, vsync_len;
 
 937         int interlace = 0, doubleline = 0;
 
 938         struct pixel_clock *pclock;
 
 939         int plen;                       /* width of pixel in clock cycles */
 
 944         int hdb_off, hde_off, base_off;
 
 945         int gstart, gend1, gend2, align;
 
 948         Get the video params out of 'var'. If a value doesn't fit, round
 
 949         it up, if it's too big, return EINVAL.
 
 950         Round up in the following order: bits_per_pixel, xres, yres,
 
 951         xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
 
 952         horizontal timing, vertical timing.
 
 954         There is a maximum of screen resolution determined by pixelclock
 
 955         and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock.
 
 956         In interlace mode this is     "     *    "     *vfmin <= pixelclock.
 
 957         Additional constraints: hfreq.
 
 958         Frequency range for multisync monitors is given via command line.
 
 959         For TV and SM124 both frequencies are fixed.
 
 961         X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32 == 0)
 
 962         Y % 16 == 0 to fit 8x16 font
 
 965         Currently interlace and doubleline mode in var are ignored.
 
 966         On SM124 and TV only the standard resolutions can be used.
 
 969         /* Reject uninitialized mode */
 
 970         if (!xres || !yres || !bpp)
 
 973         if (mon_type == F_MON_SM && bpp != 1)
 
 978                 par->hw.falcon.f_shift = 0x400;
 
 979                 par->hw.falcon.st_shift = 0x200;
 
 980         } else if (bpp <= 2) {
 
 982                 par->hw.falcon.f_shift = 0x000;
 
 983                 par->hw.falcon.st_shift = 0x100;
 
 984         } else if (bpp <= 4) {
 
 986                 par->hw.falcon.f_shift = 0x000;
 
 987                 par->hw.falcon.st_shift = 0x000;
 
 988         } else if (bpp <= 8) {
 
 990                 par->hw.falcon.f_shift = 0x010;
 
 991         } else if (bpp <= 16) {
 
 992                 bpp = 16;               /* packed pixel mode */
 
 993                 par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */
 
 996         par->hw.falcon.bpp = bpp;
 
 998         if (mon_type == F_MON_SM || DontCalcRes) {
 
 999                 /* Skip all calculations. VGA/TV/SC1224 only supported. */
 
1000                 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
 
1002                 if (bpp > myvar->bits_per_pixel ||
 
1003                     var->xres > myvar->xres ||
 
1004                     var->yres > myvar->yres)
 
1006                 fbhw->get_par(par);     /* Current par will be new par */
 
1007                 goto set_screen_base;   /* Don't forget this */
 
1010         /* Only some fixed resolutions < 640x400 */
 
1013         else if (xres <= 640 && bpp != 16)
 
1017         else if (yres <= 240)
 
1019         else if (yres <= 400)
 
1022         /* 2 planes must use STE compatibility mode */
 
1023         par->hw.falcon.ste_mode = bpp == 2;
 
1024         par->hw.falcon.mono = bpp == 1;
 
1026         /* Total and visible scanline length must be a multiple of one longword,
 
1027          * this and the console fontwidth yields the alignment for xres and
 
1029          * TODO: this way "odd" fontheights are not supported
 
1031          * Special case in STE mode: blank and graphic positions don't align,
 
1032          * avoid trash at right margin
 
1034         if (par->hw.falcon.ste_mode)
 
1035                 xres = (xres + 63) & ~63;
 
1037                 xres = (xres + 31) & ~31;
 
1039                 xres = (xres + 15) & ~15;
 
1041                 yres = (yres + 15) & ~15;
 
1043                 yres = (yres + 7) & ~7;
 
1045         if (xres_virtual < xres)
 
1046                 xres_virtual = xres;
 
1048                 xres_virtual = (xres_virtual + 31) & ~31;
 
1050                 xres_virtual = (xres_virtual + 15) & ~15;
 
1052         if (yres_virtual <= 0)
 
1054         else if (yres_virtual < yres)
 
1055                 yres_virtual = yres;
 
1057         /* backward bug-compatibility */
 
1058         if (var->pixclock > 1)
 
1061         par->hw.falcon.line_width = bpp * xres / 16;
 
1062         par->hw.falcon.line_offset = bpp * (xres_virtual - xres) / 16;
 
1064         /* single or double pixel width */
 
1065         xstretch = (xres < 640) ? 2 : 1;
 
1067 #if 0 /* SM124 supports only 640x400, this is rejected above */
 
1068         if (mon_type == F_MON_SM) {
 
1069                 if (xres != 640 && yres != 400)
 
1073                 /* SM124-mode is special */
 
1074                 par->hw.falcon.ste_mode = 1;
 
1075                 par->hw.falcon.f_shift = 0x000;
 
1076                 par->hw.falcon.st_shift = 0x200;
 
1077                 left_margin = hsync_len = 128 / plen;
 
1079                 /* TODO set all margins */
 
1082         if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
 
1083                 plen = 2 * xstretch;
 
1084                 if (var->pixclock > f32.t * plen)
 
1089                 if (var->pixclock == 0) {
 
1090                         /* set some minimal margins which center the screen */
 
1093                         hsync_len = pclock->hsync / plen;
 
1096                         vsync_len = interlace ? 3 : 4;
 
1098                         left_margin = var->left_margin;
 
1099                         right_margin = var->right_margin;
 
1100                         hsync_len = var->hsync_len;
 
1101                         upper_margin = var->upper_margin;
 
1102                         lower_margin = var->lower_margin;
 
1103                         vsync_len = var->vsync_len;
 
1104                         if (var->vmode & FB_VMODE_INTERLACED) {
 
1105                                 upper_margin = (upper_margin + 1) / 2;
 
1106                                 lower_margin = (lower_margin + 1) / 2;
 
1107                                 vsync_len = (vsync_len + 1) / 2;
 
1108                         } else if (var->vmode & FB_VMODE_DOUBLE) {
 
1114         } else {                        /* F_MON_VGA */
 
1116                         xstretch = 2;   /* Double pixel width only for hicolor */
 
1117                 /* Default values are used for vert./hor. timing if no pixelclock given. */
 
1118                 if (var->pixclock == 0) {
 
1121                         /* Choose master pixelclock depending on hor. timing */
 
1122                         plen = 1 * xstretch;
 
1123                         if ((plen * xres + f25.right + f25.hsync + f25.left) *
 
1124                             fb_info.monspecs.hfmin < f25.f)
 
1126                         else if ((plen * xres + f32.right + f32.hsync +
 
1127                                   f32.left) * fb_info.monspecs.hfmin < f32.f)
 
1129                         else if ((plen * xres + fext.right + fext.hsync +
 
1130                                   fext.left) * fb_info.monspecs.hfmin < fext.f &&
 
1136                         left_margin = pclock->left / plen;
 
1137                         right_margin = pclock->right / plen;
 
1138                         hsync_len = pclock->hsync / plen;
 
1139                         linesize = left_margin + xres + right_margin + hsync_len;
 
1144                         /* Choose largest pixelclock <= wanted clock */
 
1146                         unsigned long pcl = ULONG_MAX;
 
1148                         for (i = 1; i <= 4; i *= 2) {
 
1149                                 if (f25.t * i >= var->pixclock &&
 
1154                                 if (f32.t * i >= var->pixclock &&
 
1159                                 if (fext.t && fext.t * i >= var->pixclock &&
 
1167                         plen = pcl / pclock->t;
 
1169                         left_margin = var->left_margin;
 
1170                         right_margin = var->right_margin;
 
1171                         hsync_len = var->hsync_len;
 
1172                         upper_margin = var->upper_margin;
 
1173                         lower_margin = var->lower_margin;
 
1174                         vsync_len = var->vsync_len;
 
1175                         /* Internal unit is [single lines per (half-)frame] */
 
1176                         if (var->vmode & FB_VMODE_INTERLACED) {
 
1177                                 /* # lines in half frame */
 
1178                                 /* External unit is [lines per full frame] */
 
1179                                 upper_margin = (upper_margin + 1) / 2;
 
1180                                 lower_margin = (lower_margin + 1) / 2;
 
1181                                 vsync_len = (vsync_len + 1) / 2;
 
1182                         } else if (var->vmode & FB_VMODE_DOUBLE) {
 
1183                                 /* External unit is [double lines per frame] */
 
1189                 if (pclock == &fext)
 
1190                         longoffset = 1; /* VIDEL doesn't synchronize on short offset */
 
1192         /* Is video bus bandwidth (32MB/s) too low for this resolution? */
 
1193         /* this is definitely wrong if bus clock != 32MHz */
 
1194         if (pclock->f / plen / 8 * bpp > 32000000L)
 
1200         /* include sync lengths in right/lower margin for all calculations */
 
1201         right_margin += hsync_len;
 
1202         lower_margin += vsync_len;
 
1204         /* ! In all calculations of margins we use # of lines in half frame
 
1205          * (which is a full frame in non-interlace mode), so we can switch
 
1206          * between interlace and non-interlace without messing around
 
1210         /* Set base_offset 128 and video bus width */
 
1211         par->hw.falcon.vid_control = mon_type | f030_bus_width;
 
1213                 par->hw.falcon.vid_control |= VCO_SHORTOFFS;    /* base_offset 64 */
 
1214         if (var->sync & FB_SYNC_HOR_HIGH_ACT)
 
1215                 par->hw.falcon.vid_control |= VCO_HSYPOS;
 
1216         if (var->sync & FB_SYNC_VERT_HIGH_ACT)
 
1217                 par->hw.falcon.vid_control |= VCO_VSYPOS;
 
1219         par->hw.falcon.vid_control |= pclock->control_mask;
 
1220         /* External or internal clock */
 
1221         par->hw.falcon.sync = pclock->sync_mask | 0x2;
 
1222         /* Pixellength and prescale */
 
1223         par->hw.falcon.vid_mode = (2 / plen) << 2;
 
1225                 par->hw.falcon.vid_mode |= VMO_DOUBLE;
 
1227                 par->hw.falcon.vid_mode |= VMO_INTER;
 
1229         /*********************
 
1230          * Horizontal timing: unit = [master clock cycles]
 
1231          * unit of hxx-registers: [master clock cycles * prescale]
 
1232          * Hxx-registers are 9 bit wide
 
1234          * 1 line = ((hht + 2) * 2 * prescale) clock cycles
 
1236          * graphic output = hdb & 0x200 ?
 
1237          *        ((hht + 2) * 2 - hdb + hde) * prescale - hdboff + hdeoff:
 
1238          *        (hht + 2  - hdb + hde) * prescale - hdboff + hdeoff
 
1239          * (this must be a multiple of plen*128/bpp, on VGA pixels
 
1240          *  to the right may be cut off with a bigger right margin)
 
1242          * start of graphics relative to start of 1st halfline = hdb & 0x200 ?
 
1243          *        (hdb - hht - 2) * prescale + hdboff :
 
1244          *        hdb * prescale + hdboff
 
1246          * end of graphics relative to start of 1st halfline =
 
1247          *        (hde + hht + 2) * prescale + hdeoff
 
1248          *********************/
 
1249         /* Calculate VIDEL registers */
 
1251         prescale = hxx_prescale(&par->hw.falcon);
 
1252         base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128;
 
1254         /* Offsets depend on video mode */
 
1255         /* Offsets are in clock cycles, divide by prescale to
 
1256          * calculate hd[be]-registers
 
1258         if (par->hw.falcon.f_shift & 0x100) {
 
1261                 hdb_off = (base_off + 16 * plen) + prescale;
 
1264                 hde_off = ((128 / bpp + 2) * plen);
 
1265                 if (par->hw.falcon.ste_mode)
 
1266                         hdb_off = (64 + base_off + (128 / bpp + 2) * plen) + prescale;
 
1268                         hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale;
 
1271         gstart = (prescale / 2 + plen * left_margin) / prescale;
 
1272         /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
 
1273         gend1 = gstart + ((xres + align - 1) / align) * align * plen / prescale;
 
1274         /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
 
1275         gend2 = gstart + xres * plen / prescale;
 
1276         par->HHT = plen * (left_margin + xres + right_margin) /
 
1278 /*      par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
 
1280         par->HDB = gstart - hdb_off / prescale;
 
1283                 par->HDB += par->HHT + 2 + 0x200;
 
1284         par->HDE = gend1 - par->HHT - 2 - hde_off / prescale;
 
1285         par->HBB = gend2 - par->HHT - 2;
 
1287         /* One more Videl constraint: data fetch of two lines must not overlap */
 
1288         if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) {
 
1289                 /* if this happens increase margins, decrease hfreq. */
 
1292         if (hde_off % prescale)
 
1293                 par->HBB++;             /* compensate for non matching hde and hbb */
 
1294         par->HSS = par->HHT + 2 - plen * hsync_len / prescale;
 
1295         if (par->HSS < par->HBB)
 
1296                 par->HSS = par->HBB;
 
1299         /*  check hor. frequency */
 
1300         hfreq = pclock->f / ((par->HHT + 2) * prescale * 2);
 
1301         if (hfreq > fb_info.monspecs.hfmax && mon_type != F_MON_VGA) {
 
1302                 /* ++guenther:   ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
 
1303                 /* Too high -> enlarge margin */
 
1308         if (hfreq > fb_info.monspecs.hfmax || hfreq < fb_info.monspecs.hfmin)
 
1312         /* All Vxx must be odd in non-interlace, since frame starts in the middle
 
1313          * of the first displayed line!
 
1314          * One frame consists of VFT+1 half lines. VFT+1 must be even in
 
1315          * non-interlace, odd in interlace mode for synchronisation.
 
1316          * Vxx-registers are 11 bit wide
 
1318         par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */
 
1319         par->VDB = par->VBE;
 
1324                 par->VDE <<= 1;         /* VDE now half lines per (half-)frame */
 
1325         par->VDE += par->VDB;
 
1326         par->VBB = par->VDE;
 
1327         par->VFT = par->VBB + (lower_margin * 2 - 1) - 1;
 
1328         par->VSS = par->VFT + 1 - (vsync_len * 2 - 1);
 
1329         /* vbb,vss,vft must be even in interlace mode */
 
1336         /* V-frequency check, hope I didn't create any loop here. */
 
1337         /* Interlace and doubleline are mutually exclusive. */
 
1338         vfreq = (hfreq * 2) / (par->VFT + 1);
 
1339         if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
 
1340                 /* Too high -> try again with doubleline */
 
1343         } else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
 
1344                 /* Too low -> try again with interlace */
 
1347         } else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
 
1348                 /* Doubleline too low -> clear doubleline and enlarge margins */
 
1352                      (hfreq * 2) / (par->VFT + 1 + 4 * lines - 2 * yres) >
 
1353                      fb_info.monspecs.vfmax;
 
1356                 upper_margin += lines;
 
1357                 lower_margin += lines;
 
1359         } else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
 
1360                 /* Doubleline too high -> enlarge margins */
 
1363                      (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
 
1364                      fb_info.monspecs.vfmax;
 
1367                 upper_margin += lines;
 
1368                 lower_margin += lines;
 
1370         } else if (vfreq > fb_info.monspecs.vfmax && interlace) {
 
1371                 /* Interlace, too high -> enlarge margins */
 
1374                      (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
 
1375                      fb_info.monspecs.vfmax;
 
1378                 upper_margin += lines;
 
1379                 lower_margin += lines;
 
1381         } else if (vfreq < fb_info.monspecs.vfmin ||
 
1382                    vfreq > fb_info.monspecs.vfmax)
 
1386         linelen = xres_virtual * bpp / 8;
 
1387         if (yres_virtual * linelen > screen_len && screen_len)
 
1389         if (yres * linelen > screen_len && screen_len)
 
1391         if (var->yoffset + yres > yres_virtual && yres_virtual)
 
1393         par->yres_virtual = yres_virtual;
 
1394         par->screen_base = screen_base + var->yoffset * linelen;
 
1395         par->hw.falcon.xoffset = 0;
 
1397         // FIXME!!! sort of works, no crash
 
1398         //par->next_line = linelen;
 
1399         //par->next_plane = yres_virtual * linelen;
 
1400         par->next_line = linelen;
 
1401         par->next_plane = 2;
 
1403         //par->next_plane = linelen;
 
1404         //par->next_line  = yres_virtual * linelen;
 
1409 static int falcon_encode_var(struct fb_var_screeninfo *var,
 
1410                              struct atafb_par *par)
 
1412 /* !!! only for VGA !!! */
 
1415         int hdb_off, hde_off, base_off;
 
1416         struct falcon_hw *hw = &par->hw.falcon;
 
1418         memset(var, 0, sizeof(struct fb_var_screeninfo));
 
1419         /* possible frequencies: 25.175 or 32MHz */
 
1420         var->pixclock = hw->sync & 0x1 ? fext.t :
 
1421                         hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t;
 
1427         if (hw->vid_control & VCO_HSYPOS)
 
1428                 var->sync |= FB_SYNC_HOR_HIGH_ACT;
 
1429         if (hw->vid_control & VCO_VSYPOS)
 
1430                 var->sync |= FB_SYNC_VERT_HIGH_ACT;
 
1432         var->vmode = FB_VMODE_NONINTERLACED;
 
1433         if (hw->vid_mode & VMO_INTER)
 
1434                 var->vmode |= FB_VMODE_INTERLACED;
 
1435         if (hw->vid_mode & VMO_DOUBLE)
 
1436                 var->vmode |= FB_VMODE_DOUBLE;
 
1438         /* visible y resolution:
 
1439          * Graphics display starts at line VDB and ends at line
 
1440          * VDE. If interlace mode off unit of VC-registers is
 
1441          * half lines, else lines.
 
1443         var->yres = hw->vde - hw->vdb;
 
1444         if (!(var->vmode & FB_VMODE_INTERLACED))
 
1446         if (var->vmode & FB_VMODE_DOUBLE)
 
1450          * to get bpp, we must examine f_shift and st_shift.
 
1451          * f_shift is valid if any of bits no. 10, 8 or 4
 
1452          * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
 
1453          * if bit 10 set then bit 8 and bit 4 don't care...
 
1454          * If all these bits are 0 get display depth from st_shift
 
1455          * (as for ST and STE)
 
1457         if (hw->f_shift & 0x400)        /* 2 colors */
 
1458                 var->bits_per_pixel = 1;
 
1459         else if (hw->f_shift & 0x100)   /* hicolor */
 
1460                 var->bits_per_pixel = 16;
 
1461         else if (hw->f_shift & 0x010)   /* 8 bitplanes */
 
1462                 var->bits_per_pixel = 8;
 
1463         else if (hw->st_shift == 0)
 
1464                 var->bits_per_pixel = 4;
 
1465         else if (hw->st_shift == 0x100)
 
1466                 var->bits_per_pixel = 2;
 
1467         else                            /* if (hw->st_shift == 0x200) */
 
1468                 var->bits_per_pixel = 1;
 
1470         var->xres = hw->line_width * 16 / var->bits_per_pixel;
 
1471         var->xres_virtual = var->xres + hw->line_offset * 16 / var->bits_per_pixel;
 
1473                 var->xres_virtual += 16;
 
1475         if (var->bits_per_pixel == 16) {
 
1476                 var->red.offset = 11;
 
1477                 var->red.length = 5;
 
1478                 var->red.msb_right = 0;
 
1479                 var->green.offset = 5;
 
1480                 var->green.length = 6;
 
1481                 var->green.msb_right = 0;
 
1482                 var->blue.offset = 0;
 
1483                 var->blue.length = 5;
 
1484                 var->blue.msb_right = 0;
 
1486                 var->red.offset = 0;
 
1487                 var->red.length = hw->ste_mode ? 4 : 6;
 
1488                 if (var->red.length > var->bits_per_pixel)
 
1489                         var->red.length = var->bits_per_pixel;
 
1490                 var->red.msb_right = 0;
 
1492                 var->blue = var->green = var->red;
 
1494         var->transp.offset = 0;
 
1495         var->transp.length = 0;
 
1496         var->transp.msb_right = 0;
 
1498         linelen = var->xres_virtual * var->bits_per_pixel / 8;
 
1500                 if (par->yres_virtual)
 
1501                         var->yres_virtual = par->yres_virtual;
 
1503                         /* yres_virtual == 0 means use maximum */
 
1504                         var->yres_virtual = screen_len / linelen;
 
1507                         var->yres_virtual = 2 * var->yres;
 
1509                         var->yres_virtual = var->yres + hwscroll * 16;
 
1511         var->xoffset = 0;               /* TODO change this */
 
1514         prescale = hxx_prescale(hw);
 
1515         plen = 4 >> (hw->vid_mode >> 2 & 0x3);
 
1516         base_off = hw->vid_control & VCO_SHORTOFFS ? 64 : 128;
 
1517         if (hw->f_shift & 0x100) {
 
1519                 hdb_off = (base_off + 16 * plen) + prescale;
 
1521                 hde_off = ((128 / var->bits_per_pixel + 2) * plen);
 
1523                         hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)
 
1526                         hdb_off = (base_off + (128 / var->bits_per_pixel + 18) * plen)
 
1530         /* Right margin includes hsync */
 
1531         var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) -
 
1532                                            (hw->hdb & 0x200 ? 2 + hw->hht : 0));
 
1533         if (hw->ste_mode || mon_type != F_MON_VGA)
 
1534                 var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off;
 
1536                 /* can't use this in ste_mode, because hbb is +1 off */
 
1537                 var->right_margin = prescale * (hw->hht + 2 - hw->hbb);
 
1538         var->hsync_len = prescale * (hw->hht + 2 - hw->hss);
 
1540         /* Lower margin includes vsync */
 
1541         var->upper_margin = hw->vdb / 2;        /* round down to full lines */
 
1542         var->lower_margin = (hw->vft + 1 - hw->vde + 1) / 2;    /* round up */
 
1543         var->vsync_len = (hw->vft + 1 - hw->vss + 1) / 2;       /* round up */
 
1544         if (var->vmode & FB_VMODE_INTERLACED) {
 
1545                 var->upper_margin *= 2;
 
1546                 var->lower_margin *= 2;
 
1547                 var->vsync_len *= 2;
 
1548         } else if (var->vmode & FB_VMODE_DOUBLE) {
 
1549                 var->upper_margin = (var->upper_margin + 1) / 2;
 
1550                 var->lower_margin = (var->lower_margin + 1) / 2;
 
1551                 var->vsync_len = (var->vsync_len + 1) / 2;
 
1554         var->pixclock *= plen;
 
1555         var->left_margin /= plen;
 
1556         var->right_margin /= plen;
 
1557         var->hsync_len /= plen;
 
1559         var->right_margin -= var->hsync_len;
 
1560         var->lower_margin -= var->vsync_len;
 
1563                 var->yoffset = (par->screen_base - screen_base) / linelen;
 
1566         var->nonstd = 0;                /* what is this for? */
 
1571 static int f_change_mode;
 
1572 static struct falcon_hw f_new_mode;
 
1573 static int f_pan_display;
 
1575 static void falcon_get_par(struct atafb_par *par)
 
1578         struct falcon_hw *hw = &par->hw.falcon;
 
1580         hw->line_width = shifter_f030.scn_width;
 
1581         hw->line_offset = shifter_f030.off_next;
 
1582         hw->st_shift = videl.st_shift & 0x300;
 
1583         hw->f_shift = videl.f_shift;
 
1584         hw->vid_control = videl.control;
 
1585         hw->vid_mode = videl.mode;
 
1586         hw->sync = shifter.syncmode & 0x1;
 
1587         hw->xoffset = videl.xoffset & 0xf;
 
1588         hw->hht = videl.hht;
 
1589         hw->hbb = videl.hbb;
 
1590         hw->hbe = videl.hbe;
 
1591         hw->hdb = videl.hdb;
 
1592         hw->hde = videl.hde;
 
1593         hw->hss = videl.hss;
 
1594         hw->vft = videl.vft;
 
1595         hw->vbb = videl.vbb;
 
1596         hw->vbe = videl.vbe;
 
1597         hw->vdb = videl.vdb;
 
1598         hw->vde = videl.vde;
 
1599         hw->vss = videl.vss;
 
1601         addr = (shifter.bas_hi & 0xff) << 16 |
 
1602                (shifter.bas_md & 0xff) << 8  |
 
1603                (shifter.bas_lo & 0xff);
 
1604         par->screen_base = phys_to_virt(addr);
 
1606         /* derived parameters */
 
1607         hw->ste_mode = (hw->f_shift & 0x510) == 0 && hw->st_shift == 0x100;
 
1608         hw->mono = (hw->f_shift & 0x400) ||
 
1609                    ((hw->f_shift & 0x510) == 0 && hw->st_shift == 0x200);
 
1612 static void falcon_set_par(struct atafb_par *par)
 
1616         /* only set screen_base if really necessary */
 
1617         if (current_par.screen_base != par->screen_base)
 
1618                 fbhw->set_screen_base(par->screen_base);
 
1620         /* Don't touch any other registers if we keep the default resolution */
 
1624         /* Tell vbl-handler to change video mode.
 
1625          * We change modes only on next VBL, to avoid desynchronisation
 
1626          * (a shift to the right and wrap around by a random number of pixels
 
1627          * in all monochrome modes).
 
1628          * This seems to work on my Falcon.
 
1630         f_new_mode = par->hw.falcon;
 
1634 static irqreturn_t falcon_vbl_switcher(int irq, void *dummy)
 
1636         struct falcon_hw *hw = &f_new_mode;
 
1638         if (f_change_mode) {
 
1641                 if (hw->sync & 0x1) {
 
1642                         /* Enable external pixelclock. This code only for ScreenWonder */
 
1643                         *(volatile unsigned short *)0xffff9202 = 0xffbf;
 
1645                         /* Turn off external clocks. Read sets all output bits to 1. */
 
1646                         *(volatile unsigned short *)0xffff9202;
 
1648                 shifter.syncmode = hw->sync;
 
1650                 videl.hht = hw->hht;
 
1651                 videl.hbb = hw->hbb;
 
1652                 videl.hbe = hw->hbe;
 
1653                 videl.hdb = hw->hdb;
 
1654                 videl.hde = hw->hde;
 
1655                 videl.hss = hw->hss;
 
1656                 videl.vft = hw->vft;
 
1657                 videl.vbb = hw->vbb;
 
1658                 videl.vbe = hw->vbe;
 
1659                 videl.vdb = hw->vdb;
 
1660                 videl.vde = hw->vde;
 
1661                 videl.vss = hw->vss;
 
1663                 videl.f_shift = 0;      /* write enables Falcon palette, 0: 4 planes */
 
1665                         videl.st_shift = hw->st_shift;  /* write enables STE palette */
 
1668                          * set st_shift 0, so we can tell the screen-depth if f_shift == 0.
 
1669                          * Writing 0 to f_shift enables 4 plane Falcon mode but
 
1670                          * doesn't set st_shift. st_shift != 0 (!= 4planes) is impossible
 
1671                          * with Falcon palette.
 
1674                         /* now back to Falcon palette mode */
 
1675                         videl.f_shift = hw->f_shift;
 
1677                 /* writing to st_shift changed scn_width and vid_mode */
 
1678                 videl.xoffset = hw->xoffset;
 
1679                 shifter_f030.scn_width = hw->line_width;
 
1680                 shifter_f030.off_next = hw->line_offset;
 
1681                 videl.control = hw->vid_control;
 
1682                 videl.mode = hw->vid_mode;
 
1684         if (f_pan_display) {
 
1686                 videl.xoffset = current_par.hw.falcon.xoffset;
 
1687                 shifter_f030.off_next = current_par.hw.falcon.line_offset;
 
1692 static int falcon_pan_display(struct fb_var_screeninfo *var,
 
1693                               struct fb_info *info)
 
1695         struct atafb_par *par = (struct atafb_par *)info->par;
 
1698         int bpp = info->var.bits_per_pixel;
 
1701                 var->xoffset = up(var->xoffset, 32);
 
1703                 par->hw.falcon.xoffset = var->xoffset & 15;
 
1705                 par->hw.falcon.xoffset = 0;
 
1706                 var->xoffset = up(var->xoffset, 2);
 
1708         par->hw.falcon.line_offset = bpp *
 
1709                 (info->var.xres_virtual - info->var.xres) / 16;
 
1710         if (par->hw.falcon.xoffset)
 
1711                 par->hw.falcon.line_offset -= bpp;
 
1712         xoffset = var->xoffset - par->hw.falcon.xoffset;
 
1714         par->screen_base = screen_base +
 
1715                 (var->yoffset * info->var.xres_virtual + xoffset) * bpp / 8;
 
1716         if (fbhw->set_screen_base)
 
1717                 fbhw->set_screen_base(par->screen_base);
 
1719                 return -EINVAL;         /* shouldn't happen */
 
1724 static int falcon_setcolreg(unsigned int regno, unsigned int red,
 
1725                             unsigned int green, unsigned int blue,
 
1726                             unsigned int transp, struct fb_info *info)
 
1730         f030_col[regno] = (((red & 0xfc00) << 16) |
 
1731                            ((green & 0xfc00) << 8) |
 
1732                            ((blue & 0xfc00) >> 8));
 
1734                 shifter_tt.color_reg[regno] =
 
1735                         (((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
 
1736                         (((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
 
1737                         ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
 
1738 #ifdef FBCON_HAS_CFB16
 
1739                 fbcon_cfb16_cmap[regno] = ((red & 0xf800) |
 
1740                                            ((green & 0xfc00) >> 5) |
 
1741                                            ((blue & 0xf800) >> 11));
 
1747 static int falcon_blank(int blank_mode)
 
1749         /* ++guenther: we can switch off graphics by changing VDB and VDE,
 
1750          * so VIDEL doesn't hog the bus while saving.
 
1751          * (this may affect usleep()).
 
1753         int vdb, vss, hbe, hss;
 
1755         if (mon_type == F_MON_SM)       /* this doesn't work on SM124 */
 
1758         vdb = current_par.VDB;
 
1759         vss = current_par.VSS;
 
1760         hbe = current_par.HBE;
 
1761         hss = current_par.HSS;
 
1763         if (blank_mode >= 1) {
 
1764                 /* disable graphics output (this speeds up the CPU) ... */
 
1765                 vdb = current_par.VFT + 1;
 
1766                 /* ... and blank all lines */
 
1767                 hbe = current_par.HHT + 2;
 
1769         /* use VESA suspend modes on VGA monitors */
 
1770         if (mon_type == F_MON_VGA) {
 
1771                 if (blank_mode == 2 || blank_mode == 4)
 
1772                         vss = current_par.VFT + 1;
 
1773                 if (blank_mode == 3 || blank_mode == 4)
 
1774                         hss = current_par.HHT + 2;
 
1785 static int falcon_detect(void)
 
1787         struct atafb_par par;
 
1790         /* Determine connected monitor and set monitor parameters */
 
1791         fhw = *(unsigned char *)0xffff8006;
 
1792         mon_type = fhw >> 6 & 0x3;
 
1793         /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
 
1794         f030_bus_width = fhw << 6 & 0x80;
 
1797                 fb_info.monspecs.vfmin = 70;
 
1798                 fb_info.monspecs.vfmax = 72;
 
1799                 fb_info.monspecs.hfmin = 35713;
 
1800                 fb_info.monspecs.hfmax = 35715;
 
1805                 fb_info.monspecs.vfmin = 49;    /* not 50, since TOS defaults to 49.9x Hz */
 
1806                 fb_info.monspecs.vfmax = 60;
 
1807                 fb_info.monspecs.hfmin = 15620;
 
1808                 fb_info.monspecs.hfmax = 15755;
 
1811         /* initialize hsync-len */
 
1812         f25.hsync = h_syncs[mon_type] / f25.t;
 
1813         f32.hsync = h_syncs[mon_type] / f32.t;
 
1815                 fext.hsync = h_syncs[mon_type] / fext.t;
 
1817         falcon_get_par(&par);
 
1818         falcon_encode_var(&atafb_predefined[0], &par);
 
1820         /* Detected mode is always the "autodetect" slot */
 
1824 #endif /* ATAFB_FALCON */
 
1826 /* ------------------- ST(E) specific functions ---------------------- */
 
1830 static int stste_encode_fix(struct fb_fix_screeninfo *fix,
 
1831                             struct atafb_par *par)
 
1835         strcpy(fix->id, "Atari Builtin");
 
1836         fix->smem_start = (unsigned long)real_screen_base;
 
1837         fix->smem_len = screen_len;
 
1838         fix->type = FB_TYPE_INTERLEAVED_PLANES;
 
1840         fix->visual = FB_VISUAL_PSEUDOCOLOR;
 
1841         mode = par->hw.st.mode & 3;
 
1842         if (mode == ST_HIGH) {
 
1843                 fix->type = FB_TYPE_PACKED_PIXELS;
 
1845                 fix->visual = FB_VISUAL_MONO10;
 
1847         if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
 
1855         fix->line_length = 0;
 
1856         fix->accel = FB_ACCEL_ATARIBLITT;
 
1860 static int stste_decode_var(struct fb_var_screeninfo *var,
 
1861                             struct atafb_par *par)
 
1863         int xres = var->xres;
 
1864         int yres = var->yres;
 
1865         int bpp = var->bits_per_pixel;
 
1867         int yres_virtual = var->yres_virtual;
 
1870                 if (bpp > 1 || xres > sttt_xres || yres > st_yres)
 
1872                 par->hw.st.mode = ST_HIGH;
 
1877                 if (bpp > 4 || xres > sttt_xres || yres > st_yres)
 
1880                         if (xres > sttt_xres / 2 || yres > st_yres / 2)
 
1882                         par->hw.st.mode = ST_LOW;
 
1883                         xres = sttt_xres / 2;
 
1886                 } else if (bpp > 1) {
 
1887                         if (xres > sttt_xres || yres > st_yres / 2)
 
1889                         par->hw.st.mode = ST_MID;
 
1896         if (yres_virtual <= 0)
 
1898         else if (yres_virtual < yres)
 
1899                 yres_virtual = yres;
 
1900         if (var->sync & FB_SYNC_EXT)
 
1901                 par->hw.st.sync = (par->hw.st.sync & ~1) | 1;
 
1903                 par->hw.st.sync = (par->hw.st.sync & ~1);
 
1904         linelen = xres * bpp / 8;
 
1905         if (yres_virtual * linelen > screen_len && screen_len)
 
1907         if (yres * linelen > screen_len && screen_len)
 
1909         if (var->yoffset + yres > yres_virtual && yres_virtual)
 
1911         par->yres_virtual = yres_virtual;
 
1912         par->screen_base = screen_base + var->yoffset * linelen;
 
1916 static int stste_encode_var(struct fb_var_screeninfo *var,
 
1917                             struct atafb_par *par)
 
1920         memset(var, 0, sizeof(struct fb_var_screeninfo));
 
1921         var->red.offset = 0;
 
1922         var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
 
1923         var->red.msb_right = 0;
 
1926         var->pixclock = 31041;
 
1927         var->left_margin = 120;         /* these are incorrect */
 
1928         var->right_margin = 100;
 
1929         var->upper_margin = 8;
 
1930         var->lower_margin = 16;
 
1931         var->hsync_len = 140;
 
1932         var->vsync_len = 30;
 
1937         if (!(par->hw.st.sync & 1))
 
1940                 var->sync = FB_SYNC_EXT;
 
1942         switch (par->hw.st.mode & 3) {
 
1944                 var->xres = sttt_xres / 2;
 
1945                 var->yres = st_yres / 2;
 
1946                 var->bits_per_pixel = 4;
 
1949                 var->xres = sttt_xres;
 
1950                 var->yres = st_yres / 2;
 
1951                 var->bits_per_pixel = 2;
 
1954                 var->xres = sttt_xres;
 
1955                 var->yres = st_yres;
 
1956                 var->bits_per_pixel = 1;
 
1959         var->blue = var->green = var->red;
 
1960         var->transp.offset = 0;
 
1961         var->transp.length = 0;
 
1962         var->transp.msb_right = 0;
 
1963         var->xres_virtual = sttt_xres_virtual;
 
1964         linelen = var->xres_virtual * var->bits_per_pixel / 8;
 
1965         ovsc_addlen = linelen * (sttt_yres_virtual - st_yres);
 
1968                 var->yres_virtual = var->yres;
 
1969         else if (screen_len) {
 
1970                 if (par->yres_virtual)
 
1971                         var->yres_virtual = par->yres_virtual;
 
1973                         /* yres_virtual == 0 means use maximum */
 
1974                         var->yres_virtual = screen_len / linelen;
 
1977                         var->yres_virtual = 2 * var->yres;
 
1979                         var->yres_virtual = var->yres + hwscroll * 16;
 
1983                 var->yoffset = (par->screen_base - screen_base) / linelen;
 
1988         var->vmode = FB_VMODE_NONINTERLACED;
 
1992 static void stste_get_par(struct atafb_par *par)
 
1995         par->hw.st.mode = shifter_tt.st_shiftmode;
 
1996         par->hw.st.sync = shifter.syncmode;
 
1997         addr = ((shifter.bas_hi & 0xff) << 16) |
 
1998                ((shifter.bas_md & 0xff) << 8);
 
1999         if (ATARIHW_PRESENT(EXTD_SHIFTER))
 
2000                 addr |= (shifter.bas_lo & 0xff);
 
2001         par->screen_base = phys_to_virt(addr);
 
2004 static void stste_set_par(struct atafb_par *par)
 
2006         shifter_tt.st_shiftmode = par->hw.st.mode;
 
2007         shifter.syncmode = par->hw.st.sync;
 
2008         /* only set screen_base if really necessary */
 
2009         if (current_par.screen_base != par->screen_base)
 
2010                 fbhw->set_screen_base(par->screen_base);
 
2013 static int stste_setcolreg(unsigned int regno, unsigned int red,
 
2014                            unsigned int green, unsigned int blue,
 
2015                            unsigned int transp, struct fb_info *info)
 
2022         if (ATARIHW_PRESENT(EXTD_SHIFTER))
 
2023                 shifter_tt.color_reg[regno] =
 
2024                         (((red & 0xe) >> 1) | ((red & 1) << 3) << 8) |
 
2025                         (((green & 0xe) >> 1) | ((green & 1) << 3) << 4) |
 
2026                         ((blue & 0xe) >> 1) | ((blue & 1) << 3);
 
2028                 shifter_tt.color_reg[regno] =
 
2029                         ((red & 0xe) << 7) |
 
2030                         ((green & 0xe) << 3) |
 
2031                         ((blue & 0xe) >> 1);
 
2035 static int stste_detect(void)
 
2037         struct atafb_par par;
 
2039         /* Determine the connected monitor: The DMA sound must be
 
2040          * disabled before reading the MFP GPIP, because the Sound
 
2041          * Done Signal and the Monochrome Detect are XORed together!
 
2043         if (ATARIHW_PRESENT(PCM_8BIT)) {
 
2044                 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
 
2045                 udelay(20);             /* wait a while for things to settle down */
 
2047         mono_moni = (mfp.par_dt_reg & 0x80) == 0;
 
2049         stste_get_par(&par);
 
2050         stste_encode_var(&atafb_predefined[0], &par);
 
2052         if (!ATARIHW_PRESENT(EXTD_SHIFTER))
 
2057 static void stste_set_screen_base(void *s_base)
 
2060         addr = virt_to_phys(s_base);
 
2061         /* Setup Screen Memory */
 
2062         shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
 
2063         shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
 
2064         if (ATARIHW_PRESENT(EXTD_SHIFTER))
 
2065                 shifter.bas_lo = (unsigned char)(addr & 0x0000ff);
 
2068 #endif /* ATAFB_STE */
 
2070 /* Switching the screen size should be done during vsync, otherwise
 
2071  * the margins may get messed up. This is a well known problem of
 
2072  * the ST's video system.
 
2074  * Unfortunately there is hardly any way to find the vsync, as the
 
2075  * vertical blank interrupt is no longer in time on machines with
 
2076  * overscan type modifications.
 
2078  * We can, however, use Timer B to safely detect the black shoulder,
 
2079  * but then we've got to guess an appropriate delay to find the vsync.
 
2080  * This might not work on every machine.
 
2082  * martin_rogge @ ki.maus.de, 8th Aug 1995
 
2085 #define LINE_DELAY  (mono_moni ? 30 : 70)
 
2086 #define SYNC_DELAY  (mono_moni ? 1500 : 2000)
 
2088 /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
 
2089 static void st_ovsc_switch(void)
 
2091         unsigned long flags;
 
2092         register unsigned char old, new;
 
2094         if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
 
2096         local_irq_save(flags);
 
2098         mfp.tim_ct_b = 0x10;
 
2099         mfp.active_edge |= 8;
 
2101         mfp.tim_dt_b = 0xf0;
 
2103         while (mfp.tim_dt_b > 1)        /* TOS does it this way, don't ask why */
 
2110         } while (old != new);
 
2111         mfp.tim_ct_b = 0x10;
 
2114         if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
 
2115                 acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
 
2116         if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
 
2117                 acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
 
2118         if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
 
2119                 sound_ym.rd_data_reg_sel = 14;
 
2120                 sound_ym.wd_data = sound_ym.rd_data_reg_sel |
 
2121                                    ((atari_switches & ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
 
2122                                    ((atari_switches & ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
 
2124         local_irq_restore(flags);
 
2127 /* ------------------- External Video ---------------------- */
 
2131 static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
 
2133         strcpy(fix->id, "Unknown Extern");
 
2134         fix->smem_start = (unsigned long)external_addr;
 
2135         fix->smem_len = PAGE_ALIGN(external_len);
 
2136         if (external_depth == 1) {
 
2137                 fix->type = FB_TYPE_PACKED_PIXELS;
 
2138                 /* The letters 'n' and 'i' in the "atavideo=external:" stand
 
2139                  * for "normal" and "inverted", rsp., in the monochrome case */
 
2141                         (external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
 
2142                          external_pmode == FB_TYPE_PACKED_PIXELS) ?
 
2143                                 FB_VISUAL_MONO10 : FB_VISUAL_MONO01;
 
2145                 /* Use STATIC if we don't know how to access color registers */
 
2146                 int visual = external_vgaiobase ?
 
2147                                          FB_VISUAL_PSEUDOCOLOR :
 
2148                                          FB_VISUAL_STATIC_PSEUDOCOLOR;
 
2149                 switch (external_pmode) {
 
2150                 case -1:                /* truecolor */
 
2151                         fix->type = FB_TYPE_PACKED_PIXELS;
 
2152                         fix->visual = FB_VISUAL_TRUECOLOR;
 
2154                 case FB_TYPE_PACKED_PIXELS:
 
2155                         fix->type = FB_TYPE_PACKED_PIXELS;
 
2156                         fix->visual = visual;
 
2158                 case FB_TYPE_PLANES:
 
2159                         fix->type = FB_TYPE_PLANES;
 
2160                         fix->visual = visual;
 
2162                 case FB_TYPE_INTERLEAVED_PLANES:
 
2163                         fix->type = FB_TYPE_INTERLEAVED_PLANES;
 
2165                         fix->visual = visual;
 
2172         fix->line_length = 0;
 
2176 static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
 
2178         struct fb_var_screeninfo *myvar = &atafb_predefined[0];
 
2180         if (var->bits_per_pixel > myvar->bits_per_pixel ||
 
2181             var->xres > myvar->xres ||
 
2182             var->xres_virtual > myvar->xres_virtual ||
 
2183             var->yres > myvar->yres ||
 
2190 static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
 
2192         memset(var, 0, sizeof(struct fb_var_screeninfo));
 
2193         var->red.offset = 0;
 
2194         var->red.length = (external_pmode == -1) ? external_depth / 3 :
 
2195                         (external_vgaiobase ? external_bitspercol : 0);
 
2196         var->red.msb_right = 0;
 
2199         var->pixclock = 31041;
 
2200         var->left_margin = 120;         /* these are surely incorrect */
 
2201         var->right_margin = 100;
 
2202         var->upper_margin = 8;
 
2203         var->lower_margin = 16;
 
2204         var->hsync_len = 140;
 
2205         var->vsync_len = 30;
 
2212         var->xres = external_xres;
 
2213         var->yres = external_yres;
 
2214         var->xres_virtual = external_xres_virtual;
 
2215         var->bits_per_pixel = external_depth;
 
2217         var->blue = var->green = var->red;
 
2218         var->transp.offset = 0;
 
2219         var->transp.length = 0;
 
2220         var->transp.msb_right = 0;
 
2221         var->yres_virtual = var->yres;
 
2226         var->vmode = FB_VMODE_NONINTERLACED;
 
2230 static void ext_get_par(struct atafb_par *par)
 
2232         par->screen_base = external_addr;
 
2235 static void ext_set_par(struct atafb_par *par)
 
2239 #define OUTB(port,val) \
 
2240         *((unsigned volatile char *) ((port)+external_vgaiobase)) = (val)
 
2242         (*((unsigned volatile char *) ((port)+external_vgaiobase)))
 
2245                 unsigned char tmp = INB(0x3da); \
 
2249 static int ext_setcolreg(unsigned int regno, unsigned int red,
 
2250                          unsigned int green, unsigned int blue,
 
2251                          unsigned int transp, struct fb_info *info)
 
2253         unsigned char colmask = (1 << external_bitspercol) - 1;
 
2255         if (!external_vgaiobase)
 
2258         switch (external_card_type) {
 
2262                 OUTB(0x3c9, red & colmask);
 
2264                 OUTB(0x3c9, green & colmask);
 
2266                 OUTB(0x3c9, blue & colmask);
 
2271                 OUTB((MV300_reg[regno] << 2) + 1, red);
 
2272                 OUTB((MV300_reg[regno] << 2) + 1, green);
 
2273                 OUTB((MV300_reg[regno] << 2) + 1, blue);
 
2281 static int ext_detect(void)
 
2283         struct fb_var_screeninfo *myvar = &atafb_predefined[0];
 
2284         struct atafb_par dummy_par;
 
2286         myvar->xres = external_xres;
 
2287         myvar->xres_virtual = external_xres_virtual;
 
2288         myvar->yres = external_yres;
 
2289         myvar->bits_per_pixel = external_depth;
 
2290         ext_encode_var(myvar, &dummy_par);
 
2294 #endif /* ATAFB_EXT */
 
2296 /* ------ This is the same for most hardware types -------- */
 
2298 static void set_screen_base(void *s_base)
 
2302         addr = virt_to_phys(s_base);
 
2303         /* Setup Screen Memory */
 
2304         shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
 
2305         shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
 
2306         shifter.bas_lo = (unsigned char)(addr & 0x0000ff);
 
2309 static int pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
 
2311         struct atafb_par *par = (struct atafb_par *)info->par;
 
2313         if (!fbhw->set_screen_base ||
 
2314             (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
 
2316         var->xoffset = up(var->xoffset, 16);
 
2317         par->screen_base = screen_base +
 
2318                 (var->yoffset * info->var.xres_virtual + var->xoffset)
 
2319                 * info->var.bits_per_pixel / 8;
 
2320         fbhw->set_screen_base(par->screen_base);
 
2324 /* ------------ Interfaces to hardware functions ------------ */
 
2327 static struct fb_hwswitch tt_switch = {
 
2328         .detect         = tt_detect,
 
2329         .encode_fix     = tt_encode_fix,
 
2330         .decode_var     = tt_decode_var,
 
2331         .encode_var     = tt_encode_var,
 
2332         .get_par        = tt_get_par,
 
2333         .set_par        = tt_set_par,
 
2334         .set_screen_base = set_screen_base,
 
2335         .pan_display    = pan_display,
 
2340 static struct fb_hwswitch falcon_switch = {
 
2341         .detect         = falcon_detect,
 
2342         .encode_fix     = falcon_encode_fix,
 
2343         .decode_var     = falcon_decode_var,
 
2344         .encode_var     = falcon_encode_var,
 
2345         .get_par        = falcon_get_par,
 
2346         .set_par        = falcon_set_par,
 
2347         .set_screen_base = set_screen_base,
 
2348         .blank          = falcon_blank,
 
2349         .pan_display    = falcon_pan_display,
 
2354 static struct fb_hwswitch st_switch = {
 
2355         .detect         = stste_detect,
 
2356         .encode_fix     = stste_encode_fix,
 
2357         .decode_var     = stste_decode_var,
 
2358         .encode_var     = stste_encode_var,
 
2359         .get_par        = stste_get_par,
 
2360         .set_par        = stste_set_par,
 
2361         .set_screen_base = stste_set_screen_base,
 
2362         .pan_display    = pan_display
 
2367 static struct fb_hwswitch ext_switch = {
 
2368         .detect         = ext_detect,
 
2369         .encode_fix     = ext_encode_fix,
 
2370         .decode_var     = ext_decode_var,
 
2371         .encode_var     = ext_encode_var,
 
2372         .get_par        = ext_get_par,
 
2373         .set_par        = ext_set_par,
 
2377 static void ata_get_par(struct atafb_par *par)
 
2379         if (current_par_valid)
 
2385 static void ata_set_par(struct atafb_par *par)
 
2389         current_par_valid = 1;
 
2393 /* =========================================================== */
 
2394 /* ============== Hardware Independent Functions ============= */
 
2395 /* =========================================================== */
 
2397 /* used for hardware scrolling */
 
2399 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
 
2402         struct atafb_par par;
 
2404         err = fbhw->decode_var(var, &par);
 
2407         activate = var->activate;
 
2408         if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
 
2410         fbhw->encode_var(var, &par);
 
2411         var->activate = activate;
 
2415 static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
 
2417         struct atafb_par par;
 
2419         // Get fix directly (case con == -1 before)??
 
2420         err = fbhw->decode_var(&info->var, &par);
 
2423         memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 
2424         return fbhw->encode_fix(fix, &par);
 
2427 static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info)
 
2429         struct atafb_par par;
 
2432         fbhw->encode_var(var, &par);
 
2437 // No longer called by fbcon!
 
2438 // Still called by set_var internally
 
2440 static void atafb_set_disp(struct fb_info *info)
 
2442         atafb_get_var(&info->var, info);
 
2443         atafb_get_fix(&info->fix, info);
 
2445         info->screen_base = (void *)info->fix.smem_start;
 
2447         switch (info->fix.type) {
 
2448         case FB_TYPE_INTERLEAVED_PLANES:
 
2449                 switch (info->var.bits_per_pixel) {
 
2451                         // display->dispsw = &fbcon_iplan2p2;
 
2454                         // display->dispsw = &fbcon_iplan2p4;
 
2457                         // display->dispsw = &fbcon_iplan2p8;
 
2461         case FB_TYPE_PACKED_PIXELS:
 
2462                 switch (info->var.bits_per_pixel) {
 
2463 #ifdef FBCON_HAS_MFB
 
2465                         // display->dispsw = &fbcon_mfb;
 
2468 #ifdef FBCON_HAS_CFB8
 
2470                         // display->dispsw = &fbcon_cfb8;
 
2473 #ifdef FBCON_HAS_CFB16
 
2475                         // display->dispsw = &fbcon_cfb16;
 
2476                         // display->dispsw_data = fbcon_cfb16_cmap;
 
2484 static int atafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 
2485                            u_int transp, struct fb_info *info)
 
2491         return info->fbops->fb_setcolreg(regno, red, green, blue, transp, info);
 
2495 atafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
 
2497         int xoffset = var->xoffset;
 
2498         int yoffset = var->yoffset;
 
2501         if (var->vmode & FB_VMODE_YWRAP) {
 
2502                 if (yoffset < 0 || yoffset >= info->var.yres_virtual || xoffset)
 
2505                 if (xoffset + info->var.xres > info->var.xres_virtual ||
 
2506                     yoffset + info->var.yres > info->var.yres_virtual)
 
2510         if (fbhw->pan_display) {
 
2511                 err = fbhw->pan_display(var, info);
 
2517         info->var.xoffset = xoffset;
 
2518         info->var.yoffset = yoffset;
 
2520         if (var->vmode & FB_VMODE_YWRAP)
 
2521                 info->var.vmode |= FB_VMODE_YWRAP;
 
2523                 info->var.vmode &= ~FB_VMODE_YWRAP;
 
2529  * generic drawing routines; imageblit needs updating for image depth > 1
 
2532 #if BITS_PER_LONG == 32
 
2533 #define BYTES_PER_LONG  4
 
2534 #define SHIFT_PER_LONG  5
 
2535 #elif BITS_PER_LONG == 64
 
2536 #define BYTES_PER_LONG  8
 
2537 #define SHIFT_PER_LONG  6
 
2539 #define Please update me
 
2543 static void atafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 
2545         struct atafb_par *par = (struct atafb_par *)info->par;
 
2549         if (!rect->width || !rect->height)
 
2553          * We could use hardware clipping but on many cards you get around
 
2554          * hardware clipping by writing to framebuffer directly.
 
2556         x2 = rect->dx + rect->width;
 
2557         y2 = rect->dy + rect->height;
 
2558         x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
 
2559         y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
 
2560         width = x2 - rect->dx;
 
2561         height = y2 - rect->dy;
 
2563         if (info->var.bits_per_pixel == 1)
 
2564                 atafb_mfb_fillrect(info, par->next_line, rect->color,
 
2565                                    rect->dy, rect->dx, height, width);
 
2566         else if (info->var.bits_per_pixel == 2)
 
2567                 atafb_iplan2p2_fillrect(info, par->next_line, rect->color,
 
2568                                         rect->dy, rect->dx, height, width);
 
2569         else if (info->var.bits_per_pixel == 4)
 
2570                 atafb_iplan2p4_fillrect(info, par->next_line, rect->color,
 
2571                                         rect->dy, rect->dx, height, width);
 
2573                 atafb_iplan2p8_fillrect(info, par->next_line, rect->color,
 
2574                                         rect->dy, rect->dx, height, width);
 
2579 static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 
2581         struct atafb_par *par = (struct atafb_par *)info->par;
 
2583         u32 dx, dy, sx, sy, width, height;
 
2586         /* clip the destination */
 
2587         x2 = area->dx + area->width;
 
2588         y2 = area->dy + area->height;
 
2589         dx = area->dx > 0 ? area->dx : 0;
 
2590         dy = area->dy > 0 ? area->dy : 0;
 
2591         x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
 
2592         y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
 
2597         sx = area->sx + (dx - area->dx);
 
2598         sy = area->sy + (dy - area->dy);
 
2600         /* the source must be completely inside the virtual screen */
 
2601         if (sx < 0 || sy < 0 || (sx + width) > info->var.xres_virtual ||
 
2602             (sy + height) > info->var.yres_virtual)
 
2605         if (dy > sy || (dy == sy && dx > sx)) {
 
2611         if (info->var.bits_per_pixel == 1)
 
2612                 atafb_mfb_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
 
2613         else if (info->var.bits_per_pixel == 2)
 
2614                 atafb_iplan2p2_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
 
2615         else if (info->var.bits_per_pixel == 4)
 
2616                 atafb_iplan2p4_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
 
2618                 atafb_iplan2p8_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
 
2623 static void atafb_imageblit(struct fb_info *info, const struct fb_image *image)
 
2625         struct atafb_par *par = (struct atafb_par *)info->par;
 
2630         u32 dx, dy, width, height, pitch;
 
2633          * We could use hardware clipping but on many cards you get around
 
2634          * hardware clipping by writing to framebuffer directly like we are
 
2637         x2 = image->dx + image->width;
 
2638         y2 = image->dy + image->height;
 
2641         x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
 
2642         y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
 
2646         if (image->depth == 1) {
 
2647                 // used for font data
 
2648                 dst = (unsigned long *)
 
2649                         ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
 
2650                 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
 
2651                 dst_idx += dy * par->next_line * 8 + dx;
 
2653                 pitch = (image->width + 7) / 8;
 
2656                         if (info->var.bits_per_pixel == 1)
 
2657                                 atafb_mfb_linefill(info, par->next_line,
 
2659                                                    image->bg_color, image->fg_color);
 
2660                         else if (info->var.bits_per_pixel == 2)
 
2661                                 atafb_iplan2p2_linefill(info, par->next_line,
 
2663                                                         image->bg_color, image->fg_color);
 
2664                         else if (info->var.bits_per_pixel == 4)
 
2665                                 atafb_iplan2p4_linefill(info, par->next_line,
 
2667                                                         image->bg_color, image->fg_color);
 
2669                                 atafb_iplan2p8_linefill(info, par->next_line,
 
2671                                                         image->bg_color, image->fg_color);
 
2676                 // only used for logo; broken
 
2677                 c2p(info->screen_base, image->data, dx, dy, width, height,
 
2678                     par->next_line, par->next_plane, image->width,
 
2679                     info->var.bits_per_pixel);
 
2684 atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
 
2687 #ifdef FBCMD_GET_CURRENTPAR
 
2688         case FBCMD_GET_CURRENTPAR:
 
2689                 if (copy_to_user((void *)arg, (void *)¤t_par,
 
2690                                  sizeof(struct atafb_par)))
 
2694 #ifdef FBCMD_SET_CURRENTPAR
 
2695         case FBCMD_SET_CURRENTPAR:
 
2696                 if (copy_from_user((void *)¤t_par, (void *)arg,
 
2697                                    sizeof(struct atafb_par)))
 
2699                 ata_set_par(¤t_par);
 
2706 /* (un)blank/poweroff
 
2713 static int atafb_blank(int blank, struct fb_info *info)
 
2715         unsigned short black[16];
 
2716         struct fb_cmap cmap;
 
2717         if (fbhw->blank && !fbhw->blank(blank))
 
2720                 memset(black, 0, 16 * sizeof(unsigned short));
 
2727                 fb_set_cmap(&cmap, info);
 
2731                 do_install_cmap(info);
 
2737          * New fbcon interface ...
 
2740          /* check var by decoding var into hw par, rounding if necessary,
 
2741           * then encoding hw par back into new, validated var */
 
2742 static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 
2745         struct atafb_par par;
 
2747         /* Validate wanted screen parameters */
 
2748         // if ((err = ata_decode_var(var, &par)))
 
2749         err = fbhw->decode_var(var, &par);
 
2753         /* Encode (possibly rounded) screen parameters */
 
2754         fbhw->encode_var(var, &par);
 
2758         /* actually set hw par by decoding var, then setting hardware from
 
2759          * hw par just decoded */
 
2760 static int atafb_set_par(struct fb_info *info)
 
2762         struct atafb_par *par = (struct atafb_par *)info->par;
 
2764         /* Decode wanted screen parameters */
 
2765         fbhw->decode_var(&info->var, par);
 
2766         fbhw->encode_fix(&info->fix, par);
 
2768         /* Set new videomode */
 
2775 static struct fb_ops atafb_ops = {
 
2776         .owner =        THIS_MODULE,
 
2777         .fb_check_var   = atafb_check_var,
 
2778         .fb_set_par     = atafb_set_par,
 
2779         .fb_setcolreg   = atafb_setcolreg,
 
2780         .fb_blank =     atafb_blank,
 
2781         .fb_pan_display = atafb_pan_display,
 
2782         .fb_fillrect    = atafb_fillrect,
 
2783         .fb_copyarea    = atafb_copyarea,
 
2784         .fb_imageblit   = atafb_imageblit,
 
2785         .fb_ioctl =     atafb_ioctl,
 
2788 static void check_default_par(int detected_mode)
 
2790         char default_name[10];
 
2792         struct fb_var_screeninfo var;
 
2793         unsigned long min_mem;
 
2795         /* First try the user supplied mode */
 
2797                 var = atafb_predefined[default_par - 1];
 
2798                 var.activate = FB_ACTIVATE_TEST;
 
2799                 if (do_fb_set_var(&var, 1))
 
2800                         default_par = 0;        /* failed */
 
2802         /* Next is the autodetected one */
 
2804                 var = atafb_predefined[detected_mode - 1]; /* autodetect */
 
2805                 var.activate = FB_ACTIVATE_TEST;
 
2806                 if (!do_fb_set_var(&var, 1))
 
2807                         default_par = detected_mode;
 
2809         /* If that also failed, try some default modes... */
 
2811                 /* try default1, default2... */
 
2812                 for (i = 1; i < 10; i++) {
 
2813                         sprintf(default_name,"default%d", i);
 
2814                         default_par = get_video_mode(default_name);
 
2816                                 panic("can't set default video mode");
 
2817                         var = atafb_predefined[default_par - 1];
 
2818                         var.activate = FB_ACTIVATE_TEST;
 
2819                         if (!do_fb_set_var(&var,1))
 
2823         min_mem = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8;
 
2824         if (default_mem_req < min_mem)
 
2825                 default_mem_req = min_mem;
 
2829 static void __init atafb_setup_ext(char *spec)
 
2831         int xres, xres_virtual, yres, depth, planes;
 
2832         unsigned long addr, len;
 
2835         /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
 
2837          *            [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
 
2838          *            [;<xres-virtual>]]]]]
 
2841          * <xres_virtual>:      hardware's x-resolution (f.e. ProMST)
 
2843          * Even xres_virtual is available, we neither support panning nor hw-scrolling!
 
2845         p = strsep(&spec, ";");
 
2848         xres_virtual = xres = simple_strtoul(p, NULL, 10);
 
2852         p = strsep(&spec, ";");
 
2855         yres = simple_strtoul(p, NULL, 10);
 
2859         p = strsep(&spec, ";");
 
2862         depth = simple_strtoul(p, NULL, 10);
 
2863         if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
 
2864             depth != 16 && depth != 24)
 
2867         p = strsep(&spec, ";");
 
2871                 planes = FB_TYPE_INTERLEAVED_PLANES;
 
2873                 planes = FB_TYPE_PACKED_PIXELS;
 
2875                 planes = FB_TYPE_PLANES;
 
2877                 planes = -1;            /* true color */
 
2881         p = strsep(&spec, ";");
 
2884         addr = simple_strtoul(p, NULL, 0);
 
2886         p = strsep(&spec, ";");
 
2888                 len = xres * yres * depth / 8;
 
2890                 len = simple_strtoul(p, NULL, 0);
 
2892         p = strsep(&spec, ";");
 
2894                 external_vgaiobase = simple_strtoul(p, NULL, 0);
 
2896         p = strsep(&spec, ";");
 
2898                 external_bitspercol = simple_strtoul(p, NULL, 0);
 
2899                 if (external_bitspercol > 8)
 
2900                         external_bitspercol = 8;
 
2901                 else if (external_bitspercol < 1)
 
2902                         external_bitspercol = 1;
 
2905         p = strsep(&spec, ";");
 
2907                 if (!strcmp(p, "vga"))
 
2908                         external_card_type = IS_VGA;
 
2909                 if (!strcmp(p, "mv300"))
 
2910                         external_card_type = IS_MV300;
 
2913         p = strsep(&spec, ";");
 
2915                 xres_virtual = simple_strtoul(p, NULL, 10);
 
2916                 if (xres_virtual < xres)
 
2917                         xres_virtual = xres;
 
2918                 if (xres_virtual * yres * depth / 8 > len)
 
2919                         len = xres_virtual * yres * depth / 8;
 
2922         external_xres = xres;
 
2923         external_xres_virtual = xres_virtual;
 
2924         external_yres = yres;
 
2925         external_depth = depth;
 
2926         external_pmode = planes;
 
2927         external_addr = (void *)addr;
 
2930         if (external_card_type == IS_MV300) {
 
2931                 switch (external_depth) {
 
2933                         MV300_reg = MV300_reg_1bit;
 
2936                         MV300_reg = MV300_reg_4bit;
 
2939                         MV300_reg = MV300_reg_8bit;
 
2944 #endif /* ATAFB_EXT */
 
2946 static void __init atafb_setup_int(char *spec)
 
2948         /* Format to config extended internal video hardware like OverScan:
 
2949          * "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
 
2951          * <xres>: x-resolution
 
2952          * <yres>: y-resolution
 
2953          * The following are only needed if you have an overscan which
 
2954          * needs a black border:
 
2955          * <xres_max>: max. length of a line in pixels your OverScan hardware would allow
 
2956          * <yres_max>: max. number of lines your OverScan hardware would allow
 
2957          * <offset>: Offset from physical beginning to visible beginning
 
2958          *        of screen in bytes
 
2963         if (!(p = strsep(&spec, ";")) || !*p)
 
2965         xres = simple_strtoul(p, NULL, 10);
 
2966         if (!(p = strsep(&spec, ";")) || !*p)
 
2969         tt_yres = st_yres = simple_strtoul(p, NULL, 10);
 
2970         if ((p = strsep(&spec, ";")) && *p)
 
2971                 sttt_xres_virtual = simple_strtoul(p, NULL, 10);
 
2972         if ((p = strsep(&spec, ";")) && *p)
 
2973                 sttt_yres_virtual = simple_strtoul(p, NULL, 0);
 
2974         if ((p = strsep(&spec, ";")) && *p)
 
2975                 ovsc_offset = simple_strtoul(p, NULL, 0);
 
2977         if (ovsc_offset || (sttt_yres_virtual != st_yres))
 
2982 static void __init atafb_setup_mcap(char *spec)
 
2985         int vmin, vmax, hmin, hmax;
 
2987         /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
 
2988          * <V*> vertical freq. in Hz
 
2989          * <H*> horizontal freq. in kHz
 
2991         if (!(p = strsep(&spec, ";")) || !*p)
 
2993         vmin = simple_strtoul(p, NULL, 10);
 
2996         if (!(p = strsep(&spec, ";")) || !*p)
 
2998         vmax = simple_strtoul(p, NULL, 10);
 
2999         if (vmax <= 0 || vmax <= vmin)
 
3001         if (!(p = strsep(&spec, ";")) || !*p)
 
3003         hmin = 1000 * simple_strtoul(p, NULL, 10);
 
3006         if (!(p = strsep(&spec, "")) || !*p)
 
3008         hmax = 1000 * simple_strtoul(p, NULL, 10);
 
3009         if (hmax <= 0 || hmax <= hmin)
 
3012         fb_info.monspecs.vfmin = vmin;
 
3013         fb_info.monspecs.vfmax = vmax;
 
3014         fb_info.monspecs.hfmin = hmin;
 
3015         fb_info.monspecs.hfmax = hmax;
 
3017 #endif /* ATAFB_FALCON */
 
3019 static void __init atafb_setup_user(char *spec)
 
3021         /* Format of user defined video mode is: <xres>;<yres>;<depth>
 
3024         int xres, yres, depth, temp;
 
3026         p = strsep(&spec, ";");
 
3029         xres = simple_strtoul(p, NULL, 10);
 
3030         p = strsep(&spec, ";");
 
3033         yres = simple_strtoul(p, NULL, 10);
 
3034         p = strsep(&spec, "");
 
3037         depth = simple_strtoul(p, NULL, 10);
 
3038         temp = get_video_mode("user0");
 
3041                 atafb_predefined[default_par - 1].xres = xres;
 
3042                 atafb_predefined[default_par - 1].yres = yres;
 
3043                 atafb_predefined[default_par - 1].bits_per_pixel = depth;
 
3047 int __init atafb_setup(char *options)
 
3052         if (!options || !*options)
 
3055         while ((this_opt = strsep(&options, ",")) != NULL) {
 
3058                 if ((temp = get_video_mode(this_opt))) {
 
3060                         mode_option = this_opt;
 
3061                 } else if (!strcmp(this_opt, "inverse"))
 
3063                 else if (!strncmp(this_opt, "hwscroll_", 9)) {
 
3064                         hwscroll = simple_strtoul(this_opt + 9, NULL, 10);
 
3071                 else if (!strcmp(this_opt, "mv300")) {
 
3072                         external_bitspercol = 8;
 
3073                         external_card_type = IS_MV300;
 
3074                 } else if (!strncmp(this_opt, "external:", 9))
 
3075                         atafb_setup_ext(this_opt + 9);
 
3077                 else if (!strncmp(this_opt, "internal:", 9))
 
3078                         atafb_setup_int(this_opt + 9);
 
3080                 else if (!strncmp(this_opt, "eclock:", 7)) {
 
3081                         fext.f = simple_strtoul(this_opt + 7, NULL, 10);
 
3082                         /* external pixelclock in kHz --> ps */
 
3083                         fext.t = 1000000000 / fext.f;
 
3085                 } else if (!strncmp(this_opt, "monitorcap:", 11))
 
3086                         atafb_setup_mcap(this_opt + 11);
 
3088                 else if (!strcmp(this_opt, "keep"))
 
3090                 else if (!strncmp(this_opt, "R", 1))
 
3091                         atafb_setup_user(this_opt + 1);
 
3096 int __init atafb_init(void)
 
3100         unsigned int defmode = 0;
 
3101         unsigned long mem_req;
 
3104         char *option = NULL;
 
3106         if (fb_get_options("atafb", &option))
 
3108         atafb_setup(option);
 
3110         printk("atafb_init: start\n");
 
3117                 if (external_addr) {
 
3118                         printk("atafb_init: initializing external hw\n");
 
3120                         atafb_ops.fb_setcolreg = &ext_setcolreg;
 
3121                         defmode = DEFMODE_EXT;
 
3126                 if (ATARIHW_PRESENT(TT_SHIFTER)) {
 
3127                         printk("atafb_init: initializing TT hw\n");
 
3129                         atafb_ops.fb_setcolreg = &tt_setcolreg;
 
3130                         defmode = DEFMODE_TT;
 
3135                 if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
 
3136                         printk("atafb_init: initializing Falcon hw\n");
 
3137                         fbhw = &falcon_switch;
 
3138                         atafb_ops.fb_setcolreg = &falcon_setcolreg;
 
3139                         request_irq(IRQ_AUTO_4, falcon_vbl_switcher, IRQ_TYPE_PRIO,
 
3140                                     "framebuffer/modeswitch", falcon_vbl_switcher);
 
3141                         defmode = DEFMODE_F30;
 
3146                 if (ATARIHW_PRESENT(STND_SHIFTER) ||
 
3147                     ATARIHW_PRESENT(EXTD_SHIFTER)) {
 
3148                         printk("atafb_init: initializing ST/E hw\n");
 
3150                         atafb_ops.fb_setcolreg = &stste_setcolreg;
 
3151                         defmode = DEFMODE_STE;
 
3155                 atafb_ops.fb_setcolreg = &stste_setcolreg;
 
3156                 printk("Cannot determine video hardware; defaulting to ST(e)\n");
 
3157 #else /* ATAFB_STE */
 
3158                 /* no default driver included */
 
3159                 /* Nobody will ever see this message :-) */
 
3160                 panic("Cannot initialize video hardware");
 
3164         /* Multisync monitor capabilities */
 
3165         /* Atari-TOS defaults if no boot option present */
 
3166         if (fb_info.monspecs.hfmin == 0) {
 
3167                 fb_info.monspecs.hfmin = 31000;
 
3168                 fb_info.monspecs.hfmax = 32000;
 
3169                 fb_info.monspecs.vfmin = 58;
 
3170                 fb_info.monspecs.vfmax = 62;
 
3173         detected_mode = fbhw->detect();
 
3174         check_default_par(detected_mode);
 
3176         if (!external_addr) {
 
3177 #endif /* ATAFB_EXT */
 
3178                 mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
 
3179                 mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
 
3180                 screen_base = atari_stram_alloc(mem_req, "atafb");
 
3182                         panic("Cannot allocate screen memory");
 
3183                 memset(screen_base, 0, mem_req);
 
3184                 pad = -(unsigned long)screen_base & (PAGE_SIZE - 1);
 
3186                 real_screen_base = screen_base + ovsc_offset;
 
3187                 screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
 
3189                 if (CPU_IS_040_OR_060) {
 
3190                         /* On a '040+, the cache mode of video RAM must be set to
 
3191                          * write-through also for internal video hardware! */
 
3192                         cache_push(virt_to_phys(screen_base), screen_len);
 
3193                         kernel_set_cachemode(screen_base, screen_len,
 
3194                                              IOMAP_WRITETHROUGH);
 
3196                 printk("atafb: screen_base %p real_screen_base %p screen_len %d\n",
 
3197                         screen_base, real_screen_base, screen_len);
 
3200                 /* Map the video memory (physical address given) to somewhere
 
3201                  * in the kernel address space.
 
3203                 external_addr = ioremap_writethrough((unsigned long)external_addr,
 
3205                 if (external_vgaiobase)
 
3206                         external_vgaiobase =
 
3207                           (unsigned long)ioremap(external_vgaiobase, 0x10000);
 
3209                 real_screen_base = external_addr;
 
3210                 screen_len = external_len & PAGE_MASK;
 
3211                 memset (screen_base, 0, external_len);
 
3213 #endif /* ATAFB_EXT */
 
3215 //      strcpy(fb_info.mode->name, "Atari Builtin ");
 
3216         fb_info.fbops = &atafb_ops;
 
3217         // try to set default (detected; requested) var
 
3218         do_fb_set_var(&atafb_predefined[default_par - 1], 1);
 
3219         // reads hw state into current par, which may not be sane yet
 
3220         ata_get_par(¤t_par);
 
3221         fb_info.par = ¤t_par;
 
3222         // tries to read from HW which may not be initialized yet
 
3223         // so set sane var first, then call atafb_set_par
 
3224         atafb_get_var(&fb_info.var, &fb_info);
 
3225         fb_info.flags = FBINFO_FLAG_DEFAULT;
 
3227         if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb,
 
3228                           NUM_TOTAL_MODES, &atafb_modedb[defmode],
 
3229                           fb_info.var.bits_per_pixel)) {
 
3233         atafb_set_disp(&fb_info);
 
3235         fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0);
 
3238         printk("Determined %dx%d, depth %d\n",
 
3239                fb_info.var.xres, fb_info.var.yres, fb_info.var.bits_per_pixel);
 
3240         if ((fb_info.var.xres != fb_info.var.xres_virtual) ||
 
3241             (fb_info.var.yres != fb_info.var.yres_virtual))
 
3242                 printk("   virtual %dx%d\n", fb_info.var.xres_virtual,
 
3243                        fb_info.var.yres_virtual);
 
3245         if (register_framebuffer(&fb_info) < 0) {
 
3247                 if (external_addr) {
 
3248                         iounmap(external_addr);
 
3249                         external_addr = NULL;
 
3251                 if (external_vgaiobase) {
 
3252                         iounmap((void*)external_vgaiobase);
 
3253                         external_vgaiobase = 0;
 
3259         // FIXME: mode needs setting!
 
3260         //printk("fb%d: %s frame buffer device, using %dK of video memory\n",
 
3261         //       fb_info.node, fb_info.mode->name, screen_len>>10);
 
3262         printk("fb%d: frame buffer device, using %dK of video memory\n",
 
3263                fb_info.node, screen_len >> 10);
 
3265         /* TODO: This driver cannot be unloaded yet */
 
3269 module_init(atafb_init);
 
3272 MODULE_LICENSE("GPL");
 
3274 int cleanup_module(void)
 
3276         unregister_framebuffer(&fb_info);
 
3277         return atafb_deinit();