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