V4L/DVB (3325): WSS output interface for av7110

- Implemented v4l2 api for sliced vbi data output
to pass WSS data from userspace to the av7110

Signed-off-by: Oliver Endriss <o.endriss@gmx.de>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index a9ff5b5..b614612 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -253,7 +253,10 @@
 
 	if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
 		DEB_S(("initializing vbi...\n"));
-		result = saa7146_vbi_uops.open(dev,file);
+		if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
+			result = saa7146_vbi_uops.open(dev,file);
+		if (dev->ext_vv_data->vbi_fops.open)
+			dev->ext_vv_data->vbi_fops.open(inode, file);
 	} else {
 		DEB_S(("initializing video...\n"));
 		result = saa7146_video_uops.open(dev,file);
@@ -289,7 +292,10 @@
 		return -ERESTARTSYS;
 
 	if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-		saa7146_vbi_uops.release(dev,file);
+		if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
+			saa7146_vbi_uops.release(dev,file);
+		if (dev->ext_vv_data->vbi_fops.release)
+			dev->ext_vv_data->vbi_fops.release(inode, file);
 	} else {
 		saa7146_video_uops.release(dev,file);
 	}
@@ -382,7 +388,10 @@
 		}
 	case V4L2_BUF_TYPE_VBI_CAPTURE: {
 //		DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n", file, data, (unsigned long)count));
-		return saa7146_vbi_uops.read(file,data,count,ppos);
+		if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
+			return saa7146_vbi_uops.read(file,data,count,ppos);
+		else
+			return -EINVAL;
 		}
 		break;
 	default:
@@ -391,12 +400,31 @@
 	}
 }
 
+static ssize_t fops_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
+{
+	struct saa7146_fh *fh = file->private_data;
+
+	switch (fh->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		return -EINVAL;
+	case V4L2_BUF_TYPE_VBI_CAPTURE:
+		if (fh->dev->ext_vv_data->vbi_fops.write)
+			return fh->dev->ext_vv_data->vbi_fops.write(file, data, count, ppos);
+		else
+			return -EINVAL;
+	default:
+		BUG();
+		return -EINVAL;
+	}
+}
+
 static struct file_operations video_fops =
 {
 	.owner		= THIS_MODULE,
 	.open		= fops_open,
 	.release	= fops_release,
 	.read		= fops_read,
+	.write		= fops_write,
 	.poll		= fops_poll,
 	.mmap		= fops_mmap,
 	.ioctl		= fops_ioctl,
@@ -468,7 +496,8 @@
 	memset(vv->d_clipping.cpu_addr, 0x0, SAA7146_CLIPPING_MEM);
 
 	saa7146_video_uops.init(dev,vv);
-	saa7146_vbi_uops.init(dev,vv);
+	if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
+		saa7146_vbi_uops.init(dev,vv);
 
 	dev->vv_data = vv;
 	dev->vv_callback = &vv_callback;