Linux Audio

Check our new training course

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