public inbox for linux-media@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC v3 0/7] SDR API
@ 2013-12-16 22:08 Antti Palosaari
  2013-12-16 22:08 ` [PATCH RFC v3 1/7] v4l: add new tuner types for SDR Antti Palosaari
                   ` (7 more replies)
  0 siblings, 8 replies; 23+ messages in thread
From: Antti Palosaari @ 2013-12-16 22:08 UTC (permalink / raw)
  To: linux-media; +Cc: Mauro Carvalho Chehab, Hans Verkuil, Antti Palosaari

Now with some changes done requested by Hans.
I did not agree	very well that VIDIOC_G_FREQUENCY tuner type check
exception, but here it is...

Also two patches, as example, conversion of msi3101 and rtl2832_sdr
drivers to that API.

regards
Antti

Antti Palosaari (7):
  v4l: add new tuner types for SDR
  v4l: 1 Hz resolution flag for tuners
  v4l: add stream format for SDR receiver
  v4l: define own IOCTL ops for SDR FMT
  v4l: enable some IOCTLs for SDR receiver
  rtl2832_sdr: convert to SDR API
  msi3101: convert to SDR API

 drivers/media/v4l2-core/v4l2-dev.c               |  27 ++-
 drivers/media/v4l2-core/v4l2-ioctl.c             |  75 +++++-
 drivers/staging/media/msi3101/sdr-msi3101.c      | 204 +++++++++++-----
 drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 291 ++++++++++++++++++-----
 include/media/v4l2-ioctl.h                       |   8 +
 include/trace/events/v4l2.h                      |   1 +
 include/uapi/linux/videodev2.h                   |  14 ++
 7 files changed, 486 insertions(+), 134 deletions(-)

-- 
1.8.4.2


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH RFC v3 1/7] v4l: add new tuner types for SDR
  2013-12-16 22:08 [PATCH RFC v3 0/7] SDR API Antti Palosaari
@ 2013-12-16 22:08 ` Antti Palosaari
  2013-12-17  7:31   ` Hans Verkuil
  2013-12-16 22:08 ` [PATCH RFC v3 2/7] v4l: 1 Hz resolution flag for tuners Antti Palosaari
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 23+ messages in thread
From: Antti Palosaari @ 2013-12-16 22:08 UTC (permalink / raw)
  To: linux-media; +Cc: Mauro Carvalho Chehab, Hans Verkuil, Antti Palosaari

Define tuner types V4L2_TUNER_ADC and V4L2_TUNER_RF for SDR usage.

ADC is used for setting sampling rate (sampling frequency) to SDR
device.

Another tuner type, named as V4L2_TUNER_RF, is possible RF tuner.
Is is used to down-convert RF frequency to range ADC could sample.
Having RF tuner is optional, whilst in practice it is almost always
there.

Also add checks to VIDIOC_G_FREQUENCY, VIDIOC_S_FREQUENCY and
VIDIOC_ENUM_FREQ_BANDS only allow these two tuner types when device
type is SDR (VFL_TYPE_SDR). For VIDIOC_G_FREQUENCY we do not check
tuner type, instead override type with V4L2_TUNER_ADC in every
case (requested by Hans in order to keep functionality in line with
existing tuners and existing API does not specify it).

Prohibit VIDIOC_S_HW_FREQ_SEEK explicitly when device type is SDR,
as device cannot do hardware seek without a hardware demodulator.

Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/v4l2-core/v4l2-ioctl.c | 39 ++++++++++++++++++++++++++----------
 include/uapi/linux/videodev2.h       |  2 ++
 2 files changed, 30 insertions(+), 11 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 68e6b5e..04ec9f9 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1288,8 +1288,11 @@ static int v4l_g_frequency(const struct v4l2_ioctl_ops *ops,
 	struct video_device *vfd = video_devdata(file);
 	struct v4l2_frequency *p = arg;
 
-	p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
-			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+	if (vfd->vfl_type == VFL_TYPE_SDR)
+		p->type = V4L2_TUNER_ADC;
+	else
+		p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
+				V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
 	return ops->vidioc_g_frequency(file, fh, p);
 }
 
@@ -1300,10 +1303,15 @@ static int v4l_s_frequency(const struct v4l2_ioctl_ops *ops,
 	const struct v4l2_frequency *p = arg;
 	enum v4l2_tuner_type type;
 
-	type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
-			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
-	if (p->type != type)
-		return -EINVAL;
+	if (vfd->vfl_type == VFL_TYPE_SDR) {
+		if (p->type != V4L2_TUNER_ADC && p->type != V4L2_TUNER_RF)
+			return -EINVAL;
+	} else {
+		type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
+				V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+		if (type != p->type)
+			return -EINVAL;
+	}
 	return ops->vidioc_s_frequency(file, fh, p);
 }
 
@@ -1383,6 +1391,10 @@ static int v4l_s_hw_freq_seek(const struct v4l2_ioctl_ops *ops,
 	struct v4l2_hw_freq_seek *p = arg;
 	enum v4l2_tuner_type type;
 
+	/* s_hw_freq_seek is not supported for SDR for now */
+	if (vfd->vfl_type == VFL_TYPE_SDR)
+		return -EINVAL;
+
 	type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
 		V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
 	if (p->type != type)
@@ -1882,11 +1894,16 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops,
 	enum v4l2_tuner_type type;
 	int err;
 
-	type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
-			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
-
-	if (type != p->type)
-		return -EINVAL;
+	if (vfd->vfl_type == VFL_TYPE_SDR) {
+		if (p->type != V4L2_TUNER_ADC && p->type != V4L2_TUNER_RF)
+			return -EINVAL;
+		type = p->type; /* silence compiler warning */
+	} else {
+		type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
+				V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+		if (type != p->type)
+			return -EINVAL;
+	}
 	if (ops->vidioc_enum_freq_bands)
 		return ops->vidioc_enum_freq_bands(file, fh, p);
 	if (is_valid_ioctl(vfd, VIDIOC_G_TUNER)) {
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 437f1b0..3fff116 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -159,6 +159,8 @@ enum v4l2_tuner_type {
 	V4L2_TUNER_RADIO	     = 1,
 	V4L2_TUNER_ANALOG_TV	     = 2,
 	V4L2_TUNER_DIGITAL_TV	     = 3,
+	V4L2_TUNER_ADC               = 4,
+	V4L2_TUNER_RF                = 5,
 };
 
 enum v4l2_memory {
-- 
1.8.4.2


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH RFC v3 2/7] v4l: 1 Hz resolution flag for tuners
  2013-12-16 22:08 [PATCH RFC v3 0/7] SDR API Antti Palosaari
  2013-12-16 22:08 ` [PATCH RFC v3 1/7] v4l: add new tuner types for SDR Antti Palosaari
@ 2013-12-16 22:08 ` Antti Palosaari
  2013-12-17  7:31   ` Hans Verkuil
  2013-12-16 22:08 ` [PATCH RFC v3 3/7] v4l: add stream format for SDR receiver Antti Palosaari
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 23+ messages in thread
From: Antti Palosaari @ 2013-12-16 22:08 UTC (permalink / raw)
  To: linux-media; +Cc: Mauro Carvalho Chehab, Hans Verkuil, Antti Palosaari

Add V4L2_TUNER_CAP_1HZ for 1 Hz resolution.

Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 include/uapi/linux/videodev2.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 3fff116..97a5e50 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -1341,6 +1341,7 @@ struct v4l2_modulator {
 #define V4L2_TUNER_CAP_RDS_CONTROLS	0x0200
 #define V4L2_TUNER_CAP_FREQ_BANDS	0x0400
 #define V4L2_TUNER_CAP_HWSEEK_PROG_LIM	0x0800
+#define V4L2_TUNER_CAP_1HZ		0x1000
 
 /*  Flags for the 'rxsubchans' field */
 #define V4L2_TUNER_SUB_MONO		0x0001
-- 
1.8.4.2


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH RFC v3 3/7] v4l: add stream format for SDR receiver
  2013-12-16 22:08 [PATCH RFC v3 0/7] SDR API Antti Palosaari
  2013-12-16 22:08 ` [PATCH RFC v3 1/7] v4l: add new tuner types for SDR Antti Palosaari
  2013-12-16 22:08 ` [PATCH RFC v3 2/7] v4l: 1 Hz resolution flag for tuners Antti Palosaari
@ 2013-12-16 22:08 ` Antti Palosaari
  2013-12-17  7:32   ` Hans Verkuil
  2013-12-16 22:08 ` [PATCH RFC v3 4/7] v4l: define own IOCTL ops for SDR FMT Antti Palosaari
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 23+ messages in thread
From: Antti Palosaari @ 2013-12-16 22:08 UTC (permalink / raw)
  To: linux-media; +Cc: Mauro Carvalho Chehab, Hans Verkuil, Antti Palosaari

Add new V4L2 stream format definition, V4L2_BUF_TYPE_SDR_CAPTURE,
for SDR receiver.

Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/v4l2-core/v4l2-ioctl.c |  1 +
 include/trace/events/v4l2.h          |  1 +
 include/uapi/linux/videodev2.h       | 11 +++++++++++
 3 files changed, 13 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 04ec9f9..da197e1 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -149,6 +149,7 @@ const char *v4l2_type_names[] = {
 	[V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "vid-out-overlay",
 	[V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE] = "vid-cap-mplane",
 	[V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE] = "vid-out-mplane",
+	[V4L2_BUF_TYPE_SDR_CAPTURE]        = "sdr-cap",
 };
 EXPORT_SYMBOL(v4l2_type_names);
 
diff --git a/include/trace/events/v4l2.h b/include/trace/events/v4l2.h
index ef94eca..b9bb1f2 100644
--- a/include/trace/events/v4l2.h
+++ b/include/trace/events/v4l2.h
@@ -18,6 +18,7 @@
 		{ V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY, "VIDEO_OUTPUT_OVERLAY" },\
 		{ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, "VIDEO_CAPTURE_MPLANE" },\
 		{ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,  "VIDEO_OUTPUT_MPLANE" }, \
+		{ V4L2_BUF_TYPE_SDR_CAPTURE,          "SDR_CAPTURE" },         \
 		{ V4L2_BUF_TYPE_PRIVATE,	      "PRIVATE" })
 
 #define show_field(field)						\
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 97a5e50..c50e449 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -139,6 +139,7 @@ enum v4l2_buf_type {
 #endif
 	V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = 9,
 	V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE  = 10,
+	V4L2_BUF_TYPE_SDR_CAPTURE          = 11,
 	/* Deprecated, do not use */
 	V4L2_BUF_TYPE_PRIVATE              = 0x80,
 };
@@ -1695,6 +1696,15 @@ struct v4l2_pix_format_mplane {
 } __attribute__ ((packed));
 
 /**
+ * struct v4l2_format_sdr - SDR format definition
+ * @pixelformat:	little endian four character code (fourcc)
+ */
+struct v4l2_format_sdr {
+	__u32				pixelformat;
+	__u8				reserved[28];
+} __attribute__ ((packed));
+
+/**
  * struct v4l2_format - stream data format
  * @type:	enum v4l2_buf_type; type of the data stream
  * @pix:	definition of an image format
@@ -1712,6 +1722,7 @@ struct v4l2_format {
 		struct v4l2_window		win;     /* V4L2_BUF_TYPE_VIDEO_OVERLAY */
 		struct v4l2_vbi_format		vbi;     /* V4L2_BUF_TYPE_VBI_CAPTURE */
 		struct v4l2_sliced_vbi_format	sliced;  /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
+		struct v4l2_format_sdr		sdr;     /* V4L2_BUF_TYPE_SDR_CAPTURE */
 		__u8	raw_data[200];                   /* user-defined */
 	} fmt;
 };
-- 
1.8.4.2


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH RFC v3 4/7] v4l: define own IOCTL ops for SDR FMT
  2013-12-16 22:08 [PATCH RFC v3 0/7] SDR API Antti Palosaari
                   ` (2 preceding siblings ...)
  2013-12-16 22:08 ` [PATCH RFC v3 3/7] v4l: add stream format for SDR receiver Antti Palosaari
@ 2013-12-16 22:08 ` Antti Palosaari
  2013-12-17  7:32   ` Hans Verkuil
  2013-12-16 22:08 ` [PATCH RFC v3 5/7] v4l: enable some IOCTLs for SDR receiver Antti Palosaari
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 23+ messages in thread
From: Antti Palosaari @ 2013-12-16 22:08 UTC (permalink / raw)
  To: linux-media; +Cc: Mauro Carvalho Chehab, Hans Verkuil, Antti Palosaari

Use own format ops for SDR data:
vidioc_enum_fmt_sdr_cap
vidioc_g_fmt_sdr_cap
vidioc_s_fmt_sdr_cap
vidioc_try_fmt_sdr_cap

Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 include/media/v4l2-ioctl.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index e0b74a4..8be32f5 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -40,6 +40,8 @@ struct v4l2_ioctl_ops {
 					      struct v4l2_fmtdesc *f);
 	int (*vidioc_enum_fmt_vid_out_mplane)(struct file *file, void *fh,
 					      struct v4l2_fmtdesc *f);
+	int (*vidioc_enum_fmt_sdr_cap)     (struct file *file, void *fh,
+					    struct v4l2_fmtdesc *f);
 
 	/* VIDIOC_G_FMT handlers */
 	int (*vidioc_g_fmt_vid_cap)    (struct file *file, void *fh,
@@ -62,6 +64,8 @@ struct v4l2_ioctl_ops {
 					   struct v4l2_format *f);
 	int (*vidioc_g_fmt_vid_out_mplane)(struct file *file, void *fh,
 					   struct v4l2_format *f);
+	int (*vidioc_g_fmt_sdr_cap)    (struct file *file, void *fh,
+					struct v4l2_format *f);
 
 	/* VIDIOC_S_FMT handlers */
 	int (*vidioc_s_fmt_vid_cap)    (struct file *file, void *fh,
@@ -84,6 +88,8 @@ struct v4l2_ioctl_ops {
 					   struct v4l2_format *f);
 	int (*vidioc_s_fmt_vid_out_mplane)(struct file *file, void *fh,
 					   struct v4l2_format *f);
+	int (*vidioc_s_fmt_sdr_cap)    (struct file *file, void *fh,
+					struct v4l2_format *f);
 
 	/* VIDIOC_TRY_FMT handlers */
 	int (*vidioc_try_fmt_vid_cap)    (struct file *file, void *fh,
@@ -106,6 +112,8 @@ struct v4l2_ioctl_ops {
 					     struct v4l2_format *f);
 	int (*vidioc_try_fmt_vid_out_mplane)(struct file *file, void *fh,
 					     struct v4l2_format *f);
+	int (*vidioc_try_fmt_sdr_cap)    (struct file *file, void *fh,
+					  struct v4l2_format *f);
 
 	/* Buffer handlers */
 	int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b);
-- 
1.8.4.2


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH RFC v3 5/7] v4l: enable some IOCTLs for SDR receiver
  2013-12-16 22:08 [PATCH RFC v3 0/7] SDR API Antti Palosaari
                   ` (3 preceding siblings ...)
  2013-12-16 22:08 ` [PATCH RFC v3 4/7] v4l: define own IOCTL ops for SDR FMT Antti Palosaari
@ 2013-12-16 22:08 ` Antti Palosaari
  2013-12-17  7:34   ` Hans Verkuil
  2013-12-16 22:08 ` [PATCH RFC v3 6/7] rtl2832_sdr: convert to SDR API Antti Palosaari
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 23+ messages in thread
From: Antti Palosaari @ 2013-12-16 22:08 UTC (permalink / raw)
  To: linux-media; +Cc: Mauro Carvalho Chehab, Hans Verkuil, Antti Palosaari

