All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] airspy: remove v4l2-compliance workaround
@ 2014-07-18  1:05 Antti Palosaari
  2014-07-18  1:05 ` [PATCH 2/4] airspy: move out of staging into drivers/media/usb Antti Palosaari
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Antti Palosaari @ 2014-07-18  1:05 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari, Hans Verkuil

v4l2-compliance is now happy with frequency ranges where both lower
and upper limit is same.

Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/staging/media/airspy/airspy.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/media/airspy/airspy.c b/drivers/staging/media/airspy/airspy.c
index daecd91..5b3310f 100644
--- a/drivers/staging/media/airspy/airspy.c
+++ b/drivers/staging/media/airspy/airspy.c
@@ -62,7 +62,7 @@ static const struct v4l2_frequency_band bands[] = {
 		.index = 0,
 		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
 		.rangelow   = 20000000,
-		.rangehigh  = 20000001, /* FIXME: make v4l2-compliance happy */
+		.rangehigh  = 20000000,
 	},
 };
 
-- 
1.9.3


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

* [PATCH 2/4] airspy: move out of staging into drivers/media/usb
  2014-07-18  1:05 [PATCH 1/4] airspy: remove v4l2-compliance workaround Antti Palosaari
@ 2014-07-18  1:05 ` Antti Palosaari
  2014-07-18  1:05 ` [PATCH 3/4] airspy: print notice to point SDR API is not 100% stable yet Antti Palosaari
  2014-07-18  1:05 ` [PATCH 4/4] MAINTAINERS: add airspy driver Antti Palosaari
  2 siblings, 0 replies; 6+ messages in thread
From: Antti Palosaari @ 2014-07-18  1:05 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Move it out of staging into media like all the other SDR drivers
too. There is no good reasons to keep these SDR drivers in staging.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/usb/Kconfig             |    1 +
 drivers/media/usb/Makefile            |    1 +
 drivers/media/usb/airspy/Kconfig      |   10 +
 drivers/media/usb/airspy/Makefile     |    1 +
 drivers/media/usb/airspy/airspy.c     | 1120 +++++++++++++++++++++++++++++++++
 drivers/staging/media/Kconfig         |    1 -
 drivers/staging/media/Makefile        |    1 -
 drivers/staging/media/airspy/Kconfig  |    5 -
 drivers/staging/media/airspy/Makefile |    1 -
 drivers/staging/media/airspy/airspy.c | 1120 ---------------------------------
 10 files changed, 1133 insertions(+), 1128 deletions(-)
 create mode 100644 drivers/media/usb/airspy/Kconfig
 create mode 100644 drivers/media/usb/airspy/Makefile
 create mode 100644 drivers/media/usb/airspy/airspy.c
 delete mode 100644 drivers/staging/media/airspy/Kconfig
 delete mode 100644 drivers/staging/media/airspy/Makefile
 delete mode 100644 drivers/staging/media/airspy/airspy.c

diff --git a/drivers/media/usb/Kconfig b/drivers/media/usb/Kconfig
index e274cb9..fa67519 100644
--- a/drivers/media/usb/Kconfig
+++ b/drivers/media/usb/Kconfig
@@ -55,6 +55,7 @@ endif
 if MEDIA_SDR_SUPPORT
 	comment "Software defined radio USB devices"
 source "drivers/media/usb/msi2500/Kconfig"
+source "drivers/media/usb/airspy/Kconfig"
 endif
 
 endif #MEDIA_USB_SUPPORT
diff --git a/drivers/media/usb/Makefile b/drivers/media/usb/Makefile
index 6ba6c1ee..36647c5 100644
--- a/drivers/media/usb/Makefile
+++ b/drivers/media/usb/Makefile
@@ -9,6 +9,7 @@ obj-y += zr364xx/ stkwebcam/ s2255/
 obj-$(CONFIG_USB_VIDEO_CLASS)	+= uvc/
 obj-$(CONFIG_USB_GSPCA)         += gspca/
 obj-$(CONFIG_USB_PWC)           += pwc/
+obj-$(CONFIG_USB_AIRSPY)        += airspy/
 obj-$(CONFIG_USB_MSI2500)       += msi2500/
 obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
 obj-$(CONFIG_VIDEO_AU0828) += au0828/
