[parisc-linux] [PATCH] Voodoo framebuffer on PARISC

Helge Deller deller@gmx.de
Sun, 15 Sep 2002 02:09:46 +0200


--Boundary-00=_K/8g9cdhjiEuAkF
Content-Type: text/plain;
  charset="us-ascii"
Content-Transfer-Encoding: 8bit
Content-Disposition: inline

Hi,

there has been some discussions on this lists a few weeks back
about getting the Voodoo framebuffer driver  working on HPPA.
The attached patch allows me to use my Voodoo 2 with the sstfb
framebuffer driver in 16bpp in 640x480, 800x600 and 1024x768
resolutions on console and under X.

Greetings,
Helge

NB: This patch is already integrated into the 2.4.19-pa18 kernel and
I'll continue to do some more code-cleanups before trying to get it
into the official kernel.

--Boundary-00=_K/8g9cdhjiEuAkF
Content-Type: text/plain;
  charset="us-ascii";
  name="diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="diff"

Index: sstfb.c
===================================================================
RCS file: /var/cvs/linux/drivers/video/sstfb.c,v
retrieving revision 1.4
diff -u -p -r1.4 sstfb.c
--- sstfb.c	4 Aug 2002 22:59:15 -0000	1.4
+++ sstfb.c	14 Sep 2002 23:58:43 -0000
@@ -107,6 +107,7 @@
 
 #include <asm/io.h>
 #include <asm/ioctl.h>
+#include <asm/uaccess.h>
 
 #include <video/fbcon.h>
 #include <video/fbcon-cfb16.h>
