public inbox for linux-media@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] convert drivers to SDR API
@ 2013-12-29  4:51 Antti Palosaari
  2013-12-29  4:51 ` [PATCH 1/6] rtl2832_sdr: convert " Antti Palosaari
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Antti Palosaari @ 2013-12-29  4:51 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Antti Palosaari

Here is two drivers converted to API.

There is still a tons of things	to do, like expose tuner AGC control to
userspace. Also one very big task is to design how these DVB tuners should
be shared properly with DVB and V4L2 SDR API. Move used V4L2 FourCC codes
to API and many many other easy things!

[1] Kernel tree having latest SDR drivers (msi3101 and rtl2832)
[2] GNU Radio plugin to use these devices via Kernel API
[3] FM radio schematics for GNU	Radio to listen radio (by OZ9AEC)


[1] http://git.linuxtv.org/anttip/media_tree.git/shortlog/refs/heads/sdr
[2] http://git.linuxtv.org/anttip/gr-kernel.git
[3] http://palosaari.fi/linux/v4l-dvb/wfm_rx.py

regards
Antti

Antti Palosaari (6):
  rtl2832_sdr: convert to SDR API
  msi3101: convert to SDR API
  msi3101: add u8 sample format
  msi3101: add u16 LE sample format
  msi3101: tons of small changes
  v4l: disable lockdep on vb2_fop_mmap()

 drivers/media/v4l2-core/videobuf2-core.c         |  14 +-
 drivers/staging/media/msi3101/sdr-msi3101.c      | 526 ++++++++++++++---------
 drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 387 ++++++++++-------
 3 files changed, 565 insertions(+), 362 deletions(-)

-- 
1.8.4.2


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

* [PATCH 1/6] rtl2832_sdr: convert to SDR API
  2013-12-29  4:51 [PATCH 0/6] convert drivers to SDR API Antti Palosaari
@ 2013-12-29  4:51 ` Antti Palosaari
  2013-12-29  4:51 ` [PATCH 2/6] msi3101: " Antti Palosaari
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Antti Palosaari @ 2013-12-29  4:51 UTC (permalink / raw)
  To: linux-media; +Cc: 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 | 387 +++++++++++++----------
 1 file changed, 223 insertions(+), 164 deletions(-)

diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index 4b8c016..a26125c 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,22 +32,75 @@
 #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 */
-#define RTL2832_SDR_CID_SAMPLING_MODE       ((V4L2_CID_USER_BASE | 0xf000) +  0)
-#define RTL2832_SDR_CID_SAMPLING_RATE       ((V4L2_CID_USER_BASE | 0xf000) +  1)
-#define RTL2832_SDR_CID_SAMPLING_RESOLUTION ((V4L2_CID_USER_BASE | 0xf000) +  2)
-#define RTL2832_SDR_CID_TUNER_RF            ((V4L2_CID_USER_BASE | 0xf000) + 10)
 #define RTL2832_SDR_CID_TUNER_BW            ((V4L2_CID_USER_BASE | 0xf000) + 11)
-#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_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow   =    50000000,
+		.rangehigh  =  2000000000,
+	},
+};
+
+/* stream formats */
+struct rtl2832_sdr_format {
+	char	*name;
+	u32	pixelformat;
+};
+
+static struct rtl2832_sdr_format formats[] = {
+	{
+		.name		= "8-bit unsigned",
+		.pixelformat	= V4L2_PIX_FMT_SDR_U8,
+	}, {
+		.name		= "16-bit unsigned little endian",
+		.pixelformat	= V4L2_PIX_FMT_SDR_U16LE,
+	},
+};
+
+static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
+
 /* 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,18 +143,18 @@ 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;
-	struct v4l2_ctrl *ctrl_tuner_rf;
 	struct v4l2_ctrl *ctrl_tuner_bw;
-	struct v4l2_ctrl *ctrl_tuner_if;
 	struct v4l2_ctrl *ctrl_tuner_gain;
 
 	/* for sample rate calc */
 	unsigned int sample;
 	unsigned int sample_measured;
-	unsigned long jiffies;
+	unsigned long jiffies_next;
 };
 
 /* write multiple hardware registers */
@@ -292,27 +339,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 +404,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 +605,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 +621,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;
@@ -609,7 +671,10 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
 	if (!test_bit(POWER_ON, &s->flags))
 		return 0;
 
-	f_sr = s->ctrl_sampling_rate->val64;
+	if (s->f_adc == 0)
+		return 0;
+
+	f_sr = s->f_adc;
 
 	ret = rtl2832_sdr_wr_regs(s, 0x13e, "\x00\x00", 2);
 	ret = rtl2832_sdr_wr_regs(s, 0x115, "\x00", 1);
@@ -788,17 +853,15 @@ static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s)
 	struct dvb_frontend *fe = s->fe;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 
-	unsigned int f_rf = s->ctrl_tuner_rf->val64;
-
 	/*
-	 * bandwidth (Hz)
+	 * tuner RF (Hz)
 	 */
-	unsigned int bandwidth = s->ctrl_tuner_bw->val;
+	unsigned int f_rf = s->f_tuner;
 
 	/*
-	 * intermediate frequency (Hz)
+	 * bandwidth (Hz)
 	 */
-	unsigned int f_if = s->ctrl_tuner_if->val;
+	unsigned int bandwidth = s->ctrl_tuner_bw->val;
 
 	/*
 	 * gain (dB)
@@ -806,8 +869,11 @@ static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s)
 	int gain = s->ctrl_tuner_gain->val;
 
 	dev_dbg(&s->udev->dev,
-			"%s: f_rf=%u bandwidth=%d f_if=%u gain=%d\n",
-			__func__, f_rf, bandwidth, f_if, gain);
+			"%s: f_rf=%u bandwidth=%d gain=%d\n",
+			__func__, f_rf, bandwidth, gain);
+
+	if (f_rf == 0)
+		return 0;
 
 	if (!test_bit(POWER_ON, &s->flags))
 		return 0;
@@ -913,123 +979,182 @@ 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_g_tuner(struct file *file, void *priv,
+		struct v4l2_tuner *v)
 {
-	if (i->index != 0)
+	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_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+		v->rangelow =    50000000;
+		v->rangehigh = 2000000000;
+	} else {
 		return -EINVAL;
-
-	strlcpy(i->name, "SDR data", sizeof(i->name));
-	i->type = V4L2_INPUT_TYPE_CAMERA;
+	}
 
 	return 0;
 }
 
-static int rtl2832_sdr_g_input(struct file *file, void *fh, unsigned int *i)
+static int rtl2832_sdr_s_tuner(struct file *file, void *priv,
+		const struct v4l2_tuner *v)
 {
-	*i = 0;
+	struct rtl2832_sdr_state *s = video_drvdata(file);
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
 
 	return 0;
 }
 
-static int rtl2832_sdr_s_input(struct file *file, void *fh, unsigned int i)
-{
-	return i ? -EINVAL : 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
-		const 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;
+
+		*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_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
+static int rtl2832_sdr_g_frequency(struct file *file, void *priv,
+		struct v4l2_frequency *f)
 {
 	struct rtl2832_sdr_state *s = video_drvdata(file);
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	strcpy(v->name, "SDR RX");
-	v->capability = V4L2_TUNER_CAP_LOW;
+	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 0;
+	return ret;
 }
 
-static int vidioc_s_frequency(struct file *file, void *priv,
+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);
 
-	return v4l2_ctrl_s_ctrl_int64(s->ctrl_tuner_rf,
-			f->frequency * 625UL / 10UL);
+	if (f->tuner == 0) {
+		s->f_adc = f->frequency;
+		dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n",
+				__func__, s->f_adc);
+		ret = rtl2832_sdr_set_adc(s);
+	} else if (f->tuner == 1) {
+		s->f_tuner = f->frequency;
+		dev_dbg(&s->udev->dev, "%s: RF frequency=%u Hz\n",
+				__func__, f->frequency);
+		ret = rtl2832_sdr_set_tuner(s);
+	} else {
+		return -EINVAL;
+	}
+
+	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,14 +1162,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_input        = rtl2832_sdr_enum_input,
-	.vidioc_g_input           = rtl2832_sdr_g_input,
-	.vidioc_s_input           = rtl2832_sdr_s_input,
+	.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_reqbufs           = vb2_ioctl_reqbufs,
 	.vidioc_create_bufs       = vb2_ioctl_create_bufs,
@@ -1056,9 +1177,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,
@@ -1076,7 +1200,7 @@ static const struct v4l2_file_operations rtl2832_sdr_fops = {
 };
 
 static struct video_device rtl2832_sdr_template = {
-	.name                     = "Realtek RTL2832U SDR",
+	.name                     = "Realtek RTL2832 SDR",
 	.release                  = video_device_release_empty,
 	.fops                     = &rtl2832_sdr_fops,
 	.ioctl_ops                = &rtl2832_sdr_ioctl_ops,
@@ -1094,14 +1218,7 @@ static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl)
 			ctrl->minimum, ctrl->maximum, ctrl->step);
 
 	switch (ctrl->id) {
-	case RTL2832_SDR_CID_SAMPLING_MODE:
-	case RTL2832_SDR_CID_SAMPLING_RATE:
-	case RTL2832_SDR_CID_SAMPLING_RESOLUTION:
-		ret = rtl2832_sdr_set_adc(s);
-		break;
-	case RTL2832_SDR_CID_TUNER_RF:
 	case RTL2832_SDR_CID_TUNER_BW:
-	case RTL2832_SDR_CID_TUNER_IF:
 	case RTL2832_SDR_CID_TUNER_GAIN:
 		ret = rtl2832_sdr_set_tuner(s);
 		break;
@@ -1132,49 +1249,6 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
 	int ret;
 	struct rtl2832_sdr_state *s;
 	struct dvb_usb_device *d = i2c_get_adapdata(i2c);
-	static const char * const ctrl_sampling_mode_qmenu_strings[] = {
-		"Quadrature Sampling",
-		NULL,
-	};
-	static const struct v4l2_ctrl_config ctrl_sampling_mode = {
-		.ops	= &rtl2832_sdr_ctrl_ops,
-		.id	= RTL2832_SDR_CID_SAMPLING_MODE,
-		.type   = V4L2_CTRL_TYPE_MENU,
-		.flags  = V4L2_CTRL_FLAG_INACTIVE,
-		.name	= "Sampling Mode",
-		.qmenu  = ctrl_sampling_mode_qmenu_strings,
-	};
-	static const struct v4l2_ctrl_config ctrl_sampling_rate = {
-		.ops	= &rtl2832_sdr_ctrl_ops,
-		.id	= RTL2832_SDR_CID_SAMPLING_RATE,
-		.type	= V4L2_CTRL_TYPE_INTEGER64,
-		.name	= "Sampling Rate",
-		.min	=  900001,
-		.max	= 2800000,
-		.def    = 2048000,
-		.step	= 1,
-	};
-	static const struct v4l2_ctrl_config ctrl_sampling_resolution = {
-		.ops	= &rtl2832_sdr_ctrl_ops,
-		.id	= RTL2832_SDR_CID_SAMPLING_RESOLUTION,
-		.type	= V4L2_CTRL_TYPE_INTEGER,
-		.flags  = V4L2_CTRL_FLAG_INACTIVE,
-		.name	= "Sampling Resolution",
-		.min	= 8,
-		.max	= 8,
-		.def    = 8,
-		.step	= 1,
-	};
-	static const struct v4l2_ctrl_config ctrl_tuner_rf = {
-		.ops	= &rtl2832_sdr_ctrl_ops,
-		.id	= RTL2832_SDR_CID_TUNER_RF,
-		.type   = V4L2_CTRL_TYPE_INTEGER64,
-		.name	= "Tuner RF",
-		.min	=   40000000,
-		.max	= 2000000000,
-		.def    =  100000000,
-		.step	= 1,
-	};
 	static const struct v4l2_ctrl_config ctrl_tuner_bw = {
 		.ops	= &rtl2832_sdr_ctrl_ops,
 		.id	= RTL2832_SDR_CID_TUNER_BW,
@@ -1185,17 +1259,6 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
 		.def    =  600000,
 		.step	= 1,
 	};
-	static const struct v4l2_ctrl_config ctrl_tuner_if = {
-		.ops	= &rtl2832_sdr_ctrl_ops,
-		.id	= RTL2832_SDR_CID_TUNER_IF,
-		.type	= V4L2_CTRL_TYPE_INTEGER,
-		.flags  = V4L2_CTRL_FLAG_INACTIVE,
-		.name	= "Tuner IF",
-		.min	= 0,
-		.max	= 10,
-		.def    = 0,
-		.step	= 1,
-	};
 	static const struct v4l2_ctrl_config ctrl_tuner_gain = {
 		.ops	= &rtl2832_sdr_ctrl_ops,
 		.id	= RTL2832_SDR_CID_TUNER_GAIN,
@@ -1227,7 +1290,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);
@@ -1248,13 +1311,8 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
 	video_set_drvdata(&s->vdev, s);
 
 	/* Register controls */
-	v4l2_ctrl_handler_init(&s->ctrl_handler, 7);
-	v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_sampling_mode, NULL);
-	s->ctrl_sampling_rate = v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_sampling_rate, NULL);
-	v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_sampling_resolution, NULL);
-	s->ctrl_tuner_rf = v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_tuner_rf, NULL);
+	v4l2_ctrl_handler_init(&s->ctrl_handler, 2);
 	s->ctrl_tuner_bw = v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_tuner_bw, NULL);
-	s->ctrl_tuner_if = v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_tuner_if, NULL);
 	s->ctrl_tuner_gain = v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_tuner_gain, NULL);
 	if (s->ctrl_handler.error) {
 		ret = s->ctrl_handler.error;
@@ -1274,8 +1332,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] 11+ messages in thread

* [PATCH 2/6] msi3101: convert to SDR API
  2013-12-29  4:51 [PATCH 0/6] convert drivers to SDR API Antti Palosaari
  2013-12-29  4:51 ` [PATCH 1/6] rtl2832_sdr: convert " Antti Palosaari
