cachepc-linux

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

imsttfb.c (44559B)


      1/*
      2 *  drivers/video/imsttfb.c -- frame buffer device for IMS TwinTurbo
      3 *
      4 *  This file is derived from the powermac console "imstt" driver:
      5 *  Copyright (C) 1997 Sigurdur Asgeirsson
      6 *  With additional hacking by Jeffrey Kuskin (jsk@mojave.stanford.edu)
      7 *  Modified by Danilo Beuche 1998
      8 *  Some register values added by Damien Doligez, INRIA Rocquencourt
      9 *  Various cleanups by Paul Mundt (lethal@chaoticdreams.org)
     10 *
     11 *  This file was written by Ryan Nielsen (ran@krazynet.com)
     12 *  Most of the frame buffer device stuff was copied from atyfb.c
     13 *
     14 *  This file is subject to the terms and conditions of the GNU General Public
     15 *  License. See the file COPYING in the main directory of this archive for
     16 *  more details.
     17 */
     18
     19#include <linux/module.h>
     20#include <linux/kernel.h>
     21#include <linux/errno.h>
     22#include <linux/string.h>
     23#include <linux/mm.h>
     24#include <linux/vmalloc.h>
     25#include <linux/delay.h>
     26#include <linux/interrupt.h>
     27#include <linux/fb.h>
     28#include <linux/init.h>
     29#include <linux/pci.h>
     30#include <asm/io.h>
     31#include <linux/uaccess.h>
     32
     33#if defined(CONFIG_PPC_PMAC)
     34#include <linux/nvram.h>
     35#include "macmodes.h"
     36#endif
     37
     38#ifndef __powerpc__
     39#define eieio()		/* Enforce In-order Execution of I/O */
     40#endif
     41
     42/* TwinTurbo (Cosmo) registers */
     43enum {
     44	S1SA	=  0, /* 0x00 */
     45	S2SA	=  1, /* 0x04 */
     46	SP	=  2, /* 0x08 */
     47	DSA	=  3, /* 0x0C */
     48	CNT	=  4, /* 0x10 */
     49	DP_OCTL	=  5, /* 0x14 */
     50	CLR	=  6, /* 0x18 */
     51	BI	=  8, /* 0x20 */
     52	MBC	=  9, /* 0x24 */
     53	BLTCTL	= 10, /* 0x28 */
     54
     55	/* Scan Timing Generator Registers */
     56	HES	= 12, /* 0x30 */
     57	HEB	= 13, /* 0x34 */
     58	HSB	= 14, /* 0x38 */
     59	HT	= 15, /* 0x3C */
     60	VES	= 16, /* 0x40 */
     61	VEB	= 17, /* 0x44 */
     62	VSB	= 18, /* 0x48 */
     63	VT	= 19, /* 0x4C */
     64	HCIV	= 20, /* 0x50 */
     65	VCIV	= 21, /* 0x54 */
     66	TCDR	= 22, /* 0x58 */
     67	VIL	= 23, /* 0x5C */
     68	STGCTL	= 24, /* 0x60 */
     69
     70	/* Screen Refresh Generator Registers */
     71	SSR	= 25, /* 0x64 */
     72	HRIR	= 26, /* 0x68 */
     73	SPR	= 27, /* 0x6C */
     74	CMR	= 28, /* 0x70 */
     75	SRGCTL	= 29, /* 0x74 */
     76
     77	/* RAM Refresh Generator Registers */
     78	RRCIV	= 30, /* 0x78 */
     79	RRSC	= 31, /* 0x7C */
     80	RRCR	= 34, /* 0x88 */
     81
     82	/* System Registers */
     83	GIOE	= 32, /* 0x80 */
     84	GIO	= 33, /* 0x84 */
     85	SCR	= 35, /* 0x8C */
     86	SSTATUS	= 36, /* 0x90 */
     87	PRC	= 37, /* 0x94 */
     88
     89#if 0	
     90	/* PCI Registers */
     91	DVID	= 0x00000000L,
     92	SC	= 0x00000004L,
     93	CCR	= 0x00000008L,
     94	OG	= 0x0000000CL,
     95	BARM	= 0x00000010L,
     96	BARER	= 0x00000030L,
     97#endif
     98};
     99
    100/* IBM 624 RAMDAC Direct Registers */
    101enum {
    102	PADDRW	= 0x00,
    103	PDATA	= 0x04,
    104	PPMASK	= 0x08,
    105	PADDRR	= 0x0c,
    106	PIDXLO	= 0x10,	
    107	PIDXHI	= 0x14,	
    108	PIDXDATA= 0x18,
    109	PIDXCTL	= 0x1c
    110};
    111
    112/* IBM 624 RAMDAC Indirect Registers */
    113enum {
    114	CLKCTL		= 0x02,	/* (0x01) Miscellaneous Clock Control */
    115	SYNCCTL		= 0x03,	/* (0x00) Sync Control */
    116	HSYNCPOS	= 0x04,	/* (0x00) Horizontal Sync Position */
    117	PWRMNGMT	= 0x05,	/* (0x00) Power Management */
    118	DACOP		= 0x06,	/* (0x02) DAC Operation */
    119	PALETCTL	= 0x07,	/* (0x00) Palette Control */
    120	SYSCLKCTL	= 0x08,	/* (0x01) System Clock Control */
    121	PIXFMT		= 0x0a,	/* () Pixel Format  [bpp >> 3 + 2] */
    122	BPP8		= 0x0b,	/* () 8 Bits/Pixel Control */
    123	BPP16		= 0x0c, /* () 16 Bits/Pixel Control  [bit 1=1 for 565] */
    124	BPP24		= 0x0d,	/* () 24 Bits/Pixel Control */
    125	BPP32		= 0x0e,	/* () 32 Bits/Pixel Control */
    126	PIXCTL1		= 0x10, /* (0x05) Pixel PLL Control 1 */
    127	PIXCTL2		= 0x11,	/* (0x00) Pixel PLL Control 2 */
    128	SYSCLKN		= 0x15,	/* () System Clock N (System PLL Reference Divider) */
    129	SYSCLKM		= 0x16,	/* () System Clock M (System PLL VCO Divider) */
    130	SYSCLKP		= 0x17,	/* () System Clock P */
    131	SYSCLKC		= 0x18,	/* () System Clock C */
    132	/*
    133	 * Dot clock rate is 20MHz * (m + 1) / ((n + 1) * (p ? 2 * p : 1)
    134	 * c is charge pump bias which depends on the VCO frequency  
    135	 */
    136	PIXM0		= 0x20,	/* () Pixel M 0 */
    137	PIXN0		= 0x21,	/* () Pixel N 0 */
    138	PIXP0		= 0x22,	/* () Pixel P 0 */
    139	PIXC0		= 0x23,	/* () Pixel C 0 */
    140	CURSCTL		= 0x30,	/* (0x00) Cursor Control */
    141	CURSXLO		= 0x31,	/* () Cursor X position, low 8 bits */
    142	CURSXHI		= 0x32,	/* () Cursor X position, high 8 bits */
    143	CURSYLO		= 0x33,	/* () Cursor Y position, low 8 bits */
    144	CURSYHI		= 0x34,	/* () Cursor Y position, high 8 bits */
    145	CURSHOTX	= 0x35,	/* () Cursor Hot Spot X */
    146	CURSHOTY	= 0x36,	/* () Cursor Hot Spot Y */
    147	CURSACCTL	= 0x37,	/* () Advanced Cursor Control Enable */
    148	CURSACATTR	= 0x38,	/* () Advanced Cursor Attribute */
    149	CURS1R		= 0x40,	/* () Cursor 1 Red */
    150	CURS1G		= 0x41,	/* () Cursor 1 Green */
    151	CURS1B		= 0x42,	/* () Cursor 1 Blue */
    152	CURS2R		= 0x43,	/* () Cursor 2 Red */
    153	CURS2G		= 0x44,	/* () Cursor 2 Green */
    154	CURS2B		= 0x45,	/* () Cursor 2 Blue */
    155	CURS3R		= 0x46,	/* () Cursor 3 Red */
    156	CURS3G		= 0x47,	/* () Cursor 3 Green */
    157	CURS3B		= 0x48,	/* () Cursor 3 Blue */
    158	BORDR		= 0x60,	/* () Border Color Red */
    159	BORDG		= 0x61,	/* () Border Color Green */
    160	BORDB		= 0x62,	/* () Border Color Blue */
    161	MISCTL1		= 0x70,	/* (0x00) Miscellaneous Control 1 */
    162	MISCTL2		= 0x71,	/* (0x00) Miscellaneous Control 2 */
    163	MISCTL3		= 0x72,	/* (0x00) Miscellaneous Control 3 */
    164	KEYCTL		= 0x78	/* (0x00) Key Control/DB Operation */
    165};
    166
    167/* TI TVP 3030 RAMDAC Direct Registers */
    168enum {
    169	TVPADDRW = 0x00,	/* 0  Palette/Cursor RAM Write Address/Index */
    170	TVPPDATA = 0x04,	/* 1  Palette Data RAM Data */
    171	TVPPMASK = 0x08,	/* 2  Pixel Read-Mask */
    172	TVPPADRR = 0x0c,	/* 3  Palette/Cursor RAM Read Address */
    173	TVPCADRW = 0x10,	/* 4  Cursor/Overscan Color Write Address */
    174	TVPCDATA = 0x14,	/* 5  Cursor/Overscan Color Data */
    175				/* 6  reserved */
    176	TVPCADRR = 0x1c,	/* 7  Cursor/Overscan Color Read Address */
    177				/* 8  reserved */
    178	TVPDCCTL = 0x24,	/* 9  Direct Cursor Control */
    179	TVPIDATA = 0x28,	/* 10 Index Data */
    180	TVPCRDAT = 0x2c,	/* 11 Cursor RAM Data */
    181	TVPCXPOL = 0x30,	/* 12 Cursor-Position X LSB */
    182	TVPCXPOH = 0x34,	/* 13 Cursor-Position X MSB */
    183	TVPCYPOL = 0x38,	/* 14 Cursor-Position Y LSB */
    184	TVPCYPOH = 0x3c,	/* 15 Cursor-Position Y MSB */
    185};
    186
    187/* TI TVP 3030 RAMDAC Indirect Registers */
    188enum {
    189	TVPIRREV = 0x01,	/* Silicon Revision [RO] */
    190	TVPIRICC = 0x06,	/* Indirect Cursor Control 	(0x00) */
    191	TVPIRBRC = 0x07,	/* Byte Router Control 	(0xe4) */
    192	TVPIRLAC = 0x0f,	/* Latch Control 		(0x06) */
    193	TVPIRTCC = 0x18,	/* True Color Control  	(0x80) */
    194	TVPIRMXC = 0x19,	/* Multiplex Control		(0x98) */
    195	TVPIRCLS = 0x1a,	/* Clock Selection		(0x07) */
    196	TVPIRPPG = 0x1c,	/* Palette Page		(0x00) */
    197	TVPIRGEC = 0x1d,	/* General Control 		(0x00) */
    198	TVPIRMIC = 0x1e,	/* Miscellaneous Control	(0x00) */
    199	TVPIRPLA = 0x2c,	/* PLL Address */
    200	TVPIRPPD = 0x2d,	/* Pixel Clock PLL Data */
    201	TVPIRMPD = 0x2e,	/* Memory Clock PLL Data */
    202	TVPIRLPD = 0x2f,	/* Loop Clock PLL Data */
    203	TVPIRCKL = 0x30,	/* Color-Key Overlay Low */
    204	TVPIRCKH = 0x31,	/* Color-Key Overlay High */
    205	TVPIRCRL = 0x32,	/* Color-Key Red Low */
    206	TVPIRCRH = 0x33,	/* Color-Key Red High */
    207	TVPIRCGL = 0x34,	/* Color-Key Green Low */
    208	TVPIRCGH = 0x35,	/* Color-Key Green High */
    209	TVPIRCBL = 0x36,	/* Color-Key Blue Low */
    210	TVPIRCBH = 0x37,	/* Color-Key Blue High */
    211	TVPIRCKC = 0x38,	/* Color-Key Control 		(0x00) */
    212	TVPIRMLC = 0x39,	/* MCLK/Loop Clock Control	(0x18) */
    213	TVPIRSEN = 0x3a,	/* Sense Test			(0x00) */
    214	TVPIRTMD = 0x3b,	/* Test Mode Data */
    215	TVPIRRML = 0x3c,	/* CRC Remainder LSB [RO] */
    216	TVPIRRMM = 0x3d,	/* CRC Remainder MSB [RO] */
    217	TVPIRRMS = 0x3e,	/* CRC  Bit Select [WO] */
    218	TVPIRDID = 0x3f,	/* Device ID [RO] 		(0x30) */
    219	TVPIRRES = 0xff		/* Software Reset [WO] */
    220};
    221
    222struct initvalues {
    223	__u8 addr, value;
    224};
    225
    226static struct initvalues ibm_initregs[] = {
    227	{ CLKCTL,	0x21 },
    228	{ SYNCCTL,	0x00 },
    229	{ HSYNCPOS,	0x00 },
    230	{ PWRMNGMT,	0x00 },
    231	{ DACOP,	0x02 },
    232	{ PALETCTL,	0x00 },
    233	{ SYSCLKCTL,	0x01 },
    234
    235	/*
    236	 * Note that colors in X are correct only if all video data is
    237	 * passed through the palette in the DAC.  That is, "indirect
    238	 * color" must be configured.  This is the case for the IBM DAC
    239	 * used in the 2MB and 4MB cards, at least.
    240	 */
    241	{ BPP8,		0x00 },
    242	{ BPP16,	0x01 },
    243	{ BPP24,	0x00 },
    244	{ BPP32,	0x00 },
    245
    246	{ PIXCTL1,	0x05 },
    247	{ PIXCTL2,	0x00 },
    248	{ SYSCLKN,	0x08 },
    249	{ SYSCLKM,	0x4f },
    250	{ SYSCLKP,	0x00 },
    251	{ SYSCLKC,	0x00 },
    252	{ CURSCTL,	0x00 },
    253	{ CURSACCTL,	0x01 },
    254	{ CURSACATTR,	0xa8 },
    255	{ CURS1R,	0xff },
    256	{ CURS1G,	0xff },
    257	{ CURS1B,	0xff },
    258	{ CURS2R,	0xff },
    259	{ CURS2G,	0xff },
    260	{ CURS2B,	0xff },
    261	{ CURS3R,	0xff },
    262	{ CURS3G,	0xff },
    263	{ CURS3B,	0xff },
    264	{ BORDR,	0xff },
    265	{ BORDG,	0xff },
    266	{ BORDB,	0xff },
    267	{ MISCTL1,	0x01 },
    268	{ MISCTL2,	0x45 },
    269	{ MISCTL3,	0x00 },
    270	{ KEYCTL,	0x00 }
    271};
    272
    273static struct initvalues tvp_initregs[] = {
    274	{ TVPIRICC,	0x00 },
    275	{ TVPIRBRC,	0xe4 },
    276	{ TVPIRLAC,	0x06 },
    277	{ TVPIRTCC,	0x80 },
    278	{ TVPIRMXC,	0x4d },
    279	{ TVPIRCLS,	0x05 },
    280	{ TVPIRPPG,	0x00 },
    281	{ TVPIRGEC,	0x00 },
    282	{ TVPIRMIC,	0x08 },
    283	{ TVPIRCKL,	0xff },
    284	{ TVPIRCKH,	0xff },
    285	{ TVPIRCRL,	0xff },
    286	{ TVPIRCRH,	0xff },
    287	{ TVPIRCGL,	0xff },
    288	{ TVPIRCGH,	0xff },
    289	{ TVPIRCBL,	0xff },
    290	{ TVPIRCBH,	0xff },
    291	{ TVPIRCKC,	0x00 },
    292	{ TVPIRPLA,	0x00 },
    293	{ TVPIRPPD,	0xc0 },
    294	{ TVPIRPPD,	0xd5 },
    295	{ TVPIRPPD,	0xea },
    296	{ TVPIRPLA,	0x00 },
    297	{ TVPIRMPD,	0xb9 },
    298	{ TVPIRMPD,	0x3a },
    299	{ TVPIRMPD,	0xb1 },
    300	{ TVPIRPLA,	0x00 },
    301	{ TVPIRLPD,	0xc1 },
    302	{ TVPIRLPD,	0x3d },
    303	{ TVPIRLPD,	0xf3 },
    304};
    305
    306struct imstt_regvals {
    307	__u32 pitch;
    308	__u16 hes, heb, hsb, ht, ves, veb, vsb, vt, vil;
    309	__u8 pclk_m, pclk_n, pclk_p;
    310	/* Values of the tvp which change depending on colormode x resolution */
    311	__u8 mlc[3];	/* Memory Loop Config 0x39 */
    312	__u8 lckl_p[3];	/* P value of LCKL PLL */
    313};
    314
    315struct imstt_par {
    316	struct imstt_regvals init;
    317	__u32 __iomem *dc_regs;
    318	unsigned long cmap_regs_phys;
    319	__u8 *cmap_regs;
    320	__u32 ramdac;
    321	__u32 palette[16];
    322};
    323 
    324enum {
    325	IBM = 0,
    326	TVP = 1
    327};
    328
    329#define INIT_BPP		8
    330#define INIT_XRES		640
    331#define INIT_YRES		480
    332
    333static int inverse = 0;
    334static char fontname[40] __initdata = { 0 };
    335#if defined(CONFIG_PPC_PMAC)
    336static signed char init_vmode = -1, init_cmode = -1;
    337#endif
    338
    339static struct imstt_regvals tvp_reg_init_2 = {
    340	512,
    341	0x0002, 0x0006, 0x0026, 0x0028, 0x0003, 0x0016, 0x0196, 0x0197, 0x0196,
    342	0xec, 0x2a, 0xf3,
    343	{ 0x3c, 0x3b, 0x39 }, { 0xf3, 0xf3, 0xf3 }
    344};
    345
    346static struct imstt_regvals tvp_reg_init_6 = {
    347	640,
    348	0x0004, 0x0009, 0x0031, 0x0036, 0x0003, 0x002a, 0x020a, 0x020d, 0x020a,
    349	0xef, 0x2e, 0xb2,
    350	{ 0x39, 0x39, 0x38 }, { 0xf3, 0xf3, 0xf3 }
    351};
    352
    353static struct imstt_regvals tvp_reg_init_12 = {
    354	800,
    355	0x0005, 0x000e, 0x0040, 0x0042, 0x0003, 0x018, 0x270, 0x271, 0x270,
    356	0xf6, 0x2e, 0xf2,
    357	{ 0x3a, 0x39, 0x38 }, { 0xf3, 0xf3, 0xf3 }
    358};
    359
    360static struct imstt_regvals tvp_reg_init_13 = {
    361	832,
    362	0x0004, 0x0011, 0x0045, 0x0048, 0x0003, 0x002a, 0x029a, 0x029b, 0x0000,
    363	0xfe, 0x3e, 0xf1,
    364	{ 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
    365};
    366
    367static struct imstt_regvals tvp_reg_init_17 = {
    368	1024,
    369	0x0006, 0x0210, 0x0250, 0x0053, 0x1003, 0x0021, 0x0321, 0x0324, 0x0000,
    370	0xfc, 0x3a, 0xf1,
    371	{ 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
    372};
    373
    374static struct imstt_regvals tvp_reg_init_18 = {
    375	1152,
    376  	0x0009, 0x0011, 0x059, 0x5b, 0x0003, 0x0031, 0x0397, 0x039a, 0x0000, 
    377	0xfd, 0x3a, 0xf1,
    378	{ 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
    379};
    380
    381static struct imstt_regvals tvp_reg_init_19 = {
    382	1280,
    383	0x0009, 0x0016, 0x0066, 0x0069, 0x0003, 0x0027, 0x03e7, 0x03e8, 0x03e7,
    384	0xf7, 0x36, 0xf0,
    385	{ 0x38, 0x38, 0x38 }, { 0xf3, 0xf2, 0xf1 }
    386};
    387
    388static struct imstt_regvals tvp_reg_init_20 = {
    389	1280,
    390	0x0009, 0x0018, 0x0068, 0x006a, 0x0003, 0x0029, 0x0429, 0x042a, 0x0000,
    391	0xf0, 0x2d, 0xf0,
    392	{ 0x38, 0x38, 0x38 }, { 0xf3, 0xf2, 0xf1 }
    393};
    394
    395/*
    396 * PCI driver prototypes
    397 */
    398static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
    399static void imsttfb_remove(struct pci_dev *pdev);
    400
    401/*
    402 * Register access
    403 */
    404static inline u32 read_reg_le32(volatile u32 __iomem *base, int regindex)
    405{
    406#ifdef __powerpc__
    407	return in_le32(base + regindex);
    408#else
    409	return readl(base + regindex);
    410#endif
    411}
    412
    413static inline void write_reg_le32(volatile u32 __iomem *base, int regindex, u32 val)
    414{
    415#ifdef __powerpc__
    416	out_le32(base + regindex, val);
    417#else
    418	writel(val, base + regindex);
    419#endif
    420}
    421
    422static __u32
    423getclkMHz(struct imstt_par *par)
    424{
    425	__u32 clk_m, clk_n, clk_p;
    426
    427	clk_m = par->init.pclk_m;
    428	clk_n = par->init.pclk_n;
    429	clk_p = par->init.pclk_p;
    430
    431	return 20 * (clk_m + 1) / ((clk_n + 1) * (clk_p ? 2 * clk_p : 1));
    432}
    433
    434static void
    435setclkMHz(struct imstt_par *par, __u32 MHz)
    436{
    437	__u32 clk_m, clk_n, x, stage, spilled;
    438
    439	clk_m = clk_n = 0;
    440	stage = spilled = 0;
    441	for (;;) {
    442		switch (stage) {
    443			case 0:
    444				clk_m++;
    445				break;
    446			case 1:
    447				clk_n++;
    448				break;
    449		}
    450		x = 20 * (clk_m + 1) / (clk_n + 1);
    451		if (x == MHz)
    452			break;
    453		if (x > MHz) {
    454			spilled = 1;
    455			stage = 1;
    456		} else if (spilled && x < MHz) {
    457			stage = 0;
    458		}
    459	}
    460
    461	par->init.pclk_m = clk_m;
    462	par->init.pclk_n = clk_n;
    463	par->init.pclk_p = 0;
    464}
    465
    466static struct imstt_regvals *
    467compute_imstt_regvals_ibm(struct imstt_par *par, int xres, int yres)
    468{
    469	struct imstt_regvals *init = &par->init;
    470	__u32 MHz, hes, heb, veb, htp, vtp;
    471
    472	switch (xres) {
    473		case 640:
    474			hes = 0x0008; heb = 0x0012; veb = 0x002a; htp = 10; vtp = 2;
    475			MHz = 30 /* .25 */ ;
    476			break;
    477		case 832:
    478			hes = 0x0005; heb = 0x0020; veb = 0x0028; htp = 8; vtp = 3;
    479			MHz = 57 /* .27_ */ ;
    480			break;
    481		case 1024:
    482			hes = 0x000a; heb = 0x001c; veb = 0x0020; htp = 8; vtp = 3;
    483			MHz = 80;
    484			break;
    485		case 1152:
    486			hes = 0x0012; heb = 0x0022; veb = 0x0031; htp = 4; vtp = 3;
    487			MHz = 101 /* .6_ */ ;
    488			break;
    489		case 1280:
    490			hes = 0x0012; heb = 0x002f; veb = 0x0029; htp = 4; vtp = 1;
    491			MHz = yres == 960 ? 126 : 135;
    492			break;
    493		case 1600:
    494			hes = 0x0018; heb = 0x0040; veb = 0x002a; htp = 4; vtp = 3;
    495			MHz = 200;
    496			break;
    497		default:
    498			return NULL;
    499	}
    500
    501	setclkMHz(par, MHz);
    502
    503	init->hes = hes;
    504	init->heb = heb;
    505	init->hsb = init->heb + (xres >> 3);
    506	init->ht = init->hsb + htp;
    507	init->ves = 0x0003;
    508	init->veb = veb;
    509	init->vsb = init->veb + yres;
    510	init->vt = init->vsb + vtp;
    511	init->vil = init->vsb;
    512
    513	init->pitch = xres;
    514	return init;
    515}
    516
    517static struct imstt_regvals *
    518compute_imstt_regvals_tvp(struct imstt_par *par, int xres, int yres)
    519{
    520	struct imstt_regvals *init;
    521
    522	switch (xres) {
    523		case 512:
    524			init = &tvp_reg_init_2;
    525			break;
    526		case 640:
    527			init = &tvp_reg_init_6;
    528			break;
    529		case 800:
    530			init = &tvp_reg_init_12;
    531			break;
    532		case 832:
    533			init = &tvp_reg_init_13;
    534			break;
    535		case 1024:
    536			init = &tvp_reg_init_17;
    537			break;
    538		case 1152:
    539			init = &tvp_reg_init_18;
    540			break;
    541		case 1280:
    542			init = yres == 960 ? &tvp_reg_init_19 : &tvp_reg_init_20;
    543			break;
    544		default:
    545			return NULL;
    546	}
    547	par->init = *init;
    548	return init;
    549}
    550
    551static struct imstt_regvals *
    552compute_imstt_regvals (struct imstt_par *par, u_int xres, u_int yres)
    553{
    554	if (par->ramdac == IBM)
    555		return compute_imstt_regvals_ibm(par, xres, yres);
    556	else
    557		return compute_imstt_regvals_tvp(par, xres, yres);
    558}
    559
    560static void
    561set_imstt_regvals_ibm (struct imstt_par *par, u_int bpp)
    562{
    563	struct imstt_regvals *init = &par->init;
    564	__u8 pformat = (bpp >> 3) + 2;
    565
    566	par->cmap_regs[PIDXHI] = 0;		eieio();
    567	par->cmap_regs[PIDXLO] = PIXM0;		eieio();
    568	par->cmap_regs[PIDXDATA] = init->pclk_m;eieio();
    569	par->cmap_regs[PIDXLO] = PIXN0;		eieio();
    570	par->cmap_regs[PIDXDATA] = init->pclk_n;eieio();
    571	par->cmap_regs[PIDXLO] = PIXP0;		eieio();
    572	par->cmap_regs[PIDXDATA] = init->pclk_p;eieio();
    573	par->cmap_regs[PIDXLO] = PIXC0;		eieio();
    574	par->cmap_regs[PIDXDATA] = 0x02;	eieio();
    575
    576	par->cmap_regs[PIDXLO] = PIXFMT;	eieio();
    577	par->cmap_regs[PIDXDATA] = pformat;	eieio();
    578}
    579
    580static void
    581set_imstt_regvals_tvp (struct imstt_par *par, u_int bpp)
    582{
    583	struct imstt_regvals *init = &par->init;
    584	__u8 tcc, mxc, lckl_n, mic;
    585	__u8 mlc, lckl_p;
    586
    587	switch (bpp) {
    588		default:
    589		case 8:
    590			tcc = 0x80;
    591			mxc = 0x4d;
    592			lckl_n = 0xc1;
    593			mlc = init->mlc[0];
    594			lckl_p = init->lckl_p[0];
    595			break;
    596		case 16:
    597			tcc = 0x44;
    598			mxc = 0x55;
    599			lckl_n = 0xe1;
    600			mlc = init->mlc[1];
    601			lckl_p = init->lckl_p[1];
    602			break;
    603		case 24:
    604			tcc = 0x5e;
    605			mxc = 0x5d;
    606			lckl_n = 0xf1;
    607			mlc = init->mlc[2];
    608			lckl_p = init->lckl_p[2];
    609			break;
    610		case 32:
    611			tcc = 0x46;
    612			mxc = 0x5d;
    613			lckl_n = 0xf1;
    614			mlc = init->mlc[2];
    615			lckl_p = init->lckl_p[2];
    616			break;
    617	}
    618	mic = 0x08;
    619
    620	par->cmap_regs[TVPADDRW] = TVPIRPLA;		eieio();
    621	par->cmap_regs[TVPIDATA] = 0x00;		eieio();
    622	par->cmap_regs[TVPADDRW] = TVPIRPPD;		eieio();
    623	par->cmap_regs[TVPIDATA] = init->pclk_m;	eieio();
    624	par->cmap_regs[TVPADDRW] = TVPIRPPD;		eieio();
    625	par->cmap_regs[TVPIDATA] = init->pclk_n;	eieio();
    626	par->cmap_regs[TVPADDRW] = TVPIRPPD;		eieio();
    627	par->cmap_regs[TVPIDATA] = init->pclk_p;	eieio();
    628
    629	par->cmap_regs[TVPADDRW] = TVPIRTCC;		eieio();
    630	par->cmap_regs[TVPIDATA] = tcc;			eieio();
    631	par->cmap_regs[TVPADDRW] = TVPIRMXC;		eieio();
    632	par->cmap_regs[TVPIDATA] = mxc;			eieio();
    633	par->cmap_regs[TVPADDRW] = TVPIRMIC;		eieio();
    634	par->cmap_regs[TVPIDATA] = mic;			eieio();
    635
    636	par->cmap_regs[TVPADDRW] = TVPIRPLA;		eieio();
    637	par->cmap_regs[TVPIDATA] = 0x00;		eieio();
    638	par->cmap_regs[TVPADDRW] = TVPIRLPD;		eieio();
    639	par->cmap_regs[TVPIDATA] = lckl_n;		eieio();
    640
    641	par->cmap_regs[TVPADDRW] = TVPIRPLA;		eieio();
    642	par->cmap_regs[TVPIDATA] = 0x15;		eieio();
    643	par->cmap_regs[TVPADDRW] = TVPIRMLC;		eieio();
    644	par->cmap_regs[TVPIDATA] = mlc;			eieio();
    645
    646	par->cmap_regs[TVPADDRW] = TVPIRPLA;		eieio();
    647	par->cmap_regs[TVPIDATA] = 0x2a;		eieio();
    648	par->cmap_regs[TVPADDRW] = TVPIRLPD;		eieio();
    649	par->cmap_regs[TVPIDATA] = lckl_p;		eieio();
    650}
    651
    652static void
    653set_imstt_regvals (struct fb_info *info, u_int bpp)
    654{
    655	struct imstt_par *par = info->par;
    656	struct imstt_regvals *init = &par->init;
    657	__u32 ctl, pitch, byteswap, scr;
    658
    659	if (par->ramdac == IBM)
    660		set_imstt_regvals_ibm(par, bpp);
    661	else
    662		set_imstt_regvals_tvp(par, bpp);
    663
    664  /*
    665   * From what I (jsk) can gather poking around with MacsBug,
    666   * bits 8 and 9 in the SCR register control endianness
    667   * correction (byte swapping).  These bits must be set according
    668   * to the color depth as follows:
    669   *     Color depth    Bit 9   Bit 8
    670   *     ==========     =====   =====
    671   *        8bpp          0       0
    672   *       16bpp          0       1
    673   *       32bpp          1       1
    674   */
    675	switch (bpp) {
    676		default:
    677		case 8:
    678			ctl = 0x17b1;
    679			pitch = init->pitch >> 2;
    680			byteswap = 0x000;
    681			break;
    682		case 16:
    683			ctl = 0x17b3;
    684			pitch = init->pitch >> 1;
    685			byteswap = 0x100;
    686			break;
    687		case 24:
    688			ctl = 0x17b9;
    689			pitch = init->pitch - (init->pitch >> 2);
    690			byteswap = 0x200;
    691			break;
    692		case 32:
    693			ctl = 0x17b5;
    694			pitch = init->pitch;
    695			byteswap = 0x300;
    696			break;
    697	}
    698	if (par->ramdac == TVP)
    699		ctl -= 0x30;
    700
    701	write_reg_le32(par->dc_regs, HES, init->hes);
    702	write_reg_le32(par->dc_regs, HEB, init->heb);
    703	write_reg_le32(par->dc_regs, HSB, init->hsb);
    704	write_reg_le32(par->dc_regs, HT, init->ht);
    705	write_reg_le32(par->dc_regs, VES, init->ves);
    706	write_reg_le32(par->dc_regs, VEB, init->veb);
    707	write_reg_le32(par->dc_regs, VSB, init->vsb);
    708	write_reg_le32(par->dc_regs, VT, init->vt);
    709	write_reg_le32(par->dc_regs, VIL, init->vil);
    710	write_reg_le32(par->dc_regs, HCIV, 1);
    711	write_reg_le32(par->dc_regs, VCIV, 1);
    712	write_reg_le32(par->dc_regs, TCDR, 4);
    713	write_reg_le32(par->dc_regs, RRCIV, 1);
    714	write_reg_le32(par->dc_regs, RRSC, 0x980);
    715	write_reg_le32(par->dc_regs, RRCR, 0x11);
    716
    717	if (par->ramdac == IBM) {
    718		write_reg_le32(par->dc_regs, HRIR, 0x0100);
    719		write_reg_le32(par->dc_regs, CMR, 0x00ff);
    720		write_reg_le32(par->dc_regs, SRGCTL, 0x0073);
    721	} else {
    722		write_reg_le32(par->dc_regs, HRIR, 0x0200);
    723		write_reg_le32(par->dc_regs, CMR, 0x01ff);
    724		write_reg_le32(par->dc_regs, SRGCTL, 0x0003);
    725	}
    726
    727	switch (info->fix.smem_len) {
    728		case 0x200000:
    729			scr = 0x059d | byteswap;
    730			break;
    731		/* case 0x400000:
    732		   case 0x800000: */
    733		default:
    734			pitch >>= 1;
    735			scr = 0x150dd | byteswap;
    736			break;
    737	}
    738
    739	write_reg_le32(par->dc_regs, SCR, scr);
    740	write_reg_le32(par->dc_regs, SPR, pitch);
    741	write_reg_le32(par->dc_regs, STGCTL, ctl);
    742}
    743
    744static inline void
    745set_offset (struct fb_var_screeninfo *var, struct fb_info *info)
    746{
    747	struct imstt_par *par = info->par;
    748	__u32 off = var->yoffset * (info->fix.line_length >> 3)
    749		    + ((var->xoffset * (info->var.bits_per_pixel >> 3)) >> 3);
    750	write_reg_le32(par->dc_regs, SSR, off);
    751}
    752
    753static inline void
    754set_555 (struct imstt_par *par)
    755{
    756	if (par->ramdac == IBM) {
    757		par->cmap_regs[PIDXHI] = 0;		eieio();
    758		par->cmap_regs[PIDXLO] = BPP16;		eieio();
    759		par->cmap_regs[PIDXDATA] = 0x01;	eieio();
    760	} else {
    761		par->cmap_regs[TVPADDRW] = TVPIRTCC;	eieio();
    762		par->cmap_regs[TVPIDATA] = 0x44;	eieio();
    763	}
    764}
    765
    766static inline void
    767set_565 (struct imstt_par *par)
    768{
    769	if (par->ramdac == IBM) {
    770		par->cmap_regs[PIDXHI] = 0;		eieio();
    771		par->cmap_regs[PIDXLO] = BPP16;		eieio();
    772		par->cmap_regs[PIDXDATA] = 0x03;	eieio();
    773	} else {
    774		par->cmap_regs[TVPADDRW] = TVPIRTCC;	eieio();
    775		par->cmap_regs[TVPIDATA] = 0x45;	eieio();
    776	}
    777}
    778
    779static int
    780imsttfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
    781{
    782	if ((var->bits_per_pixel != 8 && var->bits_per_pixel != 16
    783	    && var->bits_per_pixel != 24 && var->bits_per_pixel != 32)
    784	    || var->xres_virtual < var->xres || var->yres_virtual < var->yres
    785	    || var->nonstd
    786	    || (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
    787		return -EINVAL;
    788
    789	if ((var->xres * var->yres) * (var->bits_per_pixel >> 3) > info->fix.smem_len
    790	    || (var->xres_virtual * var->yres_virtual) * (var->bits_per_pixel >> 3) > info->fix.smem_len)
    791		return -EINVAL;
    792
    793	switch (var->bits_per_pixel) {
    794		case 8:
    795			var->red.offset = 0;
    796			var->red.length = 8;
    797			var->green.offset = 0;
    798			var->green.length = 8;
    799			var->blue.offset = 0;
    800			var->blue.length = 8;
    801			var->transp.offset = 0;
    802			var->transp.length = 0;
    803			break;
    804		case 16:	/* RGB 555 or 565 */
    805			if (var->green.length != 6)
    806				var->red.offset = 10;
    807			var->red.length = 5;
    808			var->green.offset = 5;
    809			if (var->green.length != 6)
    810				var->green.length = 5;
    811			var->blue.offset = 0;
    812			var->blue.length = 5;
    813			var->transp.offset = 0;
    814			var->transp.length = 0;
    815			break;
    816		case 24:	/* RGB 888 */
    817			var->red.offset = 16;
    818			var->red.length = 8;
    819			var->green.offset = 8;
    820			var->green.length = 8;
    821			var->blue.offset = 0;
    822			var->blue.length = 8;
    823			var->transp.offset = 0;
    824			var->transp.length = 0;
    825			break;
    826		case 32:	/* RGBA 8888 */
    827			var->red.offset = 16;
    828			var->red.length = 8;
    829			var->green.offset = 8;
    830			var->green.length = 8;
    831			var->blue.offset = 0;
    832			var->blue.length = 8;
    833			var->transp.offset = 24;
    834			var->transp.length = 8;
    835			break;
    836	}
    837
    838	if (var->yres == var->yres_virtual) {
    839		__u32 vram = (info->fix.smem_len - (PAGE_SIZE << 2));
    840		var->yres_virtual = ((vram << 3) / var->bits_per_pixel) / var->xres_virtual;
    841		if (var->yres_virtual < var->yres)
    842			var->yres_virtual = var->yres;
    843	}
    844
    845	var->red.msb_right = 0;
    846	var->green.msb_right = 0;
    847	var->blue.msb_right = 0;
    848	var->transp.msb_right = 0;
    849	var->height = -1;
    850	var->width = -1;
    851	var->vmode = FB_VMODE_NONINTERLACED;
    852	var->left_margin = var->right_margin = 16;
    853	var->upper_margin = var->lower_margin = 16;
    854	var->hsync_len = var->vsync_len = 8;
    855	return 0;
    856}
    857
    858static int
    859imsttfb_set_par(struct fb_info *info) 
    860{
    861	struct imstt_par *par = info->par;
    862		
    863	if (!compute_imstt_regvals(par, info->var.xres, info->var.yres))
    864		return -EINVAL;
    865
    866	if (info->var.green.length == 6)
    867		set_565(par);
    868	else
    869		set_555(par);
    870	set_imstt_regvals(info, info->var.bits_per_pixel);
    871	info->var.pixclock = 1000000 / getclkMHz(par);
    872	return 0;
    873}
    874
    875static int
    876imsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue,
    877		   u_int transp, struct fb_info *info)
    878{
    879	struct imstt_par *par = info->par;
    880	u_int bpp = info->var.bits_per_pixel;
    881
    882	if (regno > 255)
    883		return 1;
    884
    885	red >>= 8;
    886	green >>= 8;
    887	blue >>= 8;
    888
    889	/* PADDRW/PDATA are the same as TVPPADDRW/TVPPDATA */
    890	if (0 && bpp == 16)	/* screws up X */
    891		par->cmap_regs[PADDRW] = regno << 3;
    892	else
    893		par->cmap_regs[PADDRW] = regno;
    894	eieio();
    895
    896	par->cmap_regs[PDATA] = red;	eieio();
    897	par->cmap_regs[PDATA] = green;	eieio();
    898	par->cmap_regs[PDATA] = blue;	eieio();
    899
    900	if (regno < 16)
    901		switch (bpp) {
    902			case 16:
    903				par->palette[regno] =
    904					(regno << (info->var.green.length ==
    905					5 ? 10 : 11)) | (regno << 5) | regno;
    906				break;
    907			case 24:
    908				par->palette[regno] =
    909					(regno << 16) | (regno << 8) | regno;
    910				break;
    911			case 32: {
    912				int i = (regno << 8) | regno;
    913				par->palette[regno] = (i << 16) |i;
    914				break;
    915			}
    916		}
    917	return 0;
    918}
    919
    920static int
    921imsttfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
    922{
    923	if (var->xoffset + info->var.xres > info->var.xres_virtual
    924	    || var->yoffset + info->var.yres > info->var.yres_virtual)
    925		return -EINVAL;
    926
    927	info->var.xoffset = var->xoffset;
    928	info->var.yoffset = var->yoffset;
    929	set_offset(var, info);
    930	return 0;
    931}
    932
    933static int 
    934imsttfb_blank(int blank, struct fb_info *info)
    935{
    936	struct imstt_par *par = info->par;
    937	__u32 ctrl;
    938
    939	ctrl = read_reg_le32(par->dc_regs, STGCTL);
    940	if (blank > 0) {
    941		switch (blank) {
    942		case FB_BLANK_NORMAL:
    943		case FB_BLANK_POWERDOWN:
    944			ctrl &= ~0x00000380;
    945			if (par->ramdac == IBM) {
    946				par->cmap_regs[PIDXHI] = 0;		eieio();
    947				par->cmap_regs[PIDXLO] = MISCTL2;	eieio();
    948				par->cmap_regs[PIDXDATA] = 0x55;	eieio();
    949				par->cmap_regs[PIDXLO] = MISCTL1;	eieio();
    950				par->cmap_regs[PIDXDATA] = 0x11;	eieio();
    951				par->cmap_regs[PIDXLO] = SYNCCTL;	eieio();
    952				par->cmap_regs[PIDXDATA] = 0x0f;	eieio();
    953				par->cmap_regs[PIDXLO] = PWRMNGMT;	eieio();
    954				par->cmap_regs[PIDXDATA] = 0x1f;	eieio();
    955				par->cmap_regs[PIDXLO] = CLKCTL;	eieio();
    956				par->cmap_regs[PIDXDATA] = 0xc0;
    957			}
    958			break;
    959		case FB_BLANK_VSYNC_SUSPEND:
    960			ctrl &= ~0x00000020;
    961			break;
    962		case FB_BLANK_HSYNC_SUSPEND:
    963			ctrl &= ~0x00000010;
    964			break;
    965		}
    966	} else {
    967		if (par->ramdac == IBM) {
    968			ctrl |= 0x000017b0;
    969			par->cmap_regs[PIDXHI] = 0;		eieio();
    970			par->cmap_regs[PIDXLO] = CLKCTL;	eieio();
    971			par->cmap_regs[PIDXDATA] = 0x01;	eieio();
    972			par->cmap_regs[PIDXLO] = PWRMNGMT;	eieio();
    973			par->cmap_regs[PIDXDATA] = 0x00;	eieio();
    974			par->cmap_regs[PIDXLO] = SYNCCTL;	eieio();
    975			par->cmap_regs[PIDXDATA] = 0x00;	eieio();
    976			par->cmap_regs[PIDXLO] = MISCTL1;	eieio();
    977			par->cmap_regs[PIDXDATA] = 0x01;	eieio();
    978			par->cmap_regs[PIDXLO] = MISCTL2;	eieio();
    979			par->cmap_regs[PIDXDATA] = 0x45;	eieio();
    980		} else
    981			ctrl |= 0x00001780;
    982	}
    983	write_reg_le32(par->dc_regs, STGCTL, ctrl);
    984	return 0;
    985}
    986
    987static void
    988imsttfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
    989{ 
    990	struct imstt_par *par = info->par;
    991	__u32 Bpp, line_pitch, bgc, dx, dy, width, height;
    992
    993	bgc = rect->color;
    994	bgc |= (bgc << 8);
    995	bgc |= (bgc << 16);
    996
    997	Bpp = info->var.bits_per_pixel >> 3,
    998	line_pitch = info->fix.line_length;
    999
   1000	dy = rect->dy * line_pitch;
   1001	dx = rect->dx * Bpp;
   1002	height = rect->height;
   1003	height--;
   1004	width = rect->width * Bpp;
   1005	width--;
   1006
   1007	if (rect->rop == ROP_COPY) {
   1008		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
   1009		write_reg_le32(par->dc_regs, DSA, dy + dx);
   1010		write_reg_le32(par->dc_regs, CNT, (height << 16) | width);
   1011		write_reg_le32(par->dc_regs, DP_OCTL, line_pitch);
   1012		write_reg_le32(par->dc_regs, BI, 0xffffffff);
   1013		write_reg_le32(par->dc_regs, MBC, 0xffffffff);
   1014		write_reg_le32(par->dc_regs, CLR, bgc);
   1015		write_reg_le32(par->dc_regs, BLTCTL, 0x840); /* 0x200000 */
   1016		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
   1017		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x40);
   1018	} else {
   1019		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
   1020		write_reg_le32(par->dc_regs, DSA, dy + dx);
   1021		write_reg_le32(par->dc_regs, S1SA, dy + dx);
   1022		write_reg_le32(par->dc_regs, CNT, (height << 16) | width);
   1023		write_reg_le32(par->dc_regs, DP_OCTL, line_pitch);
   1024		write_reg_le32(par->dc_regs, SP, line_pitch);
   1025		write_reg_le32(par->dc_regs, BLTCTL, 0x40005);
   1026		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
   1027		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x40);
   1028	}
   1029}
   1030
   1031static void
   1032imsttfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
   1033{
   1034	struct imstt_par *par = info->par;
   1035	__u32 Bpp, line_pitch, fb_offset_old, fb_offset_new, sp, dp_octl;
   1036 	__u32 cnt, bltctl, sx, sy, dx, dy, height, width;
   1037
   1038	Bpp = info->var.bits_per_pixel >> 3,
   1039
   1040	sx = area->sx * Bpp;
   1041	sy = area->sy;
   1042	dx = area->dx * Bpp;
   1043	dy = area->dy;
   1044	height = area->height;
   1045	height--;
   1046	width = area->width * Bpp;
   1047	width--;
   1048
   1049	line_pitch = info->fix.line_length;
   1050	bltctl = 0x05;
   1051	sp = line_pitch << 16;
   1052	cnt = height << 16;
   1053
   1054	if (sy < dy) {
   1055		sy += height;
   1056		dy += height;
   1057		sp |= -(line_pitch) & 0xffff;
   1058		dp_octl = -(line_pitch) & 0xffff;
   1059	} else {
   1060		sp |= line_pitch;
   1061		dp_octl = line_pitch;
   1062	}
   1063	if (sx < dx) {
   1064		sx += width;
   1065		dx += width;
   1066		bltctl |= 0x80;
   1067		cnt |= -(width) & 0xffff;
   1068	} else {
   1069		cnt |= width;
   1070	}
   1071	fb_offset_old = sy * line_pitch + sx;
   1072	fb_offset_new = dy * line_pitch + dx;
   1073
   1074	while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
   1075	write_reg_le32(par->dc_regs, S1SA, fb_offset_old);
   1076	write_reg_le32(par->dc_regs, SP, sp);
   1077	write_reg_le32(par->dc_regs, DSA, fb_offset_new);
   1078	write_reg_le32(par->dc_regs, CNT, cnt);
   1079	write_reg_le32(par->dc_regs, DP_OCTL, dp_octl);
   1080	write_reg_le32(par->dc_regs, BLTCTL, bltctl);
   1081	while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
   1082	while(read_reg_le32(par->dc_regs, SSTATUS) & 0x40);
   1083}
   1084
   1085#if 0
   1086static int
   1087imsttfb_load_cursor_image(struct imstt_par *par, int width, int height, __u8 fgc)
   1088{
   1089	u_int x, y;
   1090
   1091	if (width > 32 || height > 32)
   1092		return -EINVAL;
   1093
   1094	if (par->ramdac == IBM) {
   1095		par->cmap_regs[PIDXHI] = 1;	eieio();
   1096		for (x = 0; x < 0x100; x++) {
   1097			par->cmap_regs[PIDXLO] = x;		eieio();
   1098			par->cmap_regs[PIDXDATA] = 0x00;	eieio();
   1099		}
   1100		par->cmap_regs[PIDXHI] = 1;	eieio();
   1101		for (y = 0; y < height; y++)
   1102			for (x = 0; x < width >> 2; x++) {
   1103				par->cmap_regs[PIDXLO] = x + y * 8;	eieio();
   1104				par->cmap_regs[PIDXDATA] = 0xff;	eieio();
   1105			}
   1106		par->cmap_regs[PIDXHI] = 0;		eieio();
   1107		par->cmap_regs[PIDXLO] = CURS1R;	eieio();
   1108		par->cmap_regs[PIDXDATA] = fgc;		eieio();
   1109		par->cmap_regs[PIDXLO] = CURS1G;	eieio();
   1110		par->cmap_regs[PIDXDATA] = fgc;		eieio();
   1111		par->cmap_regs[PIDXLO] = CURS1B;	eieio();
   1112		par->cmap_regs[PIDXDATA] = fgc;		eieio();
   1113		par->cmap_regs[PIDXLO] = CURS2R;	eieio();
   1114		par->cmap_regs[PIDXDATA] = fgc;		eieio();
   1115		par->cmap_regs[PIDXLO] = CURS2G;	eieio();
   1116		par->cmap_regs[PIDXDATA] = fgc;		eieio();
   1117		par->cmap_regs[PIDXLO] = CURS2B;	eieio();
   1118		par->cmap_regs[PIDXDATA] = fgc;		eieio();
   1119		par->cmap_regs[PIDXLO] = CURS3R;	eieio();
   1120		par->cmap_regs[PIDXDATA] = fgc;		eieio();
   1121		par->cmap_regs[PIDXLO] = CURS3G;	eieio();
   1122		par->cmap_regs[PIDXDATA] = fgc;		eieio();
   1123		par->cmap_regs[PIDXLO] = CURS3B;	eieio();
   1124		par->cmap_regs[PIDXDATA] = fgc;		eieio();
   1125	} else {
   1126		par->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
   1127		par->cmap_regs[TVPIDATA] &= 0x03;	eieio();
   1128		par->cmap_regs[TVPADDRW] = 0;		eieio();
   1129		for (x = 0; x < 0x200; x++) {
   1130			par->cmap_regs[TVPCRDAT] = 0x00;	eieio();
   1131		}
   1132		for (x = 0; x < 0x200; x++) {
   1133			par->cmap_regs[TVPCRDAT] = 0xff;	eieio();
   1134		}
   1135		par->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
   1136		par->cmap_regs[TVPIDATA] &= 0x03;	eieio();
   1137		for (y = 0; y < height; y++)
   1138			for (x = 0; x < width >> 3; x++) {
   1139				par->cmap_regs[TVPADDRW] = x + y * 8;	eieio();
   1140				par->cmap_regs[TVPCRDAT] = 0xff;		eieio();
   1141			}
   1142		par->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
   1143		par->cmap_regs[TVPIDATA] |= 0x08;	eieio();
   1144		for (y = 0; y < height; y++)
   1145			for (x = 0; x < width >> 3; x++) {
   1146				par->cmap_regs[TVPADDRW] = x + y * 8;	eieio();
   1147				par->cmap_regs[TVPCRDAT] = 0xff;		eieio();
   1148			}
   1149		par->cmap_regs[TVPCADRW] = 0x00;	eieio();
   1150		for (x = 0; x < 12; x++) {
   1151			par->cmap_regs[TVPCDATA] = fgc;
   1152			eieio();
   1153		}
   1154	}
   1155	return 1;
   1156}
   1157
   1158static void
   1159imstt_set_cursor(struct imstt_par *par, struct fb_image *d, int on)
   1160{
   1161	if (par->ramdac == IBM) {
   1162		par->cmap_regs[PIDXHI] = 0;	eieio();
   1163		if (!on) {
   1164			par->cmap_regs[PIDXLO] = CURSCTL;	eieio();
   1165			par->cmap_regs[PIDXDATA] = 0x00;	eieio();
   1166		} else {
   1167			par->cmap_regs[PIDXLO] = CURSXHI;	eieio();
   1168			par->cmap_regs[PIDXDATA] = d->dx >> 8;	eieio();
   1169			par->cmap_regs[PIDXLO] = CURSXLO;	eieio();
   1170			par->cmap_regs[PIDXDATA] = d->dx & 0xff;eieio();
   1171			par->cmap_regs[PIDXLO] = CURSYHI;	eieio();
   1172			par->cmap_regs[PIDXDATA] = d->dy >> 8;	eieio();
   1173			par->cmap_regs[PIDXLO] = CURSYLO;	eieio();
   1174			par->cmap_regs[PIDXDATA] = d->dy & 0xff;eieio();
   1175			par->cmap_regs[PIDXLO] = CURSCTL;	eieio();
   1176			par->cmap_regs[PIDXDATA] = 0x02;	eieio();
   1177		}
   1178	} else {
   1179		if (!on) {
   1180			par->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
   1181			par->cmap_regs[TVPIDATA] = 0x00;	eieio();
   1182		} else {
   1183			__u16 x = d->dx + 0x40, y = d->dy + 0x40;
   1184
   1185			par->cmap_regs[TVPCXPOH] = x >> 8;	eieio();
   1186			par->cmap_regs[TVPCXPOL] = x & 0xff;	eieio();
   1187			par->cmap_regs[TVPCYPOH] = y >> 8;	eieio();
   1188			par->cmap_regs[TVPCYPOL] = y & 0xff;	eieio();
   1189			par->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
   1190			par->cmap_regs[TVPIDATA] = 0x02;	eieio();
   1191		}
   1192	}
   1193}
   1194
   1195static int 
   1196imsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
   1197{
   1198	struct imstt_par *par = info->par;
   1199        u32 flags = cursor->set, fg, bg, xx, yy;
   1200
   1201	if (cursor->dest == NULL && cursor->rop == ROP_XOR)
   1202		return 1;
   1203	
   1204	imstt_set_cursor(info, cursor, 0);
   1205
   1206	if (flags & FB_CUR_SETPOS) {
   1207		xx = cursor->image.dx - info->var.xoffset;
   1208		yy = cursor->image.dy - info->var.yoffset;
   1209	}
   1210
   1211	if (flags & FB_CUR_SETSIZE) {
   1212        }
   1213
   1214        if (flags & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP)) {
   1215                int fg_idx = cursor->image.fg_color;
   1216                int width = (cursor->image.width+7)/8;
   1217                u8 *dat = (u8 *) cursor->image.data;
   1218                u8 *dst = (u8 *) cursor->dest;
   1219                u8 *msk = (u8 *) cursor->mask;
   1220
   1221                switch (cursor->rop) {
   1222                case ROP_XOR:
   1223                        for (i = 0; i < cursor->image.height; i++) {
   1224                                for (j = 0; j < width; j++) {
   1225                                        d_idx = i * MAX_CURS/8  + j;
   1226                                        data[d_idx] =  byte_rev[dat[s_idx] ^
   1227                                                                dst[s_idx]];
   1228                                        mask[d_idx] = byte_rev[msk[s_idx]];
   1229                                        s_idx++;
   1230                                }
   1231                        }
   1232                        break;
   1233                case ROP_COPY:
   1234                default:
   1235                        for (i = 0; i < cursor->image.height; i++) {
   1236                                for (j = 0; j < width; j++) {
   1237                                        d_idx = i * MAX_CURS/8 + j;
   1238                                        data[d_idx] = byte_rev[dat[s_idx]];
   1239                                        mask[d_idx] = byte_rev[msk[s_idx]];
   1240                                        s_idx++;
   1241                                }
   1242			}
   1243			break;
   1244		}
   1245
   1246		fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
   1247                     ((info->cmap.green[fg_idx] & 0xf8) << 2) |
   1248                     ((info->cmap.blue[fg_idx] & 0xf8) >> 3) | 1 << 15;
   1249
   1250		imsttfb_load_cursor_image(par, xx, yy, fgc);
   1251	}
   1252	if (cursor->enable)
   1253		imstt_set_cursor(info, cursor, 1);
   1254	return 0;
   1255}
   1256#endif
   1257
   1258#define FBIMSTT_SETREG		0x545401
   1259#define FBIMSTT_GETREG		0x545402
   1260#define FBIMSTT_SETCMAPREG	0x545403
   1261#define FBIMSTT_GETCMAPREG	0x545404
   1262#define FBIMSTT_SETIDXREG	0x545405
   1263#define FBIMSTT_GETIDXREG	0x545406
   1264
   1265static int
   1266imsttfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
   1267{
   1268	struct imstt_par *par = info->par;
   1269	void __user *argp = (void __user *)arg;
   1270	__u32 reg[2];
   1271	__u8 idx[2];
   1272
   1273	switch (cmd) {
   1274		case FBIMSTT_SETREG:
   1275			if (copy_from_user(reg, argp, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
   1276				return -EFAULT;
   1277			write_reg_le32(par->dc_regs, reg[0], reg[1]);
   1278			return 0;
   1279		case FBIMSTT_GETREG:
   1280			if (copy_from_user(reg, argp, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
   1281				return -EFAULT;
   1282			reg[1] = read_reg_le32(par->dc_regs, reg[0]);
   1283			if (copy_to_user((void __user *)(arg + 4), &reg[1], 4))
   1284				return -EFAULT;
   1285			return 0;
   1286		case FBIMSTT_SETCMAPREG:
   1287			if (copy_from_user(reg, argp, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
   1288				return -EFAULT;
   1289			write_reg_le32(((u_int __iomem *)par->cmap_regs), reg[0], reg[1]);
   1290			return 0;
   1291		case FBIMSTT_GETCMAPREG:
   1292			if (copy_from_user(reg, argp, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
   1293				return -EFAULT;
   1294			reg[1] = read_reg_le32(((u_int __iomem *)par->cmap_regs), reg[0]);
   1295			if (copy_to_user((void __user *)(arg + 4), &reg[1], 4))
   1296				return -EFAULT;
   1297			return 0;
   1298		case FBIMSTT_SETIDXREG:
   1299			if (copy_from_user(idx, argp, 2))
   1300				return -EFAULT;
   1301			par->cmap_regs[PIDXHI] = 0;		eieio();
   1302			par->cmap_regs[PIDXLO] = idx[0];	eieio();
   1303			par->cmap_regs[PIDXDATA] = idx[1];	eieio();
   1304			return 0;
   1305		case FBIMSTT_GETIDXREG:
   1306			if (copy_from_user(idx, argp, 1))
   1307				return -EFAULT;
   1308			par->cmap_regs[PIDXHI] = 0;		eieio();
   1309			par->cmap_regs[PIDXLO] = idx[0];	eieio();
   1310			idx[1] = par->cmap_regs[PIDXDATA];
   1311			if (copy_to_user((void __user *)(arg + 1), &idx[1], 1))
   1312				return -EFAULT;
   1313			return 0;
   1314		default:
   1315			return -ENOIOCTLCMD;
   1316	}
   1317}
   1318
   1319static const struct pci_device_id imsttfb_pci_tbl[] = {
   1320	{ PCI_VENDOR_ID_IMS, PCI_DEVICE_ID_IMS_TT128,
   1321	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, IBM },
   1322	{ PCI_VENDOR_ID_IMS, PCI_DEVICE_ID_IMS_TT3D,
   1323	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, TVP },
   1324	{ 0, }
   1325};
   1326
   1327MODULE_DEVICE_TABLE(pci, imsttfb_pci_tbl);
   1328
   1329static struct pci_driver imsttfb_pci_driver = {
   1330	.name =		"imsttfb",
   1331	.id_table =	imsttfb_pci_tbl,
   1332	.probe =	imsttfb_probe,
   1333	.remove =	imsttfb_remove,
   1334};
   1335
   1336static const struct fb_ops imsttfb_ops = {
   1337	.owner 		= THIS_MODULE,
   1338	.fb_check_var	= imsttfb_check_var,
   1339	.fb_set_par 	= imsttfb_set_par,
   1340	.fb_setcolreg 	= imsttfb_setcolreg,
   1341	.fb_pan_display = imsttfb_pan_display,
   1342	.fb_blank 	= imsttfb_blank,
   1343	.fb_fillrect	= imsttfb_fillrect,
   1344	.fb_copyarea	= imsttfb_copyarea,
   1345	.fb_imageblit	= cfb_imageblit,
   1346	.fb_ioctl 	= imsttfb_ioctl,
   1347};
   1348
   1349static void init_imstt(struct fb_info *info)
   1350{
   1351	struct imstt_par *par = info->par;
   1352	__u32 i, tmp, *ip, *end;
   1353
   1354	tmp = read_reg_le32(par->dc_regs, PRC);
   1355	if (par->ramdac == IBM)
   1356		info->fix.smem_len = (tmp & 0x0004) ? 0x400000 : 0x200000;
   1357	else
   1358		info->fix.smem_len = 0x800000;
   1359
   1360	ip = (__u32 *)info->screen_base;
   1361	end = (__u32 *)(info->screen_base + info->fix.smem_len);
   1362	while (ip < end)
   1363		*ip++ = 0;
   1364
   1365	/* initialize the card */
   1366	tmp = read_reg_le32(par->dc_regs, STGCTL);
   1367	write_reg_le32(par->dc_regs, STGCTL, tmp & ~0x1);
   1368	write_reg_le32(par->dc_regs, SSR, 0);
   1369
   1370	/* set default values for DAC registers */
   1371	if (par->ramdac == IBM) {
   1372		par->cmap_regs[PPMASK] = 0xff;
   1373		eieio();
   1374		par->cmap_regs[PIDXHI] = 0;
   1375		eieio();
   1376		for (i = 0; i < ARRAY_SIZE(ibm_initregs); i++) {
   1377			par->cmap_regs[PIDXLO] = ibm_initregs[i].addr;
   1378			eieio();
   1379			par->cmap_regs[PIDXDATA] = ibm_initregs[i].value;
   1380			eieio();
   1381		}
   1382	} else {
   1383		for (i = 0; i < ARRAY_SIZE(tvp_initregs); i++) {
   1384			par->cmap_regs[TVPADDRW] = tvp_initregs[i].addr;
   1385			eieio();
   1386			par->cmap_regs[TVPIDATA] = tvp_initregs[i].value;
   1387			eieio();
   1388		}
   1389	}
   1390
   1391#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
   1392	if (IS_REACHABLE(CONFIG_NVRAM) && machine_is(powermac)) {
   1393		int vmode = init_vmode, cmode = init_cmode;
   1394
   1395		if (vmode == -1) {
   1396			vmode = nvram_read_byte(NV_VMODE);
   1397			if (vmode <= 0 || vmode > VMODE_MAX)
   1398				vmode = VMODE_640_480_67;
   1399		}
   1400		if (cmode == -1) {
   1401			cmode = nvram_read_byte(NV_CMODE);
   1402			if (cmode < CMODE_8 || cmode > CMODE_32)
   1403				cmode = CMODE_8;
   1404		}
   1405		if (mac_vmode_to_var(vmode, cmode, &info->var)) {
   1406			info->var.xres = info->var.xres_virtual = INIT_XRES;
   1407			info->var.yres = info->var.yres_virtual = INIT_YRES;
   1408			info->var.bits_per_pixel = INIT_BPP;
   1409		}
   1410	} else
   1411#endif
   1412	{
   1413		info->var.xres = info->var.xres_virtual = INIT_XRES;
   1414		info->var.yres = info->var.yres_virtual = INIT_YRES;
   1415		info->var.bits_per_pixel = INIT_BPP;
   1416	}
   1417
   1418	if ((info->var.xres * info->var.yres) * (info->var.bits_per_pixel >> 3) > info->fix.smem_len
   1419	    || !(compute_imstt_regvals(par, info->var.xres, info->var.yres))) {
   1420		printk("imsttfb: %ux%ux%u not supported\n", info->var.xres, info->var.yres, info->var.bits_per_pixel);
   1421		framebuffer_release(info);
   1422		return;
   1423	}
   1424
   1425	sprintf(info->fix.id, "IMS TT (%s)", par->ramdac == IBM ? "IBM" : "TVP");
   1426	info->fix.mmio_len = 0x1000;
   1427	info->fix.accel = FB_ACCEL_IMS_TWINTURBO;
   1428	info->fix.type = FB_TYPE_PACKED_PIXELS;
   1429	info->fix.visual = info->var.bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR
   1430							: FB_VISUAL_DIRECTCOLOR;
   1431	info->fix.line_length = info->var.xres * (info->var.bits_per_pixel >> 3);
   1432	info->fix.xpanstep = 8;
   1433	info->fix.ypanstep = 1;
   1434	info->fix.ywrapstep = 0;
   1435
   1436	info->var.accel_flags = FB_ACCELF_TEXT;
   1437
   1438//	if (par->ramdac == IBM)
   1439//		imstt_cursor_init(info);
   1440	if (info->var.green.length == 6)
   1441		set_565(par);
   1442	else
   1443		set_555(par);
   1444	set_imstt_regvals(info, info->var.bits_per_pixel);
   1445
   1446	info->var.pixclock = 1000000 / getclkMHz(par);
   1447
   1448	info->fbops = &imsttfb_ops;
   1449	info->flags = FBINFO_DEFAULT |
   1450                      FBINFO_HWACCEL_COPYAREA |
   1451	              FBINFO_HWACCEL_FILLRECT |
   1452	              FBINFO_HWACCEL_YPAN;
   1453
   1454	fb_alloc_cmap(&info->cmap, 0, 0);
   1455
   1456	if (register_framebuffer(info) < 0) {
   1457		framebuffer_release(info);
   1458		return;
   1459	}
   1460
   1461	tmp = (read_reg_le32(par->dc_regs, SSTATUS) & 0x0f00) >> 8;
   1462	fb_info(info, "%s frame buffer; %uMB vram; chip version %u\n",
   1463		info->fix.id, info->fix.smem_len >> 20, tmp);
   1464}
   1465
   1466static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
   1467{
   1468	unsigned long addr, size;
   1469	struct imstt_par *par;
   1470	struct fb_info *info;
   1471	struct device_node *dp;
   1472	int ret = -ENOMEM;
   1473	
   1474	dp = pci_device_to_OF_node(pdev);
   1475	if(dp)
   1476		printk(KERN_INFO "%s: OF name %pOFn\n",__func__, dp);
   1477	else if (IS_ENABLED(CONFIG_OF))
   1478		printk(KERN_ERR "imsttfb: no OF node for pci device\n");
   1479
   1480	info = framebuffer_alloc(sizeof(struct imstt_par), &pdev->dev);
   1481	if (!info)
   1482		return -ENOMEM;
   1483
   1484	par = info->par;
   1485
   1486	addr = pci_resource_start (pdev, 0);
   1487	size = pci_resource_len (pdev, 0);
   1488
   1489	if (!request_mem_region(addr, size, "imsttfb")) {
   1490		printk(KERN_ERR "imsttfb: Can't reserve memory region\n");
   1491		framebuffer_release(info);
   1492		return -ENODEV;
   1493	}
   1494
   1495	switch (pdev->device) {
   1496		case PCI_DEVICE_ID_IMS_TT128: /* IMS,tt128mbA */
   1497			par->ramdac = IBM;
   1498			if (of_node_name_eq(dp, "IMS,tt128mb8") ||
   1499			    of_node_name_eq(dp, "IMS,tt128mb8A"))
   1500				par->ramdac = TVP;
   1501			break;
   1502		case PCI_DEVICE_ID_IMS_TT3D:  /* IMS,tt3d */
   1503			par->ramdac = TVP;
   1504			break;
   1505		default:
   1506			printk(KERN_INFO "imsttfb: Device 0x%x unknown, "
   1507					 "contact maintainer.\n", pdev->device);
   1508			ret = -ENODEV;
   1509			goto error;
   1510	}
   1511
   1512	info->fix.smem_start = addr;
   1513	info->screen_base = (__u8 *)ioremap(addr, par->ramdac == IBM ?
   1514					    0x400000 : 0x800000);
   1515	if (!info->screen_base)
   1516		goto error;
   1517	info->fix.mmio_start = addr + 0x800000;
   1518	par->dc_regs = ioremap(addr + 0x800000, 0x1000);
   1519	if (!par->dc_regs)
   1520		goto error;
   1521	par->cmap_regs_phys = addr + 0x840000;
   1522	par->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000);
   1523	if (!par->cmap_regs)
   1524		goto error;
   1525	info->pseudo_palette = par->palette;
   1526	init_imstt(info);
   1527
   1528	pci_set_drvdata(pdev, info);
   1529	return 0;
   1530
   1531error:
   1532	if (par->dc_regs)
   1533		iounmap(par->dc_regs);
   1534	if (info->screen_base)
   1535		iounmap(info->screen_base);
   1536	release_mem_region(addr, size);
   1537	framebuffer_release(info);
   1538	return ret;
   1539}
   1540
   1541static void imsttfb_remove(struct pci_dev *pdev)
   1542{
   1543	struct fb_info *info = pci_get_drvdata(pdev);
   1544	struct imstt_par *par = info->par;
   1545	int size = pci_resource_len(pdev, 0);
   1546
   1547	unregister_framebuffer(info);
   1548	iounmap(par->cmap_regs);
   1549	iounmap(par->dc_regs);
   1550	iounmap(info->screen_base);
   1551	release_mem_region(info->fix.smem_start, size);
   1552	framebuffer_release(info);
   1553}
   1554
   1555#ifndef MODULE
   1556static int __init
   1557imsttfb_setup(char *options)
   1558{
   1559	char *this_opt;
   1560
   1561	if (!options || !*options)
   1562		return 0;
   1563
   1564	while ((this_opt = strsep(&options, ",")) != NULL) {
   1565		if (!strncmp(this_opt, "font:", 5)) {
   1566			char *p;
   1567			int i;
   1568
   1569			p = this_opt + 5;
   1570			for (i = 0; i < sizeof(fontname) - 1; i++)
   1571				if (!*p || *p == ' ' || *p == ',')
   1572					break;
   1573			memcpy(fontname, this_opt + 5, i);
   1574			fontname[i] = 0;
   1575		} else if (!strncmp(this_opt, "inverse", 7)) {
   1576			inverse = 1;
   1577			fb_invert_cmaps();
   1578		}
   1579#if defined(CONFIG_PPC_PMAC)
   1580		else if (!strncmp(this_opt, "vmode:", 6)) {
   1581			int vmode = simple_strtoul(this_opt+6, NULL, 0);
   1582			if (vmode > 0 && vmode <= VMODE_MAX)
   1583				init_vmode = vmode;
   1584		} else if (!strncmp(this_opt, "cmode:", 6)) {
   1585			int cmode = simple_strtoul(this_opt+6, NULL, 0);
   1586			switch (cmode) {
   1587				case CMODE_8:
   1588				case 8:
   1589					init_cmode = CMODE_8;
   1590					break;
   1591				case CMODE_16:
   1592				case 15:
   1593				case 16:
   1594					init_cmode = CMODE_16;
   1595					break;
   1596				case CMODE_32:
   1597				case 24:
   1598				case 32:
   1599					init_cmode = CMODE_32;
   1600					break;
   1601			}
   1602		}
   1603#endif
   1604	}
   1605	return 0;
   1606}
   1607
   1608#endif /* MODULE */
   1609
   1610static int __init imsttfb_init(void)
   1611{
   1612#ifndef MODULE
   1613	char *option = NULL;
   1614
   1615	if (fb_get_options("imsttfb", &option))
   1616		return -ENODEV;
   1617
   1618	imsttfb_setup(option);
   1619#endif
   1620	return pci_register_driver(&imsttfb_pci_driver);
   1621}
   1622 
   1623static void __exit imsttfb_exit(void)
   1624{
   1625	pci_unregister_driver(&imsttfb_pci_driver);
   1626}
   1627
   1628MODULE_LICENSE("GPL");
   1629
   1630module_init(imsttfb_init);
   1631module_exit(imsttfb_exit);
   1632