diff --git a/drivers/media/usb/airspy/Kconfig b/drivers/media/usb/airspy/Kconfig
new file mode 100644
index 0000000..10b204c
--- /dev/null
+++ b/drivers/media/usb/airspy/Kconfig
@@ -0,0 +1,10 @@
+config USB_AIRSPY
+	tristate "AirSpy"
+	depends on VIDEO_V4L2
+	select VIDEOBUF2_VMALLOC
+	---help---
+	  This is a video4linux2 driver for AirSpy SDR device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called airspy
+
diff --git a/drivers/media/usb/airspy/Makefile b/drivers/media/usb/airspy/Makefile
new file mode 100644
index 0000000..8d8e61c
--- /dev/null
+++ b/drivers/media/usb/airspy/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_USB_AIRSPY)              += airspy.o
diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c
new file mode 100644
index 0000000..5b3310f
--- /dev/null
+++ b/drivers/media/usb/airspy/airspy.c
@@ -0,0 +1,1120 @@
+/*
+ * AirSpy SDR driver
+ *
+ * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf2-vmalloc.h>
+
+/* AirSpy USB API commands (from AirSpy Library) */
+enum {
+	CMD_INVALID                       = 0x00,
+	CMD_RECEIVER_MODE                 = 0x01,
+	CMD_SI5351C_WRITE                 = 0x02,
+	CMD_SI5351C_READ                  = 0x03,
+	CMD_R820T_WRITE                   = 0x04,
+	CMD_R820T_READ                    = 0x05,
+	CMD_SPIFLASH_ERASE                = 0x06,
+	CMD_SPIFLASH_WRITE                = 0x07,
+	CMD_SPIFLASH_READ                 = 0x08,
+	CMD_BOARD_ID_READ                 = 0x09,
+	CMD_VERSION_STRING_READ           = 0x0a,
+	CMD_BOARD_PARTID_SERIALNO_READ    = 0x0b,
+	CMD_SET_SAMPLE_RATE               = 0x0c,
+	CMD_SET_FREQ                      = 0x0d,
+	CMD_SET_LNA_GAIN                  = 0x0e,
+	CMD_SET_MIXER_GAIN                = 0x0f,
+	CMD_SET_VGA_GAIN                  = 0x10,
+	CMD_SET_LNA_AGC                   = 0x11,
+	CMD_SET_MIXER_AGC                 = 0x12,
+	CMD_SET_PACKING                   = 0x13,
+};
+
+/*
+ *       bEndpointAddress     0x81  EP 1 IN
+ *         Transfer Type            Bulk
+ *       wMaxPacketSize     0x0200  1x 512 bytes
+ */
+#define MAX_BULK_BUFS            (6)
+#define BULK_BUFFER_SIZE         (128 * 512)
+
+static const struct v4l2_frequency_band bands[] = {
+	{
+		.tuner = 0,
+		.type = V4L2_TUNER_ADC,
+		.index = 0,
+		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow   = 20000000,
+		.rangehigh  = 20000000,
+	},
+};
+
+static const struct v4l2_frequency_band bands_rf[] = {
+	{
+		.tuner = 1,
+		.type = V4L2_TUNER_RF,
+		.index = 0,
+		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow   =   24000000,
+		.rangehigh  = 1750000000,
+	},
+};
+
+/* stream formats */
+struct airspy_format {
+	char	*name;
+	u32	pixelformat;
+};
+
+/* format descriptions for capture and preview */
+static struct airspy_format formats[] = {
+	{
+		.name		= "Real U12LE",
+		.pixelformat	=  V4L2_SDR_FMT_RU12LE,
+	},
+};
+
+static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
+
+/* intermediate buffers with raw data from the USB device */
+struct airspy_frame_buf {
+	struct vb2_buffer vb;   /* common v4l buffer stuff -- must be first */
+	struct list_head list;
+};
+
+struct airspy {
+#define POWER_ON           (1 << 1)
+#define URB_BUF            (1 << 2)
+#define USB_STATE_URB_BUF  (1 << 3)
+	unsigned long flags;
+
+	struct usb_device *udev;
+	struct video_device vdev;
+	struct v4l2_device v4l2_dev;
+
+	/* videobuf2 queue and queued buffers list */
+	struct vb2_queue vb_queue;
+	struct list_head queued_bufs;
+	spinlock_t queued_bufs_lock; /* Protects queued_bufs */
+	unsigned sequence;	     /* Buffer sequence counter */
+	unsigned int vb_full;        /* vb is full and packets dropped */
+
+	/* Note if taking both locks v4l2_lock must always be locked first! */
+	struct mutex v4l2_lock;      /* Protects everything else */
+	struct mutex vb_queue_lock;  /* Protects vb_queue and capt_file */
+
+	struct urb     *urb_list[MAX_BULK_BUFS];
+	int            buf_num;
+	unsigned long  buf_size;
+	u8             *buf_list[MAX_BULK_BUFS];
+	dma_addr_t     dma_addr[MAX_BULK_BUFS];
+	int            urbs_initialized;
+	int            urbs_submitted;
+
+	/* USB control message buffer */
+	#define BUF_SIZE 24
+	u8 buf[BUF_SIZE];
+
+	/* Current configuration */
+	unsigned int f_adc;
+	unsigned int f_rf;
+	u32 pixelformat;
+
+	/* Controls */
+	struct v4l2_ctrl_handler hdl;
+	struct v4l2_ctrl *lna_gain_auto;
+	struct v4l2_ctrl *lna_gain;
+	struct v4l2_ctrl *mixer_gain_auto;
+	struct v4l2_ctrl *mixer_gain;
+	struct v4l2_ctrl *if_gain;
+
+	/* Sample rate calc */
+	unsigned long jiffies_next;
+	unsigned int sample;
+	unsigned int sample_measured;
+};
+
+#define airspy_dbg_usb_control_msg(_udev, _r, _t, _v, _i, _b, _l) { \
+	char *_direction; \
+	if (_t & USB_DIR_IN) \
+		_direction = "<<<"; \
+	else \
+		_direction = ">>>"; \
+	dev_dbg(&_udev->dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x " \
+			"%s %*ph\n",  __func__, _t, _r, _v & 0xff, _v >> 8, \
+			_i & 0xff, _i >> 8, _l & 0xff, _l >> 8, _direction, \
+			_l, _b); \
+}
+
+/* execute firmware command */
+static int airspy_ctrl_msg(struct airspy *s, u8 request, u16 value, u16 index,
+		u8 *data, u16 size)
+{
+	int ret;
+	unsigned int pipe;
+	u8 requesttype;
+
+	switch (request) {
+	case CMD_RECEIVER_MODE:
+	case CMD_SET_FREQ:
+		pipe = usb_sndctrlpipe(s->udev, 0);
+		requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
+		break;
+	case CMD_BOARD_ID_READ:
+	case CMD_VERSION_STRING_READ:
+	case CMD_BOARD_PARTID_SERIALNO_READ:
+	case CMD_SET_LNA_GAIN:
+	case CMD_SET_MIXER_GAIN:
+	case CMD_SET_VGA_GAIN:
+	case CMD_SET_LNA_AGC:
+	case CMD_SET_MIXER_AGC:
+		pipe = usb_rcvctrlpipe(s->udev, 0);
+		requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
+		break;
+	default:
+		dev_err(&s->udev->dev, "Unknown command %02x\n", request);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/* write request */
+	if (!(requesttype & USB_DIR_IN))
+		memcpy(s->buf, data, size);
+
+	ret = usb_control_msg(s->udev, pipe, request, requesttype, value,
+			index, s->buf, size, 1000);
+	airspy_dbg_usb_control_msg(s->udev, request, requesttype, value,
+			index, s->buf, size);
+	if (ret < 0) {
+		dev_err(&s->udev->dev,
+				"usb_control_msg() failed %d request %02x\n",
+				ret, request);
+		goto err;
+	}
+
+	/* read request */
+	if (requesttype & USB_DIR_IN)
+		memcpy(data, s->buf, size);
+
+	return 0;
+err:
+	return ret;
+}
+
+/* Private functions */
+static struct airspy_frame_buf *airspy_get_next_fill_buf(struct airspy *s)
+{
+	unsigned long flags = 0;
+	struct airspy_frame_buf *buf = NULL;
+
+	spin_lock_irqsave(&s->queued_bufs_lock, flags);
+	if (list_empty(&s->queued_bufs))
+		goto leave;
+
+	buf = list_entry(s->queued_bufs.next,
+			struct airspy_frame_buf, list);
+	list_del(&buf->list);
+leave:
+	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
+	return buf;
+}
+
+static unsigned int airspy_convert_stream(struct airspy *s,
+		void *dst, void *src, unsigned int src_len)
+{
+	unsigned int dst_len;
+
+	if (s->pixelformat == V4L2_SDR_FMT_RU12LE) {
+		memcpy(dst, src, src_len);
+		dst_len = src_len;
+	} else {
+		dst_len = 0;
+	}
+
+	/* 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 = s->sample - s->sample_measured;
+		s->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
+		s->sample_measured = s->sample;
+		dev_dbg(&s->udev->dev,
+				"slen=%d samples=%u msecs=%lu sample rate=%lu\n",
+				src_len, samples, MSECS,
+				samples * 1000UL / MSECS);
+	}
+
+	/* total number of samples */
+	s->sample += src_len / 2;
+
+	return dst_len;
+}
+
+/*
+ * This gets called for the bulk stream pipe. This is done in interrupt
+ * time, so it has to be fast, not crash, and not stall. Neat.
+ */
+static void airspy_urb_complete(struct urb *urb)
+{
+	struct airspy *s = urb->context;
+	struct airspy_frame_buf *fbuf;
+
+	dev_dbg_ratelimited(&s->udev->dev,
+			"%s: status=%d length=%d/%d errors=%d\n",
+			__func__, urb->status, urb->actual_length,
+			urb->transfer_buffer_length, urb->error_count);
+
+	switch (urb->status) {
+	case 0:             /* success */
+	case -ETIMEDOUT:    /* NAK */
+		break;
+	case -ECONNRESET:   /* kill */
+	case -ENOENT:
+	case -ESHUTDOWN:
+		return;
+	default:            /* error */
+		dev_err_ratelimited(&s->udev->dev, "URB failed %d\n",
+				urb->status);
+		break;
+	}
+
+	if (likely(urb->actual_length > 0)) {
+		void *ptr;
+		unsigned int len;
+		/* get free framebuffer */
+		fbuf = airspy_get_next_fill_buf(s);
+		if (unlikely(fbuf == NULL)) {
+			s->vb_full++;
+			dev_notice_ratelimited(&s->udev->dev,
+					"videobuf is full, %d packets dropped\n",
+					s->vb_full);
+			goto skip;
+		}
+
+		/* fill framebuffer */
+		ptr = vb2_plane_vaddr(&fbuf->vb, 0);
+		len = airspy_convert_stream(s, ptr, urb->transfer_buffer,
+				urb->actual_length);
+		vb2_set_plane_payload(&fbuf->vb, 0, len);
+		v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp);
+		fbuf->vb.v4l2_buf.sequence = s->sequence++;
+		vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
+	}
+skip:
+	usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+static int airspy_kill_urbs(struct airspy *s)
+{
+	int i;
+
+	for (i = s->urbs_submitted - 1; i >= 0; i--) {
+		dev_dbg(&s->udev->dev, "%s: kill urb=%d\n", __func__, i);
+		/* stop the URB */
+		usb_kill_urb(s->urb_list[i]);
+	}
+	s->urbs_submitted = 0;
+
+	return 0;
+}
+
+static int airspy_submit_urbs(struct airspy *s)
+{
+	int i, ret;
+
+	for (i = 0; i < s->urbs_initialized; i++) {
+		dev_dbg(&s->udev->dev, "%s: submit urb=%d\n", __func__, i);
+		ret = usb_submit_urb(s->urb_list[i], GFP_ATOMIC);
+		if (ret) {
+			dev_err(&s->udev->dev,
+					"Could not submit URB no. %d - get them all back\n",
+					i);
+			airspy_kill_urbs(s);
+			return ret;
+		}
+		s->urbs_submitted++;
+	}
+
+	return 0;
+}
+
+static int airspy_free_stream_bufs(struct airspy *s)
+{
+	if (s->flags & USB_STATE_URB_BUF) {
+		while (s->buf_num) {
+			s->buf_num--;
+			dev_dbg(&s->udev->dev, "%s: free buf=%d\n",
+					__func__, s->buf_num);
+			usb_free_coherent(s->udev, s->buf_size,
+					  s->buf_list[s->buf_num],
+					  s->dma_addr[s->buf_num]);
+		}
+	}
+	s->flags &= ~USB_STATE_URB_BUF;
+
+	return 0;
+}
+
+static int airspy_alloc_stream_bufs(struct airspy *s)
+{
+	s->buf_num = 0;
+	s->buf_size = BULK_BUFFER_SIZE;
+
+	dev_dbg(&s->udev->dev,
+			"%s: all in all I will use %u bytes for streaming\n",
+			__func__,  MAX_BULK_BUFS * BULK_BUFFER_SIZE);
+
+	for (s->buf_num = 0; s->buf_num < MAX_BULK_BUFS; s->buf_num++) {
+		s->buf_list[s->buf_num] = usb_alloc_coherent(s->udev,
+				BULK_BUFFER_SIZE, GFP_ATOMIC,
+				&s->dma_addr[s->buf_num]);
+		if (!s->buf_list[s->buf_num]) {
+			dev_dbg(&s->udev->dev, "%s: alloc buf=%d failed\n",
+					__func__, s->buf_num);
+			airspy_free_stream_bufs(s);
+			return -ENOMEM;
+		}
+
+		dev_dbg(&s->udev->dev, "%s: alloc buf=%d %p (dma %llu)\n",
+				__func__, s->buf_num,
+				s->buf_list[s->buf_num],
+				(long long)s->dma_addr[s->buf_num]);
+		s->flags |= USB_STATE_URB_BUF;
+	}
+
+	return 0;
+}
+
+static int airspy_free_urbs(struct airspy *s)
+{
+	int i;
+
+	airspy_kill_urbs(s);
+
+	for (i = s->urbs_initialized - 1; i >= 0; i--) {
+		if (s->urb_list[i]) {
+			dev_dbg(&s->udev->dev, "%s: free urb=%d\n",
+					__func__, i);
+			/* free the URBs */
+			usb_free_urb(s->urb_list[i]);
+		}
+	}
+	s->urbs_initialized = 0;
+
+	return 0;
+}
+
+static int airspy_alloc_urbs(struct airspy *s)
+{
+	int i, j;
+
+	/* allocate the URBs */
+	for (i = 0; i < MAX_BULK_BUFS; i++) {
+		dev_dbg(&s->udev->dev, "%s: alloc urb=%d\n", __func__, i);
+		s->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC);
+		if (!s->urb_list[i]) {
+			dev_dbg(&s->udev->dev, "%s: failed\n", __func__);
+			for (j = 0; j < i; j++)
+				usb_free_urb(s->urb_list[j]);
+			return -ENOMEM;
+		}
+		usb_fill_bulk_urb(s->urb_list[i],
+				s->udev,
+				usb_rcvbulkpipe(s->udev, 0x81),
+				s->buf_list[i],
+				BULK_BUFFER_SIZE,
+				airspy_urb_complete, s);
+
+		s->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+		s->urb_list[i]->transfer_dma = s->dma_addr[i];
+		s->urbs_initialized++;
+	}
+
+	return 0;
+}
+
+/* Must be called with vb_queue_lock hold */
+static void airspy_cleanup_queued_bufs(struct airspy *s)
+{
+	unsigned long flags = 0;
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	spin_lock_irqsave(&s->queued_bufs_lock, flags);
+	while (!list_empty(&s->queued_bufs)) {
+		struct airspy_frame_buf *buf;
+		buf = list_entry(s->queued_bufs.next,
+				struct airspy_frame_buf, list);
+		list_del(&buf->list);
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+	}
+	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
+}
+
+/* The user yanked out the cable... */
+static void airspy_disconnect(struct usb_interface *intf)
+{
+	struct v4l2_device *v = usb_get_intfdata(intf);
+	struct airspy *s = container_of(v, struct airspy, v4l2_dev);
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	mutex_lock(&s->vb_queue_lock);
+	mutex_lock(&s->v4l2_lock);
+	/* No need to keep the urbs around after disconnection */
+	s->udev = NULL;
+	v4l2_device_disconnect(&s->v4l2_dev);
+	video_unregister_device(&s->vdev);
+	mutex_unlock(&s->v4l2_lock);
+	mutex_unlock(&s->vb_queue_lock);
+
+	v4l2_device_put(&s->v4l2_dev);
+}
+
+/* Videobuf2 operations */
+static int airspy_queue_setup(struct vb2_queue *vq,
+		const struct v4l2_format *fmt, unsigned int *nbuffers,
+		unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
+{
+	struct airspy *s = vb2_get_drv_priv(vq);
+
+	dev_dbg(&s->udev->dev, "%s: *nbuffers=%d\n", __func__, *nbuffers);
+
+	/* Need at least 8 buffers */
+	if (vq->num_buffers + *nbuffers < 8)
+		*nbuffers = 8 - vq->num_buffers;
+	*nplanes = 1;
+	sizes[0] = PAGE_ALIGN(BULK_BUFFER_SIZE);
+
+	dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n",
+			__func__, *nbuffers, sizes[0]);
+	return 0;
+}
+
+static void airspy_buf_queue(struct vb2_buffer *vb)
+{
+	struct airspy *s = vb2_get_drv_priv(vb->vb2_queue);
+	struct airspy_frame_buf *buf =
+			container_of(vb, struct airspy_frame_buf, vb);
+	unsigned long flags = 0;
+
+	/* Check the device has not disconnected between prep and queuing */
+	if (unlikely(!s->udev)) {
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		return;
+	}
+
+	spin_lock_irqsave(&s->queued_bufs_lock, flags);
+	list_add_tail(&buf->list, &s->queued_bufs);
+	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
+}
+
+static int airspy_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+	struct airspy *s = vb2_get_drv_priv(vq);
+	int ret;
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	if (!s->udev)
+		return -ENODEV;
+
+	mutex_lock(&s->v4l2_lock);
+
+	set_bit(POWER_ON, &s->flags);
+
+	s->sequence = 0;
+
+	ret = airspy_alloc_stream_bufs(s);
+	if (ret)
+		goto err;
+
+	ret = airspy_alloc_urbs(s);
+	if (ret)
+		goto err;
+
+	ret = airspy_submit_urbs(s);
+	if (ret)
+		goto err;
+
+	/* start hardware streaming */
+	ret = airspy_ctrl_msg(s, CMD_RECEIVER_MODE, 1, 0, NULL, 0);
+	if (ret)
+		goto err;
+err:
+	mutex_unlock(&s->v4l2_lock);
+
+	return ret;
+}
+
+static void airspy_stop_streaming(struct vb2_queue *vq)
+{
+	struct airspy *s = vb2_get_drv_priv(vq);
+	int ret;
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	mutex_lock(&s->v4l2_lock);
+
+	/* stop hardware streaming */
+	ret = airspy_ctrl_msg(s, CMD_RECEIVER_MODE, 0, 0, NULL, 0);
+
+	airspy_kill_urbs(s);
+	airspy_free_urbs(s);
+	airspy_free_stream_bufs(s);
+
+	airspy_cleanup_queued_bufs(s);
+
+	clear_bit(POWER_ON, &s->flags);
+
+	mutex_unlock(&s->v4l2_lock);
+}
+
+static struct vb2_ops airspy_vb2_ops = {
+	.queue_setup            = airspy_queue_setup,
+	.buf_queue              = airspy_buf_queue,
+	.start_streaming        = airspy_start_streaming,
+	.stop_streaming         = airspy_stop_streaming,
+	.wait_prepare           = vb2_ops_wait_prepare,
+	.wait_finish            = vb2_ops_wait_finish,
+};
+
+static int airspy_querycap(struct file *file, void *fh,
+		struct v4l2_capability *cap)
+{
+	struct airspy *s = video_drvdata(file);
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
+	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_SDR_CAPTURE | V4L2_CAP_STREAMING |
+			V4L2_CAP_READWRITE | V4L2_CAP_TUNER;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+
+	return 0;
+}
+
+static int airspy_enum_fmt_sdr_cap(struct file *file, void *priv,
+		struct v4l2_fmtdesc *f)
+{
+	struct airspy *s = video_drvdata(file);
+
+	dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, f->index);
+
+	if (f->index >= NUM_FORMATS)
+		return -EINVAL;
+
+	strlcpy(f->description, formats[f->index].name, sizeof(f->description));
+	f->pixelformat = formats[f->index].pixelformat;
+
+	return 0;
+}
+
+static int airspy_g_fmt_sdr_cap(struct file *file, void *priv,
+		struct v4l2_format *f)
+{
+	struct airspy *s = video_drvdata(file);
+
+	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
+			(char *)&s->pixelformat);
+
+	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
+	f->fmt.sdr.pixelformat = s->pixelformat;
+
+	return 0;
+}
+
+static int airspy_s_fmt_sdr_cap(struct file *file, void *priv,
+		struct v4l2_format *f)
+{
+	struct airspy *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.sdr.pixelformat);
+
+	if (vb2_is_busy(q))
+		return -EBUSY;
+
+	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
+	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 airspy_try_fmt_sdr_cap(struct file *file, void *priv,
+		struct v4l2_format *f)
+{
+	struct airspy *s = video_drvdata(file);
+	int i;
+
+	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
+			(char *)&f->fmt.sdr.pixelformat);
+
+	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
+	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;
+}
+
+static int airspy_s_tuner(struct file *file, void *priv,
+		const struct v4l2_tuner *v)
+{
+	struct airspy *s = video_drvdata(file);
+	int ret;
+
+	dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index);
+
+	if (v->index == 0)
+		ret = 0;
+	else if (v->index == 1)
+		ret = 0;
+	else
+		ret = -EINVAL;
+
+	return ret;
+}
+
+static int airspy_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
+{
+	struct airspy *s = video_drvdata(file);
+	int ret;
+
+	dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index);
+
+	if (v->index == 0) {
+		strlcpy(v->name, "AirSpy ADC", sizeof(v->name));
+		v->type = V4L2_TUNER_ADC;
+		v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+		v->rangelow  = bands[0].rangelow;
+		v->rangehigh = bands[0].rangehigh;
+		ret = 0;
+	} else if (v->index == 1) {
+		strlcpy(v->name, "AirSpy RF", sizeof(v->name));
+		v->type = V4L2_TUNER_RF;
+		v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+		v->rangelow  = bands_rf[0].rangelow;
+		v->rangehigh = bands_rf[0].rangehigh;
+		ret = 0;
+	} else {
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int airspy_g_frequency(struct file *file, void *priv,
+		struct v4l2_frequency *f)
+{
+	struct airspy *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->type = V4L2_TUNER_ADC;
+		f->frequency = s->f_adc;
+		ret = 0;
+	} else if (f->tuner == 1) {
+		f->type = V4L2_TUNER_RF;
+		f->frequency = s->f_rf;
+	} else {
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int airspy_s_frequency(struct file *file, void *priv,
+		const struct v4l2_frequency *f)
+{
+	struct airspy *s = video_drvdata(file);
+	int ret;
+	u8 buf[4];
+
+	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n",
+			__func__, f->tuner, f->type, f->frequency);
+
+	if (f->tuner == 0) {
+		s->f_adc = clamp_t(unsigned int, f->frequency,
+				bands[0].rangelow,
+				bands[0].rangehigh);
+		dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n",
+				__func__, s->f_adc);
+		ret = 0;
+	} else if (f->tuner == 1) {
+		s->f_rf = clamp_t(unsigned int, f->frequency,
+				bands_rf[0].rangelow,
+				bands_rf[0].rangehigh);
+		dev_dbg(&s->udev->dev, "%s: RF frequency=%u Hz\n",
+				__func__, s->f_rf);
+		buf[0] = (s->f_rf >>  0) & 0xff;
+		buf[1] = (s->f_rf >>  8) & 0xff;
+		buf[2] = (s->f_rf >> 16) & 0xff;
+		buf[3] = (s->f_rf >> 24) & 0xff;
+		ret = airspy_ctrl_msg(s, CMD_SET_FREQ, 0, 0, buf, 4);
+	} else {
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int airspy_enum_freq_bands(struct file *file, void *priv,
+		struct v4l2_frequency_band *band)
+{
+	struct airspy *s = video_drvdata(file);
+	int ret;
+	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)) {
+			ret = -EINVAL;
+		} else {
+			*band = bands[band->index];
+			ret = 0;
+		}
+	} else if (band->tuner == 1) {
+		if (band->index >= ARRAY_SIZE(bands_rf)) {
+			ret = -EINVAL;
+		} else {
+			*band = bands_rf[band->index];
+			ret = 0;
+		}
+	} else {
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static const struct v4l2_ioctl_ops airspy_ioctl_ops = {
+	.vidioc_querycap          = airspy_querycap,
+
+	.vidioc_enum_fmt_sdr_cap  = airspy_enum_fmt_sdr_cap,
+	.vidioc_g_fmt_sdr_cap     = airspy_g_fmt_sdr_cap,
+	.vidioc_s_fmt_sdr_cap     = airspy_s_fmt_sdr_cap,
+	.vidioc_try_fmt_sdr_cap   = airspy_try_fmt_sdr_cap,
+
+	.vidioc_reqbufs           = vb2_ioctl_reqbufs,
+	.vidioc_create_bufs       = vb2_ioctl_create_bufs,
+	.vidioc_prepare_buf       = vb2_ioctl_prepare_buf,
+	.vidioc_querybuf          = vb2_ioctl_querybuf,
+	.vidioc_qbuf              = vb2_ioctl_qbuf,
+	.vidioc_dqbuf             = vb2_ioctl_dqbuf,
+
+	.vidioc_streamon          = vb2_ioctl_streamon,
+	.vidioc_streamoff         = vb2_ioctl_streamoff,
+
+	.vidioc_g_tuner           = airspy_g_tuner,
+	.vidioc_s_tuner           = airspy_s_tuner,
+
+	.vidioc_g_frequency       = airspy_g_frequency,
+	.vidioc_s_frequency       = airspy_s_frequency,
+	.vidioc_enum_freq_bands   = airspy_enum_freq_bands,
+
+	.vidioc_subscribe_event   = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+	.vidioc_log_status        = v4l2_ctrl_log_status,
+};
+
+static const struct v4l2_file_operations airspy_fops = {
+	.owner                    = THIS_MODULE,
+	.open                     = v4l2_fh_open,
+	.release                  = vb2_fop_release,
+	.read                     = vb2_fop_read,
+	.poll                     = vb2_fop_poll,
+	.mmap                     = vb2_fop_mmap,
+	.unlocked_ioctl           = video_ioctl2,
+};
+
+static struct video_device airspy_template = {
+	.name                     = "AirSpy SDR",
+	.release                  = video_device_release_empty,
+	.fops                     = &airspy_fops,
+	.ioctl_ops                = &airspy_ioctl_ops,
+};
+
+static void airspy_video_release(struct v4l2_device *v)
+{
+	struct airspy *s = container_of(v, struct airspy, v4l2_dev);
+
+	v4l2_ctrl_handler_free(&s->hdl);
+	v4l2_device_unregister(&s->v4l2_dev);
+	kfree(s);
+}
+
+static int airspy_set_lna_gain(struct airspy *s)
+{
+	int ret;
+	u8 u8tmp;
+
+	dev_dbg(&s->udev->dev, "%s: lna auto=%d->%d val=%d->%d\n",
+			__func__, s->lna_gain_auto->cur.val,
+			s->lna_gain_auto->val, s->lna_gain->cur.val,
+			s->lna_gain->val);
+
+	ret = airspy_ctrl_msg(s, CMD_SET_LNA_AGC, 0, s->lna_gain_auto->val,
+			&u8tmp, 1);
+	if (ret)
+		goto err;
+
+	if (s->lna_gain_auto->val == false) {
+		ret = airspy_ctrl_msg(s, CMD_SET_LNA_GAIN, 0, s->lna_gain->val,
+				&u8tmp, 1);
+		if (ret)
+			goto err;
+	}
+err:
+	if (ret)
+		dev_dbg(&s->udev->dev, "%s: failed=%d\n", __func__, ret);
+
+	return ret;
+}
+
+static int airspy_set_mixer_gain(struct airspy *s)
+{
+	int ret;
+	u8 u8tmp;
+
+	dev_dbg(&s->udev->dev, "%s: mixer auto=%d->%d val=%d->%d\n",
+			__func__, s->mixer_gain_auto->cur.val,
+			s->mixer_gain_auto->val, s->mixer_gain->cur.val,
+			s->mixer_gain->val);
+
+	ret = airspy_ctrl_msg(s, CMD_SET_MIXER_AGC, 0, s->mixer_gain_auto->val,
+			&u8tmp, 1);
+	if (ret)
+		goto err;
+
+	if (s->mixer_gain_auto->val == false) {
+		ret = airspy_ctrl_msg(s, CMD_SET_MIXER_GAIN, 0,
+				s->mixer_gain->val, &u8tmp, 1);
+		if (ret)
+			goto err;
+	}
+err:
+	if (ret)
+		dev_dbg(&s->udev->dev, "%s: failed=%d\n", __func__, ret);
+
+	return ret;
+}
+
+static int airspy_set_if_gain(struct airspy *s)
+{
+	int ret;
+	u8 u8tmp;
+
+	dev_dbg(&s->udev->dev, "%s: val=%d->%d\n",
+			__func__, s->if_gain->cur.val, s->if_gain->val);
+
+	ret = airspy_ctrl_msg(s, CMD_SET_VGA_GAIN, 0, s->if_gain->val,
+			&u8tmp, 1);
+	if (ret)
+		goto err;
+err:
+	if (ret)
+		dev_dbg(&s->udev->dev, "%s: failed=%d\n", __func__, ret);
+
+	return ret;
+}
+
+static int airspy_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct airspy *s = container_of(ctrl->handler, struct airspy, hdl);
+	int ret;
+
+	switch (ctrl->id) {
+	case  V4L2_CID_RF_TUNER_LNA_GAIN_AUTO:
+	case  V4L2_CID_RF_TUNER_LNA_GAIN:
+		ret = airspy_set_lna_gain(s);
+		break;
+	case  V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO:
+	case  V4L2_CID_RF_TUNER_MIXER_GAIN:
+		ret = airspy_set_mixer_gain(s);
+		break;
+	case  V4L2_CID_RF_TUNER_IF_GAIN:
+		ret = airspy_set_if_gain(s);
+		break;
+	default:
+		dev_dbg(&s->udev->dev, "%s: unknown ctrl: id=%d name=%s\n",
+				__func__, ctrl->id, ctrl->name);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static const struct v4l2_ctrl_ops airspy_ctrl_ops = {
+	.s_ctrl = airspy_s_ctrl,
+};
+
+static int airspy_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+	struct airspy *s = NULL;
+	int ret;
+	u8 u8tmp, buf[BUF_SIZE];
+
+	s = kzalloc(sizeof(struct airspy), GFP_KERNEL);
+	if (s == NULL) {
+		dev_err(&udev->dev,
+				"Could not allocate memory for airspy state\n");
+		return -ENOMEM;
+	}
+
+	mutex_init(&s->v4l2_lock);
+	mutex_init(&s->vb_queue_lock);
+	spin_lock_init(&s->queued_bufs_lock);
+	INIT_LIST_HEAD(&s->queued_bufs);
+	s->udev = udev;
+	s->f_adc = bands[0].rangelow;
+	s->f_rf = bands_rf[0].rangelow;
+	s->pixelformat = V4L2_SDR_FMT_RU12LE;
+
+	/* Detect device */
+	ret = airspy_ctrl_msg(s, CMD_BOARD_ID_READ, 0, 0, &u8tmp, 1);
+	if (ret == 0)
+		ret = airspy_ctrl_msg(s, CMD_VERSION_STRING_READ, 0, 0,
+				buf, BUF_SIZE);
+	if (ret) {
+		dev_err(&s->udev->dev, "Could not detect board\n");
+		goto err_free_mem;
+	}
+
+	buf[BUF_SIZE - 1] = '\0';
+
+	dev_info(&s->udev->dev, "Board ID: %02x\n", u8tmp);
+	dev_info(&s->udev->dev, "Firmware version: %s\n", buf);
+
+	/* Init videobuf2 queue structure */
+	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 airspy_frame_buf);
+	s->vb_queue.ops = &airspy_vb2_ops;
+	s->vb_queue.mem_ops = &vb2_vmalloc_memops;
+	s->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	ret = vb2_queue_init(&s->vb_queue);
+	if (ret) {
+		dev_err(&s->udev->dev, "Could not initialize vb2 queue\n");
+		goto err_free_mem;
+	}
+
+	/* Init video_device structure */
+	s->vdev = airspy_template;
+	s->vdev.queue = &s->vb_queue;
+	s->vdev.queue->lock = &s->vb_queue_lock;
+	set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev.flags);
+	video_set_drvdata(&s->vdev, s);
+
+	/* Register the v4l2_device structure */
+	s->v4l2_dev.release = airspy_video_release;
+	ret = v4l2_device_register(&intf->dev, &s->v4l2_dev);
+	if (ret) {
+		dev_err(&s->udev->dev,
+				"Failed to register v4l2-device (%d)\n", ret);
+		goto err_free_mem;
+	}
+
+	/* Register controls */
+	v4l2_ctrl_handler_init(&s->hdl, 5);
+	s->lna_gain_auto = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
+			V4L2_CID_RF_TUNER_LNA_GAIN_AUTO, 0, 1, 1, 0);
+	s->lna_gain = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
+			V4L2_CID_RF_TUNER_LNA_GAIN, 0, 14, 1, 8);
+	v4l2_ctrl_auto_cluster(2, &s->lna_gain_auto, 0, false);
+	s->mixer_gain_auto = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
+			V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO, 0, 1, 1, 0);
+	s->mixer_gain = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
+			V4L2_CID_RF_TUNER_MIXER_GAIN, 0, 15, 1, 8);
+	v4l2_ctrl_auto_cluster(2, &s->mixer_gain_auto, 0, false);
+	s->if_gain = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
+			V4L2_CID_RF_TUNER_IF_GAIN, 0, 15, 1, 0);
+	if (s->hdl.error) {
+		ret = s->hdl.error;
+		dev_err(&s->udev->dev, "Could not initialize controls\n");
+		goto err_free_controls;
+	}
+
+	v4l2_ctrl_handler_setup(&s->hdl);
+
+	s->v4l2_dev.ctrl_handler = &s->hdl;
+	s->vdev.v4l2_dev = &s->v4l2_dev;
+	s->vdev.lock = &s->v4l2_lock;
+
+	ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1);
+	if (ret) {
+		dev_err(&s->udev->dev,
+				"Failed to register as video device (%d)\n",
+				ret);
+		goto err_unregister_v4l2_dev;
+	}
+	dev_info(&s->udev->dev, "Registered as %s\n",
+			video_device_node_name(&s->vdev));
+
+	return 0;
+
+err_free_controls:
+	v4l2_ctrl_handler_free(&s->hdl);
+err_unregister_v4l2_dev:
+	v4l2_device_unregister(&s->v4l2_dev);
+err_free_mem:
+	kfree(s);
+	return ret;
+}
+
+/* USB device ID list */
+static struct usb_device_id airspy_id_table[] = {
+	{ USB_DEVICE(0x1d50, 0x60a1) }, /* AirSpy */
+	{ }
+};
+MODULE_DEVICE_TABLE(usb, airspy_id_table);
+
+/* USB subsystem interface */
+static struct usb_driver airspy_driver = {
+	.name                     = KBUILD_MODNAME,
+	.probe                    = airspy_probe,
+	.disconnect               = airspy_disconnect,
+	.id_table                 = airspy_id_table,
+};
+
+module_usb_driver(airspy_driver);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("AirSpy SDR");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
index d7bced3..ce7d65c 100644
--- a/drivers/staging/media/Kconfig
+++ b/drivers/staging/media/Kconfig
@@ -19,7 +19,6 @@ menuconfig STAGING_MEDIA
 if STAGING_MEDIA
 
 # Please keep them in alphabetic order
