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