@@ -332,7 +333,7 @@ static void sst_dbg_print_var(struct fb_
 
 #if (SST_DEBUG_REG > 0)
 static void sst_dbg_print_read_reg (u32 reg, u32 val) {
-	char * regname =NULL;
+	char * regname = NULL;
 	switch (reg) {
 	case FBIINIT0: regname="FbiInit0"; break;
 	case FBIINIT1: regname="FbiInit1"; break;
@@ -366,8 +367,8 @@ static void sst_dbg_print_write_reg (u32
 		r_dprintk(" sst_write(%s, %#x)\n", regname, val);
 }
 #else /*  (SST_DEBUG_REG > 0) */
-#  define sst_dbg_print_read_reg(reg, val)	do {}while(0)
-#  define sst_dbg_print_write_reg(reg, val)	do {}while(0)
+#  define sst_dbg_print_read_reg(reg, val)	do {} while(0)
+#  define sst_dbg_print_write_reg(reg, val)	do {} while(0)
 #endif /*  (SST_DEBUG_REG > 0) */
 
 /* register access */
@@ -530,20 +531,15 @@ static int sstfb_setcolreg(u_int regno, 
 		break;
 #endif
 #ifdef EN_24_32_BPP
-#ifdef FBCON_HAS_CFB24
+#if defined(FBCON_HAS_CFB24) || defined(FBCON_HAS_CFB32)
 	case 24:
-		sst_info->fbcon_cmap.cfb32[regno]=col;
-		break;
-#endif
-#ifdef FBCON_HAS_CFB32
 	case 32:
 		sst_info->fbcon_cmap.cfb32[regno]=col;
 		break;
 #endif
 #endif
 	default:
-		eprintk("bug line %d: bad depth '%u'\n",__LINE__,
-			disp->var.bits_per_pixel);
+		BUG();
 		break;
 	}
 	f_dddprintk("bpp: %d . encoded color: %#x\n",
@@ -735,6 +731,7 @@ static int sstfb_encode_var (struct fb_v
 #ifdef EN_24_32_BPP
 	case 24:	/* RGB 888 LfbMode 4 */
 	case 32:	/* ARGB 8888 LfbMode 5 */
+	       	/* in 24bpp we fake a 32 bpp mode */
 		var->red.length    = 8;
 		var->green.length  = 8;
 		var->blue.length   = 8;
@@ -743,11 +740,11 @@ static int sstfb_encode_var (struct fb_v
 		var->red.offset    = 16;
 		var->green.offset  = 8;
 		var->blue.offset   = 0;
-		var->transp.offset = 0; /* in 24bpp we fake a 32 bpp mode */
+		var->transp.offset = 0;
 		break;
 #endif
 	default:
-		eprintk ("bug line %d: bad depth '%u'\n", __LINE__, par->bpp);
+		eprintk("bug line %d: bad depth '%u'\n", __LINE__, par->bpp);
 		break;
 	}
 	return 0;
@@ -775,11 +772,15 @@ static int sstfb_get_fix(struct fb_fix_s
 #define sst_info	((struct sstfb_info *) info)
 
 	struct fb_var_screeninfo *var;
+	struct fb_var_screeninfo var2;
 
 	f_dprintk("sstfb_get_fix(con: %d)\n",con);
-	if (con == -1)
-		sstfb_encode_var(var, &sst_info->current_par, sst_info);
-	else
+	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+	
+	if (con == -1) {
+		sstfb_encode_var(&var2, &sst_info->current_par, sst_info);
+		var = &var2;
+	} else
 		var = &fb_display[con].var;
 
 	strcpy(fix->id, sst_info->info.modename);
@@ -789,6 +790,7 @@ static int sstfb_get_fix(struct fb_fix_s
 
 	fix->type        = FB_TYPE_PACKED_PIXELS;
 	fix->visual      = FB_VISUAL_TRUECOLOR;
+	fix->accel       = FB_ACCEL_NONE;
 	/*
 	 *   According to the specs, the linelength must be of 1024 *pixels*.
 	 * and the 24bpp mode is in fact a 32 bpp mode.
@@ -966,42 +968,47 @@ static int sstfb_ioctl(struct inode *ino
                        struct fb_info *info)
 {
 #define sst_info	((struct sstfb_info *) info)
-#if (SST_DEBUG_IOCTL >0)
 	int i;
 	u_long p;
-	u32 tmp;
+	u32 tmp, val;
 	u32 fbiinit0;
 	struct pci_dev * sst_dev = sst_info->dev;
-#endif
 
 	f_dprintk("sstfb_ioctl(%x)\n", cmd);
-#if (SST_DEBUG_IOCTL >0)
+	
 	switch (cmd) {
-#  if (SST_DEBUG_VAR >0)
-/* tmp ioctl : dumps fb_display[0-5] */
+		
+#if (SST_DEBUG_VAR >0)
+	/* tmp ioctl : dumps fb_display[0-5] */
 	case _IO('F', 0xdb):		/* 0x46db */
 		f_dprintk("dumping fb_display[0-5].var\n");
 		for (i = 0 ; i< 6 ; i++) {
 			print_var(&fb_display[i].var, "var(%d)", i);
 		}
 		return 0;
-#  endif /* (SST_DEBUG_VAR >0) */
-/* fills the lfb up to *(u32*)arg */
+#endif /* (SST_DEBUG_VAR >0) */
+
+	/* fills the lfb up to given count of pixels */
 	case _IOW('F', 0xdc, u32):	/* 0x46dc */
-		if (*(u32*)arg > 0x400000 )
-			*(u32*) arg = 0x400000;
-		f_dprintk("filling %#x \n", *(u32*)arg);
-		for (p = 0 ; p < *(u32*)arg; p+=2)
+		if (copy_from_user(&val, (void *) arg, sizeof(val)))
+			return -EFAULT;
+		if (val > 0x400000 )
+			val = 0x400000;
+		f_dprintk("filling %#x \n", val);
+		for (p = 0 ; p < val; p+=2)
 			writew( p >> 6 , sst_info->video.vbase + p);
 		return 0;
-/* change VGA pass_through */
+		
+	/* enable/disable VGA pass_through */
 	case _IOW('F', 0xdd, u32):	/* 0x46dd */
+		if (copy_from_user(&val, (void *) arg, sizeof(val)))
+			return -EFAULT;
 		f_dprintk("switch VGA pass-through\n");
 		pci_read_config_dword(sst_dev, PCI_INIT_ENABLE, &tmp);
 		pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
 				       tmp | PCI_EN_INIT_WR );
 		fbiinit0 = sst_read (FBIINIT0);
-		if (* (u32*)arg) {
+		if (val) {
 			sst_write(FBIINIT0, fbiinit0 & ~EN_VGA_PASSTHROUGH);
 			iprintk ( "Disabling VGA pass-through\n");
 		} else {
@@ -1010,28 +1017,29 @@ static int sstfb_ioctl(struct inode *ino
 		}
 		pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp);
 		return 0;
+
+	/* display test pattern */
 	case _IO('F', 0xde):		/* 0x46de */
 		f_dprintk("test color display\n");
 		f_ddprintk("currcon: %d, bpp %d\n", sst_info->currcon,
 			  sst_info->current_par.bpp);
 		memset_io(sst_info->video.vbase, 0, sst_info->video.len);
-	switch (sst_info->current_par.bpp) {
+		switch (sst_info->current_par.bpp) {
 	       	case 16:
 			sstfb_test16(sst_info);
 			break;
-#  ifdef EN_24_32_BPP
+#ifdef EN_24_32_BPP
 		case 24:
 		case 32:
 			sstfb_test32(sst_info);
 			break;
-#  endif
+#endif
 		default:
-			dprintk("bug line %d: bad depth '%u'\n", __LINE__,
-			        sst_info->current_par.bpp);
-			}
+			return -EFAULT;
+		}
 		return 0;
 	}
-#endif /* (SST_DEBUG_IOCTL >0) */
+	
 	return -EINVAL;
 #undef sst_info
 }
@@ -1494,7 +1502,7 @@ static int sstfb_set_par(const struct ss
 	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR);
 
 	/* set lfbmode : set mode + front buffer for reads/writes
-	   + disable pipeline + disable byte swapping */
+	   + disable pipeline  */
 	switch(par->bpp) {
 	case 16:
 		lfbmode = LFB_565;
@@ -1508,12 +1516,16 @@ static int sstfb_set_par(const struct ss
 		break;
 #endif
 	default:
-		dprintk("bug line %d: bad depth '%u'\n", __LINE__,
-			par->bpp );
+		BUG();
 		return 0;
-		break;
 	}
 
+#if defined(__BIG_ENDIAN)
+	/* enable byte-swizzle functionality in hardware */
+	lfbmode |= ( LFB_WORD_SWIZZLE_WR | LFB_BYTE_SWIZZLE_WR | 
+		     LFB_WORD_SWIZZLE_RD | LFB_BYTE_SWIZZLE_RD );
+#endif
+
 	if (clipping) {
 		sst_write(LFBMODE, lfbmode | EN_PXL_PIPELINE);
 	/*
@@ -1521,7 +1533,7 @@ static int sstfb_set_par(const struct ss
 	 * writes to offscreen areas of the framebuffer are performed,
 	 * the "behaviour is undefined" (_very_ undefined) - Urs
 	 */
-	/* btw, it requires enabling pixel pipeline in LFBMODE .
+	/* btw, it requires enabling pixel pipeline in LFBMODE.
 	   off screen read/writes will just wrap and read/print pixels
 	   on screen. Ugly but not that dangerous */
 
@@ -1536,7 +1548,7 @@ static int sstfb_set_par(const struct ss
 		sst_write(LFBMODE, lfbmode );
 	}
 
-	sst_info->current_par = *par ;
+	sst_info->current_par = *par;
 	return 1;
 }
 
@@ -1571,8 +1583,7 @@ static void sst_set_vidmod_att_ti(struct
 		break;
 #endif
 	default:
-		dprintk("bug line %d: bad depth '%u'\n", __LINE__, bpp);
-		break;
+		BUG();
 	}
 }
 
@@ -1590,8 +1601,7 @@ static void sst_set_vidmod_ics(struct ss
 		break;
 #endif
 	default:
-		dprintk("bug line %d: bad depth '%u'\n", __LINE__, bpp);
-		break;
+		BUG();
 	}
 }
 
@@ -1987,34 +1997,34 @@ static void sstfb_test16(struct sstfb_in
 	u_long fbbase_virt = sst_info->video.vbase;
 
 	f_dprintk("sstfb_test16\n");
-	/* rect blanc 20x100+200+0 */
+	/* white rectangle 20x100+200+0 */
 	for (i=0 ; i< 100; i++) {
 	  p = fbbase_virt + 2048 *i+400;
-	  for (j=0 ; j < 10 ; j++) {
-	    writel( 0xffffffff, p);
+	  for (j=0; j < 10; j++) {
+	    writel(0xffffffff, p);
 	    p+=4;
 	  }
 	}
-	/* rect bleu 180x200+0+0 */
+	/* blue rectangle 180x200+0+0 */
 	for (i=0 ; i< 200; i++) {
 	  p = fbbase_virt + 2048 *i;
-	  for (j=0 ; j < 90 ; j++) {
-	    writel(0x001f001f,p);
+	  for (j=0; j < 90; j++) {
+	    writel(0x001f001f, p);
 	    p+=4;
 	  }
 	}
-	/* carre vert 40x40+100+0 */
+	/* green rectangle 40x40+100+0 */
 	for (i=0 ; i< 40 ; i++) {
 	  p = fbbase_virt + 2048 *i + 200;
-	  for (j=0; j <20;j++) {
+	  for (j=0; j <20; j++) {
 	    writel(0x07e007e0, p);
 	    p+=4;
 	  }
 	}
-	/*carre rouge 40x40+100+40 */
+	/* red rectangle 40x40+100+40 */
 	for (i=0; i<40; i++) {
 	  p = fbbase_virt + 2048 * (i+40) + 200;
-	  for (j=0; j <20;j++) {
+	  for (j=0; j <20; j++) {
 	    writel( 0xf800f800, p);
 	    p+=4;
 	  }
@@ -2034,22 +2044,22 @@ static void sstfb_test32(struct sstfb_in
 	for (i=0 ; i< 100; i++) {
 	  p = fbbase_virt + 4096*i + 800;
 	  for (j=0 ; j < 20 ; j++) {
-	    writel( 0x00ffffff, p);
+	    writel(0x00ffffff, p);
 	    p+=4;
 	  }
 	}
 	/* rect bleu 180x200+0+0 */
 	for (i=0 ; i< 200; i++) {
 	  p = fbbase_virt + 4096 * i;
-	  for (j=0 ; j < 180 ; j++) {
-	    writel(0x000000ff,p);
+	  for (j=0 ; j < 180; j++) {
+	    writel(0x000000ff, p);
 	    p+=4;
 	  }
 	}
 	/* carre vert 40x40+100+0 */
 	for (i=0 ; i< 40 ; i++) {
 	  p = fbbase_virt + 4096 *i + 400;
-	  for (j=0; j <40;j++) {
+	  for (j=0; j <40; j++) {
 	    writel(0x0000ff00, p);
 	    p+=4;
 	  }
@@ -2057,8 +2067,8 @@ static void sstfb_test32(struct sstfb_in
 	/*carre rouge 40x40+100+10 */
 	for (i=0; i<40; i++) {
 	  p = fbbase_virt + 4096 * (i+40) + 400;
-	  for (j=0; j <40;j++) {
-	    writel( 0x00ff0000, p);
+	  for (j=0; j <40; j++) {
+	    writel(0x00ff0000, p);
 	    p+=4;
 	  }
 	}
Index: sstfb.h
===================================================================
RCS file: /var/cvs/linux/drivers/video/sstfb.h,v
retrieving revision 1.3
diff -u -p -r1.3 sstfb.h
--- sstfb.h	4 Aug 2002 22:59:15 -0000	1.3
+++ sstfb.h	14 Sep 2002 23:58:44 -0000
@@ -114,7 +114,11 @@
 #  define RD_BUFF_FRONT		  0		/* read buff select (front) */
 #  define RD_BUFF_BACK		  (1 << 6)	/* back */
 #  define EN_PXL_PIPELINE	  BIT(8)	/* pixel pipeline (clip..)*/
+#  define LFB_WORD_SWIZZLE_WR	  BIT(11)	/* enable write-wordswap (big-endian) */
+#  define LFB_BYTE_SWIZZLE_WR	  BIT(12)	/* enable write-byteswap (big-endian) */
 #  define LFB_INVERT_Y		  BIT(13)	/* invert Y origin (LFB) */
+#  define LFB_WORD_SWIZZLE_RD	  BIT(15)	/* enable read-wordswap (big-endian) */
+#  define LFB_BYTE_SWIZZLE_RD	  BIT(16)	/* enable read-byteswap (big-endian) */
 #define CLIP_LEFT_RIGHT		0x0118
 #define CLIP_LOWY_HIGHY		0x011c
 #define NOPCMD			0x0120

--Boundary-00=_K/8g9cdhjiEuAkF--