-source "drivers/staging/media/airspy/Kconfig"
 source "drivers/staging/media/as102/Kconfig"
 
 source "drivers/staging/media/bcm2048/Kconfig"
diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile
index a121bc1..404e866 100644
--- a/drivers/staging/media/Makefile
+++ b/drivers/staging/media/Makefile
@@ -1,4 +1,3 @@
-obj-$(CONFIG_USB_AIRSPY)	+= airspy/
 obj-$(CONFIG_DVB_AS102)		+= as102/
 obj-$(CONFIG_I2C_BCM2048)	+= bcm2048/
 obj-$(CONFIG_DVB_CXD2099)	+= cxd2099/
diff --git a/drivers/staging/media/airspy/Kconfig b/drivers/staging/media/airspy/Kconfig
deleted file mode 100644
index 59a829b..0000000
--- a/drivers/staging/media/airspy/Kconfig
+++ /dev/null
@@ -1,5 +0,0 @@
-config USB_AIRSPY
-	tristate "AirSpy"
-	depends on USB && VIDEO_DEV && VIDEO_V4L2 && I2C
-	select VIDEOBUF2_VMALLOC
-	default m if !MEDIA_SUBDRV_AUTOSELECT
diff --git a/drivers/staging/media/airspy/Makefile b/drivers/staging/media/airspy/Makefile
deleted file mode 100644
index 8d8e61c..0000000
--- a/drivers/staging/media/airspy/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_USB_AIRSPY)              += airspy.o
diff --git a/drivers/staging/media/airspy/airspy.c b/drivers/staging/media/airspy/airspy.c
deleted file mode 100644
index 5b3310f..0000000
--- a/drivers/staging/media/airspy/airspy.c
+++ /dev/null
@@ -1,1120 +0,0 @@
-/*
- * AirSpy SDR driver
- *
- * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
-#include <media/videobuf2-vmalloc.h>
-
-/* AirSpy USB API commands (from AirSpy Library) */
-enum {
-	CMD_INVALID                       = 0x00,
-	CMD_RECEIVER_MODE                 = 0x01,
-	CMD_SI5351C_WRITE                 = 0x02,
-	CMD_SI5351C_READ                  = 0x03,
-	CMD_R820T_WRITE                   = 0x04,
-	CMD_R820T_READ                    = 0x05,
-	CMD_SPIFLASH_ERASE                = 0x06,
-	CMD_SPIFLASH_WRITE                = 0x07,
-	CMD_SPIFLASH_READ                 = 0x08,
-	CMD_BOARD_ID_READ                 = 0x09,
-	CMD_VERSION_STRING_READ           = 0x0a,
-	CMD_BOARD_PARTID_SERIALNO_READ    = 0x0b,
-	CMD_SET_SAMPLE_RATE               = 0x0c,
-	CMD_SET_FREQ                      = 0x0d,
-	CMD_SET_LNA_GAIN                  = 0x0e,
-	CMD_SET_MIXER_GAIN                = 0x0f,
-	CMD_SET_VGA_GAIN                  = 0x10,
-	CMD_SET_LNA_AGC                   = 0x11,
-	CMD_SET_MIXER_AGC                 = 0x12,
-	CMD_SET_PACKING                   = 0x13,
-};
-
-/*
- *       bEndpointAddress     0x81  EP 1 IN
- *         Transfer Type            Bulk
- *       wMaxPacketSize     0x0200  1x 512 bytes
- */
-#define MAX_BULK_BUFS            (6)
-#define BULK_BUFFER_SIZE         (128 * 512)
-
-static const struct v4l2_frequency_band bands[] = {
-	{
-		.tuner = 0,
-		.type = V4L2_TUNER_ADC,
-		.index = 0,
-		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
-		.rangelow   = 20000000,
-		.rangehigh  = 20000000,
-	},
-};
-
-static const struct v4l2_frequency_band bands_rf[] = {
-	{
-		.tuner = 1,
-		.type = V4L2_TUNER_RF,
-		.index = 0,
-		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
-		.rangelow   =   24000000,
-		.rangehigh  = 1750000000,
-	},
-};
-
-/* stream formats */
-struct airspy_format {
-	char	*name;
-	u32	pixelformat;
-};
-
-/* format descriptions for capture and preview */
-static struct airspy_format formats[] = {
-	{
-		.name		= "Real U12LE",
-		.pixelformat	=  V4L2_SDR_FMT_RU12LE,
-	},
-};
-
-static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
-
-/* intermediate buffers with raw data from the USB device */
-struct airspy_frame_buf {
-	struct vb2_buffer vb;   /* common v4l buffer stuff -- must be first */
-	struct list_head list;
-};
-
-struct airspy {
-#define POWER_ON           (1 << 1)
-#define URB_BUF            (1 << 2)
-#define USB_STATE_URB_BUF  (1 << 3)
-	unsigned long flags;
-
-	struct usb_device *udev;
-	struct video_device vdev;
-	struct v4l2_device v4l2_dev;
-
-	/* videobuf2 queue and queued buffers list */
-	struct vb2_queue vb_queue;
-	struct list_head queued_bufs;
-	spinlock_t queued_bufs_lock; /* Protects queued_bufs */
-	unsigned sequence;	     /* Buffer sequence counter */
-	unsigned int vb_full;        /* vb is full and packets dropped */
-
-	/* Note if taking both locks v4l2_lock must always be locked first! */
-	struct mutex v4l2_lock;      /* Protects everything else */
-	struct mutex vb_queue_lock;  /* Protects vb_queue and capt_file */
-
-	struct urb     *urb_list[MAX_BULK_BUFS];
-	int            buf_num;
-	unsigned long  buf_size;
-	u8             *buf_list[MAX_BULK_BUFS];
-	dma_addr_t     dma_addr[MAX_BULK_BUFS];
-	int            urbs_initialized;
-	int            urbs_submitted;
-
-	/* USB control message buffer */
-	#define BUF_SIZE 24
-	u8 buf[BUF_SIZE];
-
-	/* Current configuration */
-	unsigned int f_adc;
-	unsigned int f_rf;
-	u32 pixelformat;
-
-	/* Controls */
-	struct v4l2_ctrl_handler hdl;
-	struct v4l2_ctrl *lna_gain_auto;
-	struct v4l2_ctrl *lna_gain;
-	struct v4l2_ctrl *mixer_gain_auto;
-	struct v4l2_ctrl *mixer_gain;
-	struct v4l2_ctrl *if_gain;
-
-	/* Sample rate calc */
-	unsigned long jiffies_next;
-	unsigned int sample;
-	unsigned int sample_measured;
-};
-
-#define airspy_dbg_usb_control_msg(_udev, _r, _t, _v, _i, _b, _l) { \
-	char *_direction; \
-	if (_t & USB_DIR_IN) \
-		_direction = "<<<"; \
-	else \
-		_direction = ">>>"; \
-	dev_dbg(&_udev->dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x " \
-			"%s %*ph\n",  __func__, _t, _r, _v & 0xff, _v >> 8, \
-			_i & 0xff, _i >> 8, _l & 0xff, _l >> 8, _direction, \
-			_l, _b); \
-}
-
-/* execute firmware command */
-static int airspy_ctrl_msg(struct airspy *s, u8 request, u16 value, u16 index,
-		u8 *data, u16 size)
-{
-	int ret;
-	unsigned int pipe;
-	u8 requesttype;
-
-	switch (request) {
-	case CMD_RECEIVER_MODE:
-	case CMD_SET_FREQ:
-		pipe = usb_sndctrlpipe(s->udev, 0);
-		requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
-		break;
-	case CMD_BOARD_ID_READ:
-	case CMD_VERSION_STRING_READ:
-	case CMD_BOARD_PARTID_SERIALNO_READ:
-	case CMD_SET_LNA_GAIN:
-	case CMD_SET_MIXER_GAIN:
-	case CMD_SET_VGA_GAIN:
-	case CMD_SET_LNA_AGC:
-	case CMD_SET_MIXER_AGC:
-		pipe = usb_rcvctrlpipe(s->udev, 0);
-		requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
-		break;
-	default:
-		dev_err(&s->udev->dev, "Unknown command %02x\n", request);
-		ret = -EINVAL;
-		goto err;
-	}
-
-	/* write request */
-	if (!(requesttype & USB_DIR_IN))
-		memcpy(s->buf, data, size);
-
-	ret = usb_control_msg(s->udev, pipe, request, requesttype, value,
-			index, s->buf, size, 1000);
-	airspy_dbg_usb_control_msg(s->udev, request, requesttype, value,
-			index, s->buf, size);
-	if (ret < 0) {
-		dev_err(&s->udev->dev,
-				"usb_control_msg() failed %d request %02x\n",
-				ret, request);
-		goto err;
-	}
-
-	/* read request */
-	if (requesttype & USB_DIR_IN)
-		memcpy(data, s->buf, size);
-
-	return 0;
-err:
-	return ret;
-}
-
-/* Private functions */
-static struct airspy_frame_buf *airspy_get_next_fill_buf(struct airspy *s)
-{
-	unsigned long flags = 0;
-	struct airspy_frame_buf *buf = NULL;
-
-	spin_lock_irqsave(&s->queued_bufs_lock, flags);
-	if (list_empty(&s->queued_bufs))
-		goto leave;
-
-	buf = list_entry(s->queued_bufs.next,
-			struct airspy_frame_buf, list);
-	list_del(&buf->list);
-leave:
-	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
-	return buf;
-}
-
-static unsigned int airspy_convert_stream(struct airspy *s,
-		void *dst, void *src, unsigned int src_len)
-{
-	unsigned int dst_len;
-
-	if (s->pixelformat == V4L2_SDR_FMT_RU12LE) {
-		memcpy(dst, src, src_len);
-		dst_len = src_len;
-	} else {
-		dst_len = 0;
-	}
-
-	/* 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 = s->sample - s->sample_measured;
-		s->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
-		s->sample_measured = s->sample;
-		dev_dbg(&s->udev->dev,
-				"slen=%d samples=%u msecs=%lu sample rate=%lu\n",
-				src_len, samples, MSECS,
-				samples * 1000UL / MSECS);
-	}
-
-	/* total number of samples */
-	s->sample += src_len / 2;
-
-	return dst_len;
-}
-
-/*
- * This gets called for the bulk stream pipe. This is done in interrupt
- * time, so it has to be fast, not crash, and not stall. Neat.
- */
-static void airspy_urb_complete(struct urb *urb)
-{
-	struct airspy *s = urb->context;
-	struct airspy_frame_buf *fbuf;
-
-	dev_dbg_ratelimited(&s->udev->dev,
-			"%s: status=%d length=%d/%d errors=%d\n",
-			__func__, urb->status, urb->actual_length,
-			urb->transfer_buffer_length, urb->error_count);
-
-	switch (urb->status) {
-	case 0:             /* success */
-	case -ETIMEDOUT:    /* NAK */
-		break;
-	case -ECONNRESET:   /* kill */
-	case -ENOENT:
-	case -ESHUTDOWN:
-		return;
-	default:            /* error */
-		dev_err_ratelimited(&s->udev->dev, "URB failed %d\n",
-				urb->status);
-		break;
-	}
-
-	if (likely(urb->actual_length > 0)) {
-		void *ptr;
-		unsigned int len;
-		/* get free framebuffer */
-		fbuf = airspy_get_next_fill_buf(s);
-		if (unlikely(fbuf == NULL)) {
-			s->vb_full++;
-			dev_notice_ratelimited(&s->udev->dev,
-					"videobuf is full, %d packets dropped\n",
-					s->vb_full);
-			goto skip;
-		}
-
-		/* fill framebuffer */
-		ptr = vb2_plane_vaddr(&fbuf->vb, 0);
-		len = airspy_convert_stream(s, ptr, urb->transfer_buffer,
-				urb->actual_length);
-		vb2_set_plane_payload(&fbuf->vb, 0, len);
-		v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp);
-		fbuf->vb.v4l2_buf.sequence = s->sequence++;
-		vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
-	}
-skip:
-	usb_submit_urb(urb, GFP_ATOMIC);
-}
-
-static int airspy_kill_urbs(struct airspy *s)
-{
-	int i;
-
-	for (i = s->urbs_submitted - 1; i >= 0; i--) {
-		dev_dbg(&s->udev->dev, "%s: kill urb=%d\n", __func__, i);
-		/* stop the URB */
-		usb_kill_urb(s->urb_list[i]);
-	}
-	s->urbs_submitted = 0;
-
-	return 0;
-}
-
-static int airspy_submit_urbs(struct airspy *s)
-{
-	int i, ret;
-
-	for (i = 0; i < s->urbs_initialized; i++) {
-		dev_dbg(&s->udev->dev, "%s: submit urb=%d\n", __func__, i);
-		ret = usb_submit_urb(s->urb_list[i], GFP_ATOMIC);
-		if (ret) {
-			dev_err(&s->udev->dev,
-					"Could not submit URB no. %d - get them all back\n",
-					i);
-			airspy_kill_urbs(s);
-			return ret;
-		}
-		s->urbs_submitted++;
-	}
-
-	return 0;
-}
-
-static int airspy_free_stream_bufs(struct airspy *s)
-{
-	if (s->flags & USB_STATE_URB_BUF) {
-		while (s->buf_num) {
-			s->buf_num--;
-			dev_dbg(&s->udev->dev, "%s: free buf=%d\n",
-					__func__, s->buf_num);
-			usb_free_coherent(s->udev, s->buf_size,
-					  s->buf_list[s->buf_num],
-					  s->dma_addr[s->buf_num]);
-		}
-	}
-	s->flags &= ~USB_STATE_URB_BUF;
-
-	return 0;
-}
-
-static int airspy_alloc_stream_bufs(struct airspy *s)
-{
-	s->buf_num = 0;
-	s->buf_size = BULK_BUFFER_SIZE;
-
-	dev_dbg(&s->udev->dev,
-			"%s: all in all I will use %u bytes for streaming\n",
-			__func__,  MAX_BULK_BUFS * BULK_BUFFER_SIZE);
-
-	for (s->buf_num = 0; s->buf_num < MAX_BULK_BUFS; s->buf_num++) {
-		s->buf_list[s->buf_num] = usb_alloc_coherent(s->udev,
-				BULK_BUFFER_SIZE, GFP_ATOMIC,
-				&s->dma_addr[s->buf_num]);
-		if (!s->buf_list[s->buf_num]) {
-			dev_dbg(&s->udev->dev, "%s: alloc buf=%d failed\n",
-					__func__, s->buf_num);
-			airspy_free_stream_bufs(s);
-			return -ENOMEM;
-		}
-
-		dev_dbg(&s->udev->dev, "%s: alloc buf=%d %p (dma %llu)\n",
-				__func__, s->buf_num,
-				s->buf_list[s->buf_num],
-				(long long)s->dma_addr[s->buf_num]);
-		s->flags |= USB_STATE_URB_BUF;
-	}
-
-	return 0;
-}
-
-static int airspy_free_urbs(struct airspy *s)
-{
-	int i;
-
-	airspy_kill_urbs(s);
-
-	for (i = s->urbs_initialized - 1; i >= 0; i--) {
-		if (s->urb_list[i]) {
-			dev_dbg(&s->udev->dev, "%s: free urb=%d\n",
-					__func__, i);
-			/* free the URBs */
-			usb_free_urb(s->urb_list[i]);
-		}
-	}
-	s->urbs_initialized = 0;
-
-	return 0;
-}
-
-static int airspy_alloc_urbs(struct airspy *s)
-{
-	int i, j;
-
-	/* allocate the URBs */
-	for (i = 0; i < MAX_BULK_BUFS; i++) {
-		dev_dbg(&s->udev->dev, "%s: alloc urb=%d\n", __func__, i);
-		s->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC);
-		if (!s->urb_list[i]) {
-			dev_dbg(&s->udev->dev, "%s: failed\n", __func__);
-			for (j = 0; j < i; j++)
-				usb_free_urb(s->urb_list[j]);
-			return -ENOMEM;
-		}
-		usb_fill_bulk_urb(s->urb_list[i],
-				s->udev,
-				usb_rcvbulkpipe(s->udev, 0x81),
-				s->buf_list[i],
-				BULK_BUFFER_SIZE,
-				airspy_urb_complete, s);
-
-		s->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
-		s->urb_list[i]->transfer_dma = s->dma_addr[i];
-		s->urbs_initialized++;
-	}
-
-	return 0;
-}
-
-/* Must be called with vb_queue_lock hold */
-static void airspy_cleanup_queued_bufs(struct airspy *s)
-{
-	unsigned long flags = 0;
-
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	spin_lock_irqsave(&s->queued_bufs_lock, flags);
-	while (!list_empty(&s->queued_bufs)) {
-		struct airspy_frame_buf *buf;
-		buf = list_entry(s->queued_bufs.next,
-				struct airspy_frame_buf, list);
-		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
-	}
-	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
-}
-
-/* The user yanked out the cable... */
-static void airspy_disconnect(struct usb_interface *intf)
-{
-	struct v4l2_device *v = usb_get_intfdata(intf);
-	struct airspy *s = container_of(v, struct airspy, v4l2_dev);
-
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	mutex_lock(&s->vb_queue_lock);
-	mutex_lock(&s->v4l2_lock);
-	/* No need to keep the urbs around after disconnection */
-	s->udev = NULL;
-	v4l2_device_disconnect(&s->v4l2_dev);
-	video_unregister_device(&s->vdev);
-	mutex_unlock(&s->v4l2_lock);
-	mutex_unlock(&s->vb_queue_lock);
-
-	v4l2_device_put(&s->v4l2_dev);
-}
-
-/* Videobuf2 operations */
-static int airspy_queue_setup(struct vb2_queue *vq,
-		const struct v4l2_format *fmt, unsigned int *nbuffers,
-		unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
-{
-	struct airspy *s = vb2_get_drv_priv(vq);
-
-	dev_dbg(&s->udev->dev, "%s: *nbuffers=%d\n", __func__, *nbuffers);
-
-	/* Need at least 8 buffers */
-	if (vq->num_buffers + *nbuffers < 8)
-		*nbuffers = 8 - vq->num_buffers;
-	*nplanes = 1;
-	sizes[0] = PAGE_ALIGN(BULK_BUFFER_SIZE);
-
-	dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n",
-			__func__, *nbuffers, sizes[0]);
-	return 0;
-}
-
-static void airspy_buf_queue(struct vb2_buffer *vb)
-{
-	struct airspy *s = vb2_get_drv_priv(vb->vb2_queue);
-	struct airspy_frame_buf *buf =
-			container_of(vb, struct airspy_frame_buf, vb);
-	unsigned long flags = 0;
-
-	/* Check the device has not disconnected between prep and queuing */
-	if (unlikely(!s->udev)) {
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
-		return;
-	}
-
-	spin_lock_irqsave(&s->queued_bufs_lock, flags);
-	list_add_tail(&buf->list, &s->queued_bufs);
-	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
-}
-
-static int airspy_start_streaming(struct vb2_queue *vq, unsigned int count)
-{
-	struct airspy *s = vb2_get_drv_priv(vq);
-	int ret;
-
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	if (!s->udev)
-		return -ENODEV;
-
-	mutex_lock(&s->v4l2_lock);
-
-	set_bit(POWER_ON, &s->flags);
-
-	s->sequence = 0;
-
-	ret = airspy_alloc_stream_bufs(s);
-	if (ret)
-		goto err;
-
-	ret = airspy_alloc_urbs(s);
-	if (ret)
-		goto err;
-
-	ret = airspy_submit_urbs(s);
-	if (ret)
-		goto err;
-
-	/* start hardware streaming */
-	ret = airspy_ctrl_msg(s, CMD_RECEIVER_MODE, 1, 0, NULL, 0);
-	if (ret)
-		goto err;
-err:
-	mutex_unlock(&s->v4l2_lock);
-
-	return ret;
-}
-
-static void airspy_stop_streaming(struct vb2_queue *vq)
-{
-	struct airspy *s = vb2_get_drv_priv(vq);
-	int ret;
-
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	mutex_lock(&s->v4l2_lock);
-
-	/* stop hardware streaming */
-	ret = airspy_ctrl_msg(s, CMD_RECEIVER_MODE, 0, 0, NULL, 0);
-
-	airspy_kill_urbs(s);
-	airspy_free_urbs(s);
-	airspy_free_stream_bufs(s);
-
-	airspy_cleanup_queued_bufs(s);
-
-	clear_bit(POWER_ON, &s->flags);
-
-	mutex_unlock(&s->v4l2_lock);
-}
-
-static struct vb2_ops airspy_vb2_ops = {
-	.queue_setup            = airspy_queue_setup,
-	.buf_queue              = airspy_buf_queue,
-	.start_streaming        = airspy_start_streaming,
-	.stop_streaming         = airspy_stop_streaming,
-	.wait_prepare           = vb2_ops_wait_prepare,
-	.wait_finish            = vb2_ops_wait_finish,
-};
-
-static int airspy_querycap(struct file *file, void *fh,
-		struct v4l2_capability *cap)
-{
-	struct airspy *s = video_drvdata(file);
-
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
-	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_SDR_CAPTURE | V4L2_CAP_STREAMING |
-			V4L2_CAP_READWRITE | V4L2_CAP_TUNER;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-
-	return 0;
-}
-
-static int airspy_enum_fmt_sdr_cap(struct file *file, void *priv,
-		struct v4l2_fmtdesc *f)
-{
-	struct airspy *s = video_drvdata(file);
-
-	dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, f->index);
-
-	if (f->index >= NUM_FORMATS)
-		return -EINVAL;
-
-	strlcpy(f->description, formats[f->index].name, sizeof(f->description));
-	f->pixelformat = formats[f->index].pixelformat;
-
-	return 0;
-}
-
-static int airspy_g_fmt_sdr_cap(struct file *file, void *priv,
-		struct v4l2_format *f)
-{
-	struct airspy *s = video_drvdata(file);
-
-	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
-			(char *)&s->pixelformat);
-
-	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
-	f->fmt.sdr.pixelformat = s->pixelformat;
-
-	return 0;
-}
-
-static int airspy_s_fmt_sdr_cap(struct file *file, void *priv,
-		struct v4l2_format *f)
-{
-	struct airspy *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.sdr.pixelformat);
-
-	if (vb2_is_busy(q))
-		return -EBUSY;
-
-	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
-	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 airspy_try_fmt_sdr_cap(struct file *file, void *priv,
-		struct v4l2_format *f)
-{
-	struct airspy *s = video_drvdata(file);
-	int i;
-
-	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
-			(char *)&f->fmt.sdr.pixelformat);
-
-	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
-	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;
-}
-
-static int airspy_s_tuner(struct file *file, void *priv,
-		const struct v4l2_tuner *v)
-{
-	struct airspy *s = video_drvdata(file);
-	int ret;
-
-	dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index);
-
-	if (v->index == 0)
-		ret = 0;
-	else if (v->index == 1)
-		ret = 0;
-	else
-		ret = -EINVAL;
-
-	return ret;
-}
-
-static int airspy_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
-{
-	struct airspy *s = video_drvdata(file);
-	int ret;
-
-	dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index);
-
-	if (v->index == 0) {
-		strlcpy(v->name, "AirSpy ADC", sizeof(v->name));
-		v->type = V4L2_TUNER_ADC;
-		v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
-		v->rangelow  = bands[0].rangelow;
-		v->rangehigh = bands[0].rangehigh;
-		ret = 0;
-	} else if (v->index == 1) {
-		strlcpy(v->name, "AirSpy RF", sizeof(v->name));
-		v->type = V4L2_TUNER_RF;
-		v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
-		v->rangelow  = bands_rf[0].rangelow;
-		v->rangehigh = bands_rf[0].rangehigh;
-		ret = 0;
-	} else {
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static int airspy_g_frequency(struct file *file, void *priv,
-		struct v4l2_frequency *f)
-{
-	struct airspy *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->type = V4L2_TUNER_ADC;
-		f->frequency = s->f_adc;
-		ret = 0;
-	} else if (f->tuner == 1) {
-		f->type = V4L2_TUNER_RF;
-		f->frequency = s->f_rf;
-	} else {
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static int airspy_s_frequency(struct file *file, void *priv,
-		const struct v4l2_frequency *f)
-{
-	struct airspy *s = video_drvdata(file);
-	int ret;
-	u8 buf[4];
-
-	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n",
-			__func__, f->tuner, f->type, f->frequency);
-
-	if (f->tuner == 0) {
-		s->f_adc = clamp_t(unsigned int, f->frequency,
-				bands[0].rangelow,
-				bands[0].rangehigh);
-		dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n",
-				__func__, s->f_adc);
-		ret = 0;
-	} else if (f->tuner == 1) {
-		s->f_rf = clamp_t(unsigned int, f->frequency,
-				bands_rf[0].rangelow,
-				bands_rf[0].rangehigh);
-		dev_dbg(&s->udev->dev, "%s: RF frequency=%u Hz\n",
-				__func__, s->f_rf);
-		buf[0] = (s->f_rf >>  0) & 0xff;
-		buf[1] = (s->f_rf >>  8) & 0xff;
-		buf[2] = (s->f_rf >> 16) & 0xff;
-		buf[3] = (s->f_rf >> 24) & 0xff;
-		ret = airspy_ctrl_msg(s, CMD_SET_FREQ, 0, 0, buf, 4);
-	} else {
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static int airspy_enum_freq_bands(struct file *file, void *priv,
-		struct v4l2_frequency_band *band)
-{
-	struct airspy *s = video_drvdata(file);
-	int ret;
-	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)) {
-			ret = -EINVAL;
-		} else {
-			*band = bands[band->index];
-			ret = 0;
-		}
-	} else if (band->tuner == 1) {
-		if (band->index >= ARRAY_SIZE(bands_rf)) {
-			ret = -EINVAL;
-		} else {
-			*band = bands_rf[band->index];
-			ret = 0;
-		}
-	} else {
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static const struct v4l2_ioctl_ops airspy_ioctl_ops = {
-	.vidioc_querycap          = airspy_querycap,
-
-	.vidioc_enum_fmt_sdr_cap  = airspy_enum_fmt_sdr_cap,
-	.vidioc_g_fmt_sdr_cap     = airspy_g_fmt_sdr_cap,
-	.vidioc_s_fmt_sdr_cap     = airspy_s_fmt_sdr_cap,
-	.vidioc_try_fmt_sdr_cap   = airspy_try_fmt_sdr_cap,
-
-	.vidioc_reqbufs           = vb2_ioctl_reqbufs,
-	.vidioc_create_bufs       = vb2_ioctl_create_bufs,
-	.vidioc_prepare_buf       = vb2_ioctl_prepare_buf,
-	.vidioc_querybuf          = vb2_ioctl_querybuf,
-	.vidioc_qbuf              = vb2_ioctl_qbuf,
-	.vidioc_dqbuf             = vb2_ioctl_dqbuf,
-
-	.vidioc_streamon          = vb2_ioctl_streamon,
-	.vidioc_streamoff         = vb2_ioctl_streamoff,
-
-	.vidioc_g_tuner           = airspy_g_tuner,
-	.vidioc_s_tuner           = airspy_s_tuner,
-
-	.vidioc_g_frequency       = airspy_g_frequency,
-	.vidioc_s_frequency       = airspy_s_frequency,
-	.vidioc_enum_freq_bands   = airspy_enum_freq_bands,
-
-	.vidioc_subscribe_event   = v4l2_ctrl_subscribe_event,
-	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-	.vidioc_log_status        = v4l2_ctrl_log_status,
-};
-
-static const struct v4l2_file_operations airspy_fops = {
-	.owner                    = THIS_MODULE,
-	.open                     = v4l2_fh_open,
-	.release                  = vb2_fop_release,
-	.read                     = vb2_fop_read,
-	.poll                     = vb2_fop_poll,
-	.mmap                     = vb2_fop_mmap,
-	.unlocked_ioctl           = video_ioctl2,
-};
-
-static struct video_device airspy_template = {
-	.name                     = "AirSpy SDR",
-	.release                  = video_device_release_empty,
-	.fops                     = &airspy_fops,
-	.ioctl_ops                = &airspy_ioctl_ops,
-};
-
-static void airspy_video_release(struct v4l2_device *v)
-{
-	struct airspy *s = container_of(v, struct airspy, v4l2_dev);
-
-	v4l2_ctrl_handler_free(&s->hdl);
-	v4l2_device_unregister(&s->v4l2_dev);
-	kfree(s);
-}
-
-static int airspy_set_lna_gain(struct airspy *s)
-{
-	int ret;
-	u8 u8tmp;
-
-	dev_dbg(&s->udev->dev, "%s: lna auto=%d->%d val=%d->%d\n",
-			__func__, s->lna_gain_auto->cur.val,
-			s->lna_gain_auto->val, s->lna_gain->cur.val,
-			s->lna_gain->val);
-
-	ret = airspy_ctrl_msg(s, CMD_SET_LNA_AGC, 0, s->lna_gain_auto->val,
-			&u8tmp, 1);
-	if (ret)
-		goto err;
-
-	if (s->lna_gain_auto->val == false) {
-		ret = airspy_ctrl_msg(s, CMD_SET_LNA_GAIN, 0, s->lna_gain->val,
-				&u8tmp, 1);
-		if (ret)
-			goto err;
-	}
-err:
-	if (ret)
-		dev_dbg(&s->udev->dev, "%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-static int airspy_set_mixer_gain(struct airspy *s)
-{
-	int ret;
-	u8 u8tmp;
-
-	dev_dbg(&s->udev->dev, "%s: mixer auto=%d->%d val=%d->%d\n",
-			__func__, s->mixer_gain_auto->cur.val,
-			s->mixer_gain_auto->val, s->mixer_gain->cur.val,
-			s->mixer_gain->val);
-
-	ret = airspy_ctrl_msg(s, CMD_SET_MIXER_AGC, 0, s->mixer_gain_auto->val,
-			&u8tmp, 1);
-	if (ret)
-		goto err;
-
-	if (s->mixer_gain_auto->val == false) {
-		ret = airspy_ctrl_msg(s, CMD_SET_MIXER_GAIN, 0,
-				s->mixer_gain->val, &u8tmp, 1);
-		if (ret)
-			goto err;
-	}
-err:
-	if (ret)
-		dev_dbg(&s->udev->dev, "%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-static int airspy_set_if_gain(struct airspy *s)
-{
-	int ret;
-	u8 u8tmp;
-
-	dev_dbg(&s->udev->dev, "%s: val=%d->%d\n",
-			__func__, s->if_gain->cur.val, s->if_gain->val);
-
-	ret = airspy_ctrl_msg(s, CMD_SET_VGA_GAIN, 0, s->if_gain->val,
-			&u8tmp, 1);
-	if (ret)
-		goto err;
-err:
-	if (ret)
-		dev_dbg(&s->udev->dev, "%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-static int airspy_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct airspy *s = container_of(ctrl->handler, struct airspy, hdl);
-	int ret;
-
-	switch (ctrl->id) {
-	case  V4L2_CID_RF_TUNER_LNA_GAIN_AUTO:
-	case  V4L2_CID_RF_TUNER_LNA_GAIN:
-		ret = airspy_set_lna_gain(s);
-		break;
-	case  V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO:
-	case  V4L2_CID_RF_TUNER_MIXER_GAIN:
-		ret = airspy_set_mixer_gain(s);
-		break;
-	case  V4L2_CID_RF_TUNER_IF_GAIN:
-		ret = airspy_set_if_gain(s);
-		break;
-	default:
-		dev_dbg(&s->udev->dev, "%s: unknown ctrl: id=%d name=%s\n",
-				__func__, ctrl->id, ctrl->name);
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static const struct v4l2_ctrl_ops airspy_ctrl_ops = {
-	.s_ctrl = airspy_s_ctrl,
-};
-
-static int airspy_probe(struct usb_interface *intf,
-		const struct usb_device_id *id)
-{
-	struct usb_device *udev = interface_to_usbdev(intf);
-	struct airspy *s = NULL;
-	int ret;
-	u8 u8tmp, buf[BUF_SIZE];
-
-	s = kzalloc(sizeof(struct airspy), GFP_KERNEL);
-	if (s == NULL) {
-		dev_err(&udev->dev,
-				"Could not allocate memory for airspy state\n");
-		return -ENOMEM;
-	}
-
-	mutex_init(&s->v4l2_lock);
-	mutex_init(&s->vb_queue_lock);
-	spin_lock_init(&s->queued_bufs_lock);
-	INIT_LIST_HEAD(&s->queued_bufs);
-	s->udev = udev;
-	s->f_adc = bands[0].rangelow;
-	s->f_rf = bands_rf[0].rangelow;
-	s->pixelformat = V4L2_SDR_FMT_RU12LE;
-
-	/* Detect device */
-	ret = airspy_ctrl_msg(s, CMD_BOARD_ID_READ, 0, 0, &u8tmp, 1);
-	if (ret == 0)
-		ret = airspy_ctrl_msg(s, CMD_VERSION_STRING_READ, 0, 0,
-				buf, BUF_SIZE);
-	if (ret) {
-		dev_err(&s->udev->dev, "Could not detect board\n");
-		goto err_free_mem;
-	}
-
-	buf[BUF_SIZE - 1] = '\0';
-
-	dev_info(&s->udev->dev, "Board ID: %02x\n", u8tmp);
-	dev_info(&s->udev->dev, "Firmware version: %s\n", buf);
-
-	/* Init videobuf2 queue structure */
-	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 airspy_frame_buf);
-	s->vb_queue.ops = &airspy_vb2_ops;
-	s->vb_queue.mem_ops = &vb2_vmalloc_memops;
-	s->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-	ret = vb2_queue_init(&s->vb_queue);
-	if (ret) {
-		dev_err(&s->udev->dev, "Could not initialize vb2 queue\n");
-		goto err_free_mem;
-	}
-
-	/* Init video_device structure */
-	s->vdev = airspy_template;
-	s->vdev.queue = &s->vb_queue;
-	s->vdev.queue->lock = &s->vb_queue_lock;
-	set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev.flags);
-	video_set_drvdata(&s->vdev, s);
-
-	/* Register the v4l2_device structure */
-	s->v4l2_dev.release = airspy_video_release;
-	ret = v4l2_device_register(&intf->dev, &s->v4l2_dev);
-	if (ret) {
-		dev_err(&s->udev->dev,
-				"Failed to register v4l2-device (%d)\n", ret);
-		goto err_free_mem;
-	}
-
-	/* Register controls */
-	v4l2_ctrl_handler_init(&s->hdl, 5);
-	s->lna_gain_auto = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
-			V4L2_CID_RF_TUNER_LNA_GAIN_AUTO, 0, 1, 1, 0);
-	s->lna_gain = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
-			V4L2_CID_RF_TUNER_LNA_GAIN, 0, 14, 1, 8);
-	v4l2_ctrl_auto_cluster(2, &s->lna_gain_auto, 0, false);
-	s->mixer_gain_auto = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
-			V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO, 0, 1, 1, 0);
-	s->mixer_gain = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
-			V4L2_CID_RF_TUNER_MIXER_GAIN, 0, 15, 1, 8);
-	v4l2_ctrl_auto_cluster(2, &s->mixer_gain_auto, 0, false);
-	s->if_gain = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
-			V4L2_CID_RF_TUNER_IF_GAIN, 0, 15, 1, 0);
-	if (s->hdl.error) {
-		ret = s->hdl.error;
-		dev_err(&s->udev->dev, "Could not initialize controls\n");
-		goto err_free_controls;
-	}
-
-	v4l2_ctrl_handler_setup(&s->hdl);
-
-	s->v4l2_dev.ctrl_handler = &s->hdl;
-	s->vdev.v4l2_dev = &s->v4l2_dev;
-	s->vdev.lock = &s->v4l2_lock;
-
-	ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1);
-	if (ret) {
-		dev_err(&s->udev->dev,
-				"Failed to register as video device (%d)\n",
-				ret);
-		goto err_unregister_v4l2_dev;
-	}
-	dev_info(&s->udev->dev, "Registered as %s\n",
-			video_device_node_name(&s->vdev));
-
-	return 0;
-
-err_free_controls:
-	v4l2_ctrl_handler_free(&s->hdl);
-err_unregister_v4l2_dev:
-	v4l2_device_unregister(&s->v4l2_dev);
-err_free_mem:
-	kfree(s);
-	return ret;
-}
-
-/* USB device ID list */
-static struct usb_device_id airspy_id_table[] = {
-	{ USB_DEVICE(0x1d50, 0x60a1) }, /* AirSpy */
-	{ }
-};
-MODULE_DEVICE_TABLE(usb, airspy_id_table);
-
-/* USB subsystem interface */
-static struct usb_driver airspy_driver = {
-	.name                     = KBUILD_MODNAME,
-	.probe                    = airspy_probe,
-	.disconnect               = airspy_disconnect,
-	.id_table                 = airspy_id_table,
-};
-
-module_usb_driver(airspy_driver);
-
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("AirSpy SDR");
-MODULE_LICENSE("GPL");
-- 
1.9.3


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