Enable stream format (FMT) IOCTLs for SDR use. These are used for negotiate
used data stream format.

Enable input IOCTLs, VIDIOC_ENUMINPUT, VIDIOC_G_INPUT, VIDIOC_S_INPUT.
These are used to select possible antenna connector.

Reorganise some some IOCTL selection logic.

Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/v4l2-core/v4l2-dev.c   | 27 ++++++++++++++++++++++++---
 drivers/media/v4l2-core/v4l2-ioctl.c | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+), 3 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index 6a1e6a8..5795e8d 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -562,7 +562,7 @@ static void determine_valid_ioctls(struct video_device *vdev)
 	const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
 	bool is_vid = vdev->vfl_type == VFL_TYPE_GRABBER;
 	bool is_vbi = vdev->vfl_type == VFL_TYPE_VBI;
-	bool is_radio = vdev->vfl_type == VFL_TYPE_RADIO;
+	bool is_sdr = vdev->vfl_type == VFL_TYPE_SDR;
 	bool is_rx = vdev->vfl_dir != VFL_DIR_TX;
 	bool is_tx = vdev->vfl_dir != VFL_DIR_RX;
 
@@ -671,9 +671,26 @@ static void determine_valid_ioctls(struct video_device *vdev)
 			       ops->vidioc_try_fmt_sliced_vbi_out)))
 			set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls);
 		SET_VALID_IOCTL(ops, VIDIOC_G_SLICED_VBI_CAP, vidioc_g_sliced_vbi_cap);
+	} else if (is_sdr) {
+		/* SDR specific ioctls */
+		if (ops->vidioc_enum_fmt_sdr_cap)
+			set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls);
+		if (ops->vidioc_g_fmt_sdr_cap)
+			set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls);
+		if (ops->vidioc_s_fmt_sdr_cap)
+			set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls);
+		if (ops->vidioc_try_fmt_sdr_cap)
+			set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls);
+
+		if (is_rx) {
+			SET_VALID_IOCTL(ops, VIDIOC_ENUMINPUT, vidioc_enum_input);
+			SET_VALID_IOCTL(ops, VIDIOC_G_INPUT, vidioc_g_input);
+			SET_VALID_IOCTL(ops, VIDIOC_S_INPUT, vidioc_s_input);
+		}
 	}
-	if (!is_radio) {
-		/* ioctls valid for video or vbi */
+
+	if (is_vid || is_vbi || is_sdr) {
+		/* ioctls valid for video, vbi or sdr */
 		SET_VALID_IOCTL(ops, VIDIOC_REQBUFS, vidioc_reqbufs);
 		SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_querybuf);
 		SET_VALID_IOCTL(ops, VIDIOC_QBUF, vidioc_qbuf);
@@ -681,6 +698,10 @@ static void determine_valid_ioctls(struct video_device *vdev)
 		SET_VALID_IOCTL(ops, VIDIOC_DQBUF, vidioc_dqbuf);
 		SET_VALID_IOCTL(ops, VIDIOC_CREATE_BUFS, vidioc_create_bufs);
 		SET_VALID_IOCTL(ops, VIDIOC_PREPARE_BUF, vidioc_prepare_buf);
+	}
+
+	if (is_vid || is_vbi) {
+		/* ioctls valid for video or vbi */
 		if (ops->vidioc_s_std)
 			set_bit(_IOC_NR(VIDIOC_ENUMSTD), valid_ioctls);
 		SET_VALID_IOCTL(ops, VIDIOC_S_STD, vidioc_s_std);
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index da197e1..d0777bd 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -243,6 +243,7 @@ static void v4l_print_format(const void *arg, bool write_only)
 	const struct v4l2_vbi_format *vbi;
 	const struct v4l2_sliced_vbi_format *sliced;
 	const struct v4l2_window *win;
+	const struct v4l2_format_sdr *sdr;
 	unsigned i;
 
 	pr_cont("type=%s", prt_names(p->type, v4l2_type_names));
@@ -316,6 +317,14 @@ static void v4l_print_format(const void *arg, bool write_only)
 				sliced->service_lines[0][i],
 				sliced->service_lines[1][i]);
 		break;
+	case V4L2_BUF_TYPE_SDR_CAPTURE:
+		sdr = &p->fmt.sdr;
+		pr_cont(", pixelformat=%c%c%c%c\n",
+			(sdr->pixelformat >>  0) & 0xff,
+			(sdr->pixelformat >>  8) & 0xff,
+			(sdr->pixelformat >> 16) & 0xff,
+			(sdr->pixelformat >> 24) & 0xff);
+		break;
 	}
 }
 
@@ -879,6 +888,7 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type)
 	const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
 	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
 	bool is_vbi = vfd->vfl_type == VFL_TYPE_VBI;
+	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
 
@@ -928,6 +938,10 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type)
 		if (is_vbi && is_tx && ops->vidioc_g_fmt_sliced_vbi_out)
 			return 0;
 		break;
+	case V4L2_BUF_TYPE_SDR_CAPTURE:
+		if (is_sdr && is_rx && ops->vidioc_g_fmt_sdr_cap)
+			return 0;
+		break;
 	default:
 		break;
 	}
@@ -1047,6 +1061,10 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops,
 		if (unlikely(!is_tx || !ops->vidioc_enum_fmt_vid_out_mplane))
 			break;
 		return ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg);
+	case V4L2_BUF_TYPE_SDR_CAPTURE:
+		if (unlikely(!is_rx || !ops->vidioc_enum_fmt_sdr_cap))
+			break;
+		return ops->vidioc_enum_fmt_sdr_cap(file, fh, arg);
 	}
 	return -EINVAL;
 }
@@ -1057,6 +1075,7 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
 	struct v4l2_format *p = arg;
 	struct video_device *vfd = video_devdata(file);
 	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
+	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
 
@@ -1101,6 +1120,10 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
 		if (unlikely(!is_tx || is_vid || !ops->vidioc_g_fmt_sliced_vbi_out))
 			break;
 		return ops->vidioc_g_fmt_sliced_vbi_out(file, fh, arg);
+	case V4L2_BUF_TYPE_SDR_CAPTURE:
+		if (unlikely(!is_rx || !is_sdr || !ops->vidioc_g_fmt_sdr_cap))
+			break;
+		return ops->vidioc_g_fmt_sdr_cap(file, fh, arg);
 	}
 	return -EINVAL;
 }
@@ -1111,6 +1134,7 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
 	struct v4l2_format *p = arg;
 	struct video_device *vfd = video_devdata(file);
 	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
+	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
 
@@ -1165,6 +1189,11 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
 			break;
 		CLEAR_AFTER_FIELD(p, fmt.sliced);
 		return ops->vidioc_s_fmt_sliced_vbi_out(file, fh, arg);
+	case V4L2_BUF_TYPE_SDR_CAPTURE:
+		if (unlikely(!is_rx || !is_sdr || !ops->vidioc_s_fmt_sdr_cap))
+			break;
+		CLEAR_AFTER_FIELD(p, fmt.sdr);
+		return ops->vidioc_s_fmt_sdr_cap(file, fh, arg);
 	}
 	return -EINVAL;
 }
@@ -1175,6 +1204,7 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
 	struct v4l2_format *p = arg;
 	struct video_device *vfd = video_devdata(file);
 	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
+	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
 
@@ -1229,6 +1259,11 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
 			break;
 		CLEAR_AFTER_FIELD(p, fmt.sliced);
 		return ops->vidioc_try_fmt_sliced_vbi_out(file, fh, arg);
+	case V4L2_BUF_TYPE_SDR_CAPTURE:
+		if (unlikely(!is_rx || !is_sdr || !ops->vidioc_try_fmt_sdr_cap))
+			break;
+		CLEAR_AFTER_FIELD(p, fmt.sdr);
+		return ops->vidioc_try_fmt_sdr_cap(file, fh, arg);
 	}
 	return -EINVAL;
 }
-- 
1.8.4.2


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH RFC v3 6/7] rtl2832_sdr: convert to SDR API
  2013-12-16 22:08 [PATCH RFC v3 0/7] SDR API Antti Palosaari
                   ` (4 preceding siblings ...)
  2013-12-16 22:08 ` [PATCH RFC v3 5/7] v4l: enable some IOCTLs for SDR receiver Antti Palosaari
