^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 *)¤t_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 *)¤t_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(¤t_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(¤t_par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3175) fb_info.par = ¤t_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);