cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

atafb.c (90099B)


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