V4L/DVB (4223): Add V4L2_CID_MPEG_STREAM_VBI_FMT control

V4L2_CID_MPEG_STREAM_VBI_FMT controls if and how VBI data is embedded in
an MPEG stream. Currently only one format is supported: the format designed
for the ivtv driver. This should be extended with new standard formats
(such as defined for DVB) in the future.

Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c
index 554813e..01b22ea 100644
--- a/drivers/media/video/cx2341x.c
+++ b/drivers/media/video/cx2341x.c
@@ -43,6 +43,7 @@
 const u32 cx2341x_mpeg_ctrls[] = {
 	V4L2_CID_MPEG_CLASS,
 	V4L2_CID_MPEG_STREAM_TYPE,
+	V4L2_CID_MPEG_STREAM_VBI_FMT,
 	V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
 	V4L2_CID_MPEG_AUDIO_ENCODING,
 	V4L2_CID_MPEG_AUDIO_L2_BITRATE,
@@ -135,6 +136,9 @@
 	case V4L2_CID_MPEG_STREAM_TYPE:
 		ctrl->value = params->stream_type;
 		break;
+	case V4L2_CID_MPEG_STREAM_VBI_FMT:
+		ctrl->value = params->stream_vbi_fmt;
+		break;
 	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
 		ctrl->value = params->video_spatial_filter_mode;
 		break;
@@ -257,6 +261,9 @@
 			params->video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
 		}
 		break;
+	case V4L2_CID_MPEG_STREAM_VBI_FMT:
+		params->stream_vbi_fmt = ctrl->value;
+		break;
 	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
 		params->video_spatial_filter_mode = ctrl->value;
 		break;
@@ -418,6 +425,14 @@
 			qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
 		return err;
 
+	case V4L2_CID_MPEG_STREAM_VBI_FMT:
+		if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
+			return v4l2_ctrl_query_fill_std(qctrl);
+		return cx2341x_ctrl_query_fill(qctrl,
+				V4L2_MPEG_STREAM_VBI_FMT_NONE,
+				V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
+				V4L2_MPEG_STREAM_VBI_FMT_NONE);
+
 	/* CX23415/6 specific */
 	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
 		return cx2341x_ctrl_query_fill(qctrl,
@@ -639,6 +654,7 @@
 {
 	static struct cx2341x_mpeg_params default_params = {
 	/* misc */
+	.capabilities = 0,
 	.port = CX2341X_PORT_MEMORY,
 	.width = 720,
 	.height = 480,
@@ -646,6 +662,7 @@
 
 	/* stream */
 	.stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
+	.stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
 
 	/* audio */
 	.audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index 14e5234..f4b3d64 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -1101,6 +1101,11 @@
 		"MPEG-2 SVCD-compatible Stream",
 		NULL
 	};
+	static const char *mpeg_stream_vbi_fmt[] = {
+		"No VBI",
+		"VBI in private packets, IVTV format",
+		NULL
+	};
 
 	switch (id) {
 		case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
@@ -1129,6 +1134,8 @@
 			return mpeg_video_bitrate_mode;
 		case V4L2_CID_MPEG_STREAM_TYPE:
 			return mpeg_stream_type;
+		case V4L2_CID_MPEG_STREAM_VBI_FMT:
+			return mpeg_stream_vbi_fmt;
 		default:
 			return NULL;
 	}
@@ -1182,6 +1189,7 @@
 	case V4L2_CID_MPEG_STREAM_PID_PCR: 	name = "Stream PCR Program ID"; break;
 	case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: name = "Stream PES Audio ID"; break;
 	case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: name = "Stream PES Video ID"; break;
+	case V4L2_CID_MPEG_STREAM_VBI_FMT:	name = "Stream VBI Format"; break;
 
 	default:
 		return -EINVAL;
@@ -1208,6 +1216,7 @@
 	case V4L2_CID_MPEG_VIDEO_ASPECT:
 	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
 	case V4L2_CID_MPEG_STREAM_TYPE:
+	case V4L2_CID_MPEG_STREAM_VBI_FMT:
 		qctrl->type = V4L2_CTRL_TYPE_MENU;
 		step = 1;
 		break;
@@ -1367,6 +1376,11 @@
 		return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0);
 	case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO:
 		return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0);
+	case V4L2_CID_MPEG_STREAM_VBI_FMT:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_STREAM_VBI_FMT_NONE,
+				V4L2_MPEG_STREAM_VBI_FMT_IVTV, 1,
+				V4L2_MPEG_STREAM_VBI_FMT_NONE);
 	default:
 		return -EINVAL;
 	}
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 8b4745c..a62673d 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -822,6 +822,11 @@
 #define V4L2_CID_MPEG_STREAM_PID_PCR 		(V4L2_CID_MPEG_BASE+4)
 #define V4L2_CID_MPEG_STREAM_PES_ID_AUDIO 	(V4L2_CID_MPEG_BASE+5)
 #define V4L2_CID_MPEG_STREAM_PES_ID_VIDEO 	(V4L2_CID_MPEG_BASE+6)
+#define V4L2_CID_MPEG_STREAM_VBI_FMT 		(V4L2_CID_MPEG_BASE+7)
+enum v4l2_mpeg_stream_vbi_fmt {
+	V4L2_MPEG_STREAM_VBI_FMT_NONE = 0,  /* No VBI in the MPEG stream */
+	V4L2_MPEG_STREAM_VBI_FMT_IVTV = 1,  /* VBI in private packets, IVTV format */
+};
 
 /*  MPEG audio */
 #define V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ 	(V4L2_CID_MPEG_BASE+100)
diff --git a/include/media/cx2341x.h b/include/media/cx2341x.h
index 51fb06b..074c400 100644
--- a/include/media/cx2341x.h
+++ b/include/media/cx2341x.h
@@ -25,8 +25,13 @@
 	CX2341X_PORT_SERIAL    = 2
 };
 
+enum cx2341x_cap {
+	CX2341X_CAP_HAS_SLICED_VBI = 1 << 0,
+};
+
 struct cx2341x_mpeg_params {
 	/* misc */
+	u32 capabilities;
 	enum cx2341x_port port;
 	u16 width;
 	u16 height;
@@ -34,6 +39,7 @@
 
 	/* stream */
 	enum v4l2_mpeg_stream_type stream_type;
+	enum v4l2_mpeg_stream_vbi_fmt stream_vbi_fmt;
 
 	/* audio */
 	enum v4l2_mpeg_audio_sampling_freq audio_sampling_freq;