@ 2013-12-16 22:08 ` Antti Palosaari
  2013-12-17  7:45   ` Hans Verkuil
  2013-12-19  9:21   ` Hans Verkuil
  2013-12-16 22:08 ` [PATCH RFC v3 7/7] msi3101: " Antti Palosaari
  2013-12-17  7:36 ` [PATCH RFC v3 0/7] " Hans Verkuil
  7 siblings, 2 replies; 23+ messages in thread
From: Antti Palosaari @ 2013-12-16 22:08 UTC (permalink / raw)
  To: linux-media; +Cc: Mauro Carvalho Chehab, Hans Verkuil, Antti Palosaari

It was abusing video device API. Use SDR API instead.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 291 ++++++++++++++++++-----
 1 file changed, 227 insertions(+), 64 deletions(-)

diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index 4b8c016..f0965ea 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -20,12 +20,6 @@
  * GNU Radio plugin "gr-kernel" for device usage will be on:
  * http://git.linuxtv.org/anttip/gr-kernel.git
  *
- * TODO:
- * Help is very highly welcome for these + all the others you could imagine:
- * - move controls to V4L2 API
- * - use libv4l2 for stream format conversions
- * - gr-kernel: switch to v4l2_mmap (current read eats a lot of cpu)
- * - SDRSharp support
  */
 
 #include "dvb_frontend.h"
@@ -38,6 +32,7 @@
 #include <media/v4l2-event.h>
 #include <media/videobuf2-vmalloc.h>
 
+#include <linux/jiffies.h>
 #include <linux/math64.h>
 
 /* TODO: These should be moved to V4L2 API */
@@ -49,11 +44,68 @@
 #define RTL2832_SDR_CID_TUNER_IF            ((V4L2_CID_USER_BASE | 0xf000) + 12)
 #define RTL2832_SDR_CID_TUNER_GAIN          ((V4L2_CID_USER_BASE | 0xf000) + 13)
 
-#define V4L2_PIX_FMT_SDR_U8     v4l2_fourcc('D', 'U', '0', '8') /* unsigned 8-bit */
+#define V4L2_PIX_FMT_SDR_U8    v4l2_fourcc('D', 'U', '0', '8')
+#define V4L2_PIX_FMT_SDR_U16LE v4l2_fourcc('D', 'U', '1', '6')
 
 #define MAX_BULK_BUFS            (10)
 #define BULK_BUFFER_SIZE         (128 * 512)
 
+static const struct v4l2_frequency_band bands_adc[] = {
+	{
+		.tuner = 0,
+		.type = V4L2_TUNER_ADC,
+		.index = 0,
+		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow   =  300000,
+		.rangehigh  =  300000,
+	},
+	{
+		.tuner = 0,
+		.type = V4L2_TUNER_ADC,
+		.index = 1,
+		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow   =  900001,
+		.rangehigh  = 2800000,
+	},
+	{
+		.tuner = 0,
+		.type = V4L2_TUNER_ADC,
+		.index = 2,
+		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow   = 3200000,
+		.rangehigh  = 3200000,
+	},
+};
+
+static const struct v4l2_frequency_band bands_fm[] = {
+	{
+		.tuner = 1,
+		.type = V4L2_TUNER_RF,
+		.index = 0,
+		.capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow   =    50000000 / 62.5,
+		.rangehigh  =  2000000000 / 62.5,
+	},
+};
+
+/* stream formats */
+struct rtl2832_sdr_format {
+	char	*name;
+	u32	pixelformat;
+};
+
+static struct rtl2832_sdr_format formats[] = {
+	{
+		.name		= "I/Q 8-bit unsigned",
+		.pixelformat	= V4L2_PIX_FMT_SDR_U8,
+	}, {
+		.name		= "I/Q 16-bit unsigned little endian",
+		.pixelformat	= V4L2_PIX_FMT_SDR_U16LE,
+	},
+};
+
+static const int NUM_FORMATS = sizeof(formats) / sizeof(struct rtl2832_sdr_format);
+
 /* intermediate buffers with raw data from the USB device */
 struct rtl2832_sdr_frame_buf {
 	struct vb2_buffer vb;   /* common v4l buffer stuff -- must be first */
@@ -96,6 +148,9 @@ struct rtl2832_sdr_state {
 	int urbs_initialized;
 	int urbs_submitted;
 
+	unsigned int f_adc, f_tuner;
+	u32 pixelformat;
+
 	/* Controls */
 	struct v4l2_ctrl_handler ctrl_handler;
 	struct v4l2_ctrl *ctrl_sampling_rate;
@@ -107,7 +162,7 @@ struct rtl2832_sdr_state {
 	/* for sample rate calc */
 	unsigned int sample;
 	unsigned int sample_measured;
-	unsigned long jiffies;
+	unsigned long jiffies_next;
 };
 
 /* write multiple hardware registers */
@@ -292,27 +347,41 @@ leave:
 }
 
 static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s,
-		u8 *dst, const u8 *src, unsigned int src_len)
+		void *dst, const u8 *src, unsigned int src_len)
 {
-	memcpy(dst, src, src_len);
+	unsigned int dst_len;
+
+	if (s->pixelformat == V4L2_PIX_FMT_SDR_U8) {
+		/* native stream, no need to convert */
+		memcpy(dst, src, src_len);
+		dst_len = src_len;
+	} else if (s->pixelformat == V4L2_PIX_FMT_SDR_U16LE) {
+		/* convert u8 to u16 */
+		unsigned int i;
+		u16 *u16dst = dst;
+		for (i = 0; i < src_len; i++)
+			*u16dst++ = (src[i] << 8) | (src[i] >> 0);
+		dst_len = 2 * src_len;
+	} else {
+		dst_len = 0;
+	}
 
 	/* calculate samping rate and output it in 10 seconds intervals */
-	if ((s->jiffies + msecs_to_jiffies(10000)) <= jiffies) {
-		unsigned long jiffies_now = jiffies;
-		unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies);
+	if (unlikely(time_is_before_jiffies(s->jiffies_next))) {
+#define MSECS 10000UL
 		unsigned int samples = s->sample - s->sample_measured;
-		s->jiffies = jiffies_now;
+		s->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
 		s->sample_measured = s->sample;
 		dev_dbg(&s->udev->dev,
 				"slen=%d samples=%u msecs=%lu sampling rate=%lu\n",
-				src_len, samples, msecs,
-				samples * 1000UL / msecs);
+				src_len, samples, MSECS,
+				samples * 1000UL / MSECS);
 	}
 
 	/* total number of I+Q pairs */
 	s->sample += src_len / 2;
 
-	return src_len;
+	return dst_len;
 }
 
 /*
@@ -343,12 +412,12 @@ static void rtl2832_sdr_urb_complete(struct urb *urb)
 		break;
 	}
 
-	if (urb->actual_length > 0) {
+	if (likely(urb->actual_length > 0)) {
 		void *ptr;
 		unsigned int len;
 		/* get free framebuffer */
 		fbuf = rtl2832_sdr_get_next_fill_buf(s);
-		if (fbuf == NULL) {
+		if (unlikely(fbuf == NULL)) {
 			s->vb_full++;
 			dev_notice_ratelimited(&s->udev->dev,
 					"videobuf is full, %d packets dropped\n",
@@ -544,7 +613,7 @@ static int rtl2832_sdr_querycap(struct file *file, void *fh,
 	strlcpy(cap->card, s->vdev.name, sizeof(cap->card));
 	usb_make_path(s->udev, cap->bus_info, sizeof(cap->bus_info));
 	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
-			V4L2_CAP_READWRITE;
+			V4L2_CAP_READWRITE | V4L2_CAP_TUNER;
 	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
 	return 0;
 }
@@ -560,7 +629,8 @@ static int rtl2832_sdr_queue_setup(struct vb2_queue *vq,
 	/* Absolute min and max number of buffers available for mmap() */
 	*nbuffers = 32;
 	*nplanes = 1;
-	sizes[0] = PAGE_ALIGN(BULK_BUFFER_SIZE * 4); /* 8 * 512 * 4 = 16384 */
+	/* 2 = max 16-bit sample returned */
+	sizes[0] = PAGE_ALIGN(BULK_BUFFER_SIZE * 2);
 	dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n",
 			__func__, *nbuffers, sizes[0]);
 	return 0;
@@ -913,13 +983,14 @@ static struct vb2_ops rtl2832_sdr_vb2_ops = {
 	.wait_finish            = vb2_ops_wait_finish,
 };
 
-static int rtl2832_sdr_enum_input(struct file *file, void *fh, struct v4l2_input *i)
+static int rtl2832_sdr_enum_input(struct file *file, void *fh,
+		struct v4l2_input *i)
 {
-	if (i->index != 0)
+	if (i->index > 0)
 		return -EINVAL;
 
-	strlcpy(i->name, "SDR data", sizeof(i->name));
-	i->type = V4L2_INPUT_TYPE_CAMERA;
+	strlcpy(i->name, "Antenna #0", sizeof(i->name));
+	i->type = V4L2_INPUT_TYPE_TUNER;
 
 	return 0;
 }
@@ -933,10 +1004,39 @@ static int rtl2832_sdr_g_input(struct file *file, void *fh, unsigned int *i)
 
 static int rtl2832_sdr_s_input(struct file *file, void *fh, unsigned int i)
 {
-	return i ? -EINVAL : 0;
+	if (i > 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int rtl2832_sdr_g_tuner(struct file *file, void *priv,
+		struct v4l2_tuner *v)
+{
+	struct rtl2832_sdr_state *s = video_drvdata(file);
+	dev_dbg(&s->udev->dev, "%s: index=%d type=%d\n",
+			__func__, v->index, v->type);
+
+	if (v->index == 0) {
+		strlcpy(v->name, "ADC: Realtek RTL2832", sizeof(v->name));
+		v->type = V4L2_TUNER_ADC;
+		v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+		v->rangelow =   300000;
+		v->rangehigh = 3200000;
+	} else if (v->index == 1) {
+		strlcpy(v->name, "RF: <unknown>", sizeof(v->name));
+		v->type = V4L2_TUNER_RF;
+		v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS;
+		v->rangelow =    50000000 / 62.5;
+		v->rangehigh = 2000000000 / 62.5;
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
 }
 
-static int vidioc_s_tuner(struct file *file, void *priv,
+static int rtl2832_sdr_s_tuner(struct file *file, void *priv,
 		const struct v4l2_tuner *v)
 {
 	struct rtl2832_sdr_state *s = video_drvdata(file);
@@ -945,91 +1045,149 @@ static int vidioc_s_tuner(struct file *file, void *priv,
 	return 0;
 }
 
-static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
+static int rtl2832_sdr_enum_freq_bands(struct file *file, void *priv,
+		struct v4l2_frequency_band *band)
 {
 	struct rtl2832_sdr_state *s = video_drvdata(file);
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d index=%d\n",
+			__func__, band->tuner, band->type, band->index);
+
+	if (band->tuner == 0) {
+		if (band->index >= ARRAY_SIZE(bands_adc))
+			return -EINVAL;
 
-	strcpy(v->name, "SDR RX");
-	v->capability = V4L2_TUNER_CAP_LOW;
+		*band = bands_adc[band->index];
+	} else if (band->tuner == 1) {
+		if (band->index >= ARRAY_SIZE(bands_fm))
+			return -EINVAL;
+
+		*band = bands_fm[band->index];
+	} else {
+		return -EINVAL;
+	}
 
 	return 0;
 }
 
-static int vidioc_s_frequency(struct file *file, void *priv,
+static int rtl2832_sdr_g_frequency(struct file *file, void *priv,
+		struct v4l2_frequency *f)
+{
+	struct rtl2832_sdr_state *s = video_drvdata(file);
+	int ret  = 0;
+	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n",
+			__func__, f->tuner, f->type);
+
+	if (f->tuner == 0)
+		f->frequency = s->f_adc;
+	else if (f->tuner == 1)
+		f->frequency = s->f_tuner;
+	else
+		return -EINVAL;
+
+	return ret;
+}
+
+static int rtl2832_sdr_s_frequency(struct file *file, void *priv,
 		const struct v4l2_frequency *f)
 {
 	struct rtl2832_sdr_state *s = video_drvdata(file);
-	dev_dbg(&s->udev->dev, "%s: frequency=%lu Hz (%u)\n",
-			__func__, f->frequency * 625UL / 10UL, f->frequency);
+	int ret;
+	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n",
+			__func__, f->tuner, f->type, f->frequency);
+
+	if (f->tuner == 0) {
+		dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n",
+				__func__, f->frequency);
+		s->f_adc = f->frequency;
+		ret = v4l2_ctrl_s_ctrl_int64(s->ctrl_sampling_rate,
+				f->frequency);
+	} else if (f->tuner == 1) {
+		dev_dbg(&s->udev->dev, "%s: RF frequency=%lu Hz\n",
+				__func__, f->frequency * 625UL / 10UL);
+		s->f_tuner = f->frequency;
+		ret = v4l2_ctrl_s_ctrl_int64(s->ctrl_tuner_rf,
+				f->frequency * 625UL / 10UL);
+	} else {
+		return -EINVAL;
+	}
 
-	return v4l2_ctrl_s_ctrl_int64(s->ctrl_tuner_rf,
-			f->frequency * 625UL / 10UL);
+	return ret;
 }
 
-static int rtl2832_sdr_enum_fmt_vid_cap(struct file *file, void *priv,
+static int rtl2832_sdr_enum_fmt_sdr_cap(struct file *file, void *priv,
 		struct v4l2_fmtdesc *f)
 {
 	struct rtl2832_sdr_state *s = video_drvdata(file);
 	dev_dbg(&s->udev->dev, "%s:\n", __func__);
 
-	if (f->index > 0)
+	if (f->index >= NUM_FORMATS)
 		return -EINVAL;
 
-	f->flags = 0;
-	strcpy(f->description, "I/Q 8-bit unsigned");
-	f->pixelformat = V4L2_PIX_FMT_SDR_U8;
+	strlcpy(f->description, formats[f->index].name, sizeof(f->description));
+	f->pixelformat = formats[f->index].pixelformat;
 
 	return 0;
 }
 
-static int rtl2832_sdr_g_fmt_vid_cap(struct file *file, void *priv,
+static int rtl2832_sdr_g_fmt_sdr_cap(struct file *file, void *priv,
 		struct v4l2_format *f)
 {
 	struct rtl2832_sdr_state *s = video_drvdata(file);
 	dev_dbg(&s->udev->dev, "%s:\n", __func__);
 
-	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+	if (f->type != V4L2_BUF_TYPE_SDR_CAPTURE)
 		return -EINVAL;
 
-	memset(&f->fmt.pix, 0, sizeof(f->fmt.pix));
-	f->fmt.pix.pixelformat = V4L2_PIX_FMT_SDR_U8;
+	f->fmt.sdr.pixelformat = s->pixelformat;
 
 	return 0;
 }
 
-static int rtl2832_sdr_s_fmt_vid_cap(struct file *file, void *priv,
+static int rtl2832_sdr_s_fmt_sdr_cap(struct file *file, void *priv,
 		struct v4l2_format *f)
 {
 	struct rtl2832_sdr_state *s = video_drvdata(file);
 	struct vb2_queue *q = &s->vb_queue;
+	int i;
 	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
-			(char *)&f->fmt.pix.pixelformat);
+			(char *)&f->fmt.sdr.pixelformat);
 
-	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+	if (f->type != V4L2_BUF_TYPE_SDR_CAPTURE)
 		return -EINVAL;
 
 	if (vb2_is_busy(q))
 		return -EBUSY;
 
-	memset(&f->fmt.pix, 0, sizeof(f->fmt.pix));
-	f->fmt.pix.pixelformat = V4L2_PIX_FMT_SDR_U8;
+	for (i = 0; i < NUM_FORMATS; i++) {
+		if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
+			s->pixelformat = f->fmt.sdr.pixelformat;
+			return 0;
+		}
+	}
+
+	f->fmt.sdr.pixelformat = formats[0].pixelformat;
+	s->pixelformat = formats[0].pixelformat;
 
 	return 0;
 }
 
-static int rtl2832_sdr_try_fmt_vid_cap(struct file *file, void *priv,
+static int rtl2832_sdr_try_fmt_sdr_cap(struct file *file, void *priv,
 		struct v4l2_format *f)
 {
 	struct rtl2832_sdr_state *s = video_drvdata(file);
+	int i;
 	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
-			(char *)&f->fmt.pix.pixelformat);
+			(char *)&f->fmt.sdr.pixelformat);
 
-	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+	if (f->type != V4L2_BUF_TYPE_SDR_CAPTURE)
 		return -EINVAL;
 
-	memset(&f->fmt.pix, 0, sizeof(f->fmt.pix));
-	f->fmt.pix.pixelformat = V4L2_PIX_FMT_SDR_U8;
+	for (i = 0; i < NUM_FORMATS; i++) {
+		if (formats[i].pixelformat == f->fmt.sdr.pixelformat)
+			return 0;
+	}
+
+	f->fmt.sdr.pixelformat = formats[0].pixelformat;
 
 	return 0;
 }
@@ -1037,10 +1195,10 @@ static int rtl2832_sdr_try_fmt_vid_cap(struct file *file, void *priv,
 static const struct v4l2_ioctl_ops rtl2832_sdr_ioctl_ops = {
 	.vidioc_querycap          = rtl2832_sdr_querycap,
 
-	.vidioc_enum_fmt_vid_cap  = rtl2832_sdr_enum_fmt_vid_cap,
-	.vidioc_g_fmt_vid_cap     = rtl2832_sdr_g_fmt_vid_cap,
-	.vidioc_s_fmt_vid_cap     = rtl2832_sdr_s_fmt_vid_cap,
-	.vidioc_try_fmt_vid_cap   = rtl2832_sdr_try_fmt_vid_cap,
+	.vidioc_enum_fmt_sdr_cap  = rtl2832_sdr_enum_fmt_sdr_cap,
+	.vidioc_g_fmt_sdr_cap     = rtl2832_sdr_g_fmt_sdr_cap,
+	.vidioc_s_fmt_sdr_cap     = rtl2832_sdr_s_fmt_sdr_cap,
+	.vidioc_try_fmt_sdr_cap   = rtl2832_sdr_try_fmt_sdr_cap,
 
 	.vidioc_enum_input        = rtl2832_sdr_enum_input,
 	.vidioc_g_input           = rtl2832_sdr_g_input,
@@ -1056,9 +1214,12 @@ static const struct v4l2_ioctl_ops rtl2832_sdr_ioctl_ops = {
 	.vidioc_streamon          = vb2_ioctl_streamon,
 	.vidioc_streamoff         = vb2_ioctl_streamoff,
 
-	.vidioc_g_tuner           = vidioc_g_tuner,
-	.vidioc_s_tuner           = vidioc_s_tuner,
-	.vidioc_s_frequency       = vidioc_s_frequency,
+	.vidioc_g_tuner           = rtl2832_sdr_g_tuner,
+	.vidioc_s_tuner           = rtl2832_sdr_s_tuner,
+
+	.vidioc_enum_freq_bands   = rtl2832_sdr_enum_freq_bands,
+	.vidioc_g_frequency       = rtl2832_sdr_g_frequency,
+	.vidioc_s_frequency       = rtl2832_sdr_s_frequency,
 
 	.vidioc_subscribe_event   = v4l2_ctrl_subscribe_event,
 	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
@@ -1080,6 +1241,7 @@ static struct video_device rtl2832_sdr_template = {
 	.release                  = video_device_release_empty,
 	.fops                     = &rtl2832_sdr_fops,
 	.ioctl_ops                = &rtl2832_sdr_ioctl_ops,
+	.debug                    = 0,
 };
 
 static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl)
@@ -1227,7 +1389,7 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
 	INIT_LIST_HEAD(&s->queued_bufs);
 
 	/* Init videobuf2 queue structure */
-	s->vb_queue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	s->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE;
 	s->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
 	s->vb_queue.drv_priv = s;
 	s->vb_queue.buf_struct_size = sizeof(struct rtl2832_sdr_frame_buf);
@@ -1274,8 +1436,9 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
 	s->v4l2_dev.ctrl_handler = &s->ctrl_handler;
 	s->vdev.v4l2_dev = &s->v4l2_dev;
 	s->vdev.lock = &s->v4l2_lock;
+	s->vdev.vfl_dir = VFL_DIR_RX;
 
-	ret = video_register_device(&s->vdev, VFL_TYPE_GRABBER, -1);
+	ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1);
 	if (ret < 0) {
 		dev_err(&s->udev->dev,
 				"Failed to register as video device (%d)\n",
-- 
1.8.4.2


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH RFC v3 7/7] msi3101: convert to SDR API
  2013-12-16 22:08 [PATCH RFC v3 0/7] SDR API Antti Palosaari
                   ` (5 preceding siblings ...)
  2013-12-16 22:08 ` [PATCH RFC v3 6/7] rtl2832_sdr: convert to SDR API Antti Palosaari
@ 2013-12-16 22:08 ` Antti Palosaari
  2013-12-17  7:36 ` [PATCH RFC v3 0/7] " Hans Verkuil
  7 siblings, 0 replies; 23+ messages in thread
From: Antti Palosaari @ 2013-12-16 22:08 UTC (permalink / raw)
  To: linux-media; +Cc: Mauro Carvalho Chehab, Hans Verkuil, Antti Palosaari

Convert to SDR API.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/staging/media/msi3101/sdr-msi3101.c | 204 ++++++++++++++++++++--------
 1 file changed, 148 insertions(+), 56 deletions(-)

diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index 16ce417..9c54c63 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -386,10 +386,39 @@ static const struct msi3101_gain msi3101_gain_lut_1000[] = {
 #define MSI3101_CID_TUNER_GAIN            ((V4L2_CID_USER_BASE | 0xf000) + 13)
 
 #define V4L2_PIX_FMT_SDR_S8     v4l2_fourcc('D', 'S', '0', '8') /* signed 8-bit */
-#define V4L2_PIX_FMT_SDR_S12     v4l2_fourcc('D', 'S', '1', '2') /* signed 12-bit */
-#define V4L2_PIX_FMT_SDR_S14     v4l2_fourcc('D', 'S', '1', '4') /* signed 14-bit */
+#define V4L2_PIX_FMT_SDR_S12    v4l2_fourcc('D', 'S', '1', '2') /* signed 12-bit */
+#define V4L2_PIX_FMT_SDR_S14    v4l2_fourcc('D', 'S', '1', '4') /* signed 14-bit */
 #define V4L2_PIX_FMT_SDR_MSI2500_384 v4l2_fourcc('M', '3', '8', '4') /* Mirics MSi2500 format 384 */
 
+static const struct v4l2_frequency_band bands_adc[] = {
+	{
+		.tuner = 0,
+		.type = V4L2_TUNER_ADC,
+		.index = 0,
+		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow   =  1200000,
+		.rangehigh  = 15000000,
+	},
+};
+
+static const struct v4l2_frequency_band bands_rf[] = {
+	{
+		.tuner = 1,
+		.type = V4L2_TUNER_RF,
+		.index = 0,
+		.capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow   =   49000000 / 62.5,
+		.rangehigh  =  263000000 / 62.5,
+	}, {
+		.tuner = 1,
+		.type = V4L2_TUNER_RF,
+		.index = 1,
+		.capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow   =  390000000 / 62.5,
+		.rangehigh  =  960000000 / 62.5,
+	},
+};
+
 /* stream formats */
 struct msi3101_format {
 	char	*name;
@@ -437,6 +466,7 @@ struct msi3101_state {
 	/* Pointer to our usb_device, will be NULL after unplug */
 	struct usb_device *udev; /* Both mutexes most be hold when setting! */
 
+	unsigned int f_adc, f_tuner;
 	u32 pixelformat;
 
 	unsigned int isoc_errors; /* number of contiguous ISOC errors */
@@ -479,16 +509,6 @@ leave:
 }
 
 /*
- * Integer to 32-bit IEEE floating point representation routine is taken
- * from Radeon R600 driver (drivers/gpu/drm/radeon/r600_blit_kms.c).
- *
- * TODO: Currently we do conversion here in Kernel, but in future that will
- * be moved to the libv4l2 library as video format conversions are.
- */
-#define I2F_FRAC_BITS  23
-#define I2F_MASK ((1 << I2F_FRAC_BITS) - 1)
-
-/*
  * +===========================================================================
  * |   00-1023 | USB packet type '504'
  * +===========================================================================
@@ -1016,12 +1036,11 @@ static int msi3101_querycap(struct file *file, void *fh,
 	strlcpy(cap->card, s->vdev.name, sizeof(cap->card));
 	usb_make_path(s->udev, cap->bus_info, sizeof(cap->bus_info));
 	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
-			V4L2_CAP_READWRITE;
+			V4L2_CAP_READWRITE | V4L2_CAP_TUNER;
 	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
 	return 0;
 }
 
-
 /* Videobuf2 operations */
 static int msi3101_queue_setup(struct vb2_queue *vq,
 		const struct v4l2_format *fmt, unsigned int *nbuffers,
@@ -1037,9 +1056,9 @@ static int msi3101_queue_setup(struct vb2_queue *vq,
 	 *   3, wMaxPacketSize 3x 1024 bytes
 	 * 504, max IQ sample pairs per 1024 frame
 	 *   2, two samples, I and Q
-	 *   4, 32-bit float
+	 *   2, 16-bit is enough for single sample
 	 */
-	sizes[0] = PAGE_ALIGN(3 * 504 * 2 * 4); /* = 12096 */
+	sizes[0] = PAGE_ALIGN(3 * 504 * 2 * 2);
 	dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n",
 			__func__, *nbuffers, sizes[0]);
 	return 0;
@@ -1527,28 +1546,27 @@ static struct vb2_ops msi3101_vb2_ops = {
 
 static int msi3101_enum_input(struct file *file, void *fh, struct v4l2_input *i)
 {
-	if (i->index != 0)
+	if (i->index > 0)
 		return -EINVAL;
-
-	strlcpy(i->name, "SDR data", sizeof(i->name));
-	i->type = V4L2_INPUT_TYPE_CAMERA;
-
+	strlcpy(i->name, "Antenna #0", sizeof(i->name));
+	i->type = V4L2_INPUT_TYPE_TUNER;
 	return 0;
 }
 
 static int msi3101_g_input(struct file *file, void *fh, unsigned int *i)
 {
 	*i = 0;
-
 	return 0;
 }
 
 static int msi3101_s_input(struct file *file, void *fh, unsigned int i)
 {
-	return i ? -EINVAL : 0;
+	if (i > 0)
+		return -EINVAL;
+	return 0;
 }
 
-static int msi3101_enum_fmt_vid_cap(struct file *file, void *priv,
+static int msi3101_enum_fmt_sdr_cap(struct file *file, void *priv,
 		struct v4l2_fmtdesc *f)
 {
 	struct msi3101_state *s = video_drvdata(file);
@@ -1563,70 +1581,70 @@ static int msi3101_enum_fmt_vid_cap(struct file *file, void *priv,
 	return 0;
 }
 
-static int msi3101_g_fmt_vid_cap(struct file *file, void *priv,
+static int msi3101_g_fmt_sdr_cap(struct file *file, void *priv,
 		struct v4l2_format *f)
 {
 	struct msi3101_state *s = video_drvdata(file);
 	dev_dbg(&s->udev->dev, "%s:\n", __func__);
 
-	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+	if (f->type != V4L2_BUF_TYPE_SDR_CAPTURE)
 		return -EINVAL;
 
-	f->fmt.pix.pixelformat = s->pixelformat;
+	f->fmt.sdr.pixelformat = s->pixelformat;
 
 	return 0;
 }
 
-static int msi3101_s_fmt_vid_cap(struct file *file, void *priv,
+static int msi3101_s_fmt_sdr_cap(struct file *file, void *priv,
 		struct v4l2_format *f)
 {
 	struct msi3101_state *s = video_drvdata(file);
 	struct vb2_queue *q = &s->vb_queue;
 	int i;
 	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
-			(char *)&f->fmt.pix.pixelformat);
+			(char *)&f->fmt.sdr.pixelformat);
 
-	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+	if (f->type != V4L2_BUF_TYPE_SDR_CAPTURE)
 		return -EINVAL;
 
 	if (vb2_is_busy(q))
 		return -EBUSY;
 
 	for (i = 0; i < NUM_FORMATS; i++) {
-		if (formats[i].pixelformat == f->fmt.pix.pixelformat) {
-			s->pixelformat = f->fmt.pix.pixelformat;
+		if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
+			s->pixelformat = f->fmt.sdr.pixelformat;
 			return 0;
 		}
 	}
 
-	f->fmt.pix.pixelformat = formats[0].pixelformat;
+	f->fmt.sdr.pixelformat = formats[0].pixelformat;
 	s->pixelformat = formats[0].pixelformat;
 
 	return 0;
 }
 
-static int msi3101_try_fmt_vid_cap(struct file *file, void *priv,
+static int msi3101_try_fmt_sdr_cap(struct file *file, void *priv,
 		struct v4l2_format *f)
 {
 	struct msi3101_state *s = video_drvdata(file);
 	int i;
 	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
-			(char *)&f->fmt.pix.pixelformat);
+			(char *)&f->fmt.sdr.pixelformat);
 
-	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+	if (f->type != V4L2_BUF_TYPE_SDR_CAPTURE)
 		return -EINVAL;
 
 	for (i = 0; i < NUM_FORMATS; i++) {
-		if (formats[i].pixelformat == f->fmt.pix.pixelformat)
+		if (formats[i].pixelformat == f->fmt.sdr.pixelformat)
 			return 0;
 	}
 
-	f->fmt.pix.pixelformat = formats[0].pixelformat;
+	f->fmt.sdr.pixelformat = formats[0].pixelformat;
 
 	return 0;
 }
 
-static int vidioc_s_tuner(struct file *file, void *priv,
+static int msi3101_s_tuner(struct file *file, void *priv,
 		const struct v4l2_tuner *v)
 {
 	struct msi3101_state *s = video_drvdata(file);
@@ -1635,35 +1653,106 @@ static int vidioc_s_tuner(struct file *file, void *priv,
 	return 0;
 }
 
-static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
+static int msi3101_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
 {
 	struct msi3101_state *s = video_drvdata(file);
 	dev_dbg(&s->udev->dev, "%s:\n", __func__);
 
-	strcpy(v->name, "SDR RX");
-	v->capability = V4L2_TUNER_CAP_LOW;
+	if (v->index == 0) {
+		strlcpy(v->name, "ADC: Mirics MSi2500", sizeof(v->name));
+		v->type = V4L2_TUNER_ADC;
+		v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+		v->rangelow =   1200000;
+		v->rangehigh = 15000000;
+	} else if (v->index == 1) {
+		strlcpy(v->name, "RF: Mirics MSi001", sizeof(v->name));
+		v->type = V4L2_TUNER_RF;
+		v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS;
+		v->rangelow =    49000000 / 62.5;
+		v->rangehigh =  960000000 / 62.5;
+	} else {
+		return -EINVAL;
+	}
 
 	return 0;
 }
 
-static int vidioc_s_frequency(struct file *file, void *priv,
+static int msi3101_g_frequency(struct file *file, void *priv,
+		struct v4l2_frequency *f)
+{
+	struct msi3101_state *s = video_drvdata(file);
+	int ret  = 0;
+	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n",
+			__func__, f->tuner, f->type);
+
+	if (f->tuner == 0)
+		f->frequency = s->f_adc;
+	else if (f->tuner == 1)
+		f->frequency = s->f_tuner;
+	else
+		return -EINVAL;
+
+	return ret;
+}
+
+static int msi3101_s_frequency(struct file *file, void *priv,
 		const struct v4l2_frequency *f)
 {
 	struct msi3101_state *s = video_drvdata(file);
-	dev_dbg(&s->udev->dev, "%s: frequency=%lu Hz (%u)\n",
-			__func__, f->frequency * 625UL / 10UL, f->frequency);
+	int ret;
+	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n",
+			__func__, f->tuner, f->type, f->frequency);
+
+	if (f->tuner == 0) {
+		dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n",
+				__func__, f->frequency);
+		s->f_adc = f->frequency;
+		ret = v4l2_ctrl_s_ctrl_int64(s->ctrl_sampling_rate,
+				f->frequency);
+	} else if (f->tuner == 1) {
+		dev_dbg(&s->udev->dev, "%s: RF frequency=%lu Hz\n",
+				__func__, f->frequency * 625UL / 10UL);
+		s->f_tuner = f->frequency;
+		ret = v4l2_ctrl_s_ctrl_int64(s->ctrl_tuner_rf,
+				f->frequency * 625UL / 10UL);
+	} else {
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+static int msi3101_enum_freq_bands(struct file *file, void *priv,
+		struct v4l2_frequency_band *band)
+{
+	struct msi3101_state *s = video_drvdata(file);
+	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d index=%d\n",
+			__func__, band->tuner, band->type, band->index);
+
+	if (band->tuner == 0) {
+		if (band->index >= ARRAY_SIZE(bands_adc))
+			return -EINVAL;
+
+		*band = bands_adc[band->index];
+	} else if (band->tuner == 1) {
+		if (band->index >= ARRAY_SIZE(bands_rf))
+			return -EINVAL;
 
-	return v4l2_ctrl_s_ctrl_int64(s->ctrl_tuner_rf,
-			f->frequency * 625UL / 10UL);
+		*band = bands_rf[band->index];
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
 }
 
 static const struct v4l2_ioctl_ops msi3101_ioctl_ops = {
 	.vidioc_querycap          = msi3101_querycap,
 
-	.vidioc_enum_fmt_vid_cap  = msi3101_enum_fmt_vid_cap,
-	.vidioc_g_fmt_vid_cap     = msi3101_g_fmt_vid_cap,
-	.vidioc_s_fmt_vid_cap     = msi3101_s_fmt_vid_cap,
-	.vidioc_try_fmt_vid_cap   = msi3101_try_fmt_vid_cap,
+	.vidioc_enum_fmt_sdr_cap  = msi3101_enum_fmt_sdr_cap,
+	.vidioc_g_fmt_sdr_cap     = msi3101_g_fmt_sdr_cap,
+	.vidioc_s_fmt_sdr_cap     = msi3101_s_fmt_sdr_cap,
+	.vidioc_try_fmt_sdr_cap   = msi3101_try_fmt_sdr_cap,
 
 	.vidioc_enum_input        = msi3101_enum_input,
 	.vidioc_g_input           = msi3101_g_input,
@@ -1679,9 +1768,12 @@ static const struct v4l2_ioctl_ops msi3101_ioctl_ops = {
 	.vidioc_streamon          = vb2_ioctl_streamon,
 	.vidioc_streamoff         = vb2_ioctl_streamoff,
 
-	.vidioc_g_tuner           = vidioc_g_tuner,
-	.vidioc_s_tuner           = vidioc_s_tuner,
-	.vidioc_s_frequency       = vidioc_s_frequency,
+	.vidioc_g_tuner           = msi3101_g_tuner,
+	.vidioc_s_tuner           = msi3101_s_tuner,
+
+	.vidioc_g_frequency       = msi3101_g_frequency,
+	.vidioc_s_frequency       = msi3101_s_frequency,
+	.vidioc_enum_freq_bands   = msi3101_enum_freq_bands,
 
 	.vidioc_subscribe_event   = v4l2_ctrl_subscribe_event,
 	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
@@ -1844,7 +1936,7 @@ static int msi3101_probe(struct usb_interface *intf,
 	s->udev = udev;
 
 	/* Init videobuf2 queue structure */
-	s->vb_queue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	s->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE;
 	s->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
 	s->vb_queue.drv_priv = s;
 	s->vb_queue.buf_struct_size = sizeof(struct msi3101_frame_buf);
@@ -1892,7 +1984,7 @@ static int msi3101_probe(struct usb_interface *intf,
 	s->vdev.v4l2_dev = &s->v4l2_dev;
 	s->vdev.lock = &s->v4l2_lock;
 
-	ret = video_register_device(&s->vdev, VFL_TYPE_GRABBER, -1);
+	ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1);
 	if (ret < 0) {
 		dev_err(&s->udev->dev,
 				"Failed to register as video device (%d)\n",
-- 
1.8.4.2


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC v3 1/7] v4l: add new tuner types for SDR
  2013-12-16 22:08 ` [PATCH RFC v3 1/7] v4l: add new tuner types for SDR Antti Palosaari