* [PATCH 3/4] airspy: print notice to point SDR API is not 100% stable yet
  2014-07-18  1:05 [PATCH 1/4] airspy: remove v4l2-compliance workaround Antti Palosaari
  2014-07-18  1:05 ` [PATCH 2/4] airspy: move out of staging into drivers/media/usb Antti Palosaari
@ 2014-07-18  1:05 ` Antti Palosaari
  2014-07-18  5:15   ` Hans Verkuil
  2014-07-18  1:05 ` [PATCH 4/4] MAINTAINERS: add airspy driver Antti Palosaari
  2 siblings, 1 reply; 6+ messages in thread
From: Antti Palosaari @ 2014-07-18  1:05 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Print notice on driver load: "SDR API is still slightly
experimental and functionality changes may follow". It is just
remind possible used SDR API is very new and surprises may occur.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/usb/airspy/airspy.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c
index 5b3310f..6cf09ef 100644
--- a/drivers/media/usb/airspy/airspy.c
+++ b/drivers/media/usb/airspy/airspy.c
@@ -1086,7 +1086,9 @@ static int airspy_probe(struct usb_interface *intf,
 	}
 	dev_info(&s->udev->dev, "Registered as %s\n",
 			video_device_node_name(&s->vdev));
-
+	dev_notice(&s->udev->dev,
+			"%s: SDR API is still slightly experimental and functionality changes may follow\n",
+			KBUILD_MODNAME);
 	return 0;
 
 err_free_controls:
