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