@ 2013-12-17  7:31   ` Hans Verkuil
  0 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-12-17  7:31 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: linux-media, Mauro Carvalho Chehab

On 12/16/2013 11:08 PM, Antti Palosaari wrote:
> Define tuner types V4L2_TUNER_ADC and V4L2_TUNER_RF for SDR usage.
> 
> ADC is used for setting sampling rate (sampling frequency) to SDR
> device.
> 
> Another tuner type, named as V4L2_TUNER_RF, is possible RF tuner.
> Is is used to down-convert RF frequency to range ADC could sample.
> Having RF tuner is optional, whilst in practice it is almost always
> there.
> 
> Also add checks to VIDIOC_G_FREQUENCY, VIDIOC_S_FREQUENCY and
> VIDIOC_ENUM_FREQ_BANDS only allow these two tuner types when device
> type is SDR (VFL_TYPE_SDR). For VIDIOC_G_FREQUENCY we do not check
> tuner type, instead override type with V4L2_TUNER_ADC in every
> case (requested by Hans in order to keep functionality in line with
> existing tuners and existing API does not specify it).
> 
> Prohibit VIDIOC_S_HW_FREQ_SEEK explicitly when device type is SDR,
> as device cannot do hardware seek without a hardware demodulator.
> 
> Cc: Hans Verkuil <hverkuil@xs4all.nl>
> Signed-off-by: Antti Palosaari <crope@iki.fi>
> ---
>  drivers/media/v4l2-core/v4l2-ioctl.c | 39 ++++++++++++++++++++++++++----------
>  include/uapi/linux/videodev2.h       |  2 ++
>  2 files changed, 30 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
> index 68e6b5e..04ec9f9 100644
> --- a/drivers/media/v4l2-core/v4l2-ioctl.c
> +++ b/drivers/media/v4l2-core/v4l2-ioctl.c
> @@ -1288,8 +1288,11 @@ static int v4l_g_frequency(const struct v4l2_ioctl_ops *ops,
>  	struct video_device *vfd = video_devdata(file);
>  	struct v4l2_frequency *p = arg;
>  
> -	p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
> -			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
> +	if (vfd->vfl_type == VFL_TYPE_SDR)
> +		p->type = V4L2_TUNER_ADC;
> +	else
> +		p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
> +				V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
>  	return ops->vidioc_g_frequency(file, fh, p);
>  }
>  
> @@ -1300,10 +1303,15 @@ static int v4l_s_frequency(const struct v4l2_ioctl_ops *ops,
>  	const struct v4l2_frequency *p = arg;
>  	enum v4l2_tuner_type type;
>  
> -	type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
> -			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
> -	if (p->type != type)
> -		return -EINVAL;
> +	if (vfd->vfl_type == VFL_TYPE_SDR) {
> +		if (p->type != V4L2_TUNER_ADC && p->type != V4L2_TUNER_RF)
> +			return -EINVAL;
> +	} else {
> +		type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
> +				V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
> +		if (type != p->type)
> +			return -EINVAL;
> +	}
>  	return ops->vidioc_s_frequency(file, fh, p);
>  }
>  
> @@ -1383,6 +1391,10 @@ static int v4l_s_hw_freq_seek(const struct v4l2_ioctl_ops *ops,
>  	struct v4l2_hw_freq_seek *p = arg;
>  	enum v4l2_tuner_type type;
>  
> +	/* s_hw_freq_seek is not supported for SDR for now */
> +	if (vfd->vfl_type == VFL_TYPE_SDR)
> +		return -EINVAL;
> +
>  	type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
>  		V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
>  	if (p->type != type)
> @@ -1882,11 +1894,16 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops,
>  	enum v4l2_tuner_type type;
>  	int err;
>  
> -	type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
> -			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
> -
> -	if (type != p->type)
> -		return -EINVAL;
> +	if (vfd->vfl_type == VFL_TYPE_SDR) {
> +		if (p->type != V4L2_TUNER_ADC && p->type != V4L2_TUNER_RF)
> +			return -EINVAL;
> +		type = p->type; /* silence compiler warning */

No need for the comment. 'type' is used later, so the compiler warning
makes sense.

After dropping this comment you can add my:

Acked-by: Hans Verkuil <hans.verkuil@cisco.com>

for this patch.

Regards,

	Hans

> +	} else {
> +		type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
> +				V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
> +		if (type != p->type)
> +			return -EINVAL;
> +	}
>  	if (ops->vidioc_enum_freq_bands)
>  		return ops->vidioc_enum_freq_bands(file, fh, p);
>  	if (is_valid_ioctl(vfd, VIDIOC_G_TUNER)) {
> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
> index 437f1b0..3fff116 100644
> --- a/include/uapi/linux/videodev2.h
> +++ b/include/uapi/linux/videodev2.h
> @@ -159,6 +159,8 @@ enum v4l2_tuner_type {
>  	V4L2_TUNER_RADIO	     = 1,
>  	V4L2_TUNER_ANALOG_TV	     = 2,
>  	V4L2_TUNER_DIGITAL_TV	     = 3,
> +	V4L2_TUNER_ADC               = 4,
> +	V4L2_TUNER_RF                = 5,
>  };
>  
>  enum v4l2_memory {
> 


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC v3 2/7] v4l: 1 Hz resolution flag for tuners
  2013-12-16 22:08 ` [PATCH RFC v3 2/7] v4l: 1 Hz resolution flag for tuners Antti Palosaari