-- 
1.9.3


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

* [PATCH 4/4] MAINTAINERS: add airspy driver
  2014-07-18  1:05 [PATCH 1/4] airspy: remove v4l2-compliance workaround Antti Palosaari
  2014-07-18  1:05 ` [PATCH 2/4] airspy: move out of staging into drivers/media/usb Antti Palosaari
  2014-07-18  1:05 ` [PATCH 3/4] airspy: print notice to point SDR API is not 100% stable yet Antti Palosaari
@ 2014-07-18  1:05 ` Antti Palosaari
  2 siblings, 0 replies; 6+ messages in thread
From: Antti Palosaari @ 2014-07-18  1:05 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Video4Linux2 driver for AirSpy SDR device.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 MAINTAINERS | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 943efe3..f8e2c7f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -508,6 +508,16 @@ S:	Supported
 F:	fs/aio.c
 F:	include/linux/*aio*.h
 
+AIRSPY MEDIA DRIVER
+M:	Antti Palosaari <crope@iki.fi>
+L:	linux-media@vger.kernel.org
+W:	http://linuxtv.org/
+W:	http://palosaari.fi/linux/
+Q:	http://patchwork.linuxtv.org/project/linux-media/list/
+T:	git git://linuxtv.org/anttip/media_tree.git
+S:	Maintained
+F:	drivers/media/usb/airspy/
+
 ALCATEL SPEEDTOUCH USB DRIVER
 M:	Duncan Sands <duncan.sands@free.fr>
 L:	linux-usb@vger.kernel.org
-- 
1.9.3


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

* Re: [PATCH 3/4] airspy: print notice to point SDR API is not 100% stable yet
  2014-07-18  1:05 ` [PATCH 3/4] airspy: print notice to point SDR API is not 100% stable yet Antti Palosaari
