18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci *  drivers/video/imsttfb.c -- frame buffer device for IMS TwinTurbo
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci *  This file is derived from the powermac console "imstt" driver:
58c2ecf20Sopenharmony_ci *  Copyright (C) 1997 Sigurdur Asgeirsson
68c2ecf20Sopenharmony_ci *  With additional hacking by Jeffrey Kuskin (jsk@mojave.stanford.edu)
78c2ecf20Sopenharmony_ci *  Modified by Danilo Beuche 1998
88c2ecf20Sopenharmony_ci *  Some register values added by Damien Doligez, INRIA Rocquencourt
98c2ecf20Sopenharmony_ci *  Various cleanups by Paul Mundt (lethal@chaoticdreams.org)
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci *  This file was written by Ryan Nielsen (ran@krazynet.com)
128c2ecf20Sopenharmony_ci *  Most of the frame buffer device stuff was copied from atyfb.c
138c2ecf20Sopenharmony_ci *
148c2ecf20Sopenharmony_ci *  This file is subject to the terms and conditions of the GNU General Public
158c2ecf20Sopenharmony_ci *  License. See the file COPYING in the main directory of this archive for
168c2ecf20Sopenharmony_ci *  more details.
178c2ecf20Sopenharmony_ci */
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#include <linux/module.h>
208c2ecf20Sopenharmony_ci#include <linux/kernel.h>
218c2ecf20Sopenharmony_ci#include <linux/errno.h>
228c2ecf20Sopenharmony_ci#include <linux/string.h>
238c2ecf20Sopenharmony_ci#include <linux/mm.h>
248c2ecf20Sopenharmony_ci#include <linux/vmalloc.h>
258c2ecf20Sopenharmony_ci#include <linux/delay.h>
268c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
278c2ecf20Sopenharmony_ci#include <linux/fb.h>
288c2ecf20Sopenharmony_ci#include <linux/init.h>
298c2ecf20Sopenharmony_ci#include <linux/pci.h>
308c2ecf20Sopenharmony_ci#include <asm/io.h>
318c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#if defined(CONFIG_PPC_PMAC)
348c2ecf20Sopenharmony_ci#include <linux/nvram.h>
358c2ecf20Sopenharmony_ci#include "macmodes.h"
368c2ecf20Sopenharmony_ci#endif
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#ifndef __powerpc__
398c2ecf20Sopenharmony_ci#define eieio()		/* Enforce In-order Execution of I/O */
408c2ecf20Sopenharmony_ci#endif
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci/* TwinTurbo (Cosmo) registers */
438c2ecf20Sopenharmony_cienum {
448c2ecf20Sopenharmony_ci	S1SA	=  0, /* 0x00 */
458c2ecf20Sopenharmony_ci	S2SA	=  1, /* 0x04 */
468c2ecf20Sopenharmony_ci	SP	=  2, /* 0x08 */
478c2ecf20Sopenharmony_ci	DSA	=  3, /* 0x0C */
488c2ecf20Sopenharmony_ci	CNT	=  4, /* 0x10 */
498c2ecf20Sopenharmony_ci	DP_OCTL	=  5, /* 0x14 */
508c2ecf20Sopenharmony_ci	CLR	=  6, /* 0x18 */
518c2ecf20Sopenharmony_ci	BI	=  8, /* 0x20 */
528c2ecf20Sopenharmony_ci	MBC	=  9, /* 0x24 */
538c2ecf20Sopenharmony_ci	BLTCTL	= 10, /* 0x28 */
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	/* Scan Timing Generator Registers */
568c2ecf20Sopenharmony_ci	HES	= 12, /* 0x30 */
578c2ecf20Sopenharmony_ci	HEB	= 13, /* 0x34 */
588c2ecf20Sopenharmony_ci	HSB	= 14, /* 0x38 */
598c2ecf20Sopenharmony_ci	HT	= 15, /* 0x3C */
608c2ecf20Sopenharmony_ci	VES	= 16, /* 0x40 */
618c2ecf20Sopenharmony_ci	VEB	= 17, /* 0x44 */
628c2ecf20Sopenharmony_ci	VSB	= 18, /* 0x48 */
638c2ecf20Sopenharmony_ci	VT	= 19, /* 0x4C */
648c2ecf20Sopenharmony_ci	HCIV	= 20, /* 0x50 */
658c2ecf20Sopenharmony_ci	VCIV	= 21, /* 0x54 */
668c2ecf20Sopenharmony_ci	TCDR	= 22, /* 0x58 */
678c2ecf20Sopenharmony_ci	VIL	= 23, /* 0x5C */
688c2ecf20Sopenharmony_ci	STGCTL	= 24, /* 0x60 */
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	/* Screen Refresh Generator Registers */
718c2ecf20Sopenharmony_ci	SSR	= 25, /* 0x64 */
728c2ecf20Sopenharmony_ci	HRIR	= 26, /* 0x68 */
738c2ecf20Sopenharmony_ci	SPR	= 27, /* 0x6C */
748c2ecf20Sopenharmony_ci	CMR	= 28, /* 0x70 */
758c2ecf20Sopenharmony_ci	SRGCTL	= 29, /* 0x74 */
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	/* RAM Refresh Generator Registers */
788c2ecf20Sopenharmony_ci	RRCIV	= 30, /* 0x78 */
798c2ecf20Sopenharmony_ci	RRSC	= 31, /* 0x7C */
808c2ecf20Sopenharmony_ci	RRCR	= 34, /* 0x88 */
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	/* System Registers */
838c2ecf20Sopenharmony_ci	GIOE	= 32, /* 0x80 */
848c2ecf20Sopenharmony_ci	GIO	= 33, /* 0x84 */
858c2ecf20Sopenharmony_ci	SCR	= 35, /* 0x8C */
868c2ecf20Sopenharmony_ci	SSTATUS	= 36, /* 0x90 */
878c2ecf20Sopenharmony_ci	PRC	= 37, /* 0x94 */
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci#if 0
908c2ecf20Sopenharmony_ci	/* PCI Registers */
918c2ecf20Sopenharmony_ci	DVID	= 0x00000000L,
928c2ecf20Sopenharmony_ci	SC	= 0x00000004L,
938c2ecf20Sopenharmony_ci	CCR	= 0x00000008L,
948c2ecf20Sopenharmony_ci	OG	= 0x0000000CL,
958c2ecf20Sopenharmony_ci	BARM	= 0x00000010L,
968c2ecf20Sopenharmony_ci	BARER	= 0x00000030L,
978c2ecf20Sopenharmony_ci#endif
988c2ecf20Sopenharmony_ci};
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci/* IBM 624 RAMDAC Direct Registers */
1018c2ecf20Sopenharmony_cienum {
1028c2ecf20Sopenharmony_ci	PADDRW	= 0x00,
1038c2ecf20Sopenharmony_ci	PDATA	= 0x04,
1048c2ecf20Sopenharmony_ci	PPMASK	= 0x08,
1058c2ecf20Sopenharmony_ci	PADDRR	= 0x0c,
1068c2ecf20Sopenharmony_ci	PIDXLO	= 0x10,
1078c2ecf20Sopenharmony_ci	PIDXHI	= 0x14,
1088c2ecf20Sopenharmony_ci	PIDXDATA= 0x18,
1098c2ecf20Sopenharmony_ci	PIDXCTL	= 0x1c
1108c2ecf20Sopenharmony_ci};
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci/* IBM 624 RAMDAC Indirect Registers */
1138c2ecf20Sopenharmony_cienum {
1148c2ecf20Sopenharmony_ci	CLKCTL		= 0x02,	/* (0x01) Miscellaneous Clock Control */
1158c2ecf20Sopenharmony_ci	SYNCCTL		= 0x03,	/* (0x00) Sync Control */
1168c2ecf20Sopenharmony_ci	HSYNCPOS	= 0x04,	/* (0x00) Horizontal Sync Position */
1178c2ecf20Sopenharmony_ci	PWRMNGMT	= 0x05,	/* (0x00) Power Management */
1188c2ecf20Sopenharmony_ci	DACOP		= 0x06,	/* (0x02) DAC Operation */
1198c2ecf20Sopenharmony_ci	PALETCTL	= 0x07,	/* (0x00) Palette Control */
1208c2ecf20Sopenharmony_ci	SYSCLKCTL	= 0x08,	/* (0x01) System Clock Control */
1218c2ecf20Sopenharmony_ci	PIXFMT		= 0x0a,	/* () Pixel Format  [bpp >> 3 + 2] */
1228c2ecf20Sopenharmony_ci	BPP8		= 0x0b,	/* () 8 Bits/Pixel Control */
1238c2ecf20Sopenharmony_ci	BPP16		= 0x0c, /* () 16 Bits/Pixel Control  [bit 1=1 for 565] */
1248c2ecf20Sopenharmony_ci	BPP24		= 0x0d,	/* () 24 Bits/Pixel Control */
1258c2ecf20Sopenharmony_ci	BPP32		= 0x0e,	/* () 32 Bits/Pixel Control */
1268c2ecf20Sopenharmony_ci	PIXCTL1		= 0x10, /* (0x05) Pixel PLL Control 1 */
1278c2ecf20Sopenharmony_ci	PIXCTL2		= 0x11,	/* (0x00) Pixel PLL Control 2 */
1288c2ecf20Sopenharmony_ci	SYSCLKN		= 0x15,	/* () System Clock N (System PLL Reference Divider) */
1298c2ecf20Sopenharmony_ci	SYSCLKM		= 0x16,	/* () System Clock M (System PLL VCO Divider) */
1308c2ecf20Sopenharmony_ci	SYSCLKP		= 0x17,	/* () System Clock P */
1318c2ecf20Sopenharmony_ci	SYSCLKC		= 0x18,	/* () System Clock C */
1328c2ecf20Sopenharmony_ci	/*
1338c2ecf20Sopenharmony_ci	 * Dot clock rate is 20MHz * (m + 1) / ((n + 1) * (p ? 2 * p : 1)
1348c2ecf20Sopenharmony_ci	 * c is charge pump bias which depends on the VCO frequency
1358c2ecf20Sopenharmony_ci	 */
1368c2ecf20Sopenharmony_ci	PIXM0		= 0x20,	/* () Pixel M 0 */
1378c2ecf20Sopenharmony_ci	PIXN0		= 0x21,	/* () Pixel N 0 */
1388c2ecf20Sopenharmony_ci	PIXP0		= 0x22,	/* () Pixel P 0 */
1398c2ecf20Sopenharmony_ci	PIXC0		= 0x23,	/* () Pixel C 0 */
1408c2ecf20Sopenharmony_ci	CURSCTL		= 0x30,	/* (0x00) Cursor Control */
1418c2ecf20Sopenharmony_ci	CURSXLO		= 0x31,	/* () Cursor X position, low 8 bits */
1428c2ecf20Sopenharmony_ci	CURSXHI		= 0x32,	/* () Cursor X position, high 8 bits */
1438c2ecf20Sopenharmony_ci	CURSYLO		= 0x33,	/* () Cursor Y position, low 8 bits */
1448c2ecf20Sopenharmony_ci	CURSYHI		= 0x34,	/* () Cursor Y position, high 8 bits */
1458c2ecf20Sopenharmony_ci	CURSHOTX	= 0x35,	/* () Cursor Hot Spot X */
1468c2ecf20Sopenharmony_ci	CURSHOTY	= 0x36,	/* () Cursor Hot Spot Y */
1478c2ecf20Sopenharmony_ci	CURSACCTL	= 0x37,	/* () Advanced Cursor Control Enable */
1488c2ecf20Sopenharmony_ci	CURSACATTR	= 0x38,	/* () Advanced Cursor Attribute */
1498c2ecf20Sopenharmony_ci	CURS1R		= 0x40,	/* () Cursor 1 Red */
1508c2ecf20Sopenharmony_ci	CURS1G		= 0x41,	/* () Cursor 1 Green */
1518c2ecf20Sopenharmony_ci	CURS1B		= 0x42,	/* () Cursor 1 Blue */
1528c2ecf20Sopenharmony_ci	CURS2R		= 0x43,	/* () Cursor 2 Red */
1538c2ecf20Sopenharmony_ci	CURS2G		= 0x44,	/* () Cursor 2 Green */
1548c2ecf20Sopenharmony_ci	CURS2B		= 0x45,	/* () Cursor 2 Blue */
1558c2ecf20Sopenharmony_ci	CURS3R		= 0x46,	/* () Cursor 3 Red */
1568c2ecf20Sopenharmony_ci	CURS3G		= 0x47,	/* () Cursor 3 Green */
1578c2ecf20Sopenharmony_ci	CURS3B		= 0x48,	/* () Cursor 3 Blue */
1588c2ecf20Sopenharmony_ci	BORDR		= 0x60,	/* () Border Color Red */
1598c2ecf20Sopenharmony_ci	BORDG		= 0x61,	/* () Border Color Green */
1608c2ecf20Sopenharmony_ci	BORDB		= 0x62,	/* () Border Color Blue */
1618c2ecf20Sopenharmony_ci	MISCTL1		= 0x70,	/* (0x00) Miscellaneous Control 1 */
1628c2ecf20Sopenharmony_ci	MISCTL2		= 0x71,	/* (0x00) Miscellaneous Control 2 */
1638c2ecf20Sopenharmony_ci	MISCTL3		= 0x72,	/* (0x00) Miscellaneous Control 3 */
1648c2ecf20Sopenharmony_ci	KEYCTL		= 0x78	/* (0x00) Key Control/DB Operation */
1658c2ecf20Sopenharmony_ci};
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci/* TI TVP 3030 RAMDAC Direct Registers */
1688c2ecf20Sopenharmony_cienum {
1698c2ecf20Sopenharmony_ci	TVPADDRW = 0x00,	/* 0  Palette/Cursor RAM Write Address/Index */
1708c2ecf20Sopenharmony_ci	TVPPDATA = 0x04,	/* 1  Palette Data RAM Data */
1718c2ecf20Sopenharmony_ci	TVPPMASK = 0x08,	/* 2  Pixel Read-Mask */
1728c2ecf20Sopenharmony_ci	TVPPADRR = 0x0c,	/* 3  Palette/Cursor RAM Read Address */
1738c2ecf20Sopenharmony_ci	TVPCADRW = 0x10,	/* 4  Cursor/Overscan Color Write Address */
1748c2ecf20Sopenharmony_ci	TVPCDATA = 0x14,	/* 5  Cursor/Overscan Color Data */
1758c2ecf20Sopenharmony_ci				/* 6  reserved */
1768c2ecf20Sopenharmony_ci	TVPCADRR = 0x1c,	/* 7  Cursor/Overscan Color Read Address */
1778c2ecf20Sopenharmony_ci				/* 8  reserved */
1788c2ecf20Sopenharmony_ci	TVPDCCTL = 0x24,	/* 9  Direct Cursor Control */
1798c2ecf20Sopenharmony_ci	TVPIDATA = 0x28,	/* 10 Index Data */
1808c2ecf20Sopenharmony_ci	TVPCRDAT = 0x2c,	/* 11 Cursor RAM Data */
1818c2ecf20Sopenharmony_ci	TVPCXPOL = 0x30,	/* 12 Cursor-Position X LSB */
1828c2ecf20Sopenharmony_ci	TVPCXPOH = 0x34,	/* 13 Cursor-Position X MSB */
1838c2ecf20Sopenharmony_ci	TVPCYPOL = 0x38,	/* 14 Cursor-Position Y LSB */
1848c2ecf20Sopenharmony_ci	TVPCYPOH = 0x3c,	/* 15 Cursor-Position Y MSB */
1858c2ecf20Sopenharmony_ci};
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci/* TI TVP 3030 RAMDAC Indirect Registers */
1888c2ecf20Sopenharmony_cienum {
1898c2ecf20Sopenharmony_ci	TVPIRREV = 0x01,	/* Silicon Revision [RO] */
1908c2ecf20Sopenharmony_ci	TVPIRICC = 0x06,	/* Indirect Cursor Control 	(0x00) */
1918c2ecf20Sopenharmony_ci	TVPIRBRC = 0x07,	/* Byte Router Control 	(0xe4) */
1928c2ecf20Sopenharmony_ci	TVPIRLAC = 0x0f,	/* Latch Control 		(0x06) */
1938c2ecf20Sopenharmony_ci	TVPIRTCC = 0x18,	/* True Color Control  	(0x80) */
1948c2ecf20Sopenharmony_ci	TVPIRMXC = 0x19,	/* Multiplex Control		(0x98) */
1958c2ecf20Sopenharmony_ci	TVPIRCLS = 0x1a,	/* Clock Selection		(0x07) */
1968c2ecf20Sopenharmony_ci	TVPIRPPG = 0x1c,	/* Palette Page		(0x00) */
1978c2ecf20Sopenharmony_ci	TVPIRGEC = 0x1d,	/* General Control 		(0x00) */
1988c2ecf20Sopenharmony_ci	TVPIRMIC = 0x1e,	/* Miscellaneous Control	(0x00) */
1998c2ecf20Sopenharmony_ci	TVPIRPLA = 0x2c,	/* PLL Address */
2008c2ecf20Sopenharmony_ci	TVPIRPPD = 0x2d,	/* Pixel Clock PLL Data */
2018c2ecf20Sopenharmony_ci	TVPIRMPD = 0x2e,	/* Memory Clock PLL Data */
2028c2ecf20Sopenharmony_ci	TVPIRLPD = 0x2f,	/* Loop Clock PLL Data */
2038c2ecf20Sopenharmony_ci	TVPIRCKL = 0x30,	/* Color-Key Overlay Low */
2048c2ecf20Sopenharmony_ci	TVPIRCKH = 0x31,	/* Color-Key Overlay High */
2058c2ecf20Sopenharmony_ci	TVPIRCRL = 0x32,	/* Color-Key Red Low */
2068c2ecf20Sopenharmony_ci	TVPIRCRH = 0x33,	/* Color-Key Red High */
2078c2ecf20Sopenharmony_ci	TVPIRCGL = 0x34,	/* Color-Key Green Low */
2088c2ecf20Sopenharmony_ci	TVPIRCGH = 0x35,	/* Color-Key Green High */
2098c2ecf20Sopenharmony_ci	TVPIRCBL = 0x36,	/* Color-Key Blue Low */
2108c2ecf20Sopenharmony_ci	TVPIRCBH = 0x37,	/* Color-Key Blue High */
2118c2ecf20Sopenharmony_ci	TVPIRCKC = 0x38,	/* Color-Key Control 		(0x00) */
2128c2ecf20Sopenharmony_ci	TVPIRMLC = 0x39,	/* MCLK/Loop Clock Control	(0x18) */
2138c2ecf20Sopenharmony_ci	TVPIRSEN = 0x3a,	/* Sense Test			(0x00) */
2148c2ecf20Sopenharmony_ci	TVPIRTMD = 0x3b,	/* Test Mode Data */
2158c2ecf20Sopenharmony_ci	TVPIRRML = 0x3c,	/* CRC Remainder LSB [RO] */
2168c2ecf20Sopenharmony_ci	TVPIRRMM = 0x3d,	/* CRC Remainder MSB [RO] */
2178c2ecf20Sopenharmony_ci	TVPIRRMS = 0x3e,	/* CRC  Bit Select [WO] */
2188c2ecf20Sopenharmony_ci	TVPIRDID = 0x3f,	/* Device ID [RO] 		(0x30) */
2198c2ecf20Sopenharmony_ci	TVPIRRES = 0xff		/* Software Reset [WO] */
2208c2ecf20Sopenharmony_ci};
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_cistruct initvalues {
2238c2ecf20Sopenharmony_ci	__u8 addr, value;
2248c2ecf20Sopenharmony_ci};
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_cistatic struct initvalues ibm_initregs[] = {
2278c2ecf20Sopenharmony_ci	{ CLKCTL,	0x21 },
2288c2ecf20Sopenharmony_ci	{ SYNCCTL,	0x00 },
2298c2ecf20Sopenharmony_ci	{ HSYNCPOS,	0x00 },
2308c2ecf20Sopenharmony_ci	{ PWRMNGMT,	0x00 },
2318c2ecf20Sopenharmony_ci	{ DACOP,	0x02 },
2328c2ecf20Sopenharmony_ci	{ PALETCTL,	0x00 },
2338c2ecf20Sopenharmony_ci	{ SYSCLKCTL,	0x01 },
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	/*
2368c2ecf20Sopenharmony_ci	 * Note that colors in X are correct only if all video data is
2378c2ecf20Sopenharmony_ci	 * passed through the palette in the DAC.  That is, "indirect
2388c2ecf20Sopenharmony_ci	 * color" must be configured.  This is the case for the IBM DAC
2398c2ecf20Sopenharmony_ci	 * used in the 2MB and 4MB cards, at least.
2408c2ecf20Sopenharmony_ci	 */
2418c2ecf20Sopenharmony_ci	{ BPP8,		0x00 },
2428c2ecf20Sopenharmony_ci	{ BPP16,	0x01 },
2438c2ecf20Sopenharmony_ci	{ BPP24,	0x00 },
2448c2ecf20Sopenharmony_ci	{ BPP32,	0x00 },
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	{ PIXCTL1,	0x05 },
2478c2ecf20Sopenharmony_ci	{ PIXCTL2,	0x00 },
2488c2ecf20Sopenharmony_ci	{ SYSCLKN,	0x08 },
2498c2ecf20Sopenharmony_ci	{ SYSCLKM,	0x4f },
2508c2ecf20Sopenharmony_ci	{ SYSCLKP,	0x00 },
2518c2ecf20Sopenharmony_ci	{ SYSCLKC,	0x00 },
2528c2ecf20Sopenharmony_ci	{ CURSCTL,	0x00 },
2538c2ecf20Sopenharmony_ci	{ CURSACCTL,	0x01 },
2548c2ecf20Sopenharmony_ci	{ CURSACATTR,	0xa8 },
2558c2ecf20Sopenharmony_ci	{ CURS1R,	0xff },
2568c2ecf20Sopenharmony_ci	{ CURS1G,	0xff },
2578c2ecf20Sopenharmony_ci	{ CURS1B,	0xff },
2588c2ecf20Sopenharmony_ci	{ CURS2R,	0xff },
2598c2ecf20Sopenharmony_ci	{ CURS2G,	0xff },
2608c2ecf20Sopenharmony_ci	{ CURS2B,	0xff },
2618c2ecf20Sopenharmony_ci	{ CURS3R,	0xff },
2628c2ecf20Sopenharmony_ci	{ CURS3G,	0xff },
2638c2ecf20Sopenharmony_ci	{ CURS3B,	0xff },
2648c2ecf20Sopenharmony_ci	{ BORDR,	0xff },
2658c2ecf20Sopenharmony_ci	{ BORDG,	0xff },
2668c2ecf20Sopenharmony_ci	{ BORDB,	0xff },
2678c2ecf20Sopenharmony_ci	{ MISCTL1,	0x01 },
2688c2ecf20Sopenharmony_ci	{ MISCTL2,	0x45 },
2698c2ecf20Sopenharmony_ci	{ MISCTL3,	0x00 },
2708c2ecf20Sopenharmony_ci	{ KEYCTL,	0x00 }
2718c2ecf20Sopenharmony_ci};
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_cistatic struct initvalues tvp_initregs[] = {
2748c2ecf20Sopenharmony_ci	{ TVPIRICC,	0x00 },
2758c2ecf20Sopenharmony_ci	{ TVPIRBRC,	0xe4 },
2768c2ecf20Sopenharmony_ci	{ TVPIRLAC,	0x06 },
2778c2ecf20Sopenharmony_ci	{ TVPIRTCC,	0x80 },
2788c2ecf20Sopenharmony_ci	{ TVPIRMXC,	0x4d },
2798c2ecf20Sopenharmony_ci	{ TVPIRCLS,	0x05 },
2808c2ecf20Sopenharmony_ci	{ TVPIRPPG,	0x00 },
2818c2ecf20Sopenharmony_ci	{ TVPIRGEC,	0x00 },
2828c2ecf20Sopenharmony_ci	{ TVPIRMIC,	0x08 },
2838c2ecf20Sopenharmony_ci	{ TVPIRCKL,	0xff },
2848c2ecf20Sopenharmony_ci	{ TVPIRCKH,	0xff },
2858c2ecf20Sopenharmony_ci	{ TVPIRCRL,	0xff },
2868c2ecf20Sopenharmony_ci	{ TVPIRCRH,	0xff },
2878c2ecf20Sopenharmony_ci	{ TVPIRCGL,	0xff },
2888c2ecf20Sopenharmony_ci	{ TVPIRCGH,	0xff },
2898c2ecf20Sopenharmony_ci	{ TVPIRCBL,	0xff },
2908c2ecf20Sopenharmony_ci	{ TVPIRCBH,	0xff },
2918c2ecf20Sopenharmony_ci	{ TVPIRCKC,	0x00 },
2928c2ecf20Sopenharmony_ci	{ TVPIRPLA,	0x00 },
2938c2ecf20Sopenharmony_ci	{ TVPIRPPD,	0xc0 },
2948c2ecf20Sopenharmony_ci	{ TVPIRPPD,	0xd5 },
2958c2ecf20Sopenharmony_ci	{ TVPIRPPD,	0xea },
2968c2ecf20Sopenharmony_ci	{ TVPIRPLA,	0x00 },
2978c2ecf20Sopenharmony_ci	{ TVPIRMPD,	0xb9 },
2988c2ecf20Sopenharmony_ci	{ TVPIRMPD,	0x3a },
2998c2ecf20Sopenharmony_ci	{ TVPIRMPD,	0xb1 },
3008c2ecf20Sopenharmony_ci	{ TVPIRPLA,	0x00 },
3018c2ecf20Sopenharmony_ci	{ TVPIRLPD,	0xc1 },
3028c2ecf20Sopenharmony_ci	{ TVPIRLPD,	0x3d },
3038c2ecf20Sopenharmony_ci	{ TVPIRLPD,	0xf3 },
3048c2ecf20Sopenharmony_ci};
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_cistruct imstt_regvals {
3078c2ecf20Sopenharmony_ci	__u32 pitch;
3088c2ecf20Sopenharmony_ci	__u16 hes, heb, hsb, ht, ves, veb, vsb, vt, vil;
3098c2ecf20Sopenharmony_ci	__u8 pclk_m, pclk_n, pclk_p;
3108c2ecf20Sopenharmony_ci	/* Values of the tvp which change depending on colormode x resolution */
3118c2ecf20Sopenharmony_ci	__u8 mlc[3];	/* Memory Loop Config 0x39 */
3128c2ecf20Sopenharmony_ci	__u8 lckl_p[3];	/* P value of LCKL PLL */
3138c2ecf20Sopenharmony_ci};
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_cistruct imstt_par {
3168c2ecf20Sopenharmony_ci	struct imstt_regvals init;
3178c2ecf20Sopenharmony_ci	__u32 __iomem *dc_regs;
3188c2ecf20Sopenharmony_ci	unsigned long cmap_regs_phys;
3198c2ecf20Sopenharmony_ci	__u8 *cmap_regs;
3208c2ecf20Sopenharmony_ci	__u32 ramdac;
3218c2ecf20Sopenharmony_ci	__u32 palette[16];
3228c2ecf20Sopenharmony_ci};
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_cienum {
3258c2ecf20Sopenharmony_ci	IBM = 0,
3268c2ecf20Sopenharmony_ci	TVP = 1
3278c2ecf20Sopenharmony_ci};
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci#define INIT_BPP		8
3308c2ecf20Sopenharmony_ci#define INIT_XRES		640
3318c2ecf20Sopenharmony_ci#define INIT_YRES		480
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_cistatic int inverse = 0;
3348c2ecf20Sopenharmony_cistatic char fontname[40] __initdata = { 0 };
3358c2ecf20Sopenharmony_ci#if defined(CONFIG_PPC_PMAC)
3368c2ecf20Sopenharmony_cistatic signed char init_vmode = -1, init_cmode = -1;
3378c2ecf20Sopenharmony_ci#endif
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_cistatic struct imstt_regvals tvp_reg_init_2 = {
3408c2ecf20Sopenharmony_ci	512,
3418c2ecf20Sopenharmony_ci	0x0002, 0x0006, 0x0026, 0x0028, 0x0003, 0x0016, 0x0196, 0x0197, 0x0196,
3428c2ecf20Sopenharmony_ci	0xec, 0x2a, 0xf3,
3438c2ecf20Sopenharmony_ci	{ 0x3c, 0x3b, 0x39 }, { 0xf3, 0xf3, 0xf3 }
3448c2ecf20Sopenharmony_ci};
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_cistatic struct imstt_regvals tvp_reg_init_6 = {
3478c2ecf20Sopenharmony_ci	640,
3488c2ecf20Sopenharmony_ci	0x0004, 0x0009, 0x0031, 0x0036, 0x0003, 0x002a, 0x020a, 0x020d, 0x020a,
3498c2ecf20Sopenharmony_ci	0xef, 0x2e, 0xb2,
3508c2ecf20Sopenharmony_ci	{ 0x39, 0x39, 0x38 }, { 0xf3, 0xf3, 0xf3 }
3518c2ecf20Sopenharmony_ci};
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_cistatic struct imstt_regvals tvp_reg_init_12 = {
3548c2ecf20Sopenharmony_ci	800,
3558c2ecf20Sopenharmony_ci	0x0005, 0x000e, 0x0040, 0x0042, 0x0003, 0x018, 0x270, 0x271, 0x270,
3568c2ecf20Sopenharmony_ci	0xf6, 0x2e, 0xf2,
3578c2ecf20Sopenharmony_ci	{ 0x3a, 0x39, 0x38 }, { 0xf3, 0xf3, 0xf3 }
3588c2ecf20Sopenharmony_ci};
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_cistatic struct imstt_regvals tvp_reg_init_13 = {
3618c2ecf20Sopenharmony_ci	832,
3628c2ecf20Sopenharmony_ci	0x0004, 0x0011, 0x0045, 0x0048, 0x0003, 0x002a, 0x029a, 0x029b, 0x0000,
3638c2ecf20Sopenharmony_ci	0xfe, 0x3e, 0xf1,
3648c2ecf20Sopenharmony_ci	{ 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
3658c2ecf20Sopenharmony_ci};
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_cistatic struct imstt_regvals tvp_reg_init_17 = {
3688c2ecf20Sopenharmony_ci	1024,
3698c2ecf20Sopenharmony_ci	0x0006, 0x0210, 0x0250, 0x0053, 0x1003, 0x0021, 0x0321, 0x0324, 0x0000,
3708c2ecf20Sopenharmony_ci	0xfc, 0x3a, 0xf1,
3718c2ecf20Sopenharmony_ci	{ 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
3728c2ecf20Sopenharmony_ci};
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_cistatic struct imstt_regvals tvp_reg_init_18 = {
3758c2ecf20Sopenharmony_ci	1152,
3768c2ecf20Sopenharmony_ci  	0x0009, 0x0011, 0x059, 0x5b, 0x0003, 0x0031, 0x0397, 0x039a, 0x0000,
3778c2ecf20Sopenharmony_ci	0xfd, 0x3a, 0xf1,
3788c2ecf20Sopenharmony_ci	{ 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
3798c2ecf20Sopenharmony_ci};
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_cistatic struct imstt_regvals tvp_reg_init_19 = {
3828c2ecf20Sopenharmony_ci	1280,
3838c2ecf20Sopenharmony_ci	0x0009, 0x0016, 0x0066, 0x0069, 0x0003, 0x0027, 0x03e7, 0x03e8, 0x03e7,
3848c2ecf20Sopenharmony_ci	0xf7, 0x36, 0xf0,
3858c2ecf20Sopenharmony_ci	{ 0x38, 0x38, 0x38 }, { 0xf3, 0xf2, 0xf1 }
3868c2ecf20Sopenharmony_ci};
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_cistatic struct imstt_regvals tvp_reg_init_20 = {
3898c2ecf20Sopenharmony_ci	1280,
3908c2ecf20Sopenharmony_ci	0x0009, 0x0018, 0x0068, 0x006a, 0x0003, 0x0029, 0x0429, 0x042a, 0x0000,
3918c2ecf20Sopenharmony_ci	0xf0, 0x2d, 0xf0,
3928c2ecf20Sopenharmony_ci	{ 0x38, 0x38, 0x38 }, { 0xf3, 0xf2, 0xf1 }
3938c2ecf20Sopenharmony_ci};
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci/*
3968c2ecf20Sopenharmony_ci * PCI driver prototypes
3978c2ecf20Sopenharmony_ci */
3988c2ecf20Sopenharmony_cistatic int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
3998c2ecf20Sopenharmony_cistatic void imsttfb_remove(struct pci_dev *pdev);
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci/*
4028c2ecf20Sopenharmony_ci * Register access
4038c2ecf20Sopenharmony_ci */
4048c2ecf20Sopenharmony_cistatic inline u32 read_reg_le32(volatile u32 __iomem *base, int regindex)
4058c2ecf20Sopenharmony_ci{
4068c2ecf20Sopenharmony_ci#ifdef __powerpc__
4078c2ecf20Sopenharmony_ci	return in_le32(base + regindex);
4088c2ecf20Sopenharmony_ci#else
4098c2ecf20Sopenharmony_ci	return readl(base + regindex);
4108c2ecf20Sopenharmony_ci#endif
4118c2ecf20Sopenharmony_ci}
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_cistatic inline void write_reg_le32(volatile u32 __iomem *base, int regindex, u32 val)
4148c2ecf20Sopenharmony_ci{
4158c2ecf20Sopenharmony_ci#ifdef __powerpc__
4168c2ecf20Sopenharmony_ci	out_le32(base + regindex, val);
4178c2ecf20Sopenharmony_ci#else
4188c2ecf20Sopenharmony_ci	writel(val, base + regindex);
4198c2ecf20Sopenharmony_ci#endif
4208c2ecf20Sopenharmony_ci}
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_cistatic __u32
4238c2ecf20Sopenharmony_cigetclkMHz(struct imstt_par *par)
4248c2ecf20Sopenharmony_ci{
4258c2ecf20Sopenharmony_ci	__u32 clk_m, clk_n, clk_p;
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	clk_m = par->init.pclk_m;
4288c2ecf20Sopenharmony_ci	clk_n = par->init.pclk_n;
4298c2ecf20Sopenharmony_ci	clk_p = par->init.pclk_p;
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	return 20 * (clk_m + 1) / ((clk_n + 1) * (clk_p ? 2 * clk_p : 1));
4328c2ecf20Sopenharmony_ci}
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_cistatic void
4358c2ecf20Sopenharmony_cisetclkMHz(struct imstt_par *par, __u32 MHz)
4368c2ecf20Sopenharmony_ci{
4378c2ecf20Sopenharmony_ci	__u32 clk_m, clk_n, x, stage, spilled;
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	clk_m = clk_n = 0;
4408c2ecf20Sopenharmony_ci	stage = spilled = 0;
4418c2ecf20Sopenharmony_ci	for (;;) {
4428c2ecf20Sopenharmony_ci		switch (stage) {
4438c2ecf20Sopenharmony_ci			case 0:
4448c2ecf20Sopenharmony_ci				clk_m++;
4458c2ecf20Sopenharmony_ci				break;
4468c2ecf20Sopenharmony_ci			case 1:
4478c2ecf20Sopenharmony_ci				clk_n++;
4488c2ecf20Sopenharmony_ci				break;
4498c2ecf20Sopenharmony_ci		}
4508c2ecf20Sopenharmony_ci		x = 20 * (clk_m + 1) / (clk_n + 1);
4518c2ecf20Sopenharmony_ci		if (x == MHz)
4528c2ecf20Sopenharmony_ci			break;
4538c2ecf20Sopenharmony_ci		if (x > MHz) {
4548c2ecf20Sopenharmony_ci			spilled = 1;
4558c2ecf20Sopenharmony_ci			stage = 1;
4568c2ecf20Sopenharmony_ci		} else if (spilled && x < MHz) {
4578c2ecf20Sopenharmony_ci			stage = 0;
4588c2ecf20Sopenharmony_ci		}
4598c2ecf20Sopenharmony_ci	}
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	par->init.pclk_m = clk_m;
4628c2ecf20Sopenharmony_ci	par->init.pclk_n = clk_n;
4638c2ecf20Sopenharmony_ci	par->init.pclk_p = 0;
4648c2ecf20Sopenharmony_ci}
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_cistatic struct imstt_regvals *
4678c2ecf20Sopenharmony_cicompute_imstt_regvals_ibm(struct imstt_par *par, int xres, int yres)
4688c2ecf20Sopenharmony_ci{
4698c2ecf20Sopenharmony_ci	struct imstt_regvals *init = &par->init;
4708c2ecf20Sopenharmony_ci	__u32 MHz, hes, heb, veb, htp, vtp;
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci	switch (xres) {
4738c2ecf20Sopenharmony_ci		case 640:
4748c2ecf20Sopenharmony_ci			hes = 0x0008; heb = 0x0012; veb = 0x002a; htp = 10; vtp = 2;
4758c2ecf20Sopenharmony_ci			MHz = 30 /* .25 */ ;
4768c2ecf20Sopenharmony_ci			break;
4778c2ecf20Sopenharmony_ci		case 832:
4788c2ecf20Sopenharmony_ci			hes = 0x0005; heb = 0x0020; veb = 0x0028; htp = 8; vtp = 3;
4798c2ecf20Sopenharmony_ci			MHz = 57 /* .27_ */ ;
4808c2ecf20Sopenharmony_ci			break;
4818c2ecf20Sopenharmony_ci		case 1024:
4828c2ecf20Sopenharmony_ci			hes = 0x000a; heb = 0x001c; veb = 0x0020; htp = 8; vtp = 3;
4838c2ecf20Sopenharmony_ci			MHz = 80;
4848c2ecf20Sopenharmony_ci			break;
4858c2ecf20Sopenharmony_ci		case 1152:
4868c2ecf20Sopenharmony_ci			hes = 0x0012; heb = 0x0022; veb = 0x0031; htp = 4; vtp = 3;
4878c2ecf20Sopenharmony_ci			MHz = 101 /* .6_ */ ;
4888c2ecf20Sopenharmony_ci			break;
4898c2ecf20Sopenharmony_ci		case 1280:
4908c2ecf20Sopenharmony_ci			hes = 0x0012; heb = 0x002f; veb = 0x0029; htp = 4; vtp = 1;
4918c2ecf20Sopenharmony_ci			MHz = yres == 960 ? 126 : 135;
4928c2ecf20Sopenharmony_ci			break;
4938c2ecf20Sopenharmony_ci		case 1600:
4948c2ecf20Sopenharmony_ci			hes = 0x0018; heb = 0x0040; veb = 0x002a; htp = 4; vtp = 3;
4958c2ecf20Sopenharmony_ci			MHz = 200;
4968c2ecf20Sopenharmony_ci			break;
4978c2ecf20Sopenharmony_ci		default:
4988c2ecf20Sopenharmony_ci			return NULL;
4998c2ecf20Sopenharmony_ci	}
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci	setclkMHz(par, MHz);
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	init->hes = hes;
5048c2ecf20Sopenharmony_ci	init->heb = heb;
5058c2ecf20Sopenharmony_ci	init->hsb = init->heb + (xres >> 3);
5068c2ecf20Sopenharmony_ci	init->ht = init->hsb + htp;
5078c2ecf20Sopenharmony_ci	init->ves = 0x0003;
5088c2ecf20Sopenharmony_ci	init->veb = veb;
5098c2ecf20Sopenharmony_ci	init->vsb = init->veb + yres;
5108c2ecf20Sopenharmony_ci	init->vt = init->vsb + vtp;
5118c2ecf20Sopenharmony_ci	init->vil = init->vsb;
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci	init->pitch = xres;
5148c2ecf20Sopenharmony_ci	return init;
5158c2ecf20Sopenharmony_ci}
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_cistatic struct imstt_regvals *
5188c2ecf20Sopenharmony_cicompute_imstt_regvals_tvp(struct imstt_par *par, int xres, int yres)
5198c2ecf20Sopenharmony_ci{
5208c2ecf20Sopenharmony_ci	struct imstt_regvals *init;
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	switch (xres) {
5238c2ecf20Sopenharmony_ci		case 512:
5248c2ecf20Sopenharmony_ci			init = &tvp_reg_init_2;
5258c2ecf20Sopenharmony_ci			break;
5268c2ecf20Sopenharmony_ci		case 640:
5278c2ecf20Sopenharmony_ci			init = &tvp_reg_init_6;
5288c2ecf20Sopenharmony_ci			break;
5298c2ecf20Sopenharmony_ci		case 800:
5308c2ecf20Sopenharmony_ci			init = &tvp_reg_init_12;
5318c2ecf20Sopenharmony_ci			break;
5328c2ecf20Sopenharmony_ci		case 832:
5338c2ecf20Sopenharmony_ci			init = &tvp_reg_init_13;
5348c2ecf20Sopenharmony_ci			break;
5358c2ecf20Sopenharmony_ci		case 1024:
5368c2ecf20Sopenharmony_ci			init = &tvp_reg_init_17;
5378c2ecf20Sopenharmony_ci			break;
5388c2ecf20Sopenharmony_ci		case 1152:
5398c2ecf20Sopenharmony_ci			init = &tvp_reg_init_18;
5408c2ecf20Sopenharmony_ci			break;
5418c2ecf20Sopenharmony_ci		case 1280:
5428c2ecf20Sopenharmony_ci			init = yres == 960 ? &tvp_reg_init_19 : &tvp_reg_init_20;
5438c2ecf20Sopenharmony_ci			break;
5448c2ecf20Sopenharmony_ci		default:
5458c2ecf20Sopenharmony_ci			return NULL;
5468c2ecf20Sopenharmony_ci	}
5478c2ecf20Sopenharmony_ci	par->init = *init;
5488c2ecf20Sopenharmony_ci	return init;
5498c2ecf20Sopenharmony_ci}
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_cistatic struct imstt_regvals *
5528c2ecf20Sopenharmony_cicompute_imstt_regvals (struct imstt_par *par, u_int xres, u_int yres)
5538c2ecf20Sopenharmony_ci{
5548c2ecf20Sopenharmony_ci	if (par->ramdac == IBM)
5558c2ecf20Sopenharmony_ci		return compute_imstt_regvals_ibm(par, xres, yres);
5568c2ecf20Sopenharmony_ci	else
5578c2ecf20Sopenharmony_ci		return compute_imstt_regvals_tvp(par, xres, yres);
5588c2ecf20Sopenharmony_ci}
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_cistatic void
5618c2ecf20Sopenharmony_ciset_imstt_regvals_ibm (struct imstt_par *par, u_int bpp)
5628c2ecf20Sopenharmony_ci{
5638c2ecf20Sopenharmony_ci	struct imstt_regvals *init = &par->init;
5648c2ecf20Sopenharmony_ci	__u8 pformat = (bpp >> 3) + 2;
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	par->cmap_regs[PIDXHI] = 0;		eieio();
5678c2ecf20Sopenharmony_ci	par->cmap_regs[PIDXLO] = PIXM0;		eieio();
5688c2ecf20Sopenharmony_ci	par->cmap_regs[PIDXDATA] = init->pclk_m;eieio();
5698c2ecf20Sopenharmony_ci	par->cmap_regs[PIDXLO] = PIXN0;		eieio();
5708c2ecf20Sopenharmony_ci	par->cmap_regs[PIDXDATA] = init->pclk_n;eieio();
5718c2ecf20Sopenharmony_ci	par->cmap_regs[PIDXLO] = PIXP0;		eieio();
5728c2ecf20Sopenharmony_ci	par->cmap_regs[PIDXDATA] = init->pclk_p;eieio();
5738c2ecf20Sopenharmony_ci	par->cmap_regs[PIDXLO] = PIXC0;		eieio();
5748c2ecf20Sopenharmony_ci	par->cmap_regs[PIDXDATA] = 0x02;	eieio();
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci	par->cmap_regs[PIDXLO] = PIXFMT;	eieio();
5778c2ecf20Sopenharmony_ci	par->cmap_regs[PIDXDATA] = pformat;	eieio();
5788c2ecf20Sopenharmony_ci}
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_cistatic void
5818c2ecf20Sopenharmony_ciset_imstt_regvals_tvp (struct imstt_par *par, u_int bpp)
5828c2ecf20Sopenharmony_ci{
5838c2ecf20Sopenharmony_ci	struct imstt_regvals *init = &par->init;
5848c2ecf20Sopenharmony_ci	__u8 tcc, mxc, lckl_n, mic;
5858c2ecf20Sopenharmony_ci	__u8 mlc, lckl_p;
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci	switch (bpp) {
5888c2ecf20Sopenharmony_ci		default:
5898c2ecf20Sopenharmony_ci		case 8:
5908c2ecf20Sopenharmony_ci			tcc = 0x80;
5918c2ecf20Sopenharmony_ci			mxc = 0x4d;
5928c2ecf20Sopenharmony_ci			lckl_n = 0xc1;
5938c2ecf20Sopenharmony_ci			mlc = init->mlc[0];
5948c2ecf20Sopenharmony_ci			lckl_p = init->lckl_p[0];
5958c2ecf20Sopenharmony_ci			break;
5968c2ecf20Sopenharmony_ci		case 16:
5978c2ecf20Sopenharmony_ci			tcc = 0x44;
5988c2ecf20Sopenharmony_ci			mxc = 0x55;
5998c2ecf20Sopenharmony_ci			lckl_n = 0xe1;
6008c2ecf20Sopenharmony_ci			mlc = init->mlc[1];
6018c2ecf20Sopenharmony_ci			lckl_p = init->lckl_p[1];
6028c2ecf20Sopenharmony_ci			break;
6038c2ecf20Sopenharmony_ci		case 24:
6048c2ecf20Sopenharmony_ci			tcc = 0x5e;
6058c2ecf20Sopenharmony_ci			mxc = 0x5d;
6068c2ecf20Sopenharmony_ci			lckl_n = 0xf1;
6078c2ecf20Sopenharmony_ci			mlc = init->mlc[2];
6088c2ecf20Sopenharmony_ci			lckl_p = init->lckl_p[2];
6098c2ecf20Sopenharmony_ci			break;
6108c2ecf20Sopenharmony_ci		case 32:
6118c2ecf20Sopenharmony_ci			tcc = 0x46;
6128c2ecf20Sopenharmony_ci			mxc = 0x5d;
6138c2ecf20Sopenharmony_ci			lckl_n = 0xf1;
6148c2ecf20Sopenharmony_ci			mlc = init->mlc[2];
6158c2ecf20Sopenharmony_ci			lckl_p = init->lckl_p[2];
6168c2ecf20Sopenharmony_ci			break;
6178c2ecf20Sopenharmony_ci	}
6188c2ecf20Sopenharmony_ci	mic = 0x08;
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci	par->cmap_regs[TVPADDRW] = TVPIRPLA;		eieio();
6218c2ecf20Sopenharmony_ci	par->cmap_regs[TVPIDATA] = 0x00;		eieio();
6228c2ecf20Sopenharmony_ci	par->cmap_regs[TVPADDRW] = TVPIRPPD;		eieio();
6238c2ecf20Sopenharmony_ci	par->cmap_regs[TVPIDATA] = init->pclk_m;	eieio();
6248c2ecf20Sopenharmony_ci	par->cmap_regs[TVPADDRW] = TVPIRPPD;		eieio();
6258c2ecf20Sopenharmony_ci	par->cmap_regs[TVPIDATA] = init->pclk_n;	eieio();
6268c2ecf20Sopenharmony_ci	par->cmap_regs[TVPADDRW] = TVPIRPPD;		eieio();
6278c2ecf20Sopenharmony_ci	par->cmap_regs[TVPIDATA] = init->pclk_p;	eieio();
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	par->cmap_regs[TVPADDRW] = TVPIRTCC;		eieio();
6308c2ecf20Sopenharmony_ci	par->cmap_regs[TVPIDATA] = tcc;			eieio();
6318c2ecf20Sopenharmony_ci	par->cmap_regs[TVPADDRW] = TVPIRMXC;		eieio();
6328c2ecf20Sopenharmony_ci	par->cmap_regs[TVPIDATA] = mxc;			eieio();
6338c2ecf20Sopenharmony_ci	par->cmap_regs[TVPADDRW] = TVPIRMIC;		eieio();
6348c2ecf20Sopenharmony_ci	par->cmap_regs[TVPIDATA] = mic;			eieio();
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci	par->cmap_regs[TVPADDRW] = TVPIRPLA;		eieio();
6378c2ecf20Sopenharmony_ci	par->cmap_regs[TVPIDATA] = 0x00;		eieio();
6388c2ecf20Sopenharmony_ci	par->cmap_regs[TVPADDRW] = TVPIRLPD;		eieio();
6398c2ecf20Sopenharmony_ci	par->cmap_regs[TVPIDATA] = lckl_n;		eieio();
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci	par->cmap_regs[TVPADDRW] = TVPIRPLA;		eieio();
6428c2ecf20Sopenharmony_ci	par->cmap_regs[TVPIDATA] = 0x15;		eieio();
6438c2ecf20Sopenharmony_ci	par->cmap_regs[TVPADDRW] = TVPIRMLC;		eieio();
6448c2ecf20Sopenharmony_ci	par->cmap_regs[TVPIDATA] = mlc;			eieio();
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci	par->cmap_regs[TVPADDRW] = TVPIRPLA;		eieio();
6478c2ecf20Sopenharmony_ci	par->cmap_regs[TVPIDATA] = 0x2a;		eieio();
6488c2ecf20Sopenharmony_ci	par->cmap_regs[TVPADDRW] = TVPIRLPD;		eieio();
6498c2ecf20Sopenharmony_ci	par->cmap_regs[TVPIDATA] = lckl_p;		eieio();
6508c2ecf20Sopenharmony_ci}
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_cistatic void
6538c2ecf20Sopenharmony_ciset_imstt_regvals (struct fb_info *info, u_int bpp)
6548c2ecf20Sopenharmony_ci{
6558c2ecf20Sopenharmony_ci	struct imstt_par *par = info->par;
6568c2ecf20Sopenharmony_ci	struct imstt_regvals *init = &par->init;
6578c2ecf20Sopenharmony_ci	__u32 ctl, pitch, byteswap, scr;
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci	if (par->ramdac == IBM)
6608c2ecf20Sopenharmony_ci		set_imstt_regvals_ibm(par, bpp);
6618c2ecf20Sopenharmony_ci	else
6628c2ecf20Sopenharmony_ci		set_imstt_regvals_tvp(par, bpp);
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci  /*
6658c2ecf20Sopenharmony_ci   * From what I (jsk) can gather poking around with MacsBug,
6668c2ecf20Sopenharmony_ci   * bits 8 and 9 in the SCR register control endianness
6678c2ecf20Sopenharmony_ci   * correction (byte swapping).  These bits must be set according
6688c2ecf20Sopenharmony_ci   * to the color depth as follows:
6698c2ecf20Sopenharmony_ci   *     Color depth    Bit 9   Bit 8
6708c2ecf20Sopenharmony_ci   *     ==========     =====   =====
6718c2ecf20Sopenharmony_ci   *        8bpp          0       0
6728c2ecf20Sopenharmony_ci   *       16bpp          0       1
6738c2ecf20Sopenharmony_ci   *       32bpp          1       1
6748c2ecf20Sopenharmony_ci   */
6758c2ecf20Sopenharmony_ci	switch (bpp) {
6768c2ecf20Sopenharmony_ci		default:
6778c2ecf20Sopenharmony_ci		case 8:
6788c2ecf20Sopenharmony_ci			ctl = 0x17b1;
6798c2ecf20Sopenharmony_ci			pitch = init->pitch >> 2;
6808c2ecf20Sopenharmony_ci			byteswap = 0x000;
6818c2ecf20Sopenharmony_ci			break;
6828c2ecf20Sopenharmony_ci		case 16:
6838c2ecf20Sopenharmony_ci			ctl = 0x17b3;
6848c2ecf20Sopenharmony_ci			pitch = init->pitch >> 1;
6858c2ecf20Sopenharmony_ci			byteswap = 0x100;
6868c2ecf20Sopenharmony_ci			break;
6878c2ecf20Sopenharmony_ci		case 24:
6888c2ecf20Sopenharmony_ci			ctl = 0x17b9;
6898c2ecf20Sopenharmony_ci			pitch = init->pitch - (init->pitch >> 2);
6908c2ecf20Sopenharmony_ci			byteswap = 0x200;
6918c2ecf20Sopenharmony_ci			break;
6928c2ecf20Sopenharmony_ci		case 32:
6938c2ecf20Sopenharmony_ci			ctl = 0x17b5;
6948c2ecf20Sopenharmony_ci			pitch = init->pitch;
6958c2ecf20Sopenharmony_ci			byteswap = 0x300;
6968c2ecf20Sopenharmony_ci			break;
6978c2ecf20Sopenharmony_ci	}
6988c2ecf20Sopenharmony_ci	if (par->ramdac == TVP)
6998c2ecf20Sopenharmony_ci		ctl -= 0x30;
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, HES, init->hes);
7028c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, HEB, init->heb);
7038c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, HSB, init->hsb);
7048c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, HT, init->ht);
7058c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, VES, init->ves);
7068c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, VEB, init->veb);
7078c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, VSB, init->vsb);
7088c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, VT, init->vt);
7098c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, VIL, init->vil);
7108c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, HCIV, 1);
7118c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, VCIV, 1);
7128c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, TCDR, 4);
7138c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, RRCIV, 1);
7148c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, RRSC, 0x980);
7158c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, RRCR, 0x11);
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci	if (par->ramdac == IBM) {
7188c2ecf20Sopenharmony_ci		write_reg_le32(par->dc_regs, HRIR, 0x0100);
7198c2ecf20Sopenharmony_ci		write_reg_le32(par->dc_regs, CMR, 0x00ff);
7208c2ecf20Sopenharmony_ci		write_reg_le32(par->dc_regs, SRGCTL, 0x0073);
7218c2ecf20Sopenharmony_ci	} else {
7228c2ecf20Sopenharmony_ci		write_reg_le32(par->dc_regs, HRIR, 0x0200);
7238c2ecf20Sopenharmony_ci		write_reg_le32(par->dc_regs, CMR, 0x01ff);
7248c2ecf20Sopenharmony_ci		write_reg_le32(par->dc_regs, SRGCTL, 0x0003);
7258c2ecf20Sopenharmony_ci	}
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci	switch (info->fix.smem_len) {
7288c2ecf20Sopenharmony_ci		case 0x200000:
7298c2ecf20Sopenharmony_ci			scr = 0x059d | byteswap;
7308c2ecf20Sopenharmony_ci			break;
7318c2ecf20Sopenharmony_ci		/* case 0x400000:
7328c2ecf20Sopenharmony_ci		   case 0x800000: */
7338c2ecf20Sopenharmony_ci		default:
7348c2ecf20Sopenharmony_ci			pitch >>= 1;
7358c2ecf20Sopenharmony_ci			scr = 0x150dd | byteswap;
7368c2ecf20Sopenharmony_ci			break;
7378c2ecf20Sopenharmony_ci	}
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, SCR, scr);
7408c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, SPR, pitch);
7418c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, STGCTL, ctl);
7428c2ecf20Sopenharmony_ci}
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_cistatic inline void
7458c2ecf20Sopenharmony_ciset_offset (struct fb_var_screeninfo *var, struct fb_info *info)
7468c2ecf20Sopenharmony_ci{
7478c2ecf20Sopenharmony_ci	struct imstt_par *par = info->par;
7488c2ecf20Sopenharmony_ci	__u32 off = var->yoffset * (info->fix.line_length >> 3)
7498c2ecf20Sopenharmony_ci		    + ((var->xoffset * (info->var.bits_per_pixel >> 3)) >> 3);
7508c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, SSR, off);
7518c2ecf20Sopenharmony_ci}
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_cistatic inline void
7548c2ecf20Sopenharmony_ciset_555 (struct imstt_par *par)
7558c2ecf20Sopenharmony_ci{
7568c2ecf20Sopenharmony_ci	if (par->ramdac == IBM) {
7578c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXHI] = 0;		eieio();
7588c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXLO] = BPP16;		eieio();
7598c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXDATA] = 0x01;	eieio();
7608c2ecf20Sopenharmony_ci	} else {
7618c2ecf20Sopenharmony_ci		par->cmap_regs[TVPADDRW] = TVPIRTCC;	eieio();
7628c2ecf20Sopenharmony_ci		par->cmap_regs[TVPIDATA] = 0x44;	eieio();
7638c2ecf20Sopenharmony_ci	}
7648c2ecf20Sopenharmony_ci}
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_cistatic inline void
7678c2ecf20Sopenharmony_ciset_565 (struct imstt_par *par)
7688c2ecf20Sopenharmony_ci{
7698c2ecf20Sopenharmony_ci	if (par->ramdac == IBM) {
7708c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXHI] = 0;		eieio();
7718c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXLO] = BPP16;		eieio();
7728c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXDATA] = 0x03;	eieio();
7738c2ecf20Sopenharmony_ci	} else {
7748c2ecf20Sopenharmony_ci		par->cmap_regs[TVPADDRW] = TVPIRTCC;	eieio();
7758c2ecf20Sopenharmony_ci		par->cmap_regs[TVPIDATA] = 0x45;	eieio();
7768c2ecf20Sopenharmony_ci	}
7778c2ecf20Sopenharmony_ci}
7788c2ecf20Sopenharmony_ci
7798c2ecf20Sopenharmony_cistatic int
7808c2ecf20Sopenharmony_ciimsttfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
7818c2ecf20Sopenharmony_ci{
7828c2ecf20Sopenharmony_ci	if ((var->bits_per_pixel != 8 && var->bits_per_pixel != 16
7838c2ecf20Sopenharmony_ci	    && var->bits_per_pixel != 24 && var->bits_per_pixel != 32)
7848c2ecf20Sopenharmony_ci	    || var->xres_virtual < var->xres || var->yres_virtual < var->yres
7858c2ecf20Sopenharmony_ci	    || var->nonstd
7868c2ecf20Sopenharmony_ci	    || (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
7878c2ecf20Sopenharmony_ci		return -EINVAL;
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_ci	if ((var->xres * var->yres) * (var->bits_per_pixel >> 3) > info->fix.smem_len
7908c2ecf20Sopenharmony_ci	    || (var->xres_virtual * var->yres_virtual) * (var->bits_per_pixel >> 3) > info->fix.smem_len)
7918c2ecf20Sopenharmony_ci		return -EINVAL;
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci	switch (var->bits_per_pixel) {
7948c2ecf20Sopenharmony_ci		case 8:
7958c2ecf20Sopenharmony_ci			var->red.offset = 0;
7968c2ecf20Sopenharmony_ci			var->red.length = 8;
7978c2ecf20Sopenharmony_ci			var->green.offset = 0;
7988c2ecf20Sopenharmony_ci			var->green.length = 8;
7998c2ecf20Sopenharmony_ci			var->blue.offset = 0;
8008c2ecf20Sopenharmony_ci			var->blue.length = 8;
8018c2ecf20Sopenharmony_ci			var->transp.offset = 0;
8028c2ecf20Sopenharmony_ci			var->transp.length = 0;
8038c2ecf20Sopenharmony_ci			break;
8048c2ecf20Sopenharmony_ci		case 16:	/* RGB 555 or 565 */
8058c2ecf20Sopenharmony_ci			if (var->green.length != 6)
8068c2ecf20Sopenharmony_ci				var->red.offset = 10;
8078c2ecf20Sopenharmony_ci			var->red.length = 5;
8088c2ecf20Sopenharmony_ci			var->green.offset = 5;
8098c2ecf20Sopenharmony_ci			if (var->green.length != 6)
8108c2ecf20Sopenharmony_ci				var->green.length = 5;
8118c2ecf20Sopenharmony_ci			var->blue.offset = 0;
8128c2ecf20Sopenharmony_ci			var->blue.length = 5;
8138c2ecf20Sopenharmony_ci			var->transp.offset = 0;
8148c2ecf20Sopenharmony_ci			var->transp.length = 0;
8158c2ecf20Sopenharmony_ci			break;
8168c2ecf20Sopenharmony_ci		case 24:	/* RGB 888 */
8178c2ecf20Sopenharmony_ci			var->red.offset = 16;
8188c2ecf20Sopenharmony_ci			var->red.length = 8;
8198c2ecf20Sopenharmony_ci			var->green.offset = 8;
8208c2ecf20Sopenharmony_ci			var->green.length = 8;
8218c2ecf20Sopenharmony_ci			var->blue.offset = 0;
8228c2ecf20Sopenharmony_ci			var->blue.length = 8;
8238c2ecf20Sopenharmony_ci			var->transp.offset = 0;
8248c2ecf20Sopenharmony_ci			var->transp.length = 0;
8258c2ecf20Sopenharmony_ci			break;
8268c2ecf20Sopenharmony_ci		case 32:	/* RGBA 8888 */
8278c2ecf20Sopenharmony_ci			var->red.offset = 16;
8288c2ecf20Sopenharmony_ci			var->red.length = 8;
8298c2ecf20Sopenharmony_ci			var->green.offset = 8;
8308c2ecf20Sopenharmony_ci			var->green.length = 8;
8318c2ecf20Sopenharmony_ci			var->blue.offset = 0;
8328c2ecf20Sopenharmony_ci			var->blue.length = 8;
8338c2ecf20Sopenharmony_ci			var->transp.offset = 24;
8348c2ecf20Sopenharmony_ci			var->transp.length = 8;
8358c2ecf20Sopenharmony_ci			break;
8368c2ecf20Sopenharmony_ci	}
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	if (var->yres == var->yres_virtual) {
8398c2ecf20Sopenharmony_ci		__u32 vram = (info->fix.smem_len - (PAGE_SIZE << 2));
8408c2ecf20Sopenharmony_ci		var->yres_virtual = ((vram << 3) / var->bits_per_pixel) / var->xres_virtual;
8418c2ecf20Sopenharmony_ci		if (var->yres_virtual < var->yres)
8428c2ecf20Sopenharmony_ci			var->yres_virtual = var->yres;
8438c2ecf20Sopenharmony_ci	}
8448c2ecf20Sopenharmony_ci
8458c2ecf20Sopenharmony_ci	var->red.msb_right = 0;
8468c2ecf20Sopenharmony_ci	var->green.msb_right = 0;
8478c2ecf20Sopenharmony_ci	var->blue.msb_right = 0;
8488c2ecf20Sopenharmony_ci	var->transp.msb_right = 0;
8498c2ecf20Sopenharmony_ci	var->height = -1;
8508c2ecf20Sopenharmony_ci	var->width = -1;
8518c2ecf20Sopenharmony_ci	var->vmode = FB_VMODE_NONINTERLACED;
8528c2ecf20Sopenharmony_ci	var->left_margin = var->right_margin = 16;
8538c2ecf20Sopenharmony_ci	var->upper_margin = var->lower_margin = 16;
8548c2ecf20Sopenharmony_ci	var->hsync_len = var->vsync_len = 8;
8558c2ecf20Sopenharmony_ci	return 0;
8568c2ecf20Sopenharmony_ci}
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_cistatic int
8598c2ecf20Sopenharmony_ciimsttfb_set_par(struct fb_info *info)
8608c2ecf20Sopenharmony_ci{
8618c2ecf20Sopenharmony_ci	struct imstt_par *par = info->par;
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_ci	if (!compute_imstt_regvals(par, info->var.xres, info->var.yres))
8648c2ecf20Sopenharmony_ci		return -EINVAL;
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci	if (info->var.green.length == 6)
8678c2ecf20Sopenharmony_ci		set_565(par);
8688c2ecf20Sopenharmony_ci	else
8698c2ecf20Sopenharmony_ci		set_555(par);
8708c2ecf20Sopenharmony_ci	set_imstt_regvals(info, info->var.bits_per_pixel);
8718c2ecf20Sopenharmony_ci	info->var.pixclock = 1000000 / getclkMHz(par);
8728c2ecf20Sopenharmony_ci	return 0;
8738c2ecf20Sopenharmony_ci}
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_cistatic int
8768c2ecf20Sopenharmony_ciimsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue,
8778c2ecf20Sopenharmony_ci		   u_int transp, struct fb_info *info)
8788c2ecf20Sopenharmony_ci{
8798c2ecf20Sopenharmony_ci	struct imstt_par *par = info->par;
8808c2ecf20Sopenharmony_ci	u_int bpp = info->var.bits_per_pixel;
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci	if (regno > 255)
8838c2ecf20Sopenharmony_ci		return 1;
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci	red >>= 8;
8868c2ecf20Sopenharmony_ci	green >>= 8;
8878c2ecf20Sopenharmony_ci	blue >>= 8;
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_ci	/* PADDRW/PDATA are the same as TVPPADDRW/TVPPDATA */
8908c2ecf20Sopenharmony_ci	if (0 && bpp == 16)	/* screws up X */
8918c2ecf20Sopenharmony_ci		par->cmap_regs[PADDRW] = regno << 3;
8928c2ecf20Sopenharmony_ci	else
8938c2ecf20Sopenharmony_ci		par->cmap_regs[PADDRW] = regno;
8948c2ecf20Sopenharmony_ci	eieio();
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci	par->cmap_regs[PDATA] = red;	eieio();
8978c2ecf20Sopenharmony_ci	par->cmap_regs[PDATA] = green;	eieio();
8988c2ecf20Sopenharmony_ci	par->cmap_regs[PDATA] = blue;	eieio();
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_ci	if (regno < 16)
9018c2ecf20Sopenharmony_ci		switch (bpp) {
9028c2ecf20Sopenharmony_ci			case 16:
9038c2ecf20Sopenharmony_ci				par->palette[regno] =
9048c2ecf20Sopenharmony_ci					(regno << (info->var.green.length ==
9058c2ecf20Sopenharmony_ci					5 ? 10 : 11)) | (regno << 5) | regno;
9068c2ecf20Sopenharmony_ci				break;
9078c2ecf20Sopenharmony_ci			case 24:
9088c2ecf20Sopenharmony_ci				par->palette[regno] =
9098c2ecf20Sopenharmony_ci					(regno << 16) | (regno << 8) | regno;
9108c2ecf20Sopenharmony_ci				break;
9118c2ecf20Sopenharmony_ci			case 32: {
9128c2ecf20Sopenharmony_ci				int i = (regno << 8) | regno;
9138c2ecf20Sopenharmony_ci				par->palette[regno] = (i << 16) |i;
9148c2ecf20Sopenharmony_ci				break;
9158c2ecf20Sopenharmony_ci			}
9168c2ecf20Sopenharmony_ci		}
9178c2ecf20Sopenharmony_ci	return 0;
9188c2ecf20Sopenharmony_ci}
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_cistatic int
9218c2ecf20Sopenharmony_ciimsttfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
9228c2ecf20Sopenharmony_ci{
9238c2ecf20Sopenharmony_ci	if (var->xoffset + info->var.xres > info->var.xres_virtual
9248c2ecf20Sopenharmony_ci	    || var->yoffset + info->var.yres > info->var.yres_virtual)
9258c2ecf20Sopenharmony_ci		return -EINVAL;
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_ci	info->var.xoffset = var->xoffset;
9288c2ecf20Sopenharmony_ci	info->var.yoffset = var->yoffset;
9298c2ecf20Sopenharmony_ci	set_offset(var, info);
9308c2ecf20Sopenharmony_ci	return 0;
9318c2ecf20Sopenharmony_ci}
9328c2ecf20Sopenharmony_ci
9338c2ecf20Sopenharmony_cistatic int
9348c2ecf20Sopenharmony_ciimsttfb_blank(int blank, struct fb_info *info)
9358c2ecf20Sopenharmony_ci{
9368c2ecf20Sopenharmony_ci	struct imstt_par *par = info->par;
9378c2ecf20Sopenharmony_ci	__u32 ctrl;
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_ci	ctrl = read_reg_le32(par->dc_regs, STGCTL);
9408c2ecf20Sopenharmony_ci	if (blank > 0) {
9418c2ecf20Sopenharmony_ci		switch (blank) {
9428c2ecf20Sopenharmony_ci		case FB_BLANK_NORMAL:
9438c2ecf20Sopenharmony_ci		case FB_BLANK_POWERDOWN:
9448c2ecf20Sopenharmony_ci			ctrl &= ~0x00000380;
9458c2ecf20Sopenharmony_ci			if (par->ramdac == IBM) {
9468c2ecf20Sopenharmony_ci				par->cmap_regs[PIDXHI] = 0;		eieio();
9478c2ecf20Sopenharmony_ci				par->cmap_regs[PIDXLO] = MISCTL2;	eieio();
9488c2ecf20Sopenharmony_ci				par->cmap_regs[PIDXDATA] = 0x55;	eieio();
9498c2ecf20Sopenharmony_ci				par->cmap_regs[PIDXLO] = MISCTL1;	eieio();
9508c2ecf20Sopenharmony_ci				par->cmap_regs[PIDXDATA] = 0x11;	eieio();
9518c2ecf20Sopenharmony_ci				par->cmap_regs[PIDXLO] = SYNCCTL;	eieio();
9528c2ecf20Sopenharmony_ci				par->cmap_regs[PIDXDATA] = 0x0f;	eieio();
9538c2ecf20Sopenharmony_ci				par->cmap_regs[PIDXLO] = PWRMNGMT;	eieio();
9548c2ecf20Sopenharmony_ci				par->cmap_regs[PIDXDATA] = 0x1f;	eieio();
9558c2ecf20Sopenharmony_ci				par->cmap_regs[PIDXLO] = CLKCTL;	eieio();
9568c2ecf20Sopenharmony_ci				par->cmap_regs[PIDXDATA] = 0xc0;
9578c2ecf20Sopenharmony_ci			}
9588c2ecf20Sopenharmony_ci			break;
9598c2ecf20Sopenharmony_ci		case FB_BLANK_VSYNC_SUSPEND:
9608c2ecf20Sopenharmony_ci			ctrl &= ~0x00000020;
9618c2ecf20Sopenharmony_ci			break;
9628c2ecf20Sopenharmony_ci		case FB_BLANK_HSYNC_SUSPEND:
9638c2ecf20Sopenharmony_ci			ctrl &= ~0x00000010;
9648c2ecf20Sopenharmony_ci			break;
9658c2ecf20Sopenharmony_ci		}
9668c2ecf20Sopenharmony_ci	} else {
9678c2ecf20Sopenharmony_ci		if (par->ramdac == IBM) {
9688c2ecf20Sopenharmony_ci			ctrl |= 0x000017b0;
9698c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXHI] = 0;		eieio();
9708c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXLO] = CLKCTL;	eieio();
9718c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXDATA] = 0x01;	eieio();
9728c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXLO] = PWRMNGMT;	eieio();
9738c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXDATA] = 0x00;	eieio();
9748c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXLO] = SYNCCTL;	eieio();
9758c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXDATA] = 0x00;	eieio();
9768c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXLO] = MISCTL1;	eieio();
9778c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXDATA] = 0x01;	eieio();
9788c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXLO] = MISCTL2;	eieio();
9798c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXDATA] = 0x45;	eieio();
9808c2ecf20Sopenharmony_ci		} else
9818c2ecf20Sopenharmony_ci			ctrl |= 0x00001780;
9828c2ecf20Sopenharmony_ci	}
9838c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, STGCTL, ctrl);
9848c2ecf20Sopenharmony_ci	return 0;
9858c2ecf20Sopenharmony_ci}
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_cistatic void
9888c2ecf20Sopenharmony_ciimsttfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
9898c2ecf20Sopenharmony_ci{
9908c2ecf20Sopenharmony_ci	struct imstt_par *par = info->par;
9918c2ecf20Sopenharmony_ci	__u32 Bpp, line_pitch, bgc, dx, dy, width, height;
9928c2ecf20Sopenharmony_ci
9938c2ecf20Sopenharmony_ci	bgc = rect->color;
9948c2ecf20Sopenharmony_ci	bgc |= (bgc << 8);
9958c2ecf20Sopenharmony_ci	bgc |= (bgc << 16);
9968c2ecf20Sopenharmony_ci
9978c2ecf20Sopenharmony_ci	Bpp = info->var.bits_per_pixel >> 3,
9988c2ecf20Sopenharmony_ci	line_pitch = info->fix.line_length;
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_ci	dy = rect->dy * line_pitch;
10018c2ecf20Sopenharmony_ci	dx = rect->dx * Bpp;
10028c2ecf20Sopenharmony_ci	height = rect->height;
10038c2ecf20Sopenharmony_ci	height--;
10048c2ecf20Sopenharmony_ci	width = rect->width * Bpp;
10058c2ecf20Sopenharmony_ci	width--;
10068c2ecf20Sopenharmony_ci
10078c2ecf20Sopenharmony_ci	if (rect->rop == ROP_COPY) {
10088c2ecf20Sopenharmony_ci		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
10098c2ecf20Sopenharmony_ci		write_reg_le32(par->dc_regs, DSA, dy + dx);
10108c2ecf20Sopenharmony_ci		write_reg_le32(par->dc_regs, CNT, (height << 16) | width);
10118c2ecf20Sopenharmony_ci		write_reg_le32(par->dc_regs, DP_OCTL, line_pitch);
10128c2ecf20Sopenharmony_ci		write_reg_le32(par->dc_regs, BI, 0xffffffff);
10138c2ecf20Sopenharmony_ci		write_reg_le32(par->dc_regs, MBC, 0xffffffff);
10148c2ecf20Sopenharmony_ci		write_reg_le32(par->dc_regs, CLR, bgc);
10158c2ecf20Sopenharmony_ci		write_reg_le32(par->dc_regs, BLTCTL, 0x840); /* 0x200000 */
10168c2ecf20Sopenharmony_ci		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
10178c2ecf20Sopenharmony_ci		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x40);
10188c2ecf20Sopenharmony_ci	} else {
10198c2ecf20Sopenharmony_ci		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
10208c2ecf20Sopenharmony_ci		write_reg_le32(par->dc_regs, DSA, dy + dx);
10218c2ecf20Sopenharmony_ci		write_reg_le32(par->dc_regs, S1SA, dy + dx);
10228c2ecf20Sopenharmony_ci		write_reg_le32(par->dc_regs, CNT, (height << 16) | width);
10238c2ecf20Sopenharmony_ci		write_reg_le32(par->dc_regs, DP_OCTL, line_pitch);
10248c2ecf20Sopenharmony_ci		write_reg_le32(par->dc_regs, SP, line_pitch);
10258c2ecf20Sopenharmony_ci		write_reg_le32(par->dc_regs, BLTCTL, 0x40005);
10268c2ecf20Sopenharmony_ci		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
10278c2ecf20Sopenharmony_ci		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x40);
10288c2ecf20Sopenharmony_ci	}
10298c2ecf20Sopenharmony_ci}
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_cistatic void
10328c2ecf20Sopenharmony_ciimsttfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
10338c2ecf20Sopenharmony_ci{
10348c2ecf20Sopenharmony_ci	struct imstt_par *par = info->par;
10358c2ecf20Sopenharmony_ci	__u32 Bpp, line_pitch, fb_offset_old, fb_offset_new, sp, dp_octl;
10368c2ecf20Sopenharmony_ci 	__u32 cnt, bltctl, sx, sy, dx, dy, height, width;
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_ci	Bpp = info->var.bits_per_pixel >> 3,
10398c2ecf20Sopenharmony_ci
10408c2ecf20Sopenharmony_ci	sx = area->sx * Bpp;
10418c2ecf20Sopenharmony_ci	sy = area->sy;
10428c2ecf20Sopenharmony_ci	dx = area->dx * Bpp;
10438c2ecf20Sopenharmony_ci	dy = area->dy;
10448c2ecf20Sopenharmony_ci	height = area->height;
10458c2ecf20Sopenharmony_ci	height--;
10468c2ecf20Sopenharmony_ci	width = area->width * Bpp;
10478c2ecf20Sopenharmony_ci	width--;
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_ci	line_pitch = info->fix.line_length;
10508c2ecf20Sopenharmony_ci	bltctl = 0x05;
10518c2ecf20Sopenharmony_ci	sp = line_pitch << 16;
10528c2ecf20Sopenharmony_ci	cnt = height << 16;
10538c2ecf20Sopenharmony_ci
10548c2ecf20Sopenharmony_ci	if (sy < dy) {
10558c2ecf20Sopenharmony_ci		sy += height;
10568c2ecf20Sopenharmony_ci		dy += height;
10578c2ecf20Sopenharmony_ci		sp |= -(line_pitch) & 0xffff;
10588c2ecf20Sopenharmony_ci		dp_octl = -(line_pitch) & 0xffff;
10598c2ecf20Sopenharmony_ci	} else {
10608c2ecf20Sopenharmony_ci		sp |= line_pitch;
10618c2ecf20Sopenharmony_ci		dp_octl = line_pitch;
10628c2ecf20Sopenharmony_ci	}
10638c2ecf20Sopenharmony_ci	if (sx < dx) {
10648c2ecf20Sopenharmony_ci		sx += width;
10658c2ecf20Sopenharmony_ci		dx += width;
10668c2ecf20Sopenharmony_ci		bltctl |= 0x80;
10678c2ecf20Sopenharmony_ci		cnt |= -(width) & 0xffff;
10688c2ecf20Sopenharmony_ci	} else {
10698c2ecf20Sopenharmony_ci		cnt |= width;
10708c2ecf20Sopenharmony_ci	}
10718c2ecf20Sopenharmony_ci	fb_offset_old = sy * line_pitch + sx;
10728c2ecf20Sopenharmony_ci	fb_offset_new = dy * line_pitch + dx;
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_ci	while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
10758c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, S1SA, fb_offset_old);
10768c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, SP, sp);
10778c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, DSA, fb_offset_new);
10788c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, CNT, cnt);
10798c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, DP_OCTL, dp_octl);
10808c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, BLTCTL, bltctl);
10818c2ecf20Sopenharmony_ci	while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
10828c2ecf20Sopenharmony_ci	while(read_reg_le32(par->dc_regs, SSTATUS) & 0x40);
10838c2ecf20Sopenharmony_ci}
10848c2ecf20Sopenharmony_ci
10858c2ecf20Sopenharmony_ci#if 0
10868c2ecf20Sopenharmony_cistatic int
10878c2ecf20Sopenharmony_ciimsttfb_load_cursor_image(struct imstt_par *par, int width, int height, __u8 fgc)
10888c2ecf20Sopenharmony_ci{
10898c2ecf20Sopenharmony_ci	u_int x, y;
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci	if (width > 32 || height > 32)
10928c2ecf20Sopenharmony_ci		return -EINVAL;
10938c2ecf20Sopenharmony_ci
10948c2ecf20Sopenharmony_ci	if (par->ramdac == IBM) {
10958c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXHI] = 1;	eieio();
10968c2ecf20Sopenharmony_ci		for (x = 0; x < 0x100; x++) {
10978c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXLO] = x;		eieio();
10988c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXDATA] = 0x00;	eieio();
10998c2ecf20Sopenharmony_ci		}
11008c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXHI] = 1;	eieio();
11018c2ecf20Sopenharmony_ci		for (y = 0; y < height; y++)
11028c2ecf20Sopenharmony_ci			for (x = 0; x < width >> 2; x++) {
11038c2ecf20Sopenharmony_ci				par->cmap_regs[PIDXLO] = x + y * 8;	eieio();
11048c2ecf20Sopenharmony_ci				par->cmap_regs[PIDXDATA] = 0xff;	eieio();
11058c2ecf20Sopenharmony_ci			}
11068c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXHI] = 0;		eieio();
11078c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXLO] = CURS1R;	eieio();
11088c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXDATA] = fgc;		eieio();
11098c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXLO] = CURS1G;	eieio();
11108c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXDATA] = fgc;		eieio();
11118c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXLO] = CURS1B;	eieio();
11128c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXDATA] = fgc;		eieio();
11138c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXLO] = CURS2R;	eieio();
11148c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXDATA] = fgc;		eieio();
11158c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXLO] = CURS2G;	eieio();
11168c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXDATA] = fgc;		eieio();
11178c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXLO] = CURS2B;	eieio();
11188c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXDATA] = fgc;		eieio();
11198c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXLO] = CURS3R;	eieio();
11208c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXDATA] = fgc;		eieio();
11218c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXLO] = CURS3G;	eieio();
11228c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXDATA] = fgc;		eieio();
11238c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXLO] = CURS3B;	eieio();
11248c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXDATA] = fgc;		eieio();
11258c2ecf20Sopenharmony_ci	} else {
11268c2ecf20Sopenharmony_ci		par->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
11278c2ecf20Sopenharmony_ci		par->cmap_regs[TVPIDATA] &= 0x03;	eieio();
11288c2ecf20Sopenharmony_ci		par->cmap_regs[TVPADDRW] = 0;		eieio();
11298c2ecf20Sopenharmony_ci		for (x = 0; x < 0x200; x++) {
11308c2ecf20Sopenharmony_ci			par->cmap_regs[TVPCRDAT] = 0x00;	eieio();
11318c2ecf20Sopenharmony_ci		}
11328c2ecf20Sopenharmony_ci		for (x = 0; x < 0x200; x++) {
11338c2ecf20Sopenharmony_ci			par->cmap_regs[TVPCRDAT] = 0xff;	eieio();
11348c2ecf20Sopenharmony_ci		}
11358c2ecf20Sopenharmony_ci		par->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
11368c2ecf20Sopenharmony_ci		par->cmap_regs[TVPIDATA] &= 0x03;	eieio();
11378c2ecf20Sopenharmony_ci		for (y = 0; y < height; y++)
11388c2ecf20Sopenharmony_ci			for (x = 0; x < width >> 3; x++) {
11398c2ecf20Sopenharmony_ci				par->cmap_regs[TVPADDRW] = x + y * 8;	eieio();
11408c2ecf20Sopenharmony_ci				par->cmap_regs[TVPCRDAT] = 0xff;		eieio();
11418c2ecf20Sopenharmony_ci			}
11428c2ecf20Sopenharmony_ci		par->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
11438c2ecf20Sopenharmony_ci		par->cmap_regs[TVPIDATA] |= 0x08;	eieio();
11448c2ecf20Sopenharmony_ci		for (y = 0; y < height; y++)
11458c2ecf20Sopenharmony_ci			for (x = 0; x < width >> 3; x++) {
11468c2ecf20Sopenharmony_ci				par->cmap_regs[TVPADDRW] = x + y * 8;	eieio();
11478c2ecf20Sopenharmony_ci				par->cmap_regs[TVPCRDAT] = 0xff;		eieio();
11488c2ecf20Sopenharmony_ci			}
11498c2ecf20Sopenharmony_ci		par->cmap_regs[TVPCADRW] = 0x00;	eieio();
11508c2ecf20Sopenharmony_ci		for (x = 0; x < 12; x++) {
11518c2ecf20Sopenharmony_ci			par->cmap_regs[TVPCDATA] = fgc;
11528c2ecf20Sopenharmony_ci			eieio();
11538c2ecf20Sopenharmony_ci		}
11548c2ecf20Sopenharmony_ci	}
11558c2ecf20Sopenharmony_ci	return 1;
11568c2ecf20Sopenharmony_ci}
11578c2ecf20Sopenharmony_ci
11588c2ecf20Sopenharmony_cistatic void
11598c2ecf20Sopenharmony_ciimstt_set_cursor(struct imstt_par *par, struct fb_image *d, int on)
11608c2ecf20Sopenharmony_ci{
11618c2ecf20Sopenharmony_ci	if (par->ramdac == IBM) {
11628c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXHI] = 0;	eieio();
11638c2ecf20Sopenharmony_ci		if (!on) {
11648c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXLO] = CURSCTL;	eieio();
11658c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXDATA] = 0x00;	eieio();
11668c2ecf20Sopenharmony_ci		} else {
11678c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXLO] = CURSXHI;	eieio();
11688c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXDATA] = d->dx >> 8;	eieio();
11698c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXLO] = CURSXLO;	eieio();
11708c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXDATA] = d->dx & 0xff;eieio();
11718c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXLO] = CURSYHI;	eieio();
11728c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXDATA] = d->dy >> 8;	eieio();
11738c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXLO] = CURSYLO;	eieio();
11748c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXDATA] = d->dy & 0xff;eieio();
11758c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXLO] = CURSCTL;	eieio();
11768c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXDATA] = 0x02;	eieio();
11778c2ecf20Sopenharmony_ci		}
11788c2ecf20Sopenharmony_ci	} else {
11798c2ecf20Sopenharmony_ci		if (!on) {
11808c2ecf20Sopenharmony_ci			par->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
11818c2ecf20Sopenharmony_ci			par->cmap_regs[TVPIDATA] = 0x00;	eieio();
11828c2ecf20Sopenharmony_ci		} else {
11838c2ecf20Sopenharmony_ci			__u16 x = d->dx + 0x40, y = d->dy + 0x40;
11848c2ecf20Sopenharmony_ci
11858c2ecf20Sopenharmony_ci			par->cmap_regs[TVPCXPOH] = x >> 8;	eieio();
11868c2ecf20Sopenharmony_ci			par->cmap_regs[TVPCXPOL] = x & 0xff;	eieio();
11878c2ecf20Sopenharmony_ci			par->cmap_regs[TVPCYPOH] = y >> 8;	eieio();
11888c2ecf20Sopenharmony_ci			par->cmap_regs[TVPCYPOL] = y & 0xff;	eieio();
11898c2ecf20Sopenharmony_ci			par->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
11908c2ecf20Sopenharmony_ci			par->cmap_regs[TVPIDATA] = 0x02;	eieio();
11918c2ecf20Sopenharmony_ci		}
11928c2ecf20Sopenharmony_ci	}
11938c2ecf20Sopenharmony_ci}
11948c2ecf20Sopenharmony_ci
11958c2ecf20Sopenharmony_cistatic int
11968c2ecf20Sopenharmony_ciimsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
11978c2ecf20Sopenharmony_ci{
11988c2ecf20Sopenharmony_ci	struct imstt_par *par = info->par;
11998c2ecf20Sopenharmony_ci        u32 flags = cursor->set, fg, bg, xx, yy;
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_ci	if (cursor->dest == NULL && cursor->rop == ROP_XOR)
12028c2ecf20Sopenharmony_ci		return 1;
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_ci	imstt_set_cursor(info, cursor, 0);
12058c2ecf20Sopenharmony_ci
12068c2ecf20Sopenharmony_ci	if (flags & FB_CUR_SETPOS) {
12078c2ecf20Sopenharmony_ci		xx = cursor->image.dx - info->var.xoffset;
12088c2ecf20Sopenharmony_ci		yy = cursor->image.dy - info->var.yoffset;
12098c2ecf20Sopenharmony_ci	}
12108c2ecf20Sopenharmony_ci
12118c2ecf20Sopenharmony_ci	if (flags & FB_CUR_SETSIZE) {
12128c2ecf20Sopenharmony_ci        }
12138c2ecf20Sopenharmony_ci
12148c2ecf20Sopenharmony_ci        if (flags & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP)) {
12158c2ecf20Sopenharmony_ci                int fg_idx = cursor->image.fg_color;
12168c2ecf20Sopenharmony_ci                int width = (cursor->image.width+7)/8;
12178c2ecf20Sopenharmony_ci                u8 *dat = (u8 *) cursor->image.data;
12188c2ecf20Sopenharmony_ci                u8 *dst = (u8 *) cursor->dest;
12198c2ecf20Sopenharmony_ci                u8 *msk = (u8 *) cursor->mask;
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_ci                switch (cursor->rop) {
12228c2ecf20Sopenharmony_ci                case ROP_XOR:
12238c2ecf20Sopenharmony_ci                        for (i = 0; i < cursor->image.height; i++) {
12248c2ecf20Sopenharmony_ci                                for (j = 0; j < width; j++) {
12258c2ecf20Sopenharmony_ci                                        d_idx = i * MAX_CURS/8  + j;
12268c2ecf20Sopenharmony_ci                                        data[d_idx] =  byte_rev[dat[s_idx] ^
12278c2ecf20Sopenharmony_ci                                                                dst[s_idx]];
12288c2ecf20Sopenharmony_ci                                        mask[d_idx] = byte_rev[msk[s_idx]];
12298c2ecf20Sopenharmony_ci                                        s_idx++;
12308c2ecf20Sopenharmony_ci                                }
12318c2ecf20Sopenharmony_ci                        }
12328c2ecf20Sopenharmony_ci                        break;
12338c2ecf20Sopenharmony_ci                case ROP_COPY:
12348c2ecf20Sopenharmony_ci                default:
12358c2ecf20Sopenharmony_ci                        for (i = 0; i < cursor->image.height; i++) {
12368c2ecf20Sopenharmony_ci                                for (j = 0; j < width; j++) {
12378c2ecf20Sopenharmony_ci                                        d_idx = i * MAX_CURS/8 + j;
12388c2ecf20Sopenharmony_ci                                        data[d_idx] = byte_rev[dat[s_idx]];
12398c2ecf20Sopenharmony_ci                                        mask[d_idx] = byte_rev[msk[s_idx]];
12408c2ecf20Sopenharmony_ci                                        s_idx++;
12418c2ecf20Sopenharmony_ci                                }
12428c2ecf20Sopenharmony_ci			}
12438c2ecf20Sopenharmony_ci			break;
12448c2ecf20Sopenharmony_ci		}
12458c2ecf20Sopenharmony_ci
12468c2ecf20Sopenharmony_ci		fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
12478c2ecf20Sopenharmony_ci                     ((info->cmap.green[fg_idx] & 0xf8) << 2) |
12488c2ecf20Sopenharmony_ci                     ((info->cmap.blue[fg_idx] & 0xf8) >> 3) | 1 << 15;
12498c2ecf20Sopenharmony_ci
12508c2ecf20Sopenharmony_ci		imsttfb_load_cursor_image(par, xx, yy, fgc);
12518c2ecf20Sopenharmony_ci	}
12528c2ecf20Sopenharmony_ci	if (cursor->enable)
12538c2ecf20Sopenharmony_ci		imstt_set_cursor(info, cursor, 1);
12548c2ecf20Sopenharmony_ci	return 0;
12558c2ecf20Sopenharmony_ci}
12568c2ecf20Sopenharmony_ci#endif
12578c2ecf20Sopenharmony_ci
12588c2ecf20Sopenharmony_ci#define FBIMSTT_SETREG		0x545401
12598c2ecf20Sopenharmony_ci#define FBIMSTT_GETREG		0x545402
12608c2ecf20Sopenharmony_ci#define FBIMSTT_SETCMAPREG	0x545403
12618c2ecf20Sopenharmony_ci#define FBIMSTT_GETCMAPREG	0x545404
12628c2ecf20Sopenharmony_ci#define FBIMSTT_SETIDXREG	0x545405
12638c2ecf20Sopenharmony_ci#define FBIMSTT_GETIDXREG	0x545406
12648c2ecf20Sopenharmony_ci
12658c2ecf20Sopenharmony_cistatic int
12668c2ecf20Sopenharmony_ciimsttfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
12678c2ecf20Sopenharmony_ci{
12688c2ecf20Sopenharmony_ci	struct imstt_par *par = info->par;
12698c2ecf20Sopenharmony_ci	void __user *argp = (void __user *)arg;
12708c2ecf20Sopenharmony_ci	__u32 reg[2];
12718c2ecf20Sopenharmony_ci	__u8 idx[2];
12728c2ecf20Sopenharmony_ci
12738c2ecf20Sopenharmony_ci	switch (cmd) {
12748c2ecf20Sopenharmony_ci		case FBIMSTT_SETREG:
12758c2ecf20Sopenharmony_ci			if (copy_from_user(reg, argp, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
12768c2ecf20Sopenharmony_ci				return -EFAULT;
12778c2ecf20Sopenharmony_ci			write_reg_le32(par->dc_regs, reg[0], reg[1]);
12788c2ecf20Sopenharmony_ci			return 0;
12798c2ecf20Sopenharmony_ci		case FBIMSTT_GETREG:
12808c2ecf20Sopenharmony_ci			if (copy_from_user(reg, argp, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
12818c2ecf20Sopenharmony_ci				return -EFAULT;
12828c2ecf20Sopenharmony_ci			reg[1] = read_reg_le32(par->dc_regs, reg[0]);
12838c2ecf20Sopenharmony_ci			if (copy_to_user((void __user *)(arg + 4), &reg[1], 4))
12848c2ecf20Sopenharmony_ci				return -EFAULT;
12858c2ecf20Sopenharmony_ci			return 0;
12868c2ecf20Sopenharmony_ci		case FBIMSTT_SETCMAPREG:
12878c2ecf20Sopenharmony_ci			if (copy_from_user(reg, argp, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
12888c2ecf20Sopenharmony_ci				return -EFAULT;
12898c2ecf20Sopenharmony_ci			write_reg_le32(((u_int __iomem *)par->cmap_regs), reg[0], reg[1]);
12908c2ecf20Sopenharmony_ci			return 0;
12918c2ecf20Sopenharmony_ci		case FBIMSTT_GETCMAPREG:
12928c2ecf20Sopenharmony_ci			if (copy_from_user(reg, argp, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
12938c2ecf20Sopenharmony_ci				return -EFAULT;
12948c2ecf20Sopenharmony_ci			reg[1] = read_reg_le32(((u_int __iomem *)par->cmap_regs), reg[0]);
12958c2ecf20Sopenharmony_ci			if (copy_to_user((void __user *)(arg + 4), &reg[1], 4))
12968c2ecf20Sopenharmony_ci				return -EFAULT;
12978c2ecf20Sopenharmony_ci			return 0;
12988c2ecf20Sopenharmony_ci		case FBIMSTT_SETIDXREG:
12998c2ecf20Sopenharmony_ci			if (copy_from_user(idx, argp, 2))
13008c2ecf20Sopenharmony_ci				return -EFAULT;
13018c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXHI] = 0;		eieio();
13028c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXLO] = idx[0];	eieio();
13038c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXDATA] = idx[1];	eieio();
13048c2ecf20Sopenharmony_ci			return 0;
13058c2ecf20Sopenharmony_ci		case FBIMSTT_GETIDXREG:
13068c2ecf20Sopenharmony_ci			if (copy_from_user(idx, argp, 1))
13078c2ecf20Sopenharmony_ci				return -EFAULT;
13088c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXHI] = 0;		eieio();
13098c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXLO] = idx[0];	eieio();
13108c2ecf20Sopenharmony_ci			idx[1] = par->cmap_regs[PIDXDATA];
13118c2ecf20Sopenharmony_ci			if (copy_to_user((void __user *)(arg + 1), &idx[1], 1))
13128c2ecf20Sopenharmony_ci				return -EFAULT;
13138c2ecf20Sopenharmony_ci			return 0;
13148c2ecf20Sopenharmony_ci		default:
13158c2ecf20Sopenharmony_ci			return -ENOIOCTLCMD;
13168c2ecf20Sopenharmony_ci	}
13178c2ecf20Sopenharmony_ci}
13188c2ecf20Sopenharmony_ci
13198c2ecf20Sopenharmony_cistatic const struct pci_device_id imsttfb_pci_tbl[] = {
13208c2ecf20Sopenharmony_ci	{ PCI_VENDOR_ID_IMS, PCI_DEVICE_ID_IMS_TT128,
13218c2ecf20Sopenharmony_ci	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, IBM },
13228c2ecf20Sopenharmony_ci	{ PCI_VENDOR_ID_IMS, PCI_DEVICE_ID_IMS_TT3D,
13238c2ecf20Sopenharmony_ci	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, TVP },
13248c2ecf20Sopenharmony_ci	{ 0, }
13258c2ecf20Sopenharmony_ci};
13268c2ecf20Sopenharmony_ci
13278c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, imsttfb_pci_tbl);
13288c2ecf20Sopenharmony_ci
13298c2ecf20Sopenharmony_cistatic struct pci_driver imsttfb_pci_driver = {
13308c2ecf20Sopenharmony_ci	.name =		"imsttfb",
13318c2ecf20Sopenharmony_ci	.id_table =	imsttfb_pci_tbl,
13328c2ecf20Sopenharmony_ci	.probe =	imsttfb_probe,
13338c2ecf20Sopenharmony_ci	.remove =	imsttfb_remove,
13348c2ecf20Sopenharmony_ci};
13358c2ecf20Sopenharmony_ci
13368c2ecf20Sopenharmony_cistatic const struct fb_ops imsttfb_ops = {
13378c2ecf20Sopenharmony_ci	.owner 		= THIS_MODULE,
13388c2ecf20Sopenharmony_ci	.fb_check_var	= imsttfb_check_var,
13398c2ecf20Sopenharmony_ci	.fb_set_par 	= imsttfb_set_par,
13408c2ecf20Sopenharmony_ci	.fb_setcolreg 	= imsttfb_setcolreg,
13418c2ecf20Sopenharmony_ci	.fb_pan_display = imsttfb_pan_display,
13428c2ecf20Sopenharmony_ci	.fb_blank 	= imsttfb_blank,
13438c2ecf20Sopenharmony_ci	.fb_fillrect	= imsttfb_fillrect,
13448c2ecf20Sopenharmony_ci	.fb_copyarea	= imsttfb_copyarea,
13458c2ecf20Sopenharmony_ci	.fb_imageblit	= cfb_imageblit,
13468c2ecf20Sopenharmony_ci	.fb_ioctl 	= imsttfb_ioctl,
13478c2ecf20Sopenharmony_ci};
13488c2ecf20Sopenharmony_ci
13498c2ecf20Sopenharmony_cistatic int init_imstt(struct fb_info *info)
13508c2ecf20Sopenharmony_ci{
13518c2ecf20Sopenharmony_ci	struct imstt_par *par = info->par;
13528c2ecf20Sopenharmony_ci	__u32 i, tmp, *ip, *end;
13538c2ecf20Sopenharmony_ci
13548c2ecf20Sopenharmony_ci	tmp = read_reg_le32(par->dc_regs, PRC);
13558c2ecf20Sopenharmony_ci	if (par->ramdac == IBM)
13568c2ecf20Sopenharmony_ci		info->fix.smem_len = (tmp & 0x0004) ? 0x400000 : 0x200000;
13578c2ecf20Sopenharmony_ci	else
13588c2ecf20Sopenharmony_ci		info->fix.smem_len = 0x800000;
13598c2ecf20Sopenharmony_ci
13608c2ecf20Sopenharmony_ci	ip = (__u32 *)info->screen_base;
13618c2ecf20Sopenharmony_ci	end = (__u32 *)(info->screen_base + info->fix.smem_len);
13628c2ecf20Sopenharmony_ci	while (ip < end)
13638c2ecf20Sopenharmony_ci		*ip++ = 0;
13648c2ecf20Sopenharmony_ci
13658c2ecf20Sopenharmony_ci	/* initialize the card */
13668c2ecf20Sopenharmony_ci	tmp = read_reg_le32(par->dc_regs, STGCTL);
13678c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, STGCTL, tmp & ~0x1);
13688c2ecf20Sopenharmony_ci	write_reg_le32(par->dc_regs, SSR, 0);
13698c2ecf20Sopenharmony_ci
13708c2ecf20Sopenharmony_ci	/* set default values for DAC registers */
13718c2ecf20Sopenharmony_ci	if (par->ramdac == IBM) {
13728c2ecf20Sopenharmony_ci		par->cmap_regs[PPMASK] = 0xff;
13738c2ecf20Sopenharmony_ci		eieio();
13748c2ecf20Sopenharmony_ci		par->cmap_regs[PIDXHI] = 0;
13758c2ecf20Sopenharmony_ci		eieio();
13768c2ecf20Sopenharmony_ci		for (i = 0; i < ARRAY_SIZE(ibm_initregs); i++) {
13778c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXLO] = ibm_initregs[i].addr;
13788c2ecf20Sopenharmony_ci			eieio();
13798c2ecf20Sopenharmony_ci			par->cmap_regs[PIDXDATA] = ibm_initregs[i].value;
13808c2ecf20Sopenharmony_ci			eieio();
13818c2ecf20Sopenharmony_ci		}
13828c2ecf20Sopenharmony_ci	} else {
13838c2ecf20Sopenharmony_ci		for (i = 0; i < ARRAY_SIZE(tvp_initregs); i++) {
13848c2ecf20Sopenharmony_ci			par->cmap_regs[TVPADDRW] = tvp_initregs[i].addr;
13858c2ecf20Sopenharmony_ci			eieio();
13868c2ecf20Sopenharmony_ci			par->cmap_regs[TVPIDATA] = tvp_initregs[i].value;
13878c2ecf20Sopenharmony_ci			eieio();
13888c2ecf20Sopenharmony_ci		}
13898c2ecf20Sopenharmony_ci	}
13908c2ecf20Sopenharmony_ci
13918c2ecf20Sopenharmony_ci#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
13928c2ecf20Sopenharmony_ci	if (IS_REACHABLE(CONFIG_NVRAM) && machine_is(powermac)) {
13938c2ecf20Sopenharmony_ci		int vmode = init_vmode, cmode = init_cmode;
13948c2ecf20Sopenharmony_ci
13958c2ecf20Sopenharmony_ci		if (vmode == -1) {
13968c2ecf20Sopenharmony_ci			vmode = nvram_read_byte(NV_VMODE);
13978c2ecf20Sopenharmony_ci			if (vmode <= 0 || vmode > VMODE_MAX)
13988c2ecf20Sopenharmony_ci				vmode = VMODE_640_480_67;
13998c2ecf20Sopenharmony_ci		}
14008c2ecf20Sopenharmony_ci		if (cmode == -1) {
14018c2ecf20Sopenharmony_ci			cmode = nvram_read_byte(NV_CMODE);
14028c2ecf20Sopenharmony_ci			if (cmode < CMODE_8 || cmode > CMODE_32)
14038c2ecf20Sopenharmony_ci				cmode = CMODE_8;
14048c2ecf20Sopenharmony_ci		}
14058c2ecf20Sopenharmony_ci		if (mac_vmode_to_var(vmode, cmode, &info->var)) {
14068c2ecf20Sopenharmony_ci			info->var.xres = info->var.xres_virtual = INIT_XRES;
14078c2ecf20Sopenharmony_ci			info->var.yres = info->var.yres_virtual = INIT_YRES;
14088c2ecf20Sopenharmony_ci			info->var.bits_per_pixel = INIT_BPP;
14098c2ecf20Sopenharmony_ci		}
14108c2ecf20Sopenharmony_ci	} else
14118c2ecf20Sopenharmony_ci#endif
14128c2ecf20Sopenharmony_ci	{
14138c2ecf20Sopenharmony_ci		info->var.xres = info->var.xres_virtual = INIT_XRES;
14148c2ecf20Sopenharmony_ci		info->var.yres = info->var.yres_virtual = INIT_YRES;
14158c2ecf20Sopenharmony_ci		info->var.bits_per_pixel = INIT_BPP;
14168c2ecf20Sopenharmony_ci	}
14178c2ecf20Sopenharmony_ci
14188c2ecf20Sopenharmony_ci	if ((info->var.xres * info->var.yres) * (info->var.bits_per_pixel >> 3) > info->fix.smem_len
14198c2ecf20Sopenharmony_ci	    || !(compute_imstt_regvals(par, info->var.xres, info->var.yres))) {
14208c2ecf20Sopenharmony_ci		printk("imsttfb: %ux%ux%u not supported\n", info->var.xres, info->var.yres, info->var.bits_per_pixel);
14218c2ecf20Sopenharmony_ci		framebuffer_release(info);
14228c2ecf20Sopenharmony_ci		return -ENODEV;
14238c2ecf20Sopenharmony_ci	}
14248c2ecf20Sopenharmony_ci
14258c2ecf20Sopenharmony_ci	sprintf(info->fix.id, "IMS TT (%s)", par->ramdac == IBM ? "IBM" : "TVP");
14268c2ecf20Sopenharmony_ci	info->fix.mmio_len = 0x1000;
14278c2ecf20Sopenharmony_ci	info->fix.accel = FB_ACCEL_IMS_TWINTURBO;
14288c2ecf20Sopenharmony_ci	info->fix.type = FB_TYPE_PACKED_PIXELS;
14298c2ecf20Sopenharmony_ci	info->fix.visual = info->var.bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR
14308c2ecf20Sopenharmony_ci							: FB_VISUAL_DIRECTCOLOR;
14318c2ecf20Sopenharmony_ci	info->fix.line_length = info->var.xres * (info->var.bits_per_pixel >> 3);
14328c2ecf20Sopenharmony_ci	info->fix.xpanstep = 8;
14338c2ecf20Sopenharmony_ci	info->fix.ypanstep = 1;
14348c2ecf20Sopenharmony_ci	info->fix.ywrapstep = 0;
14358c2ecf20Sopenharmony_ci
14368c2ecf20Sopenharmony_ci	info->var.accel_flags = FB_ACCELF_TEXT;
14378c2ecf20Sopenharmony_ci
14388c2ecf20Sopenharmony_ci//	if (par->ramdac == IBM)
14398c2ecf20Sopenharmony_ci//		imstt_cursor_init(info);
14408c2ecf20Sopenharmony_ci	if (info->var.green.length == 6)
14418c2ecf20Sopenharmony_ci		set_565(par);
14428c2ecf20Sopenharmony_ci	else
14438c2ecf20Sopenharmony_ci		set_555(par);
14448c2ecf20Sopenharmony_ci	set_imstt_regvals(info, info->var.bits_per_pixel);
14458c2ecf20Sopenharmony_ci
14468c2ecf20Sopenharmony_ci	info->var.pixclock = 1000000 / getclkMHz(par);
14478c2ecf20Sopenharmony_ci
14488c2ecf20Sopenharmony_ci	info->fbops = &imsttfb_ops;
14498c2ecf20Sopenharmony_ci	info->flags = FBINFO_DEFAULT |
14508c2ecf20Sopenharmony_ci                      FBINFO_HWACCEL_COPYAREA |
14518c2ecf20Sopenharmony_ci	              FBINFO_HWACCEL_FILLRECT |
14528c2ecf20Sopenharmony_ci	              FBINFO_HWACCEL_YPAN;
14538c2ecf20Sopenharmony_ci
14548c2ecf20Sopenharmony_ci	fb_alloc_cmap(&info->cmap, 0, 0);
14558c2ecf20Sopenharmony_ci
14568c2ecf20Sopenharmony_ci	if (register_framebuffer(info) < 0) {
14578c2ecf20Sopenharmony_ci		framebuffer_release(info);
14588c2ecf20Sopenharmony_ci		return -ENODEV;
14598c2ecf20Sopenharmony_ci	}
14608c2ecf20Sopenharmony_ci
14618c2ecf20Sopenharmony_ci	tmp = (read_reg_le32(par->dc_regs, SSTATUS) & 0x0f00) >> 8;
14628c2ecf20Sopenharmony_ci	fb_info(info, "%s frame buffer; %uMB vram; chip version %u\n",
14638c2ecf20Sopenharmony_ci		info->fix.id, info->fix.smem_len >> 20, tmp);
14648c2ecf20Sopenharmony_ci	return 0;
14658c2ecf20Sopenharmony_ci}
14668c2ecf20Sopenharmony_ci
14678c2ecf20Sopenharmony_cistatic int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
14688c2ecf20Sopenharmony_ci{
14698c2ecf20Sopenharmony_ci	unsigned long addr, size;
14708c2ecf20Sopenharmony_ci	struct imstt_par *par;
14718c2ecf20Sopenharmony_ci	struct fb_info *info;
14728c2ecf20Sopenharmony_ci	struct device_node *dp;
14738c2ecf20Sopenharmony_ci	int ret = -ENOMEM;
14748c2ecf20Sopenharmony_ci
14758c2ecf20Sopenharmony_ci	dp = pci_device_to_OF_node(pdev);
14768c2ecf20Sopenharmony_ci	if(dp)
14778c2ecf20Sopenharmony_ci		printk(KERN_INFO "%s: OF name %pOFn\n",__func__, dp);
14788c2ecf20Sopenharmony_ci	else if (IS_ENABLED(CONFIG_OF))
14798c2ecf20Sopenharmony_ci		printk(KERN_ERR "imsttfb: no OF node for pci device\n");
14808c2ecf20Sopenharmony_ci
14818c2ecf20Sopenharmony_ci	info = framebuffer_alloc(sizeof(struct imstt_par), &pdev->dev);
14828c2ecf20Sopenharmony_ci	if (!info)
14838c2ecf20Sopenharmony_ci		return -ENOMEM;
14848c2ecf20Sopenharmony_ci
14858c2ecf20Sopenharmony_ci	par = info->par;
14868c2ecf20Sopenharmony_ci
14878c2ecf20Sopenharmony_ci	addr = pci_resource_start (pdev, 0);
14888c2ecf20Sopenharmony_ci	size = pci_resource_len (pdev, 0);
14898c2ecf20Sopenharmony_ci
14908c2ecf20Sopenharmony_ci	if (!request_mem_region(addr, size, "imsttfb")) {
14918c2ecf20Sopenharmony_ci		printk(KERN_ERR "imsttfb: Can't reserve memory region\n");
14928c2ecf20Sopenharmony_ci		ret = -ENODEV;
14938c2ecf20Sopenharmony_ci		goto release_info;
14948c2ecf20Sopenharmony_ci	}
14958c2ecf20Sopenharmony_ci
14968c2ecf20Sopenharmony_ci	switch (pdev->device) {
14978c2ecf20Sopenharmony_ci		case PCI_DEVICE_ID_IMS_TT128: /* IMS,tt128mbA */
14988c2ecf20Sopenharmony_ci			par->ramdac = IBM;
14998c2ecf20Sopenharmony_ci			if (of_node_name_eq(dp, "IMS,tt128mb8") ||
15008c2ecf20Sopenharmony_ci			    of_node_name_eq(dp, "IMS,tt128mb8A"))
15018c2ecf20Sopenharmony_ci				par->ramdac = TVP;
15028c2ecf20Sopenharmony_ci			break;
15038c2ecf20Sopenharmony_ci		case PCI_DEVICE_ID_IMS_TT3D:  /* IMS,tt3d */
15048c2ecf20Sopenharmony_ci			par->ramdac = TVP;
15058c2ecf20Sopenharmony_ci			break;
15068c2ecf20Sopenharmony_ci		default:
15078c2ecf20Sopenharmony_ci			printk(KERN_INFO "imsttfb: Device 0x%x unknown, "
15088c2ecf20Sopenharmony_ci					 "contact maintainer.\n", pdev->device);
15098c2ecf20Sopenharmony_ci			ret = -ENODEV;
15108c2ecf20Sopenharmony_ci			goto release_mem_region;
15118c2ecf20Sopenharmony_ci	}
15128c2ecf20Sopenharmony_ci
15138c2ecf20Sopenharmony_ci	info->fix.smem_start = addr;
15148c2ecf20Sopenharmony_ci	info->screen_base = (__u8 *)ioremap(addr, par->ramdac == IBM ?
15158c2ecf20Sopenharmony_ci					    0x400000 : 0x800000);
15168c2ecf20Sopenharmony_ci	if (!info->screen_base)
15178c2ecf20Sopenharmony_ci		goto release_mem_region;
15188c2ecf20Sopenharmony_ci	info->fix.mmio_start = addr + 0x800000;
15198c2ecf20Sopenharmony_ci	par->dc_regs = ioremap(addr + 0x800000, 0x1000);
15208c2ecf20Sopenharmony_ci	if (!par->dc_regs)
15218c2ecf20Sopenharmony_ci		goto unmap_screen_base;
15228c2ecf20Sopenharmony_ci	par->cmap_regs_phys = addr + 0x840000;
15238c2ecf20Sopenharmony_ci	par->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000);
15248c2ecf20Sopenharmony_ci	if (!par->cmap_regs)
15258c2ecf20Sopenharmony_ci		goto unmap_dc_regs;
15268c2ecf20Sopenharmony_ci	info->pseudo_palette = par->palette;
15278c2ecf20Sopenharmony_ci	ret = init_imstt(info);
15288c2ecf20Sopenharmony_ci	if (ret)
15298c2ecf20Sopenharmony_ci		goto unmap_cmap_regs;
15308c2ecf20Sopenharmony_ci
15318c2ecf20Sopenharmony_ci	pci_set_drvdata(pdev, info);
15328c2ecf20Sopenharmony_ci	return 0;
15338c2ecf20Sopenharmony_ci
15348c2ecf20Sopenharmony_ciunmap_cmap_regs:
15358c2ecf20Sopenharmony_ci	iounmap(par->cmap_regs);
15368c2ecf20Sopenharmony_ciunmap_dc_regs:
15378c2ecf20Sopenharmony_ci	iounmap(par->dc_regs);
15388c2ecf20Sopenharmony_ciunmap_screen_base:
15398c2ecf20Sopenharmony_ci	iounmap(info->screen_base);
15408c2ecf20Sopenharmony_cirelease_mem_region:
15418c2ecf20Sopenharmony_ci	release_mem_region(addr, size);
15428c2ecf20Sopenharmony_cirelease_info:
15438c2ecf20Sopenharmony_ci	framebuffer_release(info);
15448c2ecf20Sopenharmony_ci	return ret;
15458c2ecf20Sopenharmony_ci}
15468c2ecf20Sopenharmony_ci
15478c2ecf20Sopenharmony_cistatic void imsttfb_remove(struct pci_dev *pdev)
15488c2ecf20Sopenharmony_ci{
15498c2ecf20Sopenharmony_ci	struct fb_info *info = pci_get_drvdata(pdev);
15508c2ecf20Sopenharmony_ci	struct imstt_par *par = info->par;
15518c2ecf20Sopenharmony_ci	int size = pci_resource_len(pdev, 0);
15528c2ecf20Sopenharmony_ci
15538c2ecf20Sopenharmony_ci	unregister_framebuffer(info);
15548c2ecf20Sopenharmony_ci	iounmap(par->cmap_regs);
15558c2ecf20Sopenharmony_ci	iounmap(par->dc_regs);
15568c2ecf20Sopenharmony_ci	iounmap(info->screen_base);
15578c2ecf20Sopenharmony_ci	release_mem_region(info->fix.smem_start, size);
15588c2ecf20Sopenharmony_ci	framebuffer_release(info);
15598c2ecf20Sopenharmony_ci}
15608c2ecf20Sopenharmony_ci
15618c2ecf20Sopenharmony_ci#ifndef MODULE
15628c2ecf20Sopenharmony_cistatic int __init
15638c2ecf20Sopenharmony_ciimsttfb_setup(char *options)
15648c2ecf20Sopenharmony_ci{
15658c2ecf20Sopenharmony_ci	char *this_opt;
15668c2ecf20Sopenharmony_ci
15678c2ecf20Sopenharmony_ci	if (!options || !*options)
15688c2ecf20Sopenharmony_ci		return 0;
15698c2ecf20Sopenharmony_ci
15708c2ecf20Sopenharmony_ci	while ((this_opt = strsep(&options, ",")) != NULL) {
15718c2ecf20Sopenharmony_ci		if (!strncmp(this_opt, "font:", 5)) {
15728c2ecf20Sopenharmony_ci			char *p;
15738c2ecf20Sopenharmony_ci			int i;
15748c2ecf20Sopenharmony_ci
15758c2ecf20Sopenharmony_ci			p = this_opt + 5;
15768c2ecf20Sopenharmony_ci			for (i = 0; i < sizeof(fontname) - 1; i++)
15778c2ecf20Sopenharmony_ci				if (!*p || *p == ' ' || *p == ',')
15788c2ecf20Sopenharmony_ci					break;
15798c2ecf20Sopenharmony_ci			memcpy(fontname, this_opt + 5, i);
15808c2ecf20Sopenharmony_ci			fontname[i] = 0;
15818c2ecf20Sopenharmony_ci		} else if (!strncmp(this_opt, "inverse", 7)) {
15828c2ecf20Sopenharmony_ci			inverse = 1;
15838c2ecf20Sopenharmony_ci			fb_invert_cmaps();
15848c2ecf20Sopenharmony_ci		}
15858c2ecf20Sopenharmony_ci#if defined(CONFIG_PPC_PMAC)
15868c2ecf20Sopenharmony_ci		else if (!strncmp(this_opt, "vmode:", 6)) {
15878c2ecf20Sopenharmony_ci			int vmode = simple_strtoul(this_opt+6, NULL, 0);
15888c2ecf20Sopenharmony_ci			if (vmode > 0 && vmode <= VMODE_MAX)
15898c2ecf20Sopenharmony_ci				init_vmode = vmode;
15908c2ecf20Sopenharmony_ci		} else if (!strncmp(this_opt, "cmode:", 6)) {
15918c2ecf20Sopenharmony_ci			int cmode = simple_strtoul(this_opt+6, NULL, 0);
15928c2ecf20Sopenharmony_ci			switch (cmode) {
15938c2ecf20Sopenharmony_ci				case CMODE_8:
15948c2ecf20Sopenharmony_ci				case 8:
15958c2ecf20Sopenharmony_ci					init_cmode = CMODE_8;
15968c2ecf20Sopenharmony_ci					break;
15978c2ecf20Sopenharmony_ci				case CMODE_16:
15988c2ecf20Sopenharmony_ci				case 15:
15998c2ecf20Sopenharmony_ci				case 16:
16008c2ecf20Sopenharmony_ci					init_cmode = CMODE_16;
16018c2ecf20Sopenharmony_ci					break;
16028c2ecf20Sopenharmony_ci				case CMODE_32:
16038c2ecf20Sopenharmony_ci				case 24:
16048c2ecf20Sopenharmony_ci				case 32:
16058c2ecf20Sopenharmony_ci					init_cmode = CMODE_32;
16068c2ecf20Sopenharmony_ci					break;
16078c2ecf20Sopenharmony_ci			}
16088c2ecf20Sopenharmony_ci		}
16098c2ecf20Sopenharmony_ci#endif
16108c2ecf20Sopenharmony_ci	}
16118c2ecf20Sopenharmony_ci	return 0;
16128c2ecf20Sopenharmony_ci}
16138c2ecf20Sopenharmony_ci
16148c2ecf20Sopenharmony_ci#endif /* MODULE */
16158c2ecf20Sopenharmony_ci
16168c2ecf20Sopenharmony_cistatic int __init imsttfb_init(void)
16178c2ecf20Sopenharmony_ci{
16188c2ecf20Sopenharmony_ci#ifndef MODULE
16198c2ecf20Sopenharmony_ci	char *option = NULL;
16208c2ecf20Sopenharmony_ci
16218c2ecf20Sopenharmony_ci	if (fb_get_options("imsttfb", &option))
16228c2ecf20Sopenharmony_ci		return -ENODEV;
16238c2ecf20Sopenharmony_ci
16248c2ecf20Sopenharmony_ci	imsttfb_setup(option);
16258c2ecf20Sopenharmony_ci#endif
16268c2ecf20Sopenharmony_ci	return pci_register_driver(&imsttfb_pci_driver);
16278c2ecf20Sopenharmony_ci}
16288c2ecf20Sopenharmony_ci
16298c2ecf20Sopenharmony_cistatic void __exit imsttfb_exit(void)
16308c2ecf20Sopenharmony_ci{
16318c2ecf20Sopenharmony_ci	pci_unregister_driver(&imsttfb_pci_driver);
16328c2ecf20Sopenharmony_ci}
16338c2ecf20Sopenharmony_ci
16348c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
16358c2ecf20Sopenharmony_ci
16368c2ecf20Sopenharmony_cimodule_init(imsttfb_init);
16378c2ecf20Sopenharmony_cimodule_exit(imsttfb_exit);
16388c2ecf20Sopenharmony_ci
1639