@ 2013-12-17  7:31   ` Hans Verkuil
  0 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-12-17  7:31 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: linux-media, Mauro Carvalho Chehab

On 12/16/2013 11:08 PM, Antti Palosaari wrote:
> Add V4L2_TUNER_CAP_1HZ for 1 Hz resolution.
> 
> Cc: Hans Verkuil <hverkuil@xs4all.nl>
> Signed-off-by: Antti Palosaari <crope@iki.fi>
> ---
>  include/uapi/linux/videodev2.h | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
> index 3fff116..97a5e50 100644
> --- a/include/uapi/linux/videodev2.h
> +++ b/include/uapi/linux/videodev2.h
> @@ -1341,6 +1341,7 @@ struct v4l2_modulator {
>  #define V4L2_TUNER_CAP_RDS_CONTROLS	0x0200
>  #define V4L2_TUNER_CAP_FREQ_BANDS	0x0400
>  #define V4L2_TUNER_CAP_HWSEEK_PROG_LIM	0x0800
> +#define V4L2_TUNER_CAP_1HZ		0x1000
>  
>  /*  Flags for the 'rxsubchans' field */
>  #define V4L2_TUNER_SUB_MONO		0x0001
> 

Acked-by: Hans Verkuil <hans.verkuil@cisco.com>

Regards,

	Hans

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC v3 3/7] v4l: add stream format for SDR receiver
  2013-12-16 22:08 ` [PATCH RFC v3 3/7] v4l: add stream format for SDR receiver Antti Palosaari
@ 2013-12-17  7:32   ` Hans Verkuil
  0 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-12-17  7:32 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: linux-media, Mauro Carvalho Chehab

On 12/16/2013 11:08 PM, Antti Palosaari wrote:
> Add new V4L2 stream format definition, V4L2_BUF_TYPE_SDR_CAPTURE,
> for SDR receiver.
> 
> Cc: Hans Verkuil <hverkuil@xs4all.nl>
> Signed-off-by: Antti Palosaari <crope@iki.fi>
> ---
>  drivers/media/v4l2-core/v4l2-ioctl.c |  1 +
>  include/trace/events/v4l2.h          |  1 +
>  include/uapi/linux/videodev2.h       | 11 +++++++++++
>  3 files changed, 13 insertions(+)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
> index 04ec9f9..da197e1 100644
> --- a/drivers/media/v4l2-core/v4l2-ioctl.c
> +++ b/drivers/media/v4l2-core/v4l2-ioctl.c
> @@ -149,6 +149,7 @@ const char *v4l2_type_names[] = {
>  	[V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "vid-out-overlay",
>  	[V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE] = "vid-cap-mplane",
>  	[V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE] = "vid-out-mplane",
> +	[V4L2_BUF_TYPE_SDR_CAPTURE]        = "sdr-cap",
>  };
>  EXPORT_SYMBOL(v4l2_type_names);
>  
> diff --git a/include/trace/events/v4l2.h b/include/trace/events/v4l2.h
> index ef94eca..b9bb1f2 100644
> --- a/include/trace/events/v4l2.h
> +++ b/include/trace/events/v4l2.h
> @@ -18,6 +18,7 @@
>  		{ V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY, "VIDEO_OUTPUT_OVERLAY" },\
>  		{ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, "VIDEO_CAPTURE_MPLANE" },\
>  		{ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,  "VIDEO_OUTPUT_MPLANE" }, \
> +		{ V4L2_BUF_TYPE_SDR_CAPTURE,          "SDR_CAPTURE" },         \
>  		{ V4L2_BUF_TYPE_PRIVATE,	      "PRIVATE" })
>  
>  #define show_field(field)						\
> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
> index 97a5e50..c50e449 100644
> --- a/include/uapi/linux/videodev2.h
> +++ b/include/uapi/linux/videodev2.h
> @@ -139,6 +139,7 @@ enum v4l2_buf_type {
>  #endif
>  	V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = 9,
>  	V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE  = 10,
> +	V4L2_BUF_TYPE_SDR_CAPTURE          = 11,
>  	/* Deprecated, do not use */
>  	V4L2_BUF_TYPE_PRIVATE              = 0x80,
>  };
> @@ -1695,6 +1696,15 @@ struct v4l2_pix_format_mplane {
>  } __attribute__ ((packed));
>  
>  /**
> + * struct v4l2_format_sdr - SDR format definition
> + * @pixelformat:	little endian four character code (fourcc)
> + */
> +struct v4l2_format_sdr {
> +	__u32				pixelformat;
> +	__u8				reserved[28];
> +} __attribute__ ((packed));
> +
> +/**
>   * struct v4l2_format - stream data format
>   * @type:	enum v4l2_buf_type; type of the data stream
>   * @pix:	definition of an image format
> @@ -1712,6 +1722,7 @@ struct v4l2_format {
>  		struct v4l2_window		win;     /* V4L2_BUF_TYPE_VIDEO_OVERLAY */
>  		struct v4l2_vbi_format		vbi;     /* V4L2_BUF_TYPE_VBI_CAPTURE */
>  		struct v4l2_sliced_vbi_format	sliced;  /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
> +		struct v4l2_format_sdr		sdr;     /* V4L2_BUF_TYPE_SDR_CAPTURE */
>  		__u8	raw_data[200];                   /* user-defined */
>  	} fmt;
>  };
> 

Acked-by: Hans Verkuil <hans.verkuil@cisco.com>

Regards,

	Hans

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC v3 4/7] v4l: define own IOCTL ops for SDR FMT
  2013-12-16 22:08 ` [PATCH RFC v3 4/7] v4l: define own IOCTL ops for SDR FMT Antti Palosaari
@ 2013-12-17  7:32   ` Hans Verkuil
  0 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-12-17  7:32 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: linux-media, Mauro Carvalho Chehab

On 12/16/2013 11:08 PM, Antti Palosaari wrote:
> Use own format ops for SDR data:
> vidioc_enum_fmt_sdr_cap
> vidioc_g_fmt_sdr_cap
> vidioc_s_fmt_sdr_cap
> vidioc_try_fmt_sdr_cap
> 
> Cc: Hans Verkuil <hverkuil@xs4all.nl>
> Signed-off-by: Antti Palosaari <crope@iki.fi>
> ---
>  include/media/v4l2-ioctl.h | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
> index e0b74a4..8be32f5 100644
> --- a/include/media/v4l2-ioctl.h
> +++ b/include/media/v4l2-ioctl.h
> @@ -40,6 +40,8 @@ struct v4l2_ioctl_ops {
>  					      struct v4l2_fmtdesc *f);
>  	int (*vidioc_enum_fmt_vid_out_mplane)(struct file *file, void *fh,
>  					      struct v4l2_fmtdesc *f);
> +	int (*vidioc_enum_fmt_sdr_cap)     (struct file *file, void *fh,
> +					    struct v4l2_fmtdesc *f);
>  
>  	/* VIDIOC_G_FMT handlers */
>  	int (*vidioc_g_fmt_vid_cap)    (struct file *file, void *fh,
> @@ -62,6 +64,8 @@ struct v4l2_ioctl_ops {
>  					   struct v4l2_format *f);
>  	int (*vidioc_g_fmt_vid_out_mplane)(struct file *file, void *fh,
>  					   struct v4l2_format *f);
> +	int (*vidioc_g_fmt_sdr_cap)    (struct file *file, void *fh,
> +					struct v4l2_format *f);
>  
>  	/* VIDIOC_S_FMT handlers */
>  	int (*vidioc_s_fmt_vid_cap)    (struct file *file, void *fh,
> @@ -84,6 +88,8 @@ struct v4l2_ioctl_ops {
>  					   struct v4l2_format *f);
>  	int (*vidioc_s_fmt_vid_out_mplane)(struct file *file, void *fh,
>  					   struct v4l2_format *f);
> +	int (*vidioc_s_fmt_sdr_cap)    (struct file *file, void *fh,
> +					struct v4l2_format *f);
>  
>  	/* VIDIOC_TRY_FMT handlers */
>  	int (*vidioc_try_fmt_vid_cap)    (struct file *file, void *fh,
> @@ -106,6 +112,8 @@ struct v4l2_ioctl_ops {
>  					     struct v4l2_format *f);
>  	int (*vidioc_try_fmt_vid_out_mplane)(struct file *file, void *fh,
>  					     struct v4l2_format *f);
> +	int (*vidioc_try_fmt_sdr_cap)    (struct file *file, void *fh,
> +					  struct v4l2_format *f);
>  
>  	/* Buffer handlers */
>  	int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b);
> 

Acked-by: Hans Verkuil <hans.verkuil@cisco.com>

Regards,

	Hans

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC v3 5/7] v4l: enable some IOCTLs for SDR receiver
  2013-12-16 22:08 ` [PATCH RFC v3 5/7] v4l: enable some IOCTLs for SDR receiver Antti Palosaari
@ 2013-12-17  7:34   ` Hans Verkuil
  2013-12-17 16:40     ` Antti Palosaari
  0 siblings, 1 reply; 23+ messages in thread
From: Hans Verkuil @ 2013-12-17  7:34 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: linux-media, Mauro Carvalho Chehab

