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