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/delay.h>
  56#include <linux/init.h>
  57#include <linux/interrupt.h>
  58
  59#include <asm/setup.h>
  60#include <linux/uaccess.h>
  61#include <asm/pgtable.h>
  62#include <asm/irq.h>
  63#include <asm/io.h>
  64
  65#include <asm/atarihw.h>
  66#include <asm/atariints.h>
  67#include <asm/atari_stram.h>
  68
  69#include <linux/fb.h>
  70#include <asm/atarikb.h>
  71
  72#include "c2p.h"
  73#include "atafb.h"
  74
  75#define SWITCH_ACIA 0x01                /* modes for switch on OverScan */
  76#define SWITCH_SND6 0x40
  77#define SWITCH_SND7 0x80
  78#define SWITCH_NONE 0x00
  79
  80
  81#define up(x, r) (((x) + (r) - 1) & ~((r)-1))
  82
  83        /*
  84         * Interface to the world
  85         */
  86
  87static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
  88static int atafb_set_par(struct fb_info *info);
  89static int atafb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
  90                           unsigned int blue, unsigned int transp,
  91                           struct fb_info *info);
  92static int atafb_blank(int blank, struct fb_info *info);
  93static int atafb_pan_display(struct fb_var_screeninfo *var,
  94                             struct fb_info *info);
  95static void atafb_fillrect(struct fb_info *info,
  96                           const struct fb_fillrect *rect);
  97static void atafb_copyarea(struct fb_info *info,
  98                           const struct fb_copyarea *region);
  99static void atafb_imageblit(struct fb_info *info, const struct fb_image *image);
 100static int atafb_ioctl(struct fb_info *info, unsigned int cmd,
 101                       unsigned long arg);
 102
 103
 104static int default_par;         /* default resolution (0=none) */
 105
 106static unsigned long default_mem_req;
 107
 108static int hwscroll = -1;
 109
 110static int use_hwscroll = 1;
 111
 112static int sttt_xres = 640, st_yres = 400, tt_yres = 480;
 113static int sttt_xres_virtual = 640, sttt_yres_virtual = 400;
 114static int ovsc_offset, ovsc_addlen;
 115
 116        /*
 117         * Hardware parameters for current mode
 118         */
 119
 120static struct atafb_par {
 121        void *screen_base;
 122        int yres_virtual;
 123        u_long next_line;
 124#if defined ATAFB_TT || defined ATAFB_STE
 125        union {
 126                struct {
 127                        int mode;
 128                        int sync;
 129                } tt, st;
 130#endif
 131#ifdef ATAFB_FALCON
 132                struct falcon_hw {
 133                        /* Here are fields for storing a video mode, as direct
 134                         * parameters for the hardware.
 135                         */
 136                        short sync;
 137                        short line_width;
 138                        short line_offset;
 139                        short st_shift;
 140                        short f_shift;
 141                        short vid_control;
 142                        short vid_mode;
 143                        short xoffset;
 144                        short hht, hbb, hbe, hdb, hde, hss;
 145                        short vft, vbb, vbe, vdb, vde, vss;
 146                        /* auxiliary information */
 147                        short mono;
 148                        short ste_mode;
 149                        short bpp;
 150                        u32 pseudo_palette[16];
 151                } falcon;
 152#endif
 153                /* Nothing needed for external mode */
 154        } hw;
 155} current_par;
 156
 157/* Don't calculate an own resolution, and thus don't change the one found when
 158 * booting (currently used for the Falcon to keep settings for internal video
 159 * hardware extensions (e.g. ScreenBlaster)  */
 160static int DontCalcRes = 0;
 161
 162#ifdef ATAFB_FALCON
 163#define HHT hw.falcon.hht
 164#define HBB hw.falcon.hbb
 165#define HBE hw.falcon.hbe
 166#define HDB hw.falcon.hdb
 167#define HDE hw.falcon.hde
 168#define HSS hw.falcon.hss
 169#define VFT hw.falcon.vft
 170#define VBB hw.falcon.vbb
 171#define VBE hw.falcon.vbe
 172#define VDB hw.falcon.vdb
 173#define VDE hw.falcon.vde
 174#define VSS hw.falcon.vss
 175#define VCO_CLOCK25             0x04
 176#define VCO_CSYPOS              0x10
 177#define VCO_VSYPOS              0x20
 178#define VCO_HSYPOS              0x40
 179#define VCO_SHORTOFFS   0x100
 180#define VMO_DOUBLE              0x01
 181#define VMO_INTER               0x02
 182#define VMO_PREMASK             0x0c
 183#endif
 184
 185static struct fb_info fb_info = {
 186        .fix = {
 187                .id     = "Atari ",
 188                .visual = FB_VISUAL_PSEUDOCOLOR,
 189                .accel  = FB_ACCEL_NONE,
 190        }
 191};
 192
 193static void *screen_base;       /* base address of screen */
 194static void *real_screen_base;  /* (only for Overscan) */
 195
 196static int screen_len;
 197
 198static int current_par_valid;
 199
 200static int mono_moni;
 201
 202
 203#ifdef ATAFB_EXT
 204
 205/* external video handling */
 206static unsigned int external_xres;
 207static unsigned int external_xres_virtual;
 208static unsigned int external_yres;
 209
 210/*
 211 * not needed - atafb will never support panning/hardwarescroll with external
 212 * static unsigned int external_yres_virtual;
 213 */
 214static unsigned int external_depth;
 215static int external_pmode;
 216static void *external_addr;
 217static unsigned long external_len;
 218static unsigned long external_vgaiobase;
 219static unsigned int external_bitspercol = 6;
 220
 221/*
 222 * JOE <joe@amber.dinoco.de>:
 223 * added card type for external driver, is only needed for
 224 * colormap handling.
 225 */
 226enum cardtype { IS_VGA, IS_MV300 };
 227static enum cardtype external_card_type = IS_VGA;
 228
 229/*
 230 * The MV300 mixes the color registers. So we need an array of munged
 231 * indices in order to access the correct reg.
 232 */
 233static int MV300_reg_1bit[2] = {
 234        0, 1
 235};
 236static int MV300_reg_4bit[16] = {
 237        0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
 238};
 239static int MV300_reg_8bit[256] = {
 240        0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
 241        8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
 242        4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
 243        12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
 244        2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
 245        10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
 246        6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
 247        14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
 248        1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
 249        9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
 250        5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
 251        13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
 252        3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
 253        11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
 254        7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
 255        15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
 256};
 257
 258static int *MV300_reg = MV300_reg_8bit;
 259#endif /* ATAFB_EXT */
 260
 261
 262static int inverse;
 263
 264extern int fontheight_8x8;
 265extern int fontwidth_8x8;
 266extern unsigned char fontdata_8x8[];
 267
 268extern int fontheight_8x16;
 269extern int fontwidth_8x16;
 270extern unsigned char fontdata_8x16[];
 271
 272/*
 273 * struct fb_ops {
 274 *      * open/release and usage marking
 275 *      struct module *owner;
 276 *      int (*fb_open)(struct fb_info *info, int user);
 277 *      int (*fb_release)(struct fb_info *info, int user);
 278 *
 279 *      * For framebuffers with strange non linear layouts or that do not
 280 *      * work with normal memory mapped access
 281 *      ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos);
 282 *      ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
 283 *
 284 *      * checks var and eventually tweaks it to something supported,
 285 *      * DOES NOT MODIFY PAR *
 286 *      int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
 287 *
 288 *      * set the video mode according to info->var *
 289 *      int (*fb_set_par)(struct fb_info *info);
 290 *
 291 *      * set color register *
 292 *      int (*fb_setcolreg)(unsigned int regno, unsigned int red, unsigned int green,
 293 *                          unsigned int blue, unsigned int transp, struct fb_info *info);
 294 *
 295 *      * set color registers in batch *
 296 *      int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
 297 *
 298 *      * blank display *
 299 *      int (*fb_blank)(int blank, struct fb_info *info);
 300 *
 301 *      * pan display *
 302 *      int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
 303 *
 304 *      *** The meat of the drawing engine ***
 305 *      * Draws a rectangle *
 306 *      void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
 307 *      * Copy data from area to another *
 308 *      void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
 309 *      * Draws a image to the display *
 310 *      void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
 311 *
 312 *      * Draws cursor *
 313 *      int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
 314 *
 315 *      * Rotates the display *
 316 *      void (*fb_rotate)(struct fb_info *info, int angle);
 317 *
 318 *      * wait for blit idle, optional *
 319 *      int (*fb_sync)(struct fb_info *info);
 320 *
 321 *      * perform fb specific ioctl (optional) *
 322 *      int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
 323 *                      unsigned long arg);
 324 *
 325 *      * Handle 32bit compat ioctl (optional) *
 326 *      int (*fb_compat_ioctl)(struct fb_info *info, unsigned int cmd,
 327 *                      unsigned long arg);
 328 *
 329 *      * perform fb specific mmap *
 330 *      int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
 331 * } ;
 332 */
 333
 334
 335/* ++roman: This structure abstracts from the underlying hardware (ST(e),
 336 * TT, or Falcon.
 337 *
 338 * int (*detect)(void)
 339 *   This function should detect the current video mode settings and
 340 *   store them in atafb_predefined[0] for later reference by the
 341 *   user. Return the index+1 of an equivalent predefined mode or 0
 342 *   if there is no such.
 343 *
 344 * int (*encode_fix)(struct fb_fix_screeninfo *fix,
 345 *                   struct atafb_par *par)
 346 *   This function should fill in the 'fix' structure based on the
 347 *   values in the 'par' structure.
 348 * !!! Obsolete, perhaps !!!
 349 *
 350 * int (*decode_var)(struct fb_var_screeninfo *var,
 351 *                   struct atafb_par *par)
 352 *   Get the video params out of 'var'. If a value doesn't fit, round
 353 *   it up, if it's too big, return EINVAL.
 354 *   Round up in the following order: bits_per_pixel, xres, yres,
 355 *   xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
 356 *   horizontal timing, vertical timing.
 357 *
 358 * int (*encode_var)(struct fb_var_screeninfo *var,
 359 *                   struct atafb_par *par);
 360 *   Fill the 'var' structure based on the values in 'par' and maybe
 361 *   other values read out of the hardware.
 362 *
 363 * void (*get_par)(struct atafb_par *par)
 364 *   Fill the hardware's 'par' structure.
 365 *   !!! Used only by detect() !!!
 366 *
 367 * void (*set_par)(struct atafb_par *par)
 368 *   Set the hardware according to 'par'.
 369 *
 370 * void (*set_screen_base)(void *s_base)
 371 *   Set the base address of the displayed frame buffer. Only called
 372 *   if yres_virtual > yres or xres_virtual > xres.
 373 *
 374 * int (*blank)(int blank_mode)
 375 *   Blank the screen if blank_mode != 0, else unblank. If blank == NULL then
 376 *   the caller blanks by setting the CLUT to all black. Return 0 if blanking
 377 *   succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
 378 *   doesn't support it. Implements VESA suspend and powerdown modes on
 379 *   hardware that supports disabling hsync/vsync:
 380 *       blank_mode == 2: suspend vsync, 3:suspend hsync, 4: powerdown.
 381 */
 382
 383static struct fb_hwswitch {
 384        int (*detect)(void);
 385        int (*encode_fix)(struct fb_fix_screeninfo *fix,
 386                          struct atafb_par *par);
 387        int (*decode_var)(struct fb_var_screeninfo *var,
 388                          struct atafb_par *par);
 389        int (*encode_var)(struct fb_var_screeninfo *var,
 390                          struct atafb_par *par);
 391        void (*get_par)(struct atafb_par *par);
 392        void (*set_par)(struct atafb_par *par);
 393        void (*set_screen_base)(void *s_base);
 394        int (*blank)(int blank_mode);
 395        int (*pan_display)(struct fb_var_screeninfo *var,
 396                           struct fb_info *info);
 397} *fbhw;
 398
 399static char *autodetect_names[] = { "autodetect", NULL };
 400static char *stlow_names[] = { "stlow", NULL };
 401static char *stmid_names[] = { "stmid", "default5", NULL };
 402static char *sthigh_names[] = { "sthigh", "default4", NULL };
 403static char *ttlow_names[] = { "ttlow", NULL };
 404static char *ttmid_names[] = { "ttmid", "default1", NULL };
 405static char *tthigh_names[] = { "tthigh", "default2", NULL };
 406static char *vga2_names[] = { "vga2", NULL };
 407static char *vga4_names[] = { "vga4", NULL };
 408static char *vga16_names[] = { "vga16", "default3", NULL };
 409static char *vga256_names[] = { "vga256", NULL };
 410static char *falh2_names[] = { "falh2", NULL };
 411static char *falh16_names[] = { "falh16", NULL };
 412
 413static char **fb_var_names[] = {
 414        autodetect_names,
 415        stlow_names,
 416        stmid_names,
 417        sthigh_names,
 418        ttlow_names,
 419        ttmid_names,
 420        tthigh_names,
 421        vga2_names,
 422        vga4_names,
 423        vga16_names,
 424        vga256_names,
 425        falh2_names,
 426        falh16_names,
 427        NULL
 428};
 429
 430static struct fb_var_screeninfo atafb_predefined[] = {
 431        /*
 432         * yres_virtual == 0 means use hw-scrolling if possible, else yres
 433         */
 434        { /* autodetect */
 435          0, 0, 0, 0, 0, 0, 0, 0,               /* xres-grayscale */
 436          {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},   /* red green blue tran*/
 437          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 438        { /* st low */
 439          320, 200, 320, 0, 0, 0, 4, 0,
 440          {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
 441          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 442        { /* st mid */
 443          640, 200, 640, 0, 0, 0, 2, 0,
 444          {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
 445          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 446        { /* st high */
 447          640, 400, 640, 0, 0, 0, 1, 0,
 448          {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
 449          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 450        { /* tt low */
 451          320, 480, 320, 0, 0, 0, 8, 0,
 452          {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
 453          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 454        { /* tt mid */
 455          640, 480, 640, 0, 0, 0, 4, 0,
 456          {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
 457          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 458        { /* tt high */
 459          1280, 960, 1280, 0, 0, 0, 1, 0,
 460          {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
 461          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 462        { /* vga2 */
 463          640, 480, 640, 0, 0, 0, 1, 0,
 464          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 465          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 466        { /* vga4 */
 467          640, 480, 640, 0, 0, 0, 2, 0,
 468          {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
 469          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 470        { /* vga16 */
 471          640, 480, 640, 0, 0, 0, 4, 0,
 472          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 473          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 474        { /* vga256 */
 475          640, 480, 640, 0, 0, 0, 8, 0,
 476          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 477          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 478        { /* falh2 */
 479          896, 608, 896, 0, 0, 0, 1, 0,
 480          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 481          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 482        { /* falh16 */
 483          896, 608, 896, 0, 0, 0, 4, 0,
 484          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 485          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 486};
 487
 488static int num_atafb_predefined = ARRAY_SIZE(atafb_predefined);
 489
 490static struct fb_videomode atafb_modedb[] __initdata = {
 491        /*
 492         *  Atari Video Modes
 493         *
 494         *  If you change these, make sure to update DEFMODE_* as well!
 495         */
 496
 497        /*
 498         *  ST/TT Video Modes
 499         */
 500
 501        {
 502                /* 320x200, 15 kHz, 60 Hz (ST low) */
 503                "st-low", 60, 320, 200, 32000, 32, 16, 31, 14, 96, 4,
 504                0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 505        }, {
 506                /* 640x200, 15 kHz, 60 Hz (ST medium) */
 507                "st-mid", 60, 640, 200, 32000, 32, 16, 31, 14, 96, 4,
 508                0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 509        }, {
 510                /* 640x400, 30.25 kHz, 63.5 Hz (ST high) */
 511                "st-high", 63, 640, 400, 32000, 128, 0, 40, 14, 128, 4,
 512                0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 513        }, {
 514                /* 320x480, 15 kHz, 60 Hz (TT low) */
 515                "tt-low", 60, 320, 480, 31041, 120, 100, 8, 16, 140, 30,
 516                0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 517        }, {
 518                /* 640x480, 29 kHz, 57 Hz (TT medium) */
 519                "tt-mid", 60, 640, 480, 31041, 120, 100, 8, 16, 140, 30,
 520                0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 521        }, {
 522                /* 1280x960, 29 kHz, 60 Hz (TT high) */
 523                "tt-high", 57, 640, 960, 31041, 120, 100, 8, 16, 140, 30,
 524                0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 525        },
 526
 527        /*
 528         *  VGA Video Modes
 529         */
 530
 531        {
 532                /* 640x480, 31 kHz, 60 Hz (VGA) */
 533                "vga", 63.5, 640, 480, 32000, 18, 42, 31, 11, 96, 3,
 534                0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 535        }, {
 536                /* 640x400, 31 kHz, 70 Hz (VGA) */
 537                "vga70", 70, 640, 400, 32000, 18, 42, 31, 11, 96, 3,
 538                FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 539        },
 540
 541        /*
 542         *  Falcon HiRes Video Modes
 543         */
 544
 545        {
 546                /* 896x608, 31 kHz, 60 Hz (Falcon High) */
 547                "falh", 60, 896, 608, 32000, 18, 42, 31, 1, 96,3,
 548                0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
 549        },
 550};
 551
 552#define NUM_TOTAL_MODES  ARRAY_SIZE(atafb_modedb)
 553
 554static char *mode_option __initdata = NULL;
 555
 556 /* default modes */
 557
 558#define DEFMODE_TT      5               /* "tt-high" for TT */
 559#define DEFMODE_F30     7               /* "vga70" for Falcon */
 560#define DEFMODE_STE     2               /* "st-high" for ST/E */
 561#define DEFMODE_EXT     6               /* "vga" for external */
 562
 563
 564static int get_video_mode(char *vname)
 565{
 566        char ***name_list;
 567        char **name;
 568        int i;
 569
 570        name_list = fb_var_names;
 571        for (i = 0; i < num_atafb_predefined; i++) {
 572                name = *name_list++;
 573                if (!name || !*name)
 574                        break;
 575                while (*name) {
 576                        if (!strcmp(vname, *name))
 577                                return i + 1;
 578                        name++;
 579                }
 580        }
 581        return 0;
 582}
 583
 584
 585
 586/* ------------------- TT specific functions ---------------------- */
 587
 588#ifdef ATAFB_TT
 589
 590static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
 591{
 592        int mode;
 593
 594        strcpy(fix->id, "Atari Builtin");
 595        fix->smem_start = (unsigned long)real_screen_base;
 596        fix->smem_len = screen_len;
 597        fix->type = FB_TYPE_INTERLEAVED_PLANES;
 598        fix->type_aux = 2;
 599        fix->visual = FB_VISUAL_PSEUDOCOLOR;
 600        mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK;
 601        if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) {
 602                fix->type = FB_TYPE_PACKED_PIXELS;
 603                fix->type_aux = 0;
 604                if (mode == TT_SHIFTER_TTHIGH)
 605                        fix->visual = FB_VISUAL_MONO01;
 606        }
 607        fix->xpanstep = 0;
 608        fix->ypanstep = 1;
 609        fix->ywrapstep = 0;
 610        fix->line_length = par->next_line;
 611        fix->accel = FB_ACCEL_ATARIBLITT;
 612        return 0;
 613}
 614
 615static int tt_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
 616{
 617        int xres = var->xres;
 618        int yres = var->yres;
 619        int bpp = var->bits_per_pixel;
 620        int linelen;
 621        int yres_virtual = var->yres_virtual;
 622
 623        if (mono_moni) {
 624                if (bpp > 1 || xres > sttt_xres * 2 || yres > tt_yres * 2)
 625                        return -EINVAL;
 626                par->hw.tt.mode = TT_SHIFTER_TTHIGH;
 627                xres = sttt_xres * 2;
 628                yres = tt_yres * 2;
 629                bpp = 1;
 630        } else {
 631                if (bpp > 8 || xres > sttt_xres || yres > tt_yres)
 632                        return -EINVAL;
 633                if (bpp > 4) {
 634                        if (xres > sttt_xres / 2 || yres > tt_yres)
 635                                return -EINVAL;
 636                        par->hw.tt.mode = TT_SHIFTER_TTLOW;
 637                        xres = sttt_xres / 2;
 638                        yres = tt_yres;
 639                        bpp = 8;
 640                } else if (bpp > 2) {
 641                        if (xres > sttt_xres || yres > tt_yres)
 642                                return -EINVAL;
 643                        if (xres > sttt_xres / 2 || yres > st_yres / 2) {
 644                                par->hw.tt.mode = TT_SHIFTER_TTMID;
 645                                xres = sttt_xres;
 646                                yres = tt_yres;
 647                                bpp = 4;
 648                        } else {
 649                                par->hw.tt.mode = TT_SHIFTER_STLOW;
 650                                xres = sttt_xres / 2;
 651                                yres = st_yres / 2;
 652                                bpp = 4;
 653                        }
 654                } else if (bpp > 1) {
 655                        if (xres > sttt_xres || yres > st_yres / 2)
 656                                return -EINVAL;
 657                        par->hw.tt.mode = TT_SHIFTER_STMID;
 658                        xres = sttt_xres;
 659                        yres = st_yres / 2;
 660                        bpp = 2;
 661                } else if (var->xres > sttt_xres || var->yres > st_yres) {
 662                        return -EINVAL;
 663                } else {
 664                        par->hw.tt.mode = TT_SHIFTER_STHIGH;
 665                        xres = sttt_xres;
 666                        yres = st_yres;
 667                        bpp = 1;
 668                }
 669        }
 670        if (yres_virtual <= 0)
 671                yres_virtual = 0;
 672        else if (yres_virtual < yres)
 673                yres_virtual = yres;
 674        if (var->sync & FB_SYNC_EXT)
 675                par->hw.tt.sync = 0;
 676        else
 677                par->hw.tt.sync = 1;
 678        linelen = xres * bpp / 8;
 679        if (yres_virtual * linelen > screen_len && screen_len)
 680                return -EINVAL;
 681        if (yres * linelen > screen_len && screen_len)
 682                return -EINVAL;
 683        if (var->yoffset + yres > yres_virtual && yres_virtual)
 684                return -EINVAL;
 685        par->yres_virtual = yres_virtual;
 686        par->screen_base = screen_base + var->yoffset * linelen;
 687        par->next_line = linelen;
 688        return 0;
 689}
 690
 691static int tt_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
 692{
 693        int linelen;
 694        memset(var, 0, sizeof(struct fb_var_screeninfo));
 695        var->red.offset = 0;
 696        var->red.length = 4;
 697        var->red.msb_right = 0;
 698        var->grayscale = 0;
 699
 700        var->pixclock = 31041;
 701        var->left_margin = 120;         /* these may be incorrect */
 702        var->right_margin = 100;
 703        var->upper_margin = 8;
 704        var->lower_margin = 16;
 705        var->hsync_len = 140;
 706        var->vsync_len = 30;
 707
 708        var->height = -1;
 709        var->width = -1;
 710
 711        if (par->hw.tt.sync & 1)
 712                var->sync = 0;
 713        else
 714                var->sync = FB_SYNC_EXT;
 715
 716        switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) {
 717        case TT_SHIFTER_STLOW:
 718                var->xres = sttt_xres / 2;
 719                var->xres_virtual = sttt_xres_virtual / 2;
 720                var->yres = st_yres / 2;
 721                var->bits_per_pixel = 4;
 722                break;
 723        case TT_SHIFTER_STMID:
 724                var->xres = sttt_xres;
 725                var->xres_virtual = sttt_xres_virtual;
 726                var->yres = st_yres / 2;
 727                var->bits_per_pixel = 2;
 728                break;
 729        case TT_SHIFTER_STHIGH:
 730                var->xres = sttt_xres;
 731                var->xres_virtual = sttt_xres_virtual;
 732                var->yres = st_yres;
 733                var->bits_per_pixel = 1;
 734                break;
 735        case TT_SHIFTER_TTLOW:
 736                var->xres = sttt_xres / 2;
 737                var->xres_virtual = sttt_xres_virtual / 2;
 738                var->yres = tt_yres;
 739                var->bits_per_pixel = 8;
 740                break;
 741        case TT_SHIFTER_TTMID:
 742                var->xres = sttt_xres;
 743                var->xres_virtual = sttt_xres_virtual;
 744                var->yres = tt_yres;
 745                var->bits_per_pixel = 4;
 746                break;
 747        case TT_SHIFTER_TTHIGH:
 748                var->red.length = 0;
 749                var->xres = sttt_xres * 2;
 750                var->xres_virtual = sttt_xres_virtual * 2;
 751                var->yres = tt_yres * 2;
 752                var->bits_per_pixel = 1;
 753                break;
 754        }
 755        var->blue = var->green = var->red;
 756        var->transp.offset = 0;
 757        var->transp.length = 0;
 758        var->transp.msb_right = 0;
 759        linelen = var->xres_virtual * var->bits_per_pixel / 8;
 760        if (!use_hwscroll)
 761                var->yres_virtual = var->yres;
 762        else if (screen_len) {
 763                if (par->yres_virtual)
 764                        var->yres_virtual = par->yres_virtual;
 765                else
 766                        /* yres_virtual == 0 means use maximum */
 767                        var->yres_virtual = screen_len / linelen;
 768        } else {
 769                if (hwscroll < 0)
 770                        var->yres_virtual = 2 * var->yres;
 771                else
 772                        var->yres_virtual = var->yres + hwscroll * 16;
 773        }
 774        var->xoffset = 0;
 775        if (screen_base)
 776                var->yoffset = (par->screen_base - screen_base) / linelen;
 777        else
 778                var->yoffset = 0;
 779        var->nonstd = 0;
 780        var->activate = 0;
 781        var->vmode = FB_VMODE_NONINTERLACED;
 782        return 0;
 783}
 784
 785static void tt_get_par(struct atafb_par *par)
 786{
 787        unsigned long addr;
 788        par->hw.tt.mode = shifter_tt.tt_shiftmode;
 789        par->hw.tt.sync = shifter.syncmode;
 790        addr = ((shifter.bas_hi & 0xff) << 16) |
 791               ((shifter.bas_md & 0xff) << 8)  |
 792               ((shifter.bas_lo & 0xff));
 793        par->screen_base = phys_to_virt(addr);
 794}
 795
 796static void tt_set_par(struct atafb_par *par)
 797{
 798        shifter_tt.tt_shiftmode = par->hw.tt.mode;
 799        shifter.syncmode = par->hw.tt.sync;
 800        /* only set screen_base if really necessary */
 801        if (current_par.screen_base != par->screen_base)
 802                fbhw->set_screen_base(par->screen_base);
 803}
 804
 805static int tt_setcolreg(unsigned int regno, unsigned int red,
 806                        unsigned int green, unsigned int blue,
 807                        unsigned int transp, struct fb_info *info)
 808{
 809        if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
 810                regno += 254;
 811        if (regno > 255)
 812                return 1;
 813        tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) |
 814                             (blue >> 12));
 815        if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
 816            TT_SHIFTER_STHIGH && regno == 254)
 817                tt_palette[0] = 0;
 818        return 0;
 819}
 820
 821static int tt_detect(void)
 822{
 823        struct atafb_par par;
 824
 825        /* Determine the connected monitor: The DMA sound must be
 826         * disabled before reading the MFP GPIP, because the Sound
 827         * Done Signal and the Monochrome Detect are XORed together!
 828         *
 829         * Even on a TT, we should look if there is a DMA sound. It was
 830         * announced that the Eagle is TT compatible, but only the PCM is
 831         * missing...
 832         */
 833        if (ATARIHW_PRESENT(PCM_8BIT)) {
 834                tt_dmasnd.ctrl = DMASND_CTRL_OFF;
 835                udelay(20);             /* wait a while for things to settle down */
 836        }
 837        mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
 838
 839        tt_get_par(&par);
 840        tt_encode_var(&atafb_predefined[0], &par);
 841
 842        return 1;
 843}
 844
 845#endif /* ATAFB_TT */
 846
 847/* ------------------- Falcon specific functions ---------------------- */
 848
 849#ifdef ATAFB_FALCON
 850
 851static int mon_type;            /* Falcon connected monitor */
 852static int f030_bus_width;      /* Falcon ram bus width (for vid_control) */
 853#define F_MON_SM        0
 854#define F_MON_SC        1
 855#define F_MON_VGA       2
 856#define F_MON_TV        3
 857
 858static struct pixel_clock {
 859        unsigned long f;        /* f/[Hz] */
 860        unsigned long t;        /* t/[ps] (=1/f) */
 861        int right, hsync, left; /* standard timing in clock cycles, not pixel */
 862        /* hsync initialized in falcon_detect() */
 863        int sync_mask;          /* or-mask for hw.falcon.sync to set this clock */
 864        int control_mask;       /* ditto, for hw.falcon.vid_control */
 865} f25 = {
 866        25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25
 867}, f32 = {
 868        32000000, 31250, 18, 0, 42, 0x0, 0
 869}, fext = {
 870        0, 0, 18, 0, 42, 0x1, 0
 871};
 872
 873/* VIDEL-prescale values [mon_type][pixel_length from VCO] */
 874static int vdl_prescale[4][3] = {
 875        { 4,2,1 }, { 4,2,1 }, { 4,2,2 }, { 4,2,1 }
 876};
 877
 878/* Default hsync timing [mon_type] in picoseconds */
 879static long h_syncs[4] = { 3000000, 4875000, 4000000, 4875000 };
 880
 881static inline int hxx_prescale(struct falcon_hw *hw)
 882{
 883        return hw->ste_mode ? 16
 884                            : vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
 885}
 886
 887static int falcon_encode_fix(struct fb_fix_screeninfo *fix,
 888                             struct atafb_par *par)
 889{
 890        strcpy(fix->id, "Atari Builtin");
 891        fix->smem_start = (unsigned long)real_screen_base;
 892        fix->smem_len = screen_len;
 893        fix->type = FB_TYPE_INTERLEAVED_PLANES;
 894        fix->type_aux = 2;
 895        fix->visual = FB_VISUAL_PSEUDOCOLOR;
 896        fix->xpanstep = 1;
 897        fix->ypanstep = 1;
 898        fix->ywrapstep = 0;
 899        if (par->hw.falcon.mono) {
 900                fix->type = FB_TYPE_PACKED_PIXELS;
 901                fix->type_aux = 0;
 902                /* no smooth scrolling with longword aligned video mem */
 903                fix->xpanstep = 32;
 904        } else if (par->hw.falcon.f_shift & 0x100) {
 905                fix->type = FB_TYPE_PACKED_PIXELS;
 906                fix->type_aux = 0;
 907                /* Is this ok or should it be DIRECTCOLOR? */
 908                fix->visual = FB_VISUAL_TRUECOLOR;
 909                fix->xpanstep = 2;
 910        }
 911        fix->line_length = par->next_line;
 912        fix->accel = FB_ACCEL_ATARIBLITT;
 913        return 0;
 914}
 915
 916static int falcon_decode_var(struct fb_var_screeninfo *var,
 917                             struct atafb_par *par)
 918{
 919        int bpp = var->bits_per_pixel;
 920        int xres = var->xres;
 921        int yres = var->yres;
 922        int xres_virtual = var->xres_virtual;
 923        int yres_virtual = var->yres_virtual;
 924        int left_margin, right_margin, hsync_len;
 925        int upper_margin, lower_margin, vsync_len;
 926        int linelen;
 927        int interlace = 0, doubleline = 0;
 928        struct pixel_clock *pclock;
 929        int plen;                       /* width of pixel in clock cycles */
 930        int xstretch;
 931        int prescale;
 932        int longoffset = 0;
 933        int hfreq, vfreq;
 934        int hdb_off, hde_off, base_off;
 935        int gstart, gend1, gend2, align;
 936
 937/*
 938        Get the video params out of 'var'. If a value doesn't fit, round
 939        it up, if it's too big, return EINVAL.
 940        Round up in the following order: bits_per_pixel, xres, yres,
 941        xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
 942        horizontal timing, vertical timing.
 943
 944        There is a maximum of screen resolution determined by pixelclock
 945        and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock.
 946        In interlace mode this is     "     *    "     *vfmin <= pixelclock.
 947        Additional constraints: hfreq.
 948        Frequency range for multisync monitors is given via command line.
 949        For TV and SM124 both frequencies are fixed.
 950
 951        X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32 == 0)
 952        Y % 16 == 0 to fit 8x16 font
 953        Y % 8 == 0 if Y<400
 954
 955        Currently interlace and doubleline mode in var are ignored.
 956        On SM124 and TV only the standard resolutions can be used.
 957*/
 958
 959        /* Reject uninitialized mode */
 960        if (!xres || !yres || !bpp)
 961                return -EINVAL;
 962
 963        if (mon_type == F_MON_SM && bpp != 1)
 964                return -EINVAL;
 965
 966        if (bpp <= 1) {
 967                bpp = 1;
 968                par->hw.falcon.f_shift = 0x400;
 969                par->hw.falcon.st_shift = 0x200;
 970        } else if (bpp <= 2) {
 971                bpp = 2;
 972                par->hw.falcon.f_shift = 0x000;
 973                par->hw.falcon.st_shift = 0x100;
 974        } else if (bpp <= 4) {
 975                bpp = 4;
 976                par->hw.falcon.f_shift = 0x000;
 977                par->hw.falcon.st_shift = 0x000;
 978        } else if (bpp <= 8) {
 979                bpp = 8;
 980                par->hw.falcon.f_shift = 0x010;
 981        } else if (bpp <= 16) {
 982                bpp = 16;               /* packed pixel mode */
 983                par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */
 984        } else
 985                return -EINVAL;
 986        par->hw.falcon.bpp = bpp;
 987
 988        if (mon_type == F_MON_SM || DontCalcRes) {
 989                /* Skip all calculations. VGA/TV/SC1224 only supported. */
 990                struct fb_var_screeninfo *myvar = &atafb_predefined[0];
 991
 992                if (bpp > myvar->bits_per_pixel ||
 993                    var->xres > myvar->xres ||
 994                    var->yres > myvar->yres)
 995                        return -EINVAL;
 996                fbhw->get_par(par);     /* Current par will be new par */
 997                goto set_screen_base;   /* Don't forget this */
 998        }
 999
1000        /* Only some fixed resolutions < 640x400 */
1001        if (xres <= 320)
1002                xres = 320;
1003        else if (xres <= 640 && bpp != 16)
1004                xres = 640;
1005        if (yres <= 200)
1006                yres = 200;
1007        else if (yres <= 240)
1008                yres = 240;
1009        else if (yres <= 400)
1010                yres = 400;
1011
1012        /* 2 planes must use STE compatibility mode */
1013        par->hw.falcon.ste_mode = bpp == 2;
1014        par->hw.falcon.mono = bpp == 1;
1015
1016        /* Total and visible scanline length must be a multiple of one longword,
1017         * this and the console fontwidth yields the alignment for xres and
1018         * xres_virtual.
1019         * TODO: this way "odd" fontheights are not supported
1020         *
1021         * Special case in STE mode: blank and graphic positions don't align,
1022         * avoid trash at right margin
1023         */
1024        if (par->hw.falcon.ste_mode)
1025                xres = (xres + 63) & ~63;
1026        else if (bpp == 1)
1027                xres = (xres + 31) & ~31;
1028        else
1029                xres = (xres + 15) & ~15;
1030        if (yres >= 400)
1031                yres = (yres + 15) & ~15;
1032        else
1033                yres = (yres + 7) & ~7;
1034
1035        if (xres_virtual < xres)
1036                xres_virtual = xres;
1037        else if (bpp == 1)
1038                xres_virtual = (xres_virtual + 31) & ~31;
1039        else
1040                xres_virtual = (xres_virtual + 15) & ~15;
1041
1042        if (yres_virtual <= 0)
1043                yres_virtual = 0;
1044        else if (yres_virtual < yres)
1045                yres_virtual = yres;
1046
1047        /* backward bug-compatibility */
1048        if (var->pixclock > 1)
1049                var->pixclock -= 1;
1050
1051        par->hw.falcon.line_width = bpp * xres / 16;
1052        par->hw.falcon.line_offset = bpp * (xres_virtual - xres) / 16;
1053
1054        /* single or double pixel width */
1055        xstretch = (xres < 640) ? 2 : 1;
1056
1057#if 0 /* SM124 supports only 640x400, this is rejected above */
1058        if (mon_type == F_MON_SM) {
1059                if (xres != 640 && yres != 400)
1060                        return -EINVAL;
1061                plen = 1;
1062                pclock = &f32;
1063                /* SM124-mode is special */
1064                par->hw.falcon.ste_mode = 1;
1065                par->hw.falcon.f_shift = 0x000;
1066                par->hw.falcon.st_shift = 0x200;
1067                left_margin = hsync_len = 128 / plen;
1068                right_margin = 0;
1069                /* TODO set all margins */
1070        } else
1071#endif
1072        if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
1073                plen = 2 * xstretch;
1074                if (var->pixclock > f32.t * plen)
1075                        return -EINVAL;
1076                pclock = &f32;
1077                if (yres > 240)
1078                        interlace = 1;
1079                if (var->pixclock == 0) {
1080                        /* set some minimal margins which center the screen */
1081                        left_margin = 32;
1082                        right_margin = 18;
1083                        hsync_len = pclock->hsync / plen;
1084                        upper_margin = 31;
1085                        lower_margin = 14;
1086                        vsync_len = interlace ? 3 : 4;
1087                } else {
1088                        left_margin = var->left_margin;
1089                        right_margin = var->right_margin;
1090                        hsync_len = var->hsync_len;
1091                        upper_margin = var->upper_margin;
1092                        lower_margin = var->lower_margin;
1093                        vsync_len = var->vsync_len;
1094                        if (var->vmode & FB_VMODE_INTERLACED) {
1095                                upper_margin = (upper_margin + 1) / 2;
1096                                lower_margin = (lower_margin + 1) / 2;
1097                                vsync_len = (vsync_len + 1) / 2;
1098                        } else if (var->vmode & FB_VMODE_DOUBLE) {
1099                                upper_margin *= 2;
1100                                lower_margin *= 2;
1101                                vsync_len *= 2;
1102                        }
1103                }
1104        } else {                        /* F_MON_VGA */
1105                if (bpp == 16)
1106                        xstretch = 2;   /* Double pixel width only for hicolor */
1107                /* Default values are used for vert./hor. timing if no pixelclock given. */
1108                if (var->pixclock == 0) {
1109                        int linesize;
1110
1111                        /* Choose master pixelclock depending on hor. timing */
1112                        plen = 1 * xstretch;
1113                        if ((plen * xres + f25.right + f25.hsync + f25.left) *
1114                            fb_info.monspecs.hfmin < f25.f)
1115                                pclock = &f25;
1116                        else if ((plen * xres + f32.right + f32.hsync +
1117                                  f32.left) * fb_info.monspecs.hfmin < f32.f)
1118                                pclock = &f32;
1119                        else if ((plen * xres + fext.right + fext.hsync +
1120                                  fext.left) * fb_info.monspecs.hfmin < fext.f &&
1121                                 fext.f)
1122                                pclock = &fext;
1123                        else
1124                                return -EINVAL;
1125
1126                        left_margin = pclock->left / plen;
1127                        right_margin = pclock->right / plen;
1128                        hsync_len = pclock->hsync / plen;
1129                        linesize = left_margin + xres + right_margin + hsync_len;
1130                        upper_margin = 31;
1131                        lower_margin = 11;
1132                        vsync_len = 3;
1133                } else {
1134                        /* Choose largest pixelclock <= wanted clock */
1135                        int i;
1136                        unsigned long pcl = ULONG_MAX;
1137                        pclock = 0;
1138                        for (i = 1; i <= 4; i *= 2) {
1139                                if (f25.t * i >= var->pixclock &&
1140                                    f25.t * i < pcl) {
1141                                        pcl = f25.t * i;
1142                                        pclock = &f25;
1143                                }
1144                                if (f32.t * i >= var->pixclock &&
1145                                    f32.t * i < pcl) {
1146                                        pcl = f32.t * i;
1147                                        pclock = &f32;
1148                                }
1149                                if (fext.t && fext.t * i >= var->pixclock &&
1150                                    fext.t * i < pcl) {
1151                                        pcl = fext.t * i;
1152                                        pclock = &fext;
1153                                }
1154                        }
1155                        if (!pclock)
1156                                return -EINVAL;
1157                        plen = pcl / pclock->t;
1158
1159                        left_margin = var->left_margin;
1160                        right_margin = var->right_margin;
1161                        hsync_len = var->hsync_len;
1162                        upper_margin = var->upper_margin;
1163                        lower_margin = var->lower_margin;
1164                        vsync_len = var->vsync_len;
1165                        /* Internal unit is [single lines per (half-)frame] */
1166                        if (var->vmode & FB_VMODE_INTERLACED) {
1167                                /* # lines in half frame */
1168                                /* External unit is [lines per full frame] */
1169                                upper_margin = (upper_margin + 1) / 2;
1170                                lower_margin = (lower_margin + 1) / 2;
1171                                vsync_len = (vsync_len + 1) / 2;
1172                        } else if (var->vmode & FB_VMODE_DOUBLE) {
1173                                /* External unit is [double lines per frame] */
1174                                upper_margin *= 2;
1175                                lower_margin *= 2;
1176                                vsync_len *= 2;
1177                        }
1178                }
1179                if (pclock == &fext)
1180                        longoffset = 1; /* VIDEL doesn't synchronize on short offset */
1181        }
1182        /* Is video bus bandwidth (32MB/s) too low for this resolution? */
1183        /* this is definitely wrong if bus clock != 32MHz */
1184        if (pclock->f / plen / 8 * bpp > 32000000L)
1185                return -EINVAL;
1186
1187        if (vsync_len < 1)
1188                vsync_len = 1;
1189
1190        /* include sync lengths in right/lower margin for all calculations */
1191        right_margin += hsync_len;
1192        lower_margin += vsync_len;
1193
1194        /* ! In all calculations of margins we use # of lines in half frame
1195         * (which is a full frame in non-interlace mode), so we can switch
1196         * between interlace and non-interlace without messing around
1197         * with these.
1198         */
1199again:
1200        /* Set base_offset 128 and video bus width */
1201        par->hw.falcon.vid_control = mon_type | f030_bus_width;
1202        if (!longoffset)
1203                par->hw.falcon.vid_control |= VCO_SHORTOFFS;    /* base_offset 64 */
1204        if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1205                par->hw.falcon.vid_control |= VCO_HSYPOS;
1206        if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1207                par->hw.falcon.vid_control |= VCO_VSYPOS;
1208        /* Pixelclock */
1209        par->hw.falcon.vid_control |= pclock->control_mask;
1210        /* External or internal clock */
1211        par->hw.falcon.sync = pclock->sync_mask | 0x2;
1212        /* Pixellength and prescale */
1213        par->hw.falcon.vid_mode = (2 / plen) << 2;
1214        if (doubleline)
1215                par->hw.falcon.vid_mode |= VMO_DOUBLE;
1216        if (interlace)
1217                par->hw.falcon.vid_mode |= VMO_INTER;
1218
1219        /*********************
1220         * Horizontal timing: unit = [master clock cycles]
1221         * unit of hxx-registers: [master clock cycles * prescale]
1222         * Hxx-registers are 9 bit wide
1223         *
1224         * 1 line = ((hht + 2) * 2 * prescale) clock cycles
1225         *
1226         * graphic output = hdb & 0x200 ?
1227         *        ((hht + 2) * 2 - hdb + hde) * prescale - hdboff + hdeoff:
1228         *        (hht + 2  - hdb + hde) * prescale - hdboff + hdeoff
1229         * (this must be a multiple of plen*128/bpp, on VGA pixels
1230         *  to the right may be cut off with a bigger right margin)
1231         *
1232         * start of graphics relative to start of 1st halfline = hdb & 0x200 ?
1233         *        (hdb - hht - 2) * prescale + hdboff :
1234         *        hdb * prescale + hdboff
1235         *
1236         * end of graphics relative to start of 1st halfline =
1237         *        (hde + hht + 2) * prescale + hdeoff
1238         *********************/
1239        /* Calculate VIDEL registers */
1240{
1241        prescale = hxx_prescale(&par->hw.falcon);
1242        base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128;
1243
1244        /* Offsets depend on video mode */
1245        /* Offsets are in clock cycles, divide by prescale to
1246         * calculate hd[be]-registers
1247         */
1248        if (par->hw.falcon.f_shift & 0x100) {
1249                align = 1;
1250                hde_off = 0;
1251                hdb_off = (base_off + 16 * plen) + prescale;
1252        } else {
1253                align = 128 / bpp;
1254                hde_off = ((128 / bpp + 2) * plen);
1255                if (par->hw.falcon.ste_mode)
1256                        hdb_off = (64 + base_off + (128 / bpp + 2) * plen) + prescale;
1257                else
1258                        hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale;
1259        }
1260
1261        gstart = (prescale / 2 + plen * left_margin) / prescale;
1262        /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
1263        gend1 = gstart + roundup(xres, align) * plen / prescale;
1264        /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
1265        gend2 = gstart + xres * plen / prescale;
1266        par->HHT = plen * (left_margin + xres + right_margin) /
1267                           (2 * prescale) - 2;
1268/*      par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
1269
1270        par->HDB = gstart - hdb_off / prescale;
1271        par->HBE = gstart;
1272        if (par->HDB < 0)
1273                par->HDB += par->HHT + 2 + 0x200;
1274        par->HDE = gend1 - par->HHT - 2 - hde_off / prescale;
1275        par->HBB = gend2 - par->HHT - 2;
1276#if 0
1277        /* One more Videl constraint: data fetch of two lines must not overlap */
1278        if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) {
1279                /* if this happens increase margins, decrease hfreq. */
1280        }
1281#endif
1282        if (hde_off % prescale)
1283                par->HBB++;             /* compensate for non matching hde and hbb */
1284        par->HSS = par->HHT + 2 - plen * hsync_len / prescale;
1285        if (par->HSS < par->HBB)
1286                par->HSS = par->HBB;
1287}
1288
1289        /*  check hor. frequency */
1290        hfreq = pclock->f / ((par->HHT + 2) * prescale * 2);
1291        if (hfreq > fb_info.monspecs.hfmax && mon_type != F_MON_VGA) {
1292                /* ++guenther:   ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
1293                /* Too high -> enlarge margin */
1294                left_margin += 1;
1295                right_margin += 1;
1296                goto again;
1297        }
1298        if (hfreq > fb_info.monspecs.hfmax || hfreq < fb_info.monspecs.hfmin)
1299                return -EINVAL;
1300
1301        /* Vxx-registers */
1302        /* All Vxx must be odd in non-interlace, since frame starts in the middle
1303         * of the first displayed line!
1304         * One frame consists of VFT+1 half lines. VFT+1 must be even in
1305         * non-interlace, odd in interlace mode for synchronisation.
1306         * Vxx-registers are 11 bit wide
1307         */
1308        par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */
1309        par->VDB = par->VBE;
1310        par->VDE = yres;
1311        if (!interlace)
1312                par->VDE <<= 1;
1313        if (doubleline)
1314                par->VDE <<= 1;         /* VDE now half lines per (half-)frame */
1315        par->VDE += par->VDB;
1316        par->VBB = par->VDE;
1317        par->VFT = par->VBB + (lower_margin * 2 - 1) - 1;
1318        par->VSS = par->VFT + 1 - (vsync_len * 2 - 1);
1319        /* vbb,vss,vft must be even in interlace mode */
1320        if (interlace) {
1321                par->VBB++;
1322                par->VSS++;
1323                par->VFT++;
1324        }
1325
1326        /* V-frequency check, hope I didn't create any loop here. */
1327        /* Interlace and doubleline are mutually exclusive. */
1328        vfreq = (hfreq * 2) / (par->VFT + 1);
1329        if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
1330                /* Too high -> try again with doubleline */
1331                doubleline = 1;
1332                goto again;
1333        } else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
1334                /* Too low -> try again with interlace */
1335                interlace = 1;
1336                goto again;
1337        } else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
1338                /* Doubleline too low -> clear doubleline and enlarge margins */
1339                int lines;
1340                doubleline = 0;
1341                for (lines = 0;
1342                     (hfreq * 2) / (par->VFT + 1 + 4 * lines - 2 * yres) >
1343                     fb_info.monspecs.vfmax;
1344                     lines++)
1345                        ;
1346                upper_margin += lines;
1347                lower_margin += lines;
1348                goto again;
1349        } else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
1350                /* Doubleline too high -> enlarge margins */
1351                int lines;
1352                for (lines = 0;
1353                     (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
1354                     fb_info.monspecs.vfmax;
1355                     lines += 2)
1356                        ;
1357                upper_margin += lines;
1358                lower_margin += lines;
1359                goto again;
1360        } else if (vfreq > fb_info.monspecs.vfmax && interlace) {
1361                /* Interlace, too high -> enlarge margins */
1362                int lines;
1363                for (lines = 0;
1364                     (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
1365                     fb_info.monspecs.vfmax;
1366                     lines++)
1367                        ;
1368                upper_margin += lines;
1369                lower_margin += lines;
1370                goto again;
1371        } else if (vfreq < fb_info.monspecs.vfmin ||
1372                   vfreq > fb_info.monspecs.vfmax)
1373                return -EINVAL;
1374
1375set_screen_base:
1376        linelen = xres_virtual * bpp / 8;
1377        if (yres_virtual * linelen > screen_len && screen_len)
1378                return -EINVAL;
1379        if (yres * linelen > screen_len && screen_len)
1380                return -EINVAL;
1381        if (var->yoffset + yres > yres_virtual && yres_virtual)
1382                return -EINVAL;
1383        par->yres_virtual = yres_virtual;
1384        par->screen_base = screen_base + var->yoffset * linelen;
1385        par->hw.falcon.xoffset = 0;
1386
1387        par->next_line = linelen;
1388
1389        return 0;
1390}
1391
1392static int falcon_encode_var(struct fb_var_screeninfo *var,
1393                             struct atafb_par *par)
1394{
1395/* !!! only for VGA !!! */
1396        int linelen;
1397        int prescale, plen;
1398        int hdb_off, hde_off, base_off;
1399        struct falcon_hw *hw = &par->hw.falcon;
1400
1401        memset(var, 0, sizeof(struct fb_var_screeninfo));
1402        /* possible frequencies: 25.175 or 32MHz */
1403        var->pixclock = hw->sync & 0x1 ? fext.t :
1404                        hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t;
1405
1406        var->height = -1;
1407        var->width = -1;
1408
1409        var->sync = 0;
1410        if (hw->vid_control & VCO_HSYPOS)
1411                var->sync |= FB_SYNC_HOR_HIGH_ACT;
1412        if (hw->vid_control & VCO_VSYPOS)
1413                var->sync |= FB_SYNC_VERT_HIGH_ACT;
1414
1415        var->vmode = FB_VMODE_NONINTERLACED;
1416        if (hw->vid_mode & VMO_INTER)
1417                var->vmode |= FB_VMODE_INTERLACED;
1418        if (hw->vid_mode & VMO_DOUBLE)
1419                var->vmode |= FB_VMODE_DOUBLE;
1420
1421        /* visible y resolution:
1422         * Graphics display starts at line VDB and ends at line
1423         * VDE. If interlace mode off unit of VC-registers is
1424         * half lines, else lines.
1425         */
1426        var->yres = hw->vde - hw->vdb;
1427        if (!(var->vmode & FB_VMODE_INTERLACED))
1428                var->yres >>= 1;
1429        if (var->vmode & FB_VMODE_DOUBLE)
1430                var->yres >>= 1;
1431
1432        /*
1433         * to get bpp, we must examine f_shift and st_shift.
1434         * f_shift is valid if any of bits no. 10, 8 or 4
1435         * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
1436         * if bit 10 set then bit 8 and bit 4 don't care...
1437         * If all these bits are 0 get display depth from st_shift
1438         * (as for ST and STE)
1439         */
1440        if (hw->f_shift & 0x400)        /* 2 colors */
1441                var->bits_per_pixel = 1;
1442        else if (hw->f_shift & 0x100)   /* hicolor */
1443                var->bits_per_pixel = 16;
1444        else if (hw->f_shift & 0x010)   /* 8 bitplanes */
1445                var->bits_per_pixel = 8;
1446        else if (hw->st_shift == 0)
1447                var->bits_per_pixel = 4;
1448        else if (hw->st_shift == 0x100)
1449                var->bits_per_pixel = 2;
1450        else                            /* if (hw->st_shift == 0x200) */
1451                var->bits_per_pixel = 1;
1452
1453        var->xres = hw->line_width * 16 / var->bits_per_pixel;
1454        var->xres_virtual = var->xres + hw->line_offset * 16 / var->bits_per_pixel;
1455        if (hw->xoffset)
1456                var->xres_virtual += 16;
1457
1458        if (var->bits_per_pixel == 16) {
1459                var->red.offset = 11;
1460                var->red.length = 5;
1461                var->red.msb_right = 0;
1462                var->green.offset = 5;
1463                var->green.length = 6;
1464                var->green.msb_right = 0;
1465                var->blue.offset = 0;
1466                var->blue.length = 5;
1467                var->blue.msb_right = 0;
1468        } else {
1469                var->red.offset = 0;
1470                var->red.length = hw->ste_mode ? 4 : 6;
1471                if (var->red.length > var->bits_per_pixel)
1472                        var->red.length = var->bits_per_pixel;
1473                var->red.msb_right = 0;
1474                var->grayscale = 0;
1475                var->blue = var->green = var->red;
1476        }
1477        var->transp.offset = 0;
1478        var->transp.length = 0;
1479        var->transp.msb_right = 0;
1480
1481        linelen = var->xres_virtual * var->bits_per_pixel / 8;
1482        if (screen_len) {
1483                if (par->yres_virtual)
1484                        var->yres_virtual = par->yres_virtual;
1485                else
1486                        /* yres_virtual == 0 means use maximum */
1487                        var->yres_virtual = screen_len / linelen;
1488        } else {
1489                if (hwscroll < 0)
1490                        var->yres_virtual = 2 * var->yres;
1491                else
1492                        var->yres_virtual = var->yres + hwscroll * 16;
1493        }
1494        var->xoffset = 0;               /* TODO change this */
1495
1496        /* hdX-offsets */
1497        prescale = hxx_prescale(hw);
1498        plen = 4 >> (hw->vid_mode >> 2 & 0x3);
1499        base_off = hw->vid_control & VCO_SHORTOFFS ? 64 : 128;
1500        if (hw->f_shift & 0x100) {
1501                hde_off = 0;
1502                hdb_off = (base_off + 16 * plen) + prescale;
1503        } else {
1504                hde_off = ((128 / var->bits_per_pixel + 2) * plen);
1505                if (hw->ste_mode)
1506                        hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)
1507                                         + prescale;
1508                else
1509                        hdb_off = (base_off + (128 / var->bits_per_pixel + 18) * plen)
1510                                         + prescale;
1511        }
1512
1513        /* Right margin includes hsync */
1514        var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) -
1515                                           (hw->hdb & 0x200 ? 2 + hw->hht : 0));
1516        if (hw->ste_mode || mon_type != F_MON_VGA)
1517                var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off;
1518        else
1519                /* can't use this in ste_mode, because hbb is +1 off */
1520                var->right_margin = prescale * (hw->hht + 2 - hw->hbb);
1521        var->hsync_len = prescale * (hw->hht + 2 - hw->hss);
1522
1523        /* Lower margin includes vsync */
1524        var->upper_margin = hw->vdb / 2;        /* round down to full lines */
1525        var->lower_margin = (hw->vft + 1 - hw->vde + 1) / 2;    /* round up */
1526        var->vsync_len = (hw->vft + 1 - hw->vss + 1) / 2;       /* round up */
1527        if (var->vmode & FB_VMODE_INTERLACED) {
1528                var->upper_margin *= 2;
1529                var->lower_margin *= 2;
1530                var->vsync_len *= 2;
1531        } else if (var->vmode & FB_VMODE_DOUBLE) {
1532                var->upper_margin = (var->upper_margin + 1) / 2;
1533                var->lower_margin = (var->lower_margin + 1) / 2;
1534                var->vsync_len = (var->vsync_len + 1) / 2;
1535        }
1536
1537        var->pixclock *= plen;
1538        var->left_margin /= plen;
1539        var->right_margin /= plen;
1540        var->hsync_len /= plen;
1541
1542        var->right_margin -= var->hsync_len;
1543        var->lower_margin -= var->vsync_len;
1544
1545        if (screen_base)
1546                var->yoffset = (par->screen_base - screen_base) / linelen;
1547        else
1548                var->yoffset = 0;
1549        var->nonstd = 0;                /* what is this for? */
1550        var->activate = 0;
1551        return 0;
1552}
1553
1554static int f_change_mode;
1555static struct falcon_hw f_new_mode;
1556static int f_pan_display;
1557
1558static void falcon_get_par(struct atafb_par *par)
1559{
1560        unsigned long addr;
1561        struct falcon_hw *hw = &par->hw.falcon;
1562
1563        hw->line_width = shifter_f030.scn_width;
1564        hw->line_offset = shifter_f030.off_next;
1565        hw->st_shift = videl.st_shift & 0x300;
1566        hw->f_shift = videl.f_shift;
1567        hw->vid_control = videl.control;
1568        hw->vid_mode = videl.mode;
1569        hw->sync = shifter.syncmode & 0x1;
1570        hw->xoffset = videl.xoffset & 0xf;
1571        hw->hht = videl.hht;
1572        hw->hbb = videl.hbb;
1573        hw->hbe = videl.hbe;
1574        hw->hdb = videl.hdb;
1575        hw->hde = videl.hde;
1576        hw->hss = videl.hss;
1577        hw->vft = videl.vft;
1578        hw->vbb = videl.vbb;
1579        hw->vbe = videl.vbe;
1580        hw->vdb = videl.vdb;
1581        hw->vde = videl.vde;
1582        hw->vss = videl.vss;
1583
1584        addr = (shifter.bas_hi & 0xff) << 16 |
1585               (shifter.bas_md & 0xff) << 8  |
1586               (shifter.bas_lo & 0xff);
1587        par->screen_base = phys_to_virt(addr);
1588
1589        /* derived parameters */
1590        hw->ste_mode = (hw->f_shift & 0x510) == 0 && hw->st_shift == 0x100;
1591        hw->mono = (hw->f_shift & 0x400) ||
1592                   ((hw->f_shift & 0x510) == 0 && hw->st_shift == 0x200);
1593}
1594
1595static void falcon_set_par(struct atafb_par *par)
1596{
1597        f_change_mode = 0;
1598
1599        /* only set screen_base if really necessary */
1600        if (current_par.screen_base != par->screen_base)
1601                fbhw->set_screen_base(par->screen_base);
1602
1603        /* Don't touch any other registers if we keep the default resolution */
1604        if (DontCalcRes)
1605                return;
1606
1607        /* Tell vbl-handler to change video mode.
1608         * We change modes only on next VBL, to avoid desynchronisation
1609         * (a shift to the right and wrap around by a random number of pixels
1610         * in all monochrome modes).
1611         * This seems to work on my Falcon.
1612         */
1613        f_new_mode = par->hw.falcon;
1614        f_change_mode = 1;
1615}
1616
1617static irqreturn_t falcon_vbl_switcher(int irq, void *dummy)
1618{
1619        struct falcon_hw *hw = &f_new_mode;
1620
1621        if (f_change_mode) {
1622                f_change_mode = 0;
1623
1624                if (hw->sync & 0x1) {
1625                        /* Enable external pixelclock. This code only for ScreenWonder */
1626                        *(volatile unsigned short *)0xffff9202 = 0xffbf;
1627                } else {
1628                        /* Turn off external clocks. Read sets all output bits to 1. */
1629                        *(volatile unsigned short *)0xffff9202;
1630                }
1631                shifter.syncmode = hw->sync;
1632
1633                videl.hht = hw->hht;
1634                videl.hbb = hw->hbb;
1635                videl.hbe = hw->hbe;
1636                videl.hdb = hw->hdb;
1637                videl.hde = hw->hde;
1638                videl.hss = hw->hss;
1639                videl.vft = hw->vft;
1640                videl.vbb = hw->vbb;
1641                videl.vbe = hw->vbe;
1642                videl.vdb = hw->vdb;
1643                videl.vde = hw->vde;
1644                videl.vss = hw->vss;
1645
1646                videl.f_shift = 0;      /* write enables Falcon palette, 0: 4 planes */
1647                if (hw->ste_mode) {
1648                        videl.st_shift = hw->st_shift;  /* write enables STE palette */
1649                } else {
1650                        /* IMPORTANT:
1651                         * set st_shift 0, so we can tell the screen-depth if f_shift == 0.
1652                         * Writing 0 to f_shift enables 4 plane Falcon mode but
1653                         * doesn't set st_shift. st_shift != 0 (!= 4planes) is impossible
1654                         * with Falcon palette.
1655                         */
1656                        videl.st_shift = 0;
1657                        /* now back to Falcon palette mode */
1658                        videl.f_shift = hw->f_shift;
1659                }
1660                /* writing to st_shift changed scn_width and vid_mode */
1661                videl.xoffset = hw->xoffset;
1662                shifter_f030.scn_width = hw->line_width;
1663                shifter_f030.off_next = hw->line_offset;
1664                videl.control = hw->vid_control;
1665                videl.mode = hw->vid_mode;
1666        }
1667        if (f_pan_display) {
1668                f_pan_display = 0;
1669                videl.xoffset = current_par.hw.falcon.xoffset;
1670                shifter_f030.off_next = current_par.hw.falcon.line_offset;
1671        }
1672        return IRQ_HANDLED;
1673}
1674
1675static int falcon_pan_display(struct fb_var_screeninfo *var,
1676                              struct fb_info *info)
1677{
1678        struct atafb_par *par = (struct atafb_par *)info->par;
1679
1680        int xoffset;
1681        int bpp = info->var.bits_per_pixel;
1682
1683        if (bpp == 1)
1684                var->xoffset = up(var->xoffset, 32);
1685        if (bpp != 16)
1686                par->hw.falcon.xoffset = var->xoffset & 15;
1687        else {
1688                par->hw.falcon.xoffset = 0;
1689                var->xoffset = up(var->xoffset, 2);
1690        }
1691        par->hw.falcon.line_offset = bpp *
1692                (info->var.xres_virtual - info->var.xres) / 16;
1693        if (par->hw.falcon.xoffset)
1694                par->hw.falcon.line_offset -= bpp;
1695        xoffset = var->xoffset - par->hw.falcon.xoffset;
1696
1697        par->screen_base = screen_base +
1698                (var->yoffset * info->var.xres_virtual + xoffset) * bpp / 8;
1699        if (fbhw->set_screen_base)
1700                fbhw->set_screen_base(par->screen_base);
1701        else
1702                return -EINVAL;         /* shouldn't happen */
1703        f_pan_display = 1;
1704        return 0;
1705}
1706
1707static int falcon_setcolreg(unsigned int regno, unsigned int red,
1708                            unsigned int green, unsigned int blue,
1709                            unsigned int transp, struct fb_info *info)
1710{
1711        if (regno > 255)
1712                return 1;
1713        f030_col[regno] = (((red & 0xfc00) << 16) |
1714                           ((green & 0xfc00) << 8) |
1715                           ((blue & 0xfc00) >> 8));
1716        if (regno < 16) {
1717                shifter_tt.color_reg[regno] =
1718                        (((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
1719                        (((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
1720                        ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
1721                ((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) |
1722                                                       ((green & 0xfc00) >> 5) |
1723                                                       ((blue & 0xf800) >> 11));
1724        }
1725        return 0;
1726}
1727
1728static int falcon_blank(int blank_mode)
1729{
1730        /* ++guenther: we can switch off graphics by changing VDB and VDE,
1731         * so VIDEL doesn't hog the bus while saving.
1732         * (this may affect usleep()).
1733         */
1734        int vdb, vss, hbe, hss;
1735
1736        if (mon_type == F_MON_SM)       /* this doesn't work on SM124 */
1737                return 1;
1738
1739        vdb = current_par.VDB;
1740        vss = current_par.VSS;
1741        hbe = current_par.HBE;
1742        hss = current_par.HSS;
1743
1744        if (blank_mode >= 1) {
1745                /* disable graphics output (this speeds up the CPU) ... */
1746                vdb = current_par.VFT + 1;
1747                /* ... and blank all lines */
1748                hbe = current_par.HHT + 2;
1749        }
1750        /* use VESA suspend modes on VGA monitors */
1751        if (mon_type == F_MON_VGA) {
1752                if (blank_mode == 2 || blank_mode == 4)
1753                        vss = current_par.VFT + 1;
1754                if (blank_mode == 3 || blank_mode == 4)
1755                        hss = current_par.HHT + 2;
1756        }
1757
1758        videl.vdb = vdb;
1759        videl.vss = vss;
1760        videl.hbe = hbe;
1761        videl.hss = hss;
1762
1763        return 0;
1764}
1765
1766static int falcon_detect(void)
1767{
1768        struct atafb_par par;
1769        unsigned char fhw;
1770
1771        /* Determine connected monitor and set monitor parameters */
1772        fhw = *(unsigned char *)0xffff8006;
1773        mon_type = fhw >> 6 & 0x3;
1774        /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
1775        f030_bus_width = fhw << 6 & 0x80;
1776        switch (mon_type) {
1777        case F_MON_SM:
1778                fb_info.monspecs.vfmin = 70;
1779                fb_info.monspecs.vfmax = 72;
1780                fb_info.monspecs.hfmin = 35713;
1781                fb_info.monspecs.hfmax = 35715;
1782                break;
1783        case F_MON_SC:
1784        case F_MON_TV:
1785                /* PAL...NTSC */
1786                fb_info.monspecs.vfmin = 49;    /* not 50, since TOS defaults to 49.9x Hz */
1787                fb_info.monspecs.vfmax = 60;
1788                fb_info.monspecs.hfmin = 15620;
1789                fb_info.monspecs.hfmax = 15755;
1790                break;
1791        }
1792        /* initialize hsync-len */
1793        f25.hsync = h_syncs[mon_type] / f25.t;
1794        f32.hsync = h_syncs[mon_type] / f32.t;
1795        if (fext.t)
1796                fext.hsync = h_syncs[mon_type] / fext.t;
1797
1798        falcon_get_par(&par);
1799        falcon_encode_var(&atafb_predefined[0], &par);
1800
1801        /* Detected mode is always the "autodetect" slot */
1802        return 1;
1803}
1804
1805#endif /* ATAFB_FALCON */
1806
1807/* ------------------- ST(E) specific functions ---------------------- */
1808
1809#ifdef ATAFB_STE
1810
1811static int stste_encode_fix(struct fb_fix_screeninfo *fix,
1812                            struct atafb_par *par)
1813{
1814        int mode;
1815
1816        strcpy(fix->id, "Atari Builtin");
1817        fix->smem_start = (unsigned long)real_screen_base;
1818        fix->smem_len = screen_len;
1819        fix->type = FB_TYPE_INTERLEAVED_PLANES;
1820        fix->type_aux = 2;
1821        fix->visual = FB_VISUAL_PSEUDOCOLOR;
1822        mode = par->hw.st.mode & 3;
1823        if (mode == ST_HIGH) {
1824                fix->type = FB_TYPE_PACKED_PIXELS;
1825                fix->type_aux = 0;
1826                fix->visual = FB_VISUAL_MONO10;
1827        }
1828        if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
1829                fix->xpanstep = 16;
1830                fix->ypanstep = 1;
1831        } else {
1832                fix->xpanstep = 0;
1833                fix->ypanstep = 0;
1834        }
1835        fix->ywrapstep = 0;
1836        fix->line_length = par->next_line;
1837        fix->accel = FB_ACCEL_ATARIBLITT;
1838        return 0;
1839}
1840
1841static int stste_decode_var(struct fb_var_screeninfo *var,
1842                            struct atafb_par *par)
1843{
1844        int xres = var->xres;
1845        int yres = var->yres;
1846        int bpp = var->bits_per_pixel;
1847        int linelen;
1848        int yres_virtual = var->yres_virtual;
1849
1850        if (mono_moni) {
1851                if (bpp > 1 || xres > sttt_xres || yres > st_yres)
1852                        return -EINVAL;
1853                par->hw.st.mode = ST_HIGH;
1854                xres = sttt_xres;
1855                yres = st_yres;
1856                bpp = 1;
1857        } else {
1858                if (bpp > 4 || xres > sttt_xres || yres > st_yres)
1859                        return -EINVAL;
1860                if (bpp > 2) {
1861                        if (xres > sttt_xres / 2 || yres > st_yres / 2)
1862                                return -EINVAL;
1863                        par->hw.st.mode = ST_LOW;
1864                        xres = sttt_xres / 2;
1865                        yres = st_yres / 2;
1866                        bpp = 4;
1867                } else if (bpp > 1) {
1868                        if (xres > sttt_xres || yres > st_yres / 2)
1869                                return -EINVAL;
1870                        par->hw.st.mode = ST_MID;
1871                        xres = sttt_xres;
1872                        yres = st_yres / 2;
1873                        bpp = 2;
1874                } else
1875                        return -EINVAL;
1876        }
1877        if (yres_virtual <= 0)
1878                yres_virtual = 0;
1879        else if (yres_virtual < yres)
1880                yres_virtual = yres;
1881        if (var->sync & FB_SYNC_EXT)
1882                par->hw.st.sync = (par->hw.st.sync & ~1) | 1;
1883        else
1884                par->hw.st.sync = (par->hw.st.sync & ~1);
1885        linelen = xres * bpp / 8;
1886        if (yres_virtual * linelen > screen_len && screen_len)
1887                return -EINVAL;
1888        if (yres * linelen > screen_len && screen_len)
1889                return -EINVAL;
1890        if (var->yoffset + yres > yres_virtual && yres_virtual)
1891                return -EINVAL;
1892        par->yres_virtual = yres_virtual;
1893        par->screen_base = screen_base + var->yoffset * linelen;
1894        par->next_line = linelen;
1895        return 0;
1896}
1897
1898static int stste_encode_var(struct fb_var_screeninfo *var,
1899                            struct atafb_par *par)
1900{
1901        int linelen;
1902        memset(var, 0, sizeof(struct fb_var_screeninfo));
1903        var->red.offset = 0;
1904        var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
1905        var->red.msb_right = 0;
1906        var->grayscale = 0;
1907
1908        var->pixclock = 31041;
1909        var->left_margin = 120;         /* these are incorrect */
1910        var->right_margin = 100;
1911        var->upper_margin = 8;
1912        var->lower_margin = 16;
1913        var->hsync_len = 140;
1914        var->vsync_len = 30;
1915
1916        var->height = -1;
1917        var->width = -1;
1918
1919        if (!(par->hw.st.sync & 1))
1920                var->sync = 0;
1921        else
1922                var->sync = FB_SYNC_EXT;
1923
1924        switch (par->hw.st.mode & 3) {
1925        case ST_LOW:
1926                var->xres = sttt_xres / 2;
1927                var->yres = st_yres / 2;
1928                var->bits_per_pixel = 4;
1929                break;
1930        case ST_MID:
1931                var->xres = sttt_xres;
1932                var->yres = st_yres / 2;
1933                var->bits_per_pixel = 2;
1934                break;
1935        case ST_HIGH:
1936                var->xres = sttt_xres;
1937                var->yres = st_yres;
1938                var->bits_per_pixel = 1;
1939                break;
1940        }
1941        var->blue = var->green = var->red;
1942        var->transp.offset = 0;
1943        var->transp.length = 0;
1944        var->transp.msb_right = 0;
1945        var->xres_virtual = sttt_xres_virtual;
1946        linelen = var->xres_virtual * var->bits_per_pixel / 8;
1947        ovsc_addlen = linelen * (sttt_yres_virtual - st_yres);
1948
1949        if (!use_hwscroll)
1950                var->yres_virtual = var->yres;
1951        else if (screen_len) {
1952                if (par->yres_virtual)
1953                        var->yres_virtual = par->yres_virtual;
1954                else
1955                        /* yres_virtual == 0 means use maximum */
1956                        var->yres_virtual = screen_len / linelen;
1957        } else {
1958                if (hwscroll < 0)
1959                        var->yres_virtual = 2 * var->yres;
1960                else
1961                        var->yres_virtual = var->yres + hwscroll * 16;
1962        }
1963        var->xoffset = 0;
1964        if (screen_base)
1965                var->yoffset = (par->screen_base - screen_base) / linelen;
1966        else
1967                var->yoffset = 0;
1968        var->nonstd = 0;
1969        var->activate = 0;
1970        var->vmode = FB_VMODE_NONINTERLACED;
1971        return 0;
1972}
1973
1974static void stste_get_par(struct atafb_par *par)
1975{
1976        unsigned long addr;
1977        par->hw.st.mode = shifter_tt.st_shiftmode;
1978        par->hw.st.sync = shifter.syncmode;
1979        addr = ((shifter.bas_hi & 0xff) << 16) |
1980               ((shifter.bas_md & 0xff) << 8);
1981        if (ATARIHW_PRESENT(EXTD_SHIFTER))
1982                addr |= (shifter.bas_lo & 0xff);
1983        par->screen_base = phys_to_virt(addr);
1984}
1985
1986static void stste_set_par(struct atafb_par *par)
1987{
1988        shifter_tt.st_shiftmode = par->hw.st.mode;
1989        shifter.syncmode = par->hw.st.sync;
1990        /* only set screen_base if really necessary */
1991        if (current_par.screen_base != par->screen_base)
1992                fbhw->set_screen_base(par->screen_base);
1993}
1994
1995static int stste_setcolreg(unsigned int regno, unsigned int red,
1996                           unsigned int green, unsigned int blue,
1997                           unsigned int transp, struct fb_info *info)
1998{
1999        if (regno > 15)
2000                return 1;
2001        red >>= 12;
2002        blue >>= 12;
2003        green >>= 12;
2004        if (ATARIHW_PRESENT(EXTD_SHIFTER))
2005                shifter_tt.color_reg[regno] =
2006                        (((red & 0xe) >> 1) | ((red & 1) << 3) << 8) |
2007                        (((green & 0xe) >> 1) | ((green & 1) << 3) << 4) |
2008                        ((blue & 0xe) >> 1) | ((blue & 1) << 3);
2009        else
2010                shifter_tt.color_reg[regno] =
2011                        ((red & 0xe) << 7) |
2012                        ((green & 0xe) << 3) |
2013                        ((blue & 0xe) >> 1);
2014        return 0;
2015}
2016
2017static int stste_detect(void)
2018{
2019        struct atafb_par par;
2020
2021        /* Determine the connected monitor: The DMA sound must be
2022         * disabled before reading the MFP GPIP, because the Sound
2023         * Done Signal and the Monochrome Detect are XORed together!
2024         */
2025        if (ATARIHW_PRESENT(PCM_8BIT)) {
2026                tt_dmasnd.ctrl = DMASND_CTRL_OFF;
2027                udelay(20);             /* wait a while for things to settle down */
2028        }
2029        mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
2030
2031        stste_get_par(&par);
2032        stste_encode_var(&atafb_predefined[0], &par);
2033
2034        if (!ATARIHW_PRESENT(EXTD_SHIFTER))
2035                use_hwscroll = 0;
2036        return 1;
2037}
2038
2039static void stste_set_screen_base(void *s_base)
2040{
2041        unsigned long addr;
2042        addr = virt_to_phys(s_base);
2043        /* Setup Screen Memory */
2044        shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
2045        shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
2046        if (ATARIHW_PRESENT(EXTD_SHIFTER))
2047                shifter.bas_lo = (unsigned char)(addr & 0x0000ff);
2048}
2049
2050#endif /* ATAFB_STE */
2051
2052/* Switching the screen size should be done during vsync, otherwise
2053 * the margins may get messed up. This is a well known problem of
2054 * the ST's video system.
2055 *
2056 * Unfortunately there is hardly any way to find the vsync, as the
2057 * vertical blank interrupt is no longer in time on machines with
2058 * overscan type modifications.
2059 *
2060 * We can, however, use Timer B to safely detect the black shoulder,
2061 * but then we've got to guess an appropriate delay to find the vsync.
2062 * This might not work on every machine.
2063 *
2064 * martin_rogge @ ki.maus.de, 8th Aug 1995
2065 */
2066
2067#define LINE_DELAY  (mono_moni ? 30 : 70)
2068#define SYNC_DELAY  (mono_moni ? 1500 : 2000)
2069
2070/* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
2071static void st_ovsc_switch(void)
2072{
2073        unsigned long flags;
2074        register unsigned char old, new;
2075
2076        if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
2077                return;
2078        local_irq_save(flags);
2079
2080        st_mfp.tim_ct_b = 0x10;
2081        st_mfp.active_edge |= 8;
2082        st_mfp.tim_ct_b = 0;
2083        st_mfp.tim_dt_b = 0xf0;
2084        st_mfp.tim_ct_b = 8;
2085        while (st_mfp.tim_dt_b > 1)     /* TOS does it this way, don't ask why */
2086                ;
2087        new = st_mfp.tim_dt_b;
2088        do {
2089                udelay(LINE_DELAY);
2090                old = new;
2091                new = st_mfp.tim_dt_b;
2092        } while (old != new);
2093        st_mfp.tim_ct_b = 0x10;
2094        udelay(SYNC_DELAY);
2095
2096        if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
2097                acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
2098        if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
2099                acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
2100        if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
2101                sound_ym.rd_data_reg_sel = 14;
2102                sound_ym.wd_data = sound_ym.rd_data_reg_sel |
2103                                   ((atari_switches & ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
2104                                   ((atari_switches & ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
2105        }
2106        local_irq_restore(flags);
2107}
2108
2109/* ------------------- External Video ---------------------- */
2110
2111#ifdef ATAFB_EXT
2112
2113static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
2114{
2115        strcpy(fix->id, "Unknown Extern");
2116        fix->smem_start = (unsigned long)external_addr;
2117        fix->smem_len = PAGE_ALIGN(external_len);
2118        if (external_depth == 1) {
2119                fix->type = FB_TYPE_PACKED_PIXELS;
2120                /* The letters 'n' and 'i' in the "atavideo=external:" stand
2121                 * for "normal" and "inverted", rsp., in the monochrome case */
2122                fix->visual =
2123                        (external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
2124                         external_pmode == FB_TYPE_PACKED_PIXELS) ?
2125                                FB_VISUAL_MONO10 : FB_VISUAL_MONO01;
2126        } else {
2127                /* Use STATIC if we don't know how to access color registers */
2128                int visual = external_vgaiobase ?
2129                                         FB_VISUAL_PSEUDOCOLOR :
2130                                         FB_VISUAL_STATIC_PSEUDOCOLOR;
2131                switch (external_pmode) {
2132                case -1:                /* truecolor */
2133                        fix->type = FB_TYPE_PACKED_PIXELS;
2134                        fix->visual = FB_VISUAL_TRUECOLOR;
2135                        break;
2136                case FB_TYPE_PACKED_PIXELS:
2137                        fix->type = FB_TYPE_PACKED_PIXELS;
2138                        fix->visual = visual;
2139                        break;
2140                case FB_TYPE_PLANES:
2141                        fix->type = FB_TYPE_PLANES;
2142                        fix->visual = visual;
2143                        break;
2144                case FB_TYPE_INTERLEAVED_PLANES:
2145                        fix->type = FB_TYPE_INTERLEAVED_PLANES;
2146                        fix->type_aux = 2;
2147                        fix->visual = visual;
2148                        break;
2149                }
2150        }
2151        fix->xpanstep = 0;
2152        fix->ypanstep = 0;
2153        fix->ywrapstep = 0;
2154        fix->line_length = par->next_line;
2155        return 0;
2156}
2157
2158static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
2159{
2160        struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2161
2162        if (var->bits_per_pixel > myvar->bits_per_pixel ||
2163            var->xres > myvar->xres ||
2164            var->xres_virtual > myvar->xres_virtual ||
2165            var->yres > myvar->yres ||
2166            var->xoffset > 0 ||
2167            var->yoffset > 0)
2168                return -EINVAL;
2169
2170        par->next_line = external_xres_virtual * external_depth / 8;
2171        return 0;
2172}
2173
2174static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
2175{
2176        memset(var, 0, sizeof(struct fb_var_screeninfo));
2177        var->red.offset = 0;
2178        var->red.length = (external_pmode == -1) ? external_depth / 3 :
2179                        (external_vgaiobase ? external_bitspercol : 0);
2180        var->red.msb_right = 0;
2181        var->grayscale = 0;
2182
2183        var->pixclock = 31041;
2184        var->left_margin = 120;         /* these are surely incorrect */
2185        var->right_margin = 100;
2186        var->upper_margin = 8;
2187        var->lower_margin = 16;
2188        var->hsync_len = 140;
2189        var->vsync_len = 30;
2190
2191        var->height = -1;
2192        var->width = -1;
2193
2194        var->sync = 0;
2195
2196        var->xres = external_xres;
2197        var->yres = external_yres;
2198        var->xres_virtual = external_xres_virtual;
2199        var->bits_per_pixel = external_depth;
2200
2201        var->blue = var->green = var->red;
2202        var->transp.offset = 0;
2203        var->transp.length = 0;
2204        var->transp.msb_right = 0;
2205        var->yres_virtual = var->yres;
2206        var->xoffset = 0;
2207        var->yoffset = 0;
2208        var->nonstd = 0;
2209        var->activate = 0;
2210        var->vmode = FB_VMODE_NONINTERLACED;
2211        return 0;
2212}
2213
2214static void ext_get_par(struct atafb_par *par)
2215{
2216        par->screen_base = external_addr;
2217}
2218
2219static void ext_set_par(struct atafb_par *par)
2220{
2221}
2222
2223#define OUTB(port,val) \
2224        *((unsigned volatile char *) ((port)+external_vgaiobase)) = (val)
2225#define INB(port) \
2226        (*((unsigned volatile char *) ((port)+external_vgaiobase)))
2227#define DACDelay                                \
2228        do {                                    \
2229                unsigned char tmp = INB(0x3da); \
2230                tmp = INB(0x3da);                       \
2231        } while (0)
2232
2233static int ext_setcolreg(unsigned int regno, unsigned int red,
2234                         unsigned int green, unsigned int blue,
2235                         unsigned int transp, struct fb_info *info)
2236{
2237        unsigned char colmask = (1 << external_bitspercol) - 1;
2238
2239        if (!external_vgaiobase)
2240                return 1;
2241
2242        if (regno > 255)
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