On 12/16/2013 11:08 PM, Antti Palosaari wrote:
> Enable stream format (FMT) IOCTLs for SDR use. These are used for negotiate
> used data stream format.
> 
> Enable input IOCTLs, VIDIOC_ENUMINPUT, VIDIOC_G_INPUT, VIDIOC_S_INPUT.
> These are used to select possible antenna connector.
> 
> Reorganise some some IOCTL selection logic.
> 
> Cc: Hans Verkuil <hverkuil@xs4all.nl>
> Signed-off-by: Antti Palosaari <crope@iki.fi>
> ---
>  drivers/media/v4l2-core/v4l2-dev.c   | 27 ++++++++++++++++++++++++---
>  drivers/media/v4l2-core/v4l2-ioctl.c | 35 +++++++++++++++++++++++++++++++++++
>  2 files changed, 59 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
> index 6a1e6a8..5795e8d 100644
> --- a/drivers/media/v4l2-core/v4l2-dev.c
> +++ b/drivers/media/v4l2-core/v4l2-dev.c
> @@ -562,7 +562,7 @@ static void determine_valid_ioctls(struct video_device *vdev)
>  	const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
>  	bool is_vid = vdev->vfl_type == VFL_TYPE_GRABBER;
>  	bool is_vbi = vdev->vfl_type == VFL_TYPE_VBI;
> -	bool is_radio = vdev->vfl_type == VFL_TYPE_RADIO;
> +	bool is_sdr = vdev->vfl_type == VFL_TYPE_SDR;
>  	bool is_rx = vdev->vfl_dir != VFL_DIR_TX;
>  	bool is_tx = vdev->vfl_dir != VFL_DIR_RX;
>  
> @@ -671,9 +671,26 @@ static void determine_valid_ioctls(struct video_device *vdev)
>  			       ops->vidioc_try_fmt_sliced_vbi_out)))
>  			set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls);
>  		SET_VALID_IOCTL(ops, VIDIOC_G_SLICED_VBI_CAP, vidioc_g_sliced_vbi_cap);
> +	} else if (is_sdr) {
> +		/* SDR specific ioctls */
> +		if (ops->vidioc_enum_fmt_sdr_cap)
> +			set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls);
> +		if (ops->vidioc_g_fmt_sdr_cap)
> +			set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls);
> +		if (ops->vidioc_s_fmt_sdr_cap)
> +			set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls);
> +		if (ops->vidioc_try_fmt_sdr_cap)
> +			set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls);
> +
> +		if (is_rx) {
> +			SET_VALID_IOCTL(ops, VIDIOC_ENUMINPUT, vidioc_enum_input);
> +			SET_VALID_IOCTL(ops, VIDIOC_G_INPUT, vidioc_g_input);
> +			SET_VALID_IOCTL(ops, VIDIOC_S_INPUT, vidioc_s_input);

Why would you want to enable these? Normal radio devices should never use
these, so why would sdr devices?

Regards,

	Hans

> +		}
>  	}
> -	if (!is_radio) {
> -		/* ioctls valid for video or vbi */
> +
> +	if (is_vid || is_vbi || is_sdr) {
> +		/* ioctls valid for video, vbi or sdr */
>  		SET_VALID_IOCTL(ops, VIDIOC_REQBUFS, vidioc_reqbufs);
>  		SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_querybuf);
>  		SET_VALID_IOCTL(ops, VIDIOC_QBUF, vidioc_qbuf);
> @@ -681,6 +698,10 @@ static void determine_valid_ioctls(struct video_device *vdev)
>  		SET_VALID_IOCTL(ops, VIDIOC_DQBUF, vidioc_dqbuf);
>  		SET_VALID_IOCTL(ops, VIDIOC_CREATE_BUFS, vidioc_create_bufs);
>  		SET_VALID_IOCTL(ops, VIDIOC_PREPARE_BUF, vidioc_prepare_buf);
> +	}
> +
> +	if (is_vid || is_vbi) {
> +		/* ioctls valid for video or vbi */
>  		if (ops->vidioc_s_std)
>  			set_bit(_IOC_NR(VIDIOC_ENUMSTD), valid_ioctls);
>  		SET_VALID_IOCTL(ops, VIDIOC_S_STD, vidioc_s_std);
> diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
> index da197e1..d0777bd 100644
> --- a/drivers/media/v4l2-core/v4l2-ioctl.c
> +++ b/drivers/media/v4l2-core/v4l2-ioctl.c
> @@ -243,6 +243,7 @@ static void v4l_print_format(const void *arg, bool write_only)
>  	const struct v4l2_vbi_format *vbi;
>  	const struct v4l2_sliced_vbi_format *sliced;
>  	const struct v4l2_window *win;
> +	const struct v4l2_format_sdr *sdr;
>  	unsigned i;
>  
>  	pr_cont("type=%s", prt_names(p->type, v4l2_type_names));
> @@ -316,6 +317,14 @@ static void v4l_print_format(const void *arg, bool write_only)
>  				sliced->service_lines[0][i],
>  				sliced->service_lines[1][i]);
>  		break;
> +	case V4L2_BUF_TYPE_SDR_CAPTURE:
> +		sdr = &p->fmt.sdr;
> +		pr_cont(", pixelformat=%c%c%c%c\n",
> +			(sdr->pixelformat >>  0) & 0xff,
> +			(sdr->pixelformat >>  8) & 0xff,
> +			(sdr->pixelformat >> 16) & 0xff,
> +			(sdr->pixelformat >> 24) & 0xff);
> +		break;
>  	}
>  }
>  
> @@ -879,6 +888,7 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type)
>  	const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
>  	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
>  	bool is_vbi = vfd->vfl_type == VFL_TYPE_VBI;
> +	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
>  	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
>  	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
>  
> @@ -928,6 +938,10 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type)
>  		if (is_vbi && is_tx && ops->vidioc_g_fmt_sliced_vbi_out)
>  			return 0;
>  		break;
> +	case V4L2_BUF_TYPE_SDR_CAPTURE:
> +		if (is_sdr && is_rx && ops->vidioc_g_fmt_sdr_cap)
> +			return 0;
> +		break;
>  	default:
>  		break;
>  	}
> @@ -1047,6 +1061,10 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops,
>  		if (unlikely(!is_tx || !ops->vidioc_enum_fmt_vid_out_mplane))
>  			break;
>  		return ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg);
> +	case V4L2_BUF_TYPE_SDR_CAPTURE:
> +		if (unlikely(!is_rx || !ops->vidioc_enum_fmt_sdr_cap))
> +			break;
> +		return ops->vidioc_enum_fmt_sdr_cap(file, fh, arg);
>  	}
>  	return -EINVAL;
>  }
> @@ -1057,6 +1075,7 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
>  	struct v4l2_format *p = arg;
>  	struct video_device *vfd = video_devdata(file);
>  	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
> +	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
>  	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
>  	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
>  
> @@ -1101,6 +1120,10 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
>  		if (unlikely(!is_tx || is_vid || !ops->vidioc_g_fmt_sliced_vbi_out))
>  			break;
>  		return ops->vidioc_g_fmt_sliced_vbi_out(file, fh, arg);
> +	case V4L2_BUF_TYPE_SDR_CAPTURE:
> +		if (unlikely(!is_rx || !is_sdr || !ops->vidioc_g_fmt_sdr_cap))
> +			break;
> +		return ops->vidioc_g_fmt_sdr_cap(file, fh, arg);
>  	}
>  	return -EINVAL;
>  }
> @@ -1111,6 +1134,7 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
>  	struct v4l2_format *p = arg;
>  	struct video_device *vfd = video_devdata(file);
>  	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
> +	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
>  	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
>  	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
>  
> @@ -1165,6 +1189,11 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
>  			break;
>  		CLEAR_AFTER_FIELD(p, fmt.sliced);
>  		return ops->vidioc_s_fmt_sliced_vbi_out(file, fh, arg);
> +	case V4L2_BUF_TYPE_SDR_CAPTURE:
> +		if (unlikely(!is_rx || !is_sdr || !ops->vidioc_s_fmt_sdr_cap))
> +			break;
> +		CLEAR_AFTER_FIELD(p, fmt.sdr);
> +		return ops->vidioc_s_fmt_sdr_cap(file, fh, arg);
>  	}
>  	return -EINVAL;
>  }
> @@ -1175,6 +1204,7 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
>  	struct v4l2_format *p = arg;
>  	struct video_device *vfd = video_devdata(file);
>  	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
> +	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
>  	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
>  	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
>  
> @@ -1229,6 +1259,11 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
>  			break;
>  		CLEAR_AFTER_FIELD(p, fmt.sliced);
>  		return ops->vidioc_try_fmt_sliced_vbi_out(file, fh, arg);
> +	case V4L2_BUF_TYPE_SDR_CAPTURE:
> +		if (unlikely(!is_rx || !is_sdr || !ops->vidioc_try_fmt_sdr_cap))
> +			break;
> +		CLEAR_AFTER_FIELD(p, fmt.sdr);
> +		return ops->vidioc_try_fmt_sdr_cap(file, fh, arg);
>  	}
>  	return -EINVAL;
>  }
> 


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC v3 0/7] SDR API
  2013-12-16 22:08 [PATCH RFC v3 0/7] SDR API Antti Palosaari
                   ` (6 preceding siblings ...)
  2013-12-16 22:08 ` [PATCH RFC v3 7/7] msi3101: " Antti Palosaari
@ 2013-12-17  7:36 ` Hans Verkuil
  2013-12-17 16:46   ` Antti Palosaari
  7 siblings, 1 reply; 23+ messages in thread
From: Hans Verkuil @ 2013-12-17  7:36 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: linux-media, Mauro Carvalho Chehab

On 12/16/2013 11:08 PM, Antti Palosaari wrote:
> Now with some changes done requested by Hans.
> I did not agree	very well that VIDIOC_G_FREQUENCY tuner type check
> exception, but here it is...
> 
> Also two patches, as example, conversion of msi3101 and rtl2832_sdr
> drivers to that API.
> 
> regards
> Antti
> 
> Antti Palosaari (7):
>   v4l: add new tuner types for SDR
>   v4l: 1 Hz resolution flag for tuners
>   v4l: add stream format for SDR receiver
>   v4l: define own IOCTL ops for SDR FMT
>   v4l: enable some IOCTLs for SDR receiver

Is it just too early in the day or is the patch adding VFL_TYPE_SDR and
the swradio device missing in this patch series?

Regards,

	Hans