@ 2014-07-18  5:15   ` Hans Verkuil
  2014-07-18 16:28     ` Antti Palosaari
  0 siblings, 1 reply; 6+ messages in thread
From: Hans Verkuil @ 2014-07-18  5:15 UTC (permalink / raw)
  To: Antti Palosaari, linux-media

On 07/18/2014 03:05 AM, Antti Palosaari wrote:
> Print notice on driver load: "SDR API is still slightly
> experimental and functionality changes may follow". It is just
> remind possible used SDR API is very new and surprises may occur.
> 
> Signed-off-by: Antti Palosaari <crope@iki.fi>
> ---
>  drivers/media/usb/airspy/airspy.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c
> index 5b3310f..6cf09ef 100644
> --- a/drivers/media/usb/airspy/airspy.c
> +++ b/drivers/media/usb/airspy/airspy.c
> @@ -1086,7 +1086,9 @@ static int airspy_probe(struct usb_interface *intf,
>  	}
>  	dev_info(&s->udev->dev, "Registered as %s\n",
>  			video_device_node_name(&s->vdev));
> -
> +	dev_notice(&s->udev->dev,
> +			"%s: SDR API is still slightly experimental and functionality changes may follow\n",
> +			KBUILD_MODNAME);
>  	return 0;
>  
>  err_free_controls:
> 

