xref: /openbmc/linux/drivers/video/fbdev/stifb.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1f7018c21STomi Valkeinen /*
2f7018c21STomi Valkeinen  * linux/drivers/video/stifb.c -
3f7018c21STomi Valkeinen  * Low level Frame buffer driver for HP workstations with
4f7018c21STomi Valkeinen  * STI (standard text interface) video firmware.
5f7018c21STomi Valkeinen  *
6f7018c21STomi Valkeinen  * Copyright (C) 2001-2006 Helge Deller <deller@gmx.de>
7f7018c21STomi Valkeinen  * Portions Copyright (C) 2001 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
8f7018c21STomi Valkeinen  *
9f7018c21STomi Valkeinen  * Based on:
10f7018c21STomi Valkeinen  * - linux/drivers/video/artistfb.c -- Artist frame buffer driver
11f7018c21STomi Valkeinen  *	Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
12f7018c21STomi Valkeinen  *   - based on skeletonfb, which was
13f7018c21STomi Valkeinen  *	Created 28 Dec 1997 by Geert Uytterhoeven
14f7018c21STomi Valkeinen  * - HP Xhp cfb-based X11 window driver for XFree86
15f7018c21STomi Valkeinen  *	(c)Copyright 1992 Hewlett-Packard Co.
16f7018c21STomi Valkeinen  *
17f7018c21STomi Valkeinen  *
18f7018c21STomi Valkeinen  *  The following graphics display devices (NGLE family) are supported by this driver:
19f7018c21STomi Valkeinen  *
20f7018c21STomi Valkeinen  *  HPA4070A	known as "HCRX", a 1280x1024 color device with 8 planes
21f7018c21STomi Valkeinen  *  HPA4071A	known as "HCRX24", a 1280x1024 color device with 24 planes,
22f7018c21STomi Valkeinen  *		optionally available with a hardware accelerator as HPA4071A_Z
23f7018c21STomi Valkeinen  *  HPA1659A	known as "CRX", a 1280x1024 color device with 8 planes
24f7018c21STomi Valkeinen  *  HPA1439A	known as "CRX24", a 1280x1024 color device with 24 planes,
25f7018c21STomi Valkeinen  *		optionally available with a hardware accelerator.
26f7018c21STomi Valkeinen  *  HPA1924A	known as "GRX", a 1280x1024 grayscale device with 8 planes
27f7018c21STomi Valkeinen  *  HPA2269A	known as "Dual CRX", a 1280x1024 color device with 8 planes,
28f7018c21STomi Valkeinen  *		implements support for two displays on a single graphics card.
29f7018c21STomi Valkeinen  *  HP710C	internal graphics support optionally available on the HP9000s710 SPU,
30f7018c21STomi Valkeinen  *		supports 1280x1024 color displays with 8 planes.
31f7018c21STomi Valkeinen  *  HP710G	same as HP710C, 1280x1024 grayscale only
32f7018c21STomi Valkeinen  *  HP710L	same as HP710C, 1024x768 color only
33f7018c21STomi Valkeinen  *  HP712	internal graphics support on HP9000s712 SPU, supports 640x480,
34f7018c21STomi Valkeinen  *		1024x768 or 1280x1024 color displays on 8 planes (Artist)
35f7018c21STomi Valkeinen  *
36f7018c21STomi Valkeinen  * This file is subject to the terms and conditions of the GNU General Public
37f7018c21STomi Valkeinen  * License.  See the file COPYING in the main directory of this archive
38f7018c21STomi Valkeinen  * for more details.
39f7018c21STomi Valkeinen  */
40f7018c21STomi Valkeinen 
41f7018c21STomi Valkeinen /* TODO:
42f7018c21STomi Valkeinen  *	- 1bpp mode is completely untested
43f7018c21STomi Valkeinen  *	- add support for h/w acceleration
44f7018c21STomi Valkeinen  *	- add hardware cursor
45f7018c21STomi Valkeinen  *	- automatically disable double buffering (e.g. on RDI precisionbook laptop)
46f7018c21STomi Valkeinen  */
47f7018c21STomi Valkeinen 
48f7018c21STomi Valkeinen 
49f7018c21STomi Valkeinen /* on supported graphic devices you may:
50f7018c21STomi Valkeinen  * #define FALLBACK_TO_1BPP to fall back to 1 bpp, or
51f7018c21STomi Valkeinen  * #undef  FALLBACK_TO_1BPP to reject support for unsupported cards */
52f7018c21STomi Valkeinen #undef FALLBACK_TO_1BPP
53f7018c21STomi Valkeinen 
54f7018c21STomi Valkeinen #undef DEBUG_STIFB_REGS		/* debug sti register accesses */
55f7018c21STomi Valkeinen 
56f7018c21STomi Valkeinen 
57f7018c21STomi Valkeinen #include <linux/module.h>
58f7018c21STomi Valkeinen #include <linux/kernel.h>
59f7018c21STomi Valkeinen #include <linux/errno.h>
60f7018c21STomi Valkeinen #include <linux/string.h>
61f7018c21STomi Valkeinen #include <linux/mm.h>
62f7018c21STomi Valkeinen #include <linux/slab.h>
63f7018c21STomi Valkeinen #include <linux/delay.h>
64f7018c21STomi Valkeinen #include <linux/fb.h>
65f7018c21STomi Valkeinen #include <linux/init.h>
66f7018c21STomi Valkeinen #include <linux/ioport.h>
672584cf83SDan Williams #include <linux/io.h>
68f7018c21STomi Valkeinen 
69f7018c21STomi Valkeinen #include <asm/grfioctl.h>	/* for HP-UX compatibility */
707c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
71f7018c21STomi Valkeinen 
72f7018c21STomi Valkeinen #include <video/sticore.h>
73f7018c21STomi Valkeinen 
74f7018c21STomi Valkeinen /* REGION_BASE(fb_info, index) returns the physical address for region <index> */
75f7018c21STomi Valkeinen #define REGION_BASE(fb_info, index) \
76f7018c21STomi Valkeinen 	F_EXTEND(fb_info->sti->regions_phys[index])
77f7018c21STomi Valkeinen 
78f7018c21STomi Valkeinen #define NGLEDEVDEPROM_CRT_REGION 1
79f7018c21STomi Valkeinen 
80f7018c21STomi Valkeinen #define NR_PALETTE 256
81f7018c21STomi Valkeinen 
82f7018c21STomi Valkeinen typedef struct {
83f7018c21STomi Valkeinen 	__s32	video_config_reg;
84f7018c21STomi Valkeinen 	__s32	misc_video_start;
85f7018c21STomi Valkeinen 	__s32	horiz_timing_fmt;
86f7018c21STomi Valkeinen 	__s32	serr_timing_fmt;
87f7018c21STomi Valkeinen 	__s32	vert_timing_fmt;
88f7018c21STomi Valkeinen 	__s32	horiz_state;
89f7018c21STomi Valkeinen 	__s32	vert_state;
90f7018c21STomi Valkeinen 	__s32	vtg_state_elements;
91f7018c21STomi Valkeinen 	__s32	pipeline_delay;
92f7018c21STomi Valkeinen 	__s32	misc_video_end;
93f7018c21STomi Valkeinen } video_setup_t;
94f7018c21STomi Valkeinen 
95f7018c21STomi Valkeinen typedef struct {
96f7018c21STomi Valkeinen 	__s16	sizeof_ngle_data;
97f7018c21STomi Valkeinen 	__s16	x_size_visible;	    /* visible screen dim in pixels  */
98f7018c21STomi Valkeinen 	__s16	y_size_visible;
99f7018c21STomi Valkeinen 	__s16	pad2[15];
100f7018c21STomi Valkeinen 	__s16	cursor_pipeline_delay;
101f7018c21STomi Valkeinen 	__s16	video_interleaves;
102f7018c21STomi Valkeinen 	__s32	pad3[11];
103f7018c21STomi Valkeinen } ngle_rom_t;
104f7018c21STomi Valkeinen 
105f7018c21STomi Valkeinen struct stifb_info {
106f7018c21STomi Valkeinen 	struct fb_info info;
107f7018c21STomi Valkeinen 	unsigned int id;
108f7018c21STomi Valkeinen 	ngle_rom_t ngle_rom;
109f7018c21STomi Valkeinen 	struct sti_struct *sti;
110f7018c21STomi Valkeinen 	int deviceSpecificConfig;
111f7018c21STomi Valkeinen 	u32 pseudo_palette[16];
112f7018c21STomi Valkeinen };
113f7018c21STomi Valkeinen 
114f7018c21STomi Valkeinen static int __initdata stifb_bpp_pref[MAX_STI_ROMS];
115f7018c21STomi Valkeinen 
116f7018c21STomi Valkeinen /* ------------------- chipset specific functions -------------------------- */
117f7018c21STomi Valkeinen 
118f7018c21STomi Valkeinen /* offsets to graphic-chip internal registers */
119f7018c21STomi Valkeinen 
120f7018c21STomi Valkeinen #define REG_1		0x000118
121f7018c21STomi Valkeinen #define REG_2		0x000480
122f7018c21STomi Valkeinen #define REG_3		0x0004a0
123f7018c21STomi Valkeinen #define REG_4		0x000600
124f7018c21STomi Valkeinen #define REG_6		0x000800
125cb908ed3SAlex Ivanov #define REG_7		0x000804
126f7018c21STomi Valkeinen #define REG_8		0x000820
127f7018c21STomi Valkeinen #define REG_9		0x000a04
128f7018c21STomi Valkeinen #define REG_10		0x018000
129f7018c21STomi Valkeinen #define REG_11		0x018004
130f7018c21STomi Valkeinen #define REG_12		0x01800c
131f7018c21STomi Valkeinen #define REG_13		0x018018
132f7018c21STomi Valkeinen #define REG_14  	0x01801c
133f7018c21STomi Valkeinen #define REG_15		0x200000
134f7018c21STomi Valkeinen #define REG_15b0	0x200000
135f7018c21STomi Valkeinen #define REG_16b1	0x200005
136f7018c21STomi Valkeinen #define REG_16b3	0x200007
137f7018c21STomi Valkeinen #define REG_21		0x200218
138f7018c21STomi Valkeinen #define REG_22		0x0005a0
139f7018c21STomi Valkeinen #define REG_23		0x0005c0
140cb908ed3SAlex Ivanov #define REG_24		0x000808
141cb908ed3SAlex Ivanov #define REG_25		0x000b00
142f7018c21STomi Valkeinen #define REG_26		0x200118
143f7018c21STomi Valkeinen #define REG_27		0x200308
144f7018c21STomi Valkeinen #define REG_32		0x21003c
145f7018c21STomi Valkeinen #define REG_33		0x210040
146f7018c21STomi Valkeinen #define REG_34		0x200008
147f7018c21STomi Valkeinen #define REG_35		0x018010
148f7018c21STomi Valkeinen #define REG_38		0x210020
149f7018c21STomi Valkeinen #define REG_39		0x210120
150f7018c21STomi Valkeinen #define REG_40		0x210130
151f7018c21STomi Valkeinen #define REG_42		0x210028
152f7018c21STomi Valkeinen #define REG_43		0x21002c
153f7018c21STomi Valkeinen #define REG_44		0x210030
154f7018c21STomi Valkeinen #define REG_45		0x210034
155f7018c21STomi Valkeinen 
156f7018c21STomi Valkeinen #define READ_BYTE(fb,reg)		gsc_readb((fb)->info.fix.mmio_start + (reg))
157f7018c21STomi Valkeinen #define READ_WORD(fb,reg)		gsc_readl((fb)->info.fix.mmio_start + (reg))
158f7018c21STomi Valkeinen 
159f7018c21STomi Valkeinen 
160f7018c21STomi Valkeinen #ifndef DEBUG_STIFB_REGS
161f7018c21STomi Valkeinen # define  DEBUG_OFF()
162f7018c21STomi Valkeinen # define  DEBUG_ON()
163f7018c21STomi Valkeinen # define WRITE_BYTE(value,fb,reg)	gsc_writeb((value),(fb)->info.fix.mmio_start + (reg))
164f7018c21STomi Valkeinen # define WRITE_WORD(value,fb,reg)	gsc_writel((value),(fb)->info.fix.mmio_start + (reg))
165f7018c21STomi Valkeinen #else
166f7018c21STomi Valkeinen   static int debug_on = 1;
167f7018c21STomi Valkeinen # define  DEBUG_OFF() debug_on=0
168f7018c21STomi Valkeinen # define  DEBUG_ON()  debug_on=1
169f7018c21STomi Valkeinen # define WRITE_BYTE(value,fb,reg)	do { if (debug_on) \
170f7018c21STomi Valkeinen 						printk(KERN_DEBUG "%30s: WRITE_BYTE(0x%06x) = 0x%02x (old=0x%02x)\n", \
171f7018c21STomi Valkeinen 							__func__, reg, value, READ_BYTE(fb,reg)); 		  \
172f7018c21STomi Valkeinen 					gsc_writeb((value),(fb)->info.fix.mmio_start + (reg)); } while (0)
173f7018c21STomi Valkeinen # define WRITE_WORD(value,fb,reg)	do { if (debug_on) \
174f7018c21STomi Valkeinen 						printk(KERN_DEBUG "%30s: WRITE_WORD(0x%06x) = 0x%08x (old=0x%08x)\n", \
175f7018c21STomi Valkeinen 							__func__, reg, value, READ_WORD(fb,reg)); 		  \
176f7018c21STomi Valkeinen 					gsc_writel((value),(fb)->info.fix.mmio_start + (reg)); } while (0)
177f7018c21STomi Valkeinen #endif /* DEBUG_STIFB_REGS */
178f7018c21STomi Valkeinen 
179f7018c21STomi Valkeinen 
180f7018c21STomi Valkeinen #define ENABLE	1	/* for enabling/disabling screen */
181f7018c21STomi Valkeinen #define DISABLE 0
182f7018c21STomi Valkeinen 
183f7018c21STomi Valkeinen #define NGLE_LOCK(fb_info)	do { } while (0)
184f7018c21STomi Valkeinen #define NGLE_UNLOCK(fb_info)	do { } while (0)
185f7018c21STomi Valkeinen 
186f7018c21STomi Valkeinen static void
SETUP_HW(struct stifb_info * fb)187f7018c21STomi Valkeinen SETUP_HW(struct stifb_info *fb)
188f7018c21STomi Valkeinen {
189f7018c21STomi Valkeinen 	char stat;
190f7018c21STomi Valkeinen 
191f7018c21STomi Valkeinen 	do {
192f7018c21STomi Valkeinen 		stat = READ_BYTE(fb, REG_15b0);
193f7018c21STomi Valkeinen 		if (!stat)
194f7018c21STomi Valkeinen 	    		stat = READ_BYTE(fb, REG_15b0);
195f7018c21STomi Valkeinen 	} while (stat);
196f7018c21STomi Valkeinen }
197f7018c21STomi Valkeinen 
198f7018c21STomi Valkeinen 
199f7018c21STomi Valkeinen static void
SETUP_FB(struct stifb_info * fb)200f7018c21STomi Valkeinen SETUP_FB(struct stifb_info *fb)
201f7018c21STomi Valkeinen {
202f7018c21STomi Valkeinen 	unsigned int reg10_value = 0;
203f7018c21STomi Valkeinen 
204f7018c21STomi Valkeinen 	SETUP_HW(fb);
205f7018c21STomi Valkeinen 	switch (fb->id)
206f7018c21STomi Valkeinen 	{
207f7018c21STomi Valkeinen 		case CRT_ID_VISUALIZE_EG:
208f7018c21STomi Valkeinen 		case S9000_ID_ARTIST:
209f7018c21STomi Valkeinen 		case S9000_ID_A1659A:
210f7018c21STomi Valkeinen 			reg10_value = 0x13601000;
211f7018c21STomi Valkeinen 			break;
212f7018c21STomi Valkeinen 		case S9000_ID_A1439A:
213f7018c21STomi Valkeinen 			if (fb->info.var.bits_per_pixel == 32)
214f7018c21STomi Valkeinen 				reg10_value = 0xBBA0A000;
215f7018c21STomi Valkeinen 			else
216f7018c21STomi Valkeinen 				reg10_value = 0x13601000;
217f7018c21STomi Valkeinen 			break;
218f7018c21STomi Valkeinen 		case S9000_ID_HCRX:
219f7018c21STomi Valkeinen 			if (fb->info.var.bits_per_pixel == 32)
220f7018c21STomi Valkeinen 				reg10_value = 0xBBA0A000;
221f7018c21STomi Valkeinen 			else
222f7018c21STomi Valkeinen 				reg10_value = 0x13602000;
223f7018c21STomi Valkeinen 			break;
224f7018c21STomi Valkeinen 		case S9000_ID_TIMBER:
225f7018c21STomi Valkeinen 		case CRX24_OVERLAY_PLANES:
226f7018c21STomi Valkeinen 			reg10_value = 0x13602000;
227f7018c21STomi Valkeinen 			break;
228f7018c21STomi Valkeinen 	}
229f7018c21STomi Valkeinen 	if (reg10_value)
230f7018c21STomi Valkeinen 		WRITE_WORD(reg10_value, fb, REG_10);
231f7018c21STomi Valkeinen 	WRITE_WORD(0x83000300, fb, REG_14);
232f7018c21STomi Valkeinen 	SETUP_HW(fb);
233f7018c21STomi Valkeinen 	WRITE_BYTE(1, fb, REG_16b1);
234f7018c21STomi Valkeinen }
235f7018c21STomi Valkeinen 
236f7018c21STomi Valkeinen static void
START_IMAGE_COLORMAP_ACCESS(struct stifb_info * fb)237f7018c21STomi Valkeinen START_IMAGE_COLORMAP_ACCESS(struct stifb_info *fb)
238f7018c21STomi Valkeinen {
239f7018c21STomi Valkeinen 	SETUP_HW(fb);
240f7018c21STomi Valkeinen 	WRITE_WORD(0xBBE0F000, fb, REG_10);
241f7018c21STomi Valkeinen 	WRITE_WORD(0x03000300, fb, REG_14);
242f7018c21STomi Valkeinen 	WRITE_WORD(~0, fb, REG_13);
243f7018c21STomi Valkeinen }
244f7018c21STomi Valkeinen 
245f7018c21STomi Valkeinen static void
WRITE_IMAGE_COLOR(struct stifb_info * fb,int index,int color)246f7018c21STomi Valkeinen WRITE_IMAGE_COLOR(struct stifb_info *fb, int index, int color)
247f7018c21STomi Valkeinen {
248f7018c21STomi Valkeinen 	SETUP_HW(fb);
249f7018c21STomi Valkeinen 	WRITE_WORD(((0x100+index)<<2), fb, REG_3);
250f7018c21STomi Valkeinen 	WRITE_WORD(color, fb, REG_4);
251f7018c21STomi Valkeinen }
252f7018c21STomi Valkeinen 
253f7018c21STomi Valkeinen static void
FINISH_IMAGE_COLORMAP_ACCESS(struct stifb_info * fb)254f7018c21STomi Valkeinen FINISH_IMAGE_COLORMAP_ACCESS(struct stifb_info *fb)
255f7018c21STomi Valkeinen {
256f7018c21STomi Valkeinen 	WRITE_WORD(0x400, fb, REG_2);
257f7018c21STomi Valkeinen 	if (fb->info.var.bits_per_pixel == 32) {
258f7018c21STomi Valkeinen 		WRITE_WORD(0x83000100, fb, REG_1);
259f7018c21STomi Valkeinen 	} else {
260f7018c21STomi Valkeinen 		if (fb->id == S9000_ID_ARTIST || fb->id == CRT_ID_VISUALIZE_EG)
261f7018c21STomi Valkeinen 			WRITE_WORD(0x80000100, fb, REG_26);
262f7018c21STomi Valkeinen 		else
263f7018c21STomi Valkeinen 			WRITE_WORD(0x80000100, fb, REG_1);
264f7018c21STomi Valkeinen 	}
265f7018c21STomi Valkeinen 	SETUP_FB(fb);
266f7018c21STomi Valkeinen }
267f7018c21STomi Valkeinen 
268f7018c21STomi Valkeinen static void
SETUP_RAMDAC(struct stifb_info * fb)269f7018c21STomi Valkeinen SETUP_RAMDAC(struct stifb_info *fb)
270f7018c21STomi Valkeinen {
271f7018c21STomi Valkeinen 	SETUP_HW(fb);
272f7018c21STomi Valkeinen 	WRITE_WORD(0x04000000, fb, 0x1020);
273f7018c21STomi Valkeinen 	WRITE_WORD(0xff000000, fb, 0x1028);
274f7018c21STomi Valkeinen }
275f7018c21STomi Valkeinen 
276f7018c21STomi Valkeinen static void
CRX24_SETUP_RAMDAC(struct stifb_info * fb)277f7018c21STomi Valkeinen CRX24_SETUP_RAMDAC(struct stifb_info *fb)
278f7018c21STomi Valkeinen {
279f7018c21STomi Valkeinen 	SETUP_HW(fb);
280f7018c21STomi Valkeinen 	WRITE_WORD(0x04000000, fb, 0x1000);
281f7018c21STomi Valkeinen 	WRITE_WORD(0x02000000, fb, 0x1004);
282f7018c21STomi Valkeinen 	WRITE_WORD(0xff000000, fb, 0x1008);
283f7018c21STomi Valkeinen 	WRITE_WORD(0x05000000, fb, 0x1000);
284f7018c21STomi Valkeinen 	WRITE_WORD(0x02000000, fb, 0x1004);
285f7018c21STomi Valkeinen 	WRITE_WORD(0x03000000, fb, 0x1008);
286f7018c21STomi Valkeinen }
287f7018c21STomi Valkeinen 
288f7018c21STomi Valkeinen #if 0
289f7018c21STomi Valkeinen static void
290f7018c21STomi Valkeinen HCRX_SETUP_RAMDAC(struct stifb_info *fb)
291f7018c21STomi Valkeinen {
292f7018c21STomi Valkeinen 	WRITE_WORD(0xffffffff, fb, REG_32);
293f7018c21STomi Valkeinen }
294f7018c21STomi Valkeinen #endif
295f7018c21STomi Valkeinen 
296f7018c21STomi Valkeinen static void
CRX24_SET_OVLY_MASK(struct stifb_info * fb)297f7018c21STomi Valkeinen CRX24_SET_OVLY_MASK(struct stifb_info *fb)
298f7018c21STomi Valkeinen {
299f7018c21STomi Valkeinen 	SETUP_HW(fb);
300f7018c21STomi Valkeinen 	WRITE_WORD(0x13a02000, fb, REG_11);
301f7018c21STomi Valkeinen 	WRITE_WORD(0x03000300, fb, REG_14);
302f7018c21STomi Valkeinen 	WRITE_WORD(0x000017f0, fb, REG_3);
303f7018c21STomi Valkeinen 	WRITE_WORD(0xffffffff, fb, REG_13);
304f7018c21STomi Valkeinen 	WRITE_WORD(0xffffffff, fb, REG_22);
305f7018c21STomi Valkeinen 	WRITE_WORD(0x00000000, fb, REG_23);
306f7018c21STomi Valkeinen }
307f7018c21STomi Valkeinen 
308f7018c21STomi Valkeinen static void
ENABLE_DISABLE_DISPLAY(struct stifb_info * fb,int enable)309f7018c21STomi Valkeinen ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)
310f7018c21STomi Valkeinen {
311f7018c21STomi Valkeinen 	unsigned int value = enable ? 0x43000000 : 0x03000000;
312f7018c21STomi Valkeinen         SETUP_HW(fb);
313f7018c21STomi Valkeinen         WRITE_WORD(0x06000000,	fb, 0x1030);
314f7018c21STomi Valkeinen         WRITE_WORD(value, 	fb, 0x1038);
315f7018c21STomi Valkeinen }
316f7018c21STomi Valkeinen 
317f7018c21STomi Valkeinen static void
CRX24_ENABLE_DISABLE_DISPLAY(struct stifb_info * fb,int enable)318f7018c21STomi Valkeinen CRX24_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)
319f7018c21STomi Valkeinen {
320f7018c21STomi Valkeinen 	unsigned int value = enable ? 0x10000000 : 0x30000000;
321f7018c21STomi Valkeinen 	SETUP_HW(fb);
322f7018c21STomi Valkeinen 	WRITE_WORD(0x01000000,	fb, 0x1000);
323f7018c21STomi Valkeinen 	WRITE_WORD(0x02000000,	fb, 0x1004);
324f7018c21STomi Valkeinen 	WRITE_WORD(value,	fb, 0x1008);
325f7018c21STomi Valkeinen }
326f7018c21STomi Valkeinen 
327f7018c21STomi Valkeinen static void
ARTIST_ENABLE_DISABLE_DISPLAY(struct stifb_info * fb,int enable)328f7018c21STomi Valkeinen ARTIST_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)
329f7018c21STomi Valkeinen {
330f7018c21STomi Valkeinen 	u32 DregsMiscVideo = REG_21;
331f7018c21STomi Valkeinen 	u32 DregsMiscCtl = REG_27;
332f7018c21STomi Valkeinen 
333f7018c21STomi Valkeinen 	SETUP_HW(fb);
334f7018c21STomi Valkeinen 	if (enable) {
335f7018c21STomi Valkeinen 	  WRITE_WORD(READ_WORD(fb, DregsMiscVideo) | 0x0A000000, fb, DregsMiscVideo);
336f7018c21STomi Valkeinen 	  WRITE_WORD(READ_WORD(fb, DregsMiscCtl)   | 0x00800000, fb, DregsMiscCtl);
337f7018c21STomi Valkeinen 	} else {
338f7018c21STomi Valkeinen 	  WRITE_WORD(READ_WORD(fb, DregsMiscVideo) & ~0x0A000000, fb, DregsMiscVideo);
339f7018c21STomi Valkeinen 	  WRITE_WORD(READ_WORD(fb, DregsMiscCtl)   & ~0x00800000, fb, DregsMiscCtl);
340f7018c21STomi Valkeinen 	}
341f7018c21STomi Valkeinen }
342f7018c21STomi Valkeinen 
343f7018c21STomi Valkeinen #define GET_ROMTABLE_INDEX(fb) \
344f7018c21STomi Valkeinen 	(READ_BYTE(fb, REG_16b3) - 1)
345f7018c21STomi Valkeinen 
346f7018c21STomi Valkeinen #define HYPER_CONFIG_PLANES_24 0x00000100
347f7018c21STomi Valkeinen 
348f7018c21STomi Valkeinen #define IS_24_DEVICE(fb) \
349f7018c21STomi Valkeinen 	(fb->deviceSpecificConfig & HYPER_CONFIG_PLANES_24)
350f7018c21STomi Valkeinen 
351f7018c21STomi Valkeinen #define IS_888_DEVICE(fb) \
352f7018c21STomi Valkeinen 	(!(IS_24_DEVICE(fb)))
353f7018c21STomi Valkeinen 
354f7018c21STomi Valkeinen #define GET_FIFO_SLOTS(fb, cnt, numslots)	\
355f7018c21STomi Valkeinen {	while (cnt < numslots) 			\
356f7018c21STomi Valkeinen 		cnt = READ_WORD(fb, REG_34);	\
357f7018c21STomi Valkeinen 	cnt -= numslots;			\
358f7018c21STomi Valkeinen }
359f7018c21STomi Valkeinen 
360f7018c21STomi Valkeinen #define	    IndexedDcd	0	/* Pixel data is indexed (pseudo) color */
361f7018c21STomi Valkeinen #define	    Otc04	2	/* Pixels in each longword transfer (4) */
362f7018c21STomi Valkeinen #define	    Otc32	5	/* Pixels in each longword transfer (32) */
363f7018c21STomi Valkeinen #define	    Ots08	3	/* Each pixel is size (8)d transfer (1) */
364f7018c21STomi Valkeinen #define	    OtsIndirect	6	/* Each bit goes through FG/BG color(8) */
365f7018c21STomi Valkeinen #define	    AddrLong	5	/* FB address is Long aligned (pixel) */
366f7018c21STomi Valkeinen #define	    BINovly	0x2	/* 8 bit overlay */
367f7018c21STomi Valkeinen #define	    BINapp0I	0x0	/* Application Buffer 0, Indexed */
368f7018c21STomi Valkeinen #define	    BINapp1I	0x1	/* Application Buffer 1, Indexed */
369f7018c21STomi Valkeinen #define	    BINapp0F8	0xa	/* Application Buffer 0, Fractional 8-8-8 */
370f7018c21STomi Valkeinen #define	    BINattr	0xd	/* Attribute Bitmap */
371f7018c21STomi Valkeinen #define	    RopSrc 	0x3
372f7018c21STomi Valkeinen #define	    BitmapExtent08  3	/* Each write hits ( 8) bits in depth */
373f7018c21STomi Valkeinen #define	    BitmapExtent32  5	/* Each write hits (32) bits in depth */
374f7018c21STomi Valkeinen #define	    DataDynamic	    0	/* Data register reloaded by direct access */
375f7018c21STomi Valkeinen #define	    MaskDynamic	    1	/* Mask register reloaded by direct access */
376f7018c21STomi Valkeinen #define	    MaskOtc	    0	/* Mask contains Object Count valid bits */
377f7018c21STomi Valkeinen 
378f7018c21STomi Valkeinen #define MaskAddrOffset(offset) (offset)
379f7018c21STomi Valkeinen #define StaticReg(en) (en)
380f7018c21STomi Valkeinen #define BGx(en) (en)
381f7018c21STomi Valkeinen #define FGx(en) (en)
382f7018c21STomi Valkeinen 
383f7018c21STomi Valkeinen #define BAJustPoint(offset) (offset)
384f7018c21STomi Valkeinen #define BAIndexBase(base) (base)
385f7018c21STomi Valkeinen #define BA(F,C,S,A,J,B,I) \
386f7018c21STomi Valkeinen 	(((F)<<31)|((C)<<27)|((S)<<24)|((A)<<21)|((J)<<16)|((B)<<12)|(I))
387f7018c21STomi Valkeinen 
388f7018c21STomi Valkeinen #define IBOvals(R,M,X,S,D,L,B,F) \
389f7018c21STomi Valkeinen 	(((R)<<8)|((M)<<16)|((X)<<24)|((S)<<29)|((D)<<28)|((L)<<31)|((B)<<1)|(F))
390f7018c21STomi Valkeinen 
391f7018c21STomi Valkeinen #define NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb, val) \
392f7018c21STomi Valkeinen 	WRITE_WORD(val, fb, REG_14)
393f7018c21STomi Valkeinen 
394f7018c21STomi Valkeinen #define NGLE_QUICK_SET_DST_BM_ACCESS(fb, val) \
395f7018c21STomi Valkeinen 	WRITE_WORD(val, fb, REG_11)
396f7018c21STomi Valkeinen 
397f7018c21STomi Valkeinen #define NGLE_QUICK_SET_CTL_PLN_REG(fb, val) \
398f7018c21STomi Valkeinen 	WRITE_WORD(val, fb, REG_12)
399f7018c21STomi Valkeinen 
400f7018c21STomi Valkeinen #define NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, plnmsk32) \
401f7018c21STomi Valkeinen 	WRITE_WORD(plnmsk32, fb, REG_13)
402f7018c21STomi Valkeinen 
403f7018c21STomi Valkeinen #define NGLE_REALLY_SET_IMAGE_FG_COLOR(fb, fg32) \
404f7018c21STomi Valkeinen 	WRITE_WORD(fg32, fb, REG_35)
405f7018c21STomi Valkeinen 
406f7018c21STomi Valkeinen #define NGLE_SET_TRANSFERDATA(fb, val) \
407f7018c21STomi Valkeinen 	WRITE_WORD(val, fb, REG_8)
408f7018c21STomi Valkeinen 
409f7018c21STomi Valkeinen #define NGLE_SET_DSTXY(fb, val) \
410f7018c21STomi Valkeinen 	WRITE_WORD(val, fb, REG_6)
411f7018c21STomi Valkeinen 
412f7018c21STomi Valkeinen #define NGLE_LONG_FB_ADDRESS(fbaddrbase, x, y) (		\
413f7018c21STomi Valkeinen 	(u32) (fbaddrbase) +					\
414f7018c21STomi Valkeinen 	    (	(unsigned int)  ( (y) << 13      ) |		\
415f7018c21STomi Valkeinen 		(unsigned int)  ( (x) << 2       )	)	\
416f7018c21STomi Valkeinen 	)
417f7018c21STomi Valkeinen 
418f7018c21STomi Valkeinen #define NGLE_BINC_SET_DSTADDR(fb, addr) \
419f7018c21STomi Valkeinen 	WRITE_WORD(addr, fb, REG_3)
420f7018c21STomi Valkeinen 
421f7018c21STomi Valkeinen #define NGLE_BINC_SET_SRCADDR(fb, addr) \
422f7018c21STomi Valkeinen 	WRITE_WORD(addr, fb, REG_2)
423f7018c21STomi Valkeinen 
424f7018c21STomi Valkeinen #define NGLE_BINC_SET_DSTMASK(fb, mask) \
425f7018c21STomi Valkeinen 	WRITE_WORD(mask, fb, REG_22)
426f7018c21STomi Valkeinen 
427f7018c21STomi Valkeinen #define NGLE_BINC_WRITE32(fb, data32) \
428f7018c21STomi Valkeinen 	WRITE_WORD(data32, fb, REG_23)
429f7018c21STomi Valkeinen 
430f7018c21STomi Valkeinen #define START_COLORMAPLOAD(fb, cmapBltCtlData32) \
431f7018c21STomi Valkeinen 	WRITE_WORD((cmapBltCtlData32), fb, REG_38)
432f7018c21STomi Valkeinen 
433f7018c21STomi Valkeinen #define SET_LENXY_START_RECFILL(fb, lenxy) \
434f7018c21STomi Valkeinen 	WRITE_WORD(lenxy, fb, REG_9)
435f7018c21STomi Valkeinen 
436cb908ed3SAlex Ivanov #define SETUP_COPYAREA(fb) \
437cb908ed3SAlex Ivanov 	WRITE_BYTE(0, fb, REG_16b1)
438cb908ed3SAlex Ivanov 
439f7018c21STomi Valkeinen static void
HYPER_ENABLE_DISABLE_DISPLAY(struct stifb_info * fb,int enable)440f7018c21STomi Valkeinen HYPER_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)
441f7018c21STomi Valkeinen {
442f7018c21STomi Valkeinen 	u32 DregsHypMiscVideo = REG_33;
443f7018c21STomi Valkeinen 	unsigned int value;
444f7018c21STomi Valkeinen 	SETUP_HW(fb);
445f7018c21STomi Valkeinen 	value = READ_WORD(fb, DregsHypMiscVideo);
446f7018c21STomi Valkeinen 	if (enable)
447f7018c21STomi Valkeinen 		value |= 0x0A000000;
448f7018c21STomi Valkeinen 	else
449f7018c21STomi Valkeinen 		value &= ~0x0A000000;
450f7018c21STomi Valkeinen 	WRITE_WORD(value, fb, DregsHypMiscVideo);
451f7018c21STomi Valkeinen }
452f7018c21STomi Valkeinen 
453f7018c21STomi Valkeinen 
454f7018c21STomi Valkeinen /* BufferNumbers used by SETUP_ATTR_ACCESS() */
455f7018c21STomi Valkeinen #define BUFF0_CMAP0	0x00001e02
456f7018c21STomi Valkeinen #define BUFF1_CMAP0	0x02001e02
457f7018c21STomi Valkeinen #define BUFF1_CMAP3	0x0c001e02
458f7018c21STomi Valkeinen #define ARTIST_CMAP0	0x00000102
459f7018c21STomi Valkeinen #define HYPER_CMAP8	0x00000100
460f7018c21STomi Valkeinen #define HYPER_CMAP24	0x00000800
461f7018c21STomi Valkeinen 
462f7018c21STomi Valkeinen static void
SETUP_ATTR_ACCESS(struct stifb_info * fb,unsigned BufferNumber)463f7018c21STomi Valkeinen SETUP_ATTR_ACCESS(struct stifb_info *fb, unsigned BufferNumber)
464f7018c21STomi Valkeinen {
465f7018c21STomi Valkeinen 	SETUP_HW(fb);
466f7018c21STomi Valkeinen 	WRITE_WORD(0x2EA0D000, fb, REG_11);
467f7018c21STomi Valkeinen 	WRITE_WORD(0x23000302, fb, REG_14);
468f7018c21STomi Valkeinen 	WRITE_WORD(BufferNumber, fb, REG_12);
469f7018c21STomi Valkeinen 	WRITE_WORD(0xffffffff, fb, REG_8);
470f7018c21STomi Valkeinen }
471f7018c21STomi Valkeinen 
472f7018c21STomi Valkeinen static void
SET_ATTR_SIZE(struct stifb_info * fb,int width,int height)473f7018c21STomi Valkeinen SET_ATTR_SIZE(struct stifb_info *fb, int width, int height)
474f7018c21STomi Valkeinen {
475f7018c21STomi Valkeinen 	/* REG_6 seems to have special values when run on a
476f7018c21STomi Valkeinen 	   RDI precisionbook parisc laptop (INTERNAL_EG_DX1024 or
477f7018c21STomi Valkeinen 	   INTERNAL_EG_X1024).  The values are:
478f7018c21STomi Valkeinen 		0x2f0: internal (LCD) & external display enabled
479f7018c21STomi Valkeinen 		0x2a0: external display only
480f7018c21STomi Valkeinen 		0x000: zero on standard artist graphic cards
481f7018c21STomi Valkeinen 	*/
482f7018c21STomi Valkeinen 	WRITE_WORD(0x00000000, fb, REG_6);
483f7018c21STomi Valkeinen 	WRITE_WORD((width<<16) | height, fb, REG_9);
484f7018c21STomi Valkeinen 	WRITE_WORD(0x05000000, fb, REG_6);
485f7018c21STomi Valkeinen 	WRITE_WORD(0x00040001, fb, REG_9);
486f7018c21STomi Valkeinen }
487f7018c21STomi Valkeinen 
488f7018c21STomi Valkeinen static void
FINISH_ATTR_ACCESS(struct stifb_info * fb)489f7018c21STomi Valkeinen FINISH_ATTR_ACCESS(struct stifb_info *fb)
490f7018c21STomi Valkeinen {
491f7018c21STomi Valkeinen 	SETUP_HW(fb);
492f7018c21STomi Valkeinen 	WRITE_WORD(0x00000000, fb, REG_12);
493f7018c21STomi Valkeinen }
494f7018c21STomi Valkeinen 
495f7018c21STomi Valkeinen static void
elkSetupPlanes(struct stifb_info * fb)496f7018c21STomi Valkeinen elkSetupPlanes(struct stifb_info *fb)
497f7018c21STomi Valkeinen {
498f7018c21STomi Valkeinen 	SETUP_RAMDAC(fb);
499f7018c21STomi Valkeinen 	SETUP_FB(fb);
500f7018c21STomi Valkeinen }
501f7018c21STomi Valkeinen 
502f7018c21STomi Valkeinen static void
ngleSetupAttrPlanes(struct stifb_info * fb,int BufferNumber)503f7018c21STomi Valkeinen ngleSetupAttrPlanes(struct stifb_info *fb, int BufferNumber)
504f7018c21STomi Valkeinen {
505f7018c21STomi Valkeinen 	SETUP_ATTR_ACCESS(fb, BufferNumber);
506f7018c21STomi Valkeinen 	SET_ATTR_SIZE(fb, fb->info.var.xres, fb->info.var.yres);
507f7018c21STomi Valkeinen 	FINISH_ATTR_ACCESS(fb);
508f7018c21STomi Valkeinen 	SETUP_FB(fb);
509f7018c21STomi Valkeinen }
510f7018c21STomi Valkeinen 
511f7018c21STomi Valkeinen 
512f7018c21STomi Valkeinen static void
rattlerSetupPlanes(struct stifb_info * fb)513f7018c21STomi Valkeinen rattlerSetupPlanes(struct stifb_info *fb)
514f7018c21STomi Valkeinen {
515f7018c21STomi Valkeinen 	int saved_id, y;
516f7018c21STomi Valkeinen 
517f7018c21STomi Valkeinen  	/* Write RAMDAC pixel read mask register so all overlay
518f7018c21STomi Valkeinen 	 * planes are display-enabled.  (CRX24 uses Bt462 pixel
519f7018c21STomi Valkeinen 	 * read mask register for overlay planes, not image planes).
520f7018c21STomi Valkeinen 	 */
521f7018c21STomi Valkeinen 	CRX24_SETUP_RAMDAC(fb);
522f7018c21STomi Valkeinen 
523f7018c21STomi Valkeinen 	/* change fb->id temporarily to fool SETUP_FB() */
524f7018c21STomi Valkeinen 	saved_id = fb->id;
525f7018c21STomi Valkeinen 	fb->id = CRX24_OVERLAY_PLANES;
526f7018c21STomi Valkeinen 	SETUP_FB(fb);
527f7018c21STomi Valkeinen 	fb->id = saved_id;
528f7018c21STomi Valkeinen 
529f7018c21STomi Valkeinen 	for (y = 0; y < fb->info.var.yres; ++y)
5308ce7ad78SHelge Deller 		fb_memset_io(fb->info.screen_base + y * fb->info.fix.line_length,
531f7018c21STomi Valkeinen 			     0xff, fb->info.var.xres * fb->info.var.bits_per_pixel/8);
532f7018c21STomi Valkeinen 
533f7018c21STomi Valkeinen 	CRX24_SET_OVLY_MASK(fb);
534f7018c21STomi Valkeinen 	SETUP_FB(fb);
535f7018c21STomi Valkeinen }
536f7018c21STomi Valkeinen 
537f7018c21STomi Valkeinen 
538f7018c21STomi Valkeinen #define HYPER_CMAP_TYPE				0
539f7018c21STomi Valkeinen #define NGLE_CMAP_INDEXED0_TYPE			0
540f7018c21STomi Valkeinen #define NGLE_CMAP_OVERLAY_TYPE			3
541f7018c21STomi Valkeinen 
542f7018c21STomi Valkeinen /* typedef of LUT (Colormap) BLT Control Register */
543f7018c21STomi Valkeinen typedef union	/* Note assumption that fields are packed left-to-right */
544f7018c21STomi Valkeinen {	u32 all;
545f7018c21STomi Valkeinen 	struct
546f7018c21STomi Valkeinen 	{
547f7018c21STomi Valkeinen 		unsigned enable              :  1;
548f7018c21STomi Valkeinen 		unsigned waitBlank           :  1;
549f7018c21STomi Valkeinen 		unsigned reserved1           :  4;
550f7018c21STomi Valkeinen 		unsigned lutOffset           : 10;   /* Within destination LUT */
551f7018c21STomi Valkeinen 		unsigned lutType             :  2;   /* Cursor, image, overlay */
552f7018c21STomi Valkeinen 		unsigned reserved2           :  4;
553f7018c21STomi Valkeinen 		unsigned length              : 10;
554f7018c21STomi Valkeinen 	} fields;
555f7018c21STomi Valkeinen } NgleLutBltCtl;
556f7018c21STomi Valkeinen 
557f7018c21STomi Valkeinen 
558f7018c21STomi Valkeinen #if 0
559f7018c21STomi Valkeinen static NgleLutBltCtl
560f7018c21STomi Valkeinen setNgleLutBltCtl(struct stifb_info *fb, int offsetWithinLut, int length)
561f7018c21STomi Valkeinen {
562f7018c21STomi Valkeinen 	NgleLutBltCtl lutBltCtl;
563f7018c21STomi Valkeinen 
564f7018c21STomi Valkeinen 	/* set enable, zero reserved fields */
565f7018c21STomi Valkeinen 	lutBltCtl.all           = 0x80000000;
566f7018c21STomi Valkeinen 	lutBltCtl.fields.length = length;
567f7018c21STomi Valkeinen 
568f7018c21STomi Valkeinen 	switch (fb->id)
569f7018c21STomi Valkeinen 	{
570f7018c21STomi Valkeinen 	case S9000_ID_A1439A:		/* CRX24 */
571f7018c21STomi Valkeinen 		if (fb->var.bits_per_pixel == 8) {
572f7018c21STomi Valkeinen 			lutBltCtl.fields.lutType = NGLE_CMAP_OVERLAY_TYPE;
573f7018c21STomi Valkeinen 			lutBltCtl.fields.lutOffset = 0;
574f7018c21STomi Valkeinen 		} else {
575f7018c21STomi Valkeinen 			lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE;
576f7018c21STomi Valkeinen 			lutBltCtl.fields.lutOffset = 0 * 256;
577f7018c21STomi Valkeinen 		}
578f7018c21STomi Valkeinen 		break;
579f7018c21STomi Valkeinen 
580f7018c21STomi Valkeinen 	case S9000_ID_ARTIST:
581f7018c21STomi Valkeinen 		lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE;
582f7018c21STomi Valkeinen 		lutBltCtl.fields.lutOffset = 0 * 256;
583f7018c21STomi Valkeinen 		break;
584f7018c21STomi Valkeinen 
585f7018c21STomi Valkeinen 	default:
586f7018c21STomi Valkeinen 		lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE;
587f7018c21STomi Valkeinen 		lutBltCtl.fields.lutOffset = 0;
588f7018c21STomi Valkeinen 		break;
589f7018c21STomi Valkeinen 	}
590f7018c21STomi Valkeinen 
591f7018c21STomi Valkeinen 	/* Offset points to start of LUT.  Adjust for within LUT */
592f7018c21STomi Valkeinen 	lutBltCtl.fields.lutOffset += offsetWithinLut;
593f7018c21STomi Valkeinen 
594f7018c21STomi Valkeinen 	return lutBltCtl;
595f7018c21STomi Valkeinen }
596f7018c21STomi Valkeinen #endif
597f7018c21STomi Valkeinen 
598f7018c21STomi Valkeinen static NgleLutBltCtl
setHyperLutBltCtl(struct stifb_info * fb,int offsetWithinLut,int length)599f7018c21STomi Valkeinen setHyperLutBltCtl(struct stifb_info *fb, int offsetWithinLut, int length)
600f7018c21STomi Valkeinen {
601f7018c21STomi Valkeinen 	NgleLutBltCtl lutBltCtl;
602f7018c21STomi Valkeinen 
603f7018c21STomi Valkeinen 	/* set enable, zero reserved fields */
604f7018c21STomi Valkeinen 	lutBltCtl.all = 0x80000000;
605f7018c21STomi Valkeinen 
606f7018c21STomi Valkeinen 	lutBltCtl.fields.length = length;
607f7018c21STomi Valkeinen 	lutBltCtl.fields.lutType = HYPER_CMAP_TYPE;
608f7018c21STomi Valkeinen 
609f7018c21STomi Valkeinen 	/* Expect lutIndex to be 0 or 1 for image cmaps, 2 or 3 for overlay cmaps */
610f7018c21STomi Valkeinen 	if (fb->info.var.bits_per_pixel == 8)
611f7018c21STomi Valkeinen 		lutBltCtl.fields.lutOffset = 2 * 256;
612f7018c21STomi Valkeinen 	else
613f7018c21STomi Valkeinen 		lutBltCtl.fields.lutOffset = 0 * 256;
614f7018c21STomi Valkeinen 
615f7018c21STomi Valkeinen 	/* Offset points to start of LUT.  Adjust for within LUT */
616f7018c21STomi Valkeinen 	lutBltCtl.fields.lutOffset += offsetWithinLut;
617f7018c21STomi Valkeinen 
618f7018c21STomi Valkeinen 	return lutBltCtl;
619f7018c21STomi Valkeinen }
620f7018c21STomi Valkeinen 
621f7018c21STomi Valkeinen 
hyperUndoITE(struct stifb_info * fb)622f7018c21STomi Valkeinen static void hyperUndoITE(struct stifb_info *fb)
623f7018c21STomi Valkeinen {
624f7018c21STomi Valkeinen 	int nFreeFifoSlots = 0;
625f7018c21STomi Valkeinen 	u32 fbAddr;
626f7018c21STomi Valkeinen 
627f7018c21STomi Valkeinen 	NGLE_LOCK(fb);
628f7018c21STomi Valkeinen 
629f7018c21STomi Valkeinen 	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 1);
630f7018c21STomi Valkeinen 	WRITE_WORD(0xffffffff, fb, REG_32);
631f7018c21STomi Valkeinen 
632f7018c21STomi Valkeinen 	/* Write overlay transparency mask so only entry 255 is transparent */
633f7018c21STomi Valkeinen 
634f7018c21STomi Valkeinen 	/* Hardware setup for full-depth write to "magic" location */
635f7018c21STomi Valkeinen 	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 7);
636f7018c21STomi Valkeinen 	NGLE_QUICK_SET_DST_BM_ACCESS(fb,
637f7018c21STomi Valkeinen 		BA(IndexedDcd, Otc04, Ots08, AddrLong,
638f7018c21STomi Valkeinen 		BAJustPoint(0), BINovly, BAIndexBase(0)));
639f7018c21STomi Valkeinen 	NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb,
640f7018c21STomi Valkeinen 		IBOvals(RopSrc, MaskAddrOffset(0),
641f7018c21STomi Valkeinen 		BitmapExtent08, StaticReg(0),
642f7018c21STomi Valkeinen 		DataDynamic, MaskOtc, BGx(0), FGx(0)));
643f7018c21STomi Valkeinen 
644f7018c21STomi Valkeinen 	/* Now prepare to write to the "magic" location */
645f7018c21STomi Valkeinen 	fbAddr = NGLE_LONG_FB_ADDRESS(0, 1532, 0);
646f7018c21STomi Valkeinen 	NGLE_BINC_SET_DSTADDR(fb, fbAddr);
647f7018c21STomi Valkeinen 	NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xffffff);
648f7018c21STomi Valkeinen 	NGLE_BINC_SET_DSTMASK(fb, 0xffffffff);
649f7018c21STomi Valkeinen 
650f7018c21STomi Valkeinen 	/* Finally, write a zero to clear the mask */
651f7018c21STomi Valkeinen 	NGLE_BINC_WRITE32(fb, 0);
652f7018c21STomi Valkeinen 
653f7018c21STomi Valkeinen 	NGLE_UNLOCK(fb);
654f7018c21STomi Valkeinen }
655f7018c21STomi Valkeinen 
656f7018c21STomi Valkeinen static void
ngleDepth8_ClearImagePlanes(struct stifb_info * fb)657f7018c21STomi Valkeinen ngleDepth8_ClearImagePlanes(struct stifb_info *fb)
658f7018c21STomi Valkeinen {
659f7018c21STomi Valkeinen 	/* FIXME! */
660f7018c21STomi Valkeinen }
661f7018c21STomi Valkeinen 
662f7018c21STomi Valkeinen static void
ngleDepth24_ClearImagePlanes(struct stifb_info * fb)663f7018c21STomi Valkeinen ngleDepth24_ClearImagePlanes(struct stifb_info *fb)
664f7018c21STomi Valkeinen {
665f7018c21STomi Valkeinen 	/* FIXME! */
666f7018c21STomi Valkeinen }
667f7018c21STomi Valkeinen 
668f7018c21STomi Valkeinen static void
ngleResetAttrPlanes(struct stifb_info * fb,unsigned int ctlPlaneReg)669f7018c21STomi Valkeinen ngleResetAttrPlanes(struct stifb_info *fb, unsigned int ctlPlaneReg)
670f7018c21STomi Valkeinen {
671f7018c21STomi Valkeinen 	int nFreeFifoSlots = 0;
672f7018c21STomi Valkeinen 	u32 packed_dst;
673f7018c21STomi Valkeinen 	u32 packed_len;
674f7018c21STomi Valkeinen 
675f7018c21STomi Valkeinen 	NGLE_LOCK(fb);
676f7018c21STomi Valkeinen 
677f7018c21STomi Valkeinen 	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 4);
678f7018c21STomi Valkeinen 	NGLE_QUICK_SET_DST_BM_ACCESS(fb,
679f7018c21STomi Valkeinen 				     BA(IndexedDcd, Otc32, OtsIndirect,
680f7018c21STomi Valkeinen 					AddrLong, BAJustPoint(0),
681f7018c21STomi Valkeinen 					BINattr, BAIndexBase(0)));
682f7018c21STomi Valkeinen 	NGLE_QUICK_SET_CTL_PLN_REG(fb, ctlPlaneReg);
683f7018c21STomi Valkeinen 	NGLE_SET_TRANSFERDATA(fb, 0xffffffff);
684f7018c21STomi Valkeinen 
685f7018c21STomi Valkeinen 	NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb,
686f7018c21STomi Valkeinen 				       IBOvals(RopSrc, MaskAddrOffset(0),
687f7018c21STomi Valkeinen 					       BitmapExtent08, StaticReg(1),
688f7018c21STomi Valkeinen 					       DataDynamic, MaskOtc,
689f7018c21STomi Valkeinen 					       BGx(0), FGx(0)));
690f7018c21STomi Valkeinen 	packed_dst = 0;
691f7018c21STomi Valkeinen 	packed_len = (fb->info.var.xres << 16) | fb->info.var.yres;
692f7018c21STomi Valkeinen 	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 2);
693f7018c21STomi Valkeinen 	NGLE_SET_DSTXY(fb, packed_dst);
694f7018c21STomi Valkeinen 	SET_LENXY_START_RECFILL(fb, packed_len);
695f7018c21STomi Valkeinen 
696f7018c21STomi Valkeinen 	/*
697f7018c21STomi Valkeinen 	 * In order to work around an ELK hardware problem (Buffy doesn't
698f7018c21STomi Valkeinen 	 * always flush it's buffers when writing to the attribute
699f7018c21STomi Valkeinen 	 * planes), at least 4 pixels must be written to the attribute
700f7018c21STomi Valkeinen 	 * planes starting at (X == 1280) and (Y != to the last Y written
701f7018c21STomi Valkeinen 	 * by BIF):
702f7018c21STomi Valkeinen 	 */
703f7018c21STomi Valkeinen 
704f7018c21STomi Valkeinen 	if (fb->id == S9000_ID_A1659A) {   /* ELK_DEVICE_ID */
705f7018c21STomi Valkeinen 		/* It's safe to use scanline zero: */
706f7018c21STomi Valkeinen 		packed_dst = (1280 << 16);
707f7018c21STomi Valkeinen 		GET_FIFO_SLOTS(fb, nFreeFifoSlots, 2);
708f7018c21STomi Valkeinen 		NGLE_SET_DSTXY(fb, packed_dst);
709f7018c21STomi Valkeinen 		packed_len = (4 << 16) | 1;
710f7018c21STomi Valkeinen 		SET_LENXY_START_RECFILL(fb, packed_len);
711f7018c21STomi Valkeinen 	}   /* ELK Hardware Kludge */
712f7018c21STomi Valkeinen 
713f7018c21STomi Valkeinen 	/**** Finally, set the Control Plane Register back to zero: ****/
714f7018c21STomi Valkeinen 	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 1);
715f7018c21STomi Valkeinen 	NGLE_QUICK_SET_CTL_PLN_REG(fb, 0);
716f7018c21STomi Valkeinen 
717f7018c21STomi Valkeinen 	NGLE_UNLOCK(fb);
718f7018c21STomi Valkeinen }
719f7018c21STomi Valkeinen 
720f7018c21STomi Valkeinen static void
ngleClearOverlayPlanes(struct stifb_info * fb,int mask,int data)721f7018c21STomi Valkeinen ngleClearOverlayPlanes(struct stifb_info *fb, int mask, int data)
722f7018c21STomi Valkeinen {
723f7018c21STomi Valkeinen 	int nFreeFifoSlots = 0;
724f7018c21STomi Valkeinen 	u32 packed_dst;
725f7018c21STomi Valkeinen 	u32 packed_len;
726f7018c21STomi Valkeinen 
727f7018c21STomi Valkeinen 	NGLE_LOCK(fb);
728f7018c21STomi Valkeinen 
729f7018c21STomi Valkeinen 	/* Hardware setup */
730f7018c21STomi Valkeinen 	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 8);
731f7018c21STomi Valkeinen 	NGLE_QUICK_SET_DST_BM_ACCESS(fb,
732f7018c21STomi Valkeinen 				     BA(IndexedDcd, Otc04, Ots08, AddrLong,
733f7018c21STomi Valkeinen 					BAJustPoint(0), BINovly, BAIndexBase(0)));
734f7018c21STomi Valkeinen 
735f7018c21STomi Valkeinen         NGLE_SET_TRANSFERDATA(fb, 0xffffffff);  /* Write foreground color */
736f7018c21STomi Valkeinen 
737f7018c21STomi Valkeinen         NGLE_REALLY_SET_IMAGE_FG_COLOR(fb, data);
738f7018c21STomi Valkeinen         NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, mask);
739f7018c21STomi Valkeinen 
740f7018c21STomi Valkeinen         packed_dst = 0;
741f7018c21STomi Valkeinen         packed_len = (fb->info.var.xres << 16) | fb->info.var.yres;
742f7018c21STomi Valkeinen         NGLE_SET_DSTXY(fb, packed_dst);
743f7018c21STomi Valkeinen 
744f7018c21STomi Valkeinen 	/* Write zeroes to overlay planes */
745f7018c21STomi Valkeinen 	NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb,
746f7018c21STomi Valkeinen 				       IBOvals(RopSrc, MaskAddrOffset(0),
747f7018c21STomi Valkeinen 					       BitmapExtent08, StaticReg(0),
748f7018c21STomi Valkeinen 					       DataDynamic, MaskOtc, BGx(0), FGx(0)));
749f7018c21STomi Valkeinen 
750f7018c21STomi Valkeinen         SET_LENXY_START_RECFILL(fb, packed_len);
751f7018c21STomi Valkeinen 
752f7018c21STomi Valkeinen 	NGLE_UNLOCK(fb);
753f7018c21STomi Valkeinen }
754f7018c21STomi Valkeinen 
755f7018c21STomi Valkeinen static void
hyperResetPlanes(struct stifb_info * fb,int enable)756f7018c21STomi Valkeinen hyperResetPlanes(struct stifb_info *fb, int enable)
757f7018c21STomi Valkeinen {
758f7018c21STomi Valkeinen 	unsigned int controlPlaneReg;
759f7018c21STomi Valkeinen 
760f7018c21STomi Valkeinen 	NGLE_LOCK(fb);
761f7018c21STomi Valkeinen 
762f7018c21STomi Valkeinen 	if (IS_24_DEVICE(fb))
763f7018c21STomi Valkeinen 		if (fb->info.var.bits_per_pixel == 32)
764f7018c21STomi Valkeinen 			controlPlaneReg = 0x04000F00;
765f7018c21STomi Valkeinen 		else
766f7018c21STomi Valkeinen 			controlPlaneReg = 0x00000F00;   /* 0x00000800 should be enough, but lets clear all 4 bits */
767f7018c21STomi Valkeinen 	else
768f7018c21STomi Valkeinen 		controlPlaneReg = 0x00000F00; /* 0x00000100 should be enough, but lets clear all 4 bits */
769f7018c21STomi Valkeinen 
770f7018c21STomi Valkeinen 	switch (enable) {
771f7018c21STomi Valkeinen 	case ENABLE:
772f7018c21STomi Valkeinen 		/* clear screen */
773f7018c21STomi Valkeinen 		if (IS_24_DEVICE(fb))
774f7018c21STomi Valkeinen 			ngleDepth24_ClearImagePlanes(fb);
775f7018c21STomi Valkeinen 		else
776f7018c21STomi Valkeinen 			ngleDepth8_ClearImagePlanes(fb);
777f7018c21STomi Valkeinen 
778f7018c21STomi Valkeinen 		/* Paint attribute planes for default case.
779f7018c21STomi Valkeinen 		 * On Hyperdrive, this means all windows using overlay cmap 0. */
780f7018c21STomi Valkeinen 		ngleResetAttrPlanes(fb, controlPlaneReg);
781f7018c21STomi Valkeinen 
782f7018c21STomi Valkeinen 		/* clear overlay planes */
783f7018c21STomi Valkeinen 	        ngleClearOverlayPlanes(fb, 0xff, 255);
784f7018c21STomi Valkeinen 
785f7018c21STomi Valkeinen 		/**************************************************
786f7018c21STomi Valkeinen 		 ** Also need to counteract ITE settings
787f7018c21STomi Valkeinen 		 **************************************************/
788f7018c21STomi Valkeinen 		hyperUndoITE(fb);
789f7018c21STomi Valkeinen 		break;
790f7018c21STomi Valkeinen 
791f7018c21STomi Valkeinen 	case DISABLE:
792f7018c21STomi Valkeinen 		/* clear screen */
793f7018c21STomi Valkeinen 		if (IS_24_DEVICE(fb))
794f7018c21STomi Valkeinen 			ngleDepth24_ClearImagePlanes(fb);
795f7018c21STomi Valkeinen 		else
796f7018c21STomi Valkeinen 			ngleDepth8_ClearImagePlanes(fb);
797f7018c21STomi Valkeinen 		ngleResetAttrPlanes(fb, controlPlaneReg);
798f7018c21STomi Valkeinen 		ngleClearOverlayPlanes(fb, 0xff, 0);
799f7018c21STomi Valkeinen 		break;
800f7018c21STomi Valkeinen 
801f7018c21STomi Valkeinen 	case -1:	/* RESET */
802f7018c21STomi Valkeinen 		hyperUndoITE(fb);
803f7018c21STomi Valkeinen 		ngleResetAttrPlanes(fb, controlPlaneReg);
804f7018c21STomi Valkeinen 		break;
805f7018c21STomi Valkeinen     	}
806f7018c21STomi Valkeinen 
807f7018c21STomi Valkeinen 	NGLE_UNLOCK(fb);
808f7018c21STomi Valkeinen }
809f7018c21STomi Valkeinen 
810f7018c21STomi Valkeinen /* Return pointer to in-memory structure holding ELK device-dependent ROM values. */
811f7018c21STomi Valkeinen 
812f7018c21STomi Valkeinen static void
ngleGetDeviceRomData(struct stifb_info * fb)813f7018c21STomi Valkeinen ngleGetDeviceRomData(struct stifb_info *fb)
814f7018c21STomi Valkeinen {
815f7018c21STomi Valkeinen #if 0
816f7018c21STomi Valkeinen XXX: FIXME: !!!
817f7018c21STomi Valkeinen 	int	*pBytePerLongDevDepData;/* data byte == LSB */
818f7018c21STomi Valkeinen 	int 	*pRomTable;
819f7018c21STomi Valkeinen 	NgleDevRomData	*pPackedDevRomData;
820f7018c21STomi Valkeinen 	int	sizePackedDevRomData = sizeof(*pPackedDevRomData);
821f7018c21STomi Valkeinen 	char	*pCard8;
822f7018c21STomi Valkeinen 	int	i;
823f7018c21STomi Valkeinen 	char	*mapOrigin = NULL;
824f7018c21STomi Valkeinen 
825f7018c21STomi Valkeinen 	int romTableIdx;
826f7018c21STomi Valkeinen 
827f7018c21STomi Valkeinen 	pPackedDevRomData = fb->ngle_rom;
828f7018c21STomi Valkeinen 
829f7018c21STomi Valkeinen 	SETUP_HW(fb);
830f7018c21STomi Valkeinen 	if (fb->id == S9000_ID_ARTIST) {
831f7018c21STomi Valkeinen 		pPackedDevRomData->cursor_pipeline_delay = 4;
832f7018c21STomi Valkeinen 		pPackedDevRomData->video_interleaves     = 4;
833f7018c21STomi Valkeinen 	} else {
834f7018c21STomi Valkeinen 		/* Get pointer to unpacked byte/long data in ROM */
835f7018c21STomi Valkeinen 		pBytePerLongDevDepData = fb->sti->regions[NGLEDEVDEPROM_CRT_REGION];
836f7018c21STomi Valkeinen 
837f7018c21STomi Valkeinen 		/* Tomcat supports several resolutions: 1280x1024, 1024x768, 640x480 */
838f7018c21STomi Valkeinen 		if (fb->id == S9000_ID_TOMCAT)
839f7018c21STomi Valkeinen 	{
840f7018c21STomi Valkeinen 	    /*  jump to the correct ROM table  */
841f7018c21STomi Valkeinen 	    GET_ROMTABLE_INDEX(romTableIdx);
842f7018c21STomi Valkeinen 	    while  (romTableIdx > 0)
843f7018c21STomi Valkeinen 	    {
844f7018c21STomi Valkeinen 		pCard8 = (Card8 *) pPackedDevRomData;
845f7018c21STomi Valkeinen 		pRomTable = pBytePerLongDevDepData;
846f7018c21STomi Valkeinen 		/* Pack every fourth byte from ROM into structure */
847f7018c21STomi Valkeinen 		for (i = 0; i < sizePackedDevRomData; i++)
848f7018c21STomi Valkeinen 		{
849f7018c21STomi Valkeinen 		    *pCard8++ = (Card8) (*pRomTable++);
850f7018c21STomi Valkeinen 		}
851f7018c21STomi Valkeinen 
852f7018c21STomi Valkeinen 		pBytePerLongDevDepData = (Card32 *)
853f7018c21STomi Valkeinen 			((Card8 *) pBytePerLongDevDepData +
854f7018c21STomi Valkeinen 			       pPackedDevRomData->sizeof_ngle_data);
855f7018c21STomi Valkeinen 
856f7018c21STomi Valkeinen 		romTableIdx--;
857f7018c21STomi Valkeinen 	    }
858f7018c21STomi Valkeinen 	}
859f7018c21STomi Valkeinen 
860f7018c21STomi Valkeinen 	pCard8 = (Card8 *) pPackedDevRomData;
861f7018c21STomi Valkeinen 
862f7018c21STomi Valkeinen 	/* Pack every fourth byte from ROM into structure */
863f7018c21STomi Valkeinen 	for (i = 0; i < sizePackedDevRomData; i++)
864f7018c21STomi Valkeinen 	{
865f7018c21STomi Valkeinen 	    *pCard8++ = (Card8) (*pBytePerLongDevDepData++);
866f7018c21STomi Valkeinen 	}
867f7018c21STomi Valkeinen     }
868f7018c21STomi Valkeinen 
869f7018c21STomi Valkeinen     SETUP_FB(fb);
870f7018c21STomi Valkeinen #endif
871f7018c21STomi Valkeinen }
872f7018c21STomi Valkeinen 
873f7018c21STomi Valkeinen 
874f7018c21STomi Valkeinen #define HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES	4
875f7018c21STomi Valkeinen #define HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE	8
876f7018c21STomi Valkeinen #define HYPERBOWL_MODE01_8_24_LUT0_OPAQUE_LUT1_OPAQUE		10
877f7018c21STomi Valkeinen #define HYPERBOWL_MODE2_8_24					15
878f7018c21STomi Valkeinen 
879f7018c21STomi Valkeinen /* HCRX specific boot-time initialization */
880f7018c21STomi Valkeinen static void __init
SETUP_HCRX(struct stifb_info * fb)881f7018c21STomi Valkeinen SETUP_HCRX(struct stifb_info *fb)
882f7018c21STomi Valkeinen {
883f7018c21STomi Valkeinen 	int	hyperbowl;
884f7018c21STomi Valkeinen         int	nFreeFifoSlots = 0;
885f7018c21STomi Valkeinen 
886f7018c21STomi Valkeinen 	if (fb->id != S9000_ID_HCRX)
887f7018c21STomi Valkeinen 		return;
888f7018c21STomi Valkeinen 
889f7018c21STomi Valkeinen 	/* Initialize Hyperbowl registers */
890f7018c21STomi Valkeinen 	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 7);
891f7018c21STomi Valkeinen 
892f7018c21STomi Valkeinen 	if (IS_24_DEVICE(fb)) {
893f7018c21STomi Valkeinen 		hyperbowl = (fb->info.var.bits_per_pixel == 32) ?
894f7018c21STomi Valkeinen 			HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE :
895f7018c21STomi Valkeinen 			HYPERBOWL_MODE01_8_24_LUT0_OPAQUE_LUT1_OPAQUE;
896f7018c21STomi Valkeinen 
897f7018c21STomi Valkeinen 		/* First write to Hyperbowl must happen twice (bug) */
898f7018c21STomi Valkeinen 		WRITE_WORD(hyperbowl, fb, REG_40);
899f7018c21STomi Valkeinen 		WRITE_WORD(hyperbowl, fb, REG_40);
900f7018c21STomi Valkeinen 
901f7018c21STomi Valkeinen 		WRITE_WORD(HYPERBOWL_MODE2_8_24, fb, REG_39);
902f7018c21STomi Valkeinen 
903f7018c21STomi Valkeinen 		WRITE_WORD(0x014c0148, fb, REG_42); /* Set lut 0 to be the direct color */
904f7018c21STomi Valkeinen 		WRITE_WORD(0x404c4048, fb, REG_43);
905f7018c21STomi Valkeinen 		WRITE_WORD(0x034c0348, fb, REG_44);
906f7018c21STomi Valkeinen 		WRITE_WORD(0x444c4448, fb, REG_45);
907f7018c21STomi Valkeinen 	} else {
908f7018c21STomi Valkeinen 		hyperbowl = HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES;
909f7018c21STomi Valkeinen 
910f7018c21STomi Valkeinen 		/* First write to Hyperbowl must happen twice (bug) */
911f7018c21STomi Valkeinen 		WRITE_WORD(hyperbowl, fb, REG_40);
912f7018c21STomi Valkeinen 		WRITE_WORD(hyperbowl, fb, REG_40);
913f7018c21STomi Valkeinen 
914f7018c21STomi Valkeinen 		WRITE_WORD(0x00000000, fb, REG_42);
915f7018c21STomi Valkeinen 		WRITE_WORD(0x00000000, fb, REG_43);
916f7018c21STomi Valkeinen 		WRITE_WORD(0x00000000, fb, REG_44);
917f7018c21STomi Valkeinen 		WRITE_WORD(0x444c4048, fb, REG_45);
918f7018c21STomi Valkeinen 	}
919f7018c21STomi Valkeinen }
920f7018c21STomi Valkeinen 
921f7018c21STomi Valkeinen 
922f7018c21STomi Valkeinen /* ------------------- driver specific functions --------------------------- */
923f7018c21STomi Valkeinen 
924f7018c21STomi Valkeinen static int
stifb_check_var(struct fb_var_screeninfo * var,struct fb_info * info)925203873a5SHelge Deller stifb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
926203873a5SHelge Deller {
927203873a5SHelge Deller 	struct stifb_info *fb = container_of(info, struct stifb_info, info);
928203873a5SHelge Deller 
929203873a5SHelge Deller 	if (var->xres != fb->info.var.xres ||
930203873a5SHelge Deller 	    var->yres != fb->info.var.yres ||
931203873a5SHelge Deller 	    var->bits_per_pixel != fb->info.var.bits_per_pixel)
932203873a5SHelge Deller 		return -EINVAL;
933203873a5SHelge Deller 
934203873a5SHelge Deller 	var->xres_virtual = var->xres;
935203873a5SHelge Deller 	var->yres_virtual = var->yres;
936203873a5SHelge Deller 	var->xoffset = 0;
937203873a5SHelge Deller 	var->yoffset = 0;
938203873a5SHelge Deller 	var->grayscale = fb->info.var.grayscale;
939203873a5SHelge Deller 	var->red.length = fb->info.var.red.length;
940203873a5SHelge Deller 	var->green.length = fb->info.var.green.length;
941203873a5SHelge Deller 	var->blue.length = fb->info.var.blue.length;
942203873a5SHelge Deller 
943203873a5SHelge Deller 	return 0;
944203873a5SHelge Deller }
945203873a5SHelge Deller 
946203873a5SHelge Deller static int
stifb_setcolreg(u_int regno,u_int red,u_int green,u_int blue,u_int transp,struct fb_info * info)947f7018c21STomi Valkeinen stifb_setcolreg(u_int regno, u_int red, u_int green,
948f7018c21STomi Valkeinen 	      u_int blue, u_int transp, struct fb_info *info)
949f7018c21STomi Valkeinen {
9501f17a0faSFabian Frederick 	struct stifb_info *fb = container_of(info, struct stifb_info, info);
951f7018c21STomi Valkeinen 	u32 color;
952f7018c21STomi Valkeinen 
953f7018c21STomi Valkeinen 	if (regno >= NR_PALETTE)
954f7018c21STomi Valkeinen 		return 1;
955f7018c21STomi Valkeinen 
956f7018c21STomi Valkeinen 	red   >>= 8;
957f7018c21STomi Valkeinen 	green >>= 8;
958f7018c21STomi Valkeinen 	blue  >>= 8;
959f7018c21STomi Valkeinen 
960f7018c21STomi Valkeinen 	DEBUG_OFF();
961f7018c21STomi Valkeinen 
962f7018c21STomi Valkeinen 	START_IMAGE_COLORMAP_ACCESS(fb);
963f7018c21STomi Valkeinen 
964f7018c21STomi Valkeinen 	if (unlikely(fb->info.var.grayscale)) {
965f7018c21STomi Valkeinen 		/* gray = 0.30*R + 0.59*G + 0.11*B */
966f7018c21STomi Valkeinen 		color = ((red * 77) +
967f7018c21STomi Valkeinen 			 (green * 151) +
968f7018c21STomi Valkeinen 			 (blue * 28)) >> 8;
969f7018c21STomi Valkeinen 	} else {
970f7018c21STomi Valkeinen 		color = ((red << 16) |
971f7018c21STomi Valkeinen 			 (green << 8) |
972f7018c21STomi Valkeinen 			 (blue));
973f7018c21STomi Valkeinen 	}
974f7018c21STomi Valkeinen 
975f7018c21STomi Valkeinen 	if (fb->info.fix.visual == FB_VISUAL_DIRECTCOLOR) {
976f7018c21STomi Valkeinen 		struct fb_var_screeninfo *var = &fb->info.var;
977f7018c21STomi Valkeinen 		if (regno < 16)
978f7018c21STomi Valkeinen 			((u32 *)fb->info.pseudo_palette)[regno] =
979f7018c21STomi Valkeinen 				regno << var->red.offset |
980f7018c21STomi Valkeinen 				regno << var->green.offset |
981f7018c21STomi Valkeinen 				regno << var->blue.offset;
982f7018c21STomi Valkeinen 	}
983f7018c21STomi Valkeinen 
984f7018c21STomi Valkeinen 	WRITE_IMAGE_COLOR(fb, regno, color);
985f7018c21STomi Valkeinen 
986f7018c21STomi Valkeinen 	if (fb->id == S9000_ID_HCRX) {
987f7018c21STomi Valkeinen 		NgleLutBltCtl lutBltCtl;
988f7018c21STomi Valkeinen 
989f7018c21STomi Valkeinen 		lutBltCtl = setHyperLutBltCtl(fb,
990f7018c21STomi Valkeinen 				0,	/* Offset w/i LUT */
991f7018c21STomi Valkeinen 				256);	/* Load entire LUT */
992f7018c21STomi Valkeinen 		NGLE_BINC_SET_SRCADDR(fb,
993f7018c21STomi Valkeinen 				NGLE_LONG_FB_ADDRESS(0, 0x100, 0));
994f7018c21STomi Valkeinen 				/* 0x100 is same as used in WRITE_IMAGE_COLOR() */
995f7018c21STomi Valkeinen 		START_COLORMAPLOAD(fb, lutBltCtl.all);
996f7018c21STomi Valkeinen 		SETUP_FB(fb);
997f7018c21STomi Valkeinen 	} else {
998f7018c21STomi Valkeinen 		/* cleanup colormap hardware */
999f7018c21STomi Valkeinen 		FINISH_IMAGE_COLORMAP_ACCESS(fb);
1000f7018c21STomi Valkeinen 	}
1001f7018c21STomi Valkeinen 
1002f7018c21STomi Valkeinen 	DEBUG_ON();
1003f7018c21STomi Valkeinen 
1004f7018c21STomi Valkeinen 	return 0;
1005f7018c21STomi Valkeinen }
1006f7018c21STomi Valkeinen 
1007f7018c21STomi Valkeinen static int
stifb_blank(int blank_mode,struct fb_info * info)1008f7018c21STomi Valkeinen stifb_blank(int blank_mode, struct fb_info *info)
1009f7018c21STomi Valkeinen {
10101f17a0faSFabian Frederick 	struct stifb_info *fb = container_of(info, struct stifb_info, info);
1011f7018c21STomi Valkeinen 	int enable = (blank_mode == 0) ? ENABLE : DISABLE;
1012f7018c21STomi Valkeinen 
1013f7018c21STomi Valkeinen 	switch (fb->id) {
1014f7018c21STomi Valkeinen 	case S9000_ID_A1439A:
1015f7018c21STomi Valkeinen 		CRX24_ENABLE_DISABLE_DISPLAY(fb, enable);
1016f7018c21STomi Valkeinen 		break;
1017f7018c21STomi Valkeinen 	case CRT_ID_VISUALIZE_EG:
1018f7018c21STomi Valkeinen 	case S9000_ID_ARTIST:
1019f7018c21STomi Valkeinen 		ARTIST_ENABLE_DISABLE_DISPLAY(fb, enable);
1020f7018c21STomi Valkeinen 		break;
1021f7018c21STomi Valkeinen 	case S9000_ID_HCRX:
1022f7018c21STomi Valkeinen 		HYPER_ENABLE_DISABLE_DISPLAY(fb, enable);
1023f7018c21STomi Valkeinen 		break;
1024df561f66SGustavo A. R. Silva 	case S9000_ID_A1659A:
1025f7018c21STomi Valkeinen 	case S9000_ID_TIMBER:
1026f7018c21STomi Valkeinen 	case CRX24_OVERLAY_PLANES:
1027f7018c21STomi Valkeinen 	default:
1028f7018c21STomi Valkeinen 		ENABLE_DISABLE_DISPLAY(fb, enable);
1029f7018c21STomi Valkeinen 		break;
1030f7018c21STomi Valkeinen 	}
1031f7018c21STomi Valkeinen 
1032f7018c21STomi Valkeinen 	SETUP_FB(fb);
1033f7018c21STomi Valkeinen 	return 0;
1034f7018c21STomi Valkeinen }
1035f7018c21STomi Valkeinen 
1036cb908ed3SAlex Ivanov static void
stifb_copyarea(struct fb_info * info,const struct fb_copyarea * area)1037cb908ed3SAlex Ivanov stifb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
1038cb908ed3SAlex Ivanov {
1039cb908ed3SAlex Ivanov 	struct stifb_info *fb = container_of(info, struct stifb_info, info);
1040cb908ed3SAlex Ivanov 
1041cb908ed3SAlex Ivanov 	SETUP_COPYAREA(fb);
1042cb908ed3SAlex Ivanov 
1043cb908ed3SAlex Ivanov 	SETUP_HW(fb);
1044cb908ed3SAlex Ivanov 	if (fb->info.var.bits_per_pixel == 32) {
1045cb908ed3SAlex Ivanov 		WRITE_WORD(0xBBA0A000, fb, REG_10);
1046cb908ed3SAlex Ivanov 
1047cb908ed3SAlex Ivanov 		NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xffffffff);
1048cb908ed3SAlex Ivanov 	} else {
1049cb908ed3SAlex Ivanov 		WRITE_WORD(fb->id == S9000_ID_HCRX ? 0x13a02000 : 0x13a01000, fb, REG_10);
1050cb908ed3SAlex Ivanov 
1051cb908ed3SAlex Ivanov 		NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xff);
1052cb908ed3SAlex Ivanov 	}
1053cb908ed3SAlex Ivanov 
1054cb908ed3SAlex Ivanov 	NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb,
1055cb908ed3SAlex Ivanov 		IBOvals(RopSrc, MaskAddrOffset(0),
1056cb908ed3SAlex Ivanov 		BitmapExtent08, StaticReg(1),
1057cb908ed3SAlex Ivanov 		DataDynamic, MaskOtc, BGx(0), FGx(0)));
1058cb908ed3SAlex Ivanov 
1059cb908ed3SAlex Ivanov 	WRITE_WORD(((area->sx << 16) | area->sy), fb, REG_24);
1060cb908ed3SAlex Ivanov 	WRITE_WORD(((area->width << 16) | area->height), fb, REG_7);
1061cb908ed3SAlex Ivanov 	WRITE_WORD(((area->dx << 16) | area->dy), fb, REG_25);
1062cb908ed3SAlex Ivanov 
1063cb908ed3SAlex Ivanov 	SETUP_FB(fb);
1064cb908ed3SAlex Ivanov }
1065cb908ed3SAlex Ivanov 
10669c379c65SHelge Deller #define ARTIST_VRAM_SIZE			0x000804
10679c379c65SHelge Deller #define ARTIST_VRAM_SRC				0x000808
10689c379c65SHelge Deller #define ARTIST_VRAM_SIZE_TRIGGER_WINFILL	0x000a04
10699c379c65SHelge Deller #define ARTIST_VRAM_DEST_TRIGGER_BLOCKMOVE	0x000b00
10709c379c65SHelge Deller #define ARTIST_SRC_BM_ACCESS			0x018008
10719c379c65SHelge Deller #define ARTIST_FGCOLOR				0x018010
10729c379c65SHelge Deller #define ARTIST_BGCOLOR				0x018014
10739c379c65SHelge Deller #define ARTIST_BITMAP_OP			0x01801c
10749c379c65SHelge Deller 
10759c379c65SHelge Deller static void
stifb_fillrect(struct fb_info * info,const struct fb_fillrect * rect)10769c379c65SHelge Deller stifb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
10779c379c65SHelge Deller {
10789c379c65SHelge Deller 	struct stifb_info *fb = container_of(info, struct stifb_info, info);
10799c379c65SHelge Deller 
1080776d875fSHelge Deller 	if (rect->rop != ROP_COPY ||
1081776d875fSHelge Deller 	    (fb->id == S9000_ID_HCRX && fb->info.var.bits_per_pixel == 32))
10829c379c65SHelge Deller 		return cfb_fillrect(info, rect);
10839c379c65SHelge Deller 
10849c379c65SHelge Deller 	SETUP_HW(fb);
10859c379c65SHelge Deller 
10869c379c65SHelge Deller 	if (fb->info.var.bits_per_pixel == 32) {
10879c379c65SHelge Deller 		WRITE_WORD(0xBBA0A000, fb, REG_10);
10889c379c65SHelge Deller 
10899c379c65SHelge Deller 		NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xffffffff);
10909c379c65SHelge Deller 	} else {
10919c379c65SHelge Deller 		WRITE_WORD(fb->id == S9000_ID_HCRX ? 0x13a02000 : 0x13a01000, fb, REG_10);
10929c379c65SHelge Deller 
10939c379c65SHelge Deller 		NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xff);
10949c379c65SHelge Deller 	}
10959c379c65SHelge Deller 
10969c379c65SHelge Deller 	WRITE_WORD(0x03000300, fb, ARTIST_BITMAP_OP);
10979c379c65SHelge Deller 	WRITE_WORD(0x2ea01000, fb, ARTIST_SRC_BM_ACCESS);
10989c379c65SHelge Deller 	NGLE_QUICK_SET_DST_BM_ACCESS(fb, 0x2ea01000);
10999c379c65SHelge Deller 	NGLE_REALLY_SET_IMAGE_FG_COLOR(fb, rect->color);
11009c379c65SHelge Deller 	WRITE_WORD(0, fb, ARTIST_BGCOLOR);
11019c379c65SHelge Deller 
11029c379c65SHelge Deller 	NGLE_SET_DSTXY(fb, (rect->dx << 16) | (rect->dy));
11039c379c65SHelge Deller 	SET_LENXY_START_RECFILL(fb, (rect->width << 16) | (rect->height));
11049c379c65SHelge Deller 
11059c379c65SHelge Deller 	SETUP_FB(fb);
11069c379c65SHelge Deller }
11079c379c65SHelge Deller 
1108f7018c21STomi Valkeinen static void __init
stifb_init_display(struct stifb_info * fb)1109f7018c21STomi Valkeinen stifb_init_display(struct stifb_info *fb)
1110f7018c21STomi Valkeinen {
1111f7018c21STomi Valkeinen 	int id = fb->id;
1112f7018c21STomi Valkeinen 
1113f7018c21STomi Valkeinen 	SETUP_FB(fb);
1114f7018c21STomi Valkeinen 
1115f7018c21STomi Valkeinen 	/* HCRX specific initialization */
1116f7018c21STomi Valkeinen 	SETUP_HCRX(fb);
1117f7018c21STomi Valkeinen 
1118f7018c21STomi Valkeinen 	/*
1119f7018c21STomi Valkeinen 	if (id == S9000_ID_HCRX)
1120f7018c21STomi Valkeinen 		hyperInitSprite(fb);
1121f7018c21STomi Valkeinen 	else
1122f7018c21STomi Valkeinen 		ngleInitSprite(fb);
1123f7018c21STomi Valkeinen 	*/
1124f7018c21STomi Valkeinen 
1125f7018c21STomi Valkeinen 	/* Initialize the image planes. */
1126f7018c21STomi Valkeinen         switch (id) {
1127f7018c21STomi Valkeinen 	 case S9000_ID_HCRX:
1128f7018c21STomi Valkeinen 	    hyperResetPlanes(fb, ENABLE);
1129f7018c21STomi Valkeinen 	    break;
1130f7018c21STomi Valkeinen 	 case S9000_ID_A1439A:
1131f7018c21STomi Valkeinen 	    rattlerSetupPlanes(fb);
1132f7018c21STomi Valkeinen 	    break;
1133f7018c21STomi Valkeinen 	 case S9000_ID_A1659A:
1134f7018c21STomi Valkeinen 	 case S9000_ID_ARTIST:
1135f7018c21STomi Valkeinen 	 case CRT_ID_VISUALIZE_EG:
1136f7018c21STomi Valkeinen 	    elkSetupPlanes(fb);
1137f7018c21STomi Valkeinen 	    break;
1138f7018c21STomi Valkeinen 	}
1139f7018c21STomi Valkeinen 
1140f7018c21STomi Valkeinen 	/* Clear attribute planes on non HCRX devices. */
1141f7018c21STomi Valkeinen         switch (id) {
1142f7018c21STomi Valkeinen 	 case S9000_ID_A1659A:
1143f7018c21STomi Valkeinen 	 case S9000_ID_A1439A:
1144f7018c21STomi Valkeinen 	    if (fb->info.var.bits_per_pixel == 32)
1145f7018c21STomi Valkeinen 		ngleSetupAttrPlanes(fb, BUFF1_CMAP3);
1146f7018c21STomi Valkeinen 	    else {
1147f7018c21STomi Valkeinen 		ngleSetupAttrPlanes(fb, BUFF1_CMAP0);
1148f7018c21STomi Valkeinen 	    }
1149f7018c21STomi Valkeinen 	    if (id == S9000_ID_A1439A)
1150f7018c21STomi Valkeinen 		ngleClearOverlayPlanes(fb, 0xff, 0);
1151f7018c21STomi Valkeinen 	    break;
1152f7018c21STomi Valkeinen 	 case S9000_ID_ARTIST:
1153f7018c21STomi Valkeinen 	 case CRT_ID_VISUALIZE_EG:
1154f7018c21STomi Valkeinen 	    if (fb->info.var.bits_per_pixel == 32)
1155f7018c21STomi Valkeinen 		ngleSetupAttrPlanes(fb, BUFF1_CMAP3);
1156f7018c21STomi Valkeinen 	    else {
1157f7018c21STomi Valkeinen 		ngleSetupAttrPlanes(fb, ARTIST_CMAP0);
1158f7018c21STomi Valkeinen 	    }
1159f7018c21STomi Valkeinen 	    break;
1160f7018c21STomi Valkeinen 	}
1161f7018c21STomi Valkeinen 	stifb_blank(0, (struct fb_info *)fb);	/* 0=enable screen */
1162f7018c21STomi Valkeinen 
1163f7018c21STomi Valkeinen 	SETUP_FB(fb);
1164f7018c21STomi Valkeinen }
1165f7018c21STomi Valkeinen 
1166f7018c21STomi Valkeinen /* ------------ Interfaces to hardware functions ------------ */
1167f7018c21STomi Valkeinen 
11688a48ac33SJani Nikula static const struct fb_ops stifb_ops = {
1169f7018c21STomi Valkeinen 	.owner		= THIS_MODULE,
1170203873a5SHelge Deller 	.fb_check_var	= stifb_check_var,
1171f7018c21STomi Valkeinen 	.fb_setcolreg	= stifb_setcolreg,
1172f7018c21STomi Valkeinen 	.fb_blank	= stifb_blank,
11739c379c65SHelge Deller 	.fb_fillrect	= stifb_fillrect,
1174cb908ed3SAlex Ivanov 	.fb_copyarea	= stifb_copyarea,
1175f7018c21STomi Valkeinen 	.fb_imageblit	= cfb_imageblit,
1176f7018c21STomi Valkeinen };
1177f7018c21STomi Valkeinen 
1178f7018c21STomi Valkeinen 
1179f7018c21STomi Valkeinen /*
1180f7018c21STomi Valkeinen  *  Initialization
1181f7018c21STomi Valkeinen  */
1182f7018c21STomi Valkeinen 
stifb_init_fb(struct sti_struct * sti,int bpp_pref)1183f7018c21STomi Valkeinen static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
1184f7018c21STomi Valkeinen {
1185f7018c21STomi Valkeinen 	struct fb_fix_screeninfo *fix;
1186f7018c21STomi Valkeinen 	struct fb_var_screeninfo *var;
1187f7018c21STomi Valkeinen 	struct stifb_info *fb;
1188f7018c21STomi Valkeinen 	struct fb_info *info;
1189f7018c21STomi Valkeinen 	unsigned long sti_rom_address;
1190203873a5SHelge Deller 	char modestr[32];
1191f7018c21STomi Valkeinen 	char *dev_name;
1192f7018c21STomi Valkeinen 	int bpp, xres, yres;
1193f7018c21STomi Valkeinen 
1194f7018c21STomi Valkeinen 	fb = kzalloc(sizeof(*fb), GFP_ATOMIC);
1195b78f8ca8SMarkus Elfring 	if (!fb)
1196f9815f94SMarkus Elfring 		return -ENOMEM;
1197f7018c21STomi Valkeinen 
1198f7018c21STomi Valkeinen 	info = &fb->info;
1199f7018c21STomi Valkeinen 
1200f7018c21STomi Valkeinen 	/* set struct to a known state */
1201f7018c21STomi Valkeinen 	fix = &info->fix;
1202f7018c21STomi Valkeinen 	var = &info->var;
1203f7018c21STomi Valkeinen 
1204f7018c21STomi Valkeinen 	fb->sti = sti;
1205f7018c21STomi Valkeinen 	dev_name = sti->sti_data->inq_outptr.dev_name;
1206f7018c21STomi Valkeinen 	/* store upper 32bits of the graphics id */
1207f7018c21STomi Valkeinen 	fb->id = fb->sti->graphics_id[0];
1208f7018c21STomi Valkeinen 
1209f7018c21STomi Valkeinen 	/* only supported cards are allowed */
1210f7018c21STomi Valkeinen 	switch (fb->id) {
1211f7018c21STomi Valkeinen 	case CRT_ID_VISUALIZE_EG:
1212f7018c21STomi Valkeinen 		/* Visualize cards can run either in "double buffer" or
1213f7018c21STomi Valkeinen  		  "standard" mode. Depending on the mode, the card reports
1214f7018c21STomi Valkeinen 		  a different device name, e.g. "INTERNAL_EG_DX1024" in double
1215f7018c21STomi Valkeinen 		  buffer mode and "INTERNAL_EG_X1024" in standard mode.
1216f7018c21STomi Valkeinen 		  Since this driver only supports standard mode, we check
1217f7018c21STomi Valkeinen 		  if the device name contains the string "DX" and tell the
1218f7018c21STomi Valkeinen 		  user how to reconfigure the card. */
1219f7018c21STomi Valkeinen 		if (strstr(dev_name, "DX")) {
1220f7018c21STomi Valkeinen 		   printk(KERN_WARNING
1221f7018c21STomi Valkeinen "WARNING: stifb framebuffer driver does not support '%s' in double-buffer mode.\n"
1222f7018c21STomi Valkeinen "WARNING: Please disable the double-buffer mode in IPL menu (the PARISC-BIOS).\n",
1223f7018c21STomi Valkeinen 			dev_name);
1224f7018c21STomi Valkeinen 		   goto out_err0;
1225f7018c21STomi Valkeinen 		}
1226df561f66SGustavo A. R. Silva 		fallthrough;
1227f7018c21STomi Valkeinen 	case S9000_ID_ARTIST:
1228f7018c21STomi Valkeinen 	case S9000_ID_HCRX:
1229f7018c21STomi Valkeinen 	case S9000_ID_TIMBER:
1230f7018c21STomi Valkeinen 	case S9000_ID_A1659A:
1231f7018c21STomi Valkeinen 	case S9000_ID_A1439A:
1232f7018c21STomi Valkeinen 		break;
1233f7018c21STomi Valkeinen 	default:
1234f7018c21STomi Valkeinen 		printk(KERN_WARNING "stifb: '%s' (id: 0x%08x) not supported.\n",
1235f7018c21STomi Valkeinen 			dev_name, fb->id);
1236f7018c21STomi Valkeinen 		goto out_err0;
1237f7018c21STomi Valkeinen 	}
1238f7018c21STomi Valkeinen 
1239f7018c21STomi Valkeinen 	/* default to 8 bpp on most graphic chips */
1240f7018c21STomi Valkeinen 	bpp = 8;
1241f7018c21STomi Valkeinen 	xres = sti_onscreen_x(fb->sti);
1242f7018c21STomi Valkeinen 	yres = sti_onscreen_y(fb->sti);
1243f7018c21STomi Valkeinen 
1244f7018c21STomi Valkeinen 	ngleGetDeviceRomData(fb);
1245f7018c21STomi Valkeinen 
1246f7018c21STomi Valkeinen 	/* get (virtual) io region base addr */
1247f7018c21STomi Valkeinen 	fix->mmio_start = REGION_BASE(fb,2);
1248f7018c21STomi Valkeinen 	fix->mmio_len   = 0x400000;
1249f7018c21STomi Valkeinen 
1250f7018c21STomi Valkeinen        	/* Reject any device not in the NGLE family */
1251f7018c21STomi Valkeinen 	switch (fb->id) {
1252f7018c21STomi Valkeinen 	case S9000_ID_A1659A:	/* CRX/A1659A */
1253f7018c21STomi Valkeinen 		break;
1254f7018c21STomi Valkeinen 	case S9000_ID_ELM:	/* GRX, grayscale but else same as A1659A */
1255f7018c21STomi Valkeinen 		var->grayscale = 1;
1256f7018c21STomi Valkeinen 		fb->id = S9000_ID_A1659A;
1257f7018c21STomi Valkeinen 		break;
1258f7018c21STomi Valkeinen 	case S9000_ID_TIMBER:	/* HP9000/710 Any (may be a grayscale device) */
1259f7018c21STomi Valkeinen 		if (strstr(dev_name, "GRAYSCALE") ||
1260f7018c21STomi Valkeinen 		    strstr(dev_name, "Grayscale") ||
1261f7018c21STomi Valkeinen 		    strstr(dev_name, "grayscale"))
1262f7018c21STomi Valkeinen 			var->grayscale = 1;
1263f7018c21STomi Valkeinen 		break;
1264f7018c21STomi Valkeinen 	case S9000_ID_TOMCAT:	/* Dual CRX, behaves else like a CRX */
1265f7018c21STomi Valkeinen 		/* FIXME: TomCat supports two heads:
1266f7018c21STomi Valkeinen 		 * fb.iobase = REGION_BASE(fb_info,3);
12674bdc0d67SChristoph Hellwig 		 * fb.screen_base = ioremap(REGION_BASE(fb_info,2),xxx);
1268f7018c21STomi Valkeinen 		 * for now we only support the left one ! */
1269f7018c21STomi Valkeinen 		xres = fb->ngle_rom.x_size_visible;
1270f7018c21STomi Valkeinen 		yres = fb->ngle_rom.y_size_visible;
1271f7018c21STomi Valkeinen 		fb->id = S9000_ID_A1659A;
1272f7018c21STomi Valkeinen 		break;
1273f7018c21STomi Valkeinen 	case S9000_ID_A1439A:	/* CRX24/A1439A */
1274f7018c21STomi Valkeinen 		bpp = 32;
1275f7018c21STomi Valkeinen 		break;
1276f7018c21STomi Valkeinen 	case S9000_ID_HCRX:	/* Hyperdrive/HCRX */
1277f7018c21STomi Valkeinen 		memset(&fb->ngle_rom, 0, sizeof(fb->ngle_rom));
1278f7018c21STomi Valkeinen 		if ((fb->sti->regions_phys[0] & 0xfc000000) ==
1279f7018c21STomi Valkeinen 		    (fb->sti->regions_phys[2] & 0xfc000000))
1280f7018c21STomi Valkeinen 			sti_rom_address = F_EXTEND(fb->sti->regions_phys[0]);
1281f7018c21STomi Valkeinen 		else
1282f7018c21STomi Valkeinen 			sti_rom_address = F_EXTEND(fb->sti->regions_phys[1]);
1283f7018c21STomi Valkeinen 
1284f7018c21STomi Valkeinen 		fb->deviceSpecificConfig = gsc_readl(sti_rom_address);
1285f7018c21STomi Valkeinen 		if (IS_24_DEVICE(fb)) {
1286f7018c21STomi Valkeinen 			if (bpp_pref == 8 || bpp_pref == 32)
1287f7018c21STomi Valkeinen 				bpp = bpp_pref;
1288f7018c21STomi Valkeinen 			else
1289f7018c21STomi Valkeinen 				bpp = 32;
1290f7018c21STomi Valkeinen 		} else
1291f7018c21STomi Valkeinen 			bpp = 8;
1292f7018c21STomi Valkeinen 		READ_WORD(fb, REG_15);
1293f7018c21STomi Valkeinen 		SETUP_HW(fb);
1294f7018c21STomi Valkeinen 		break;
1295f7018c21STomi Valkeinen 	case CRT_ID_VISUALIZE_EG:
1296f7018c21STomi Valkeinen 	case S9000_ID_ARTIST:	/* Artist */
1297f7018c21STomi Valkeinen 		break;
1298f7018c21STomi Valkeinen 	default:
1299f7018c21STomi Valkeinen #ifdef FALLBACK_TO_1BPP
1300f7018c21STomi Valkeinen 		printk(KERN_WARNING
1301f7018c21STomi Valkeinen 			"stifb: Unsupported graphics card (id=0x%08x) "
1302f7018c21STomi Valkeinen 				"- now trying 1bpp mode instead\n",
1303f7018c21STomi Valkeinen 			fb->id);
1304f7018c21STomi Valkeinen 		bpp = 1;	/* default to 1 bpp */
1305f7018c21STomi Valkeinen 		break;
1306f7018c21STomi Valkeinen #else
1307f7018c21STomi Valkeinen 		printk(KERN_WARNING
1308f7018c21STomi Valkeinen 			"stifb: Unsupported graphics card (id=0x%08x) "
1309f7018c21STomi Valkeinen 				"- skipping.\n",
1310f7018c21STomi Valkeinen 			fb->id);
1311f7018c21STomi Valkeinen 		goto out_err0;
1312f7018c21STomi Valkeinen #endif
1313f7018c21STomi Valkeinen 	}
1314f7018c21STomi Valkeinen 
1315f7018c21STomi Valkeinen 
1316f7018c21STomi Valkeinen 	/* get framebuffer physical and virtual base addr & len (64bit ready) */
1317f7018c21STomi Valkeinen 	fix->smem_start = F_EXTEND(fb->sti->regions_phys[1]);
1318f7018c21STomi Valkeinen 	fix->smem_len = fb->sti->regions[1].region_desc.length * 4096;
1319f7018c21STomi Valkeinen 
1320f7018c21STomi Valkeinen 	fix->line_length = (fb->sti->glob_cfg->total_x * bpp) / 8;
1321f7018c21STomi Valkeinen 	if (!fix->line_length)
1322f7018c21STomi Valkeinen 		fix->line_length = 2048; /* default */
1323f7018c21STomi Valkeinen 
1324f7018c21STomi Valkeinen 	/* limit fbsize to max visible screen size */
1325f7018c21STomi Valkeinen 	if (fix->smem_len > yres*fix->line_length)
1326aca7c13dSHelge Deller 		fix->smem_len = ALIGN(yres*fix->line_length, 4*1024*1024);
1327f7018c21STomi Valkeinen 
1328f7018c21STomi Valkeinen 	fix->accel = FB_ACCEL_NONE;
1329f7018c21STomi Valkeinen 
1330f7018c21STomi Valkeinen 	switch (bpp) {
1331f7018c21STomi Valkeinen 	    case 1:
1332f7018c21STomi Valkeinen 		fix->type = FB_TYPE_PLANES;	/* well, sort of */
1333f7018c21STomi Valkeinen 		fix->visual = FB_VISUAL_MONO10;
1334f7018c21STomi Valkeinen 		var->red.length = var->green.length = var->blue.length = 1;
1335f7018c21STomi Valkeinen 		break;
1336f7018c21STomi Valkeinen 	    case 8:
1337f7018c21STomi Valkeinen 		fix->type = FB_TYPE_PACKED_PIXELS;
1338f7018c21STomi Valkeinen 		fix->visual = FB_VISUAL_PSEUDOCOLOR;
1339f7018c21STomi Valkeinen 		var->red.length = var->green.length = var->blue.length = 8;
1340f7018c21STomi Valkeinen 		break;
1341f7018c21STomi Valkeinen 	    case 32:
1342f7018c21STomi Valkeinen 		fix->type = FB_TYPE_PACKED_PIXELS;
1343f7018c21STomi Valkeinen 		fix->visual = FB_VISUAL_DIRECTCOLOR;
1344f7018c21STomi Valkeinen 		var->red.length = var->green.length = var->blue.length = var->transp.length = 8;
1345f7018c21STomi Valkeinen 		var->blue.offset = 0;
1346f7018c21STomi Valkeinen 		var->green.offset = 8;
1347f7018c21STomi Valkeinen 		var->red.offset = 16;
1348f7018c21STomi Valkeinen 		var->transp.offset = 24;
1349f7018c21STomi Valkeinen 		break;
1350f7018c21STomi Valkeinen 	    default:
1351f7018c21STomi Valkeinen 		break;
1352f7018c21STomi Valkeinen 	}
1353f7018c21STomi Valkeinen 
1354f7018c21STomi Valkeinen 	var->xres = var->xres_virtual = xres;
1355f7018c21STomi Valkeinen 	var->yres = var->yres_virtual = yres;
1356f7018c21STomi Valkeinen 	var->bits_per_pixel = bpp;
1357f7018c21STomi Valkeinen 
1358f7018c21STomi Valkeinen 	strcpy(fix->id, "stifb");
1359f7018c21STomi Valkeinen 	info->fbops = &stifb_ops;
13604bdc0d67SChristoph Hellwig 	info->screen_base = ioremap(REGION_BASE(fb,1), fix->smem_len);
136174a2b96eSArvind Yadav 	if (!info->screen_base) {
136274a2b96eSArvind Yadav 		printk(KERN_ERR "stifb: failed to map memory\n");
136374a2b96eSArvind Yadav 		goto out_err0;
136474a2b96eSArvind Yadav 	}
1365f7018c21STomi Valkeinen 	info->screen_size = fix->smem_len;
13669c379c65SHelge Deller 	info->flags = FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;
1367f7018c21STomi Valkeinen 	info->pseudo_palette = &fb->pseudo_palette;
1368f7018c21STomi Valkeinen 
1369203873a5SHelge Deller 	scnprintf(modestr, sizeof(modestr), "%dx%d-%d", xres, yres, bpp);
1370203873a5SHelge Deller 	fb_find_mode(&info->var, info, modestr, NULL, 0, NULL, bpp);
1371203873a5SHelge Deller 
1372f7018c21STomi Valkeinen 	/* This has to be done !!! */
1373f7018c21STomi Valkeinen 	if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0))
1374f7018c21STomi Valkeinen 		goto out_err1;
1375f7018c21STomi Valkeinen 	stifb_init_display(fb);
1376f7018c21STomi Valkeinen 
1377f7018c21STomi Valkeinen 	if (!request_mem_region(fix->smem_start, fix->smem_len, "stifb fb")) {
1378f7018c21STomi Valkeinen 		printk(KERN_ERR "stifb: cannot reserve fb region 0x%04lx-0x%04lx\n",
1379f7018c21STomi Valkeinen 				fix->smem_start, fix->smem_start+fix->smem_len);
1380f7018c21STomi Valkeinen 		goto out_err2;
1381f7018c21STomi Valkeinen 	}
1382f7018c21STomi Valkeinen 
1383f7018c21STomi Valkeinen 	if (!request_mem_region(fix->mmio_start, fix->mmio_len, "stifb mmio")) {
1384f7018c21STomi Valkeinen 		printk(KERN_ERR "stifb: cannot reserve sti mmio region 0x%04lx-0x%04lx\n",
1385f7018c21STomi Valkeinen 				fix->mmio_start, fix->mmio_start+fix->mmio_len);
1386f7018c21STomi Valkeinen 		goto out_err3;
1387f7018c21STomi Valkeinen 	}
1388f7018c21STomi Valkeinen 
1389cf936af7SHelge Deller 	/* save for primary gfx device detection & unregister_framebuffer() */
1390cf936af7SHelge Deller 	sti->info = info;
1391f7018c21STomi Valkeinen 	if (register_framebuffer(&fb->info) < 0)
1392f7018c21STomi Valkeinen 		goto out_err4;
1393f7018c21STomi Valkeinen 
1394f7018c21STomi Valkeinen 	fb_info(&fb->info, "%s %dx%d-%d frame buffer device, %s, id: %04x, mmio: 0x%04lx\n",
1395f7018c21STomi Valkeinen 		fix->id,
1396f7018c21STomi Valkeinen 		var->xres,
1397f7018c21STomi Valkeinen 		var->yres,
1398f7018c21STomi Valkeinen 		var->bits_per_pixel,
1399f7018c21STomi Valkeinen 		dev_name,
1400f7018c21STomi Valkeinen 		fb->id,
1401f7018c21STomi Valkeinen 		fix->mmio_start);
1402f7018c21STomi Valkeinen 
1403f7018c21STomi Valkeinen 	return 0;
1404f7018c21STomi Valkeinen 
1405f7018c21STomi Valkeinen 
1406f7018c21STomi Valkeinen out_err4:
1407f7018c21STomi Valkeinen 	release_mem_region(fix->mmio_start, fix->mmio_len);
1408f7018c21STomi Valkeinen out_err3:
1409f7018c21STomi Valkeinen 	release_mem_region(fix->smem_start, fix->smem_len);
1410f7018c21STomi Valkeinen out_err2:
1411f7018c21STomi Valkeinen 	fb_dealloc_cmap(&info->cmap);
1412f7018c21STomi Valkeinen out_err1:
1413f7018c21STomi Valkeinen 	iounmap(info->screen_base);
1414f7018c21STomi Valkeinen out_err0:
1415f7018c21STomi Valkeinen 	kfree(fb);
1416*0bdf1ad8SHelge Deller 	sti->info = NULL;
1417f7018c21STomi Valkeinen 	return -ENXIO;
1418f7018c21STomi Valkeinen }
1419f7018c21STomi Valkeinen 
1420f7018c21STomi Valkeinen static int stifb_disabled __initdata;
1421f7018c21STomi Valkeinen 
1422f7018c21STomi Valkeinen int __init
1423f7018c21STomi Valkeinen stifb_setup(char *options);
1424f7018c21STomi Valkeinen 
stifb_init(void)1425f7018c21STomi Valkeinen static int __init stifb_init(void)
1426f7018c21STomi Valkeinen {
1427f7018c21STomi Valkeinen 	struct sti_struct *sti;
1428f7018c21STomi Valkeinen 	struct sti_struct *def_sti;
1429f7018c21STomi Valkeinen 	int i;
1430f7018c21STomi Valkeinen 
1431f7018c21STomi Valkeinen #ifndef MODULE
1432f7018c21STomi Valkeinen 	char *option = NULL;
1433f7018c21STomi Valkeinen 
1434f7018c21STomi Valkeinen 	if (fb_get_options("stifb", &option))
1435f7018c21STomi Valkeinen 		return -ENODEV;
1436f7018c21STomi Valkeinen 	stifb_setup(option);
1437f7018c21STomi Valkeinen #endif
1438f7018c21STomi Valkeinen 	if (stifb_disabled) {
1439f7018c21STomi Valkeinen 		printk(KERN_INFO "stifb: disabled by \"stifb=off\" kernel parameter\n");
1440f7018c21STomi Valkeinen 		return -ENXIO;
1441f7018c21STomi Valkeinen 	}
1442f7018c21STomi Valkeinen 
1443f7018c21STomi Valkeinen 	def_sti = sti_get_rom(0);
1444f7018c21STomi Valkeinen 	if (def_sti) {
1445f7018c21STomi Valkeinen 		for (i = 1; i <= MAX_STI_ROMS; i++) {
1446f7018c21STomi Valkeinen 			sti = sti_get_rom(i);
1447f7018c21STomi Valkeinen 			if (!sti)
1448f7018c21STomi Valkeinen 				break;
1449f7018c21STomi Valkeinen 			if (sti == def_sti) {
1450f7018c21STomi Valkeinen 				stifb_init_fb(sti, stifb_bpp_pref[i - 1]);
1451f7018c21STomi Valkeinen 				break;
1452f7018c21STomi Valkeinen 			}
1453f7018c21STomi Valkeinen 		}
1454f7018c21STomi Valkeinen 	}
1455f7018c21STomi Valkeinen 
1456f7018c21STomi Valkeinen 	for (i = 1; i <= MAX_STI_ROMS; i++) {
1457f7018c21STomi Valkeinen 		sti = sti_get_rom(i);
1458f7018c21STomi Valkeinen 		if (!sti)
1459f7018c21STomi Valkeinen 			break;
1460f7018c21STomi Valkeinen 		if (sti == def_sti)
1461f7018c21STomi Valkeinen 			continue;
1462f7018c21STomi Valkeinen 		stifb_init_fb(sti, stifb_bpp_pref[i - 1]);
1463f7018c21STomi Valkeinen 	}
1464f7018c21STomi Valkeinen 	return 0;
1465f7018c21STomi Valkeinen }
1466f7018c21STomi Valkeinen 
1467f7018c21STomi Valkeinen /*
1468f7018c21STomi Valkeinen  *  Cleanup
1469f7018c21STomi Valkeinen  */
1470f7018c21STomi Valkeinen 
1471f7018c21STomi Valkeinen static void __exit
stifb_cleanup(void)1472f7018c21STomi Valkeinen stifb_cleanup(void)
1473f7018c21STomi Valkeinen {
1474f7018c21STomi Valkeinen 	struct sti_struct *sti;
1475f7018c21STomi Valkeinen 	int i;
1476f7018c21STomi Valkeinen 
1477f7018c21STomi Valkeinen 	for (i = 1; i <= MAX_STI_ROMS; i++) {
1478f7018c21STomi Valkeinen 		sti = sti_get_rom(i);
1479f7018c21STomi Valkeinen 		if (!sti)
1480f7018c21STomi Valkeinen 			break;
1481f7018c21STomi Valkeinen 		if (sti->info) {
1482f7018c21STomi Valkeinen 			struct fb_info *info = sti->info;
1483f7018c21STomi Valkeinen 			unregister_framebuffer(sti->info);
1484f7018c21STomi Valkeinen 			release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
1485f7018c21STomi Valkeinen 		        release_mem_region(info->fix.smem_start, info->fix.smem_len);
1486f7018c21STomi Valkeinen 				if (info->screen_base)
1487f7018c21STomi Valkeinen 					iounmap(info->screen_base);
1488f7018c21STomi Valkeinen 		        fb_dealloc_cmap(&info->cmap);
1489f7018c21STomi Valkeinen 		        framebuffer_release(info);
1490f7018c21STomi Valkeinen 		}
1491f7018c21STomi Valkeinen 		sti->info = NULL;
1492f7018c21STomi Valkeinen 	}
1493f7018c21STomi Valkeinen }
1494f7018c21STomi Valkeinen 
1495f7018c21STomi Valkeinen int __init
stifb_setup(char * options)1496f7018c21STomi Valkeinen stifb_setup(char *options)
1497f7018c21STomi Valkeinen {
1498f7018c21STomi Valkeinen 	int i;
1499f7018c21STomi Valkeinen 
1500f7018c21STomi Valkeinen 	if (!options || !*options)
1501f7018c21STomi Valkeinen 		return 1;
1502f7018c21STomi Valkeinen 
1503f7018c21STomi Valkeinen 	if (strncmp(options, "off", 3) == 0) {
1504f7018c21STomi Valkeinen 		stifb_disabled = 1;
1505f7018c21STomi Valkeinen 		options += 3;
1506f7018c21STomi Valkeinen 	}
1507f7018c21STomi Valkeinen 
1508f7018c21STomi Valkeinen 	if (strncmp(options, "bpp", 3) == 0) {
1509f7018c21STomi Valkeinen 		options += 3;
1510f7018c21STomi Valkeinen 		for (i = 0; i < MAX_STI_ROMS; i++) {
1511f7018c21STomi Valkeinen 			if (*options++ != ':')
1512f7018c21STomi Valkeinen 				break;
1513f7018c21STomi Valkeinen 			stifb_bpp_pref[i] = simple_strtoul(options, &options, 10);
1514f7018c21STomi Valkeinen 		}
1515f7018c21STomi Valkeinen 	}
1516f7018c21STomi Valkeinen 	return 1;
1517f7018c21STomi Valkeinen }
1518f7018c21STomi Valkeinen 
1519f7018c21STomi Valkeinen __setup("stifb=", stifb_setup);
1520f7018c21STomi Valkeinen 
1521f7018c21STomi Valkeinen module_init(stifb_init);
1522f7018c21STomi Valkeinen module_exit(stifb_cleanup);
1523f7018c21STomi Valkeinen 
1524f7018c21STomi Valkeinen MODULE_AUTHOR("Helge Deller <deller@gmx.de>, Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
1525f7018c21STomi Valkeinen MODULE_DESCRIPTION("Framebuffer driver for HP's NGLE series graphics cards in HP PARISC machines");
1526f7018c21STomi Valkeinen MODULE_LICENSE("GPL v2");
1527