>   rtl2832_sdr: convert to SDR API
>   msi3101: convert to SDR API
> 
>  drivers/media/v4l2-core/v4l2-dev.c               |  27 ++-
>  drivers/media/v4l2-core/v4l2-ioctl.c             |  75 +++++-
>  drivers/staging/media/msi3101/sdr-msi3101.c      | 204 +++++++++++-----
>  drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 291 ++++++++++++++++++-----
>  include/media/v4l2-ioctl.h                       |   8 +
>  include/trace/events/v4l2.h                      |   1 +
>  include/uapi/linux/videodev2.h                   |  14 ++
>  7 files changed, 486 insertions(+), 134 deletions(-)
> 


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC v3 6/7] rtl2832_sdr: convert to SDR API
  2013-12-16 22:08 ` [PATCH RFC v3 6/7] rtl2832_sdr: convert to SDR API Antti Palosaari
@ 2013-12-17  7:45   ` Hans Verkuil
  2013-12-19  9:21   ` Hans Verkuil
  1 sibling, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-12-17  7:45 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: linux-media, Mauro Carvalho Chehab

On 12/16/2013 11:08 PM, Antti Palosaari wrote:
> It was abusing video device API. Use SDR API instead.
> 
> Signed-off-by: Antti Palosaari <crope@iki.fi>
> ---
>  drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 291 ++++++++++++++++++-----
>  1 file changed, 227 insertions(+), 64 deletions(-)
> 
> diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
> index 4b8c016..f0965ea 100644
> --- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
> +++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
> @@ -20,12 +20,6 @@
>   * GNU Radio plugin "gr-kernel" for device usage will be on:
>   * http://git.linuxtv.org/anttip/gr-kernel.git
>   *
> - * TODO:
> - * Help is very highly welcome for these + all the others you could imagine:
> - * - move controls to V4L2 API
> - * - use libv4l2 for stream format conversions
> - * - gr-kernel: switch to v4l2_mmap (current read eats a lot of cpu)
> - * - SDRSharp support
>   */
>  
>  #include "dvb_frontend.h"
> @@ -38,6 +32,7 @@
>  #include <media/v4l2-event.h>
>  #include <media/videobuf2-vmalloc.h>
>  
> +#include <linux/jiffies.h>
>  #include <linux/math64.h>
>  
>  /* TODO: These should be moved to V4L2 API */
> @@ -49,11 +44,68 @@
>  #define RTL2832_SDR_CID_TUNER_IF            ((V4L2_CID_USER_BASE | 0xf000) + 12)
>  #define RTL2832_SDR_CID_TUNER_GAIN          ((V4L2_CID_USER_BASE | 0xf000) + 13)
>  
> -#define V4L2_PIX_FMT_SDR_U8     v4l2_fourcc('D', 'U', '0', '8') /* unsigned 8-bit */
> +#define V4L2_PIX_FMT_SDR_U8    v4l2_fourcc('D', 'U', '0', '8')
> +#define V4L2_PIX_FMT_SDR_U16LE v4l2_fourcc('D', 'U', '1', '6')
>  
>  #define MAX_BULK_BUFS            (10)
>  #define BULK_BUFFER_SIZE         (128 * 512)
>  
> +static const struct v4l2_frequency_band bands_adc[] = {
> +	{
> +		.tuner = 0,
> +		.type = V4L2_TUNER_ADC,
> +		.index = 0,
> +		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
> +		.rangelow   =  300000,
> +		.rangehigh  =  300000,
> +	},
> +	{
> +		.tuner = 0,
> +		.type = V4L2_TUNER_ADC,
> +		.index = 1,
> +		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
> +		.rangelow   =  900001,
> +		.rangehigh  = 2800000,
> +	},
> +	{
> +		.tuner = 0,
> +		.type = V4L2_TUNER_ADC,
> +		.index = 2,
> +		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
> +		.rangelow   = 3200000,
> +		.rangehigh  = 3200000,
> +	},
> +};
> +
> +static const struct v4l2_frequency_band bands_fm[] = {
> +	{
> +		.tuner = 1,
> +		.type = V4L2_TUNER_RF,
> +		.index = 0,
> +		.capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS,
> +		.rangelow   =    50000000 / 62.5,
> +		.rangehigh  =  2000000000 / 62.5,
> +	},
> +};
> +
> +/* stream formats */
> +struct rtl2832_sdr_format {
> +	char	*name;
> +	u32	pixelformat;
> +};
> +
> +static struct rtl2832_sdr_format formats[] = {
> +	{
> +		.name		= "I/Q 8-bit unsigned",
> +		.pixelformat	= V4L2_PIX_FMT_SDR_U8,
> +	}, {
> +		.name		= "I/Q 16-bit unsigned little endian",
> +		.pixelformat	= V4L2_PIX_FMT_SDR_U16LE,
> +	},
> +};
> +
> +static const int NUM_FORMATS = sizeof(formats) / sizeof(struct rtl2832_sdr_format);
> +
>  /* intermediate buffers with raw data from the USB device */
>  struct rtl2832_sdr_frame_buf {
>  	struct vb2_buffer vb;   /* common v4l buffer stuff -- must be first */
> @@ -96,6 +148,9 @@ struct rtl2832_sdr_state {
>  	int urbs_initialized;
>  	int urbs_submitted;
>  
> +	unsigned int f_adc, f_tuner;
> +	u32 pixelformat;
> +
>  	/* Controls */
>  	struct v4l2_ctrl_handler ctrl_handler;
>  	struct v4l2_ctrl *ctrl_sampling_rate;
> @@ -107,7 +162,7 @@ struct rtl2832_sdr_state {
>  	/* for sample rate calc */
>  	unsigned int sample;
>  	unsigned int sample_measured;
> -	unsigned long jiffies;
> +	unsigned long jiffies_next;
>  };
>  
>  /* write multiple hardware registers */
> @@ -292,27 +347,41 @@ leave:
>  }
>  
>  static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s,
> -		u8 *dst, const u8 *src, unsigned int src_len)
> +		void *dst, const u8 *src, unsigned int src_len)
>  {
> -	memcpy(dst, src, src_len);
> +	unsigned int dst_len;
> +
> +	if (s->pixelformat == V4L2_PIX_FMT_SDR_U8) {
> +		/* native stream, no need to convert */
> +		memcpy(dst, src, src_len);
> +		dst_len = src_len;
> +	} else if (s->pixelformat == V4L2_PIX_FMT_SDR_U16LE) {
> +		/* convert u8 to u16 */
> +		unsigned int i;
> +		u16 *u16dst = dst;
> +		for (i = 0; i < src_len; i++)
> +			*u16dst++ = (src[i] << 8) | (src[i] >> 0);
> +		dst_len = 2 * src_len;
> +	} else {
> +		dst_len = 0;
> +	}
>  
>  	/* calculate samping rate and output it in 10 seconds intervals */
> -	if ((s->jiffies + msecs_to_jiffies(10000)) <= jiffies) {
> -		unsigned long jiffies_now = jiffies;
> -		unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies);
> +	if (unlikely(time_is_before_jiffies(s->jiffies_next))) {
> +#define MSECS 10000UL
>  		unsigned int samples = s->sample - s->sample_measured;
> -		s->jiffies = jiffies_now;
> +		s->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
>  		s->sample_measured = s->sample;
>  		dev_dbg(&s->udev->dev,
>  				"slen=%d samples=%u msecs=%lu sampling rate=%lu\n",
> -				src_len, samples, msecs,
> -				samples * 1000UL / msecs);
> +				src_len, samples, MSECS,
> +				samples * 1000UL / MSECS);
>  	}
>  
>  	/* total number of I+Q pairs */
>  	s->sample += src_len / 2;
>  
> -	return src_len;
> +	return dst_len;
>  }
>  
>  /*
> @@ -343,12 +412,12 @@ static void rtl2832_sdr_urb_complete(struct urb *urb)
>  		break;
>  	}
>  
> -	if (urb->actual_length > 0) {
> +	if (likely(urb->actual_length > 0)) {
>  		void *ptr;
>  		unsigned int len;
>  		/* get free framebuffer */
>  		fbuf = rtl2832_sdr_get_next_fill_buf(s);
> -		if (fbuf == NULL) {
> +		if (unlikely(fbuf == NULL)) {
>  			s->vb_full++;
>  			dev_notice_ratelimited(&s->udev->dev,
>  					"videobuf is full, %d packets dropped\n",
> @@ -544,7 +613,7 @@ static int rtl2832_sdr_querycap(struct file *file, void *fh,
>  	strlcpy(cap->card, s->vdev.name, sizeof(cap->card));
>  	usb_make_path(s->udev, cap->bus_info, sizeof(cap->bus_info));
>  	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
> -			V4L2_CAP_READWRITE;
> +			V4L2_CAP_READWRITE | V4L2_CAP_TUNER;

Shouldn't we have a V4L2_CAP_SDR_CAPTURE? I think that would make a lot of sense.

>  	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
>  	return 0;
>  }
> @@ -560,7 +629,8 @@ static int rtl2832_sdr_queue_setup(struct vb2_queue *vq,
>  	/* Absolute min and max number of buffers available for mmap() */
>  	*nbuffers = 32;
>  	*nplanes = 1;
> -	sizes[0] = PAGE_ALIGN(BULK_BUFFER_SIZE * 4); /* 8 * 512 * 4 = 16384 */
> +	/* 2 = max 16-bit sample returned */
> +	sizes[0] = PAGE_ALIGN(BULK_BUFFER_SIZE * 2);
>  	dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n",
>  			__func__, *nbuffers, sizes[0]);
>  	return 0;
> @@ -913,13 +983,14 @@ static struct vb2_ops rtl2832_sdr_vb2_ops = {
>  	.wait_finish            = vb2_ops_wait_finish,
>  };
>  
> -static int rtl2832_sdr_enum_input(struct file *file, void *fh, struct v4l2_input *i)
> +static int rtl2832_sdr_enum_input(struct file *file, void *fh,
> +		struct v4l2_input *i)
>  {
> -	if (i->index != 0)
> +	if (i->index > 0)
>  		return -EINVAL;
>  
> -	strlcpy(i->name, "SDR data", sizeof(i->name));
> -	i->type = V4L2_INPUT_TYPE_CAMERA;
> +	strlcpy(i->name, "Antenna #0", sizeof(i->name));
> +	i->type = V4L2_INPUT_TYPE_TUNER;
>  
>  	return 0;
>  }
> @@ -933,10 +1004,39 @@ static int rtl2832_sdr_g_input(struct file *file, void *fh, unsigned int *i)
>  
>  static int rtl2832_sdr_s_input(struct file *file, void *fh, unsigned int i)
>  {
> -	return i ? -EINVAL : 0;
> +	if (i > 0)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static int rtl2832_sdr_g_tuner(struct file *file, void *priv,
> +		struct v4l2_tuner *v)
> +{
> +	struct rtl2832_sdr_state *s = video_drvdata(file);
> +	dev_dbg(&s->udev->dev, "%s: index=%d type=%d\n",
> +			__func__, v->index, v->type);
> +
> +	if (v->index == 0) {
> +		strlcpy(v->name, "ADC: Realtek RTL2832", sizeof(v->name));
> +		v->type = V4L2_TUNER_ADC;
> +		v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
> +		v->rangelow =   300000;
> +		v->rangehigh = 3200000;
> +	} else if (v->index == 1) {
> +		strlcpy(v->name, "RF: <unknown>", sizeof(v->name));
> +		v->type = V4L2_TUNER_RF;
> +		v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS;
> +		v->rangelow =    50000000 / 62.5;
> +		v->rangehigh = 2000000000 / 62.5;
> +	} else {
> +		return -EINVAL;
> +	}
> +
> +	return 0;
>  }
>  
> -static int vidioc_s_tuner(struct file *file, void *priv,
> +static int rtl2832_sdr_s_tuner(struct file *file, void *priv,
>  		const struct v4l2_tuner *v)
>  {
>  	struct rtl2832_sdr_state *s = video_drvdata(file);
> @@ -945,91 +1045,149 @@ static int vidioc_s_tuner(struct file *file, void *priv,
>  	return 0;
>  }
>  
> -static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
> +static int rtl2832_sdr_enum_freq_bands(struct file *file, void *priv,
> +		struct v4l2_frequency_band *band)
>  {
>  	struct rtl2832_sdr_state *s = video_drvdata(file);
> -	dev_dbg(&s->udev->dev, "%s:\n", __func__);
> +	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d index=%d\n",
> +			__func__, band->tuner, band->type, band->index);
> +
> +	if (band->tuner == 0) {
> +		if (band->index >= ARRAY_SIZE(bands_adc))
> +			return -EINVAL;
>  
> -	strcpy(v->name, "SDR RX");
> -	v->capability = V4L2_TUNER_CAP_LOW;
> +		*band = bands_adc[band->index];
> +	} else if (band->tuner == 1) {
> +		if (band->index >= ARRAY_SIZE(bands_fm))
> +			return -EINVAL;
> +
> +		*band = bands_fm[band->index];
> +	} else {
> +		return -EINVAL;
> +	}
>  
>  	return 0;
>  }
>  
> -static int vidioc_s_frequency(struct file *file, void *priv,
> +static int rtl2832_sdr_g_frequency(struct file *file, void *priv,
> +		struct v4l2_frequency *f)
> +{
> +	struct rtl2832_sdr_state *s = video_drvdata(file);
> +	int ret  = 0;
> +	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n",
> +			__func__, f->tuner, f->type);
> +
> +	if (f->tuner == 0)
> +		f->frequency = s->f_adc;
> +	else if (f->tuner == 1)
> +		f->frequency = s->f_tuner;
> +	else
> +		return -EINVAL;
> +
> +	return ret;
> +}
> +
> +static int rtl2832_sdr_s_frequency(struct file *file, void *priv,
>  		const struct v4l2_frequency *f)
>  {
>  	struct rtl2832_sdr_state *s = video_drvdata(file);
> -	dev_dbg(&s->udev->dev, "%s: frequency=%lu Hz (%u)\n",
> -			__func__, f->frequency * 625UL / 10UL, f->frequency);
> +	int ret;
> +	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n",
> +			__func__, f->tuner, f->type, f->frequency);
> +
> +	if (f->tuner == 0) {
> +		dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n",
> +				__func__, f->frequency);
> +		s->f_adc = f->frequency;
> +		ret = v4l2_ctrl_s_ctrl_int64(s->ctrl_sampling_rate,
> +				f->frequency);
> +	} else if (f->tuner == 1) {
> +		dev_dbg(&s->udev->dev, "%s: RF frequency=%lu Hz\n",
> +				__func__, f->frequency * 625UL / 10UL);
> +		s->f_tuner = f->frequency;
> +		ret = v4l2_ctrl_s_ctrl_int64(s->ctrl_tuner_rf,
> +				f->frequency * 625UL / 10UL);
> +	} else {
> +		return -EINVAL;
> +	}
>  
> -	return v4l2_ctrl_s_ctrl_int64(s->ctrl_tuner_rf,
> -			f->frequency * 625UL / 10UL);
> +	return ret;
>  }
>  
> -static int rtl2832_sdr_enum_fmt_vid_cap(struct file *file, void *priv,
> +static int rtl2832_sdr_enum_fmt_sdr_cap(struct file *file, void *priv,
>  		struct v4l2_fmtdesc *f)
>  {
>  	struct rtl2832_sdr_state *s = video_drvdata(file);
>  	dev_dbg(&s->udev->dev, "%s:\n", __func__);
>  
> -	if (f->index > 0)
> +	if (f->index >= NUM_FORMATS)
>  		return -EINVAL;
>  
> -	f->flags = 0;
> -	strcpy(f->description, "I/Q 8-bit unsigned");
> -	f->pixelformat = V4L2_PIX_FMT_SDR_U8;
> +	strlcpy(f->description, formats[f->index].name, sizeof(f->description));
> +	f->pixelformat = formats[f->index].pixelformat;
>  
>  	return 0;
>  }
>  
> -static int rtl2832_sdr_g_fmt_vid_cap(struct file *file, void *priv,
> +static int rtl2832_sdr_g_fmt_sdr_cap(struct file *file, void *priv,
>  		struct v4l2_format *f)
>  {
>  	struct rtl2832_sdr_state *s = video_drvdata(file);
>  	dev_dbg(&s->udev->dev, "%s:\n", __func__);
>  
> -	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
> +	if (f->type != V4L2_BUF_TYPE_SDR_CAPTURE)
>  		return -EINVAL;

No need anymore for this test. The core tests that already. Ditto for the
other s/try functions.

>  
> -	memset(&f->fmt.pix, 0, sizeof(f->fmt.pix));
> -	f->fmt.pix.pixelformat = V4L2_PIX_FMT_SDR_U8;
> +	f->fmt.sdr.pixelformat = s->pixelformat;
>  
>  	return 0;
>  }
>  
> -static int rtl2832_sdr_s_fmt_vid_cap(struct file *file, void *priv,
> +static int rtl2832_sdr_s_fmt_sdr_cap(struct file *file, void *priv,
>  		struct v4l2_format *f)
>  {
>  	struct rtl2832_sdr_state *s = video_drvdata(file);
>  	struct vb2_queue *q = &s->vb_queue;
> +	int i;
>  	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
> -			(char *)&f->fmt.pix.pixelformat);
> +			(char *)&f->fmt.sdr.pixelformat);
>  
> -	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
> +	if (f->type != V4L2_BUF_TYPE_SDR_CAPTURE)
>  		return -EINVAL;
>  
>  	if (vb2_is_busy(q))
>  		return -EBUSY;
>  
> -	memset(&f->fmt.pix, 0, sizeof(f->fmt.pix));
> -	f->fmt.pix.pixelformat = V4L2_PIX_FMT_SDR_U8;
> +	for (i = 0; i < NUM_FORMATS; i++) {
> +		if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
> +			s->pixelformat = f->fmt.sdr.pixelformat;
> +			return 0;
> +		}
> +	}
> +
> +	f->fmt.sdr.pixelformat = formats[0].pixelformat;
> +	s->pixelformat = formats[0].pixelformat;
>  
>  	return 0;
>  }
>  
> -static int rtl2832_sdr_try_fmt_vid_cap(struct file *file, void *priv,
> +static int rtl2832_sdr_try_fmt_sdr_cap(struct file *file, void *priv,
>  		struct v4l2_format *f)
>  {
>  	struct rtl2832_sdr_state *s = video_drvdata(file);
> +	int i;
>  	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
> -			(char *)&f->fmt.pix.pixelformat);
> +			(char *)&f->fmt.sdr.pixelformat);
>  
> -	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
> +	if (f->type != V4L2_BUF_TYPE_SDR_CAPTURE)
>  		return -EINVAL;
>  
> -	memset(&f->fmt.pix, 0, sizeof(f->fmt.pix));
> -	f->fmt.pix.pixelformat = V4L2_PIX_FMT_SDR_U8;
> +	for (i = 0; i < NUM_FORMATS; i++) {
> +		if (formats[i].pixelformat == f->fmt.sdr.pixelformat)
> +			return 0;
> +	}
> +
> +	f->fmt.sdr.pixelformat = formats[0].pixelformat;
>  
>  	return 0;
>  }
> @@ -1037,10 +1195,10 @@ static int rtl2832_sdr_try_fmt_vid_cap(struct file *file, void *priv,
>  static const struct v4l2_ioctl_ops rtl2832_sdr_ioctl_ops = {
>  	.vidioc_querycap          = rtl2832_sdr_querycap,
>  
> -	.vidioc_enum_fmt_vid_cap  = rtl2832_sdr_enum_fmt_vid_cap,
> -	.vidioc_g_fmt_vid_cap     = rtl2832_sdr_g_fmt_vid_cap,
> -	.vidioc_s_fmt_vid_cap     = rtl2832_sdr_s_fmt_vid_cap,
> -	.vidioc_try_fmt_vid_cap   = rtl2832_sdr_try_fmt_vid_cap,
> +	.vidioc_enum_fmt_sdr_cap  = rtl2832_sdr_enum_fmt_sdr_cap,
> +	.vidioc_g_fmt_sdr_cap     = rtl2832_sdr_g_fmt_sdr_cap,
> +	.vidioc_s_fmt_sdr_cap     = rtl2832_sdr_s_fmt_sdr_cap,
> +	.vidioc_try_fmt_sdr_cap   = rtl2832_sdr_try_fmt_sdr_cap,
>  
>  	.vidioc_enum_input        = rtl2832_sdr_enum_input,
>  	.vidioc_g_input           = rtl2832_sdr_g_input,

I see no reason why sdr should support these input ioctls.

> @@ -1056,9 +1214,12 @@ static const struct v4l2_ioctl_ops rtl2832_sdr_ioctl_ops = {
>  	.vidioc_streamon          = vb2_ioctl_streamon,
>  	.vidioc_streamoff         = vb2_ioctl_streamoff,
>  
> -	.vidioc_g_tuner           = vidioc_g_tuner,
> -	.vidioc_s_tuner           = vidioc_s_tuner,
> -	.vidioc_s_frequency       = vidioc_s_frequency,
> +	.vidioc_g_tuner           = rtl2832_sdr_g_tuner,
> +	.vidioc_s_tuner           = rtl2832_sdr_s_tuner,
> +
> +	.vidioc_enum_freq_bands   = rtl2832_sdr_enum_freq_bands,
> +	.vidioc_g_frequency       = rtl2832_sdr_g_frequency,
> +	.vidioc_s_frequency       = rtl2832_sdr_s_frequency,
>  
>  	.vidioc_subscribe_event   = v4l2_ctrl_subscribe_event,
>  	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
> @@ -1080,6 +1241,7 @@ static struct video_device rtl2832_sdr_template = {
>  	.release                  = video_device_release_empty,
>  	.fops                     = &rtl2832_sdr_fops,
>  	.ioctl_ops                = &rtl2832_sdr_ioctl_ops,
> +	.debug                    = 0,

Please drop this. You probably used it for debugging.

You can enable this dynamically using:

echo 1 >/sys/class/video4linux/radio0/debug

>  };
>  
>  static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl)
> @@ -1227,7 +1389,7 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
>  	INIT_LIST_HEAD(&s->queued_bufs);
>  
>  	/* Init videobuf2 queue structure */
> -	s->vb_queue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> +	s->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE;
>  	s->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
>  	s->vb_queue.drv_priv = s;
>  	s->vb_queue.buf_struct_size = sizeof(struct rtl2832_sdr_frame_buf);
> @@ -1274,8 +1436,9 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
>  	s->v4l2_dev.ctrl_handler = &s->ctrl_handler;
>  	s->vdev.v4l2_dev = &s->v4l2_dev;
>  	s->vdev.lock = &s->v4l2_lock;
> +	s->vdev.vfl_dir = VFL_DIR_RX;
>  
> -	ret = video_register_device(&s->vdev, VFL_TYPE_GRABBER, -1);
> +	ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1);
>  	if (ret < 0) {
>  		dev_err(&s->udev->dev,
>  				"Failed to register as video device (%d)\n",
> 

Regards,

	Hans

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC v3 5/7] v4l: enable some IOCTLs for SDR receiver
  2013-12-17  7:34   ` Hans Verkuil
