V4L/DVB (3835): [PATCH] update pwc driver

Add v4l2 compatibility
Include the decompressor (legal problem has been resolv by Alan Cox)
Faster decoder and easier to maintain, optimize, ...
Can export to userland compressed stream
Support more cameras, lot of bugs are fixed.

Signed-off-by: Luc Saillard <luc@saillard.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
diff --git a/drivers/media/video/pwc/pwc-uncompress.c b/drivers/media/video/pwc/pwc-uncompress.c
index b37a89a..5d82028 100644
--- a/drivers/media/video/pwc/pwc-uncompress.c
+++ b/drivers/media/video/pwc/pwc-uncompress.c
@@ -1,7 +1,7 @@
 /* Linux driver for Philips webcam
    Decompression frontend.
    (C) 1999-2003 Nemosoft Unv.
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -22,6 +22,8 @@
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+   vim: set ts=8:
 */
 
 #include <asm/current.h>
@@ -29,6 +31,8 @@
 
 #include "pwc.h"
 #include "pwc-uncompress.h"
+#include "pwc-dec1.h"
+#include "pwc-dec23.h"
 
 int pwc_decompress(struct pwc_device *pdev)
 {
@@ -40,107 +44,95 @@
 
 	if (pdev == NULL)
 		return -EFAULT;
-#if defined(__KERNEL__) && defined(PWC_MAGIC)
-	if (pdev->magic != PWC_MAGIC) {
-		Err("pwc_decompress(): magic failed.\n");
-		return -EFAULT;
-	}
-#endif
 
 	fbuf = pdev->read_frame;
 	if (fbuf == NULL)
 		return -EFAULT;
-	image = pdev->image_ptr[pdev->fill_image];
-	if (!image)
-		return -EFAULT;
+	image  = pdev->image_data;
+	image += pdev->images[pdev->fill_image].offset;
 
 	yuv = fbuf->data + pdev->frame_header_size;  /* Skip header */
 
 	/* Raw format; that's easy... */
 	if (pdev->vpalette == VIDEO_PALETTE_RAW)
 	{
-		memcpy(image, yuv, pdev->frame_size);
+		struct pwc_raw_frame *raw_frame = image;
+		raw_frame->type = cpu_to_le16(pdev->type);
+		raw_frame->vbandlength = cpu_to_le16(pdev->vbandlength);
+			/* cmd_buf is always 4 bytes, but sometimes, only the
+			 * first 3 bytes is filled (Nala case). We can
+			 * determine this using the type of the webcam */
+		memcpy(raw_frame->cmd, pdev->cmd_buf, 4);
+		memcpy(raw_frame+1, yuv, pdev->frame_size);
 		return 0;
 	}
 
 	if (pdev->vbandlength == 0) {
-		/* Uncompressed mode. We copy the data into the output buffer,
-		   using the viewport size (which may be larger than the image
-		   size). Unfortunately we have to do a bit of byte stuffing
-		   to get the desired output format/size.
+		/* Uncompressed mode.
+		 * We copy the data into the output buffer, using the viewport
+		 * size (which may be larger than the image size).
+		 * Unfortunately we have to do a bit of byte stuffing to get
+		 * the desired output format/size.
+		 *
+		 * We do some byte shuffling here to go from the
+		 * native format to YUV420P.
 		 */
-			/*
-			 * We do some byte shuffling here to go from the
-			 * native format to YUV420P.
-			 */
-			src = (u16 *)yuv;
-			n = pdev->view.x * pdev->view.y;
+		src = (u16 *)yuv;
+		n = pdev->view.x * pdev->view.y;
 
-			/* offset in Y plane */
-			stride = pdev->view.x * pdev->offset.y + pdev->offset.x;
-			dsty = (u16 *)(image + stride);
+		/* offset in Y plane */
+		stride = pdev->view.x * pdev->offset.y + pdev->offset.x;
+		dsty = (u16 *)(image + stride);
 
-			/* offsets in U/V planes */
-			stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2;
-			dstu = (u16 *)(image + n +         stride);
-			dstv = (u16 *)(image + n + n / 4 + stride);
+		/* offsets in U/V planes */
+		stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2;
+		dstu = (u16 *)(image + n +         stride);
+		dstv = (u16 *)(image + n + n / 4 + stride);
 
-			/* increment after each line */
-			stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */
+		/* increment after each line */
+		stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */
 
-			for (line = 0; line < pdev->image.y; line++) {
-				for (col = 0; col < pdev->image.x; col += 4) {
-					*dsty++ = *src++;
-					*dsty++ = *src++;
-					if (line & 1)
-						*dstv++ = *src++;
-					else
-						*dstu++ = *src++;
-				}
-				dsty += stride;
+		for (line = 0; line < pdev->image.y; line++) {
+			for (col = 0; col < pdev->image.x; col += 4) {
+				*dsty++ = *src++;
+				*dsty++ = *src++;
 				if (line & 1)
-					dstv += (stride >> 1);
+					*dstv++ = *src++;
 				else
-					dstu += (stride >> 1);
+					*dstu++ = *src++;
 			}
+			dsty += stride;
+			if (line & 1)
+				dstv += (stride >> 1);
+			else
+				dstu += (stride >> 1);
+		}
+
+		return 0;
 	}
-	else {
-		/* Compressed; the decompressor routines will write the data
-		   in planar format immediately.
-		 */
-		int flags;
 
-		flags = PWCX_FLAG_PLANAR;
-		if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot)
-		 {
-		   printk(KERN_ERR "pwc: Mode Bayer is not supported for now\n");
-		   flags |= PWCX_FLAG_BAYER;
-		   return -ENXIO; /* No such device or address: missing decompressor */
-		 }
+	/*
+	 * Compressed;
+	 * the decompressor routines will write the data in planar format
+	 * immediately.
+	 */
+	if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot) {
+		PWC_ERROR("Mode Bayer is not supported for now\n");
+		/* flags |= PWCX_FLAG_BAYER; */
+		return -ENXIO; /* No such device or address: missing decompressor */
+	}
 
-#if 0
-		switch (pdev->type)
-		 {
-		  case 675:
-		  case 680:
-		  case 690:
-		  case 720:
-		  case 730:
-		  case 740:
-		  case 750:
-		    pwc_dec23_decompress(&pdev->image, &pdev->view,
-				&pdev->offset, yuv, image, flags,
-				pdev->decompress_data, pdev->vbandlength);
-		    break;
-		  case 645:
-		  case 646:
-		    /* TODO & FIXME */
-		    return -ENXIO; /* Missing decompressor */
-		    break;
-		 }
-#endif
+	if (DEVICE_USE_CODEC1(pdev->type)) {
+
+		/* TODO & FIXME */
+		PWC_ERROR("This chipset is not supported for now\n");
+		return -ENXIO; /* No such device or address: missing decompressor */
+
+	} else {
+		pwc_dec23_decompress(pdev, yuv, image, PWCX_FLAG_PLANAR);
 	}
 	return 0;
 }
 
 
+/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */