V4L/DVB: pwc: fully convert driver to V4L2

Remove the V4L1 API from this driver, making it fully V4L2.

Also fix a bug where the /dev/videoX device was created too early, which led
to initialization problems of the camera, making it unable to capture video.

Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
diff --git a/drivers/media/video/pwc/Kconfig b/drivers/media/video/pwc/Kconfig
index 11980db..8da42e4 100644
--- a/drivers/media/video/pwc/Kconfig
+++ b/drivers/media/video/pwc/Kconfig
@@ -1,6 +1,6 @@
 config USB_PWC
 	tristate "USB Philips Cameras"
-	depends on VIDEO_V4L1
+	depends on VIDEO_V4L2
 	---help---
 	  Say Y or M here if you want to use one of these Philips & OEM
 	  webcams:
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c
index f7f7e04..6b8fbdd 100644
--- a/drivers/media/video/pwc/pwc-ctrl.c
+++ b/drivers/media/video/pwc/pwc-ctrl.c
@@ -261,7 +261,7 @@
 		PWC_DEBUG_MODULE("Failed to send video command... %d\n", ret);
 		return ret;
 	}
-	if (pEntry->compressed && pdev->vpalette != VIDEO_PALETTE_RAW)
+	if (pEntry->compressed && pdev->pixfmt == V4L2_PIX_FMT_YUV420)
 		pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data);
 
 	pdev->cmd_len = 3;
@@ -321,7 +321,7 @@
 	if (ret < 0)
 		return ret;
 
-	if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
+	if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420)
 		pwc_dec23_init(pdev, pdev->type, buf);
 
 	pdev->cmd_len = 13;
@@ -356,7 +356,7 @@
 	fps = (frames / 5) - 1;
 
 	/* special case: VGA @ 5 fps and snapshot is raw bayer mode */
-	if (size == PSZ_VGA && frames == 5 && snapshot && pdev->vpalette == VIDEO_PALETTE_RAW)
+	if (size == PSZ_VGA && frames == 5 && snapshot && pdev->pixfmt != V4L2_PIX_FMT_YUV420)
 	{
 		/* Only available in case the raw palette is selected or
 		   we have the decompressor available. This mode is
@@ -394,7 +394,7 @@
 	if (ret < 0)
 		return ret;
 
-	if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
+	if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420)
 		pwc_dec23_init(pdev, pdev->type, buf);
 
 	pdev->cmd_len = 12;
@@ -429,7 +429,7 @@
 {
 	int ret, size;
 
-	PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette);
+	PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n", width, height, frames, pdev->pixfmt);
 	size = pwc_decode_size(pdev, width, height);
 	if (size < 0) {
 		PWC_DEBUG_MODULE("Could not find suitable size.\n");
@@ -519,13 +519,13 @@
 {
 	int i, factor = 0;
 
-	/* for PALETTE_YUV420P */
-	switch(pdev->vpalette)
-	{
-	case VIDEO_PALETTE_YUV420P:
+	/* for V4L2_PIX_FMT_YUV420 */
+	switch (pdev->pixfmt) {
+	case V4L2_PIX_FMT_YUV420:
 		factor = 6;
 		break;
-	case VIDEO_PALETTE_RAW:
+	case V4L2_PIX_FMT_PWC1:
+	case V4L2_PIX_FMT_PWC2:
 		factor = 6; /* can be uncompressed YUV420P */
 		break;
 	}
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index aea7e22..d06e157 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -1365,7 +1365,7 @@
 	}
 
 	PWC_DEBUG_READ("Copying data to user space.\n");
-	if (pdev->vpalette == VIDEO_PALETTE_RAW)
+	if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
 		bytes_to_read = pdev->frame_size + sizeof(struct pwc_raw_frame);
 	else
 		bytes_to_read = pdev->view.size;
@@ -1800,13 +1800,6 @@
 	}
 
 	pdev->vdev->release = video_device_release;
-	rc = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr);
-	if (rc < 0) {
-		PWC_ERROR("Failed to register as video device (%d).\n", rc);
-		goto err_video_release;
-	}
-
-	PWC_INFO("Registered as %s.\n", video_device_node_name(pdev->vdev));
 
 	/* occupy slot */
 	if (hint < MAX_DEV_HINTS)
