Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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