[parisc-linux-cvs] pa11, more stifb-code for non-artist gfx's

Helge Deller deller@gmx.de
Wed, 11 Jul 2001 00:21:54 +0200


- EXTRAVERSION = -pa11
- more code for other gfx chips other than artist
(but still #ifdef'ed  out for non-artist chips. Feel free to
take this #if..#endif out and test the code)

Index: Makefile
===================================================================
RCS file: /home/cvs/parisc/linux/Makefile,v
retrieving revision 1.93
diff -u -r1.93 Makefile
--- Makefile	2001/07/10 16:50:51	1.93
+++ Makefile	2001/07/10 22:10:07
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 6
-EXTRAVERSION = -pa10
+EXTRAVERSION = -pa11
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
Index: drivers/video/sti/stifb.c
===================================================================
RCS file: /home/cvs/parisc/linux/drivers/video/sti/stifb.c,v
retrieving revision 1.18
diff -u -r1.18 stifb.c
--- stifb.c	2001/07/08 12:41:57	1.18
+++ stifb.c	2001/07/10 22:10:19
@@ -37,7 +37,16 @@
  * for more details.
  */
 
+/* TODO:
+ *	- Artist gfx is the only supported chip atm,
+ *	- remove the static fb_info to support multiple cards
+ *	- remove the completely untested 1bpp mode
+ *	- add support for h/w acceleration
+ *	- add hardware cursor
+ *	-
+ */
 
+
 /* on supported graphic devices you may:
  * #define FALLBACK_TO_1BPP to fall back to 1 bpp, or
  * #undef  FALLBACK_TO_1BPP to reject support for unsupported cards */
@@ -58,7 +67,6 @@
 #include <linux/selection.h>
 
 #include <video/fbcon.h>
-#include <video/fbcon-cfb4.h>
 #include <video/fbcon-cfb8.h>
 #include <video/fbcon-cfb24.h>
 
@@ -100,7 +108,7 @@
 struct stifb_info {
 	struct fb_info_gen gen;
 	struct sti_struct *sti;
-	__u32 id;
+	unsigned int id, real_id;
 	unsigned long iobase;
 	unsigned long smem_start; /* Start of frame buffer mem (physical address) */
 	unsigned long smem_len;		/* size of framebuffer */
@@ -108,6 +116,8 @@
 	char *screen_base;		/* Virtual address (io-remapped) */
 	int grayscale;
 	int bpp;
+	int screenWidth;
+	int screenHeight;
 	int deviceSpecificConfig;
 	ngle_rom_t ngle_rom;
 	struct { u_short red, green, blue; } palette[256];
@@ -143,6 +153,7 @@
 #define REG_12		0x01800c
 #define REG_13		0x018018
 #define REG_14  	0x01801c
+#define REG_15		0x200000
 #define REG_15b0	0x200000
 #define REG_16b1	0x200005
 #define REG_16b3	0x200007
@@ -155,6 +166,12 @@
 #define REG_33		0x210040
 #define REG_34		0x200008
 #define REG_38		0x210020
+#define REG_39		0x210120
+#define REG_40		0x210130
+#define REG_42		0x210028
+#define REG_43		0x21002c
+#define REG_44		0x210030
+#define REG_45		0x210034
 
 #define READ_BYTE(base)		readb(base)
 #define READ_WORD(base)		readl(base)
@@ -184,7 +201,6 @@
 SETUP_FB(struct stifb_info *fb_info)
 {	
 	unsigned int reg10_value = 0;
-	int depth = fb_info->bpp;
 	
 	SETUP_HW(fb_info);
 	switch (fb_info->id)
@@ -194,13 +210,13 @@
 			reg10_value = 0x13601000;
 			break;
 		case S9000_ID_A1439A:
-			if (depth == 24)						
+			if (fb_info->bpp == 24)						
 				reg10_value = 0xBBA0A000;
 			else 
 				reg10_value = 0x13601000;
 			break;
 		case S9000_ID_HCRX:
-			if (depth == 24)
+			if (fb_info->bpp == 24)
 				reg10_value = 0xBBA0A000;
 			else					
 				reg10_value = 0x13602000;
@@ -470,13 +486,31 @@
 ngleSetupAttrPlanes(struct stifb_info *fb_info, int BufferNumber)
 {
 	SETUP_ATTR_ACCESS(fb_info, BufferNumber);
-	SET_ATTR_SIZE(fb_info, current_par.x_virt, current_par.y_virt );
-	/* XXX: pScreenPriv->screenWidth, pScreenPriv->screenHeight */
+	SET_ATTR_SIZE(fb_info, fb_info->screenWidth, fb_info->screenHeight);
 	FINISH_ATTR_ACCESS(fb_info);
 	SETUP_FB(fb_info);
 }
 
 
+static void
+rattlerSetupPlanes(struct stifb_info *fb_info)
+{
+	CRX24_SETUP_RAMDAC(fb_info);
+    
+	/* replacement for: SETUP_FB(fb_info, CRX24_OVERLAY_PLANES); */
+	WRITE_WORD(0x83000300, fb_info->iobase + REG_14);
+	SETUP_HW(fb_info);
+	WRITE_BYTE(1, fb_info->iobase + REG_16b1);
+
+	/* XXX: replace by fb_setmem(), smem_start or screen_base ? */
+	memset_io(fb_info->smem_start, 0xff,
+		fb_info->screenHeight*fb_info->line_length);
+    
+	CRX24_SET_OVLY_MASK(fb_info);
+	SETUP_FB(fb_info);
+}
+
+
 #define HYPER_CMAP_TYPE				0
 #define NGLE_CMAP_INDEXED0_TYPE			0
 #define NGLE_CMAP_OVERLAY_TYPE			3
@@ -500,7 +534,6 @@
 static NgleLutBltCtl
 setNgleLutBltCtl(struct stifb_info *fb_info, int offsetWithinLut, int length)
 {
-	int depth = fb_info->bpp;
 	NgleLutBltCtl lutBltCtl;
 
 	/* set enable, zero reserved fields */
@@ -510,7 +543,7 @@
 	switch (fb_info->id) 
 	{
 	case S9000_ID_A1439A:		/* CRX24 */
-		if (depth == 8) {
+		if (fb_info->bpp == 8) {
 			lutBltCtl.fields.lutType = NGLE_CMAP_OVERLAY_TYPE;
 			lutBltCtl.fields.lutOffset = 0;
 		} else {
@@ -540,7 +573,6 @@
 static NgleLutBltCtl
 setHyperLutBltCtl(struct stifb_info *fb_info, int offsetWithinLut, int length) 
 {
-	int depth = fb_info->bpp;
 	NgleLutBltCtl lutBltCtl;
 
 	/* set enable, zero reserved fields */
@@ -550,7 +582,7 @@
 	lutBltCtl.fields.lutType = HYPER_CMAP_TYPE;
 
 	/* Expect lutIndex to be 0 or 1 for image cmaps, 2 or 3 for overlay cmaps */
-	if (depth == 8)
+	if (fb_info->bpp == 8)
 		lutBltCtl.fields.lutOffset = 2 * 256;
 	else
 		lutBltCtl.fields.lutOffset = 0 * 256;
@@ -634,7 +666,7 @@
 		controlPlaneReg = 0x00000F00; /* 0x00000100 should be enought, but lets clear all 4 bits */
 
 	switch (enable) {
-	case 1:		/* SERVER_INIT */
+	case 1:		/* ENABLE */
 		/* clear screen */
 		if (IS_24_DEVICE(fb_info))
 			ngleDepth24_ClearImagePlanes(fb_info);
@@ -657,7 +689,7 @@
 		hyperUndoITE(fb_info);
 		break;
 
-	case 0:		/* SERVER_EXIT */
+	case 0:		/* DISABLE */
 		/* clear screen */
 		if (IS_24_DEVICE(fb_info))
 			ngleDepth24_ClearImagePlanes(fb_info);
@@ -667,7 +699,7 @@
 		ngleClearOverlayPlanes(fb_info, 0xff, 0);
 		break;
 
-	case -1:	/* SERVER_RECOVERY */
+	case -1:	/* RESET */
 		hyperUndoITE(fb_info);
 		ngleResetAttrPlanes(fb_info, controlPlaneReg);
 		break;
@@ -678,10 +710,11 @@
 
 /* Return pointer to in-memory structure holding ELK device-dependent ROM values. */
 
-#if 0
 static void 
 ngleGetDeviceRomData(struct stifb_info *fb_info)
 {
+#if 0
+XXX: FIXME: !!!
 	int	*pBytePerLongDevDepData;/* data byte == LSB */
 	int 	*pRomTable;
 	NgleDevRomData	*pPackedDevRomData;
@@ -733,12 +766,59 @@
 	    *pCard8++ = (Card8) (*pBytePerLongDevDepData++);
 	}
     }
-
-    SETUP_FB(pDregs,pScreenPriv->deviceID,pScreenPriv->devDepth);
 
-    return(pPackedDevRomData);
-}   /* ngleGetDeviceRomData() */
+    SETUP_FB(fb_info);
 #endif
+}
+
+
+#define HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES	4
+#define HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE	8
+#define HYPERBOWL_MODE01_8_24_LUT0_OPAQUE_LUT1_OPAQUE		10
+#define HYPERBOWL_MODE2_8_24					15
+
+/* HCRX specific boot-time initialization */
+static void __init
+SETUP_HCRX(struct stifb_info *fb_info)
+{
+	int	hyperbowl;
+        int	nFreeFifoSlots = 0;
+	unsigned long base = fb_info->iobase;
+
+	if (fb_info->id != S9000_ID_HCRX)
+		return;
+
+	/* Initialize Hyperbowl registers */
+	GET_FIFO_SLOTS(fb_info, nFreeFifoSlots, 7);
+	
+	if (IS_24_DEVICE(fb_info)) {
+		hyperbowl = (fb_info->bpp == 24) ?
+			HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE :
+			HYPERBOWL_MODE01_8_24_LUT0_OPAQUE_LUT1_OPAQUE;
+
+		/* First write to Hyperbowl must happen twice (bug) */
+		WRITE_WORD(hyperbowl, base + REG_40);
+		WRITE_WORD(hyperbowl, base + REG_40);
+		
+		WRITE_WORD(HYPERBOWL_MODE2_8_24, base + REG_39);
+		
+		WRITE_WORD(0x014c0148, base + REG_42); /* Set lut 0 to be the direct color */
+		WRITE_WORD(0x404c4048, base + REG_43);
+		WRITE_WORD(0x034c0348, base + REG_44);
+		WRITE_WORD(0x444c4448, base + REG_45);
+	} else {
+		hyperbowl = HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES;
+
+		/* First write to Hyperbowl must happen twice (bug) */
+		WRITE_WORD(hyperbowl, base + REG_40);
+		WRITE_WORD(hyperbowl, base + REG_40);
+
+		WRITE_WORD(0x00000000, base + REG_42);
+		WRITE_WORD(0x00000000, base + REG_43);
+		WRITE_WORD(0x00000000, base + REG_44);
+		WRITE_WORD(0x444c4048, base + REG_45);
+	}
+}
 
 
 /* ------------------- driver specific functions --------------------------- */
@@ -757,6 +837,8 @@
 	fix->line_length = fb_info->line_length;
 	fix->smem_start = fb_info->smem_start;
 	fix->smem_len = fb_info->smem_len;
+	fix->mmio_start = fb_info->iobase;	/* ioremap() ? */
+	fix->mmio_len = 0x300000;		/* XXX */
 
 	if (par->bpp == 1) {
 	    fix->type = FB_TYPE_PLANES;	/* well, sort of */
@@ -807,11 +889,26 @@
 	var->yres_virtual = par->y_virt;
 	var->xoffset = var->yoffset = 0;
 	var->bits_per_pixel = par->bpp;
-	var->grayscale = 0;
+	var->grayscale = 0; /* XXX: ((struct stifb_info *)info)->grayscale; */
 	var->height = -1;
 	var->width = -1;
 	var->vmode = FB_VMODE_NONINTERLACED;
 
+	if (par->bpp == 24) {
+		/* correct the RGB masks and offsets */
+		var->red.offset		= 16;
+		var->green.offset	= 8;
+		var->blue.offset	= 0;
+			
+		var->red.msb_right	= 
+		var->green.msb_right	= 
+		var->blue.msb_right	= 8;
+		
+		var->red.msb_right	= 
+		var->green.msb_right	= 
+		var->blue.msb_right	= 0; /* XXX: !=0: Most significant bit is right */
+	}
+
 	return 0;
 }
 
@@ -819,11 +916,12 @@
 stifb_get_par(void *par, struct fb_info_gen *info)
 {
 	if (!current_par_valid) {
-		current_par.x = sti_onscreen_x(fb_info.sti);
-		current_par.y = sti_onscreen_y(fb_info.sti);
-		current_par.x_virt = PTR_STI(fb_info.sti->glob_cfg)->total_x;
-		current_par.y_virt = PTR_STI(fb_info.sti->glob_cfg)->total_y;
-		current_par.bpp = fb_info.bpp;
+		struct stifb_info *p = (struct stifb_info *) info;
+		current_par.x = p->screenWidth;
+		current_par.y = p->screenHeight;
+		current_par.x_virt = PTR_STI(p->sti->glob_cfg)->total_x;
+		current_par.y_virt = PTR_STI(p->sti->glob_cfg)->total_y;
+		current_par.bpp = p->bpp;
 		current_par_valid = 1;
 	}
 	*(struct stifb_par *)par = current_par; 
@@ -900,50 +998,12 @@
 }
 
 static void
-stifb_set_disp(const void *_par,
-		struct display *disp,
-		struct fb_info_gen *info)
-{
-	struct stifb_info *fb_info = (struct stifb_info *) info;
-	const struct stifb_par *par = _par;
-	
-	disp->screen_base = fb_info->screen_base;
-	
-	/* Hack: Currently only Artist-Framebuffer supported ! */
-	if (fb_info->id == S9000_ID_ARTIST) {
-	//	elkSetupPlanes(fb_info);	/* XXX */
-		ngleSetupAttrPlanes(fb_info, ARTIST_CMAP0);
-	//	ngleSetupAttrPlanes(fb_info, BUFF0_CMAP0);
-		ARTIST_ENABLE_DISABLE_DISPLAY(fb_info, ENABLE);
-		SETUP_FB(fb_info); 
-	}
-
-	switch(par->bpp) {
-#ifdef FBCON_HAS_CFB24
-	case 24:disp->dispsw = &fbcon_cfb24;
-        	break;
-#endif
-#ifdef FBCON_HAS_CFB8
-	case 8:	disp->dispsw = &fbcon_cfb8;
-        	break;
-#endif
-	case 1:	disp->dispsw = &fbcon_sti;
-		break;
-		
-	default:
-		disp->dispsw = &fbcon_dummy;
-    	}
-	
-	disp->scrollmode = SCROLL_YREDRAW;
-}
-
-static void
 stifb_detect(void)
 {
 	struct stifb_par par;
 	
-	par.x = sti_onscreen_x(fb_info.sti);
-	par.y = sti_onscreen_y(fb_info.sti);
+	par.x = fb_info.screenWidth;
+	par.y = fb_info.screenHeight;
 	par.x_virt = PTR_STI(fb_info.sti->glob_cfg)->total_x;
 	par.y_virt = PTR_STI(fb_info.sti->glob_cfg)->total_y;
 	par.bpp = fb_info.bpp;
@@ -985,6 +1045,65 @@
 	return 1;  /* FIXME: should be 0 later ! */
 }
 
+static void
+stifb_set_disp(const void *_par,
+		struct display *disp,
+		struct fb_info_gen *info)
+{
+	struct stifb_info *fb_info = (struct stifb_info *) info;
+	const struct stifb_par *par = _par;
+	int id = fb_info->id;
+	
+	disp->screen_base = fb_info->screen_base;
+	disp->scrollmode = SCROLL_YREDRAW;
+	
+	/*
+	if (id == S9000_ID_HCRX)
+		hyperInitSprite(fb_info);
+	else
+		ngleInitSprite(fb_info);
+	*/
+	
+	/* Initialize the image planes. */ 
+	if (id == S9000_ID_HCRX)
+		hyperResetPlanes(fb_info, ENABLE);
+	else if (id == S9000_ID_A1439A)
+		rattlerSetupPlanes(fb_info);
+	else if (id == S9000_ID_A1659A /* || id == S9000_ID_ARTIST*/)
+		elkSetupPlanes(fb_info);
+
+	/* Clear attribute planes on non HCRX devices. */
+	if (id == S9000_ID_A1659A || id == S9000_ID_A1439A ||
+		id == S9000_ID_ARTIST) {
+		if (fb_info->bpp == 24)
+			ngleSetupAttrPlanes(fb_info, BUFF1_CMAP3);
+		else
+			ngleSetupAttrPlanes(fb_info, (id==S9000_ID_ARTIST) ?
+					ARTIST_CMAP0 : BUFF1_CMAP0);
+	}		
+
+	stifb_blank(0, info);	/* 0=enable screen */
+
+	SETUP_FB(fb_info);
+	
+	switch(par->bpp) {
+#ifdef FBCON_HAS_CFB24
+	case 24:disp->dispsw = &fbcon_cfb24;
+        	break;
+#endif
+#ifdef FBCON_HAS_CFB8
+	case 8:	disp->dispsw = &fbcon_cfb8;
+        	break;
+#endif
+	case 1:	disp->dispsw = &fbcon_sti;
+		break;
+		
+	default:
+		disp->dispsw = &fbcon_dummy;
+    	}
+}
+
+
 /* ------------ Interfaces to hardware functions ------------ */
 
 struct fbgen_hwswitch stifb_switch = {
@@ -1022,6 +1141,8 @@
 stifb_init(void)
 {
 	static int stifb_initialized;
+	unsigned long sti_rom_address;
+	char *dev_name;
 
 	if (stifb_initialized) {
 		printk(KERN_WARNING "WARNING: Only one stifb will be supported currently.\n");
@@ -1036,6 +1157,14 @@
 
 	/* store upper 32bits of the graphics id */
 	fb_info.id = fb_info.sti->graphics_id[0];
+	fb_info.real_id = fb_info.id;	/* save the real id */
+
+#if 1
+	/* HACK: Only allow an Artist gfx */
+	if (fb_info.id != S9000_ID_ARTIST) {
+		return -ENXIO;
+	}
+#endif
 	
 	/* get (virtual) io region base addr */
 	fb_info.iobase = REGION_BASE(fb_info,2);
@@ -1049,29 +1178,54 @@
 				fb_info.line_length;
 	fb_info.screen_base = (void*) REGION_BASE(fb_info,1);
 
+	fb_info.screenWidth = sti_onscreen_x(fb_info.sti);
+	fb_info.screenHeight = sti_onscreen_y(fb_info.sti);
+	
+	/* default to 8 bpp on most graphic chips */
+	fb_info.bpp = 8;
+
+	ngleGetDeviceRomData(&fb_info);
+	
        	/* Reject any device not in the NGLE family */
-	/* FIXME: At this stage only Artist fb is supported! */
 	switch (fb_info.id) {
-	case S9000_ID_A1659A:	/* CRX */
-		printk("Found CRX/A1659A graphics. Support is not finished yet.\n");
-		return -ENODEV;
-	case S9000_ID_ELM:	/* GRX */
-		printk("Found ELM/GRX graphics. Support is not finished yet.\n");
-		return -ENODEV;
-	case S9000_ID_TIMBER:	/* 710 Any */
-		printk("Found Timber/710 style graphics. Support is not finished yet.\n");
-		return -ENODEV;
-	case S9000_ID_TOMCAT:	/* Dual CRX */
-		printk("Found Tomcat/Dual-CRX graphics. Support is not finished yet.\n");
-		return -ENODEV;
-	case S9000_ID_A1439A:	/* CRX24 */
-		printk("Found CRX24/A1439A graphics. Support is not finished yet.\n");
-		return -ENODEV;
-	case S9000_ID_HCRX:	/* Hyperdrive */
-		printk("Found Hyperdrive/HCRX graphics. Support is not finished yet.\n");
-		return -ENODEV;
+	case S9000_ID_A1659A:	/* CRX/A1659A */
+		break;
+	case S9000_ID_ELM:	/* GRX, grayscale but else same as A1659A */
+		fb_info.grayscale = 1;
+		fb_info.id = S9000_ID_A1659A;
+		break;
+	case S9000_ID_TIMBER:	/* HP9000/710 Any (may be a grayscale device) */
+		dev_name = fb_info.sti->outptr.dev_name;
+		if (strstr(dev_name, "GRAYSCALE") || 
+		    strstr(dev_name, "Grayscale") ||
+		    strstr(dev_name, "grayscale"))
+			fb_info.grayscale = 1;
+		break;
+	case S9000_ID_TOMCAT:	/* Dual CRX, behaves else like a CRX */
+		/* FIXME: TomCat supports two heads:
+		 * fb_info.iobase = REGION_BASE(fb_info,3);
+		 * fb_info.screen_base = (void*) REGION_BASE(fb_info,2);
+		 * for now we only support the left one ! */
+		fb_info.screenWidth = fb_info.ngle_rom.x_size_visible;
+		fb_info.screenHeight = fb_info.ngle_rom.y_size_visible;
+		fb_info.id = S9000_ID_A1659A;
+		break;
+	case S9000_ID_A1439A:	/* CRX24/A1439A */
+		fb_info.bpp = 24;
+		break;
+	case S9000_ID_HCRX:	/* Hyperdrive/HCRX */
+		memset(&fb_info.ngle_rom, 0, sizeof(fb_info.ngle_rom));
+		fb_info.bpp = 24;
+		if ((fb_info.sti->regions_phys[0] & 0xfc000000) ==
+		    (fb_info.sti->regions_phys[2] & 0xfc000000))
+			sti_rom_address = fb_info.sti->regions_phys[2];
+		else
+			sti_rom_address = fb_info.sti->regions_phys[3];
+		READ_WORD(fb_info.iobase + REG_15);
+		SETUP_HW(&fb_info);
+		fb_info.deviceSpecificConfig = gsc_readl(sti_rom_address);
+		break;
 	case S9000_ID_ARTIST:	/* Artist */
-		fb_info.bpp = 8;	/* default to 8 bpp */
 		break;
 	default: 
 #ifdef FALLBACK_TO_1BPP
@@ -1089,7 +1243,12 @@
 		return -ENXIO;
 #endif
 	}
-	    
+
+	SETUP_FB(&fb_info);
+
+	/* HCRX specific initialization */
+	SETUP_HCRX(&fb_info);
+
 	strcpy(fb_info.gen.info.modename, "stifb");
 	fb_info.gen.info.node = -1;
 	fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;