@ 2013-12-29  4:51 ` Antti Palosaari
  2013-12-29  4:51 ` [PATCH 3/6] msi3101: add u8 sample format Antti Palosaari
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Antti Palosaari @ 2013-12-29  4:51 UTC (permalink / raw)
  To: linux-media; +Cc: 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] 11+ messages in thread

* [PATCH 3/6] msi3101: add u8 sample format
  2013-12-29  4:51 [PATCH 0/6] convert drivers to SDR API Antti Palosaari
  2013-12-29  4:51 ` [PATCH 1/6] rtl2832_sdr: convert " Antti Palosaari
  2013-12-29  4:51 ` [PATCH 2/6] msi3101: " Antti Palosaari
@ 2013-12-29  4:51 ` Antti Palosaari
  2014-01-05 12:14   ` Hans Verkuil
  2013-12-29  4:51 ` [PATCH 4/6] msi3101: add u16 LE " Antti Palosaari
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Antti Palosaari @ 2013-12-29  4:51 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Antti Palosaari

Add unsigned 8-bit sample format. Format is got directly from
hardware, but it is converted from signed to unsigned. It is worst
known sampling resolution hardware offer.

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

diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index 9c54c63..2110488 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -385,6 +385,7 @@ static const struct msi3101_gain msi3101_gain_lut_1000[] = {
 #define MSI3101_CID_TUNER_IF              ((V4L2_CID_USER_BASE | 0xf000) + 12)
 #define MSI3101_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_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 */
@@ -428,6 +429,9 @@ struct msi3101_format {
 /* format descriptions for capture and preview */
 static struct msi3101_format formats[] = {
 	{
+		.name		= "I/Q 8-bit unsigned",
+		.pixelformat	= V4L2_PIX_FMT_SDR_U8,
+	}, {
 		.name		= "I/Q 8-bit signed",
 		.pixelformat	= V4L2_PIX_FMT_SDR_S8,
 	}, {
@@ -487,6 +491,7 @@ struct msi3101_state {
 	u32 next_sample; /* for track lost packets */
 	u32 sample; /* for sample rate calc */
 	unsigned long jiffies;
+	unsigned long jiffies_next;
 	unsigned int sample_ctrl_bit[4];
 };
 
@@ -572,6 +577,63 @@ static int msi3101_convert_stream_504(struct msi3101_state *s, u8 *dst,
 	return dst_len;
 }
 
+static int msi3101_convert_stream_504_u8(struct msi3101_state *s, u8 *dst,
+		u8 *src, unsigned int src_len)
+{
+	int i, j, i_max, dst_len = 0;
+	u32 sample_num[3];
+	s8 *s8src;
+	u8 *u8dst;
+
+	/* There could be 1-3 1024 bytes URB frames */
+	i_max = src_len / 1024;
+	u8dst = (u8 *) dst;
+
+	for (i = 0; i < i_max; i++) {
+		sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0;
+		if (i == 0 && s->next_sample != sample_num[0]) {
+			dev_dbg_ratelimited(&s->udev->dev,
+					"%d samples lost, %d %08x:%08x\n",
+					sample_num[0] - s->next_sample,
+					src_len, s->next_sample, sample_num[0]);
+		}
+
+		/*
+		 * Dump all unknown 'garbage' data - maybe we will discover
+		 * someday if there is something rational...
+		 */
+		dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]);
+
+		/* 504 x I+Q samples */
+		src += 16;
+
+		s8src = (s8 *) src;
+		for (j = 0; j < 1008; j++)
+			*u8dst++ = *s8src++ + 128;
+
+		src += 1008;
+		dst += 1008;
+		dst_len += 1008;
+	}
+
+	/* calculate samping rate and output it in 10 seconds intervals */
+	if (unlikely(time_is_before_jiffies(s->jiffies_next))) {
+#define MSECS 10000UL
+		unsigned int samples = sample_num[i_max - 1] - s->sample;
+		s->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
+		s->sample = sample_num[i_max - 1];
+		dev_dbg(&s->udev->dev,
+				"slen=%d samples=%u msecs=%lu sampling rate=%lu\n",
+				src_len, samples, MSECS,
+				samples * 1000UL / MSECS);
+	}
+
+	/* next sample (sample = sample + i * 504) */
+	s->next_sample = sample_num[i_max - 1] + 504;
+
+	return dst_len;
+}
+
 /*
  * +===========================================================================
  * |   00-1023 | USB packet type '384'
@@ -1159,7 +1221,10 @@ static int msi3101_set_usb_adc(struct msi3101_state *s)
 		reg7 = 0x000c9407;
 	}
 
-	if (s->pixelformat == V4L2_PIX_FMT_SDR_S8) {
+	if (s->pixelformat == V4L2_PIX_FMT_SDR_U8) {
+		s->convert_stream = msi3101_convert_stream_504_u8;
+		reg7 = 0x000c9407;
+	} else if (s->pixelformat == V4L2_PIX_FMT_SDR_S8) {
 		s->convert_stream = msi3101_convert_stream_504;
 		reg7 = 0x000c9407;
 	} else if (s->pixelformat == V4L2_PIX_FMT_SDR_MSI2500_384) {
-- 
1.8.4.2


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

* [PATCH 4/6] msi3101: add u16 LE sample format
  2013-12-29  4:51 [PATCH 0/6] convert drivers to SDR API Antti Palosaari
                   ` (2 preceding siblings ...)
  2013-12-29  4:51 ` [PATCH 3/6] msi3101: add u8 sample format Antti Palosaari
@ 2013-12-29  4:51 ` Antti Palosaari
  2013-12-29  4:51 ` [PATCH 5/6] msi3101: tons of small changes Antti Palosaari
  2013-12-29  4:51 ` [PATCH 6/6] v4l: disable lockdep on vb2_fop_mmap() Antti Palosaari
  5 siblings, 0 replies; 11+ messages in thread