@@ -1814,14 +1807,22 @@
 
 	PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev);
 	usb_set_intfdata(intf, pdev);
-	rc = pwc_create_sysfs_files(pdev->vdev);
-	if (rc)
-		goto err_video_unreg;
 
 	/* Set the leds off */
 	pwc_set_leds(pdev, 0, 0);
 	pwc_camera_power(pdev, 0);
 
+	rc = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr);
+	if (rc < 0) {
+		PWC_ERROR("Failed to register as video device (%d).\n", rc);
+		goto err_video_release;
+	}
+	rc = pwc_create_sysfs_files(pdev->vdev);
+	if (rc)
+		goto err_video_unreg;
+
+	PWC_INFO("Registered as %s.\n", video_device_node_name(pdev->vdev));
+
 #ifdef CONFIG_USB_PWC_INPUT_EVDEV
 	/* register webcam snapshot button input device */
 	pdev->button_dev = input_allocate_device();
diff --git a/drivers/media/video/pwc/pwc-misc.c b/drivers/media/video/pwc/pwc-misc.c
index 589c687..6af5bb5 100644
--- a/drivers/media/video/pwc/pwc-misc.c
+++ b/drivers/media/video/pwc/pwc-misc.c
@@ -47,7 +47,7 @@
 	   you don't have the decompressor loaded or use RAW mode,
 	   the maximum viewable size is smaller.
 	*/