On that topic: I would like to see a 'buffersize' or 'samples_per_buffer'
field in struct v4l2_sdr_format. That gives applications the opportunity
to 1) get the current buffer size and 2) be able to change it if the driver
supports that. E.g. for high sampling rates they might want to use larger
buffers, for low they might want to select smaller buffers.

Right now it is fixed and you won't know the buffer size until you do
QUERYBUF. Which is not in sync with what other formats do.

Regards,

	Hans

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

* Re: [PATCH 3/4] airspy: print notice to point SDR API is not 100% stable yet
  2014-07-18  5:15   ` Hans Verkuil
@ 2014-07-18 16:28     ` Antti Palosaari
  0 siblings, 0 replies; 6+ messages in thread
From: Antti Palosaari @ 2014-07-18 16:28 UTC (permalink / raw)
  To: Hans Verkuil, linux-media

Moikka!

On 07/18/2014 08:15 AM, Hans Verkuil wrote:
> On 07/18/2014 03:05 AM, Antti Palosaari wrote:
>> Print notice on driver load: "SDR API is still slightly
>> experimental and functionality changes may follow". It is just
>> remind possible used SDR API is very new and surprises may occur.

>
> On that topic: I would like to see a 'buffersize' or 'samples_per_buffer'
> field in struct v4l2_sdr_format. That gives applications the opportunity
> to 1) get the current buffer size and 2) be able to change it if the driver
> supports that. E.g. for high sampling rates they might want to use larger
> buffers, for low they might want to select smaller buffers.
>
> Right now it is fixed and you won't know the buffer size until you do
> QUERYBUF. Which is not in sync with what other formats do.

I understand what you mean. If you use mmap or userptr then you would 
like to really know how much data you will get per buffer, but if you 
use read then it has no meaning.

I prefer 'buffersize' over 'samples_per_buffer', just because some 
formats are very complex, packed and compressed, and calculating 
'buffersize' from 'samples_per_buffer' could be quite complex.

It is also possible report both, but then you should decide how handle 
situation on S_FMT. Another should be zero and driver uses the one which 
has value !zero.


regards
Antti

-- 
http://palosaari.fi/

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

end of thread, other threads:[~2014-07-18 16:28 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-18  1:05 [PATCH 1/4] airspy: remove v4l2-compliance workaround Antti Palosaari
2014-07-18  1:05 ` [PATCH 2/4] airspy: move out of staging into drivers/media/usb Antti Palosaari
2014-07-18  1:05 ` [PATCH 3/4] airspy: print notice to point SDR API is not 100% stable yet Antti Palosaari
2014-07-18  5:15   ` Hans Verkuil
2014-07-18 16:28     ` Antti Palosaari
2014-07-18  1:05 ` [PATCH 4/4] MAINTAINERS: add airspy driver Antti Palosaari

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.