From: Antti Palosaari @ 2013-12-29  4:51 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Antti Palosaari

Add unsigned 16-bit little endian sample format. That stream
format is scaled from hardware 14-bit signed value. That is best
known sampling resolution that MSi2500 ADC provides.

It is not guaranteed to be little endian, but host endian which is
usually little endian - room for improvement.

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

diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index 2110488..41894c1 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -386,6 +386,7 @@ 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_U8     v4l2_fourcc('D', 'U', '0', '8') /* unsigned 8-bit */
+#define V4L2_PIX_FMT_SDR_U16LE  v4l2_fourcc('D', 'U', '1', '6') /* unsigned 16-bit LE */
 #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 */
@@ -432,6 +433,9 @@ static struct msi3101_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,
+	}, {
 		.name		= "I/Q 8-bit signed",
 		.pixelformat	= V4L2_PIX_FMT_SDR_S8,
 	}, {
@@ -857,6 +861,78 @@ static int msi3101_convert_stream_252(struct msi3101_state *s, u8 *dst,
 	return dst_len;
 }
 
+static int msi3101_convert_stream_252_u16(struct msi3101_state *s, u8 *dst,
+		u8 *src, unsigned int src_len)
+{
+	int i, j, i_max, dst_len = 0;
+	u32 sample_num[3];
+	u16 *u16dst = (u16 *) dst;
+	struct {signed int x:14;} se;
+
+	/* There could be 1-3 1024 bytes URB frames */
+	i_max = src_len / 1024;
+
+	for (i = 0; i < i_max; i++) {
+		sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0;
+		if (i == 0 && s->next_sample != sample_num[0]) {
+			dev_dbg_ratelimited(&s->udev->dev,
+					"%d samples lost, %d %08x:%08x\n",
+					sample_num[0] - s->next_sample,
+					src_len, s->next_sample, sample_num[0]);
+		}
+
+		/*
+		 * Dump all unknown 'garbage' data - maybe we will discover
+		 * someday if there is something rational...
+		 */
+		dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]);
+
+		/* 252 x I+Q samples */
+		src += 16;
+
+		for (j = 0; j < 1008; j += 4) {
+			unsigned int usample[2];
+			int ssample[2];
+
+			usample[0] = src[j + 0] >> 0 | src[j + 1] << 8;
+			usample[1] = src[j + 2] >> 0 | src[j + 3] << 8;
+
+			/* sign extension from 14-bit to signed int */
+			ssample[0] = se.x = usample[0];
+			ssample[1] = se.x = usample[1];
+
+			/* from signed to unsigned */
+			usample[0] = ssample[0] + 8192;
+			usample[1] = ssample[1] + 8192;
+
+			/* from 14-bit to 16-bit */
+			*u16dst++ = (usample[0] << 2) | (usample[0] >> 12);
+			*u16dst++ = (usample[1] << 2) | (usample[1] >> 12);
+		}
+
+		src += 1008;
+		dst += 1008;
+		dst_len += 1008;
+	}
+
+	/* calculate samping rate and output it in 10 seconds intervals */
+	if (unlikely(time_is_before_jiffies(s->jiffies_next))) {
+#define MSECS 10000UL
+		unsigned int samples = sample_num[i_max - 1] - s->sample;
+		s->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
+		s->sample = sample_num[i_max - 1];
+		dev_dbg(&s->udev->dev,
+				"slen=%d samples=%u msecs=%lu sampling rate=%lu\n",
+				src_len, samples, MSECS,
+				samples * 1000UL / MSECS);
+	}
+
+	/* next sample (sample = sample + i * 252) */
+	s->next_sample = sample_num[i_max - 1] + 252;
+
+	return dst_len;
+}
+
 /*
  * This gets called for the Isochronous pipe (stream). This is done in interrupt
  * time, so it has to be fast, not crash, and not stall. Neat.
@@ -1224,6 +1300,9 @@ static int msi3101_set_usb_adc(struct msi3101_state *s)
 	if (s->pixelformat == V4L2_PIX_FMT_SDR_U8) {
 		s->convert_stream = msi3101_convert_stream_504_u8;
 		reg7 = 0x000c9407;
+	} else if (s->pixelformat == V4L2_PIX_FMT_SDR_U16LE) {
+		s->convert_stream = msi3101_convert_stream_252_u16;
+		reg7 = 0x00009407;
 	} else if (s->pixelformat == V4L2_PIX_FMT_SDR_S8) {
 		s->convert_stream = msi3101_convert_stream_504;
 		reg7 = 0x000c9407;
-- 
1.8.4.2


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

* [PATCH 5/6] msi3101: tons of small changes
  2013-12-29  4:51 [PATCH 0/6] convert drivers to SDR API Antti Palosaari
                   ` (3 preceding siblings ...)
  2013-12-29  4:51 ` [PATCH 4/6] msi3101: add u16 LE " Antti Palosaari
@ 2013-12-29  4:51 ` Antti Palosaari
  2013-12-29  4:51 ` [PATCH 6/6] v4l: disable lockdep on vb2_fop_mmap() Antti Palosaari
  5 siblings, 0 replies; 11+ messages in thread
From: Antti Palosaari @ 2013-12-29  4:51 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Antti Palosaari

* remove unneeded controls
* rename things
* remove unneeded callbacks
* use likely/unlikely on hot paths
* use 1Hz resolution for tuner RF frequency

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

diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index 41894c1..24dfd79 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -21,20 +21,6 @@
  *  (C) 1999-2004 Nemosoft Unv.
  *  (C) 2004-2006 Luc Saillard (luc@saillard.org)
  *  (C) 2011 Hans de Goede <hdegoede@redhat.com>
- *
- * Development tree of that driver will be on:
- * http://git.linuxtv.org/anttip/media_tree.git/shortlog/refs/heads/mirics
- *
- * 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:
- * - split USB ADC interface and RF tuner to own drivers (msi2500 and msi001)
- * - 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 <linux/module.h>
@@ -377,12 +363,7 @@ static const struct msi3101_gain msi3101_gain_lut_1000[] = {
 #define MAX_ISOC_ERRORS         20
 
 /* TODO: These should be moved to V4L2 API */
-#define MSI3101_CID_SAMPLING_MODE         ((V4L2_CID_USER_BASE | 0xf000) + 0)
-#define MSI3101_CID_SAMPLING_RATE         ((V4L2_CID_USER_BASE | 0xf000) + 1)
-#define MSI3101_CID_SAMPLING_RESOLUTION   ((V4L2_CID_USER_BASE | 0xf000) + 2)
-#define MSI3101_CID_TUNER_RF              ((V4L2_CID_USER_BASE | 0xf000) + 10)
 #define MSI3101_CID_TUNER_BW              ((V4L2_CID_USER_BASE | 0xf000) + 11)
-#define MSI3101_CID_TUNER_IF              ((V4L2_CID_USER_BASE | 0xf000) + 12)
 #define MSI3101_CID_TUNER_GAIN            ((V4L2_CID_USER_BASE | 0xf000) + 13)
 
 #define V4L2_PIX_FMT_SDR_U8     v4l2_fourcc('D', 'U', '0', '8') /* unsigned 8-bit */
@@ -408,16 +389,16 @@ 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,
+		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow   =   49000000,
+		.rangehigh  =  263000000,
 	}, {
 		.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,
+		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow   =  390000000,
+		.rangehigh  =  960000000,
 	},
 };
 
