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