-	if (pdev->vpalette == VIDEO_PALETTE_RAW)
+	if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
 	{
 		if (width > pdev->abs_max.x || height > pdev->abs_max.y)
 		{
@@ -123,7 +123,7 @@
 		pdev->frame_header_size = 0;
 		pdev->frame_trailer_size = 0;
 	}
-	pdev->vpalette = VIDEO_PALETTE_YUV420P; /* default */
+	pdev->pixfmt = V4L2_PIX_FMT_YUV420; /* default */
 	pdev->view_min.size = pdev->view_min.x * pdev->view_min.y;
 	pdev->view_max.size = pdev->view_max.x * pdev->view_max.y;
 	/* length of image, in YUV format; always allocate enough memory. */
diff --git a/drivers/media/video/pwc/pwc-uncompress.c b/drivers/media/video/pwc/pwc-uncompress.c
index 5d82028..3b73f29 100644
--- a/drivers/media/video/pwc/pwc-uncompress.c
+++ b/drivers/media/video/pwc/pwc-uncompress.c
@@ -54,7 +54,7 @@
 	yuv = fbuf->data + pdev->frame_header_size;  /* Skip header */
 
 	/* Raw format; that's easy... */
-	if (pdev->vpalette == VIDEO_PALETTE_RAW)
+	if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
 	{
 		struct pwc_raw_frame *raw_frame = image;
 		raw_frame->type = cpu_to_le16(pdev->type);
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c
index 62d89b3..7061a03f 100644
--- a/drivers/media/video/pwc/pwc-v4l.c
+++ b/drivers/media/video/pwc/pwc-v4l.c
@@ -216,7 +216,7 @@
 	f->fmt.pix.width        = pdev->view.x;
 	f->fmt.pix.height       = pdev->view.y;
 	f->fmt.pix.field        = V4L2_FIELD_NONE;
-	if (pdev->vpalette == VIDEO_PALETTE_YUV420P) {
+	if (pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
 		f->fmt.pix.pixelformat  = V4L2_PIX_FMT_YUV420;
 		f->fmt.pix.bytesperline = (f->fmt.pix.width * 3)/2;
 		f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
@@ -304,10 +304,10 @@
 			fps = pdev->vframes;
 	}
 
-	if (pixelformat == V4L2_PIX_FMT_YUV420)
-		pdev->vpalette = VIDEO_PALETTE_YUV420P;
-	else
-		pdev->vpalette = VIDEO_PALETTE_RAW;
+	if (pixelformat != V4L2_PIX_FMT_YUV420 &&
+	    pixelformat != V4L2_PIX_FMT_PWC1 &&
+	    pixelformat != V4L2_PIX_FMT_PWC2)
+		return -EINVAL;
 
 	PWC_DEBUG_IOCTL("Try to change format to: width=%d height=%d fps=%d "
 			"compression=%d snapshot=%d format=%c%c%c%c\n",
@@ -330,6 +330,8 @@
 	if (ret)
 		return ret;
 
+	pdev->pixfmt = pixelformat;
+
 	pwc_vidioc_fill_fmt(pdev, f);
 
 	return 0;
@@ -357,152 +359,7 @@
 
 
 	switch (cmd) {
-		/* Query cabapilities */
-		case VIDIOCGCAP:
-		{
-			struct video_capability *caps = arg;
-
-			strcpy(caps->name, vdev->name);
-			caps->type = VID_TYPE_CAPTURE;
-			caps->channels = 1;
-			caps->audios = 1;
-			caps->minwidth  = pdev->view_min.x;
-			caps->minheight = pdev->view_min.y;
-			caps->maxwidth  = pdev->view_max.x;
-			caps->maxheight = pdev->view_max.y;
-			break;
-		}
-
-		/* Channel functions (simulate 1 channel) */
-		case VIDIOCGCHAN:
-		{
-			struct video_channel *v = arg;
-
-			if (v->channel != 0)
-				return -EINVAL;
-			v->flags = 0;
-			v->tuners = 0;
-			v->type = VIDEO_TYPE_CAMERA;
-			strcpy(v->name, "Webcam");
-			return 0;
-		}
-
-		case VIDIOCSCHAN:
-		{
-			/* The spec says the argument is an integer, but
-			   the bttv driver uses a video_channel arg, which
-			   makes sense becasue it also has the norm flag.
-			 */
-			struct video_channel *v = arg;
-			if (v->channel != 0)
-				return -EINVAL;
-			return 0;
-		}
-
-
-		/* Picture functions; contrast etc. */
-		case VIDIOCGPICT:
-		{
-			struct video_picture *p = arg;
-			int val;
-
-			val = pwc_get_brightness(pdev);
-			if (val >= 0)
-				p->brightness = (val<<9);
-			else
-				p->brightness = 0xffff;
-			val = pwc_get_contrast(pdev);
-			if (val >= 0)
-				p->contrast = (val<<10);
-			else
-				p->contrast = 0xffff;
-			/* Gamma, Whiteness, what's the difference? :) */
-			val = pwc_get_gamma(pdev);
-			if (val >= 0)
-				p->whiteness = (val<<11);
-			else
-				p->whiteness = 0xffff;
-			if (pwc_get_saturation(pdev, &val)<0)
-				p->colour = 0xffff;
-			else
-				p->colour = 32768 + val * 327;
-			p->depth = 24;
-			p->palette = pdev->vpalette;
-			p->hue = 0xFFFF; /* N/A */
-			break;
-		}
-
-		case VIDIOCSPICT:
-		{
-			struct video_picture *p = arg;
-			/*
-			 *	FIXME:	Suppose we are mid read
-				ANSWER: No problem: the firmware of the camera
-					can handle brightness/contrast/etc
-					changes at _any_ time, and the palette
-					is used exactly once in the uncompress
-					routine.
-			 */
-			pwc_set_brightness(pdev, p->brightness);
-			pwc_set_contrast(pdev, p->contrast);
-			pwc_set_gamma(pdev, p->whiteness);
-			pwc_set_saturation(pdev, (p->colour-32768)/327);
-			if (p->palette && p->palette != pdev->vpalette) {
-				switch (p->palette) {
-					case VIDEO_PALETTE_YUV420P:
-					case VIDEO_PALETTE_RAW:
-						pdev->vpalette = p->palette;
-						return pwc_try_video_mode(pdev, pdev->image.x, pdev->image.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
-						break;
-					default:
-						return -EINVAL;
-						break;
-				}
-			}
-			break;
-		}
-
-		/* Window/size parameters */
-		case VIDIOCGWIN:
-		{
-			struct video_window *vw = arg;
-
-			vw->x = 0;
-			vw->y = 0;
-			vw->width = pdev->view.x;
-			vw->height = pdev->view.y;
-			vw->chromakey = 0;
-			vw->flags = (pdev->vframes << PWC_FPS_SHIFT) |
-				   (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0);
-			break;
-		}
-
-		case VIDIOCSWIN:
-		{
-			struct video_window *vw = arg;
-			int fps, snapshot, ret;
-
-			fps = (vw->flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
-			snapshot = vw->flags & PWC_FPS_SNAPSHOT;
-			if (fps == 0)
-				fps = pdev->vframes;
-			if (pdev->view.x == vw->width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot)
-				return 0;
-			ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot);
-			if (ret)
-				return ret;
-			break;
-		}
-
-		/* We don't have overlay support (yet) */
-		case VIDIOCGFBUF:
-		{
-			struct video_buffer *vb = arg;
-
-			memset(vb,0,sizeof(*vb));
-			break;
-		}
-
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 		/* mmap() functions */
 		case VIDIOCGMBUF:
 		{
@@ -517,164 +374,7 @@
 				vm->offsets[i] = i * pdev->len_per_image;
 			break;
 		}
-
-		case VIDIOCMCAPTURE:
-		{
-			/* Start capture into a given image buffer (called 'frame' in video_mmap structure) */
-			struct video_mmap *vm = arg;
-
-			PWC_DEBUG_READ("VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm->width, vm->height, vm->frame, vm->format);
-			if (vm->frame < 0 || vm->frame >= pwc_mbufs)
-				return -EINVAL;
-
-			/* xawtv is nasty. It probes the available palettes
-			   by setting a very small image size and trying
-			   various palettes... The driver doesn't support
-			   such small images, so I'm working around it.
-			 */
-			if (vm->format)
-			{
-				switch (vm->format)
-				{
-					case VIDEO_PALETTE_YUV420P:
-					case VIDEO_PALETTE_RAW:
-						break;
-					default:
-						return -EINVAL;
-						break;
-				}
-			}
-
-			if ((vm->width != pdev->view.x || vm->height != pdev->view.y) &&
-			    (vm->width >= pdev->view_min.x && vm->height >= pdev->view_min.y)) {
-				int ret;
-
-				PWC_DEBUG_OPEN("VIDIOCMCAPTURE: changing size to please xawtv :-(.\n");
-				ret = pwc_try_video_mode(pdev, vm->width, vm->height, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
-				if (ret)
-					return ret;
-			} /* ... size mismatch */
-
-			/* FIXME: should we lock here? */
-			if (pdev->image_used[vm->frame])
-				return -EBUSY;	/* buffer wasn't available. Bummer */
-			pdev->image_used[vm->frame] = 1;
-
-			/* Okay, we're done here. In the SYNC call we wait until a
-			   frame comes available, then expand image into the given
-			   buffer.
-			   In contrast to the CPiA cam the Philips cams deliver a
-			   constant stream, almost like a grabber card. Also,
-			   we have separate buffers for the rawdata and the image,
-			   meaning we can nearly always expand into the requested buffer.
-			 */
-			PWC_DEBUG_READ("VIDIOCMCAPTURE done.\n");
-			break;
-		}
-
-		case VIDIOCSYNC:
-		{
-			/* The doc says: "Whenever a buffer is used it should
-			   call VIDIOCSYNC to free this frame up and continue."
-
-			   The only odd thing about this whole procedure is
-			   that MCAPTURE flags the buffer as "in use", and
-			   SYNC immediately unmarks it, while it isn't
-			   after SYNC that you know that the buffer actually
-			   got filled! So you better not start a CAPTURE in
-			   the same frame immediately (use double buffering).
-			   This is not a problem for this cam, since it has
-			   extra intermediate buffers, but a hardware
-			   grabber card will then overwrite the buffer
-			   you're working on.
-			 */
-			int *mbuf = arg;
-			int ret;
-
-			PWC_DEBUG_READ("VIDIOCSYNC called (%d).\n", *mbuf);
-
-			/* bounds check */
-			if (*mbuf < 0 || *mbuf >= pwc_mbufs)
-				return -EINVAL;
-			/* check if this buffer was requested anyway */
-			if (pdev->image_used[*mbuf] == 0)
-				return -EINVAL;
-
-			/* Add ourselves to the frame wait-queue.
-
-			   FIXME: needs auditing for safety.
-			   QUESTION: In what respect? I think that using the
-				     frameq is safe now.
-			 */
-			add_wait_queue(&pdev->frameq, &wait);
-			while (pdev->full_frames == NULL) {
-				/* Check for unplugged/etc. here */
-				if (pdev->error_status) {
-					remove_wait_queue(&pdev->frameq, &wait);
-					set_current_state(TASK_RUNNING);
-					return -pdev->error_status;
-				}
-
-				if (signal_pending(current)) {
-					remove_wait_queue(&pdev->frameq, &wait);
-					set_current_state(TASK_RUNNING);
-					return -ERESTARTSYS;
-				}
-				schedule();
-				set_current_state(TASK_INTERRUPTIBLE);
-			}
-			remove_wait_queue(&pdev->frameq, &wait);
-			set_current_state(TASK_RUNNING);
-
-			/* The frame is ready. Expand in the image buffer
-			   requested by the user. I don't care if you
-			   mmap() 5 buffers and request data in this order:
-			   buffer 4 2 3 0 1 2 3 0 4 3 1 . . .
-			   Grabber hardware may not be so forgiving.
-			 */
-			PWC_DEBUG_READ("VIDIOCSYNC: frame ready.\n");
-			pdev->fill_image = *mbuf; /* tell in which buffer we want the image to be expanded */
-			/* Decompress, etc */
-			ret = pwc_handle_frame(pdev);
-			pdev->image_used[*mbuf] = 0;
-			if (ret)
-				return -EFAULT;
-			break;
-		}
-
-		case VIDIOCGAUDIO:
-		{
-			struct video_audio *v = arg;
-
-			strcpy(v->name, "Microphone");
-			v->audio = -1; /* unknown audio minor */
-			v->flags = 0;
-			v->mode = VIDEO_SOUND_MONO;
-			v->volume = 0;
-			v->bass = 0;
-			v->treble = 0;
-			v->balance = 0x8000;
-			v->step = 1;
-			break;
-		}
-
-		case VIDIOCSAUDIO:
-		{
-			/* Dummy: nothing can be set */
-			break;
-		}
-
-		case VIDIOCGUNIT:
-		{
-			struct video_unit *vu = arg;
-
-			vu->video = pdev->vdev->minor & 0x3F;
-			vu->audio = -1; /* not known yet */
-			vu->vbi = -1;
-			vu->radio = -1;
-			vu->teletext = -1;
-			break;
-		}
+#endif
 
 		/* V4L2 Layer */
 		case VIDIOC_QUERYCAP:
@@ -1081,7 +781,7 @@
 			buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 			buf->index = index;
 			buf->m.offset = index * pdev->len_per_image;
-			if (pdev->vpalette == VIDEO_PALETTE_RAW)
+			if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
 				buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
 			else
 				buf->bytesused = pdev->view.size;
@@ -1158,7 +858,7 @@
 			PWC_DEBUG_IOCTL("VIDIOC_DQBUF: after pwc_handle_frame\n");
 
 			buf->index = pdev->fill_image;
-			if (pdev->vpalette == VIDEO_PALETTE_RAW)
+			if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
 				buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
 			else
 				buf->bytesused = pdev->view.size;
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h
index f1b2066..36a9c83 100644
--- a/drivers/media/video/pwc/pwc.h
+++ b/drivers/media/video/pwc/pwc.h
@@ -34,7 +34,7 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <asm/errno.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 #ifdef CONFIG_USB_PWC_INPUT_EVDEV
@@ -49,7 +49,7 @@
 #define PWC_MINOR	0
 #define PWC_EXTRAMINOR	12
 #define PWC_VERSION_CODE KERNEL_VERSION(PWC_MAJOR,PWC_MINOR,PWC_EXTRAMINOR)
-#define PWC_VERSION 	"10.0.13"
+#define PWC_VERSION	"10.0.14"
 #define PWC_NAME 	"pwc"
 #define PFX		PWC_NAME ": "
 
@@ -180,7 +180,7 @@
    int vcinterface;		/* video control interface */
    int valternate;		/* alternate interface needed */
    int vframes, vsize;		/* frames-per-second & size (see PSZ_*) */
-   int vpalette;		/* palette: 420P, RAW or RGBBAYER */
+   int pixfmt;			/* pixelformat: V4L2_PIX_FMT_YUV420 or raw: _PWC1, _PWC2 */
    int vframe_count;		/* received frames */
    int vframes_dumped; 		/* counter for dumped frames */
    int vframes_error;		/* frames received in error */