@ 2013-12-17 16:40     ` Antti Palosaari
  2013-12-18  7:32       ` Hans Verkuil
  0 siblings, 1 reply; 23+ messages in thread
From: Antti Palosaari @ 2013-12-17 16:40 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, Mauro Carvalho Chehab

On 17.12.2013 09:34, Hans Verkuil wrote:
> On 12/16/2013 11:08 PM, Antti Palosaari wrote:
>> +	} else if (is_sdr) {

>> +
>> +		if (is_rx) {
>> +			SET_VALID_IOCTL(ops, VIDIOC_ENUMINPUT, vidioc_enum_input);
>> +			SET_VALID_IOCTL(ops, VIDIOC_G_INPUT, vidioc_g_input);
>> +			SET_VALID_IOCTL(ops, VIDIOC_S_INPUT, vidioc_s_input);
>
> Why would you want to enable these? Normal radio devices should never use
> these, so why would sdr devices?

I though it might be good idea to select possible antenna input. I have 
one rtl2832u prototype which has 2 physical antenna connector, but on 
the real life input selection is not needed even on that case as 
antennas are hardwired to different tuner inputs => selection is done 
according to frequency. Almost all modern silicon tuners has multiple 
inputs, whilst device has only one physical antenna connector.

All-in-all, it is not needed now and I can remove it without any noise 
if you wish. It is trivial to add later if really needed.

regards
Antti

-- 
http://palosaari.fi/

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC v3 0/7] SDR API
  2013-12-17  7:36 ` [PATCH RFC v3 0/7] " Hans Verkuil
@ 2013-12-17 16:46   ` Antti Palosaari
  0 siblings, 0 replies; 23+ messages in thread
From: Antti Palosaari @ 2013-12-17 16:46 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, Mauro Carvalho Chehab

On 17.12.2013 09:36, Hans Verkuil wrote:
> On 12/16/2013 11:08 PM, Antti Palosaari wrote:
>> Now with some changes done requested by Hans.
>> I did not agree	very well that VIDIOC_G_FREQUENCY tuner type check
>> exception, but here it is...
>>
>> Also two patches, as example, conversion of msi3101 and rtl2832_sdr
>> drivers to that API.
>>
>> regards
>> Antti
>>
>> Antti Palosaari (7):
>>    v4l: add new tuner types for SDR
>>    v4l: 1 Hz resolution flag for tuners
>>    v4l: add stream format for SDR receiver
>>    v4l: define own IOCTL ops for SDR FMT
>>    v4l: enable some IOCTLs for SDR receiver
>
> Is it just too early in the day or is the patch adding VFL_TYPE_SDR and
> the swradio device missing in this patch series?

My mistake. Just selected off-by-one starting patch. I will add that to 
next try at the same time I send documentation changes.

regards
Antti

-- 
http://palosaari.fi/

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC v3 5/7] v4l: enable some IOCTLs for SDR receiver
  2013-12-17 16:40     ` Antti Palosaari
@ 2013-12-18  7:32       ` Hans Verkuil
  0 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-12-18  7:32 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: linux-media, Mauro Carvalho Chehab

On 12/17/2013 05:40 PM, Antti Palosaari wrote:
> On 17.12.2013 09:34, Hans Verkuil wrote:
>> On 12/16/2013 11:08 PM, Antti Palosaari wrote:
>>> +	} else if (is_sdr) {
> 
>>> +
>>> +		if (is_rx) {
>>> +			SET_VALID_IOCTL(ops, VIDIOC_ENUMINPUT, vidioc_enum_input);
>>> +			SET_VALID_IOCTL(ops, VIDIOC_G_INPUT, vidioc_g_input);
>>> +			SET_VALID_IOCTL(ops, VIDIOC_S_INPUT, vidioc_s_input);
>>
>> Why would you want to enable these? Normal radio devices should never use
>> these, so why would sdr devices?
> 
> I though it might be good idea to select possible antenna input. I have 
> one rtl2832u prototype which has 2 physical antenna connector, but on 
> the real life input selection is not needed even on that case as 
> antennas are hardwired to different tuner inputs => selection is done 
> according to frequency. Almost all modern silicon tuners has multiple 
> inputs, whilst device has only one physical antenna connector.
> 
> All-in-all, it is not needed now and I can remove it without any noise 
> if you wish. It is trivial to add later if really needed.

Please remove it. If we need antenna input selection in the future, then
we have to look at this again.

Regards,

	Hans


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC v3 6/7] rtl2832_sdr: convert to SDR API
  2013-12-16 22:08 ` [PATCH RFC v3 6/7] rtl2832_sdr: convert to SDR API Antti Palosaari
  2013-12-17  7:45   ` Hans Verkuil
@ 2013-12-19  9:21   ` Hans Verkuil
  2013-12-19 16:50     ` Antti Palosaari
  1 sibling, 1 reply; 23+ messages in thread
From: Hans Verkuil @ 2013-12-19  9:21 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: linux-media, Mauro Carvalho Chehab

On 12/16/2013 11:08 PM, Antti Palosaari wrote:
> It was abusing video device API. Use SDR API instead.
> 
> Signed-off-by: Antti Palosaari <crope@iki.fi>
> ---
>  drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 291 ++++++++++++++++++-----
>  1 file changed, 227 insertions(+), 64 deletions(-)
> 

A question: does this driver only do SDR, or does it also 
do 'regular' video and/or radio?

If it does, then how does it switch from one tuner mode to another?

E.g. from ANALOG_TV to RADIO to SDR?

During the Barcelona summit in 2012 we discussed this. See the last two
slides of my presentation:

http://linuxtv.org/downloads/presentations/media_ws_2012_EU/ambiguities2.odp

Basically this proposal was accepted provided that the code to handle tuner
ownership should be shared between DVB and V4L2.

I made an initial attempt for this here:

http://git.linuxtv.org/hverkuil/media_tree.git/shortlog/refs/heads/tuner

I never had the time to continue with it, but it might be useful for rtl2832.

Regards,

	Hans

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC v3 6/7] rtl2832_sdr: convert to SDR API
  2013-12-19  9:21   ` Hans Verkuil
@ 2013-12-19 16:50     ` Antti Palosaari
  2013-12-19 16:59       ` Devin Heitmueller
  0 siblings, 1 reply; 23+ messages in thread
From: Antti Palosaari @ 2013-12-19 16:50 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, Mauro Carvalho Chehab

Hi Hans!

On 19.12.2013 11:21, Hans Verkuil wrote:
> On 12/16/2013 11:08 PM, Antti Palosaari wrote:
>> It was abusing video device API. Use SDR API instead.
>>
>> Signed-off-by: Antti Palosaari <crope@iki.fi>
>> ---
>>   drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 291 ++++++++++++++++++-----
>>   1 file changed, 227 insertions(+), 64 deletions(-)
>>
>
> A question: does this driver only do SDR, or does it also
> do 'regular' video and/or radio?
>
> If it does, then how does it switch from one tuner mode to another?
>
> E.g. from ANALOG_TV to RADIO to SDR?
>
> During the Barcelona summit in 2012 we discussed this. See the last two
> slides of my presentation:
>
> http://linuxtv.org/downloads/presentations/media_ws_2012_EU/ambiguities2.odp
>
> Basically this proposal was accepted provided that the code to handle tuner
> ownership should be shared between DVB and V4L2.
>
> I made an initial attempt for this here:
>
> http://git.linuxtv.org/hverkuil/media_tree.git/shortlog/refs/heads/tuner
>
> I never had the time to continue with it, but it might be useful for rtl2832.

Yes, that driver sits on both DVB and V4L2 API. It is USB DVB-T stick, 
which could be abused as a SDR.

There is following software blocks:
1) dvb_usb + dvb_usb_rtl28xxu modules to provide USB interface
2) rtl2832 module to provide DVB-T demodulator (implements DVB frontend, 
which logical entity representing DVB hardware)
3) various silicon RF tuners, eg. e4000, r820t, fc0013... These tuners 
are provided via DVB API, frontend tuners.
4) rtl2832_sdr module, which is attached to DVB frontend using "sec". 
Term sec stays satellite equipment controller (provides typically LNB 
voltage)

It should be also noted that DVB-T demodulator and SDR functionality is 
provided "physically" by same RTL2832 demod - whilst I decided to split 
those own drivers. And make situation looks even more complex, I can say 
RTL2832 demod is integrated physically to same silicon than USB-bridge 
(but logically those seems to be totally different chip sill).

Hope those explanations could give some light what kind of connections 
and blocks there is involved.

So indeed there is that same hybrid tuner problem to resolve. And not 
only that hybrid problem, but you will need to expose much more 
properties from RF tuner than DVB API or V4L2 API tuner model does 
currently. I haven't looked situation more carefully yet, but one thing 
that must be done at the very first is to add some lock to prevent only 
DVB or V4L2 API could access the hardware at time.

regards
Antti

-- 
http://palosaari.fi/

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC v3 6/7] rtl2832_sdr: convert to SDR API
  2013-12-19 16:50     ` Antti Palosaari
@ 2013-12-19 16:59       ` Devin Heitmueller
  2013-12-19 18:38         ` Antti Palosaari
  0 siblings, 1 reply; 23+ messages in thread
From: Devin Heitmueller @ 2013-12-19 16:59 UTC (permalink / raw)
  To: Antti Palosaari
  Cc: Hans Verkuil, Linux Media Mailing List, Mauro Carvalho Chehab

> I haven't
> looked situation more carefully yet, but one thing that must be done at the
> very first is to add some lock to prevent only DVB or V4L2 API could access
> the hardware at time.

Probably worth mentioning that we have *lots* of devices that suffer
from this problem.  Our general tact has to been to do nothing and let
the driver crash and burn in non-predictable ways when userland tries
to use both APIs at the same time.

So while it's pretty pathetic that we still haven't resolved this
after all these years, if you didn't address the issue in the initial
release then you wouldn't be much worse off than lots of other
devices.

Devin

-- 
Devin J. Heitmueller - Kernel Labs
http://www.kernellabs.com

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC v3 6/7] rtl2832_sdr: convert to SDR API
  2013-12-19 16:59       ` Devin Heitmueller
@ 2013-12-19 18:38         ` Antti Palosaari
  2013-12-19 19:12           ` Devin Heitmueller
  0 siblings, 1 reply; 23+ messages in thread
From: Antti Palosaari @ 2013-12-19 18:38 UTC (permalink / raw)
  To: Devin Heitmueller
  Cc: Hans Verkuil, Linux Media Mailing List, Mauro Carvalho Chehab

On 19.12.2013 18:59, Devin Heitmueller wrote:
>> I haven't
>> looked situation more carefully yet, but one thing that must be done at the
>> very first is to add some lock to prevent only DVB or V4L2 API could access
>> the hardware at time.
>
> Probably worth mentioning that we have *lots* of devices that suffer
> from this problem.  Our general tact has to been to do nothing and let
> the driver crash and burn in non-predictable ways when userland tries
> to use both APIs at the same time.
>
> So while it's pretty pathetic that we still haven't resolved this
> after all these years, if you didn't address the issue in the initial
> release then you wouldn't be much worse off than lots of other
> devices.

I think I could add some lock quite easily. I remember when I 
implemented cxd2820r DVB-T/T2/C demod driver and at the time it 
implements 2 frontends, one for DVB-T/T2 and one for DVB-C. I used 
shared lock to prevent access only for single fe at time. I think same 
solution works in that case too.

regards
Antti

-- 
http://palosaari.fi/

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC v3 6/7] rtl2832_sdr: convert to SDR API
  2013-12-19 18:38         ` Antti Palosaari
@ 2013-12-19 19:12           ` Devin Heitmueller
  0 siblings, 0 replies; 23+ messages in thread
From: Devin Heitmueller @ 2013-12-19 19:12 UTC (permalink / raw)
  To: Antti Palosaari
  Cc: Hans Verkuil, Linux Media Mailing List, Mauro Carvalho Chehab

> I think I could add some lock quite easily. I remember when I implemented
> cxd2820r DVB-T/T2/C demod driver and at the time it implements 2 frontends,
> one for DVB-T/T2 and one for DVB-C. I used shared lock to prevent access
> only for single fe at time. I think same solution works in that case too.

Locking between v4l and dvb is more problematic because of known bugs
related to the dvb_frontend deferring the shutdown of the tuner.  As a
result there is a race condition if you try to close the DVB device
and then immediately open the V4L device (which would be a common use
case if using an application like MythTV when switching from digital
to analog mode).

You can't simply add a lock because the V4L side will get hit with
-EBUSY because the DVB frontend hasn't completely shutdown yet.

Unfortunately it's one of those cases where it "seems" easy until you
start scoping out the edge cases and race conditions.

Devin

-- 
Devin J. Heitmueller - Kernel Labs
http://www.kernellabs.com

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2013-12-19 19:12 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-16 22:08 [PATCH RFC v3 0/7] SDR API Antti Palosaari
2013-12-16 22:08 ` [PATCH RFC v3 1/7] v4l: add new tuner types for SDR Antti Palosaari
2013-12-17  7:31   ` Hans Verkuil
2013-12-16 22:08 ` [PATCH RFC v3 2/7] v4l: 1 Hz resolution flag for tuners Antti Palosaari
2013-12-17  7:31   ` Hans Verkuil
2013-12-16 22:08 ` [PATCH RFC v3 3/7] v4l: add stream format for SDR receiver Antti Palosaari
2013-12-17  7:32   ` Hans Verkuil
2013-12-16 22:08 ` [PATCH RFC v3 4/7] v4l: define own IOCTL ops for SDR FMT Antti Palosaari
2013-12-17  7:32   ` Hans Verkuil
2013-12-16 22:08 ` [PATCH RFC v3 5/7] v4l: enable some IOCTLs for SDR receiver Antti Palosaari
2013-12-17  7:34   ` Hans Verkuil
2013-12-17 16:40     ` Antti Palosaari
2013-12-18  7:32       ` Hans Verkuil
2013-12-16 22:08 ` [PATCH RFC v3 6/7] rtl2832_sdr: convert to SDR API Antti Palosaari
2013-12-17  7:45   ` Hans Verkuil
2013-12-19  9:21   ` Hans Verkuil
2013-12-19 16:50     ` Antti Palosaari
2013-12-19 16:59       ` Devin Heitmueller
2013-12-19 18:38         ` Antti Palosaari
2013-12-19 19:12           ` Devin Heitmueller
2013-12-16 22:08 ` [PATCH RFC v3 7/7] msi3101: " Antti Palosaari
2013-12-17  7:36 ` [PATCH RFC v3 0/7] " Hans Verkuil
2013-12-17 16:46   ` Antti Palosaari

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox