brintos

brintos / linux-shallow public Read only

0
0
Text · 38.8 KiB · 8e5bac2 Raw
1532 lines · c
1/*2 * linux/drivers/video/stifb.c -3 * Low level Frame buffer driver for HP workstations with4 * STI (standard text interface) video firmware.5 *6 * Copyright (C) 2001-2006 Helge Deller <deller@gmx.de>7 * Portions Copyright (C) 2001 Thomas Bogendoerfer <tsbogend@alpha.franken.de>8 *9 * Based on:10 * - linux/drivers/video/artistfb.c -- Artist frame buffer driver11 *	Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>12 *   - based on skeletonfb, which was13 *	Created 28 Dec 1997 by Geert Uytterhoeven14 * - HP Xhp cfb-based X11 window driver for XFree8615 *	(c)Copyright 1992 Hewlett-Packard Co.16 *17 *18 *  The following graphics display devices (NGLE family) are supported by this driver:19 *20 *  HPA4070A	known as "HCRX", a 1280x1024 color device with 8 planes21 *  HPA4071A	known as "HCRX24", a 1280x1024 color device with 24 planes,22 *		optionally available with a hardware accelerator as HPA4071A_Z23 *  HPA1659A	known as "CRX", a 1280x1024 color device with 8 planes24 *  HPA1439A	known as "CRX24", a 1280x1024 color device with 24 planes,25 *		optionally available with a hardware accelerator.26 *  HPA1924A	known as "GRX", a 1280x1024 grayscale device with 8 planes27 *  HPA2269A	known as "Dual CRX", a 1280x1024 color device with 8 planes,28 *		implements support for two displays on a single graphics card.29 *  HP710C	internal graphics support optionally available on the HP9000s710 SPU,30 *		supports 1280x1024 color displays with 8 planes.31 *  HP710G	same as HP710C, 1280x1024 grayscale only32 *  HP710L	same as HP710C, 1024x768 color only33 *  HP712	internal graphics support on HP9000s712 SPU, supports 640x480,34 *		1024x768 or 1280x1024 color displays on 8 planes (Artist)35 *36 * This file is subject to the terms and conditions of the GNU General Public37 * License.  See the file COPYING in the main directory of this archive38 * for more details.39 */40 41/* TODO:42 *	- 1bpp mode is completely untested43 *	- add support for h/w acceleration44 *	- add hardware cursor45 *	- automatically disable double buffering (e.g. on RDI precisionbook laptop)46 */47 48 49/* on supported graphic devices you may:50 * #define FALLBACK_TO_1BPP to fall back to 1 bpp, or51 * #undef  FALLBACK_TO_1BPP to reject support for unsupported cards */52#undef FALLBACK_TO_1BPP53 54#undef DEBUG_STIFB_REGS		/* debug sti register accesses */55 56 57#include <linux/module.h>58#include <linux/kernel.h>59#include <linux/errno.h>60#include <linux/string.h>61#include <linux/mm.h>62#include <linux/slab.h>63#include <linux/delay.h>64#include <linux/fb.h>65#include <linux/init.h>66#include <linux/ioport.h>67#include <linux/io.h>68 69#include <asm/grfioctl.h>	/* for HP-UX compatibility */70#include <linux/uaccess.h>71 72#include <video/sticore.h>73 74/* REGION_BASE(fb_info, index) returns the physical address for region <index> */75#define REGION_BASE(fb_info, index) \76	F_EXTEND(fb_info->sti->regions_phys[index])77 78#define NGLEDEVDEPROM_CRT_REGION 179 80#define NR_PALETTE 25681 82typedef struct {83	__s32	video_config_reg;84	__s32	misc_video_start;85	__s32	horiz_timing_fmt;86	__s32	serr_timing_fmt;87	__s32	vert_timing_fmt;88	__s32	horiz_state;89	__s32	vert_state;90	__s32	vtg_state_elements;91	__s32	pipeline_delay;92	__s32	misc_video_end;93} video_setup_t;94 95typedef struct {96	__s16	sizeof_ngle_data;97	__s16	x_size_visible;	    /* visible screen dim in pixels  */98	__s16	y_size_visible;99	__s16	pad2[15];100	__s16	cursor_pipeline_delay;101	__s16	video_interleaves;102	__s32	pad3[11];103} ngle_rom_t;104 105struct stifb_info {106	struct fb_info *info;107	unsigned int id;108	ngle_rom_t ngle_rom;109	struct sti_struct *sti;110	int deviceSpecificConfig;111	u32 pseudo_palette[16];112};113 114static int __initdata stifb_bpp_pref[MAX_STI_ROMS];115 116/* ------------------- chipset specific functions -------------------------- */117 118/* offsets to graphic-chip internal registers */119 120#define REG_1		0x000118121#define REG_2		0x000480122#define REG_3		0x0004a0123#define REG_4		0x000600124#define REG_6		0x000800125#define REG_7		0x000804126#define REG_8		0x000820127#define REG_9		0x000a04128#define REG_10		0x018000129#define REG_11		0x018004130#define REG_12		0x01800c131#define REG_13		0x018018132#define REG_14  	0x01801c133#define REG_15		0x200000134#define REG_15b0	0x200000135#define REG_16b1	0x200005136#define REG_16b3	0x200007137#define REG_21		0x200218138#define REG_22		0x0005a0139#define REG_23		0x0005c0140#define REG_24		0x000808141#define REG_25		0x000b00142#define REG_26		0x200118143#define REG_27		0x200308144#define REG_32		0x21003c145#define REG_33		0x210040146#define REG_34		0x200008147#define REG_35		0x018010148#define REG_38		0x210020149#define REG_39		0x210120150#define REG_40		0x210130151#define REG_42		0x210028152#define REG_43		0x21002c153#define REG_44		0x210030154#define REG_45		0x210034155 156#define READ_BYTE(fb, reg)		gsc_readb((fb)->info->fix.mmio_start + (reg))157#define READ_WORD(fb, reg)		gsc_readl((fb)->info->fix.mmio_start + (reg))158 159 160#ifndef DEBUG_STIFB_REGS161# define  DEBUG_OFF()162# define  DEBUG_ON()163# define WRITE_BYTE(value, fb, reg)	gsc_writeb((value), (fb)->info->fix.mmio_start + (reg))164# define WRITE_WORD(value, fb, reg)	gsc_writel((value), (fb)->info->fix.mmio_start + (reg))165#else166  static int debug_on = 1;167# define  DEBUG_OFF() debug_on=0168# define  DEBUG_ON()  debug_on=1169# define WRITE_BYTE(value,fb,reg)	do { if (debug_on) \170						printk(KERN_DEBUG "%30s: WRITE_BYTE(0x%06x) = 0x%02x (old=0x%02x)\n", \171							__func__, reg, value, READ_BYTE(fb,reg)); 		  \172					gsc_writeb((value), (fb)->info->fix.mmio_start + (reg)); } while (0)173# define WRITE_WORD(value,fb,reg)	do { if (debug_on) \174						printk(KERN_DEBUG "%30s: WRITE_WORD(0x%06x) = 0x%08x (old=0x%08x)\n", \175							__func__, reg, value, READ_WORD(fb,reg)); 		  \176					gsc_writel((value), (fb)->info->fix.mmio_start + (reg)); } while (0)177#endif /* DEBUG_STIFB_REGS */178 179 180#define ENABLE	1	/* for enabling/disabling screen */181#define DISABLE 0182 183#define NGLE_LOCK(fb_info)	do { } while (0)184#define NGLE_UNLOCK(fb_info)	do { } while (0)185 186static void187SETUP_HW(struct stifb_info *fb)188{189	char stat;190 191	do {192		stat = READ_BYTE(fb, REG_15b0);193		if (!stat)194	    		stat = READ_BYTE(fb, REG_15b0);195	} while (stat);196}197 198 199static void200SETUP_FB(struct stifb_info *fb)201{202	unsigned int reg10_value = 0;203 204	SETUP_HW(fb);205	switch (fb->id)206	{207		case CRT_ID_VISUALIZE_EG:208		case S9000_ID_ARTIST:209		case S9000_ID_A1659A:210			reg10_value = 0x13601000;211			break;212		case S9000_ID_A1439A:213			if (fb->info->var.bits_per_pixel == 32)214				reg10_value = 0xBBA0A000;215			else216				reg10_value = 0x13601000;217			break;218		case S9000_ID_HCRX:219			if (fb->info->var.bits_per_pixel == 32)220				reg10_value = 0xBBA0A000;221			else222				reg10_value = 0x13602000;223			break;224		case S9000_ID_TIMBER:225		case CRX24_OVERLAY_PLANES:226			reg10_value = 0x13602000;227			break;228	}229	if (reg10_value)230		WRITE_WORD(reg10_value, fb, REG_10);231	WRITE_WORD(0x83000300, fb, REG_14);232	SETUP_HW(fb);233	WRITE_BYTE(1, fb, REG_16b1);234}235 236static void237START_IMAGE_COLORMAP_ACCESS(struct stifb_info *fb)238{239	SETUP_HW(fb);240	WRITE_WORD(0xBBE0F000, fb, REG_10);241	WRITE_WORD(0x03000300, fb, REG_14);242	WRITE_WORD(~0, fb, REG_13);243}244 245static void246WRITE_IMAGE_COLOR(struct stifb_info *fb, int index, int color)247{248	SETUP_HW(fb);249	WRITE_WORD(((0x100+index)<<2), fb, REG_3);250	WRITE_WORD(color, fb, REG_4);251}252 253static void254FINISH_IMAGE_COLORMAP_ACCESS(struct stifb_info *fb)255{256	WRITE_WORD(0x400, fb, REG_2);257	if (fb->info->var.bits_per_pixel == 32) {258		WRITE_WORD(0x83000100, fb, REG_1);259	} else {260		if (fb->id == S9000_ID_ARTIST || fb->id == CRT_ID_VISUALIZE_EG)261			WRITE_WORD(0x80000100, fb, REG_26);262		else263			WRITE_WORD(0x80000100, fb, REG_1);264	}265	SETUP_FB(fb);266}267 268static void269SETUP_RAMDAC(struct stifb_info *fb)270{271	SETUP_HW(fb);272	WRITE_WORD(0x04000000, fb, 0x1020);273	WRITE_WORD(0xff000000, fb, 0x1028);274}275 276static void277CRX24_SETUP_RAMDAC(struct stifb_info *fb)278{279	SETUP_HW(fb);280	WRITE_WORD(0x04000000, fb, 0x1000);281	WRITE_WORD(0x02000000, fb, 0x1004);282	WRITE_WORD(0xff000000, fb, 0x1008);283	WRITE_WORD(0x05000000, fb, 0x1000);284	WRITE_WORD(0x02000000, fb, 0x1004);285	WRITE_WORD(0x03000000, fb, 0x1008);286}287 288#if 0289static void290HCRX_SETUP_RAMDAC(struct stifb_info *fb)291{292	WRITE_WORD(0xffffffff, fb, REG_32);293}294#endif295 296static void297CRX24_SET_OVLY_MASK(struct stifb_info *fb)298{299	SETUP_HW(fb);300	WRITE_WORD(0x13a02000, fb, REG_11);301	WRITE_WORD(0x03000300, fb, REG_14);302	WRITE_WORD(0x000017f0, fb, REG_3);303	WRITE_WORD(0xffffffff, fb, REG_13);304	WRITE_WORD(0xffffffff, fb, REG_22);305	WRITE_WORD(0x00000000, fb, REG_23);306}307 308static void309ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)310{311	unsigned int value = enable ? 0x43000000 : 0x03000000;312        SETUP_HW(fb);313        WRITE_WORD(0x06000000,	fb, 0x1030);314        WRITE_WORD(value, 	fb, 0x1038);315}316 317static void318CRX24_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)319{320	unsigned int value = enable ? 0x10000000 : 0x30000000;321	SETUP_HW(fb);322	WRITE_WORD(0x01000000,	fb, 0x1000);323	WRITE_WORD(0x02000000,	fb, 0x1004);324	WRITE_WORD(value,	fb, 0x1008);325}326 327static void328ARTIST_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)329{330	u32 DregsMiscVideo = REG_21;331	u32 DregsMiscCtl = REG_27;332 333	SETUP_HW(fb);334	if (enable) {335	  WRITE_WORD(READ_WORD(fb, DregsMiscVideo) | 0x0A000000, fb, DregsMiscVideo);336	  WRITE_WORD(READ_WORD(fb, DregsMiscCtl)   | 0x00800000, fb, DregsMiscCtl);337	} else {338	  WRITE_WORD(READ_WORD(fb, DregsMiscVideo) & ~0x0A000000, fb, DregsMiscVideo);339	  WRITE_WORD(READ_WORD(fb, DregsMiscCtl)   & ~0x00800000, fb, DregsMiscCtl);340	}341}342 343#define GET_ROMTABLE_INDEX(fb) \344	(READ_BYTE(fb, REG_16b3) - 1)345 346#define HYPER_CONFIG_PLANES_24 0x00000100347 348#define IS_24_DEVICE(fb) \349	(fb->deviceSpecificConfig & HYPER_CONFIG_PLANES_24)350 351#define IS_888_DEVICE(fb) \352	(!(IS_24_DEVICE(fb)))353 354#define GET_FIFO_SLOTS(fb, cnt, numslots)	\355{	while (cnt < numslots) 			\356		cnt = READ_WORD(fb, REG_34);	\357	cnt -= numslots;			\358}359 360#define	    IndexedDcd	0	/* Pixel data is indexed (pseudo) color */361#define	    Otc04	2	/* Pixels in each longword transfer (4) */362#define	    Otc32	5	/* Pixels in each longword transfer (32) */363#define	    Ots08	3	/* Each pixel is size (8)d transfer (1) */364#define	    OtsIndirect	6	/* Each bit goes through FG/BG color(8) */365#define	    AddrLong	5	/* FB address is Long aligned (pixel) */366#define	    BINovly	0x2	/* 8 bit overlay */367#define	    BINapp0I	0x0	/* Application Buffer 0, Indexed */368#define	    BINapp1I	0x1	/* Application Buffer 1, Indexed */369#define	    BINapp0F8	0xa	/* Application Buffer 0, Fractional 8-8-8 */370#define	    BINattr	0xd	/* Attribute Bitmap */371#define	    RopSrc 	0x3372#define	    BitmapExtent08  3	/* Each write hits ( 8) bits in depth */373#define	    BitmapExtent32  5	/* Each write hits (32) bits in depth */374#define	    DataDynamic	    0	/* Data register reloaded by direct access */375#define	    MaskDynamic	    1	/* Mask register reloaded by direct access */376#define	    MaskOtc	    0	/* Mask contains Object Count valid bits */377 378#define MaskAddrOffset(offset) (offset)379#define StaticReg(en) (en)380#define BGx(en) (en)381#define FGx(en) (en)382 383#define BAJustPoint(offset) (offset)384#define BAIndexBase(base) (base)385#define BA(F,C,S,A,J,B,I) \386	(((F)<<31)|((C)<<27)|((S)<<24)|((A)<<21)|((J)<<16)|((B)<<12)|(I))387 388#define IBOvals(R,M,X,S,D,L,B,F) \389	(((R)<<8)|((M)<<16)|((X)<<24)|((S)<<29)|((D)<<28)|((L)<<31)|((B)<<1)|(F))390 391#define NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb, val) \392	WRITE_WORD(val, fb, REG_14)393 394#define NGLE_QUICK_SET_DST_BM_ACCESS(fb, val) \395	WRITE_WORD(val, fb, REG_11)396 397#define NGLE_QUICK_SET_CTL_PLN_REG(fb, val) \398	WRITE_WORD(val, fb, REG_12)399 400#define NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, plnmsk32) \401	WRITE_WORD(plnmsk32, fb, REG_13)402 403#define NGLE_REALLY_SET_IMAGE_FG_COLOR(fb, fg32) \404	WRITE_WORD(fg32, fb, REG_35)405 406#define NGLE_SET_TRANSFERDATA(fb, val) \407	WRITE_WORD(val, fb, REG_8)408 409#define NGLE_SET_DSTXY(fb, val) \410	WRITE_WORD(val, fb, REG_6)411 412#define NGLE_LONG_FB_ADDRESS(fbaddrbase, x, y) (		\413	(u32) (fbaddrbase) +					\414	    (	(unsigned int)  ( (y) << 13      ) |		\415		(unsigned int)  ( (x) << 2       )	)	\416	)417 418#define NGLE_BINC_SET_DSTADDR(fb, addr) \419	WRITE_WORD(addr, fb, REG_3)420 421#define NGLE_BINC_SET_SRCADDR(fb, addr) \422	WRITE_WORD(addr, fb, REG_2)423 424#define NGLE_BINC_SET_DSTMASK(fb, mask) \425	WRITE_WORD(mask, fb, REG_22)426 427#define NGLE_BINC_WRITE32(fb, data32) \428	WRITE_WORD(data32, fb, REG_23)429 430#define START_COLORMAPLOAD(fb, cmapBltCtlData32) \431	WRITE_WORD((cmapBltCtlData32), fb, REG_38)432 433#define SET_LENXY_START_RECFILL(fb, lenxy) \434	WRITE_WORD(lenxy, fb, REG_9)435 436#define SETUP_COPYAREA(fb) \437	WRITE_BYTE(0, fb, REG_16b1)438 439static void440HYPER_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)441{442	u32 DregsHypMiscVideo = REG_33;443	unsigned int value;444	SETUP_HW(fb);445	value = READ_WORD(fb, DregsHypMiscVideo);446	if (enable)447		value |= 0x0A000000;448	else449		value &= ~0x0A000000;450	WRITE_WORD(value, fb, DregsHypMiscVideo);451}452 453 454/* BufferNumbers used by SETUP_ATTR_ACCESS() */455#define BUFF0_CMAP0	0x00001e02456#define BUFF1_CMAP0	0x02001e02457#define BUFF1_CMAP3	0x0c001e02458#define ARTIST_CMAP0	0x00000102459#define HYPER_CMAP8	0x00000100460#define HYPER_CMAP24	0x00000800461 462static void463SETUP_ATTR_ACCESS(struct stifb_info *fb, unsigned BufferNumber)464{465	SETUP_HW(fb);466	WRITE_WORD(0x2EA0D000, fb, REG_11);467	WRITE_WORD(0x23000302, fb, REG_14);468	WRITE_WORD(BufferNumber, fb, REG_12);469	WRITE_WORD(0xffffffff, fb, REG_8);470}471 472static void473SET_ATTR_SIZE(struct stifb_info *fb, int width, int height)474{475	/* REG_6 seems to have special values when run on a476	   RDI precisionbook parisc laptop (INTERNAL_EG_DX1024 or477	   INTERNAL_EG_X1024).  The values are:478		0x2f0: internal (LCD) & external display enabled479		0x2a0: external display only480		0x000: zero on standard artist graphic cards481	*/482	WRITE_WORD(0x00000000, fb, REG_6);483	WRITE_WORD((width<<16) | height, fb, REG_9);484	WRITE_WORD(0x05000000, fb, REG_6);485	WRITE_WORD(0x00040001, fb, REG_9);486}487 488static void489FINISH_ATTR_ACCESS(struct stifb_info *fb)490{491	SETUP_HW(fb);492	WRITE_WORD(0x00000000, fb, REG_12);493}494 495static void496elkSetupPlanes(struct stifb_info *fb)497{498	SETUP_RAMDAC(fb);499	SETUP_FB(fb);500}501 502static void503ngleSetupAttrPlanes(struct stifb_info *fb, int BufferNumber)504{505	SETUP_ATTR_ACCESS(fb, BufferNumber);506	SET_ATTR_SIZE(fb, fb->info->var.xres, fb->info->var.yres);507	FINISH_ATTR_ACCESS(fb);508	SETUP_FB(fb);509}510 511 512static void513rattlerSetupPlanes(struct stifb_info *fb)514{515	int saved_id, y;516 517 	/* Write RAMDAC pixel read mask register so all overlay518	 * planes are display-enabled.  (CRX24 uses Bt462 pixel519	 * read mask register for overlay planes, not image planes).520	 */521	CRX24_SETUP_RAMDAC(fb);522 523	/* change fb->id temporarily to fool SETUP_FB() */524	saved_id = fb->id;525	fb->id = CRX24_OVERLAY_PLANES;526	SETUP_FB(fb);527	fb->id = saved_id;528 529	for (y = 0; y < fb->info->var.yres; ++y)530		fb_memset_io(fb->info->screen_base + y * fb->info->fix.line_length,531			     0xff, fb->info->var.xres * fb->info->var.bits_per_pixel/8);532 533	CRX24_SET_OVLY_MASK(fb);534	SETUP_FB(fb);535}536 537 538#define HYPER_CMAP_TYPE				0539#define NGLE_CMAP_INDEXED0_TYPE			0540#define NGLE_CMAP_OVERLAY_TYPE			3541 542/* typedef of LUT (Colormap) BLT Control Register */543typedef union	/* Note assumption that fields are packed left-to-right */544{	u32 all;545	struct546	{547		unsigned enable              :  1;548		unsigned waitBlank           :  1;549		unsigned reserved1           :  4;550		unsigned lutOffset           : 10;   /* Within destination LUT */551		unsigned lutType             :  2;   /* Cursor, image, overlay */552		unsigned reserved2           :  4;553		unsigned length              : 10;554	} fields;555} NgleLutBltCtl;556 557 558#if 0559static NgleLutBltCtl560setNgleLutBltCtl(struct stifb_info *fb, int offsetWithinLut, int length)561{562	NgleLutBltCtl lutBltCtl;563 564	/* set enable, zero reserved fields */565	lutBltCtl.all           = 0x80000000;566	lutBltCtl.fields.length = length;567 568	switch (fb->id)569	{570	case S9000_ID_A1439A:		/* CRX24 */571		if (fb->var.bits_per_pixel == 8) {572			lutBltCtl.fields.lutType = NGLE_CMAP_OVERLAY_TYPE;573			lutBltCtl.fields.lutOffset = 0;574		} else {575			lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE;576			lutBltCtl.fields.lutOffset = 0 * 256;577		}578		break;579 580	case S9000_ID_ARTIST:581		lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE;582		lutBltCtl.fields.lutOffset = 0 * 256;583		break;584 585	default:586		lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE;587		lutBltCtl.fields.lutOffset = 0;588		break;589	}590 591	/* Offset points to start of LUT.  Adjust for within LUT */592	lutBltCtl.fields.lutOffset += offsetWithinLut;593 594	return lutBltCtl;595}596#endif597 598static NgleLutBltCtl599setHyperLutBltCtl(struct stifb_info *fb, int offsetWithinLut, int length)600{601	NgleLutBltCtl lutBltCtl;602 603	/* set enable, zero reserved fields */604	lutBltCtl.all = 0x80000000;605 606	lutBltCtl.fields.length = length;607	lutBltCtl.fields.lutType = HYPER_CMAP_TYPE;608 609	/* Expect lutIndex to be 0 or 1 for image cmaps, 2 or 3 for overlay cmaps */610	if (fb->info->var.bits_per_pixel == 8)611		lutBltCtl.fields.lutOffset = 2 * 256;612	else613		lutBltCtl.fields.lutOffset = 0 * 256;614 615	/* Offset points to start of LUT.  Adjust for within LUT */616	lutBltCtl.fields.lutOffset += offsetWithinLut;617 618	return lutBltCtl;619}620 621 622static void hyperUndoITE(struct stifb_info *fb)623{624	int nFreeFifoSlots = 0;625	u32 fbAddr;626 627	NGLE_LOCK(fb);628 629	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 1);630	WRITE_WORD(0xffffffff, fb, REG_32);631 632	/* Write overlay transparency mask so only entry 255 is transparent */633 634	/* Hardware setup for full-depth write to "magic" location */635	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 7);636	NGLE_QUICK_SET_DST_BM_ACCESS(fb,637		BA(IndexedDcd, Otc04, Ots08, AddrLong,638		BAJustPoint(0), BINovly, BAIndexBase(0)));639	NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb,640		IBOvals(RopSrc, MaskAddrOffset(0),641		BitmapExtent08, StaticReg(0),642		DataDynamic, MaskOtc, BGx(0), FGx(0)));643 644	/* Now prepare to write to the "magic" location */645	fbAddr = NGLE_LONG_FB_ADDRESS(0, 1532, 0);646	NGLE_BINC_SET_DSTADDR(fb, fbAddr);647	NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xffffff);648	NGLE_BINC_SET_DSTMASK(fb, 0xffffffff);649 650	/* Finally, write a zero to clear the mask */651	NGLE_BINC_WRITE32(fb, 0);652 653	NGLE_UNLOCK(fb);654}655 656static void657ngleDepth8_ClearImagePlanes(struct stifb_info *fb)658{659	/* FIXME! */660}661 662static void663ngleDepth24_ClearImagePlanes(struct stifb_info *fb)664{665	/* FIXME! */666}667 668static void669ngleResetAttrPlanes(struct stifb_info *fb, unsigned int ctlPlaneReg)670{671	int nFreeFifoSlots = 0;672	u32 packed_dst;673	u32 packed_len;674 675	NGLE_LOCK(fb);676 677	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 4);678	NGLE_QUICK_SET_DST_BM_ACCESS(fb,679				     BA(IndexedDcd, Otc32, OtsIndirect,680					AddrLong, BAJustPoint(0),681					BINattr, BAIndexBase(0)));682	NGLE_QUICK_SET_CTL_PLN_REG(fb, ctlPlaneReg);683	NGLE_SET_TRANSFERDATA(fb, 0xffffffff);684 685	NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb,686				       IBOvals(RopSrc, MaskAddrOffset(0),687					       BitmapExtent08, StaticReg(1),688					       DataDynamic, MaskOtc,689					       BGx(0), FGx(0)));690	packed_dst = 0;691	packed_len = (fb->info->var.xres << 16) | fb->info->var.yres;692	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 2);693	NGLE_SET_DSTXY(fb, packed_dst);694	SET_LENXY_START_RECFILL(fb, packed_len);695 696	/*697	 * In order to work around an ELK hardware problem (Buffy doesn't698	 * always flush it's buffers when writing to the attribute699	 * planes), at least 4 pixels must be written to the attribute700	 * planes starting at (X == 1280) and (Y != to the last Y written701	 * by BIF):702	 */703 704	if (fb->id == S9000_ID_A1659A) {   /* ELK_DEVICE_ID */705		/* It's safe to use scanline zero: */706		packed_dst = (1280 << 16);707		GET_FIFO_SLOTS(fb, nFreeFifoSlots, 2);708		NGLE_SET_DSTXY(fb, packed_dst);709		packed_len = (4 << 16) | 1;710		SET_LENXY_START_RECFILL(fb, packed_len);711	}   /* ELK Hardware Kludge */712 713	/**** Finally, set the Control Plane Register back to zero: ****/714	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 1);715	NGLE_QUICK_SET_CTL_PLN_REG(fb, 0);716 717	NGLE_UNLOCK(fb);718}719 720static void721ngleClearOverlayPlanes(struct stifb_info *fb, int mask, int data)722{723	int nFreeFifoSlots = 0;724	u32 packed_dst;725	u32 packed_len;726 727	NGLE_LOCK(fb);728 729	/* Hardware setup */730	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 8);731	NGLE_QUICK_SET_DST_BM_ACCESS(fb,732				     BA(IndexedDcd, Otc04, Ots08, AddrLong,733					BAJustPoint(0), BINovly, BAIndexBase(0)));734 735        NGLE_SET_TRANSFERDATA(fb, 0xffffffff);  /* Write foreground color */736 737        NGLE_REALLY_SET_IMAGE_FG_COLOR(fb, data);738        NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, mask);739 740        packed_dst = 0;741	packed_len = (fb->info->var.xres << 16) | fb->info->var.yres;742        NGLE_SET_DSTXY(fb, packed_dst);743 744	/* Write zeroes to overlay planes */745	NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb,746				       IBOvals(RopSrc, MaskAddrOffset(0),747					       BitmapExtent08, StaticReg(0),748					       DataDynamic, MaskOtc, BGx(0), FGx(0)));749 750        SET_LENXY_START_RECFILL(fb, packed_len);751 752	NGLE_UNLOCK(fb);753}754 755static void756hyperResetPlanes(struct stifb_info *fb, int enable)757{758	unsigned int controlPlaneReg;759 760	NGLE_LOCK(fb);761 762	if (IS_24_DEVICE(fb))763		if (fb->info->var.bits_per_pixel == 32)764			controlPlaneReg = 0x04000F00;765		else766			controlPlaneReg = 0x00000F00;   /* 0x00000800 should be enough, but lets clear all 4 bits */767	else768		controlPlaneReg = 0x00000F00; /* 0x00000100 should be enough, but lets clear all 4 bits */769 770	switch (enable) {771	case ENABLE:772		/* clear screen */773		if (IS_24_DEVICE(fb))774			ngleDepth24_ClearImagePlanes(fb);775		else776			ngleDepth8_ClearImagePlanes(fb);777 778		/* Paint attribute planes for default case.779		 * On Hyperdrive, this means all windows using overlay cmap 0. */780		ngleResetAttrPlanes(fb, controlPlaneReg);781 782		/* clear overlay planes */783	        ngleClearOverlayPlanes(fb, 0xff, 255);784 785		/**************************************************786		 ** Also need to counteract ITE settings787		 **************************************************/788		hyperUndoITE(fb);789		break;790 791	case DISABLE:792		/* clear screen */793		if (IS_24_DEVICE(fb))794			ngleDepth24_ClearImagePlanes(fb);795		else796			ngleDepth8_ClearImagePlanes(fb);797		ngleResetAttrPlanes(fb, controlPlaneReg);798		ngleClearOverlayPlanes(fb, 0xff, 0);799		break;800 801	case -1:	/* RESET */802		hyperUndoITE(fb);803		ngleResetAttrPlanes(fb, controlPlaneReg);804		break;805    	}806 807	NGLE_UNLOCK(fb);808}809 810/* Return pointer to in-memory structure holding ELK device-dependent ROM values. */811 812static void813ngleGetDeviceRomData(struct stifb_info *fb)814{815#if 0816XXX: FIXME: !!!817	int	*pBytePerLongDevDepData;/* data byte == LSB */818	int 	*pRomTable;819	NgleDevRomData	*pPackedDevRomData;820	int	sizePackedDevRomData = sizeof(*pPackedDevRomData);821	char	*pCard8;822	int	i;823	char	*mapOrigin = NULL;824 825	int romTableIdx;826 827	pPackedDevRomData = fb->ngle_rom;828 829	SETUP_HW(fb);830	if (fb->id == S9000_ID_ARTIST) {831		pPackedDevRomData->cursor_pipeline_delay = 4;832		pPackedDevRomData->video_interleaves     = 4;833	} else {834		/* Get pointer to unpacked byte/long data in ROM */835		pBytePerLongDevDepData = fb->sti->regions[NGLEDEVDEPROM_CRT_REGION];836 837		/* Tomcat supports several resolutions: 1280x1024, 1024x768, 640x480 */838		if (fb->id == S9000_ID_TOMCAT)839	{840	    /*  jump to the correct ROM table  */841	    GET_ROMTABLE_INDEX(romTableIdx);842	    while  (romTableIdx > 0)843	    {844		pCard8 = (Card8 *) pPackedDevRomData;845		pRomTable = pBytePerLongDevDepData;846		/* Pack every fourth byte from ROM into structure */847		for (i = 0; i < sizePackedDevRomData; i++)848		{849		    *pCard8++ = (Card8) (*pRomTable++);850		}851 852		pBytePerLongDevDepData = (Card32 *)853			((Card8 *) pBytePerLongDevDepData +854			       pPackedDevRomData->sizeof_ngle_data);855 856		romTableIdx--;857	    }858	}859 860	pCard8 = (Card8 *) pPackedDevRomData;861 862	/* Pack every fourth byte from ROM into structure */863	for (i = 0; i < sizePackedDevRomData; i++)864	{865	    *pCard8++ = (Card8) (*pBytePerLongDevDepData++);866	}867    }868 869    SETUP_FB(fb);870#endif871}872 873 874#define HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES	4875#define HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE	8876#define HYPERBOWL_MODE01_8_24_LUT0_OPAQUE_LUT1_OPAQUE		10877#define HYPERBOWL_MODE2_8_24					15878 879/* HCRX specific boot-time initialization */880static void __init881SETUP_HCRX(struct stifb_info *fb)882{883	int	hyperbowl;884        int	nFreeFifoSlots = 0;885 886	if (fb->id != S9000_ID_HCRX)887		return;888 889	/* Initialize Hyperbowl registers */890	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 7);891 892	if (IS_24_DEVICE(fb)) {893		hyperbowl = (fb->info->var.bits_per_pixel == 32) ?894			HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE :895			HYPERBOWL_MODE01_8_24_LUT0_OPAQUE_LUT1_OPAQUE;896 897		/* First write to Hyperbowl must happen twice (bug) */898		WRITE_WORD(hyperbowl, fb, REG_40);899		WRITE_WORD(hyperbowl, fb, REG_40);900 901		WRITE_WORD(HYPERBOWL_MODE2_8_24, fb, REG_39);902 903		WRITE_WORD(0x014c0148, fb, REG_42); /* Set lut 0 to be the direct color */904		WRITE_WORD(0x404c4048, fb, REG_43);905		WRITE_WORD(0x034c0348, fb, REG_44);906		WRITE_WORD(0x444c4448, fb, REG_45);907	} else {908		hyperbowl = HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES;909 910		/* First write to Hyperbowl must happen twice (bug) */911		WRITE_WORD(hyperbowl, fb, REG_40);912		WRITE_WORD(hyperbowl, fb, REG_40);913 914		WRITE_WORD(0x00000000, fb, REG_42);915		WRITE_WORD(0x00000000, fb, REG_43);916		WRITE_WORD(0x00000000, fb, REG_44);917		WRITE_WORD(0x444c4048, fb, REG_45);918	}919}920 921 922/* ------------------- driver specific functions --------------------------- */923 924static int925stifb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)926{927	struct stifb_info *fb = info->par;928 929	if (var->xres != fb->info->var.xres ||930	    var->yres != fb->info->var.yres ||931	    var->bits_per_pixel != fb->info->var.bits_per_pixel)932		return -EINVAL;933 934	var->xres_virtual = var->xres;935	var->yres_virtual = var->yres;936	var->xoffset = 0;937	var->yoffset = 0;938	var->grayscale = fb->info->var.grayscale;939	var->red.length = fb->info->var.red.length;940	var->green.length = fb->info->var.green.length;941	var->blue.length = fb->info->var.blue.length;942 943	return 0;944}945 946static int947stifb_setcolreg(u_int regno, u_int red, u_int green,948	      u_int blue, u_int transp, struct fb_info *info)949{950	struct stifb_info *fb = info->par;951	u32 color;952 953	if (regno >= NR_PALETTE)954		return 1;955 956	red   >>= 8;957	green >>= 8;958	blue  >>= 8;959 960	DEBUG_OFF();961 962	START_IMAGE_COLORMAP_ACCESS(fb);963 964	if (unlikely(fb->info->var.grayscale)) {965		/* gray = 0.30*R + 0.59*G + 0.11*B */966		color = ((red * 77) +967			 (green * 151) +968			 (blue * 28)) >> 8;969	} else {970		color = ((red << 16) |971			 (green << 8) |972			 (blue));973	}974 975	if (fb->info->fix.visual == FB_VISUAL_DIRECTCOLOR) {976		struct fb_var_screeninfo *var = &fb->info->var;977		if (regno < 16)978			((u32 *)fb->info->pseudo_palette)[regno] =979				regno << var->red.offset |980				regno << var->green.offset |981				regno << var->blue.offset;982	}983 984	WRITE_IMAGE_COLOR(fb, regno, color);985 986	if (fb->id == S9000_ID_HCRX) {987		NgleLutBltCtl lutBltCtl;988 989		lutBltCtl = setHyperLutBltCtl(fb,990				0,	/* Offset w/i LUT */991				256);	/* Load entire LUT */992		NGLE_BINC_SET_SRCADDR(fb,993				NGLE_LONG_FB_ADDRESS(0, 0x100, 0));994				/* 0x100 is same as used in WRITE_IMAGE_COLOR() */995		START_COLORMAPLOAD(fb, lutBltCtl.all);996		SETUP_FB(fb);997	} else {998		/* cleanup colormap hardware */999		FINISH_IMAGE_COLORMAP_ACCESS(fb);1000	}1001 1002	DEBUG_ON();1003 1004	return 0;1005}1006 1007static int1008stifb_blank(int blank_mode, struct fb_info *info)1009{1010	struct stifb_info *fb = info->par;1011	int enable = (blank_mode == 0) ? ENABLE : DISABLE;1012 1013	switch (fb->id) {1014	case S9000_ID_A1439A:1015		CRX24_ENABLE_DISABLE_DISPLAY(fb, enable);1016		break;1017	case CRT_ID_VISUALIZE_EG:1018	case S9000_ID_ARTIST:1019		ARTIST_ENABLE_DISABLE_DISPLAY(fb, enable);1020		break;1021	case S9000_ID_HCRX:1022		HYPER_ENABLE_DISABLE_DISPLAY(fb, enable);1023		break;1024	case S9000_ID_A1659A:1025	case S9000_ID_TIMBER:1026	case CRX24_OVERLAY_PLANES:1027	default:1028		ENABLE_DISABLE_DISPLAY(fb, enable);1029		break;1030	}1031 1032	SETUP_FB(fb);1033	return 0;1034}1035 1036static void1037stifb_copyarea(struct fb_info *info, const struct fb_copyarea *area)1038{1039	struct stifb_info *fb = info->par;1040 1041	SETUP_COPYAREA(fb);1042 1043	SETUP_HW(fb);1044	if (fb->info->var.bits_per_pixel == 32) {1045		WRITE_WORD(0xBBA0A000, fb, REG_10);1046 1047		NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xffffffff);1048	} else {1049		WRITE_WORD(fb->id == S9000_ID_HCRX ? 0x13a02000 : 0x13a01000, fb, REG_10);1050 1051		NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xff);1052	}1053 1054	NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb,1055		IBOvals(RopSrc, MaskAddrOffset(0),1056		BitmapExtent08, StaticReg(1),1057		DataDynamic, MaskOtc, BGx(0), FGx(0)));1058 1059	WRITE_WORD(((area->sx << 16) | area->sy), fb, REG_24);1060	WRITE_WORD(((area->width << 16) | area->height), fb, REG_7);1061	WRITE_WORD(((area->dx << 16) | area->dy), fb, REG_25);1062 1063	SETUP_FB(fb);1064}1065 1066#define ARTIST_VRAM_SIZE			0x0008041067#define ARTIST_VRAM_SRC				0x0008081068#define ARTIST_VRAM_SIZE_TRIGGER_WINFILL	0x000a041069#define ARTIST_VRAM_DEST_TRIGGER_BLOCKMOVE	0x000b001070#define ARTIST_SRC_BM_ACCESS			0x0180081071#define ARTIST_FGCOLOR				0x0180101072#define ARTIST_BGCOLOR				0x0180141073#define ARTIST_BITMAP_OP			0x01801c1074 1075static void1076stifb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)1077{1078	struct stifb_info *fb = info->par;1079 1080	if (rect->rop != ROP_COPY ||1081	    (fb->id == S9000_ID_HCRX && fb->info->var.bits_per_pixel == 32))1082		return cfb_fillrect(info, rect);1083 1084	SETUP_HW(fb);1085 1086	if (fb->info->var.bits_per_pixel == 32) {1087		WRITE_WORD(0xBBA0A000, fb, REG_10);1088 1089		NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xffffffff);1090	} else {1091		WRITE_WORD(fb->id == S9000_ID_HCRX ? 0x13a02000 : 0x13a01000, fb, REG_10);1092 1093		NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xff);1094	}1095 1096	WRITE_WORD(0x03000300, fb, ARTIST_BITMAP_OP);1097	WRITE_WORD(0x2ea01000, fb, ARTIST_SRC_BM_ACCESS);1098	NGLE_QUICK_SET_DST_BM_ACCESS(fb, 0x2ea01000);1099	NGLE_REALLY_SET_IMAGE_FG_COLOR(fb, rect->color);1100	WRITE_WORD(0, fb, ARTIST_BGCOLOR);1101 1102	NGLE_SET_DSTXY(fb, (rect->dx << 16) | (rect->dy));1103	SET_LENXY_START_RECFILL(fb, (rect->width << 16) | (rect->height));1104 1105	SETUP_FB(fb);1106}1107 1108static void __init1109stifb_init_display(struct stifb_info *fb)1110{1111	int id = fb->id;1112 1113	SETUP_FB(fb);1114 1115	/* HCRX specific initialization */1116	SETUP_HCRX(fb);1117 1118	/*1119	if (id == S9000_ID_HCRX)1120		hyperInitSprite(fb);1121	else1122		ngleInitSprite(fb);1123	*/1124 1125	/* Initialize the image planes. */1126        switch (id) {1127	 case S9000_ID_HCRX:1128	    hyperResetPlanes(fb, ENABLE);1129	    break;1130	 case S9000_ID_A1439A:1131	    rattlerSetupPlanes(fb);1132	    break;1133	 case S9000_ID_A1659A:1134	 case S9000_ID_ARTIST:1135	 case CRT_ID_VISUALIZE_EG:1136	    elkSetupPlanes(fb);1137	    break;1138	}1139 1140	/* Clear attribute planes on non HCRX devices. */1141        switch (id) {1142	 case S9000_ID_A1659A:1143	 case S9000_ID_A1439A:1144	    if (fb->info->var.bits_per_pixel == 32)1145		ngleSetupAttrPlanes(fb, BUFF1_CMAP3);1146	    else {1147		ngleSetupAttrPlanes(fb, BUFF1_CMAP0);1148	    }1149	    if (id == S9000_ID_A1439A)1150		ngleClearOverlayPlanes(fb, 0xff, 0);1151	    break;1152	 case S9000_ID_ARTIST:1153	 case CRT_ID_VISUALIZE_EG:1154	    if (fb->info->var.bits_per_pixel == 32)1155		ngleSetupAttrPlanes(fb, BUFF1_CMAP3);1156	    else {1157		ngleSetupAttrPlanes(fb, ARTIST_CMAP0);1158	    }1159	    break;1160	}1161	stifb_blank(0, fb->info);	/* 0=enable screen */1162 1163	SETUP_FB(fb);1164}1165 1166/* ------------ Interfaces to hardware functions ------------ */1167 1168static const struct fb_ops stifb_ops = {1169	.owner		= THIS_MODULE,1170	__FB_DEFAULT_IOMEM_OPS_RDWR,1171	.fb_check_var	= stifb_check_var,1172	.fb_setcolreg	= stifb_setcolreg,1173	.fb_blank	= stifb_blank,1174	.fb_fillrect	= stifb_fillrect,1175	.fb_copyarea	= stifb_copyarea,1176	.fb_imageblit	= cfb_imageblit,1177	__FB_DEFAULT_IOMEM_OPS_MMAP,1178};1179 1180 1181/*1182 *  Initialization1183 */1184 1185static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)1186{1187	struct fb_fix_screeninfo *fix;1188	struct fb_var_screeninfo *var;1189	struct stifb_info *fb;1190	struct fb_info *info;1191	unsigned long sti_rom_address;1192	char modestr[32];1193	char *dev_name;1194	int bpp, xres, yres;1195 1196	info = framebuffer_alloc(sizeof(*fb), sti->dev);1197	if (!info)1198		return -ENOMEM;1199	fb = info->par;1200	fb->info = info;1201 1202	/* set struct to a known state */1203	fix = &info->fix;1204	var = &info->var;1205 1206	fb->sti = sti;1207	dev_name = sti->sti_data->inq_outptr.dev_name;1208	/* store upper 32bits of the graphics id */1209	fb->id = fb->sti->graphics_id[0];1210 1211	/* only supported cards are allowed */1212	switch (fb->id) {1213	case CRT_ID_VISUALIZE_EG:1214		/* Visualize cards can run either in "double buffer" or1215 		  "standard" mode. Depending on the mode, the card reports1216		  a different device name, e.g. "INTERNAL_EG_DX1024" in double1217		  buffer mode and "INTERNAL_EG_X1024" in standard mode.1218		  Since this driver only supports standard mode, we check1219		  if the device name contains the string "DX" and tell the1220		  user how to reconfigure the card. */1221		if (strstr(dev_name, "DX")) {1222		   printk(KERN_WARNING1223"WARNING: stifb framebuffer driver does not support '%s' in double-buffer mode.\n"1224"WARNING: Please disable the double-buffer mode in IPL menu (the PARISC-BIOS).\n",1225			dev_name);1226		   goto out_err0;1227		}1228		fallthrough;1229	case S9000_ID_ARTIST:1230	case S9000_ID_HCRX:1231	case S9000_ID_TIMBER:1232	case S9000_ID_A1659A:1233	case S9000_ID_A1439A:1234		break;1235	default:1236		printk(KERN_WARNING "stifb: '%s' (id: 0x%08x) not supported.\n",1237			dev_name, fb->id);1238		goto out_err0;1239	}1240 1241	/* default to 8 bpp on most graphic chips */1242	bpp = 8;1243	xres = sti_onscreen_x(fb->sti);1244	yres = sti_onscreen_y(fb->sti);1245 1246	ngleGetDeviceRomData(fb);1247 1248	/* get (virtual) io region base addr */1249	fix->mmio_start = REGION_BASE(fb,2);1250	fix->mmio_len   = 0x400000;1251 1252       	/* Reject any device not in the NGLE family */1253	switch (fb->id) {1254	case S9000_ID_A1659A:	/* CRX/A1659A */1255		break;1256	case S9000_ID_ELM:	/* GRX, grayscale but else same as A1659A */1257		var->grayscale = 1;1258		fb->id = S9000_ID_A1659A;1259		break;1260	case S9000_ID_TIMBER:	/* HP9000/710 Any (may be a grayscale device) */1261		if (strstr(dev_name, "GRAYSCALE") ||1262		    strstr(dev_name, "Grayscale") ||1263		    strstr(dev_name, "grayscale"))1264			var->grayscale = 1;1265		break;1266	case S9000_ID_TOMCAT:	/* Dual CRX, behaves else like a CRX */1267		/* FIXME: TomCat supports two heads:1268		 * fb.iobase = REGION_BASE(fb_info,3);1269		 * fb.screen_base = ioremap(REGION_BASE(fb_info,2),xxx);1270		 * for now we only support the left one ! */1271		xres = fb->ngle_rom.x_size_visible;1272		yres = fb->ngle_rom.y_size_visible;1273		fb->id = S9000_ID_A1659A;1274		break;1275	case S9000_ID_A1439A:	/* CRX24/A1439A */1276		bpp = 32;1277		break;1278	case S9000_ID_HCRX:	/* Hyperdrive/HCRX */1279		memset(&fb->ngle_rom, 0, sizeof(fb->ngle_rom));1280		if ((fb->sti->regions_phys[0] & 0xfc000000) ==1281		    (fb->sti->regions_phys[2] & 0xfc000000))1282			sti_rom_address = F_EXTEND(fb->sti->regions_phys[0]);1283		else1284			sti_rom_address = F_EXTEND(fb->sti->regions_phys[1]);1285 1286		fb->deviceSpecificConfig = gsc_readl(sti_rom_address);1287		if (IS_24_DEVICE(fb)) {1288			if (bpp_pref == 8 || bpp_pref == 32)1289				bpp = bpp_pref;1290			else1291				bpp = 32;1292		} else1293			bpp = 8;1294		READ_WORD(fb, REG_15);1295		SETUP_HW(fb);1296		break;1297	case CRT_ID_VISUALIZE_EG:1298	case S9000_ID_ARTIST:	/* Artist */1299		break;1300	default:1301#ifdef FALLBACK_TO_1BPP1302		printk(KERN_WARNING1303			"stifb: Unsupported graphics card (id=0x%08x) "1304				"- now trying 1bpp mode instead\n",1305			fb->id);1306		bpp = 1;	/* default to 1 bpp */1307		break;1308#else1309		printk(KERN_WARNING1310			"stifb: Unsupported graphics card (id=0x%08x) "1311				"- skipping.\n",1312			fb->id);1313		goto out_err0;1314#endif1315	}1316 1317 1318	/* get framebuffer physical and virtual base addr & len (64bit ready) */1319	fix->smem_start = F_EXTEND(fb->sti->regions_phys[1]);1320	fix->smem_len = fb->sti->regions[1].region_desc.length * 4096;1321 1322	fix->line_length = (fb->sti->glob_cfg->total_x * bpp) / 8;1323	if (!fix->line_length)1324		fix->line_length = 2048; /* default */1325 1326	/* limit fbsize to max visible screen size */1327	if (fix->smem_len > yres*fix->line_length)1328		fix->smem_len = ALIGN(yres*fix->line_length, 4*1024*1024);1329 1330	fix->accel = FB_ACCEL_NONE;1331 1332	switch (bpp) {1333	    case 1:1334		fix->type = FB_TYPE_PLANES;	/* well, sort of */1335		fix->visual = FB_VISUAL_MONO10;1336		var->red.length = var->green.length = var->blue.length = 1;1337		break;1338	    case 8:1339		fix->type = FB_TYPE_PACKED_PIXELS;1340		fix->visual = FB_VISUAL_PSEUDOCOLOR;1341		var->red.length = var->green.length = var->blue.length = 8;1342		break;1343	    case 32:1344		fix->type = FB_TYPE_PACKED_PIXELS;1345		fix->visual = FB_VISUAL_DIRECTCOLOR;1346		var->red.length = var->green.length = var->blue.length = var->transp.length = 8;1347		var->blue.offset = 0;1348		var->green.offset = 8;1349		var->red.offset = 16;1350		var->transp.offset = 24;1351		break;1352	    default:1353		break;1354	}1355 1356	var->xres = var->xres_virtual = xres;1357	var->yres = var->yres_virtual = yres;1358	var->bits_per_pixel = bpp;1359 1360	strcpy(fix->id, "stifb");1361	info->fbops = &stifb_ops;1362	info->screen_base = ioremap(REGION_BASE(fb,1), fix->smem_len);1363	if (!info->screen_base) {1364		printk(KERN_ERR "stifb: failed to map memory\n");1365		goto out_err0;1366	}1367	info->screen_size = fix->smem_len;1368	info->flags = FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;1369	info->pseudo_palette = &fb->pseudo_palette;1370 1371	scnprintf(modestr, sizeof(modestr), "%dx%d-%d", xres, yres, bpp);1372	fb_find_mode(&info->var, info, modestr, NULL, 0, NULL, bpp);1373 1374	/* This has to be done !!! */1375	if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0))1376		goto out_err1;1377	stifb_init_display(fb);1378 1379	if (!request_mem_region(fix->smem_start, fix->smem_len, "stifb fb")) {1380		printk(KERN_ERR "stifb: cannot reserve fb region 0x%04lx-0x%04lx\n",1381				fix->smem_start, fix->smem_start+fix->smem_len);1382		goto out_err2;1383	}1384 1385	if (!request_mem_region(fix->mmio_start, fix->mmio_len, "stifb mmio")) {1386		printk(KERN_ERR "stifb: cannot reserve sti mmio region 0x%04lx-0x%04lx\n",1387				fix->mmio_start, fix->mmio_start+fix->mmio_len);1388		goto out_err3;1389	}1390 1391	/* save for primary gfx device detection & unregister_framebuffer() */1392	if (register_framebuffer(fb->info) < 0)1393		goto out_err4;1394 1395	fb_info(fb->info, "%s %dx%d-%d frame buffer device, %s, id: %04x, mmio: 0x%04lx\n",1396		fix->id,1397		var->xres,1398		var->yres,1399		var->bits_per_pixel,1400		dev_name,1401		fb->id,1402		fix->mmio_start);1403 1404	dev_set_drvdata(sti->dev, info);1405 1406	return 0;1407 1408 1409out_err4:1410	release_mem_region(fix->mmio_start, fix->mmio_len);1411out_err3:1412	release_mem_region(fix->smem_start, fix->smem_len);1413out_err2:1414	fb_dealloc_cmap(&info->cmap);1415out_err1:1416	iounmap(info->screen_base);1417out_err0:1418	framebuffer_release(info);1419	return -ENXIO;1420}1421 1422static int stifb_disabled __initdata;1423 1424int __init1425stifb_setup(char *options);1426 1427static int __init stifb_init(void)1428{1429	struct sti_struct *sti;1430	struct sti_struct *def_sti;1431	int i;1432 1433#ifndef MODULE1434	char *option = NULL;1435 1436	if (fb_get_options("stifb", &option))1437		return -ENODEV;1438	stifb_setup(option);1439#endif1440	if (stifb_disabled) {1441		printk(KERN_INFO "stifb: disabled by \"stifb=off\" kernel parameter\n");1442		return -ENXIO;1443	}1444 1445	def_sti = sti_get_rom(0);1446	if (def_sti) {1447		for (i = 1; i <= MAX_STI_ROMS; i++) {1448			sti = sti_get_rom(i);1449			if (!sti)1450				break;1451			if (sti == def_sti) {1452				stifb_init_fb(sti, stifb_bpp_pref[i - 1]);1453				break;1454			}1455		}1456	}1457 1458	for (i = 1; i <= MAX_STI_ROMS; i++) {1459		sti = sti_get_rom(i);1460		if (!sti)1461			break;1462		if (sti == def_sti)1463			continue;1464		stifb_init_fb(sti, stifb_bpp_pref[i - 1]);1465	}1466	return 0;1467}1468 1469/*1470 *  Cleanup1471 */1472 1473static void __exit1474stifb_cleanup(void)1475{1476	struct sti_struct *sti;1477	int i;1478 1479	for (i = 1; i <= MAX_STI_ROMS; i++) {1480		sti = sti_get_rom(i);1481		if (!sti)1482			break;1483		if (sti->dev) {1484			struct fb_info *info = dev_get_drvdata(sti->dev);1485 1486			if (!info)1487				continue;1488			unregister_framebuffer(info);1489			release_mem_region(info->fix.mmio_start, info->fix.mmio_len);1490		        release_mem_region(info->fix.smem_start, info->fix.smem_len);1491				if (info->screen_base)1492					iounmap(info->screen_base);1493		        fb_dealloc_cmap(&info->cmap);1494		        framebuffer_release(info);1495			dev_set_drvdata(sti->dev, NULL);1496		}1497	}1498}1499 1500int __init1501stifb_setup(char *options)1502{1503	int i;1504 1505	if (!options || !*options)1506		return 1;1507 1508	if (strncmp(options, "off", 3) == 0) {1509		stifb_disabled = 1;1510		options += 3;1511	}1512 1513	if (strncmp(options, "bpp", 3) == 0) {1514		options += 3;1515		for (i = 0; i < MAX_STI_ROMS; i++) {1516			if (*options++ != ':')1517				break;1518			stifb_bpp_pref[i] = simple_strtoul(options, &options, 10);1519		}1520	}1521	return 1;1522}1523 1524__setup("stifb=", stifb_setup);1525 1526module_init(stifb_init);1527module_exit(stifb_cleanup);1528 1529MODULE_AUTHOR("Helge Deller <deller@gmx.de>, Thomas Bogendoerfer <tsbogend@alpha.franken.de>");1530MODULE_DESCRIPTION("Framebuffer driver for HP's NGLE series graphics cards in HP PARISC machines");1531MODULE_LICENSE("GPL v2");1532