@@ -430,27 +411,27 @@ struct msi3101_format {
 /* format descriptions for capture and preview */
 static struct msi3101_format formats[] = {
 	{
-		.name		= "I/Q 8-bit unsigned",
+		.name		= "8-bit unsigned",
 		.pixelformat	= V4L2_PIX_FMT_SDR_U8,
 	}, {
-		.name		= "I/Q 16-bit unsigned little endian",
+		.name		= "16-bit unsigned little endian",
 		.pixelformat	= V4L2_PIX_FMT_SDR_U16LE,
 	}, {
-		.name		= "I/Q 8-bit signed",
+		.name		= "8-bit signed",
 		.pixelformat	= V4L2_PIX_FMT_SDR_S8,
 	}, {
-		.name		= "I/Q 10+2-bit signed",
+		.name		= "10+2-bit signed",
 		.pixelformat	= V4L2_PIX_FMT_SDR_MSI2500_384,
 	}, {
-		.name		= "I/Q 12-bit signed",
+		.name		= "12-bit signed",
 		.pixelformat	= V4L2_PIX_FMT_SDR_S12,
 	}, {
-		.name		= "I/Q 14-bit signed",
+		.name		= "14-bit signed",
 		.pixelformat	= V4L2_PIX_FMT_SDR_S14,
 	},
 };
 
-static const int NUM_FORMATS = sizeof(formats) / sizeof(struct msi3101_format);
+static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
 
 /* intermediate buffers with raw data from the USB device */
 struct msi3101_frame_buf {
@@ -486,15 +467,11 @@ struct msi3101_state {
 
 	/* Controls */
 	struct v4l2_ctrl_handler ctrl_handler;
-	struct v4l2_ctrl *ctrl_sampling_rate;
-	struct v4l2_ctrl *ctrl_tuner_rf;
 	struct v4l2_ctrl *ctrl_tuner_bw;
-	struct v4l2_ctrl *ctrl_tuner_if;
 	struct v4l2_ctrl *ctrl_tuner_gain;
 
 	u32 next_sample; /* for track lost packets */
 	u32 sample; /* for sample rate calc */
-	unsigned long jiffies;
 	unsigned long jiffies_next;
 	unsigned int sample_ctrl_bit[4];
 };
@@ -563,11 +540,11 @@ static int msi3101_convert_stream_504(struct msi3101_state *s, u8 *dst,
 	}
 
 	/* calculate samping rate and output it in 10 seconds intervals */
-	if ((s->jiffies + msecs_to_jiffies(10000)) <= jiffies) {
+	if ((s->jiffies_next + msecs_to_jiffies(10000)) <= jiffies) {
 		unsigned long jiffies_now = jiffies;
-		unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies);
+		unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies_next);
 		unsigned int samples = sample_num[i_max - 1] - s->sample;
-		s->jiffies = jiffies_now;
+		s->jiffies_next = jiffies_now;
 		s->sample = sample_num[i_max - 1];
 		dev_dbg(&s->udev->dev,
 				"slen=%d samples=%u msecs=%lu sampling rate=%lu\n",
@@ -715,11 +692,11 @@ static int msi3101_convert_stream_384(struct msi3101_state *s, u8 *dst,
 	}
 
 	/* calculate samping rate and output it in 10 seconds intervals */
-	if ((s->jiffies + msecs_to_jiffies(10000)) <= jiffies) {
+	if ((s->jiffies_next + msecs_to_jiffies(10000)) <= jiffies) {
 		unsigned long jiffies_now = jiffies;
-		unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies);
+		unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies_next);
 		unsigned int samples = sample_num[i_max - 1] - s->sample;
-		s->jiffies = jiffies_now;
+		s->jiffies_next = jiffies_now;
 		s->sample = sample_num[i_max - 1];
 		dev_dbg(&s->udev->dev,
 				"slen=%d samples=%u msecs=%lu sampling rate=%lu bits=%d.%d.%d.%d\n",
@@ -780,11 +757,11 @@ static int msi3101_convert_stream_336(struct msi3101_state *s, u8 *dst,
 	}
 
 	/* calculate samping rate and output it in 10 seconds intervals */
-	if ((s->jiffies + msecs_to_jiffies(10000)) <= jiffies) {
+	if ((s->jiffies_next + msecs_to_jiffies(10000)) <= jiffies) {
 		unsigned long jiffies_now = jiffies;
-		unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies);
+		unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies_next);
 		unsigned int samples = sample_num[i_max - 1] - s->sample;
-		s->jiffies = jiffies_now;
+		s->jiffies_next = jiffies_now;
 		s->sample = sample_num[i_max - 1];
 		dev_dbg(&s->udev->dev,
 				"slen=%d samples=%u msecs=%lu sampling rate=%lu\n",
@@ -843,11 +820,11 @@ static int msi3101_convert_stream_252(struct msi3101_state *s, u8 *dst,
 	}
 
 	/* calculate samping rate and output it in 10 seconds intervals */
-	if ((s->jiffies + msecs_to_jiffies(10000)) <= jiffies) {
+	if ((s->jiffies_next + msecs_to_jiffies(10000)) <= jiffies) {
 		unsigned long jiffies_now = jiffies;
-		unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies);
+		unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies_next);
 		unsigned int samples = sample_num[i_max - 1] - s->sample;
-		s->jiffies = jiffies_now;
+		s->jiffies_next = jiffies_now;
 		s->sample = sample_num[i_max - 1];
 		dev_dbg(&s->udev->dev,
 				"slen=%d samples=%u msecs=%lu sampling rate=%lu\n",
@@ -944,14 +921,14 @@ static void msi3101_isoc_handler(struct urb *urb)
 	unsigned char *iso_buf = NULL;
 	struct msi3101_frame_buf *fbuf;
 
-	if (urb->status == -ENOENT || urb->status == -ECONNRESET ||
-			urb->status == -ESHUTDOWN) {
+	if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET ||
+			urb->status == -ESHUTDOWN)) {
 		dev_dbg(&s->udev->dev, "URB (%p) unlinked %ssynchronuously\n",
 				urb, urb->status == -ENOENT ? "" : "a");
 		return;
 	}
 
-	if (urb->status != 0) {
+	if (unlikely(urb->status != 0)) {
 		dev_dbg(&s->udev->dev,
 				"msi3101_isoc_handler() called with status %d\n",
 				urb->status);
@@ -971,28 +948,28 @@ static void msi3101_isoc_handler(struct urb *urb)
 
 		/* Check frame error */
 		fstatus = urb->iso_frame_desc[i].status;
-		if (fstatus) {
+		if (unlikely(fstatus)) {
 			dev_dbg_ratelimited(&s->udev->dev,
 					"frame=%d/%d has error %d skipping\n",
 					i, urb->number_of_packets, fstatus);
-			goto skip;
+			continue;
 		}
 
 		/* Check if that frame contains data */
 		flen = urb->iso_frame_desc[i].actual_length;
-		if (flen == 0)
-			goto skip;
+		if (unlikely(flen == 0))
+			continue;
 
 		iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
 
 		/* Get free framebuffer */
 		fbuf = msi3101_get_next_fill_buf(s);
-		if (fbuf == NULL) {
+		if (unlikely(fbuf == NULL)) {
 			s->vb_full++;
 			dev_dbg_ratelimited(&s->udev->dev,
 					"videobuf is full, %d packets dropped\n",
 					s->vb_full);
-			goto skip;
+			continue;
 		}
 
 		/* fill framebuffer */
@@ -1000,13 +977,11 @@ static void msi3101_isoc_handler(struct urb *urb)
 		flen = s->convert_stream(s, ptr, iso_buf, flen);
 		vb2_set_plane_payload(&fbuf->vb, 0, flen);
 		vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
-skip:
-		;
 	}
 
 handler_end:
 	i = usb_submit_urb(urb, GFP_ATOMIC);
-	if (i != 0)
+	if (unlikely(i != 0))
 		dev_dbg(&s->udev->dev,
 				"Error (%d) re-submitting urb in msi3101_isoc_handler\n",
 				i);
@@ -1069,7 +1044,7 @@ static int msi3101_isoc_init(struct msi3101_state *s)
 	udev = s->udev;
 
 	ret = usb_set_interface(s->udev, 0, 1);
-	if (ret < 0)
+	if (ret)
 		return ret;
 
 	/* Allocate and init Isochronuous urbs */
@@ -1202,17 +1177,6 @@ static int msi3101_queue_setup(struct vb2_queue *vq,
 	return 0;
 }
 
-static int msi3101_buf_prepare(struct vb2_buffer *vb)
-{
-	struct msi3101_state *s = vb2_get_drv_priv(vb->vb2_queue);
-
-	/* Don't allow queing new buffers after device disconnection */
-	if (!s->udev)
-		return -ENODEV;
-
-	return 0;
-}
-
 static void msi3101_buf_queue(struct vb2_buffer *vb)
 {
 	struct msi3101_state *s = vb2_get_drv_priv(vb->vb2_queue);
@@ -1221,7 +1185,7 @@ static void msi3101_buf_queue(struct vb2_buffer *vb)
 	unsigned long flags = 0;
 
 	/* Check the device has not disconnected between prep and queuing */
-	if (!s->udev) {
+	if (unlikely(!s->udev)) {
 		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
 		return;
 	}
@@ -1280,7 +1244,7 @@ static int msi3101_set_usb_adc(struct msi3101_state *s)
 	int ret, div_n, div_m, div_r_out, f_sr, f_vco, fract;
 	u32 reg3, reg4, reg7;
 
-	f_sr = s->ctrl_sampling_rate->val64;
+	f_sr = s->f_adc;
 
 	/* select stream format */
 	if (f_sr < 6000000) {
@@ -1455,7 +1419,7 @@ static int msi3101_set_tuner(struct msi3101_state *s)
 		{8000000, 0x07}, /* 8 MHz */
 	};
 
-	unsigned int f_rf = s->ctrl_tuner_rf->val64;
+	unsigned int f_rf = s->f_tuner;
 
 	/*
 	 * bandwidth (Hz)
@@ -1467,7 +1431,7 @@ static int msi3101_set_tuner(struct msi3101_state *s)
 	 * intermediate frequency (Hz)
 	 * 0, 450000, 1620000, 2048000
 	 */
-	unsigned int f_if = s->ctrl_tuner_if->val;
+	unsigned int f_if = 0;
 
 	/*
 	 * gain reduction (dB)
@@ -1680,7 +1644,6 @@ static int msi3101_stop_streaming(struct vb2_queue *vq)
 
 static struct vb2_ops msi3101_vb2_ops = {
 	.queue_setup            = msi3101_queue_setup,
-	.buf_prepare            = msi3101_buf_prepare,
 	.buf_queue              = msi3101_buf_queue,
 	.start_streaming        = msi3101_start_streaming,
 	.stop_streaming         = msi3101_stop_streaming,
@@ -1811,9 +1774,9 @@ static int msi3101_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
 	} 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;
+		v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+		v->rangelow =    49000000;
+		v->rangehigh =  960000000;
 	} else {
 		return -EINVAL;
 	}
@@ -1848,17 +1811,15 @@ static int msi3101_s_frequency(struct file *file, void *priv,
 			__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);
+		dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n",
+				__func__, s->f_adc);
+		ret = msi3101_set_usb_adc(s);
 	} 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);
+		dev_dbg(&s->udev->dev, "%s: RF frequency=%u Hz\n",
+				__func__, f->frequency);
+		ret = msi3101_set_tuner(s);
 	} else {
 		return -EINVAL;
 	}
@@ -1939,6 +1900,7 @@ static struct video_device msi3101_template = {
 	.release                  = video_device_release_empty,
 	.fops                     = &msi3101_fops,
 	.ioctl_ops                = &msi3101_ioctl_ops,
+	.debug                    = 0,
 };
 
 static int msi3101_s_ctrl(struct v4l2_ctrl *ctrl)
@@ -1953,14 +1915,7 @@ static int msi3101_s_ctrl(struct v4l2_ctrl *ctrl)
 			ctrl->minimum, ctrl->maximum, ctrl->step);
 
 	switch (ctrl->id) {
-	case MSI3101_CID_SAMPLING_MODE:
-	case MSI3101_CID_SAMPLING_RATE:
-	case MSI3101_CID_SAMPLING_RESOLUTION:
-		ret = 0;
-		break;
-	case MSI3101_CID_TUNER_RF:
 	case MSI3101_CID_TUNER_BW:
-	case MSI3101_CID_TUNER_IF:
 	case MSI3101_CID_TUNER_GAIN:
 		ret = msi3101_set_tuner(s);
 		break;
@@ -1991,70 +1946,16 @@ static int msi3101_probe(struct usb_interface *intf,
 	struct usb_device *udev = interface_to_usbdev(intf);
 	struct msi3101_state *s = NULL;
 	int ret;
-	static const char * const ctrl_sampling_mode_qmenu_strings[] = {
-		"Quadrature Sampling",
-		NULL,
-	};
-	static const struct v4l2_ctrl_config ctrl_sampling_mode = {
-		.ops	= &msi3101_ctrl_ops,
-		.id	= MSI3101_CID_SAMPLING_MODE,
-		.type   = V4L2_CTRL_TYPE_MENU,
-		.flags  = V4L2_CTRL_FLAG_INACTIVE,
-		.name	= "Sampling Mode",
-		.qmenu  = ctrl_sampling_mode_qmenu_strings,
-	};
-	static const struct v4l2_ctrl_config ctrl_sampling_rate = {
-		.ops	= &msi3101_ctrl_ops,
-		.id	= MSI3101_CID_SAMPLING_RATE,
-		.type	= V4L2_CTRL_TYPE_INTEGER64,
-		.name	= "Sampling Rate",
-		.min	= 500000,
-		.max	= 12000000,
-		.def    = 2048000,
-		.step	= 1,
-	};
-	static const struct v4l2_ctrl_config ctrl_sampling_resolution = {
-		.ops	= &msi3101_ctrl_ops,
-		.id	= MSI3101_CID_SAMPLING_RESOLUTION,
-		.type	= V4L2_CTRL_TYPE_INTEGER,
-		.flags  = V4L2_CTRL_FLAG_INACTIVE,
-		.name	= "Sampling Resolution",
-		.min	= 10,
-		.max	= 10,
-		.def    = 10,
-		.step	= 1,
-	};
-	static const struct v4l2_ctrl_config ctrl_tuner_rf = {
-		.ops	= &msi3101_ctrl_ops,
-		.id	= MSI3101_CID_TUNER_RF,
-		.type   = V4L2_CTRL_TYPE_INTEGER64,
-		.name	= "Tuner RF",
-		.min	= 40000000,
-		.max	= 2000000000,
-		.def    = 100000000,
-		.step	= 1,
-	};
 	static const struct v4l2_ctrl_config ctrl_tuner_bw = {
 		.ops	= &msi3101_ctrl_ops,
 		.id	= MSI3101_CID_TUNER_BW,
 		.type	= V4L2_CTRL_TYPE_INTEGER,
-		.name	= "Tuner BW",
+		.name	= "Tuner Bandwidth",
 		.min	= 200000,
 		.max	= 8000000,
 		.def    = 600000,
 		.step	= 1,
 	};
-	static const struct v4l2_ctrl_config ctrl_tuner_if = {
-		.ops	= &msi3101_ctrl_ops,
-		.id	= MSI3101_CID_TUNER_IF,
-		.type	= V4L2_CTRL_TYPE_INTEGER,
-		.flags  = V4L2_CTRL_FLAG_INACTIVE,
-		.name	= "Tuner IF",
-		.min	= 0,
-		.max	= 2048000,
-		.def    = 0,
-		.step	= 1,
-	};
 	static const struct v4l2_ctrl_config ctrl_tuner_gain = {
 		.ops	= &msi3101_ctrl_ops,
 		.id	= MSI3101_CID_TUNER_GAIN,
@@ -2062,7 +1963,7 @@ static int msi3101_probe(struct usb_interface *intf,
 		.name	= "Tuner Gain",
 		.min	= 0,
 		.max	= 102,
-		.def    = 0,
+		.def    = 50,
 		.step	= 1,
 	};
 
@@ -2088,7 +1989,7 @@ static int msi3101_probe(struct usb_interface *intf,
 	s->vb_queue.mem_ops = &vb2_vmalloc_memops;
 	s->vb_queue.timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 	ret = vb2_queue_init(&s->vb_queue);
-	if (ret < 0) {
+	if (ret) {
 		dev_err(&s->udev->dev, "Could not initialize vb2 queue\n");
 		goto err_free_mem;
 	}
@@ -2101,13 +2002,8 @@ static int msi3101_probe(struct usb_interface *intf,
 	video_set_drvdata(&s->vdev, s);
 
 	/* Register controls */
-	v4l2_ctrl_handler_init(&s->ctrl_handler, 7);
-	v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_sampling_mode, NULL);
-	s->ctrl_sampling_rate = v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_sampling_rate, NULL);
-	v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_sampling_resolution, NULL);
-	s->ctrl_tuner_rf = v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_tuner_rf, NULL);
+	v4l2_ctrl_handler_init(&s->ctrl_handler, 2);
 	s->ctrl_tuner_bw = v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_tuner_bw, NULL);
-	s->ctrl_tuner_if = v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_tuner_if, NULL);
 	s->ctrl_tuner_gain = v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_tuner_gain, NULL);
 	if (s->ctrl_handler.error) {
 		ret = s->ctrl_handler.error;
@@ -2129,7 +2025,7 @@ static int msi3101_probe(struct usb_interface *intf,
 	s->vdev.lock = &s->v4l2_lock;
 
 	ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1);
-	if (ret < 0) {
+	if (ret) {
 		dev_err(&s->udev->dev,
 				"Failed to register as video device (%d)\n",
 				ret);
-- 
1.8.4.2


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

* [PATCH 6/6] v4l: disable lockdep on vb2_fop_mmap()
  2013-12-29  4:51 [PATCH 0/6] convert drivers to SDR API Antti Palosaari
                   ` (4 preceding siblings ...)
  2013-12-29  4:51 ` [PATCH 5/6] msi3101: tons of small changes Antti Palosaari
@ 2013-12-29  4:51 ` Antti Palosaari
  2014-01-17 10:04   ` Hans Verkuil
  5 siblings, 1 reply; 11+ messages in thread
From: Antti Palosaari @ 2013-12-29  4:51 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Antti Palosaari

Avoid that lockdep warning:

[ INFO: possible circular locking dependency detected ]
3.13.0-rc1+ #77 Tainted: G         C O
-------------------------------------------------------
video_source:sr/32072 is trying to acquire lock:
 (&dev->mutex#2){+.+.+.}, at: [<ffffffffa073fde3>] vb2_fop_mmap+0x33/0x90 [videobuf2_core]

                                                but task is already holding lock:
 (&mm->mmap_sem){++++++}, at: [<ffffffff8117825f>] vm_mmap_pgoff+0x6f/0xc0

 Possible unsafe locking scenario:
       CPU0                    CPU1
       ----                    ----
  lock(&mm->mmap_sem);
                               lock(&dev->mutex#2);
                               lock(&mm->mmap_sem);
  lock(&dev->mutex#2);
                                                 *** DEADLOCK ***

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/v4l2-core/videobuf2-core.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 12df9fd..2a74295 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -2641,12 +2641,24 @@ int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
 	struct video_device *vdev = video_devdata(file);
 	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
 	int err;
+	/*
+	 * FIXME: Ugly hack. Disable possible lockdep as it detects possible
+	 * deadlock. "INFO: possible circular locking dependency detected"
+	 */
+	lockdep_off();
 
-	if (lock && mutex_lock_interruptible(lock))
+	if (lock && mutex_lock_interruptible(lock)) {
+		lockdep_on();
 		return -ERESTARTSYS;
+	}
+
 	err = vb2_mmap(vdev->queue, vma);
+
 	if (lock)
 		mutex_unlock(lock);
+
+	lockdep_on();
+
 	return err;
 }
 EXPORT_SYMBOL_GPL(vb2_fop_mmap);
-- 
1.8.4.2


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

* Re: [PATCH 3/6] msi3101: add u8 sample format
  2013-12-29  4:51 ` [PATCH 3/6] msi3101: add u8 sample format Antti Palosaari
@ 2014-01-05 12:14   ` Hans Verkuil
  2014-01-14  1:46     ` Antti Palosaari
  0 siblings, 1 reply; 11+ messages in thread
From: Hans Verkuil @ 2014-01-05 12:14 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: linux-media

On 12/29/2013 05:51 AM, Antti Palosaari wrote:
> Add unsigned 8-bit sample format. Format is got directly from
> hardware, but it is converted from signed to unsigned. It is worst
> known sampling resolution hardware offer.
> 
> Signed-off-by: Antti Palosaari <crope@iki.fi>
> ---
>  drivers/staging/media/msi3101/sdr-msi3101.c | 67 ++++++++++++++++++++++++++++-
>  1 file changed, 66 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
> index 9c54c63..2110488 100644
> --- a/drivers/staging/media/msi3101/sdr-msi3101.c
> +++ b/drivers/staging/media/msi3101/sdr-msi3101.c
> @@ -385,6 +385,7 @@ static const struct msi3101_gain msi3101_gain_lut_1000[] = {
>  #define MSI3101_CID_TUNER_IF              ((V4L2_CID_USER_BASE | 0xf000) + 12)
>  #define MSI3101_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_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 */

These defines should be moved to videodev2.h and documented in DocBook.

Regards,

	Hans

> @@ -428,6 +429,9 @@ struct msi3101_format {
>  /* format descriptions for capture and preview */
>  static struct msi3101_format formats[] = {
>  	{
> +		.name		= "I/Q 8-bit unsigned",
> +		.pixelformat	= V4L2_PIX_FMT_SDR_U8,
> +	}, {
>  		.name		= "I/Q 8-bit signed",
>  		.pixelformat	= V4L2_PIX_FMT_SDR_S8,
>  	}, {
> @@ -487,6 +491,7 @@ struct msi3101_state {
>  	u32 next_sample; /* for track lost packets */
>  	u32 sample; /* for sample rate calc */
>  	unsigned long jiffies;
> +	unsigned long jiffies_next;
>  	unsigned int sample_ctrl_bit[4];
>  };
>  
> @@ -572,6 +577,63 @@ static int msi3101_convert_stream_504(struct msi3101_state *s, u8 *dst,
>  	return dst_len;
>  }
>  
> +static int msi3101_convert_stream_504_u8(struct msi3101_state *s, u8 *dst,
> +		u8 *src, unsigned int src_len)
> +{
> +	int i, j, i_max, dst_len = 0;
> +	u32 sample_num[3];
> +	s8 *s8src;
> +	u8 *u8dst;
> +
> +	/* There could be 1-3 1024 bytes URB frames */
> +	i_max = src_len / 1024;
> +	u8dst = (u8 *) dst;
> +
> +	for (i = 0; i < i_max; i++) {
> +		sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0;
> +		if (i == 0 && s->next_sample != sample_num[0]) {
> +			dev_dbg_ratelimited(&s->udev->dev,
> +					"%d samples lost, %d %08x:%08x\n",
> +					sample_num[0] - s->next_sample,
> +					src_len, s->next_sample, sample_num[0]);
> +		}
> +
> +		/*
> +		 * Dump all unknown 'garbage' data - maybe we will discover
> +		 * someday if there is something rational...
> +		 */
> +		dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]);
> +
> +		/* 504 x I+Q samples */
> +		src += 16;
> +
> +		s8src = (s8 *) src;
> +		for (j = 0; j < 1008; j++)
> +			*u8dst++ = *s8src++ + 128;
> +
> +		src += 1008;
> +		dst += 1008;
> +		dst_len += 1008;
> +	}
> +
> +	/* calculate samping rate and output it in 10 seconds intervals */
> +	if (unlikely(time_is_before_jiffies(s->jiffies_next))) {
> +#define MSECS 10000UL
> +		unsigned int samples = sample_num[i_max - 1] - s->sample;
> +		s->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
> +		s->sample = sample_num[i_max - 1];
> +		dev_dbg(&s->udev->dev,
> +				"slen=%d samples=%u msecs=%lu sampling rate=%lu\n",
> +				src_len, samples, MSECS,
> +				samples * 1000UL / MSECS);
> +	}
> +
> +	/* next sample (sample = sample + i * 504) */
> +	s->next_sample = sample_num[i_max - 1] + 504;
> +
> +	return dst_len;
> +}
> +
>  /*
>   * +===========================================================================
>   * |   00-1023 | USB packet type '384'
> @@ -1159,7 +1221,10 @@ static int msi3101_set_usb_adc(struct msi3101_state *s)
>  		reg7 = 0x000c9407;
>  	}
>  
> -	if (s->pixelformat == V4L2_PIX_FMT_SDR_S8) {
> +	if (s->pixelformat == V4L2_PIX_FMT_SDR_U8) {
> +		s->convert_stream = msi3101_convert_stream_504_u8;
> +		reg7 = 0x000c9407;
> +	} else if (s->pixelformat == V4L2_PIX_FMT_SDR_S8) {
>  		s->convert_stream = msi3101_convert_stream_504;
>  		reg7 = 0x000c9407;
>  	} else if (s->pixelformat == V4L2_PIX_FMT_SDR_MSI2500_384) {
> 


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

* Re: [PATCH 3/6] msi3101: add u8 sample format
  2014-01-05 12:14   ` Hans Verkuil
@ 2014-01-14  1:46     ` Antti Palosaari
  0 siblings, 0 replies; 11+ messages in thread
From: Antti Palosaari @ 2014-01-14  1:46 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

On 05.01.2014 14:14, Hans Verkuil wrote:
> On 12/29/2013 05:51 AM, Antti Palosaari wrote:
>> Add unsigned 8-bit sample format. Format is got directly from
>> hardware, but it is converted from signed to unsigned. It is worst
>> known sampling resolution hardware offer.
>>
>> Signed-off-by: Antti Palosaari <crope@iki.fi>
>> ---
>>   drivers/staging/media/msi3101/sdr-msi3101.c | 67 ++++++++++++++++++++++++++++-
>>   1 file changed, 66 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
>> index 9c54c63..2110488 100644
>> --- a/drivers/staging/media/msi3101/sdr-msi3101.c
>> +++ b/drivers/staging/media/msi3101/sdr-msi3101.c
>> @@ -385,6 +385,7 @@ static const struct msi3101_gain msi3101_gain_lut_1000[] = {
>>   #define MSI3101_CID_TUNER_IF              ((V4L2_CID_USER_BASE | 0xf000) + 12)
>>   #define MSI3101_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_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 */
>
> These defines should be moved to videodev2.h and documented in DocBook.

Indeed, but that driver is still on staging. I will move those later...

regards
Antti


-- 
http://palosaari.fi/

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

* Re: [PATCH 6/6] v4l: disable lockdep on vb2_fop_mmap()
  2013-12-29  4:51 ` [PATCH 6/6] v4l: disable lockdep on vb2_fop_mmap() Antti Palosaari
@ 2014-01-17 10:04   ` Hans Verkuil
  2014-01-17 15:14     ` Antti Palosaari
  0 siblings, 1 reply; 11+ messages in thread
From: Hans Verkuil @ 2014-01-17 10:04 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: linux-media

Hi Antti,

Is this still needed after this commit was merged?

http://git.linuxtv.org/media_tree.git/commit/b18a8ff29d80b132018d33479e86ab8ecaee6b46

Regards,

	Hans

On 12/29/2013 05:51 AM, Antti Palosaari wrote:
> Avoid that lockdep warning:
> 
> [ INFO: possible circular locking dependency detected ]
> 3.13.0-rc1+ #77 Tainted: G         C O
> -------------------------------------------------------
> video_source:sr/32072 is trying to acquire lock:
>  (&dev->mutex#2){+.+.+.}, at: [<ffffffffa073fde3>] vb2_fop_mmap+0x33/0x90 [videobuf2_core]
> 
>                                                 but task is already holding lock:
>  (&mm->mmap_sem){++++++}, at: [<ffffffff8117825f>] vm_mmap_pgoff+0x6f/0xc0
> 
>  Possible unsafe locking scenario:
>        CPU0                    CPU1
>        ----                    ----
>   lock(&mm->mmap_sem);
>                                lock(&dev->mutex#2);
>                                lock(&mm->mmap_sem);
>   lock(&dev->mutex#2);
>                                                  *** DEADLOCK ***
> 
> Signed-off-by: Antti Palosaari <crope@iki.fi>
> ---
>  drivers/media/v4l2-core/videobuf2-core.c | 14 +++++++++++++-
>  1 file changed, 13 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
> index 12df9fd..2a74295 100644
> --- a/drivers/media/v4l2-core/videobuf2-core.c
> +++ b/drivers/media/v4l2-core/videobuf2-core.c
> @@ -2641,12 +2641,24 @@ int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
>  	struct video_device *vdev = video_devdata(file);
>  	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
>  	int err;
> +	/*
> +	 * FIXME: Ugly hack. Disable possible lockdep as it detects possible
> +	 * deadlock. "INFO: possible circular locking dependency detected"
> +	 */
> +	lockdep_off();
>  
> -	if (lock && mutex_lock_interruptible(lock))
> +	if (lock && mutex_lock_interruptible(lock)) {
> +		lockdep_on();
>  		return -ERESTARTSYS;
> +	}
> +
>  	err = vb2_mmap(vdev->queue, vma);
> +
>  	if (lock)
>  		mutex_unlock(lock);
> +
> +	lockdep_on();
> +
>  	return err;
>  }
>  EXPORT_SYMBOL_GPL(vb2_fop_mmap);
> 


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

* Re: [PATCH 6/6] v4l: disable lockdep on vb2_fop_mmap()
  2014-01-17 10:04   ` Hans Verkuil
@ 2014-01-17 15:14     ` Antti Palosaari
  0 siblings, 0 replies; 11+ messages in thread
From: Antti Palosaari @ 2014-01-17 15:14 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

Hi Hans

On 17.01.2014 12:04, Hans Verkuil wrote:
> Hi Antti,
>
> Is this still needed after this commit was merged?
>
> http://git.linuxtv.org/media_tree.git/commit/b18a8ff29d80b132018d33479e86ab8ecaee6b46

It didn't fix the problem.

I could reproduce that issue easily using vivi and Cheese (webcam app).

1) Compile Kernel with lockdep debug. For me these seems to be enabled:
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_LOCKDEP=y
CONFIG_DEBUG_LOCKDEP=y

2) Load virtual video driver (vivi)
# modprobe vivi

3) Start Cheese
$ cheese

Lockdep error appears to system log just after Cheese is started. I 
think it is related to mmap.

regards
Antti


tammi 17 17:07:38 localhost.localdomain kernel: media: Linux media 
interface: v0.10
tammi 17 17:07:38 localhost.localdomain kernel: Linux video capture 
interface: v2.00
tammi 17 17:07:38 localhost.localdomain kernel: vivi-000: V4L2 device 
registered as video0
tammi 17 17:07:38 localhost.localdomain kernel: Video Technology 
Magazine Virtual Video Capture Board ver 0.8.1 successfully loaded.
tammi 17 17:07:50 localhost.localdomain /etc/gdm/Xsession[1521]: Window 
manager warning: Buggy client sent a _NET_ACTIVE_WINDOW message with a 
timestamp of 0 for 0x3200024 (Cheese)
tammi 17 17:07:50 localhost.localdomain /etc/gdm/Xsession[1521]: Window 
manager warning: meta_window_activate called by a pager with a 0 
timestamp; the pager needs to be fixed.
tammi 17 17:07:50 localhost.localdomain kernel: tammi 17 17:07:50 
localhost.localdomain kernel: 
======================================================
tammi 17 17:07:50 localhost.localdomain kernel: [ INFO: possible 
circular locking dependency detected ]
tammi 17 17:07:50 localhost.localdomain kernel: 3.13.0-rc1+ #79 Tainted: 
G         C O
tammi 17 17:07:50 localhost.localdomain kernel: 
-------------------------------------------------------
tammi 17 17:07:50 localhost.localdomain kernel: video_source:sr/8871 is 
trying to acquire lock:
tammi 17 17:07:50 localhost.localdomain kernel: 
(&dev->mutex#2){+.+.+.}, at: [<ffffffffa06a8df3>] vb2_fop_mmap+0x33/0x90 
[videobuf2_core]
tammi 17 17:07:50 localhost.localdomain kernel:
                                                 but task is already 
holding lock:
tammi 17 17:07:50 localhost.localdomain kernel: 
(&mm->mmap_sem){++++++}, at: [<ffffffff8117825f>] vm_mmap_pgoff+0x6f/0xc0
tammi 17 17:07:50 localhost.localdomain kernel:
                                                 which lock already 
depends on the new lock.
tammi 17 17:07:50 localhost.localdomain kernel:
                                                 the existing dependency 
chain (in reverse order) is:
tammi 17 17:07:50 localhost.localdomain kernel:
                                                 -> #1 
(&mm->mmap_sem){++++++}:
tammi 17 17:07:50 localhost.localdomain kernel: 
[<ffffffff810bb386>] __lock_acquire+0x3d6/0xc40
tammi 17 17:07:50 localhost.localdomain kernel: 
[<ffffffff810bbca0>] lock_acquire+0xb0/0x150
tammi 17 17:07:50 localhost.localdomain kernel: 
[<ffffffff81181f3c>] might_fault+0x8c/0xb0
tammi 17 17:07:50 localhost.localdomain kernel: 
[<ffffffffa067dc15>] video_usercopy+0x375/0x5e0 [videodev]
tammi 17 17:07:50 localhost.localdomain kernel: 
[<ffffffffa067de95>] video_ioctl2+0x15/0x20 [videodev]
tammi 17 17:07:50 localhost.localdomain kernel: 
[<ffffffffa0677703>] v4l2_ioctl+0x123/0x160 [videodev]
tammi 17 17:07:50 localhost.localdomain kernel: 
[<ffffffff811e0590>] do_vfs_ioctl+0x300/0x520
tammi 17 17:07:50 localhost.localdomain kernel: 
[<ffffffff811e0831>] SyS_ioctl+0x81/0xa0
tammi 17 17:07:50 localhost.localdomain kernel: 
[<ffffffff816ca729>] system_call_fastpath+0x16/0x1b
tammi 17 17:07:50 localhost.localdomain kernel:
                                                 -> #0 
(&dev->mutex#2){+.+.+.}:
tammi 17 17:07:50 localhost.localdomain kernel: 
[<ffffffff810b96b7>] validate_chain.isra.36+0x10d7/0x1130
tammi 17 17:07:50 localhost.localdomain kernel: 
[<ffffffff810bb386>] __lock_acquire+0x3d6/0xc40
tammi 17 17:07:50 localhost.localdomain kernel: 
[<ffffffff810bbca0>] lock_acquire+0xb0/0x150
tammi 17 17:07:50 localhost.localdomain kernel: 
[<ffffffff816bf1c7>] mutex_lock_interruptible_nested+0x77/0x460
tammi 17 17:07:50 localhost.localdomain kernel: 
[<ffffffffa06a8df3>] vb2_fop_mmap+0x33/0x90 [videobuf2_core]
tammi 17 17:07:50 localhost.localdomain kernel: 
[<ffffffffa067711a>] v4l2_mmap+0x5a/0xa0 [videodev]
tammi 17 17:07:50 localhost.localdomain kernel: 
[<ffffffff8118da7d>] mmap_region+0x3cd/0x5a0
tammi 17 17:07:50 localhost.localdomain kernel: 
[<ffffffff8118dfa7>] do_mmap_pgoff+0x357/0x3e0
tammi 17 17:07:50 localhost.localdomain kernel: 
[<ffffffff81178280>] vm_mmap_pgoff+0x90/0xc0
tammi 17 17:07:50 localhost.localdomain kernel: 
[<ffffffff8118c553>] SyS_mmap_pgoff+0x1d3/0x270
tammi 17 17:07:50 localhost.localdomain kernel: 
[<ffffffff810191a2>] SyS_mmap+0x22/0x30
tammi 17 17:07:50 localhost.localdomain kernel: 
[<ffffffff816ca729>] system_call_fastpath+0x16/0x1b
tammi 17 17:07:50 localhost.localdomain kernel:
                                                 other info that might 
help us debug this:
tammi 17 17:07:50 localhost.localdomain kernel:  Possible unsafe locking 
scenario:
tammi 17 17:07:50 localhost.localdomain kernel:        CPU0 
        CPU1
tammi 17 17:07:50 localhost.localdomain kernel:        ---- 
        ----
tammi 17 17:07:50 localhost.localdomain kernel:   lock(&mm->mmap_sem);
tammi 17 17:07:50 localhost.localdomain kernel: 
        lock(&dev->mutex#2);
tammi 17 17:07:50 localhost.localdomain kernel: 
        lock(&mm->mmap_sem);
tammi 17 17:07:50 localhost.localdomain kernel:   lock(&dev->mutex#2);
tammi 17 17:07:50 localhost.localdomain kernel:
                                                  *** DEADLOCK ***
tammi 17 17:07:50 localhost.localdomain kernel: 1 lock held by 
video_source:sr/8871:
tammi 17 17:07:50 localhost.localdomain kernel:  #0: 
(&mm->mmap_sem){++++++}, at: [<ffffffff8117825f>] vm_mmap_pgoff+0x6f/0xc0
tammi 17 17:07:50 localhost.localdomain kernel:
                                                 stack backtrace:
tammi 17 17:07:50 localhost.localdomain kernel: CPU: 3 PID: 8871 Comm: 
video_source:sr Tainted: G         C O 3.13.0-rc1+ #79
tammi 17 17:07:50 localhost.localdomain kernel: Hardware name: System 
manufacturer System Product Name/M5A78L-M/USB3, BIOS 1801    11/12/2013
tammi 17 17:07:50 localhost.localdomain kernel:  ffffffff824f9bd0 
ffff880083075b68 ffffffff816b8da9 ffffffff824f9bd0
tammi 17 17:07:50 localhost.localdomain kernel:  ffff880083075ba8 
ffffffff816b2c9b ffff880083075be0 0000000000000000
tammi 17 17:07:50 localhost.localdomain kernel:  ffff8801ee6fc378 
0000000000000001 ffff8801ee6fbcf0 ffff8801ee6fc378
tammi 17 17:07:50 localhost.localdomain kernel: Call Trace:
tammi 17 17:07:50 localhost.localdomain kernel:  [<ffffffff816b8da9>] 
dump_stack+0x4d/0x66
tammi 17 17:07:50 localhost.localdomain kernel:  [<ffffffff816b2c9b>] 
print_circular_bug+0x200/0x20e
tammi 17 17:07:50 localhost.localdomain kernel:  [<ffffffff810b96b7>] 
validate_chain.isra.36+0x10d7/0x1130
tammi 17 17:07:50 localhost.localdomain kernel:  [<ffffffff810bb3a7>] ? 
__lock_acquire+0x3f7/0xc40
tammi 17 17:07:50 localhost.localdomain kernel:  [<ffffffff8101c413>] ? 
native_sched_clock+0x13/0x80
tammi 17 17:07:50 localhost.localdomain kernel:  [<ffffffff810bb386>] 
__lock_acquire+0x3d6/0xc40
tammi 17 17:07:50 localhost.localdomain kernel:  [<ffffffff8101c413>] ? 
native_sched_clock+0x13/0x80
tammi 17 17:07:50 localhost.localdomain kernel:  [<ffffffff8101c489>] ? 
sched_clock+0x9/0x10
tammi 17 17:07:50 localhost.localdomain kernel:  [<ffffffff810bbca0>] 
lock_acquire+0xb0/0x150
tammi 17 17:07:50 localhost.localdomain kernel:  [<ffffffffa06a8df3>] ? 
vb2_fop_mmap+0x33/0x90 [videobuf2_core]
tammi 17 17:07:50 localhost.localdomain kernel:  [<ffffffff816bf1c7>] 
mutex_lock_interruptible_nested+0x77/0x460
tammi 17 17:07:50 localhost.localdomain kernel:  [<ffffffffa06a8df3>] ? 
vb2_fop_mmap+0x33/0x90 [videobuf2_core]
tammi 17 17:07:50 localhost.localdomain kernel:  [<ffffffffa06a8df3>] ? 
vb2_fop_mmap+0x33/0x90 [videobuf2_core]
tammi 17 17:07:50 localhost.localdomain kernel:  [<ffffffffa06a8df3>] 
vb2_fop_mmap+0x33/0x90 [videobuf2_core]
tammi 17 17:07:50 localhost.localdomain kernel:  [<ffffffffa067711a>] 
v4l2_mmap+0x5a/0xa0 [videodev]
tammi 17 17:07:50 localhost.localdomain kernel:  [<ffffffff8118da7d>] 
mmap_region+0x3cd/0x5a0
tammi 17 17:07:50 localhost.localdomain kernel:  [<ffffffff8118dfa7>] 
do_mmap_pgoff+0x357/0x3e0
tammi 17 17:07:50 localhost.localdomain kernel:  [<ffffffff81178280>] 
vm_mmap_pgoff+0x90/0xc0
tammi 17 17:07:50 localhost.localdomain kernel:  [<ffffffff8118c553>] 
SyS_mmap_pgoff+0x1d3/0x270
tammi 17 17:07:50 localhost.localdomain kernel:  [<ffffffff810191a2>] 
SyS_mmap+0x22/0x30
tammi 17 17:07:50 localhost.localdomain kernel:  [<ffffffff816ca729>] 
system_call_fastpath+0x16/0x1b





>
> Regards,
>
> 	Hans
>
> On 12/29/2013 05:51 AM, Antti Palosaari wrote:
>> Avoid that lockdep warning:
>>
>> [ INFO: possible circular locking dependency detected ]
>> 3.13.0-rc1+ #77 Tainted: G         C O
>> -------------------------------------------------------
>> video_source:sr/32072 is trying to acquire lock:
>>   (&dev->mutex#2){+.+.+.}, at: [<ffffffffa073fde3>] vb2_fop_mmap+0x33/0x90 [videobuf2_core]
>>
>>                                                  but task is already holding lock:
>>   (&mm->mmap_sem){++++++}, at: [<ffffffff8117825f>] vm_mmap_pgoff+0x6f/0xc0
>>
>>   Possible unsafe locking scenario:
>>         CPU0                    CPU1
>>         ----                    ----
>>    lock(&mm->mmap_sem);
>>                                 lock(&dev->mutex#2);
>>                                 lock(&mm->mmap_sem);
>>    lock(&dev->mutex#2);
>>                                                   *** DEADLOCK ***
>>
>> Signed-off-by: Antti Palosaari <crope@iki.fi>
>> ---
>>   drivers/media/v4l2-core/videobuf2-core.c | 14 +++++++++++++-
>>   1 file changed, 13 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
>> index 12df9fd..2a74295 100644
>> --- a/drivers/media/v4l2-core/videobuf2-core.c
>> +++ b/drivers/media/v4l2-core/videobuf2-core.c
>> @@ -2641,12 +2641,24 @@ int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
>>   	struct video_device *vdev = video_devdata(file);
>>   	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
>>   	int err;
>> +	/*
>> +	 * FIXME: Ugly hack. Disable possible lockdep as it detects possible
>> +	 * deadlock. "INFO: possible circular locking dependency detected"
>> +	 */
>> +	lockdep_off();
>>
>> -	if (lock && mutex_lock_interruptible(lock))
>> +	if (lock && mutex_lock_interruptible(lock)) {
>> +		lockdep_on();
>>   		return -ERESTARTSYS;
>> +	}
>> +
>>   	err = vb2_mmap(vdev->queue, vma);
>> +
>>   	if (lock)
>>   		mutex_unlock(lock);
>> +
>> +	lockdep_on();
>> +
>>   	return err;
>>   }
>>   EXPORT_SYMBOL_GPL(vb2_fop_mmap);
>>
>


-- 
http://palosaari.fi/

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

end of thread, other threads:[~2014-01-17 15:14 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-29  4:51 [PATCH 0/6] convert drivers to SDR API Antti Palosaari
2013-12-29  4:51 ` [PATCH 1/6] rtl2832_sdr: convert " Antti Palosaari
2013-12-29  4:51 ` [PATCH 2/6] msi3101: " Antti Palosaari
2013-12-29  4:51 ` [PATCH 3/6] msi3101: add u8 sample format Antti Palosaari
2014-01-05 12:14   ` Hans Verkuil
2014-01-14  1:46     ` Antti Palosaari
2013-12-29  4:51 ` [PATCH 4/6] msi3101: add u16 LE " Antti Palosaari
2013-12-29  4:51 ` [PATCH 5/6] msi3101: tons of small changes Antti Palosaari
2013-12-29  4:51 ` [PATCH 6/6] v4l: disable lockdep on vb2_fop_mmap() Antti Palosaari
2014-01-17 10:04   ` Hans Verkuil
2014-01-17 15:14     ` Antti Palosaari

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