brintos

brintos / linux-shallow public Read only

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