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