* [REVIEW PATCH 01/86] rtl2832_sdr: Realtek RTL2832 SDR driver module
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 02/86] rtl28xxu: attach SDR extension module Antti Palosaari
` (86 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Implement SDR driver for Realtek RTL2832U chip as a DVB extension
module. SDR module is attached by DVB USB RTL28XXU driver as a DVB
SEC (satellite equipment controller) module. Abusing unused SEC here
has no harm as that is DVB-T only frontend.
SDR functionality is provided by RTL2832 DVB-T demodulator. I suspect
it is originally planned for DAB and FM, but it could be abused general
SDR, due to modern silicon tuners that has wide frequency range and a
lot of configurable parameters (filters, gains, ...).
http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/44461
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/Kconfig | 2 +
drivers/staging/media/Makefile | 2 +
drivers/staging/media/rtl2832u_sdr/Kconfig | 7 +
drivers/staging/media/rtl2832u_sdr/Makefile | 4 +
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 1184 ++++++++++++++++++++++
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h | 52 +
6 files changed, 1251 insertions(+)
create mode 100644 drivers/staging/media/rtl2832u_sdr/Kconfig
create mode 100644 drivers/staging/media/rtl2832u_sdr/Makefile
create mode 100644 drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
create mode 100644 drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
index 22b0c9d..a9f2e63 100644
--- a/drivers/staging/media/Kconfig
+++ b/drivers/staging/media/Kconfig
@@ -41,6 +41,8 @@ source "drivers/staging/media/solo6x10/Kconfig"
source "drivers/staging/media/omap4iss/Kconfig"
+source "drivers/staging/media/rtl2832u_sdr/Kconfig"
+
# Keep LIRC at the end, as it has sub-menus
source "drivers/staging/media/lirc/Kconfig"
diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile
index bedc62a..8e2c5d2 100644
--- a/drivers/staging/media/Makefile
+++ b/drivers/staging/media/Makefile
@@ -11,3 +11,5 @@ obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/
obj-$(CONFIG_USB_SN9C102) += sn9c102/
obj-$(CONFIG_VIDEO_OMAP2) += omap24xx/
obj-$(CONFIG_VIDEO_TCM825X) += omap24xx/
+obj-$(CONFIG_DVB_RTL2832_SDR) += rtl2832u_sdr/
+
diff --git a/drivers/staging/media/rtl2832u_sdr/Kconfig b/drivers/staging/media/rtl2832u_sdr/Kconfig
new file mode 100644
index 0000000..3ede5fe
--- /dev/null
+++ b/drivers/staging/media/rtl2832u_sdr/Kconfig
@@ -0,0 +1,7 @@
+config DVB_RTL2832_SDR
+ tristate "Realtek RTL2832 SDR"
+ depends on USB && DVB_CORE && I2C && VIDEO_V4L2 && DVB_USB_RTL28XXU
+ select DVB_RTL2832
+ select VIDEOBUF2_VMALLOC
+ default m if !MEDIA_SUBDRV_AUTOSELECT
+
diff --git a/drivers/staging/media/rtl2832u_sdr/Makefile b/drivers/staging/media/rtl2832u_sdr/Makefile
new file mode 100644
index 0000000..684546776
--- /dev/null
+++ b/drivers/staging/media/rtl2832u_sdr/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_DVB_RTL2832_SDR) += rtl2832_sdr.o
+
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/usb/dvb-usb-v2
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
new file mode 100644
index 0000000..0b110a3
--- /dev/null
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -0,0 +1,1184 @@
+/*
+ * Realtek RTL2832U SDR driver
+ *
+ * Copyright (C) 2013 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * 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"
+#include "rtl2832_sdr.h"
+#include "dvb_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>
+
+/* 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 MAX_BULK_BUFS (8)
+#define BULK_BUFFER_SIZE (8 * 512)
+
+/* 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 */
+ struct list_head list;
+};
+
+struct rtl2832_sdr_state {
+#define POWER_ON (1 << 1)
+#define URB_BUF (1 << 2)
+ unsigned long flags;
+
+ const struct rtl2832_sdr_config *cfg;
+ struct dvb_frontend *fe;
+ struct dvb_usb_device *d;
+ struct i2c_adapter *i2c;
+ u8 bank;
+
+ 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 */
+
+ /* 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 */
+
+ /* Pointer to our usb_device, will be NULL after unplug */
+ struct usb_device *udev; /* Both mutexes most be hold when setting! */
+
+ unsigned int vb_full; /* vb is full and packets dropped */
+
+ 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;
+
+ /* 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;
+};
+
+/* write multiple hardware registers */
+static int rtl2832_sdr_wr(struct rtl2832_sdr_state *s, u8 reg, const u8 *val,
+ int len)
+{
+ int ret;
+ u8 buf[1 + len];
+ struct i2c_msg msg[1] = {
+ {
+ .addr = s->cfg->i2c_addr,
+ .flags = 0,
+ .len = 1 + len,
+ .buf = buf,
+ }
+ };
+
+ buf[0] = reg;
+ memcpy(&buf[1], val, len);
+
+ ret = i2c_transfer(s->i2c, msg, 1);
+ if (ret == 1) {
+ ret = 0;
+ } else {
+ dev_err(&s->i2c->dev,
+ "%s: I2C wr failed=%d reg=%02x len=%d\n",
+ KBUILD_MODNAME, ret, reg, len);
+ ret = -EREMOTEIO;
+ }
+ return ret;
+}
+
+#if 0
+/* read multiple hardware registers */
+static int rtl2832_sdr_rd(struct rtl2832_sdr_state *s, u8 reg, u8 *val, int len)
+{
+ int ret;
+ struct i2c_msg msg[2] = {
+ {
+ .addr = s->cfg->i2c_addr,
+ .flags = 0,
+ .len = 1,
+ .buf = ®,
+ }, {
+ .addr = s->cfg->i2c_addr,
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = val,
+ }
+ };
+
+ ret = i2c_transfer(s->i2c, msg, 2);
+ if (ret == 2) {
+ ret = 0;
+ } else {
+ dev_err(&s->i2c->dev,
+ "%s: I2C rd failed=%d reg=%02x len=%d\n",
+ KBUILD_MODNAME, ret, reg, len);
+ ret = -EREMOTEIO;
+ }
+ return ret;
+}
+#endif
+
+/* write multiple registers */
+static int rtl2832_sdr_wr_regs(struct rtl2832_sdr_state *s, u16 reg,
+ const u8 *val, int len)
+{
+ int ret;
+ u8 reg2 = (reg >> 0) & 0xff;
+ u8 bank = (reg >> 8) & 0xff;
+
+ /* switch bank if needed */
+ if (bank != s->bank) {
+ ret = rtl2832_sdr_wr(s, 0x00, &bank, 1);
+ if (ret)
+ return ret;
+
+ s->bank = bank;
+ }
+
+ return rtl2832_sdr_wr(s, reg2, val, len);
+}
+
+#if 0
+/* read multiple registers */
+static int rtl2832_sdr_rd_regs(struct rtl2832_sdr_state *s, u16 reg, u8 *val,
+ int len)
+{
+ int ret;
+ u8 reg2 = (reg >> 0) & 0xff;
+ u8 bank = (reg >> 8) & 0xff;
+
+ /* switch bank if needed */
+ if (bank != s->bank) {
+ ret = rtl2832_sdr_wr(s, 0x00, &bank, 1);
+ if (ret)
+ return ret;
+
+ s->bank = bank;
+ }
+
+ return rtl2832_sdr_rd(s, reg2, val, len);
+}
+
+/* read single register */
+static int rtl2832_sdr_rd_reg(struct rtl2832_sdr_state *s, u16 reg, u8 *val)
+{
+ return rtl2832_sdr_rd_regs(s, reg, val, 1);
+}
+
+/* write single register with mask */
+static int rtl2832_sdr_wr_reg_mask(struct rtl2832_sdr_state *s, u16 reg,
+ u8 val, u8 mask)
+{
+ int ret;
+ u8 tmp;
+
+ /* no need for read if whole reg is written */
+ if (mask != 0xff) {
+ ret = rtl2832_sdr_rd_regs(s, reg, &tmp, 1);
+ if (ret)
+ return ret;
+
+ val &= mask;
+ tmp &= ~mask;
+ val |= tmp;
+ }
+
+ return rtl2832_sdr_wr_regs(s, reg, &val, 1);
+}
+
+/* read single register with mask */
+static int rtl2832_sdr_rd_reg_mask(struct rtl2832_sdr_state *s, u16 reg,
+ u8 *val, u8 mask)
+{
+ int ret, i;
+ u8 tmp;
+
+ ret = rtl2832_sdr_rd_regs(s, reg, &tmp, 1);
+ if (ret)
+ return ret;
+
+ tmp &= mask;
+
+ /* find position of the first bit */
+ for (i = 0; i < 8; i++) {
+ if ((mask >> i) & 0x01)
+ break;
+ }
+ *val = tmp >> i;
+
+ return 0;
+}
+#endif
+
+/* Private functions */
+static struct rtl2832_sdr_frame_buf *rtl2832_sdr_get_next_fill_buf(
+ struct rtl2832_sdr_state *s)
+{
+ unsigned long flags = 0;
+ struct rtl2832_sdr_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 rtl2832_sdr_frame_buf, list);
+ list_del(&buf->list);
+leave:
+ spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
+ return buf;
+}
+
+/*
+ * 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)
+
+/*
+ * Converts signed 8-bit integer into 32-bit IEEE floating point
+ * representation.
+ */
+static u32 rtl2832_sdr_convert_sample(struct rtl2832_sdr_state *s, u16 x)
+{
+ u32 msb, exponent, fraction, sign;
+
+ /* Zero is special */
+ if (!x)
+ return 0;
+
+ /* Negative / positive value */
+ if (x & (1 << 7)) {
+ x = -x;
+ x &= 0x7f; /* result is 7 bit ... + sign */
+ sign = 1 << 31;
+ } else {
+ sign = 0 << 31;
+ }
+
+ /* Get location of the most significant bit */
+ msb = __fls(x);
+
+ fraction = ror32(x, (msb - I2F_FRAC_BITS) & 0x1f) & I2F_MASK;
+ exponent = (127 + msb) << I2F_FRAC_BITS;
+
+ return (fraction + exponent) | sign;
+}
+
+static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s,
+ u32 *dst, const u8 *src, unsigned int src_len)
+{
+ unsigned int i, dst_len = 0;
+
+ for (i = 0; i < src_len; i++)
+ *dst++ = rtl2832_sdr_convert_sample(s, src[i]);
+
+ /* 8-bit to 32-bit IEEE floating point */
+ dst_len = src_len * 4;
+
+ /* 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);
+ unsigned int samples = s->sample - s->sample_measured;
+ s->jiffies = jiffies_now;
+ 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);
+ }
+
+ /* total number of I+Q pairs */
+ 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 rtl2832_sdr_urb_complete(struct urb *urb)
+{
+ struct rtl2832_sdr_state *s = urb->context;
+ struct rtl2832_sdr_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 (urb->actual_length > 0) {
+ void *ptr;
+ unsigned int len;
+ /* get free framebuffer */
+ fbuf = rtl2832_sdr_get_next_fill_buf(s);
+ if (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 = rtl2832_sdr_convert_stream(s, ptr, urb->transfer_buffer,
+ urb->actual_length);
+ vb2_set_plane_payload(&fbuf->vb, 0, len);
+ vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
+ }
+skip:
+ usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+static int rtl2832_sdr_kill_urbs(struct rtl2832_sdr_state *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 rtl2832_sdr_submit_urbs(struct rtl2832_sdr_state *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);
+ rtl2832_sdr_kill_urbs(s);
+ return ret;
+ }
+ s->urbs_submitted++;
+ }
+
+ return 0;
+}
+
+static int rtl2832_sdr_free_stream_bufs(struct rtl2832_sdr_state *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 rtl2832_sdr_alloc_stream_bufs(struct rtl2832_sdr_state *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);
+ rtl2832_sdr_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 rtl2832_sdr_free_urbs(struct rtl2832_sdr_state *s)
+{
+ int i;
+
+ rtl2832_sdr_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 rtl2832_sdr_alloc_urbs(struct rtl2832_sdr_state *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,
+ rtl2832_sdr_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 rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_state *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 rtl2832_sdr_frame_buf *buf;
+ buf = list_entry(s->queued_bufs.next,
+ struct rtl2832_sdr_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 rtl2832_sdr_release_sec(struct dvb_frontend *fe)
+{
+ struct rtl2832_sdr_state *s = fe->sec_priv;
+ 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);
+
+ fe->sec_priv = NULL;
+}
+
+static int rtl2832_sdr_querycap(struct file *file, void *fh,
+ struct v4l2_capability *cap)
+{
+ struct rtl2832_sdr_state *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_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
+ V4L2_CAP_READWRITE;
+ cap->device_caps = V4L2_CAP_TUNER;
+ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+ return 0;
+}
+
+/* Videobuf2 operations */
+static int rtl2832_sdr_queue_setup(struct vb2_queue *vq,
+ const struct v4l2_format *fmt, unsigned int *nbuffers,
+ unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
+{
+ struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq);
+ dev_dbg(&s->udev->dev, "%s: *nbuffers=%d\n", __func__, *nbuffers);
+
+ /* 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 */
+ dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n",
+ __func__, *nbuffers, sizes[0]);
+ return 0;
+}
+
+static int rtl2832_sdr_buf_prepare(struct vb2_buffer *vb)
+{
+ struct rtl2832_sdr_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 rtl2832_sdr_buf_queue(struct vb2_buffer *vb)
+{
+ struct rtl2832_sdr_state *s = vb2_get_drv_priv(vb->vb2_queue);
+ struct rtl2832_sdr_frame_buf *buf =
+ container_of(vb, struct rtl2832_sdr_frame_buf, vb);
+ unsigned long flags = 0;
+
+ /* Check the device has not disconnected between prep and queuing */
+ if (!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 rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
+{
+ int ret;
+ unsigned int f_sr;
+
+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+ if (!test_bit(POWER_ON, &s->flags))
+ return 0;
+
+ f_sr = s->ctrl_sampling_rate->val64;
+
+ ret = rtl2832_sdr_wr_regs(s, 0x13e, "\x00\x00", 2);
+ ret = rtl2832_sdr_wr_regs(s, 0x115, "\x00", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x116, "\x00\x00", 2);
+ ret = rtl2832_sdr_wr_regs(s, 0x118, "\x00", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x119, "\x00\x00", 2);
+ ret = rtl2832_sdr_wr_regs(s, 0x11b, "\x00", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x19f, "\x03\x84", 2);
+ ret = rtl2832_sdr_wr_regs(s, 0x1a1, "\x00\x00", 2);
+ ret = rtl2832_sdr_wr_regs(s, 0x11c, "\xca", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x11d, "\xdc", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x11e, "\xd7", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x11f, "\xd8", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x120, "\xe0", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x121, "\xf2", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x122, "\x0e", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x123, "\x35", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x124, "\x06", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x125, "\x50", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x126, "\x9c", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x127, "\x0d", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x128, "\x71", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x129, "\x11", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x12a, "\x14", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x12b, "\x71", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x12c, "\x74", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x12d, "\x19", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x12e, "\x41", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x12f, "\xa5", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x017, "\x11", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x018, "\x10", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x019, "\x21", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x01f, "\xff", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x01e, "\x01", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x01d, "\x06", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x01c, "\x0d", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x01b, "\x16", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x01a, "\x1b", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x192, "\x00", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x193, "\xf0", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x194, "\x0f", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x061, "\x60", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x006, "\x80", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x112, "\x5a", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x102, "\x40", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x103, "\x5a", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x30", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x104, "\xd0", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x18", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x106, "\x35", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1c9, "\x21", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1ca, "\x21", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1cb, "\x00", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x107, "\x40", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1cd, "\x10", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1ce, "\x10", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x108, "\x80", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x109, "\x7f", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x10a, "\x80", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x10b, "\x7f", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x011, "\xd4", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1e5, "\xf0", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1d9, "\x00", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1db, "\x00", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1dd, "\x14", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1de, "\xec", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1d8, "\x0c", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1e6, "\x02", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1d7, "\x09", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x83", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x010, "\x49", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x87", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x85", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x013, "\x02", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x008, "\xcd", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1b1, "\x01", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x101, "\x14", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x101, "\x10", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x019, "\x21", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x10c, "\x00", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x101, "\x14", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x101, "\x10", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x116, "\x00\xe3", 2);
+ ret = rtl2832_sdr_wr_regs(s, 0x118, "\x8e", 1);
+
+ return ret;
+};
+
+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)
+ */
+ unsigned int bandwidth = s->ctrl_tuner_bw->val;
+
+ /*
+ * intermediate frequency (Hz)
+ */
+ unsigned int f_if = s->ctrl_tuner_if->val;
+
+ /*
+ * gain (dB)
+ */
+ 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);
+
+ if (!test_bit(POWER_ON, &s->flags))
+ return 0;
+
+ if (fe->ops.tuner_ops.init)
+ fe->ops.tuner_ops.init(fe);
+
+ c->bandwidth_hz = bandwidth;
+ c->frequency = f_rf;
+
+ if (fe->ops.tuner_ops.set_params)
+ fe->ops.tuner_ops.set_params(fe);
+
+ return 0;
+};
+
+static void rtl2832_sdr_unset_tuner(struct rtl2832_sdr_state *s)
+{
+ struct dvb_frontend *fe = s->fe;
+
+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+ if (fe->ops.tuner_ops.sleep)
+ fe->ops.tuner_ops.sleep(fe);
+
+ return;
+};
+
+static int rtl2832_sdr_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+ struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq);
+ int ret;
+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+ if (!s->udev)
+ return -ENODEV;
+
+ if (mutex_lock_interruptible(&s->v4l2_lock))
+ return -ERESTARTSYS;
+
+ if (s->d->props->power_ctrl)
+ s->d->props->power_ctrl(s->d, 1);
+
+ set_bit(POWER_ON, &s->flags);
+
+ ret = rtl2832_sdr_set_tuner(s);
+ if (ret)
+ goto err;
+
+ ret = rtl2832_sdr_set_adc(s);
+ if (ret)
+ goto err;
+
+ ret = rtl2832_sdr_alloc_stream_bufs(s);
+ if (ret)
+ goto err;
+
+ ret = rtl2832_sdr_alloc_urbs(s);
+ if (ret)
+ goto err;
+
+ ret = rtl2832_sdr_submit_urbs(s);
+ if (ret)
+ goto err;
+
+err:
+ mutex_unlock(&s->v4l2_lock);
+
+ return ret;
+}
+
+static int rtl2832_sdr_stop_streaming(struct vb2_queue *vq)
+{
+ struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq);
+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+ if (mutex_lock_interruptible(&s->v4l2_lock))
+ return -ERESTARTSYS;
+
+ rtl2832_sdr_kill_urbs(s);
+ rtl2832_sdr_free_urbs(s);
+ rtl2832_sdr_free_stream_bufs(s);
+ rtl2832_sdr_cleanup_queued_bufs(s);
+ rtl2832_sdr_unset_tuner(s);
+
+ clear_bit(POWER_ON, &s->flags);
+
+ if (s->d->props->power_ctrl)
+ s->d->props->power_ctrl(s->d, 0);
+
+ mutex_unlock(&s->v4l2_lock);
+
+ return 0;
+}
+
+static struct vb2_ops rtl2832_sdr_vb2_ops = {
+ .queue_setup = rtl2832_sdr_queue_setup,
+ .buf_prepare = rtl2832_sdr_buf_prepare,
+ .buf_queue = rtl2832_sdr_buf_queue,
+ .start_streaming = rtl2832_sdr_start_streaming,
+ .stop_streaming = rtl2832_sdr_stop_streaming,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+};
+
+static int rtl2832_sdr_enum_input(struct file *file, void *fh, struct v4l2_input *i)
+{
+ if (i->index != 0)
+ 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)
+{
+ *i = 0;
+
+ 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)
+{
+ struct rtl2832_sdr_state *s = video_drvdata(file);
+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+ return 0;
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
+{
+ struct rtl2832_sdr_state *s = video_drvdata(file);
+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+ strcpy(v->name, "SDR RX");
+ v->capability = V4L2_TUNER_CAP_LOW;
+
+ return 0;
+}
+
+static int vidioc_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);
+
+ return v4l2_ctrl_s_ctrl_int64(s->ctrl_tuner_rf,
+ f->frequency * 625UL / 10UL);
+}
+
+static const struct v4l2_ioctl_ops rtl2832_sdr_ioctl_ops = {
+ .vidioc_querycap = rtl2832_sdr_querycap,
+
+ .vidioc_enum_input = rtl2832_sdr_enum_input,
+ .vidioc_g_input = rtl2832_sdr_g_input,
+ .vidioc_s_input = rtl2832_sdr_s_input,
+
+ .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 = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_s_frequency = vidioc_s_frequency,
+
+ .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 rtl2832_sdr_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 rtl2832_sdr_template = {
+ .name = "Realtek RTL2832U SDR",
+ .release = video_device_release_empty,
+ .fops = &rtl2832_sdr_fops,
+ .ioctl_ops = &rtl2832_sdr_ioctl_ops,
+};
+
+static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct rtl2832_sdr_state *s =
+ container_of(ctrl->handler, struct rtl2832_sdr_state,
+ ctrl_handler);
+ int ret;
+ dev_dbg(&s->udev->dev,
+ "%s: id=%d name=%s val=%d min=%d max=%d step=%d\n",
+ __func__, ctrl->id, ctrl->name, ctrl->val,
+ 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;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static const struct v4l2_ctrl_ops rtl2832_sdr_ctrl_ops = {
+ .s_ctrl = rtl2832_sdr_s_ctrl,
+};
+
+static void rtl2832_sdr_video_release(struct v4l2_device *v)
+{
+ struct rtl2832_sdr_state *s =
+ container_of(v, struct rtl2832_sdr_state, v4l2_dev);
+
+ v4l2_ctrl_handler_free(&s->ctrl_handler);
+ v4l2_device_unregister(&s->v4l2_dev);
+ kfree(s);
+}
+
+struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c, const struct rtl2832_sdr_config *cfg)
+{
+ 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 = 500000,
+ .max = 4000000,
+ .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,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Tuner BW",
+ .min = 200000,
+ .max = 8000000,
+ .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,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Tuner Gain",
+ .min = 0,
+ .max = 102,
+ .def = 0,
+ .step = 1,
+ };
+
+ s = kzalloc(sizeof(struct rtl2832_sdr_state), GFP_KERNEL);
+ if (s == NULL) {
+ dev_err(&d->udev->dev,
+ "Could not allocate memory for rtl2832_sdr_state\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /* setup the state */
+ s->fe = fe;
+ s->d = d;
+ s->udev = d->udev;
+ s->i2c = i2c;
+ s->cfg = cfg;
+
+ mutex_init(&s->v4l2_lock);
+ mutex_init(&s->vb_queue_lock);
+ spin_lock_init(&s->queued_bufs_lock);
+ INIT_LIST_HEAD(&s->queued_bufs);
+
+ /* Init videobuf2 queue structure */
+ s->vb_queue.type = V4L2_BUF_TYPE_VIDEO_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);
+ s->vb_queue.ops = &rtl2832_sdr_vb2_ops;
+ 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) {
+ dev_err(&s->udev->dev, "Could not initialize vb2 queue\n");
+ goto err_free_mem;
+ }
+
+ /* Init video_device structure */
+ s->vdev = rtl2832_sdr_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 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);
+ 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;
+ dev_err(&s->udev->dev, "Could not initialize controls\n");
+ goto err_free_controls;
+ }
+
+ /* Register the v4l2_device structure */
+ s->v4l2_dev.release = rtl2832_sdr_video_release;
+ ret = v4l2_device_register(&s->udev->dev, &s->v4l2_dev);
+ if (ret) {
+ dev_err(&s->udev->dev,
+ "Failed to register v4l2-device (%d)\n", ret);
+ goto err_free_controls;
+ }
+
+ s->v4l2_dev.ctrl_handler = &s->ctrl_handler;
+ s->vdev.v4l2_dev = &s->v4l2_dev;
+ s->vdev.lock = &s->v4l2_lock;
+
+ ret = video_register_device(&s->vdev, VFL_TYPE_GRABBER, -1);
+ if (ret < 0) {
+ 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));
+
+ fe->sec_priv = s;
+ fe->ops.release_sec = rtl2832_sdr_release_sec;
+
+ dev_info(&s->i2c->dev, "%s: Realtek RTL2832 SDR attached\n",
+ KBUILD_MODNAME);
+ return fe;
+
+err_unregister_v4l2_dev:
+ v4l2_device_unregister(&s->v4l2_dev);
+err_free_controls:
+ v4l2_ctrl_handler_free(&s->ctrl_handler);
+err_free_mem:
+ kfree(s);
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL(rtl2832_sdr_attach);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Realtek RTL2832 SDR driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h
new file mode 100644
index 0000000..69d97c1
--- /dev/null
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h
@@ -0,0 +1,52 @@
+/*
+ * Realtek RTL2832U SDR driver
+ *
+ * Copyright (C) 2013 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * 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
+ */
+
+#ifndef RTL2832_SDR_H
+#define RTL2832_SDR_H
+
+#include <linux/kconfig.h>
+
+struct rtl2832_sdr_config {
+ u8 i2c_addr;
+};
+
+#if IS_ENABLED(CONFIG_DVB_RTL2832_SDR)
+extern struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c, const struct rtl2832_sdr_config *cfg);
+#else
+static inline struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c, const struct rtl2832_sdr_config *cfg)
+{
+ dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif
+
+#endif /* RTL2832_SDR_H */
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 02/86] rtl28xxu: attach SDR extension module
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 01/86] rtl2832_sdr: Realtek RTL2832 SDR driver module Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 03/86] rtl2832_sdr: use config struct from rtl2832 module Antti Palosaari
` (85 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
With that extension module it supports SDR.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/usb/dvb-usb-v2/Makefile | 1 +
drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 8 ++++++++
2 files changed, 9 insertions(+)
diff --git a/drivers/media/usb/dvb-usb-v2/Makefile b/drivers/media/usb/dvb-usb-v2/Makefile
index 2c06714..bfe67f9 100644
--- a/drivers/media/usb/dvb-usb-v2/Makefile
+++ b/drivers/media/usb/dvb-usb-v2/Makefile
@@ -44,3 +44,4 @@ ccflags-y += -I$(srctree)/drivers/media/dvb-core
ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
ccflags-y += -I$(srctree)/drivers/media/tuners
ccflags-y += -I$(srctree)/drivers/media/common
+ccflags-y += -I$(srctree)/drivers/staging/media/rtl2832u_sdr
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index fda5c64..b398ebf 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -24,6 +24,7 @@
#include "rtl2830.h"
#include "rtl2832.h"
+#include "rtl2832_sdr.h"
#include "qt1010.h"
#include "mt2060.h"
@@ -734,6 +735,9 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
struct dvb_usb_device *d = adap_to_d(adap);
struct rtl28xxu_priv *priv = d_to_priv(d);
struct rtl2832_config *rtl2832_config;
+ static const struct rtl2832_sdr_config rtl2832_sdr_config = {
+ .i2c_addr = 0x10,
+ };
dev_dbg(&d->udev->dev, "%s:\n", __func__);
@@ -775,6 +779,10 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
/* set fe callback */
adap->fe[0]->callback = rtl2832u_frontend_callback;
+ /* attach SDR */
+ dvb_attach(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
+ &rtl2832_sdr_config);
+
return 0;
err:
dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 03/86] rtl2832_sdr: use config struct from rtl2832 module
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 01/86] rtl2832_sdr: Realtek RTL2832 SDR driver module Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 02/86] rtl28xxu: attach SDR extension module Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 04/86] rtl2832_sdr: initial support for R820T tuner Antti Palosaari
` (84 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
There is absolutely no need to define own configuration struct as
same params are used demod main module. So use existing config.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 5 +----
drivers/staging/media/rtl2832u_sdr/Makefile | 1 +
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 4 ++--
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h | 9 ++++-----
4 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index b398ebf..ec6ab0f 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -735,9 +735,6 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
struct dvb_usb_device *d = adap_to_d(adap);
struct rtl28xxu_priv *priv = d_to_priv(d);
struct rtl2832_config *rtl2832_config;
- static const struct rtl2832_sdr_config rtl2832_sdr_config = {
- .i2c_addr = 0x10,
- };
dev_dbg(&d->udev->dev, "%s:\n", __func__);
@@ -781,7 +778,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
/* attach SDR */
dvb_attach(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
- &rtl2832_sdr_config);
+ rtl2832_config);
return 0;
err:
diff --git a/drivers/staging/media/rtl2832u_sdr/Makefile b/drivers/staging/media/rtl2832u_sdr/Makefile
index 684546776..1009276 100644
--- a/drivers/staging/media/rtl2832u_sdr/Makefile
+++ b/drivers/staging/media/rtl2832u_sdr/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_DVB_RTL2832_SDR) += rtl2832_sdr.o
ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
ccflags-y += -Idrivers/media/usb/dvb-usb-v2
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index 0b110a3..208520e 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -61,7 +61,7 @@ struct rtl2832_sdr_state {
#define URB_BUF (1 << 2)
unsigned long flags;
- const struct rtl2832_sdr_config *cfg;
+ const struct rtl2832_config *cfg;
struct dvb_frontend *fe;
struct dvb_usb_device *d;
struct i2c_adapter *i2c;
@@ -1004,7 +1004,7 @@ static void rtl2832_sdr_video_release(struct v4l2_device *v)
}
struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
- struct i2c_adapter *i2c, const struct rtl2832_sdr_config *cfg)
+ struct i2c_adapter *i2c, const struct rtl2832_config *cfg)
{
int ret;
struct rtl2832_sdr_state *s;
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h
index 69d97c1..0803e45 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h
@@ -33,16 +33,15 @@
#include <linux/kconfig.h>
-struct rtl2832_sdr_config {
- u8 i2c_addr;
-};
+/* for config struct */
+#include "rtl2832.h"
#if IS_ENABLED(CONFIG_DVB_RTL2832_SDR)
extern struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
- struct i2c_adapter *i2c, const struct rtl2832_sdr_config *cfg);
+ struct i2c_adapter *i2c, const struct rtl2832_config *cfg);
#else
static inline struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
- struct i2c_adapter *i2c, const struct rtl2832_sdr_config *cfg)
+ struct i2c_adapter *i2c, const struct rtl2832_config *cfg)
{
dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__);
return NULL;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 04/86] rtl2832_sdr: initial support for R820T tuner
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (2 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 03/86] rtl2832_sdr: use config struct from rtl2832 module Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 05/86] rtl2832_sdr: use get_if_frequency() Antti Palosaari
` (83 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Use tuner via internal DVB API.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 84 +++++++++++++++---------
1 file changed, 53 insertions(+), 31 deletions(-)
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index 208520e..513da22 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -646,8 +646,16 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
ret = rtl2832_sdr_wr_regs(s, 0x115, "\x00", 1);
ret = rtl2832_sdr_wr_regs(s, 0x116, "\x00\x00", 2);
ret = rtl2832_sdr_wr_regs(s, 0x118, "\x00", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x119, "\x00\x00", 2);
- ret = rtl2832_sdr_wr_regs(s, 0x11b, "\x00", 1);
+
+ if (s->cfg->tuner == RTL2832_TUNER_R820T) {
+ ret = rtl2832_sdr_wr_regs(s, 0x119, "\x38\x11", 2);
+ ret = rtl2832_sdr_wr_regs(s, 0x11b, "\x12", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x115, "\x01", 1);
+ } else {
+ ret = rtl2832_sdr_wr_regs(s, 0x119, "\x00\x00", 2);
+ ret = rtl2832_sdr_wr_regs(s, 0x11b, "\x00", 1);
+ }
+
ret = rtl2832_sdr_wr_regs(s, 0x19f, "\x03\x84", 2);
ret = rtl2832_sdr_wr_regs(s, 0x1a1, "\x00\x00", 2);
ret = rtl2832_sdr_wr_regs(s, 0x11c, "\xca", 1);
@@ -686,11 +694,21 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
ret = rtl2832_sdr_wr_regs(s, 0x006, "\x80", 1);
ret = rtl2832_sdr_wr_regs(s, 0x112, "\x5a", 1);
ret = rtl2832_sdr_wr_regs(s, 0x102, "\x40", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x103, "\x5a", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x30", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x104, "\xd0", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x18", 1);
+
+ if (s->cfg->tuner == RTL2832_TUNER_R820T) {
+ ret = rtl2832_sdr_wr_regs(s, 0x103, "\x80", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x24", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x104, "\xcc", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x14", 1);
+ } else {
+ ret = rtl2832_sdr_wr_regs(s, 0x103, "\x5a", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x30", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x104, "\xd0", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x18", 1);
+ }
+
ret = rtl2832_sdr_wr_regs(s, 0x106, "\x35", 1);
ret = rtl2832_sdr_wr_regs(s, 0x1c9, "\x21", 1);
ret = rtl2832_sdr_wr_regs(s, 0x1ca, "\x21", 1);
@@ -704,30 +722,34 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
ret = rtl2832_sdr_wr_regs(s, 0x10b, "\x7f", 1);
ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x011, "\xd4", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1e5, "\xf0", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1d9, "\x00", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1db, "\x00", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1dd, "\x14", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1de, "\xec", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1d8, "\x0c", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1e6, "\x02", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1d7, "\x09", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x83", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x010, "\x49", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x87", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x85", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x013, "\x02", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x008, "\xcd", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1b1, "\x01", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x101, "\x14", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x101, "\x10", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x019, "\x21", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x10c, "\x00", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x101, "\x14", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x101, "\x10", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x116, "\x00\xe3", 2);
- ret = rtl2832_sdr_wr_regs(s, 0x118, "\x8e", 1);
+
+ if (s->cfg->tuner == RTL2832_TUNER_R820T) {
+ ret = rtl2832_sdr_wr_regs(s, 0x011, "\xf4", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x101, "\x14", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x101, "\x10", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x019, "\x21", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x116, "\x00\x00", 2);
+ ret = rtl2832_sdr_wr_regs(s, 0x118, "\x00", 1);
+ } else {
+ ret = rtl2832_sdr_wr_regs(s, 0x011, "\xd4", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1e5, "\xf0", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1d9, "\x00", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1db, "\x00", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1dd, "\x14", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1de, "\xec", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1d8, "\x0c", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1e6, "\x02", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1d7, "\x09", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x83", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x010, "\x49", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x87", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x85", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x013, "\x02", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x008, "\xcd", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x10c, "\x00", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x101, "\x14", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x101, "\x10", 1);
+ }
return ret;
};
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 05/86] rtl2832_sdr: use get_if_frequency()
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (3 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 04/86] rtl2832_sdr: initial support for R820T tuner Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 06/86] rtl2832_sdr: implement sampling rate Antti Palosaari
` (82 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Get IF from tuner and use it.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 60 ++++++++++++++++++++----
1 file changed, 51 insertions(+), 9 deletions(-)
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index 513da22..c4b72c1 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -208,7 +208,15 @@ static int rtl2832_sdr_rd_regs(struct rtl2832_sdr_state *s, u16 reg, u8 *val,
return rtl2832_sdr_rd(s, reg2, val, len);
}
+#endif
+/* write single register */
+static int rtl2832_sdr_wr_reg(struct rtl2832_sdr_state *s, u16 reg, u8 val)
+{
+ return rtl2832_sdr_wr_regs(s, reg, &val, 1);
+}
+
+#if 0
/* read single register */
static int rtl2832_sdr_rd_reg(struct rtl2832_sdr_state *s, u16 reg, u8 *val)
{
@@ -632,8 +640,12 @@ static void rtl2832_sdr_buf_queue(struct vb2_buffer *vb)
static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
{
+ struct dvb_frontend *fe = s->fe;
int ret;
- unsigned int f_sr;
+ unsigned int f_sr, f_if;
+ u8 buf[3], tmp;
+ u64 u64tmp;
+ u32 u32tmp;
dev_dbg(&s->udev->dev, "%s:\n", __func__);
@@ -647,14 +659,42 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
ret = rtl2832_sdr_wr_regs(s, 0x116, "\x00\x00", 2);
ret = rtl2832_sdr_wr_regs(s, 0x118, "\x00", 1);
- if (s->cfg->tuner == RTL2832_TUNER_R820T) {
- ret = rtl2832_sdr_wr_regs(s, 0x119, "\x38\x11", 2);
- ret = rtl2832_sdr_wr_regs(s, 0x11b, "\x12", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x115, "\x01", 1);
- } else {
- ret = rtl2832_sdr_wr_regs(s, 0x119, "\x00\x00", 2);
- ret = rtl2832_sdr_wr_regs(s, 0x11b, "\x00", 1);
- }
+ /* get IF from tuner */
+ if (fe->ops.tuner_ops.get_if_frequency)
+ ret = fe->ops.tuner_ops.get_if_frequency(fe, &f_if);
+ else
+ ret = -EINVAL;
+
+ if (ret)
+ goto err;
+
+ /* program IF */
+ u64tmp = f_if % s->cfg->xtal;
+ u64tmp *= 0x400000;
+ u64tmp = div_u64(u64tmp, s->cfg->xtal);
+ u64tmp = -u64tmp;
+ u32tmp = u64tmp & 0x3fffff;
+
+ dev_dbg(&s->udev->dev, "%s: f_if=%u if_ctl=%08x\n",
+ __func__, f_if, u32tmp);
+
+ buf[0] = (u32tmp >> 16) & 0xff;
+ buf[1] = (u32tmp >> 8) & 0xff;
+ buf[2] = (u32tmp >> 0) & 0xff;
+
+ ret = rtl2832_sdr_wr_regs(s, 0x119, buf, 3);
+ if (ret)
+ goto err;
+
+ /* program BB / IF mode */
+ if (f_if)
+ tmp = 0x00;
+ else
+ tmp = 0x01;
+
+ ret = rtl2832_sdr_wr_reg(s, 0x1b1, tmp);
+ if (ret)
+ goto err;
ret = rtl2832_sdr_wr_regs(s, 0x19f, "\x03\x84", 2);
ret = rtl2832_sdr_wr_regs(s, 0x1a1, "\x00\x00", 2);
@@ -696,6 +736,7 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
ret = rtl2832_sdr_wr_regs(s, 0x102, "\x40", 1);
if (s->cfg->tuner == RTL2832_TUNER_R820T) {
+ ret = rtl2832_sdr_wr_regs(s, 0x115, "\x01", 1);
ret = rtl2832_sdr_wr_regs(s, 0x103, "\x80", 1);
ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x24", 1);
ret = rtl2832_sdr_wr_regs(s, 0x104, "\xcc", 1);
@@ -751,6 +792,7 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
ret = rtl2832_sdr_wr_regs(s, 0x101, "\x10", 1);
}
+err:
return ret;
};
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 06/86] rtl2832_sdr: implement sampling rate
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (4 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 05/86] rtl2832_sdr: use get_if_frequency() Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 07/86] rtl2832_sdr: initial support for FC0012 tuner Antti Palosaari
` (81 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Now it is possible to set desired sampling rate via v4l2 controls.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 21 ++++++++++++++++-----
1 file changed, 16 insertions(+), 5 deletions(-)
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index c4b72c1..0e12e1a 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -38,6 +38,8 @@
#include <media/v4l2-event.h>
#include <media/videobuf2-vmalloc.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)
@@ -643,7 +645,7 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
struct dvb_frontend *fe = s->fe;
int ret;
unsigned int f_sr, f_if;
- u8 buf[3], tmp;
+ u8 buf[4], tmp;
u64 u64tmp;
u32 u32tmp;
@@ -696,8 +698,17 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
if (ret)
goto err;
- ret = rtl2832_sdr_wr_regs(s, 0x19f, "\x03\x84", 2);
- ret = rtl2832_sdr_wr_regs(s, 0x1a1, "\x00\x00", 2);
+ /* program sampling rate (resampling down) */
+ u32tmp = div_u64(s->cfg->xtal * 0x400000ULL, f_sr * 4U);
+ u32tmp <<= 2;
+ buf[0] = (u32tmp >> 24) & 0xff;
+ buf[1] = (u32tmp >> 16) & 0xff;
+ buf[2] = (u32tmp >> 8) & 0xff;
+ buf[3] = (u32tmp >> 0) & 0xff;
+ ret = rtl2832_sdr_wr_regs(s, 0x19f, buf, 4);
+ if (ret)
+ goto err;
+
ret = rtl2832_sdr_wr_regs(s, 0x11c, "\xca", 1);
ret = rtl2832_sdr_wr_regs(s, 0x11d, "\xdc", 1);
ret = rtl2832_sdr_wr_regs(s, 0x11e, "\xd7", 1);
@@ -1090,8 +1101,8 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
.id = RTL2832_SDR_CID_SAMPLING_RATE,
.type = V4L2_CTRL_TYPE_INTEGER64,
.name = "Sampling Rate",
- .min = 500000,
- .max = 4000000,
+ .min = 900001,
+ .max = 2800000,
.def = 2048000,
.step = 1,
};
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 07/86] rtl2832_sdr: initial support for FC0012 tuner
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (5 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 06/86] rtl2832_sdr: implement sampling rate Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 08/86] rtl2832_sdr: initial support for FC0013 tuner Antti Palosaari
` (80 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Use tuner via internal DVB API.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index 0e12e1a..c088957 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -753,6 +753,12 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
ret = rtl2832_sdr_wr_regs(s, 0x104, "\xcc", 1);
ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1);
ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x14", 1);
+ } else if (s->cfg->tuner == RTL2832_TUNER_FC0012) {
+ ret = rtl2832_sdr_wr_regs(s, 0x103, "\x5a", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x2c", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x104, "\xcc", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x16", 1);
} else {
ret = rtl2832_sdr_wr_regs(s, 0x103, "\x5a", 1);
ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x30", 1);
@@ -782,6 +788,19 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
ret = rtl2832_sdr_wr_regs(s, 0x019, "\x21", 1);
ret = rtl2832_sdr_wr_regs(s, 0x116, "\x00\x00", 2);
ret = rtl2832_sdr_wr_regs(s, 0x118, "\x00", 1);
+ } else if (s->cfg->tuner == RTL2832_TUNER_FC0012) {
+ ret = rtl2832_sdr_wr_regs(s, 0x011, "\xe9\xbf", 2);
+ ret = rtl2832_sdr_wr_regs(s, 0x1e5, "\xf0", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1d9, "\x00", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1db, "\x00", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1dd, "\x11", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1de, "\xef", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1d8, "\x0c", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1e6, "\x02", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1d7, "\x09", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x008, "\xcd", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x101, "\x14", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x101, "\x10", 1);
} else {
ret = rtl2832_sdr_wr_regs(s, 0x011, "\xd4", 1);
ret = rtl2832_sdr_wr_regs(s, 0x1e5, "\xf0", 1);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 08/86] rtl2832_sdr: initial support for FC0013 tuner
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (6 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 07/86] rtl2832_sdr: initial support for FC0012 tuner Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 09/86] rtl28xxu: constify demod config structs Antti Palosaari
` (79 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Use tuner via internal DVB API.
It is about same tuner than FC0012 and uses just same settings.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index c088957..2c84654 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -753,7 +753,8 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
ret = rtl2832_sdr_wr_regs(s, 0x104, "\xcc", 1);
ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1);
ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x14", 1);
- } else if (s->cfg->tuner == RTL2832_TUNER_FC0012) {
+ } else if (s->cfg->tuner == RTL2832_TUNER_FC0012 ||
+ s->cfg->tuner == RTL2832_TUNER_FC0013) {
ret = rtl2832_sdr_wr_regs(s, 0x103, "\x5a", 1);
ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x2c", 1);
ret = rtl2832_sdr_wr_regs(s, 0x104, "\xcc", 1);
@@ -788,7 +789,8 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
ret = rtl2832_sdr_wr_regs(s, 0x019, "\x21", 1);
ret = rtl2832_sdr_wr_regs(s, 0x116, "\x00\x00", 2);
ret = rtl2832_sdr_wr_regs(s, 0x118, "\x00", 1);
- } else if (s->cfg->tuner == RTL2832_TUNER_FC0012) {
+ } else if (s->cfg->tuner == RTL2832_TUNER_FC0012 ||
+ s->cfg->tuner == RTL2832_TUNER_FC0013) {
ret = rtl2832_sdr_wr_regs(s, 0x011, "\xe9\xbf", 2);
ret = rtl2832_sdr_wr_regs(s, 0x1e5, "\xf0", 1);
ret = rtl2832_sdr_wr_regs(s, 0x1d9, "\x00", 1);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 09/86] rtl28xxu: constify demod config structs
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (7 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 08/86] rtl2832_sdr: initial support for FC0013 tuner Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 10/86] rtl2832: remove unused if_dvbt config parameter Antti Palosaari
` (78 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Optimize a little bit from data to text.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index ec6ab0f..c0e651a 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -514,7 +514,7 @@ err:
return ret;
}
-static struct rtl2830_config rtl28xxu_rtl2830_mt2060_config = {
+static const struct rtl2830_config rtl28xxu_rtl2830_mt2060_config = {
.i2c_addr = 0x10, /* 0x20 */
.xtal = 28800000,
.ts_mode = 0,
@@ -525,7 +525,7 @@ static struct rtl2830_config rtl28xxu_rtl2830_mt2060_config = {
};
-static struct rtl2830_config rtl28xxu_rtl2830_qt1010_config = {
+static const struct rtl2830_config rtl28xxu_rtl2830_qt1010_config = {
.i2c_addr = 0x10, /* 0x20 */
.xtal = 28800000,
.ts_mode = 0,
@@ -535,7 +535,7 @@ static struct rtl2830_config rtl28xxu_rtl2830_qt1010_config = {
.agc_targ_val = 0x2d,
};
-static struct rtl2830_config rtl28xxu_rtl2830_mxl5005s_config = {
+static const struct rtl2830_config rtl28xxu_rtl2830_mxl5005s_config = {
.i2c_addr = 0x10, /* 0x20 */
.xtal = 28800000,
.ts_mode = 0,
@@ -549,7 +549,7 @@ static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dvb_usb_device *d = adap_to_d(adap);
struct rtl28xxu_priv *priv = d_to_priv(d);
- struct rtl2830_config *rtl2830_config;
+ const struct rtl2830_config *rtl2830_config;
int ret;
dev_dbg(&d->udev->dev, "%s:\n", __func__);
@@ -584,33 +584,33 @@ err:
return ret;
}
-static struct rtl2832_config rtl28xxu_rtl2832_fc0012_config = {
+static const struct rtl2832_config rtl28xxu_rtl2832_fc0012_config = {
.i2c_addr = 0x10, /* 0x20 */
.xtal = 28800000,
.if_dvbt = 0,
.tuner = TUNER_RTL2832_FC0012
};
-static struct rtl2832_config rtl28xxu_rtl2832_fc0013_config = {
+static const struct rtl2832_config rtl28xxu_rtl2832_fc0013_config = {
.i2c_addr = 0x10, /* 0x20 */
.xtal = 28800000,
.if_dvbt = 0,
.tuner = TUNER_RTL2832_FC0013
};
-static struct rtl2832_config rtl28xxu_rtl2832_tua9001_config = {
+static const struct rtl2832_config rtl28xxu_rtl2832_tua9001_config = {
.i2c_addr = 0x10, /* 0x20 */
.xtal = 28800000,
.tuner = TUNER_RTL2832_TUA9001,
};
-static struct rtl2832_config rtl28xxu_rtl2832_e4000_config = {
+static const struct rtl2832_config rtl28xxu_rtl2832_e4000_config = {
.i2c_addr = 0x10, /* 0x20 */
.xtal = 28800000,
.tuner = TUNER_RTL2832_E4000,
};
-static struct rtl2832_config rtl28xxu_rtl2832_r820t_config = {
+static const struct rtl2832_config rtl28xxu_rtl2832_r820t_config = {
.i2c_addr = 0x10,
.xtal = 28800000,
.tuner = TUNER_RTL2832_R820T,
@@ -734,7 +734,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
int ret;
struct dvb_usb_device *d = adap_to_d(adap);
struct rtl28xxu_priv *priv = d_to_priv(d);
- struct rtl2832_config *rtl2832_config;
+ const struct rtl2832_config *rtl2832_config;
dev_dbg(&d->udev->dev, "%s:\n", __func__);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 10/86] rtl2832: remove unused if_dvbt config parameter
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (8 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 09/86] rtl28xxu: constify demod config structs Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 11/86] rtl2832: style changes and minor cleanup Antti Palosaari
` (77 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
All used tuners has get_if_frequency() callback and that parameter
is not needed and will not needed as all upcoming tuner drivers
should implement get_if_frequency().
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/dvb-frontends/rtl2832.c | 6 ------
drivers/media/dvb-frontends/rtl2832.h | 7 -------
drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 2 --
3 files changed, 15 deletions(-)
diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c
index ff73da9..61d4ecb 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -514,12 +514,6 @@ static int rtl2832_init(struct dvb_frontend *fe)
goto err;
}
- if (!fe->ops.tuner_ops.get_if_frequency) {
- ret = rtl2832_set_if(fe, priv->cfg.if_dvbt);
- if (ret)
- goto err;
- }
-
/*
* r820t NIM code does a software reset here at the demod -
* may not be needed, as there's already a software reset at set_params()
diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h
index 2cfbb6a..e543081 100644
--- a/drivers/media/dvb-frontends/rtl2832.h
+++ b/drivers/media/dvb-frontends/rtl2832.h
@@ -38,13 +38,6 @@ struct rtl2832_config {
u32 xtal;
/*
- * IFs for all used modes.
- * Hz
- * 4570000, 4571429, 36000000, 36125000, 36166667, 44000000
- */
- u32 if_dvbt;
-
- /*
* tuner
* XXX: This must be keep sync with dvb_usb_rtl28xxu demod driver.
*/
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index c0e651a..6a5eb0f 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -587,14 +587,12 @@ err:
static const struct rtl2832_config rtl28xxu_rtl2832_fc0012_config = {
.i2c_addr = 0x10, /* 0x20 */
.xtal = 28800000,
- .if_dvbt = 0,
.tuner = TUNER_RTL2832_FC0012
};
static const struct rtl2832_config rtl28xxu_rtl2832_fc0013_config = {
.i2c_addr = 0x10, /* 0x20 */
.xtal = 28800000,
- .if_dvbt = 0,
.tuner = TUNER_RTL2832_FC0013
};
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 11/86] rtl2832: style changes and minor cleanup
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (9 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 10/86] rtl2832: remove unused if_dvbt config parameter Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 12/86] rtl2832_sdr: pixel format for SDR Antti Palosaari
` (76 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Most of those were reported by checkpatch.pl...
debug module parameter is not used anywhere so remove it.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/dvb-frontends/rtl2832.c | 26 +++++++---------
drivers/media/dvb-frontends/rtl2832.h | 2 +-
drivers/media/dvb-frontends/rtl2832_priv.h | 50 +++++++++++++++---------------
3 files changed, 38 insertions(+), 40 deletions(-)
diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c
index 61d4ecb..00e63b9 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -24,11 +24,6 @@
/* Max transfer size done by I2C transfer functions */
#define MAX_XFER_SIZE 64
-
-int rtl2832_debug;
-module_param_named(debug, rtl2832_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
#define REG_MASK(b) (BIT(b + 1) - 1)
static const struct rtl2832_reg_entry registers[] = {
@@ -189,8 +184,9 @@ static int rtl2832_wr(struct rtl2832_priv *priv, u8 reg, u8 *val, int len)
if (ret == 1) {
ret = 0;
} else {
- dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
- "len=%d\n", KBUILD_MODNAME, ret, reg, len);
+ dev_warn(&priv->i2c->dev,
+ "%s: i2c wr failed=%d reg=%02x len=%d\n",
+ KBUILD_MODNAME, ret, reg, len);
ret = -EREMOTEIO;
}
return ret;
@@ -218,8 +214,9 @@ static int rtl2832_rd(struct rtl2832_priv *priv, u8 reg, u8 *val, int len)
if (ret == 2) {
ret = 0;
} else {
- dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
- "len=%d\n", KBUILD_MODNAME, ret, reg, len);
+ dev_warn(&priv->i2c->dev,
+ "%s: i2c rd failed=%d reg=%02x len=%d\n",
+ KBUILD_MODNAME, ret, reg, len);
ret = -EREMOTEIO;
}
return ret;
@@ -417,7 +414,7 @@ static int rtl2832_set_if(struct dvb_frontend *fe, u32 if_freq)
ret = rtl2832_wr_demod_reg(priv, DVBT_PSET_IFFREQ, pset_iffreq);
- return (ret);
+ return ret;
}
static int rtl2832_init(struct dvb_frontend *fe)
@@ -516,7 +513,8 @@ static int rtl2832_init(struct dvb_frontend *fe)
/*
* r820t NIM code does a software reset here at the demod -
- * may not be needed, as there's already a software reset at set_params()
+ * may not be needed, as there's already a software reset at
+ * set_params()
*/
#if 1
/* soft reset */
@@ -593,9 +591,9 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe)
};
- dev_dbg(&priv->i2c->dev, "%s: frequency=%d bandwidth_hz=%d " \
- "inversion=%d\n", __func__, c->frequency,
- c->bandwidth_hz, c->inversion);
+ dev_dbg(&priv->i2c->dev,
+ "%s: frequency=%d bandwidth_hz=%d inversion=%d\n",
+ __func__, c->frequency, c->bandwidth_hz, c->inversion);
/* program tuner */
if (fe->ops.tuner_ops.set_params)
diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h
index e543081..fa4e5f6 100644
--- a/drivers/media/dvb-frontends/rtl2832.h
+++ b/drivers/media/dvb-frontends/rtl2832.h
@@ -51,7 +51,7 @@ struct rtl2832_config {
};
#if IS_ENABLED(CONFIG_DVB_RTL2832)
-extern struct dvb_frontend *rtl2832_attach(
+struct dvb_frontend *rtl2832_attach(
const struct rtl2832_config *cfg,
struct i2c_adapter *i2c
);
diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h
index b5f2b80..4c845af 100644
--- a/drivers/media/dvb-frontends/rtl2832_priv.h
+++ b/drivers/media/dvb-frontends/rtl2832_priv.h
@@ -267,7 +267,7 @@ static const struct rtl2832_reg_value rtl2832_tuner_init_tua9001[] = {
{DVBT_OPT_ADC_IQ, 0x1},
{DVBT_AD_AVI, 0x0},
{DVBT_AD_AVQ, 0x0},
- {DVBT_SPEC_INV, 0x0},
+ {DVBT_SPEC_INV, 0x0},
};
static const struct rtl2832_reg_value rtl2832_tuner_init_fc0012[] = {
@@ -301,7 +301,7 @@ static const struct rtl2832_reg_value rtl2832_tuner_init_fc0012[] = {
{DVBT_GI_PGA_STATE, 0x0},
{DVBT_EN_AGC_PGA, 0x1},
{DVBT_IF_AGC_MAN, 0x0},
- {DVBT_SPEC_INV, 0x0},
+ {DVBT_SPEC_INV, 0x0},
};
static const struct rtl2832_reg_value rtl2832_tuner_init_e4000[] = {
@@ -339,32 +339,32 @@ static const struct rtl2832_reg_value rtl2832_tuner_init_e4000[] = {
{DVBT_REG_MONSEL, 0x1},
{DVBT_REG_MON, 0x1},
{DVBT_REG_4MSEL, 0x0},
- {DVBT_SPEC_INV, 0x0},
+ {DVBT_SPEC_INV, 0x0},
};
static const struct rtl2832_reg_value rtl2832_tuner_init_r820t[] = {
- {DVBT_DAGC_TRG_VAL, 0x39},
- {DVBT_AGC_TARG_VAL_0, 0x0},
- {DVBT_AGC_TARG_VAL_8_1, 0x40},
- {DVBT_AAGC_LOOP_GAIN, 0x16},
- {DVBT_LOOP_GAIN2_3_0, 0x8},
- {DVBT_LOOP_GAIN2_4, 0x1},
- {DVBT_LOOP_GAIN3, 0x18},
- {DVBT_VTOP1, 0x35},
- {DVBT_VTOP2, 0x21},
- {DVBT_VTOP3, 0x21},
- {DVBT_KRF1, 0x0},
- {DVBT_KRF2, 0x40},
- {DVBT_KRF3, 0x10},
- {DVBT_KRF4, 0x10},
- {DVBT_IF_AGC_MIN, 0x80},
- {DVBT_IF_AGC_MAX, 0x7f},
- {DVBT_RF_AGC_MIN, 0x80},
- {DVBT_RF_AGC_MAX, 0x7f},
- {DVBT_POLAR_RF_AGC, 0x0},
- {DVBT_POLAR_IF_AGC, 0x0},
- {DVBT_AD7_SETTING, 0xe9f4},
- {DVBT_SPEC_INV, 0x1},
+ {DVBT_DAGC_TRG_VAL, 0x39},
+ {DVBT_AGC_TARG_VAL_0, 0x0},
+ {DVBT_AGC_TARG_VAL_8_1, 0x40},
+ {DVBT_AAGC_LOOP_GAIN, 0x16},
+ {DVBT_LOOP_GAIN2_3_0, 0x8},
+ {DVBT_LOOP_GAIN2_4, 0x1},
+ {DVBT_LOOP_GAIN3, 0x18},
+ {DVBT_VTOP1, 0x35},
+ {DVBT_VTOP2, 0x21},
+ {DVBT_VTOP3, 0x21},
+ {DVBT_KRF1, 0x0},
+ {DVBT_KRF2, 0x40},
+ {DVBT_KRF3, 0x10},
+ {DVBT_KRF4, 0x10},
+ {DVBT_IF_AGC_MIN, 0x80},
+ {DVBT_IF_AGC_MAX, 0x7f},
+ {DVBT_RF_AGC_MIN, 0x80},
+ {DVBT_RF_AGC_MAX, 0x7f},
+ {DVBT_POLAR_RF_AGC, 0x0},
+ {DVBT_POLAR_IF_AGC, 0x0},
+ {DVBT_AD7_SETTING, 0xe9f4},
+ {DVBT_SPEC_INV, 0x1},
};
#endif /* RTL2832_PRIV_H */
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 12/86] rtl2832_sdr: pixel format for SDR
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (10 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 11/86] rtl2832: style changes and minor cleanup Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 13/86] rtl2832_sdr: implement FMT IOCTLs Antti Palosaari
` (75 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
These are used for converting / streaming I/Q data from SDR.
* unsigned 8-bit
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index 2c84654..d3db859 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -49,6 +49,8 @@
#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 MAX_BULK_BUFS (8)
#define BULK_BUFFER_SIZE (8 * 512)
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 13/86] rtl2832_sdr: implement FMT IOCTLs
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (11 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 12/86] rtl2832_sdr: pixel format for SDR Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 14/86] msi3101: add signed 8-bit pixel format for SDR Antti Palosaari
` (74 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
VIDIOC_ENUM_FMT, VIDIOC_G_FMT, VIDIOC_S_FMT and VIDIOC_TRY_FMT.
Return stream according to FMT.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 125 ++++++++++++++---------
1 file changed, 75 insertions(+), 50 deletions(-)
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index d3db859..348df05 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -291,56 +291,10 @@ leave:
return buf;
}
-/*
- * 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)
-
-/*
- * Converts signed 8-bit integer into 32-bit IEEE floating point
- * representation.
- */
-static u32 rtl2832_sdr_convert_sample(struct rtl2832_sdr_state *s, u16 x)
-{
- u32 msb, exponent, fraction, sign;
-
- /* Zero is special */
- if (!x)
- return 0;
-
- /* Negative / positive value */
- if (x & (1 << 7)) {
- x = -x;
- x &= 0x7f; /* result is 7 bit ... + sign */
- sign = 1 << 31;
- } else {
- sign = 0 << 31;
- }
-
- /* Get location of the most significant bit */
- msb = __fls(x);
-
- fraction = ror32(x, (msb - I2F_FRAC_BITS) & 0x1f) & I2F_MASK;
- exponent = (127 + msb) << I2F_FRAC_BITS;
-
- return (fraction + exponent) | sign;
-}
-
static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s,
- u32 *dst, const u8 *src, unsigned int src_len)
+ u8 *dst, const u8 *src, unsigned int src_len)
{
- unsigned int i, dst_len = 0;
-
- for (i = 0; i < src_len; i++)
- *dst++ = rtl2832_sdr_convert_sample(s, src[i]);
-
- /* 8-bit to 32-bit IEEE floating point */
- dst_len = src_len * 4;
+ memcpy(dst, src, src_len);
/* calculate samping rate and output it in 10 seconds intervals */
if ((s->jiffies + msecs_to_jiffies(10000)) <= jiffies) {
@@ -358,7 +312,7 @@ static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s,
/* total number of I+Q pairs */
s->sample += src_len / 2;
- return dst_len;
+ return src_len;
}
/*
@@ -591,7 +545,6 @@ static int rtl2832_sdr_querycap(struct file *file, void *fh,
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;
- cap->device_caps = V4L2_CAP_TUNER;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
return 0;
}
@@ -1014,9 +967,81 @@ static int vidioc_s_frequency(struct file *file, void *priv,
f->frequency * 625UL / 10UL);
}
+static int rtl2832_sdr_enum_fmt_vid_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)
+ return -EINVAL;
+
+ f->flags = 0;
+ strcpy(f->description, "I/Q 8-bit unsigned");
+ f->pixelformat = V4L2_PIX_FMT_SDR_U8;
+
+ return 0;
+}
+
+static int rtl2832_sdr_g_fmt_vid_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)
+ return -EINVAL;
+
+ memset(&f->fmt.pix, 0, sizeof(f->fmt.pix));
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_SDR_U8;
+
+ return 0;
+}
+
+static int rtl2832_sdr_s_fmt_vid_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;
+ dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
+ (char *)&f->fmt.pix.pixelformat);
+
+ if (f->type != V4L2_BUF_TYPE_VIDEO_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;
+
+ return 0;
+}
+
+static int rtl2832_sdr_try_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct rtl2832_sdr_state *s = video_drvdata(file);
+ dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
+ (char *)&f->fmt.pix.pixelformat);
+
+ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ memset(&f->fmt.pix, 0, sizeof(f->fmt.pix));
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_SDR_U8;
+
+ return 0;
+}
+
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,
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 14/86] msi3101: add signed 8-bit pixel format for SDR
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (12 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 13/86] rtl2832_sdr: implement FMT IOCTLs Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 15/86] msi3101: implement FMT IOCTLs Antti Palosaari
` (73 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
It is 8-bit unsigned data, byte after byte. Used for streaming SDR
I/Q data from ADC.
V4L2_PIX_FMT_SDR_S8, v4l fourcc "DS08".
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/msi3101/sdr-msi3101.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index 4c3bf77..e208b57 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -385,6 +385,8 @@ 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_S8 v4l2_fourcc('D', 'S', '0', '8') /* signed 8-bit */
+
/* intermediate buffers with raw data from the USB device */
struct msi3101_frame_buf {
struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 15/86] msi3101: implement FMT IOCTLs
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (13 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 14/86] msi3101: add signed 8-bit pixel format for SDR Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 16/86] msi3101: move format 384 conversion to libv4lconvert Antti Palosaari
` (72 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
VIDIOC_ENUM_FMT, VIDIOC_G_FMT, VIDIOC_S_FMT and VIDIOC_TRY_FMT.
Implement 8-bit signed stream (type '504' samples per USB packet)
using FMT.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/msi3101/sdr-msi3101.c | 165 +++++++++++++++++++++-------
1 file changed, 123 insertions(+), 42 deletions(-)
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index e208b57..ba68ea9 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -387,6 +387,22 @@ static const struct msi3101_gain msi3101_gain_lut_1000[] = {
#define V4L2_PIX_FMT_SDR_S8 v4l2_fourcc('D', 'S', '0', '8') /* signed 8-bit */
+/* stream formats */
+struct msi3101_format {
+ char *name;
+ u32 pixelformat;
+};
+
+/* format descriptions for capture and preview */
+static struct msi3101_format formats[] = {
+ {
+ .name = "I/Q 8-bit signed",
+ .pixelformat = V4L2_PIX_FMT_SDR_S8,
+ },
+};
+
+static const int NUM_FORMATS = sizeof(formats) / sizeof(struct msi3101_format);
+
/* intermediate buffers with raw data from the USB device */
struct msi3101_frame_buf {
struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */
@@ -409,6 +425,8 @@ struct msi3101_state {
/* Pointer to our usb_device, will be NULL after unplug */
struct usb_device *udev; /* Both mutexes most be hold when setting! */
+ u32 pixelformat;
+
unsigned int isoc_errors; /* number of contiguous ISOC errors */
unsigned int vb_full; /* vb is full and packets dropped */
@@ -447,7 +465,6 @@ leave:
spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
return buf;
}
-
/*
* +===========================================================================
* | 00-1023 | USB packet type '384'
@@ -504,40 +521,22 @@ leave:
#define I2F_MASK ((1 << I2F_FRAC_BITS) - 1)
/*
- * Converts signed 8-bit integer into 32-bit IEEE floating point
- * representation.
+ * +===========================================================================
+ * | 00-1023 | USB packet type '504'
+ * +===========================================================================
+ * | 00- 03 | sequence number of first sample in that USB packet
+ * +---------------------------------------------------------------------------
+ * | 04- 15 | garbage
+ * +---------------------------------------------------------------------------
+ * | 16-1023 | samples
+ * +---------------------------------------------------------------------------
+ * signed 8-bit sample
+ * 504 * 2 = 1008 samples
*/
-static u32 msi3101_convert_sample_504(struct msi3101_state *s, u16 x)
-{
- u32 msb, exponent, fraction, sign;
-
- /* Zero is special */
- if (!x)
- return 0;
-
- /* Negative / positive value */
- if (x & (1 << 7)) {
- x = -x;
- x &= 0x7f; /* result is 7 bit ... + sign */
- sign = 1 << 31;
- } else {
- sign = 0 << 31;
- }
-
- /* Get location of the most significant bit */
- msb = __fls(x);
-
- fraction = ror32(x, (msb - I2F_FRAC_BITS) & 0x1f) & I2F_MASK;
- exponent = (127 + msb) << I2F_FRAC_BITS;
-
- return (fraction + exponent) | sign;
-}
-
-static int msi3101_convert_stream_504(struct msi3101_state *s, u32 *dst,
+static int msi3101_convert_stream_504(struct msi3101_state *s, u8 *dst,
u8 *src, unsigned int src_len)
{
- int i, j, i_max, dst_len = 0;
- u16 sample[2];
+ int i, i_max, dst_len = 0;
u32 sample_num[3];
/* There could be 1-3 1024 bytes URB frames */
@@ -558,17 +557,12 @@ static int msi3101_convert_stream_504(struct msi3101_state *s, u32 *dst,
*/
dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]);
+ /* 504 x I+Q samples */
src += 16;
- for (j = 0; j < 1008; j += 2) {
- sample[0] = src[j + 0];
- sample[1] = src[j + 1];
-
- *dst++ = msi3101_convert_sample_504(s, sample[0]);
- *dst++ = msi3101_convert_sample_504(s, sample[1]);
- }
- /* 504 x I+Q 32bit float samples */
- dst_len += 504 * 2 * 4;
+ memcpy(dst, src, 1008);
src += 1008;
+ dst += 1008;
+ dst_len += 1008;
}
/* calculate samping rate and output it in 10 seconds intervals */
@@ -1116,7 +1110,6 @@ static int msi3101_querycap(struct file *file, void *fh,
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;
- cap->device_caps = V4L2_CAP_TUNER;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
return 0;
}
@@ -1240,6 +1233,11 @@ static int msi3101_set_usb_adc(struct msi3101_state *s)
reg7 = 0x000c9407;
}
+ if (s->pixelformat == V4L2_PIX_FMT_SDR_S8) {
+ s->convert_stream = msi3101_convert_stream_504;
+ reg7 = 0x000c9407;
+ }
+
/*
* Synthesizer config is just a educated guess...
*
@@ -1634,6 +1632,84 @@ static int msi3101_s_input(struct file *file, void *fh, unsigned int i)
return i ? -EINVAL : 0;
}
+static int msi3101_enum_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+{
+ struct msi3101_state *s = video_drvdata(file);
+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+ 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 msi3101_g_fmt_vid_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)
+ return -EINVAL;
+
+ f->fmt.pix.pixelformat = s->pixelformat;
+
+ return 0;
+}
+
+static int msi3101_s_fmt_vid_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);
+
+ if (f->type != V4L2_BUF_TYPE_VIDEO_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;
+ return 0;
+ }
+ }
+
+ f->fmt.pix.pixelformat = formats[0].pixelformat;
+ s->pixelformat = formats[0].pixelformat;
+
+ return 0;
+}
+
+static int msi3101_try_fmt_vid_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);
+
+ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ for (i = 0; i < NUM_FORMATS; i++) {
+ if (formats[i].pixelformat == f->fmt.pix.pixelformat)
+ return 0;
+ }
+
+ f->fmt.pix.pixelformat = formats[0].pixelformat;
+
+ return 0;
+}
+
static int vidioc_s_tuner(struct file *file, void *priv,
const struct v4l2_tuner *v)
{
@@ -1668,6 +1744,11 @@ static int vidioc_s_frequency(struct file *file, void *priv,
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_input = msi3101_enum_input,
.vidioc_g_input = msi3101_g_input,
.vidioc_s_input = msi3101_s_input,
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 16/86] msi3101: move format 384 conversion to libv4lconvert
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (14 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 15/86] msi3101: implement FMT IOCTLs Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 17/86] msi3101: move format 336 " Antti Palosaari
` (71 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Move format 384 conversion to libv4lconvert as a fourcc "M384".
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/msi3101/sdr-msi3101.c | 163 ++++++++++------------------
1 file changed, 57 insertions(+), 106 deletions(-)
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index ba68ea9..37fea45 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_S8 v4l2_fourcc('D', 'S', '0', '8') /* signed 8-bit */
+#define V4L2_PIX_FMT_SDR_MSI2500_384 v4l2_fourcc('M', '3', '8', '4') /* Mirics MSi2500 format 384 */
/* stream formats */
struct msi3101_format {
@@ -399,6 +400,10 @@ static struct msi3101_format formats[] = {
.name = "I/Q 8-bit signed",
.pixelformat = V4L2_PIX_FMT_SDR_S8,
},
+ {
+ .name = "I/Q 10+2-bit signed",
+ .pixelformat = V4L2_PIX_FMT_SDR_MSI2500_384,
+ },
};
static const int NUM_FORMATS = sizeof(formats) / sizeof(struct msi3101_format);
@@ -465,50 +470,6 @@ leave:
spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
return buf;
}
-/*
- * +===========================================================================
- * | 00-1023 | USB packet type '384'
- * +===========================================================================
- * | 00- 03 | sequence number of first sample in that USB packet
- * +---------------------------------------------------------------------------
- * | 04- 15 | garbage
- * +---------------------------------------------------------------------------
- * | 16- 175 | samples
- * +---------------------------------------------------------------------------
- * | 176- 179 | control bits for previous samples
- * +---------------------------------------------------------------------------
- * | 180- 339 | samples
- * +---------------------------------------------------------------------------
- * | 340- 343 | control bits for previous samples
- * +---------------------------------------------------------------------------
- * | 344- 503 | samples
- * +---------------------------------------------------------------------------
- * | 504- 507 | control bits for previous samples
- * +---------------------------------------------------------------------------
- * | 508- 667 | samples
- * +---------------------------------------------------------------------------
- * | 668- 671 | control bits for previous samples
- * +---------------------------------------------------------------------------
- * | 672- 831 | samples
- * +---------------------------------------------------------------------------
- * | 832- 835 | control bits for previous samples
- * +---------------------------------------------------------------------------
- * | 836- 995 | samples
- * +---------------------------------------------------------------------------
- * | 996- 999 | control bits for previous samples
- * +---------------------------------------------------------------------------
- * | 1000-1023 | garbage
- * +---------------------------------------------------------------------------
- *
- * Bytes 4 - 7 could have some meaning?
- *
- * Control bits for previous samples is 32-bit field, containing 16 x 2-bit
- * numbers. This results one 2-bit number for 8 samples. It is likely used for
- * for bit shifting sample by given bits, increasing actual sampling resolution.
- * Number 2 (0b10) was never seen.
- *
- * 6 * 16 * 2 * 4 = 768 samples. 768 * 4 = 3072 bytes
- */
/*
* Integer to 32-bit IEEE floating point representation routine is taken
@@ -585,48 +546,53 @@ static int msi3101_convert_stream_504(struct msi3101_state *s, u8 *dst,
}
/*
- * Converts signed ~10+2-bit integer into 32-bit IEEE floating point
- * representation.
+ * +===========================================================================
+ * | 00-1023 | USB packet type '384'
+ * +===========================================================================
+ * | 00- 03 | sequence number of first sample in that USB packet
+ * +---------------------------------------------------------------------------
+ * | 04- 15 | garbage
+ * +---------------------------------------------------------------------------
+ * | 16- 175 | samples
+ * +---------------------------------------------------------------------------
+ * | 176- 179 | control bits for previous samples
+ * +---------------------------------------------------------------------------
+ * | 180- 339 | samples
+ * +---------------------------------------------------------------------------
+ * | 340- 343 | control bits for previous samples
+ * +---------------------------------------------------------------------------
+ * | 344- 503 | samples
+ * +---------------------------------------------------------------------------
+ * | 504- 507 | control bits for previous samples
+ * +---------------------------------------------------------------------------
+ * | 508- 667 | samples
+ * +---------------------------------------------------------------------------
+ * | 668- 671 | control bits for previous samples
+ * +---------------------------------------------------------------------------
+ * | 672- 831 | samples
+ * +---------------------------------------------------------------------------
+ * | 832- 835 | control bits for previous samples
+ * +---------------------------------------------------------------------------
+ * | 836- 995 | samples
+ * +---------------------------------------------------------------------------
+ * | 996- 999 | control bits for previous samples
+ * +---------------------------------------------------------------------------
+ * | 1000-1023 | garbage
+ * +---------------------------------------------------------------------------
+ *
+ * Bytes 4 - 7 could have some meaning?
+ *
+ * Control bits for previous samples is 32-bit field, containing 16 x 2-bit
+ * numbers. This results one 2-bit number for 8 samples. It is likely used for
+ * for bit shifting sample by given bits, increasing actual sampling resolution.
+ * Number 2 (0b10) was never seen.
+ *
+ * 6 * 16 * 2 * 4 = 768 samples. 768 * 4 = 3072 bytes
*/
-static u32 msi3101_convert_sample_384(struct msi3101_state *s, u16 x, int shift)
-{
- u32 msb, exponent, fraction, sign;
- s->sample_ctrl_bit[shift]++;
-
- /* Zero is special */
- if (!x)
- return 0;
-
- if (shift == 3)
- shift = 2;
-
- /* Convert 10-bit two's complement to 12-bit */
- if (x & (1 << 9)) {
- x |= ~0U << 10; /* set all the rest bits to one */
- x <<= shift;
- x = -x;
- x &= 0x7ff; /* result is 11 bit ... + sign */
- sign = 1 << 31;
- } else {
- x <<= shift;
- sign = 0 << 31;
- }
-
- /* Get location of the most significant bit */
- msb = __fls(x);
-
- fraction = ror32(x, (msb - I2F_FRAC_BITS) & 0x1f) & I2F_MASK;
- exponent = (127 + msb) << I2F_FRAC_BITS;
-
- return (fraction + exponent) | sign;
-}
-
-static int msi3101_convert_stream_384(struct msi3101_state *s, u32 *dst,
+static int msi3101_convert_stream_384(struct msi3101_state *s, u8 *dst,
u8 *src, unsigned int src_len)
{
- int i, j, k, l, i_max, dst_len = 0;
- u16 sample[4];
- u32 bits;
+ int i, i_max, dst_len = 0;
u32 sample_num[3];
/* There could be 1-3 1024 bytes URB frames */
@@ -647,30 +613,12 @@ static int msi3101_convert_stream_384(struct msi3101_state *s, u32 *dst,
dev_dbg_ratelimited(&s->udev->dev,
"%*ph %*ph\n", 12, &src[4], 24, &src[1000]);
+ /* 384 x I+Q samples */
src += 16;
- for (j = 0; j < 6; j++) {
- bits = src[160 + 3] << 24 | src[160 + 2] << 16 | src[160 + 1] << 8 | src[160 + 0] << 0;
- for (k = 0; k < 16; k++) {
- for (l = 0; l < 10; l += 5) {
- sample[0] = (src[l + 0] & 0xff) >> 0 | (src[l + 1] & 0x03) << 8;
- sample[1] = (src[l + 1] & 0xfc) >> 2 | (src[l + 2] & 0x0f) << 6;
- sample[2] = (src[l + 2] & 0xf0) >> 4 | (src[l + 3] & 0x3f) << 4;
- sample[3] = (src[l + 3] & 0xc0) >> 6 | (src[l + 4] & 0xff) << 2;
-
- *dst++ = msi3101_convert_sample_384(s, sample[0], (bits >> (2 * k)) & 0x3);
- *dst++ = msi3101_convert_sample_384(s, sample[1], (bits >> (2 * k)) & 0x3);
- *dst++ = msi3101_convert_sample_384(s, sample[2], (bits >> (2 * k)) & 0x3);
- *dst++ = msi3101_convert_sample_384(s, sample[3], (bits >> (2 * k)) & 0x3);
- }
- src += 10;
- }
- dev_dbg_ratelimited(&s->udev->dev,
- "sample control bits %08x\n", bits);
- src += 4;
- }
- /* 384 x I+Q 32bit float samples */
- dst_len += 384 * 2 * 4;
- src += 24;
+ memcpy(dst, src, 984);
+ src += 984 + 24;
+ dst += 984;
+ dst_len += 984;
}
/* calculate samping rate and output it in 10 seconds intervals */
@@ -1236,6 +1184,9 @@ static int msi3101_set_usb_adc(struct msi3101_state *s)
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) {
+ s->convert_stream = msi3101_convert_stream_384;
+ reg7 = 0x0000a507;
}
/*
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 17/86] msi3101: move format 336 conversion to libv4lconvert
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (15 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 16/86] msi3101: move format 384 conversion to libv4lconvert Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 18/86] msi3101: move format 252 " Antti Palosaari
` (70 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Move format 384 conversion to libv4lconvert as a fourcc "DS12".
It is 12-bit sample pairs packed to 3 bytes.
msi3101: move format 336 conversion 336 to libv4l
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/msi3101/sdr-msi3101.c | 66 +++++++++++------------------
1 file changed, 24 insertions(+), 42 deletions(-)
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index 37fea45..7c1dc43 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_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_MSI2500_384 v4l2_fourcc('M', '3', '8', '4') /* Mirics MSi2500 format 384 */
/* stream formats */
@@ -399,10 +400,12 @@ static struct msi3101_format formats[] = {
{
.name = "I/Q 8-bit signed",
.pixelformat = V4L2_PIX_FMT_SDR_S8,
- },
- {
+ }, {
.name = "I/Q 10+2-bit signed",
.pixelformat = V4L2_PIX_FMT_SDR_MSI2500_384,
+ }, {
+ .name = "I/Q 12-bit signed",
+ .pixelformat = V4L2_PIX_FMT_SDR_S12,
},
};
@@ -643,40 +646,21 @@ static int msi3101_convert_stream_384(struct msi3101_state *s, u8 *dst,
}
/*
- * Converts signed 12-bit integer into 32-bit IEEE floating point
- * representation.
+ * +===========================================================================
+ * | 00-1023 | USB packet type '336'
+ * +===========================================================================
+ * | 00- 03 | sequence number of first sample in that USB packet
+ * +---------------------------------------------------------------------------
+ * | 04- 15 | garbage
+ * +---------------------------------------------------------------------------
+ * | 16-1023 | samples
+ * +---------------------------------------------------------------------------
+ * signed 12-bit sample
*/
-static u32 msi3101_convert_sample_336(struct msi3101_state *s, u16 x)
-{
- u32 msb, exponent, fraction, sign;
-
- /* Zero is special */
- if (!x)
- return 0;
-
- /* Negative / positive value */
- if (x & (1 << 11)) {
- x = -x;
- x &= 0x7ff; /* result is 11 bit ... + sign */
- sign = 1 << 31;
- } else {
- sign = 0 << 31;
- }
-
- /* Get location of the most significant bit */
- msb = __fls(x);
-
- fraction = ror32(x, (msb - I2F_FRAC_BITS) & 0x1f) & I2F_MASK;
- exponent = (127 + msb) << I2F_FRAC_BITS;
-
- return (fraction + exponent) | sign;
-}
-
-static int msi3101_convert_stream_336(struct msi3101_state *s, u32 *dst,
+static int msi3101_convert_stream_336(struct msi3101_state *s, u8 *dst,
u8 *src, unsigned int src_len)
{
- int i, j, i_max, dst_len = 0;
- u16 sample[2];
+ int i, i_max, dst_len = 0;
u32 sample_num[3];
/* There could be 1-3 1024 bytes URB frames */
@@ -697,17 +681,12 @@ static int msi3101_convert_stream_336(struct msi3101_state *s, u32 *dst,
*/
dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]);
+ /* 336 x I+Q samples */
src += 16;
- for (j = 0; j < 1008; j += 3) {
- sample[0] = (src[j + 0] & 0xff) >> 0 | (src[j + 1] & 0x0f) << 8;
- sample[1] = (src[j + 1] & 0xf0) >> 4 | (src[j + 2] & 0xff) << 4;
-
- *dst++ = msi3101_convert_sample_336(s, sample[0]);
- *dst++ = msi3101_convert_sample_336(s, sample[1]);
- }
- /* 336 x I+Q 32bit float samples */
- dst_len += 336 * 2 * 4;
+ memcpy(dst, src, 1008);
src += 1008;
+ dst += 1008;
+ dst_len += 1008;
}
/* calculate samping rate and output it in 10 seconds intervals */
@@ -1187,6 +1166,9 @@ static int msi3101_set_usb_adc(struct msi3101_state *s)
} else if (s->pixelformat == V4L2_PIX_FMT_SDR_MSI2500_384) {
s->convert_stream = msi3101_convert_stream_384;
reg7 = 0x0000a507;
+ } else if (s->pixelformat == V4L2_PIX_FMT_SDR_S12) {
+ s->convert_stream = msi3101_convert_stream_336;
+ reg7 = 0x00008507;
}
/*
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 18/86] msi3101: move format 252 conversion to libv4lconvert
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (16 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 17/86] msi3101: move format 336 " Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 19/86] rtl28xxu: add module parameter to disable IR Antti Palosaari
` (69 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Move format 252 conversion to libv4lconvert as a fourcc "DS14".
It is 14-bit sample pairs packed to 4 bytes.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/msi3101/sdr-msi3101.c | 65 +++++++++++------------------
1 file changed, 24 insertions(+), 41 deletions(-)
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index 7c1dc43..16ce417 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -387,6 +387,7 @@ static const struct msi3101_gain msi3101_gain_lut_1000[] = {
#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_MSI2500_384 v4l2_fourcc('M', '3', '8', '4') /* Mirics MSi2500 format 384 */
/* stream formats */
@@ -406,6 +407,9 @@ static struct msi3101_format formats[] = {
}, {
.name = "I/Q 12-bit signed",
.pixelformat = V4L2_PIX_FMT_SDR_S12,
+ }, {
+ .name = "I/Q 14-bit signed",
+ .pixelformat = V4L2_PIX_FMT_SDR_S14,
},
};
@@ -439,7 +443,7 @@ struct msi3101_state {
unsigned int vb_full; /* vb is full and packets dropped */
struct urb *urbs[MAX_ISO_BUFS];
- int (*convert_stream) (struct msi3101_state *s, u32 *dst, u8 *src,
+ int (*convert_stream) (struct msi3101_state *s, u8 *dst, u8 *src,
unsigned int src_len);
/* Controls */
@@ -709,40 +713,21 @@ static int msi3101_convert_stream_336(struct msi3101_state *s, u8 *dst,
}
/*
- * Converts signed 14-bit integer into 32-bit IEEE floating point
- * representation.
+ * +===========================================================================
+ * | 00-1023 | USB packet type '252'
+ * +===========================================================================
+ * | 00- 03 | sequence number of first sample in that USB packet
+ * +---------------------------------------------------------------------------
+ * | 04- 15 | garbage
+ * +---------------------------------------------------------------------------
+ * | 16-1023 | samples
+ * +---------------------------------------------------------------------------
+ * signed 14-bit sample
*/
-static u32 msi3101_convert_sample_252(struct msi3101_state *s, u16 x)
-{
- u32 msb, exponent, fraction, sign;
-
- /* Zero is special */
- if (!x)
- return 0;
-
- /* Negative / positive value */
- if (x & (1 << 13)) {
- x = -x;
- x &= 0x1fff; /* result is 13 bit ... + sign */
- sign = 1 << 31;
- } else {
- sign = 0 << 31;
- }
-
- /* Get location of the most significant bit */
- msb = __fls(x);
-
- fraction = ror32(x, (msb - I2F_FRAC_BITS) & 0x1f) & I2F_MASK;
- exponent = (127 + msb) << I2F_FRAC_BITS;
-
- return (fraction + exponent) | sign;
-}
-
-static int msi3101_convert_stream_252(struct msi3101_state *s, u32 *dst,
+static int msi3101_convert_stream_252(struct msi3101_state *s, u8 *dst,
u8 *src, unsigned int src_len)
{
- int i, j, i_max, dst_len = 0;
- u16 sample[2];
+ int i, i_max, dst_len = 0;
u32 sample_num[3];
/* There could be 1-3 1024 bytes URB frames */
@@ -763,17 +748,12 @@ static int msi3101_convert_stream_252(struct msi3101_state *s, u32 *dst,
*/
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) {
- sample[0] = src[j + 0] >> 0 | src[j + 1] << 8;
- sample[1] = src[j + 2] >> 0 | src[j + 3] << 8;
-
- *dst++ = msi3101_convert_sample_252(s, sample[0]);
- *dst++ = msi3101_convert_sample_252(s, sample[1]);
- }
- /* 252 x I+Q 32bit float samples */
- dst_len += 252 * 2 * 4;
+ memcpy(dst, src, 1008);
src += 1008;
+ dst += 1008;
+ dst_len += 1008;
}
/* calculate samping rate and output it in 10 seconds intervals */
@@ -1169,6 +1149,9 @@ static int msi3101_set_usb_adc(struct msi3101_state *s)
} else if (s->pixelformat == V4L2_PIX_FMT_SDR_S12) {
s->convert_stream = msi3101_convert_stream_336;
reg7 = 0x00008507;
+ } else if (s->pixelformat == V4L2_PIX_FMT_SDR_S14) {
+ s->convert_stream = msi3101_convert_stream_252;
+ reg7 = 0x00009407;
}
/*
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 19/86] rtl28xxu: add module parameter to disable IR
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (17 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 18/86] msi3101: move format 252 " Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 20/86] rtl2832_sdr: increase USB buffers Antti Palosaari
` (68 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Disable IR interrupts in order to avoid SDR sample loss.
IR interrupts causes some extra load for device and it seems
be one reason to loss samples when sampling rate is high.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index 6a5eb0f..77f1fc9 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -36,6 +36,9 @@
#include "tua9001.h"
#include "r820t.h"
+static int rtl28xxu_disable_rc;
+module_param_named(disable_rc, rtl28xxu_disable_rc, int, 0644);
+MODULE_PARM_DESC(disable_rc, "disable RTL2832U remote controller");
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req)
@@ -1325,6 +1328,10 @@ err:
static int rtl2832u_get_rc_config(struct dvb_usb_device *d,
struct dvb_usb_rc *rc)
{
+ /* disable IR interrupts in order to avoid SDR sample loss */
+ if (rtl28xxu_disable_rc)
+ return rtl28xx_wr_reg(d, IR_RX_IE, 0x00);
+
/* load empty to enable rc */
if (!rc->map_name)
rc->map_name = RC_MAP_EMPTY;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 20/86] rtl2832_sdr: increase USB buffers
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (18 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 19/86] rtl28xxu: add module parameter to disable IR Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 21/86] rtl2832_sdr: convert to SDR API Antti Palosaari
` (67 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Increase USB xfer buffers heavily in order handle wider data stream.
Stream is quite heavy, over 50Mbit/sec, when sampling rates are
increased up to 3.2Msps. With remote controller interrupts disabled
and huge USB buffers it seems to perform even 3.2Msps rather well.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index 348df05..4b8c016 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -51,8 +51,8 @@
#define V4L2_PIX_FMT_SDR_U8 v4l2_fourcc('D', 'U', '0', '8') /* unsigned 8-bit */
-#define MAX_BULK_BUFS (8)
-#define BULK_BUFFER_SIZE (8 * 512)
+#define MAX_BULK_BUFS (10)
+#define BULK_BUFFER_SIZE (128 * 512)
/* intermediate buffers with raw data from the USB device */
struct rtl2832_sdr_frame_buf {
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 21/86] rtl2832_sdr: convert to SDR API
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (19 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 20/86] rtl2832_sdr: increase USB buffers Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 22/86] msi3101: " Antti Palosaari
` (66 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: 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.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 22/86] msi3101: convert to SDR API
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (20 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 21/86] rtl2832_sdr: convert to SDR API Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 23/86] msi3101: add u8 sample format Antti Palosaari
` (65 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Convert to SDR API.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/msi3101/sdr-msi3101.c | 218 ++++++++++++++++++----------
1 file changed, 142 insertions(+), 76 deletions(-)
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index 16ce417..502d35d 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;
@@ -1525,30 +1544,7 @@ static struct vb2_ops msi3101_vb2_ops = {
.wait_finish = vb2_ops_wait_finish,
};
-static int msi3101_enum_input(struct file *file, void *fh, struct v4l2_input *i)
-{
- if (i->index != 0)
- return -EINVAL;
-
- strlcpy(i->name, "SDR data", sizeof(i->name));
- i->type = V4L2_INPUT_TYPE_CAMERA;
-
- 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;
-}
-
-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 +1559,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,39 +1631,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 v4l2_ctrl_s_ctrl_int64(s->ctrl_tuner_rf,
- f->frequency * 625UL / 10UL);
+ 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;
+
+ *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_input = msi3101_enum_input,
- .vidioc_g_input = msi3101_g_input,
- .vidioc_s_input = msi3101_s_input,
+ .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_reqbufs = vb2_ioctl_reqbufs,
.vidioc_create_bufs = vb2_ioctl_create_bufs,
@@ -1679,9 +1742,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 +1910,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 +1958,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.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 23/86] msi3101: add u8 sample format
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (21 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 22/86] msi3101: " Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 24/86] msi3101: add u16 LE " Antti Palosaari
` (64 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: 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 502d35d..c50402d 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.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 24/86] msi3101: add u16 LE sample format
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (22 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 23/86] msi3101: add u8 sample format Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 25/86] msi3101: tons of small changes Antti Palosaari
` (63 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: 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 c50402d..7a64f18 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.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 25/86] msi3101: tons of small changes
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (23 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 24/86] msi3101: add u16 LE " Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 26/86] rtl2832_sdr: return NULL on rtl2832_sdr_attach failure Antti Palosaari
` (62 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: 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 7a64f18..cb66f81 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,
@@ -1789,9 +1752,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;
}
@@ -1826,17 +1789,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;
}
@@ -1913,6 +1874,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)
@@ -1927,14 +1889,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;
@@ -1965,70 +1920,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,
@@ -2036,7 +1937,7 @@ static int msi3101_probe(struct usb_interface *intf,
.name = "Tuner Gain",
.min = 0,
.max = 102,
- .def = 0,
+ .def = 50,
.step = 1,
};
@@ -2062,7 +1963,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;
}
@@ -2075,13 +1976,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;
@@ -2103,7 +1999,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.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 26/86] rtl2832_sdr: return NULL on rtl2832_sdr_attach failure
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (24 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 25/86] msi3101: tons of small changes Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 27/86] rtl2832_sdr: calculate bandwidth if not set by user Antti Palosaari
` (61 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
dvb_attach() expects NULL on attach failure.
Do some style changes also while we are here.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 50 ++++++++++++------------
1 file changed, 25 insertions(+), 25 deletions(-)
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index a26125c..1cc7bf7 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -1250,31 +1250,31 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
struct rtl2832_sdr_state *s;
struct dvb_usb_device *d = i2c_get_adapdata(i2c);
static const struct v4l2_ctrl_config ctrl_tuner_bw = {
- .ops = &rtl2832_sdr_ctrl_ops,
- .id = RTL2832_SDR_CID_TUNER_BW,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Tuner BW",
- .min = 200000,
- .max = 8000000,
+ .ops = &rtl2832_sdr_ctrl_ops,
+ .id = RTL2832_SDR_CID_TUNER_BW,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Tuner BW",
+ .min = 200000,
+ .max = 8000000,
.def = 600000,
- .step = 1,
+ .step = 1,
};
static const struct v4l2_ctrl_config ctrl_tuner_gain = {
- .ops = &rtl2832_sdr_ctrl_ops,
- .id = RTL2832_SDR_CID_TUNER_GAIN,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Tuner Gain",
- .min = 0,
- .max = 102,
+ .ops = &rtl2832_sdr_ctrl_ops,
+ .id = RTL2832_SDR_CID_TUNER_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Tuner Gain",
+ .min = 0,
+ .max = 102,
.def = 0,
- .step = 1,
+ .step = 1,
};
s = kzalloc(sizeof(struct rtl2832_sdr_state), GFP_KERNEL);
if (s == NULL) {
dev_err(&d->udev->dev,
"Could not allocate memory for rtl2832_sdr_state\n");
- return ERR_PTR(-ENOMEM);
+ return NULL;
}
/* setup the state */
@@ -1298,18 +1298,11 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
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;
}
- /* Init video_device structure */
- s->vdev = rtl2832_sdr_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 controls */
v4l2_ctrl_handler_init(&s->ctrl_handler, 2);
s->ctrl_tuner_bw = v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_tuner_bw, NULL);
@@ -1320,6 +1313,13 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
goto err_free_controls;
}
+ /* Init video_device structure */
+ s->vdev = rtl2832_sdr_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 = rtl2832_sdr_video_release;
ret = v4l2_device_register(&s->udev->dev, &s->v4l2_dev);
@@ -1335,7 +1335,7 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
s->vdev.vfl_dir = VFL_DIR_RX;
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);
@@ -1357,7 +1357,7 @@ err_free_controls:
v4l2_ctrl_handler_free(&s->ctrl_handler);
err_free_mem:
kfree(s);
- return ERR_PTR(ret);
+ return NULL;
}
EXPORT_SYMBOL(rtl2832_sdr_attach);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 27/86] rtl2832_sdr: calculate bandwidth if not set by user
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (25 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 26/86] rtl2832_sdr: return NULL on rtl2832_sdr_attach failure Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 28/86] rtl2832_sdr: clamp ADC frequency to valid range always Antti Palosaari
` (60 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Calculate bandwidth from sampling rate if it is not set by user.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index 1cc7bf7..2c9b703 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -881,6 +881,10 @@ static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s)
if (fe->ops.tuner_ops.init)
fe->ops.tuner_ops.init(fe);
+ /* user has not requested bandwidth so calculate automatically */
+ if (bandwidth == 0)
+ bandwidth = s->f_adc;
+
c->bandwidth_hz = bandwidth;
c->frequency = f_rf;
@@ -1254,9 +1258,9 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
.id = RTL2832_SDR_CID_TUNER_BW,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Tuner BW",
- .min = 200000,
- .max = 8000000,
- .def = 600000,
+ .min = 0,
+ .max = INT_MAX,
+ .def = 0,
.step = 1,
};
static const struct v4l2_ctrl_config ctrl_tuner_gain = {
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 28/86] rtl2832_sdr: clamp ADC frequency to valid range always
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (26 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 27/86] rtl2832_sdr: calculate bandwidth if not set by user Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 29/86] rtl2832_sdr: improve ADC device programming logic Antti Palosaari
` (59 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
V4L2 tuner API says incorrect value should be round to nearest
legal value. Implement it for ADC frequency setting.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 24 ++++++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index 2c9b703..ddacfd2 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -666,7 +666,7 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
u64 u64tmp;
u32 u32tmp;
- dev_dbg(&s->udev->dev, "%s:\n", __func__);
+ dev_dbg(&s->udev->dev, "%s: f_adc=%u\n", __func__, s->f_adc);
if (!test_bit(POWER_ON, &s->flags))
return 0;
@@ -1064,12 +1064,26 @@ static int rtl2832_sdr_s_frequency(struct file *file, void *priv,
const struct v4l2_frequency *f)
{
struct rtl2832_sdr_state *s = video_drvdata(file);
- int ret;
+ int ret, band;
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 = f->frequency;
+ /* ADC band midpoints */
+ #define BAND_ADC_0 ((bands_adc[0].rangehigh + bands_adc[1].rangelow) / 2)
+ #define BAND_ADC_1 ((bands_adc[1].rangehigh + bands_adc[2].rangelow) / 2)
+
+ if (f->tuner == 0 && f->type == V4L2_TUNER_ADC) {
+ if (f->frequency < BAND_ADC_0)
+ band = 0;
+ else if (f->frequency < BAND_ADC_1)
+ band = 1;
+ else
+ band = 2;
+
+ s->f_adc = clamp_t(unsigned int, f->frequency,
+ bands_adc[band].rangelow,
+ bands_adc[band].rangehigh);
+
dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n",
__func__, s->f_adc);
ret = rtl2832_sdr_set_adc(s);
@@ -1287,6 +1301,8 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
s->udev = d->udev;
s->i2c = i2c;
s->cfg = cfg;
+ s->f_adc = bands_adc[0].rangelow;
+ s->pixelformat = V4L2_PIX_FMT_SDR_U8;
mutex_init(&s->v4l2_lock);
mutex_init(&s->vb_queue_lock);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 29/86] rtl2832_sdr: improve ADC device programming logic
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (27 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 28/86] rtl2832_sdr: clamp ADC frequency to valid range always Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 30/86] rtl2832_sdr: remove FMT buffer type checks Antti Palosaari
` (58 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Refactor and implement properly RTL2832 programming logic. Implement
some things more correctly. Restore some critical registers to POR
default state, making it possible to use it as a DVB-T device without
resetting or replugging.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 283 ++++++++++++++---------
1 file changed, 177 insertions(+), 106 deletions(-)
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index ddacfd2..0bc417d 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -187,7 +187,6 @@ static int rtl2832_sdr_wr(struct rtl2832_sdr_state *s, u8 reg, const u8 *val,
return ret;
}
-#if 0
/* read multiple hardware registers */
static int rtl2832_sdr_rd(struct rtl2832_sdr_state *s, u8 reg, u8 *val, int len)
{
@@ -217,7 +216,6 @@ static int rtl2832_sdr_rd(struct rtl2832_sdr_state *s, u8 reg, u8 *val, int len)
}
return ret;
}
-#endif
/* write multiple registers */
static int rtl2832_sdr_wr_regs(struct rtl2832_sdr_state *s, u16 reg,
@@ -239,7 +237,6 @@ static int rtl2832_sdr_wr_regs(struct rtl2832_sdr_state *s, u16 reg,
return rtl2832_sdr_wr(s, reg2, val, len);
}
-#if 0
/* read multiple registers */
static int rtl2832_sdr_rd_regs(struct rtl2832_sdr_state *s, u16 reg, u8 *val,
int len)
@@ -259,7 +256,6 @@ static int rtl2832_sdr_rd_regs(struct rtl2832_sdr_state *s, u16 reg, u8 *val,
return rtl2832_sdr_rd(s, reg2, val, len);
}
-#endif
/* write single register */
static int rtl2832_sdr_wr_reg(struct rtl2832_sdr_state *s, u16 reg, u8 val)
@@ -273,6 +269,7 @@ static int rtl2832_sdr_rd_reg(struct rtl2832_sdr_state *s, u16 reg, u8 *val)
{
return rtl2832_sdr_rd_regs(s, reg, val, 1);
}
+#endif
/* write single register with mask */
static int rtl2832_sdr_wr_reg_mask(struct rtl2832_sdr_state *s, u16 reg,
@@ -295,6 +292,7 @@ static int rtl2832_sdr_wr_reg_mask(struct rtl2832_sdr_state *s, u16 reg,
return rtl2832_sdr_wr_regs(s, reg, &val, 1);
}
+#if 0
/* read single register with mask */
static int rtl2832_sdr_rd_reg_mask(struct rtl2832_sdr_state *s, u16 reg,
u8 *val, u8 mask)
@@ -662,10 +660,9 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
struct dvb_frontend *fe = s->fe;
int ret;
unsigned int f_sr, f_if;
- u8 buf[4], tmp;
+ u8 buf[4], u8tmp1, u8tmp2;
u64 u64tmp;
u32 u32tmp;
-
dev_dbg(&s->udev->dev, "%s: f_adc=%u\n", __func__, s->f_adc);
if (!test_bit(POWER_ON, &s->flags))
@@ -677,9 +674,12 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
f_sr = s->f_adc;
ret = rtl2832_sdr_wr_regs(s, 0x13e, "\x00\x00", 2);
- ret = rtl2832_sdr_wr_regs(s, 0x115, "\x00", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x116, "\x00\x00", 2);
- ret = rtl2832_sdr_wr_regs(s, 0x118, "\x00", 1);
+ if (ret)
+ goto err;
+
+ ret = rtl2832_sdr_wr_regs(s, 0x115, "\x00\x00\x00\x00", 4);
+ if (ret)
+ goto err;
/* get IF from tuner */
if (fe->ops.tuner_ops.get_if_frequency)
@@ -708,13 +708,25 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
if (ret)
goto err;
- /* program BB / IF mode */
- if (f_if)
- tmp = 0x00;
- else
- tmp = 0x01;
+ /* BB / IF mode */
+ /* POR: 0x1b1=0x1f, 0x008=0x0d, 0x006=0x80 */
+ if (f_if) {
+ u8tmp1 = 0x1a; /* disable Zero-IF */
+ u8tmp2 = 0x8d; /* enable ADC I */
+ } else {
+ u8tmp1 = 0x1b; /* enable Zero-IF, DC, IQ */
+ u8tmp2 = 0xcd; /* enable ADC I, ADC Q */
+ }
- ret = rtl2832_sdr_wr_reg(s, 0x1b1, tmp);
+ ret = rtl2832_sdr_wr_reg(s, 0x1b1, u8tmp1);
+ if (ret)
+ goto err;
+
+ ret = rtl2832_sdr_wr_reg(s, 0x008, u8tmp2);
+ if (ret)
+ goto err;
+
+ ret = rtl2832_sdr_wr_reg(s, 0x006, 0x80);
if (ret)
goto err;
@@ -729,101 +741,59 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
if (ret)
goto err;
- ret = rtl2832_sdr_wr_regs(s, 0x11c, "\xca", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x11d, "\xdc", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x11e, "\xd7", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x11f, "\xd8", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x120, "\xe0", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x121, "\xf2", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x122, "\x0e", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x123, "\x35", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x124, "\x06", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x125, "\x50", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x126, "\x9c", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x127, "\x0d", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x128, "\x71", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x129, "\x11", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x12a, "\x14", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x12b, "\x71", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x12c, "\x74", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x12d, "\x19", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x12e, "\x41", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x12f, "\xa5", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x017, "\x11", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x018, "\x10", 1);
+ /* low-pass filter */
+ ret = rtl2832_sdr_wr_regs(s, 0x11c,
+ "\xca\xdc\xd7\xd8\xe0\xf2\x0e\x35\x06\x50\x9c\x0d\x71\x11\x14\x71\x74\x19\x41\xa5",
+ 20);
+ if (ret)
+ goto err;
+
+ /* mode */
+ ret = rtl2832_sdr_wr_regs(s, 0x017, "\x11\x10", 2);
+ if (ret)
+ goto err;
+
ret = rtl2832_sdr_wr_regs(s, 0x019, "\x21", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x01f, "\xff", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x01e, "\x01", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x01d, "\x06", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x01c, "\x0d", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x01b, "\x16", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x01a, "\x1b", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x192, "\x00", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x193, "\xf0", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x194, "\x0f", 1);
+ if (ret)
+ goto err;
+
+ ret = rtl2832_sdr_wr_regs(s, 0x01a, "\x1b\x16\x0d\x06\x01\xff", 6);
+ if (ret)
+ goto err;
+
+ /* FSM */
+ ret = rtl2832_sdr_wr_regs(s, 0x192, "\x00\xf0\x0f", 3);
+ if (ret)
+ goto err;
+
+ /* PID filter */
ret = rtl2832_sdr_wr_regs(s, 0x061, "\x60", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x006, "\x80", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x112, "\x5a", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x102, "\x40", 1);
+ if (ret)
+ goto err;
- if (s->cfg->tuner == RTL2832_TUNER_R820T) {
- ret = rtl2832_sdr_wr_regs(s, 0x115, "\x01", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x103, "\x80", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x24", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x104, "\xcc", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x14", 1);
- } else if (s->cfg->tuner == RTL2832_TUNER_FC0012 ||
- s->cfg->tuner == RTL2832_TUNER_FC0013) {
- ret = rtl2832_sdr_wr_regs(s, 0x103, "\x5a", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x2c", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x104, "\xcc", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x16", 1);
- } else {
+ /* used RF tuner based settings */
+ switch (s->cfg->tuner) {
+ case RTL2832_TUNER_E4000:
+ ret = rtl2832_sdr_wr_regs(s, 0x112, "\x5a", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x102, "\x40", 1);
ret = rtl2832_sdr_wr_regs(s, 0x103, "\x5a", 1);
ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x30", 1);
ret = rtl2832_sdr_wr_regs(s, 0x104, "\xd0", 1);
ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1);
ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x18", 1);
- }
-
- ret = rtl2832_sdr_wr_regs(s, 0x106, "\x35", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1c9, "\x21", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1ca, "\x21", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1cb, "\x00", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x107, "\x40", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1cd, "\x10", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1ce, "\x10", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x108, "\x80", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x109, "\x7f", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x10a, "\x80", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x10b, "\x7f", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
-
- if (s->cfg->tuner == RTL2832_TUNER_R820T) {
- ret = rtl2832_sdr_wr_regs(s, 0x011, "\xf4", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x101, "\x14", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x101, "\x10", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x019, "\x21", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x116, "\x00\x00", 2);
- ret = rtl2832_sdr_wr_regs(s, 0x118, "\x00", 1);
- } else if (s->cfg->tuner == RTL2832_TUNER_FC0012 ||
- s->cfg->tuner == RTL2832_TUNER_FC0013) {
- ret = rtl2832_sdr_wr_regs(s, 0x011, "\xe9\xbf", 2);
- ret = rtl2832_sdr_wr_regs(s, 0x1e5, "\xf0", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1d9, "\x00", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1db, "\x00", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1dd, "\x11", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1de, "\xef", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1d8, "\x0c", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1e6, "\x02", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x1d7, "\x09", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x008, "\xcd", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x101, "\x14", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x101, "\x10", 1);
- } else {
+ ret = rtl2832_sdr_wr_regs(s, 0x106, "\x35", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1c9, "\x21", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1ca, "\x21", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1cb, "\x00", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x107, "\x40", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1cd, "\x10", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1ce, "\x10", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x108, "\x80", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x109, "\x7f", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x10a, "\x80", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x10b, "\x7f", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
ret = rtl2832_sdr_wr_regs(s, 0x011, "\xd4", 1);
ret = rtl2832_sdr_wr_regs(s, 0x1e5, "\xf0", 1);
ret = rtl2832_sdr_wr_regs(s, 0x1d9, "\x00", 1);
@@ -838,16 +808,115 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x87", 1);
ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x85", 1);
ret = rtl2832_sdr_wr_regs(s, 0x013, "\x02", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x008, "\xcd", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x10c, "\x00", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x101, "\x14", 1);
- ret = rtl2832_sdr_wr_regs(s, 0x101, "\x10", 1);
+ break;
+ case RTL2832_TUNER_FC0012:
+ case RTL2832_TUNER_FC0013:
+ ret = rtl2832_sdr_wr_regs(s, 0x112, "\x5a", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x102, "\x40", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x103, "\x5a", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x2c", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x104, "\xcc", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x16", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x106, "\x35", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1c9, "\x21", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1ca, "\x21", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1cb, "\x00", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x107, "\x40", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1cd, "\x10", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1ce, "\x10", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x108, "\x80", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x109, "\x7f", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x10a, "\x80", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x10b, "\x7f", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x011, "\xe9\xbf", 2);
+ ret = rtl2832_sdr_wr_regs(s, 0x1e5, "\xf0", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1d9, "\x00", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1db, "\x00", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1dd, "\x11", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1de, "\xef", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1d8, "\x0c", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1e6, "\x02", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1d7, "\x09", 1);
+ break;
+ case RTL2832_TUNER_R820T:
+ ret = rtl2832_sdr_wr_regs(s, 0x112, "\x5a", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x102, "\x40", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x115, "\x01", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x103, "\x80", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x24", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x104, "\xcc", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x14", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x106, "\x35", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1c9, "\x21", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1ca, "\x21", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1cb, "\x00", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x107, "\x40", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1cd, "\x10", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x1ce, "\x10", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x108, "\x80", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x109, "\x7f", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x10a, "\x80", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x10b, "\x7f", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
+ ret = rtl2832_sdr_wr_regs(s, 0x011, "\xf4", 1);
+ break;
+ default:
+ dev_notice(&s->udev->dev, "Unsupported tuner\n");
}
+ /* software reset */
+ ret = rtl2832_sdr_wr_reg_mask(s, 0x101, 0x04, 0x04);
+ if (ret)
+ goto err;
+
+ ret = rtl2832_sdr_wr_reg_mask(s, 0x101, 0x00, 0x04);
+ if (ret)
+ goto err;
err:
return ret;
};
+static void rtl2832_sdr_unset_adc(struct rtl2832_sdr_state *s)
+{
+ int ret;
+
+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+ /* PID filter */
+ ret = rtl2832_sdr_wr_regs(s, 0x061, "\xe0", 1);
+ if (ret)
+ goto err;
+
+ /* mode */
+ ret = rtl2832_sdr_wr_regs(s, 0x019, "\x20", 1);
+ if (ret)
+ goto err;
+
+ ret = rtl2832_sdr_wr_regs(s, 0x017, "\x11\x10", 2);
+ if (ret)
+ goto err;
+
+ /* FSM */
+ ret = rtl2832_sdr_wr_regs(s, 0x192, "\x00\x0f\xff", 3);
+ if (ret)
+ goto err;
+
+ ret = rtl2832_sdr_wr_regs(s, 0x13e, "\x40\x00", 2);
+ if (ret)
+ goto err;
+
+ ret = rtl2832_sdr_wr_regs(s, 0x115, "\x06\x3f\xce\xcc", 4);
+ if (ret)
+ goto err;
+err:
+ return;
+};
+
static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s)
{
struct dvb_frontend *fe = s->fe;
@@ -887,6 +956,7 @@ static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s)
c->bandwidth_hz = bandwidth;
c->frequency = f_rf;
+ c->delivery_system = SYS_DVBT;
if (fe->ops.tuner_ops.set_params)
fe->ops.tuner_ops.set_params(fe);
@@ -961,6 +1031,7 @@ static int rtl2832_sdr_stop_streaming(struct vb2_queue *vq)
rtl2832_sdr_free_urbs(s);
rtl2832_sdr_free_stream_bufs(s);
rtl2832_sdr_cleanup_queued_bufs(s);
+ rtl2832_sdr_unset_adc(s);
rtl2832_sdr_unset_tuner(s);
clear_bit(POWER_ON, &s->flags);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 30/86] rtl2832_sdr: remove FMT buffer type checks
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (28 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 29/86] rtl2832_sdr: improve ADC device programming logic Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 31/86] rtl2832_sdr: switch FM to DAB mode Antti Palosaari
` (57 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Remove unneeded buffer type checks from FMT IOTCL handlers. Checks
are already done by V4L core.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index 0bc417d..d101409 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -1191,9 +1191,6 @@ static int rtl2832_sdr_g_fmt_sdr_cap(struct file *file, void *priv,
struct rtl2832_sdr_state *s = video_drvdata(file);
dev_dbg(&s->udev->dev, "%s:\n", __func__);
- if (f->type != V4L2_BUF_TYPE_SDR_CAPTURE)
- return -EINVAL;
-
f->fmt.sdr.pixelformat = s->pixelformat;
return 0;
@@ -1208,9 +1205,6 @@ static int rtl2832_sdr_s_fmt_sdr_cap(struct file *file, void *priv,
dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
(char *)&f->fmt.sdr.pixelformat);
- if (f->type != V4L2_BUF_TYPE_SDR_CAPTURE)
- return -EINVAL;
-
if (vb2_is_busy(q))
return -EBUSY;
@@ -1235,9 +1229,6 @@ static int rtl2832_sdr_try_fmt_sdr_cap(struct file *file, void *priv,
dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
(char *)&f->fmt.sdr.pixelformat);
- if (f->type != V4L2_BUF_TYPE_SDR_CAPTURE)
- return -EINVAL;
-
for (i = 0; i < NUM_FORMATS; i++) {
if (formats[i].pixelformat == f->fmt.sdr.pixelformat)
return 0;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 31/86] rtl2832_sdr: switch FM to DAB mode
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (29 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 30/86] rtl2832_sdr: remove FMT buffer type checks Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 32/86] msi3101: calculate tuner filters Antti Palosaari
` (56 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
It seems to perform a little bit better on weak signals when mode
is DAB. It looks like weak signals are faded out by squelch(?) in
FM mode as voice was silenced under one sec when tuned to weak FM
station.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index d101409..fccb16f 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -748,12 +748,12 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
if (ret)
goto err;
- /* mode */
ret = rtl2832_sdr_wr_regs(s, 0x017, "\x11\x10", 2);
if (ret)
goto err;
- ret = rtl2832_sdr_wr_regs(s, 0x019, "\x21", 1);
+ /* mode */
+ ret = rtl2832_sdr_wr_regs(s, 0x019, "\x05", 1);
if (ret)
goto err;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 32/86] msi3101: calculate tuner filters
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (30 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 31/86] rtl2832_sdr: switch FM to DAB mode Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 33/86] msi3101: remove FMT buffer type checks Antti Palosaari
` (55 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Calculate tuner filters from sampling rate and use it if not
defined manually.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/msi3101/sdr-msi3101.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index cb66f81..02960c7 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -1416,7 +1416,7 @@ static int msi3101_set_tuner(struct msi3101_state *s)
{5000000, 0x04}, /* 5 MHz */
{6000000, 0x05}, /* 6 MHz */
{7000000, 0x06}, /* 7 MHz */
- {8000000, 0x07}, /* 8 MHz */
+ { ~0U, 0x07}, /* 8 MHz */
};
unsigned int f_rf = s->f_tuner;
@@ -1473,8 +1473,12 @@ static int msi3101_set_tuner(struct msi3101_state *s)
if (i == ARRAY_SIZE(if_freq_lut))
goto err;
+ /* user has not requested bandwidth, set some reasonable */
+ if (bandwidth == 0)
+ bandwidth = s->f_adc;
+
for (i = 0; i < ARRAY_SIZE(bandwidth_lut); i++) {
- if (bandwidth == bandwidth_lut[i].freq) {
+ if (bandwidth <= bandwidth_lut[i].freq) {
bandwidth = bandwidth_lut[i].val;
break;
}
@@ -1483,6 +1487,9 @@ static int msi3101_set_tuner(struct msi3101_state *s)
if (i == ARRAY_SIZE(bandwidth_lut))
goto err;
+ dev_dbg(&s->udev->dev, "%s: bandwidth selected=%d\n",
+ __func__, bandwidth_lut[i].freq);
+
#define F_OUT_STEP 1
#define R_REF 4
f_vco = (f_rf + f_if + f_if1) * lo_div;
@@ -1925,9 +1932,9 @@ static int msi3101_probe(struct usb_interface *intf,
.id = MSI3101_CID_TUNER_BW,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Tuner Bandwidth",
- .min = 200000,
+ .min = 0,
.max = 8000000,
- .def = 600000,
+ .def = 0,
.step = 1,
};
static const struct v4l2_ctrl_config ctrl_tuner_gain = {
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 33/86] msi3101: remove FMT buffer type checks
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (31 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 32/86] msi3101: calculate tuner filters Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 34/86] msi3101: improve ADC config stream format selection Antti Palosaari
` (54 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Remove unneeded buffer type checks from FMT IOTCL handlers. Checks
are already done by V4L core.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/msi3101/sdr-msi3101.c | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index 02960c7..6b9f0da 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -1679,9 +1679,6 @@ static int msi3101_g_fmt_sdr_cap(struct file *file, void *priv,
struct msi3101_state *s = video_drvdata(file);
dev_dbg(&s->udev->dev, "%s:\n", __func__);
- if (f->type != V4L2_BUF_TYPE_SDR_CAPTURE)
- return -EINVAL;
-
f->fmt.sdr.pixelformat = s->pixelformat;
return 0;
@@ -1696,9 +1693,6 @@ static int msi3101_s_fmt_sdr_cap(struct file *file, void *priv,
dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
(char *)&f->fmt.sdr.pixelformat);
- if (f->type != V4L2_BUF_TYPE_SDR_CAPTURE)
- return -EINVAL;
-
if (vb2_is_busy(q))
return -EBUSY;
@@ -1723,9 +1717,6 @@ static int msi3101_try_fmt_sdr_cap(struct file *file, void *priv,
dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
(char *)&f->fmt.sdr.pixelformat);
- if (f->type != V4L2_BUF_TYPE_SDR_CAPTURE)
- return -EINVAL;
-
for (i = 0; i < NUM_FORMATS; i++) {
if (formats[i].pixelformat == f->fmt.sdr.pixelformat)
return 0;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 34/86] msi3101: improve ADC config stream format selection
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (32 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 33/86] msi3101: remove FMT buffer type checks Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 35/86] msi3101: clamp ADC and RF to valid range Antti Palosaari
` (53 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Improve ADC config stream format selection. No functional changes.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/msi3101/sdr-msi3101.c | 37 +++++++++++++----------------
1 file changed, 17 insertions(+), 20 deletions(-)
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index 6b9f0da..ba37fce 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -1247,38 +1247,35 @@ static int msi3101_set_usb_adc(struct msi3101_state *s)
f_sr = s->f_adc;
/* select stream format */
- if (f_sr < 6000000) {
- s->convert_stream = msi3101_convert_stream_252;
- reg7 = 0x00009407;
- } else if (f_sr < 8000000) {
- s->convert_stream = msi3101_convert_stream_336;
- reg7 = 0x00008507;
- } else if (f_sr < 9000000) {
- s->convert_stream = msi3101_convert_stream_384;
- reg7 = 0x0000a507;
- } else {
- s->convert_stream = msi3101_convert_stream_504;
- reg7 = 0x000c9407;
- }
-
- if (s->pixelformat == V4L2_PIX_FMT_SDR_U8) {
+ switch (s->pixelformat) {
+ case V4L2_PIX_FMT_SDR_U8:
s->convert_stream = msi3101_convert_stream_504_u8;
reg7 = 0x000c9407;
- } else if (s->pixelformat == V4L2_PIX_FMT_SDR_U16LE) {
+ break;
+ case V4L2_PIX_FMT_SDR_U16LE:
s->convert_stream = msi3101_convert_stream_252_u16;
reg7 = 0x00009407;
- } else if (s->pixelformat == V4L2_PIX_FMT_SDR_S8) {
+ break;
+ case V4L2_PIX_FMT_SDR_S8:
s->convert_stream = msi3101_convert_stream_504;
reg7 = 0x000c9407;
- } else if (s->pixelformat == V4L2_PIX_FMT_SDR_MSI2500_384) {
+ break;
+ case V4L2_PIX_FMT_SDR_MSI2500_384:
s->convert_stream = msi3101_convert_stream_384;
reg7 = 0x0000a507;
- } else if (s->pixelformat == V4L2_PIX_FMT_SDR_S12) {
+ break;
+ case V4L2_PIX_FMT_SDR_S12:
s->convert_stream = msi3101_convert_stream_336;
reg7 = 0x00008507;
- } else if (s->pixelformat == V4L2_PIX_FMT_SDR_S14) {
+ break;
+ case V4L2_PIX_FMT_SDR_S14:
s->convert_stream = msi3101_convert_stream_252;
reg7 = 0x00009407;
+ break;
+ default:
+ s->convert_stream = msi3101_convert_stream_504_u8;
+ reg7 = 0x000c9407;
+ break;
}
/*
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 35/86] msi3101: clamp ADC and RF to valid range
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (33 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 34/86] msi3101: improve ADC config stream format selection Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 36/86] msi3101: disable all but u8 and u16le formats Antti Palosaari
` (52 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Clamp both sampling frequency and RF frequency to valid range to
meet V4L2 API spec. It is caller responsibility to check valid ranges
using VIDIOC_ENUM_FREQ_BANDS IOCTL.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/msi3101/sdr-msi3101.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index ba37fce..2b812fe 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -1779,17 +1779,26 @@ static int msi3101_s_frequency(struct file *file, void *priv,
const struct v4l2_frequency *f)
{
struct msi3101_state *s = video_drvdata(file);
- int ret;
+ int ret, band;
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 = f->frequency;
+ s->f_adc = clamp_t(unsigned int, f->frequency,
+ bands_adc[0].rangelow,
+ bands_adc[0].rangehigh);
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) {
- s->f_tuner = f->frequency;
+ #define BAND_RF_0 ((bands_rf[0].rangehigh + bands_rf[1].rangelow) / 2)
+ if (f->frequency < BAND_RF_0)
+ band = 0;
+ else
+ band = 1;
+ s->f_tuner = clamp_t(unsigned int, f->frequency,
+ bands_rf[band].rangelow,
+ bands_rf[band].rangehigh);
dev_dbg(&s->udev->dev, "%s: RF frequency=%u Hz\n",
__func__, f->frequency);
ret = msi3101_set_tuner(s);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 36/86] msi3101: disable all but u8 and u16le formats
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (34 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 35/86] msi3101: clamp ADC and RF to valid range Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 37/86] v4l: add RF tuner gain controls Antti Palosaari
` (51 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
As for now, better to support only two general stream formats.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/msi3101/sdr-msi3101.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index 2b812fe..e6b7cba 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -416,6 +416,7 @@ static struct msi3101_format formats[] = {
}, {
.name = "16-bit unsigned little endian",
.pixelformat = V4L2_PIX_FMT_SDR_U16LE,
+#if 0
}, {
.name = "8-bit signed",
.pixelformat = V4L2_PIX_FMT_SDR_S8,
@@ -428,6 +429,7 @@ static struct msi3101_format formats[] = {
}, {
.name = "14-bit signed",
.pixelformat = V4L2_PIX_FMT_SDR_S14,
+#endif
},
};
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 37/86] v4l: add RF tuner gain controls
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (35 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 36/86] msi3101: disable all but u8 and u16le formats Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 38/86] msi3101: use standard V4L " Antti Palosaari
` (50 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Modern silicon RF tuners used nowadays has many controllable gain
stages on signal path. Usually, but not always, there is at least
3 gain stages. Also on some cases there could be multiple gain
stages within the ones specified here. However, I think that having
these three controllable gain stages offers enough fine-tuning for
real use cases.
1) LNA gain. That is first gain just after antenna input.
2) Mixer gain. It is located quite middle of the signal path, where
RF signal is down-converted to IF/BB.
3) IF gain. That is last gain in order to adjust output signal level
to optimal level for receiving party (usually demodulator ADC).
Each gain stage could be set rather often both manual or automatic
(AGC) mode. Due to that add separate controls for controlling
operation mode.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/v4l2-core/v4l2-ctrls.c | 15 +++++++++++++++
include/uapi/linux/v4l2-controls.h | 11 +++++++++++
2 files changed, 26 insertions(+)
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 6ff002b..d201f61 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -857,6 +857,14 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_FM_RX_CLASS: return "FM Radio Receiver Controls";
case V4L2_CID_TUNE_DEEMPHASIS: return "De-Emphasis";
case V4L2_CID_RDS_RECEPTION: return "RDS Reception";
+
+ case V4L2_CID_RF_TUNER_CLASS: return "RF Tuner Controls";
+ case V4L2_CID_LNA_GAIN_AUTO: return "LNA Gain, Auto";
+ case V4L2_CID_LNA_GAIN: return "LNA Gain";
+ case V4L2_CID_MIXER_GAIN_AUTO: return "Mixer Gain, Auto";
+ case V4L2_CID_MIXER_GAIN: return "Mixer Gain";
+ case V4L2_CID_IF_GAIN_AUTO: return "IF Gain, Auto";
+ case V4L2_CID_IF_GAIN: return "IF Gain";
default:
return NULL;
}
@@ -906,6 +914,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_WIDE_DYNAMIC_RANGE:
case V4L2_CID_IMAGE_STABILIZATION:
case V4L2_CID_RDS_RECEPTION:
+ case V4L2_CID_LNA_GAIN_AUTO:
+ case V4L2_CID_MIXER_GAIN_AUTO:
+ case V4L2_CID_IF_GAIN_AUTO:
*type = V4L2_CTRL_TYPE_BOOLEAN;
*min = 0;
*max = *step = 1;
@@ -991,6 +1002,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_IMAGE_PROC_CLASS:
case V4L2_CID_DV_CLASS:
case V4L2_CID_FM_RX_CLASS:
+ case V4L2_CID_RF_TUNER_CLASS:
*type = V4L2_CTRL_TYPE_CTRL_CLASS;
/* You can neither read not write these */
*flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY;
@@ -1063,6 +1075,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_PILOT_TONE_FREQUENCY:
case V4L2_CID_TUNE_POWER_LEVEL:
case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
+ case V4L2_CID_LNA_GAIN:
+ case V4L2_CID_MIXER_GAIN:
+ case V4L2_CID_IF_GAIN:
*flags |= V4L2_CTRL_FLAG_SLIDER;
break;
case V4L2_CID_PAN_RELATIVE:
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 2cbe605..076fa34 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -60,6 +60,7 @@
#define V4L2_CTRL_CLASS_IMAGE_PROC 0x009f0000 /* Image processing controls */
#define V4L2_CTRL_CLASS_DV 0x00a00000 /* Digital Video controls */
#define V4L2_CTRL_CLASS_FM_RX 0x00a10000 /* FM Receiver controls */
+#define V4L2_CTRL_CLASS_RF_TUNER 0x00a20000 /* RF tuner controls */
/* User-class control IDs */
@@ -895,4 +896,14 @@ enum v4l2_deemphasis {
#define V4L2_CID_RDS_RECEPTION (V4L2_CID_FM_RX_CLASS_BASE + 2)
+#define V4L2_CID_RF_TUNER_CLASS_BASE (V4L2_CTRL_CLASS_RF_TUNER | 0x900)
+#define V4L2_CID_RF_TUNER_CLASS (V4L2_CTRL_CLASS_RF_TUNER | 1)
+
+#define V4L2_CID_LNA_GAIN_AUTO (V4L2_CID_RF_TUNER_CLASS_BASE + 1)
+#define V4L2_CID_LNA_GAIN (V4L2_CID_RF_TUNER_CLASS_BASE + 2)
+#define V4L2_CID_MIXER_GAIN_AUTO (V4L2_CID_RF_TUNER_CLASS_BASE + 3)
+#define V4L2_CID_MIXER_GAIN (V4L2_CID_RF_TUNER_CLASS_BASE + 4)
+#define V4L2_CID_IF_GAIN_AUTO (V4L2_CID_RF_TUNER_CLASS_BASE + 5)
+#define V4L2_CID_IF_GAIN (V4L2_CID_RF_TUNER_CLASS_BASE + 6)
+
#endif
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 38/86] msi3101: use standard V4L gain controls
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (36 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 37/86] v4l: add RF tuner gain controls Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 39/86] e4000: convert DVB tuner to I2C driver model Antti Palosaari
` (49 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Use LNA, Mixer and IF gain controls offered by V4L API.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/msi3101/sdr-msi3101.c | 433 ++++------------------------
1 file changed, 56 insertions(+), 377 deletions(-)
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index e6b7cba..e8dfcac 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -34,317 +34,6 @@
#include <linux/usb.h>
#include <media/videobuf2-vmalloc.h>
-struct msi3101_gain {
- u8 tot:7;
- u8 baseband:6;
- bool lna:1;
- bool mixer:1;
-};
-
-/* 60 – 120 MHz band, lna 24dB, mixer 19dB */
-static const struct msi3101_gain msi3101_gain_lut_120[] = {
- { 0, 0, 0, 0},
- { 1, 1, 0, 0},
- { 2, 2, 0, 0},
- { 3, 3, 0, 0},
- { 4, 4, 0, 0},
- { 5, 5, 0, 0},
- { 6, 6, 0, 0},
- { 7, 7, 0, 0},
- { 8, 8, 0, 0},
- { 9, 9, 0, 0},
- { 10, 10, 0, 0},
- { 11, 11, 0, 0},
- { 12, 12, 0, 0},
- { 13, 13, 0, 0},
- { 14, 14, 0, 0},
- { 15, 15, 0, 0},
- { 16, 16, 0, 0},
- { 17, 17, 0, 0},
- { 18, 18, 0, 0},
- { 19, 19, 0, 0},
- { 20, 20, 0, 0},
- { 21, 21, 0, 0},
- { 22, 22, 0, 0},
- { 23, 23, 0, 0},
- { 24, 24, 0, 0},
- { 25, 25, 0, 0},
- { 26, 26, 0, 0},
- { 27, 27, 0, 0},
- { 28, 28, 0, 0},
- { 29, 5, 1, 0},
- { 30, 6, 1, 0},
- { 31, 7, 1, 0},
- { 32, 8, 1, 0},
- { 33, 9, 1, 0},
- { 34, 10, 1, 0},
- { 35, 11, 1, 0},
- { 36, 12, 1, 0},
- { 37, 13, 1, 0},
- { 38, 14, 1, 0},
- { 39, 15, 1, 0},
- { 40, 16, 1, 0},
- { 41, 17, 1, 0},
- { 42, 18, 1, 0},
- { 43, 19, 1, 0},
- { 44, 20, 1, 0},
- { 45, 21, 1, 0},
- { 46, 22, 1, 0},
- { 47, 23, 1, 0},
- { 48, 24, 1, 0},
- { 49, 25, 1, 0},
- { 50, 26, 1, 0},
- { 51, 27, 1, 0},
- { 52, 28, 1, 0},
- { 53, 29, 1, 0},
- { 54, 30, 1, 0},
- { 55, 31, 1, 0},
- { 56, 32, 1, 0},
- { 57, 33, 1, 0},
- { 58, 34, 1, 0},
- { 59, 35, 1, 0},
- { 60, 36, 1, 0},
- { 61, 37, 1, 0},
- { 62, 38, 1, 0},
- { 63, 39, 1, 0},
- { 64, 40, 1, 0},
- { 65, 41, 1, 0},
- { 66, 42, 1, 0},
- { 67, 43, 1, 0},
- { 68, 44, 1, 0},
- { 69, 45, 1, 0},
- { 70, 46, 1, 0},
- { 71, 47, 1, 0},
- { 72, 48, 1, 0},
- { 73, 49, 1, 0},
- { 74, 50, 1, 0},
- { 75, 51, 1, 0},
- { 76, 52, 1, 0},
- { 77, 53, 1, 0},
- { 78, 54, 1, 0},
- { 79, 55, 1, 0},
- { 80, 56, 1, 0},
- { 81, 57, 1, 0},
- { 82, 58, 1, 0},
- { 83, 40, 1, 1},
- { 84, 41, 1, 1},
- { 85, 42, 1, 1},
- { 86, 43, 1, 1},
- { 87, 44, 1, 1},
- { 88, 45, 1, 1},
- { 89, 46, 1, 1},
- { 90, 47, 1, 1},
- { 91, 48, 1, 1},
- { 92, 49, 1, 1},
- { 93, 50, 1, 1},
- { 94, 51, 1, 1},
- { 95, 52, 1, 1},
- { 96, 53, 1, 1},
- { 97, 54, 1, 1},
- { 98, 55, 1, 1},
- { 99, 56, 1, 1},
- {100, 57, 1, 1},
- {101, 58, 1, 1},
- {102, 59, 1, 1},
-};
-
-/* 120 – 245 MHz band, lna 24dB, mixer 19dB */
-static const struct msi3101_gain msi3101_gain_lut_245[] = {
- { 0, 0, 0, 0},
- { 1, 1, 0, 0},
- { 2, 2, 0, 0},
- { 3, 3, 0, 0},
- { 4, 4, 0, 0},
- { 5, 5, 0, 0},
- { 6, 6, 0, 0},
- { 7, 7, 0, 0},
- { 8, 8, 0, 0},
- { 9, 9, 0, 0},
- { 10, 10, 0, 0},
- { 11, 11, 0, 0},
- { 12, 12, 0, 0},
- { 13, 13, 0, 0},
- { 14, 14, 0, 0},
- { 15, 15, 0, 0},
- { 16, 16, 0, 0},
- { 17, 17, 0, 0},
- { 18, 18, 0, 0},
- { 19, 19, 0, 0},
- { 20, 20, 0, 0},
- { 21, 21, 0, 0},
- { 22, 22, 0, 0},
- { 23, 23, 0, 0},
- { 24, 24, 0, 0},
- { 25, 25, 0, 0},
- { 26, 26, 0, 0},
- { 27, 27, 0, 0},
- { 28, 28, 0, 0},
- { 29, 5, 1, 0},
- { 30, 6, 1, 0},
- { 31, 7, 1, 0},
- { 32, 8, 1, 0},
- { 33, 9, 1, 0},
- { 34, 10, 1, 0},
- { 35, 11, 1, 0},
- { 36, 12, 1, 0},
- { 37, 13, 1, 0},
- { 38, 14, 1, 0},
- { 39, 15, 1, 0},
- { 40, 16, 1, 0},
- { 41, 17, 1, 0},
- { 42, 18, 1, 0},
- { 43, 19, 1, 0},
- { 44, 20, 1, 0},
- { 45, 21, 1, 0},
- { 46, 22, 1, 0},
- { 47, 23, 1, 0},
- { 48, 24, 1, 0},
- { 49, 25, 1, 0},
- { 50, 26, 1, 0},
- { 51, 27, 1, 0},
- { 52, 28, 1, 0},
- { 53, 29, 1, 0},
- { 54, 30, 1, 0},
- { 55, 31, 1, 0},
- { 56, 32, 1, 0},
- { 57, 33, 1, 0},
- { 58, 34, 1, 0},
- { 59, 35, 1, 0},
- { 60, 36, 1, 0},
- { 61, 37, 1, 0},
- { 62, 38, 1, 0},
- { 63, 39, 1, 0},
- { 64, 40, 1, 0},
- { 65, 41, 1, 0},
- { 66, 42, 1, 0},
- { 67, 43, 1, 0},
- { 68, 44, 1, 0},
- { 69, 45, 1, 0},
- { 70, 46, 1, 0},
- { 71, 47, 1, 0},
- { 72, 48, 1, 0},
- { 73, 49, 1, 0},
- { 74, 50, 1, 0},
- { 75, 51, 1, 0},
- { 76, 52, 1, 0},
- { 77, 53, 1, 0},
- { 78, 54, 1, 0},
- { 79, 55, 1, 0},
- { 80, 56, 1, 0},
- { 81, 57, 1, 0},
- { 82, 58, 1, 0},
- { 83, 40, 1, 1},
- { 84, 41, 1, 1},
- { 85, 42, 1, 1},
- { 86, 43, 1, 1},
- { 87, 44, 1, 1},
- { 88, 45, 1, 1},
- { 89, 46, 1, 1},
- { 90, 47, 1, 1},
- { 91, 48, 1, 1},
- { 92, 49, 1, 1},
- { 93, 50, 1, 1},
- { 94, 51, 1, 1},
- { 95, 52, 1, 1},
- { 96, 53, 1, 1},
- { 97, 54, 1, 1},
- { 98, 55, 1, 1},
- { 99, 56, 1, 1},
- {100, 57, 1, 1},
- {101, 58, 1, 1},
- {102, 59, 1, 1},
-};
-
-/* 420 – 1000 MHz band, lna 7dB, mixer 19dB */
-static const struct msi3101_gain msi3101_gain_lut_1000[] = {
- { 0, 0, 0, 0},
- { 1, 1, 0, 0},
- { 2, 2, 0, 0},
- { 3, 3, 0, 0},
- { 4, 4, 0, 0},
- { 5, 5, 0, 0},
- { 6, 6, 0, 0},
- { 7, 7, 0, 0},
- { 8, 8, 0, 0},
- { 9, 9, 0, 0},
- { 10, 10, 0, 0},
- { 11, 11, 0, 0},
- { 12, 5, 1, 0},
- { 13, 6, 1, 0},
- { 14, 7, 1, 0},
- { 15, 8, 1, 0},
- { 16, 9, 1, 0},
- { 17, 10, 1, 0},
- { 18, 11, 1, 0},
- { 19, 12, 1, 0},
- { 20, 13, 1, 0},
- { 21, 14, 1, 0},
- { 22, 15, 1, 0},
- { 23, 16, 1, 0},
- { 24, 17, 1, 0},
- { 25, 18, 1, 0},
- { 26, 19, 1, 0},
- { 27, 20, 1, 0},
- { 28, 21, 1, 0},
- { 29, 22, 1, 0},
- { 30, 23, 1, 0},
- { 31, 24, 1, 0},
- { 32, 25, 1, 0},
- { 33, 26, 1, 0},
- { 34, 27, 1, 0},
- { 35, 28, 1, 0},
- { 36, 29, 1, 0},
- { 37, 30, 1, 0},
- { 38, 31, 1, 0},
- { 39, 32, 1, 0},
- { 40, 33, 1, 0},
- { 41, 34, 1, 0},
- { 42, 35, 1, 0},
- { 43, 36, 1, 0},
- { 44, 37, 1, 0},
- { 45, 38, 1, 0},
- { 46, 39, 1, 0},
- { 47, 40, 1, 0},
- { 48, 41, 1, 0},
- { 49, 42, 1, 0},
- { 50, 43, 1, 0},
- { 51, 44, 1, 0},
- { 52, 45, 1, 0},
- { 53, 46, 1, 0},
- { 54, 47, 1, 0},
- { 55, 48, 1, 0},
- { 56, 49, 1, 0},
- { 57, 50, 1, 0},
- { 58, 51, 1, 0},
- { 59, 52, 1, 0},
- { 60, 53, 1, 0},
- { 61, 54, 1, 0},
- { 62, 55, 1, 0},
- { 63, 56, 1, 0},
- { 64, 57, 1, 0},
- { 65, 58, 1, 0},
- { 66, 40, 1, 1},
- { 67, 41, 1, 1},
- { 68, 42, 1, 1},
- { 69, 43, 1, 1},
- { 70, 44, 1, 1},
- { 71, 45, 1, 1},
- { 72, 46, 1, 1},
- { 73, 47, 1, 1},
- { 74, 48, 1, 1},
- { 75, 49, 1, 1},
- { 76, 50, 1, 1},
- { 77, 51, 1, 1},
- { 78, 52, 1, 1},
- { 79, 53, 1, 1},
- { 80, 54, 1, 1},
- { 81, 55, 1, 1},
- { 82, 56, 1, 1},
- { 83, 57, 1, 1},
- { 84, 58, 1, 1},
- { 85, 59, 1, 1},
-};
-
/*
* iConfiguration 0
* bInterfaceNumber 0
@@ -364,7 +53,6 @@ static const struct msi3101_gain msi3101_gain_lut_1000[] = {
/* TODO: These should be moved to V4L2 API */
#define MSI3101_CID_TUNER_BW ((V4L2_CID_USER_BASE | 0xf000) + 11)
-#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 */
@@ -468,9 +156,14 @@ struct msi3101_state {
unsigned int src_len);
/* Controls */
- struct v4l2_ctrl_handler ctrl_handler;
+ 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_auto;
+ struct v4l2_ctrl *if_gain;
struct v4l2_ctrl *ctrl_tuner_bw;
- struct v4l2_ctrl *ctrl_tuner_gain;
u32 next_sample; /* for track lost packets */
u32 sample; /* for sample rate calc */
@@ -1376,14 +1069,37 @@ err:
return ret;
};
+static int msi3101_set_gain(struct msi3101_state *s)
+{
+ int ret;
+ u32 reg;
+ dev_dbg(&s->udev->dev, "%s: lna=%d mixer=%d if=%d\n", __func__,
+ s->lna_gain->val, s->mixer_gain->val, s->if_gain->val);
+
+ reg = 1 << 0;
+ reg |= (59 - s->if_gain->val) << 4;
+ reg |= 0 << 10;
+ reg |= (1 - s->mixer_gain->val) << 12;
+ reg |= (1 - s->lna_gain->val) << 13;
+ reg |= 4 << 14;
+ reg |= 0 << 17;
+ ret = msi3101_tuner_write(s, reg);
+ if (ret)
+ goto err;
+
+ return 0;
+err:
+ dev_dbg(&s->udev->dev, "%s: failed %d\n", __func__, ret);
+ return ret;
+};
+
static int msi3101_set_tuner(struct msi3101_state *s)
{
- int ret, i, len;
+ int ret, i;
unsigned int n, m, thresh, frac, vco_step, tmp, f_if1;
u32 reg;
u64 f_vco, tmp64;
u8 mode, filter_mode, lo_div;
- const struct msi3101_gain *gain_lut;
static const struct {
u32 rf;
u8 mode;
@@ -1432,16 +1148,9 @@ static int msi3101_set_tuner(struct msi3101_state *s)
*/
unsigned int f_if = 0;
- /*
- * gain reduction (dB)
- * 0 - 102 below 420 MHz
- * 0 - 85 above 420 MHz
- */
- int gain = s->ctrl_tuner_gain->val;
-
dev_dbg(&s->udev->dev,
- "%s: f_rf=%d bandwidth=%d f_if=%d gain=%d\n",
- __func__, f_rf, bandwidth, f_if, gain);
+ "%s: f_rf=%d bandwidth=%d f_if=%d\n",
+ __func__, f_rf, bandwidth, f_if);
ret = -EINVAL;
@@ -1553,38 +1262,7 @@ static int msi3101_set_tuner(struct msi3101_state *s)
if (ret)
goto err;
- if (f_rf < 120000000) {
- gain_lut = msi3101_gain_lut_120;
- len = ARRAY_SIZE(msi3101_gain_lut_120);
- } else if (f_rf < 245000000) {
- gain_lut = msi3101_gain_lut_245;
- len = ARRAY_SIZE(msi3101_gain_lut_120);
- } else {
- gain_lut = msi3101_gain_lut_1000;
- len = ARRAY_SIZE(msi3101_gain_lut_1000);
- }
-
- for (i = 0; i < len; i++) {
- if (gain_lut[i].tot >= gain)
- break;
- }
-
- if (i == len)
- goto err;
-
- dev_dbg(&s->udev->dev,
- "%s: gain tot=%d baseband=%d lna=%d mixer=%d\n",
- __func__, gain_lut[i].tot, gain_lut[i].baseband,
- gain_lut[i].lna, gain_lut[i].mixer);
-
- reg = 1 << 0;
- reg |= gain_lut[i].baseband << 4;
- reg |= 0 << 10;
- reg |= gain_lut[i].mixer << 12;
- reg |= gain_lut[i].lna << 13;
- reg |= 4 << 14;
- reg |= 0 << 17;
- ret = msi3101_tuner_write(s, reg);
+ ret = msi3101_set_gain(s);
if (ret)
goto err;
@@ -1887,7 +1565,7 @@ static int msi3101_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct msi3101_state *s =
container_of(ctrl->handler, struct msi3101_state,
- ctrl_handler);
+ hdl);
int ret;
dev_dbg(&s->udev->dev,
"%s: id=%d name=%s val=%d min=%d max=%d step=%d\n",
@@ -1896,10 +1574,15 @@ static int msi3101_s_ctrl(struct v4l2_ctrl *ctrl)
switch (ctrl->id) {
case MSI3101_CID_TUNER_BW:
- case MSI3101_CID_TUNER_GAIN:
ret = msi3101_set_tuner(s);
break;
+ case V4L2_CID_LNA_GAIN:
+ case V4L2_CID_MIXER_GAIN:
+ case V4L2_CID_IF_GAIN:
+ ret = msi3101_set_gain(s);
+ break;
default:
+ dev_dbg(&s->udev->dev, "%s: EINVAL\n", __func__);
ret = -EINVAL;
}
@@ -1915,7 +1598,7 @@ static void msi3101_video_release(struct v4l2_device *v)
struct msi3101_state *s =
container_of(v, struct msi3101_state, v4l2_dev);
- v4l2_ctrl_handler_free(&s->ctrl_handler);
+ v4l2_ctrl_handler_free(&s->hdl);
v4l2_device_unregister(&s->v4l2_dev);
kfree(s);
}
@@ -1925,6 +1608,7 @@ static int msi3101_probe(struct usb_interface *intf,
{
struct usb_device *udev = interface_to_usbdev(intf);
struct msi3101_state *s = NULL;
+ const struct v4l2_ctrl_ops *ops = &msi3101_ctrl_ops;
int ret;
static const struct v4l2_ctrl_config ctrl_tuner_bw = {
.ops = &msi3101_ctrl_ops,
@@ -1936,16 +1620,6 @@ static int msi3101_probe(struct usb_interface *intf,
.def = 0,
.step = 1,
};
- static const struct v4l2_ctrl_config ctrl_tuner_gain = {
- .ops = &msi3101_ctrl_ops,
- .id = MSI3101_CID_TUNER_GAIN,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Tuner Gain",
- .min = 0,
- .max = 102,
- .def = 50,
- .step = 1,
- };
s = kzalloc(sizeof(struct msi3101_state), GFP_KERNEL);
if (s == NULL) {
@@ -1982,11 +1656,16 @@ static int msi3101_probe(struct usb_interface *intf,
video_set_drvdata(&s->vdev, s);
/* Register controls */
- 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_gain = v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_tuner_gain, NULL);
- if (s->ctrl_handler.error) {
- ret = s->ctrl_handler.error;
+ v4l2_ctrl_handler_init(&s->hdl, 4);
+ s->ctrl_tuner_bw = v4l2_ctrl_new_custom(&s->hdl, &ctrl_tuner_bw, NULL);
+ s->lna_gain = v4l2_ctrl_new_std(&s->hdl, ops,
+ V4L2_CID_LNA_GAIN, 0, 1, 1, 1);
+ s->mixer_gain = v4l2_ctrl_new_std(&s->hdl, ops,
+ V4L2_CID_MIXER_GAIN, 0, 1, 1, 1);
+ s->if_gain = v4l2_ctrl_new_std(&s->hdl, ops,
+ V4L2_CID_IF_GAIN, 0, 59, 1, 0);
+ if (s->hdl.error) {
+ ret = s->hdl.error;
dev_err(&s->udev->dev, "Could not initialize controls\n");
goto err_free_controls;
}
@@ -2000,7 +1679,7 @@ static int msi3101_probe(struct usb_interface *intf,
goto err_free_controls;
}
- s->v4l2_dev.ctrl_handler = &s->ctrl_handler;
+ s->v4l2_dev.ctrl_handler = &s->hdl;
s->vdev.v4l2_dev = &s->v4l2_dev;
s->vdev.lock = &s->v4l2_lock;
@@ -2019,7 +1698,7 @@ static int msi3101_probe(struct usb_interface *intf,
err_unregister_v4l2_dev:
v4l2_device_unregister(&s->v4l2_dev);
err_free_controls:
- v4l2_ctrl_handler_free(&s->ctrl_handler);
+ v4l2_ctrl_handler_free(&s->hdl);
err_free_mem:
kfree(s);
return ret;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 39/86] e4000: convert DVB tuner to I2C driver model
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (37 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 38/86] msi3101: use standard V4L " Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 40/86] e4000: add manual gain controls Antti Palosaari
` (48 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari, Jean Delvare, Mauro Carvalho Chehab
Driver conversion from proprietary DVB tuner model to more
general I2C driver model.
Cc: Jean Delvare <khali@linux-fr.org>
Cc: Mauro Carvalho Chehab <m.chehab@samsung.com>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/tuners/e4000.c | 115 ++++++++++++++++++++------------
drivers/media/tuners/e4000.h | 21 ++----
drivers/media/tuners/e4000_priv.h | 5 +-
drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 41 +++++++++---
drivers/media/usb/dvb-usb-v2/rtl28xxu.h | 1 +
5 files changed, 111 insertions(+), 72 deletions(-)
diff --git a/drivers/media/tuners/e4000.c b/drivers/media/tuners/e4000.c
index 40c1da7..0153169 100644
--- a/drivers/media/tuners/e4000.c
+++ b/drivers/media/tuners/e4000.c
@@ -31,7 +31,7 @@ static int e4000_wr_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len)
u8 buf[MAX_XFER_SIZE];
struct i2c_msg msg[1] = {
{
- .addr = priv->cfg->i2c_addr,
+ .addr = priv->client->addr,
.flags = 0,
.len = 1 + len,
.buf = buf,
@@ -39,7 +39,7 @@ static int e4000_wr_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len)
};
if (1 + len > sizeof(buf)) {
- dev_warn(&priv->i2c->dev,
+ dev_warn(&priv->client->dev,
"%s: i2c wr reg=%04x: len=%d is too big!\n",
KBUILD_MODNAME, reg, len);
return -EINVAL;
@@ -48,11 +48,11 @@ static int e4000_wr_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len)
buf[0] = reg;
memcpy(&buf[1], val, len);
- ret = i2c_transfer(priv->i2c, msg, 1);
+ ret = i2c_transfer(priv->client->adapter, msg, 1);
if (ret == 1) {
ret = 0;
} else {
- dev_warn(&priv->i2c->dev,
+ dev_warn(&priv->client->dev,
"%s: i2c wr failed=%d reg=%02x len=%d\n",
KBUILD_MODNAME, ret, reg, len);
ret = -EREMOTEIO;
@@ -67,12 +67,12 @@ static int e4000_rd_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len)
u8 buf[MAX_XFER_SIZE];
struct i2c_msg msg[2] = {
{
- .addr = priv->cfg->i2c_addr,
+ .addr = priv->client->addr,
.flags = 0,
.len = 1,
.buf = ®,
}, {
- .addr = priv->cfg->i2c_addr,
+ .addr = priv->client->addr,
.flags = I2C_M_RD,
.len = len,
.buf = buf,
@@ -80,18 +80,18 @@ static int e4000_rd_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len)
};
if (len > sizeof(buf)) {
- dev_warn(&priv->i2c->dev,
+ dev_warn(&priv->client->dev,
"%s: i2c rd reg=%04x: len=%d is too big!\n",
KBUILD_MODNAME, reg, len);
return -EINVAL;
}
- ret = i2c_transfer(priv->i2c, msg, 2);
+ ret = i2c_transfer(priv->client->adapter, msg, 2);
if (ret == 2) {
memcpy(val, buf, len);
ret = 0;
} else {
- dev_warn(&priv->i2c->dev,
+ dev_warn(&priv->client->dev,
"%s: i2c rd failed=%d reg=%02x len=%d\n",
KBUILD_MODNAME, ret, reg, len);
ret = -EREMOTEIO;
@@ -117,7 +117,7 @@ static int e4000_init(struct dvb_frontend *fe)
struct e4000_priv *priv = fe->tuner_priv;
int ret;
- dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+ dev_dbg(&priv->client->dev, "%s:\n", __func__);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
@@ -186,7 +186,7 @@ err:
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
- dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+ dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
@@ -195,7 +195,7 @@ static int e4000_sleep(struct dvb_frontend *fe)
struct e4000_priv *priv = fe->tuner_priv;
int ret;
- dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+ dev_dbg(&priv->client->dev, "%s:\n", __func__);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
@@ -212,7 +212,7 @@ err:
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
- dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+ dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
@@ -224,7 +224,7 @@ static int e4000_set_params(struct dvb_frontend *fe)
unsigned int f_vco;
u8 buf[5], i_data[4], q_data[4];
- dev_dbg(&priv->i2c->dev,
+ dev_dbg(&priv->client->dev,
"%s: delivery_system=%d frequency=%d bandwidth_hz=%d\n",
__func__, c->delivery_system, c->frequency,
c->bandwidth_hz);
@@ -253,14 +253,15 @@ static int e4000_set_params(struct dvb_frontend *fe)
* or more.
*/
f_vco = c->frequency * e4000_pll_lut[i].mul;
- sigma_delta = div_u64(0x10000ULL * (f_vco % priv->cfg->clock), priv->cfg->clock);
- buf[0] = f_vco / priv->cfg->clock;
+ sigma_delta = div_u64(0x10000ULL * (f_vco % priv->clock), priv->clock);
+ buf[0] = f_vco / priv->clock;
buf[1] = (sigma_delta >> 0) & 0xff;
buf[2] = (sigma_delta >> 8) & 0xff;
buf[3] = 0x00;
buf[4] = e4000_pll_lut[i].div;
- dev_dbg(&priv->i2c->dev, "%s: f_vco=%u pll div=%d sigma_delta=%04x\n",
+ dev_dbg(&priv->client->dev,
+ "%s: f_vco=%u pll div=%d sigma_delta=%04x\n",
__func__, f_vco, buf[0], sigma_delta);
ret = e4000_wr_regs(priv, 0x09, buf, 5);
@@ -369,7 +370,7 @@ err:
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
- dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+ dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
@@ -377,24 +378,13 @@ static int e4000_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
{
struct e4000_priv *priv = fe->tuner_priv;
- dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+ dev_dbg(&priv->client->dev, "%s:\n", __func__);
*frequency = 0; /* Zero-IF */
return 0;
}
-static int e4000_release(struct dvb_frontend *fe)
-{
- struct e4000_priv *priv = fe->tuner_priv;
-
- dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
-
- kfree(fe->tuner_priv);
-
- return 0;
-}
-
static const struct dvb_tuner_ops e4000_tuner_ops = {
.info = {
.name = "Elonics E4000",
@@ -402,8 +392,6 @@ static const struct dvb_tuner_ops e4000_tuner_ops = {
.frequency_max = 862000000,
},
- .release = e4000_release,
-
.init = e4000_init,
.sleep = e4000_sleep,
.set_params = e4000_set_params,
@@ -411,9 +399,11 @@ static const struct dvb_tuner_ops e4000_tuner_ops = {
.get_if_frequency = e4000_get_if_frequency,
};
-struct dvb_frontend *e4000_attach(struct dvb_frontend *fe,
- struct i2c_adapter *i2c, const struct e4000_config *cfg)
+static int e4000_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
+ struct e4000_config *cfg = client->dev.platform_data;
+ struct dvb_frontend *fe = cfg->fe;
struct e4000_priv *priv;
int ret;
u8 chip_id;
@@ -424,29 +414,33 @@ struct dvb_frontend *e4000_attach(struct dvb_frontend *fe,
priv = kzalloc(sizeof(struct e4000_priv), GFP_KERNEL);
if (!priv) {
ret = -ENOMEM;
- dev_err(&i2c->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME);
+ dev_err(&client->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME);
goto err;
}
- priv->cfg = cfg;
- priv->i2c = i2c;
+ priv->clock = cfg->clock;
+ priv->client = client;
+ priv->fe = cfg->fe;
/* check if the tuner is there */
ret = e4000_rd_reg(priv, 0x02, &chip_id);
if (ret < 0)
goto err;
- dev_dbg(&priv->i2c->dev, "%s: chip_id=%02x\n", __func__, chip_id);
+ dev_dbg(&priv->client->dev,
+ "%s: chip_id=%02x\n", __func__, chip_id);
- if (chip_id != 0x40)
+ if (chip_id != 0x40) {
+ ret = -ENODEV;
goto err;
+ }
/* put sleep as chip seems to be in normal mode by default */
ret = e4000_wr_reg(priv, 0x00, 0x00);
if (ret < 0)
goto err;
- dev_info(&priv->i2c->dev,
+ dev_info(&priv->client->dev,
"%s: Elonics E4000 successfully identified\n",
KBUILD_MODNAME);
@@ -457,16 +451,49 @@ struct dvb_frontend *e4000_attach(struct dvb_frontend *fe,
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
- return fe;
+ i2c_set_clientdata(client, priv);
+
+ return 0;
err:
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
- dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
+ dev_dbg(&client->dev, "%s: failed=%d\n", __func__, ret);
kfree(priv);
- return NULL;
+ return ret;
}
-EXPORT_SYMBOL(e4000_attach);
+
+static int e4000_remove(struct i2c_client *client)
+{
+ struct e4000_priv *priv = i2c_get_clientdata(client);
+ struct dvb_frontend *fe = priv->fe;
+
+ dev_dbg(&client->dev, "%s:\n", __func__);
+
+ memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
+ fe->tuner_priv = NULL;
+ kfree(priv);
+
+ return 0;
+}
+
+static const struct i2c_device_id e4000_id[] = {
+ {"e4000", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, e4000_id);
+
+static struct i2c_driver e4000_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "e4000",
+ },
+ .probe = e4000_probe,
+ .remove = e4000_remove,
+ .id_table = e4000_id,
+};
+
+module_i2c_driver(e4000_driver);
MODULE_DESCRIPTION("Elonics E4000 silicon tuner driver");
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff --git a/drivers/media/tuners/e4000.h b/drivers/media/tuners/e4000.h
index 25ee7c0..e74b8b2 100644
--- a/drivers/media/tuners/e4000.h
+++ b/drivers/media/tuners/e4000.h
@@ -24,12 +24,15 @@
#include <linux/kconfig.h>
#include "dvb_frontend.h"
+/*
+ * I2C address
+ * 0x64, 0x65, 0x66, 0x67
+ */
struct e4000_config {
/*
- * I2C address
- * 0x64, 0x65, 0x66, 0x67
+ * frontend
*/
- u8 i2c_addr;
+ struct dvb_frontend *fe;
/*
* clock
@@ -37,16 +40,4 @@ struct e4000_config {
u32 clock;
};
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_E4000)
-extern struct dvb_frontend *e4000_attach(struct dvb_frontend *fe,
- struct i2c_adapter *i2c, const struct e4000_config *cfg);
-#else
-static inline struct dvb_frontend *e4000_attach(struct dvb_frontend *fe,
- struct i2c_adapter *i2c, const struct e4000_config *cfg)
-{
- dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
-}
-#endif
-
#endif
diff --git a/drivers/media/tuners/e4000_priv.h b/drivers/media/tuners/e4000_priv.h
index a385505..8f45a30 100644
--- a/drivers/media/tuners/e4000_priv.h
+++ b/drivers/media/tuners/e4000_priv.h
@@ -24,8 +24,9 @@
#include "e4000.h"
struct e4000_priv {
- const struct e4000_config *cfg;
- struct i2c_adapter *i2c;
+ struct i2c_client *client;
+ u32 clock;
+ struct dvb_frontend *fe;
};
struct e4000_pll {
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index 77f1fc9..76cf0de 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -857,11 +857,6 @@ err:
return ret;
}
-static const struct e4000_config rtl2832u_e4000_config = {
- .i2c_addr = 0x64,
- .clock = 28800000,
-};
-
static const struct fc2580_config rtl2832u_fc2580_config = {
.i2c_addr = 0x56,
.clock = 16384000,
@@ -895,10 +890,13 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
int ret;
struct dvb_usb_device *d = adap_to_d(adap);
struct rtl28xxu_priv *priv = d_to_priv(d);
- struct dvb_frontend *fe;
+ struct dvb_frontend *fe = NULL;
+ struct i2c_board_info info;
dev_dbg(&d->udev->dev, "%s:\n", __func__);
+ memset(&info, 0, sizeof(struct i2c_board_info));
+
switch (priv->tuner) {
case TUNER_RTL2832_FC0012:
fe = dvb_attach(fc0012_attach, adap->fe[0],
@@ -918,9 +916,19 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
adap->fe[0]->ops.read_signal_strength =
adap->fe[0]->ops.tuner_ops.get_rf_strength;
return 0;
- case TUNER_RTL2832_E4000:
- fe = dvb_attach(e4000_attach, adap->fe[0], &d->i2c_adap,
- &rtl2832u_e4000_config);
+ case TUNER_RTL2832_E4000: {
+ struct e4000_config e4000_config = {
+ .fe = adap->fe[0],
+ .clock = 28800000,
+ };
+
+ strlcpy(info.type, "e4000", I2C_NAME_SIZE);
+ info.addr = 0x64;
+ info.platform_data = &e4000_config;
+
+ request_module("e4000");
+ priv->client = i2c_new_device(&d->i2c_adap, &info);
+ }
break;
case TUNER_RTL2832_FC2580:
fe = dvb_attach(fc2580_attach, adap->fe[0], &d->i2c_adap,
@@ -969,12 +977,11 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
adap->fe[0]->ops.tuner_ops.get_rf_strength;
break;
default:
- fe = NULL;
dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME,
priv->tuner);
}
- if (fe == NULL) {
+ if (fe == NULL && priv->client == NULL) {
ret = -ENODEV;
goto err;
}
@@ -1019,6 +1026,17 @@ err:
return ret;
}
+static void rtl28xxu_exit(struct dvb_usb_device *d)
+{
+ struct rtl28xxu_priv *priv = d->priv;
+
+ dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+ i2c_release_client(priv->client);
+
+ return;
+}
+
static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff)
{
int ret;
@@ -1381,6 +1399,7 @@ static const struct dvb_usb_device_properties rtl2832u_props = {
.frontend_attach = rtl2832u_frontend_attach,
.tuner_attach = rtl2832u_tuner_attach,
.init = rtl28xxu_init,
+ .exit = rtl28xxu_exit,
.get_rc_config = rtl2832u_get_rc_config,
.num_adapters = 1,
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
index 2142bcb..367aca1 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
@@ -56,6 +56,7 @@ struct rtl28xxu_priv {
char *tuner_name;
u8 page; /* integrated demod active register page */
bool rc_active;
+ struct i2c_client *client;
};
enum rtl28xxu_chip_id {
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 40/86] e4000: add manual gain controls
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (38 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 39/86] e4000: convert DVB tuner to I2C driver model Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 41/86] rtl2832_sdr: expose E4000 gain controls to user space Antti Palosaari
` (47 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Add gain control for LNA, Mixer and IF. Expose controls via DVB
frontend .set_config callback.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/tuners/e4000.c | 68 +++++++++++++++++++++++++++++++++++++++
drivers/media/tuners/e4000.h | 6 ++++
drivers/media/tuners/e4000_priv.h | 63 ++++++++++++++++++++++++++++++++++++
3 files changed, 137 insertions(+)
diff --git a/drivers/media/tuners/e4000.c b/drivers/media/tuners/e4000.c
index 0153169..651de11 100644
--- a/drivers/media/tuners/e4000.c
+++ b/drivers/media/tuners/e4000.c
@@ -385,6 +385,73 @@ static int e4000_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
return 0;
}
+static int e4000_set_config(struct dvb_frontend *fe, void *priv_cfg)
+{
+ struct e4000_priv *priv = fe->tuner_priv;
+ struct e4000_ctrl *ctrl = priv_cfg;
+ int ret;
+ u8 buf[2];
+ u8 u8tmp;
+ dev_dbg(&priv->client->dev, "%s: lna=%d mixer=%d if=%d\n", __func__,
+ ctrl->lna_gain, ctrl->mixer_gain, ctrl->if_gain);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ if (ctrl->lna_gain == INT_MIN && ctrl->if_gain == INT_MIN)
+ u8tmp = 0x17;
+ else if (ctrl->lna_gain == INT_MIN)
+ u8tmp = 0x19;
+ else if (ctrl->if_gain == INT_MIN)
+ u8tmp = 0x16;
+ else
+ u8tmp = 0x10;
+
+ ret = e4000_wr_reg(priv, 0x1a, u8tmp);
+ if (ret)
+ goto err;
+
+ if (ctrl->mixer_gain == INT_MIN)
+ u8tmp = 0x15;
+ else
+ u8tmp = 0x14;
+
+ ret = e4000_wr_reg(priv, 0x20, u8tmp);
+ if (ret)
+ goto err;
+
+ if (ctrl->lna_gain != INT_MIN) {
+ ret = e4000_wr_reg(priv, 0x14, ctrl->lna_gain);
+ if (ret)
+ goto err;
+ }
+
+ if (ctrl->mixer_gain != INT_MIN) {
+ ret = e4000_wr_reg(priv, 0x15, ctrl->mixer_gain);
+ if (ret)
+ goto err;
+ }
+
+ if (ctrl->if_gain != INT_MIN) {
+ buf[0] = e4000_if_gain_lut[ctrl->if_gain].reg16_val;
+ buf[1] = e4000_if_gain_lut[ctrl->if_gain].reg17_val;
+ ret = e4000_wr_regs(priv, 0x16, buf, 2);
+ if (ret)
+ goto err;
+ }
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ return 0;
+err:
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
+ return ret;
+}
+
static const struct dvb_tuner_ops e4000_tuner_ops = {
.info = {
.name = "Elonics E4000",
@@ -395,6 +462,7 @@ static const struct dvb_tuner_ops e4000_tuner_ops = {
.init = e4000_init,
.sleep = e4000_sleep,
.set_params = e4000_set_params,
+ .set_config = e4000_set_config,
.get_if_frequency = e4000_get_if_frequency,
};
diff --git a/drivers/media/tuners/e4000.h b/drivers/media/tuners/e4000.h
index e74b8b2..d95c472 100644
--- a/drivers/media/tuners/e4000.h
+++ b/drivers/media/tuners/e4000.h
@@ -40,4 +40,10 @@ struct e4000_config {
u32 clock;
};
+struct e4000_ctrl {
+ int lna_gain;
+ int mixer_gain;
+ int if_gain;
+};
+
#endif
diff --git a/drivers/media/tuners/e4000_priv.h b/drivers/media/tuners/e4000_priv.h
index 8f45a30..a75a383 100644
--- a/drivers/media/tuners/e4000_priv.h
+++ b/drivers/media/tuners/e4000_priv.h
@@ -145,4 +145,67 @@ static const struct e4000_if_filter e4000_if_filter_lut[] = {
{ 0xffffffff, 0x00, 0x20 },
};
+struct e4000_if_gain {
+ u8 reg16_val;
+ u8 reg17_val;
+};
+
+static const struct e4000_if_gain e4000_if_gain_lut[] = {
+ {0x00, 0x00},
+ {0x20, 0x00},
+ {0x40, 0x00},
+ {0x02, 0x00},
+ {0x22, 0x00},
+ {0x42, 0x00},
+ {0x04, 0x00},
+ {0x24, 0x00},
+ {0x44, 0x00},
+ {0x01, 0x00},
+ {0x21, 0x00},
+ {0x41, 0x00},
+ {0x03, 0x00},
+ {0x23, 0x00},
+ {0x43, 0x00},
+ {0x05, 0x00},
+ {0x25, 0x00},
+ {0x45, 0x00},
+ {0x07, 0x00},
+ {0x27, 0x00},
+ {0x47, 0x00},
+ {0x0f, 0x00},
+ {0x2f, 0x00},
+ {0x4f, 0x00},
+ {0x17, 0x00},
+ {0x37, 0x00},
+ {0x57, 0x00},
+ {0x1f, 0x00},
+ {0x3f, 0x00},
+ {0x5f, 0x00},
+ {0x1f, 0x01},
+ {0x3f, 0x01},
+ {0x5f, 0x01},
+ {0x1f, 0x02},
+ {0x3f, 0x02},
+ {0x5f, 0x02},
+ {0x1f, 0x03},
+ {0x3f, 0x03},
+ {0x5f, 0x03},
+ {0x1f, 0x04},
+ {0x3f, 0x04},
+ {0x5f, 0x04},
+ {0x1f, 0x0c},
+ {0x3f, 0x0c},
+ {0x5f, 0x0c},
+ {0x1f, 0x14},
+ {0x3f, 0x14},
+ {0x5f, 0x14},
+ {0x1f, 0x1c},
+ {0x3f, 0x1c},
+ {0x5f, 0x1c},
+ {0x1f, 0x24},
+ {0x3f, 0x24},
+ {0x5f, 0x24},
+ {0x7f, 0x24},
+};
+
#endif
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 41/86] rtl2832_sdr: expose E4000 gain controls to user space
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (39 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 40/86] e4000: add manual gain controls Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 42/86] r820t: add manual gain controls Antti Palosaari
` (46 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Provide E4000 gain controls to userspace via V4L2 API. LNA, Mixer
and IF gain controls are offered, each one both manual and automode.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/rtl2832u_sdr/Makefile | 1 +
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 115 +++++++++++++++++------
2 files changed, 88 insertions(+), 28 deletions(-)
diff --git a/drivers/staging/media/rtl2832u_sdr/Makefile b/drivers/staging/media/rtl2832u_sdr/Makefile
index 1009276..7e00a0d 100644
--- a/drivers/staging/media/rtl2832u_sdr/Makefile
+++ b/drivers/staging/media/rtl2832u_sdr/Makefile
@@ -2,4 +2,5 @@ obj-$(CONFIG_DVB_RTL2832_SDR) += rtl2832_sdr.o
ccflags-y += -Idrivers/media/dvb-core
ccflags-y += -Idrivers/media/dvb-frontends
+ccflags-y += -Idrivers/media/tuners
ccflags-y += -Idrivers/media/usb/dvb-usb-v2
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index fccb16f..ee72233 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -25,6 +25,7 @@
#include "dvb_frontend.h"
#include "rtl2832_sdr.h"
#include "dvb_usb.h"
+#include "e4000.h"
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
@@ -147,9 +148,14 @@ struct rtl2832_sdr_state {
u32 pixelformat;
/* Controls */
- struct v4l2_ctrl_handler ctrl_handler;
+ 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_auto;
+ struct v4l2_ctrl *if_gain;
struct v4l2_ctrl *ctrl_tuner_bw;
- struct v4l2_ctrl *ctrl_tuner_gain;
/* for sample rate calc */
unsigned int sample;
@@ -917,10 +923,49 @@ err:
return;
};
+static int rtl2832_sdr_set_gain_e4000(struct rtl2832_sdr_state *s)
+{
+ int ret;
+ struct dvb_frontend *fe = s->fe;
+ struct e4000_ctrl ctrl;
+ dev_dbg(&s->udev->dev, "%s: lna=%d mixer=%d if=%d\n", __func__,
+ s->lna_gain->val, s->mixer_gain->val, s->if_gain->val);
+
+ ctrl.lna_gain = s->lna_gain_auto->val ? INT_MIN : s->lna_gain->val;
+ ctrl.mixer_gain = s->mixer_gain_auto->val ? INT_MIN : s->mixer_gain->val;
+ ctrl.if_gain = s->if_gain_auto->val ? INT_MIN : s->if_gain->val;
+
+ if (fe->ops.tuner_ops.set_config) {
+ ret = fe->ops.tuner_ops.set_config(fe, &ctrl);
+ if (ret)
+ goto err;
+ }
+
+ return 0;
+err:
+ dev_dbg(&s->udev->dev, "%s: failed %d\n", __func__, ret);
+ return ret;
+};
+
+static int rtl2832_sdr_set_gain(struct rtl2832_sdr_state *s)
+{
+ int ret;
+
+ switch (s->cfg->tuner) {
+ case RTL2832_TUNER_E4000:
+ ret = rtl2832_sdr_set_gain_e4000(s);
+ break;
+ default:
+ ret = 0;
+ }
+ return ret;
+}
+
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;
+ int ret;
/*
* tuner RF (Hz)
@@ -932,14 +977,9 @@ static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s)
*/
unsigned int bandwidth = s->ctrl_tuner_bw->val;
- /*
- * gain (dB)
- */
- int gain = s->ctrl_tuner_gain->val;
-
dev_dbg(&s->udev->dev,
- "%s: f_rf=%u bandwidth=%d gain=%d\n",
- __func__, f_rf, bandwidth, gain);
+ "%s: f_rf=%u bandwidth=%d\n",
+ __func__, f_rf, bandwidth);
if (f_rf == 0)
return 0;
@@ -961,6 +1001,8 @@ static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s)
if (fe->ops.tuner_ops.set_params)
fe->ops.tuner_ops.set_params(fe);
+ ret = rtl2832_sdr_set_gain(s);
+
return 0;
};
@@ -1290,7 +1332,7 @@ static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct rtl2832_sdr_state *s =
container_of(ctrl->handler, struct rtl2832_sdr_state,
- ctrl_handler);
+ hdl);
int ret;
dev_dbg(&s->udev->dev,
"%s: id=%d name=%s val=%d min=%d max=%d step=%d\n",
@@ -1302,6 +1344,15 @@ static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl)
case RTL2832_SDR_CID_TUNER_GAIN:
ret = rtl2832_sdr_set_tuner(s);
break;
+ case V4L2_CID_LNA_GAIN_AUTO:
+ case V4L2_CID_LNA_GAIN:
+ case V4L2_CID_MIXER_GAIN_AUTO:
+ case V4L2_CID_MIXER_GAIN:
+ case V4L2_CID_IF_GAIN_AUTO:
+ case V4L2_CID_IF_GAIN:
+ dev_dbg(&s->udev->dev, "%s: GAIN IOCTL\n", __func__);
+ ret = rtl2832_sdr_set_gain(s);
+ break;
default:
ret = -EINVAL;
}
@@ -1318,7 +1369,7 @@ static void rtl2832_sdr_video_release(struct v4l2_device *v)
struct rtl2832_sdr_state *s =
container_of(v, struct rtl2832_sdr_state, v4l2_dev);
- v4l2_ctrl_handler_free(&s->ctrl_handler);
+ v4l2_ctrl_handler_free(&s->hdl);
v4l2_device_unregister(&s->v4l2_dev);
kfree(s);
}
@@ -1328,6 +1379,7 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
{
int ret;
struct rtl2832_sdr_state *s;
+ const struct v4l2_ctrl_ops *ops = &rtl2832_sdr_ctrl_ops;
struct dvb_usb_device *d = i2c_get_adapdata(i2c);
static const struct v4l2_ctrl_config ctrl_tuner_bw = {
.ops = &rtl2832_sdr_ctrl_ops,
@@ -1339,16 +1391,6 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
.def = 0,
.step = 1,
};
- static const struct v4l2_ctrl_config ctrl_tuner_gain = {
- .ops = &rtl2832_sdr_ctrl_ops,
- .id = RTL2832_SDR_CID_TUNER_GAIN,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Tuner Gain",
- .min = 0,
- .max = 102,
- .def = 0,
- .step = 1,
- };
s = kzalloc(sizeof(struct rtl2832_sdr_state), GFP_KERNEL);
if (s == NULL) {
@@ -1386,11 +1428,28 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
}
/* Register controls */
- 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_gain = v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_tuner_gain, NULL);
- if (s->ctrl_handler.error) {
- ret = s->ctrl_handler.error;
+ switch (s->cfg->tuner) {
+ case RTL2832_TUNER_E4000:
+ v4l2_ctrl_handler_init(&s->hdl, 7);
+ s->ctrl_tuner_bw = v4l2_ctrl_new_custom(&s->hdl, &ctrl_tuner_bw, NULL);
+ s->lna_gain_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_LNA_GAIN_AUTO, 0, 1, 1, 1);
+ s->lna_gain = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_LNA_GAIN, 0, 15, 1, 10);
+ v4l2_ctrl_auto_cluster(2, &s->lna_gain_auto, 0, false);
+ s->mixer_gain_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_MIXER_GAIN_AUTO, 0, 1, 1, 1);
+ s->mixer_gain = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_MIXER_GAIN, 0, 1, 1, 1);
+ v4l2_ctrl_auto_cluster(2, &s->mixer_gain_auto, 0, false);
+ s->if_gain_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_IF_GAIN_AUTO, 0, 1, 1, 1);
+ s->if_gain = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_IF_GAIN, 0, 54, 1, 0);
+ v4l2_ctrl_auto_cluster(2, &s->if_gain_auto, 0, false);
+ break;
+ default:
+ v4l2_ctrl_handler_init(&s->hdl, 1);
+ s->ctrl_tuner_bw = v4l2_ctrl_new_custom(&s->hdl, &ctrl_tuner_bw, NULL);
+ break;
+ }
+
+ if (s->hdl.error) {
+ ret = s->hdl.error;
dev_err(&s->udev->dev, "Could not initialize controls\n");
goto err_free_controls;
}
@@ -1411,7 +1470,7 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
goto err_free_controls;
}
- s->v4l2_dev.ctrl_handler = &s->ctrl_handler;
+ s->v4l2_dev.ctrl_handler = &s->hdl;
s->vdev.v4l2_dev = &s->v4l2_dev;
s->vdev.lock = &s->v4l2_lock;
s->vdev.vfl_dir = VFL_DIR_RX;
@@ -1436,7 +1495,7 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
err_unregister_v4l2_dev:
v4l2_device_unregister(&s->v4l2_dev);
err_free_controls:
- v4l2_ctrl_handler_free(&s->ctrl_handler);
+ v4l2_ctrl_handler_free(&s->hdl);
err_free_mem:
kfree(s);
return NULL;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 42/86] r820t: add manual gain controls
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (40 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 41/86] rtl2832_sdr: expose E4000 gain controls to user space Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 43/86] rtl2832_sdr: expose R820 gain controls to user space Antti Palosaari
` (45 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari, Mauro Carvalho Chehab
Add gain control for LNA, Mixer and IF. Expose controls via DVB
frontend .set_config callback.
Cc: Mauro Carvalho Chehab <m.chehab@samsung.com>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/tuners/r820t.c | 38 ++++++++++++++++++++++++++++++++++++++
drivers/media/tuners/r820t.h | 7 +++++++
2 files changed, 45 insertions(+)
diff --git a/drivers/media/tuners/r820t.c b/drivers/media/tuners/r820t.c
index 319adc4..231c614 100644
--- a/drivers/media/tuners/r820t.c
+++ b/drivers/media/tuners/r820t.c
@@ -1251,6 +1251,43 @@ static int r820t_set_gain_mode(struct r820t_priv *priv,
}
#endif
+static int r820t_set_config(struct dvb_frontend *fe, void *priv_cfg)
+{
+ struct r820t_priv *priv = fe->tuner_priv;
+ struct r820t_ctrl *ctrl = priv_cfg;
+ int rc;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ if (ctrl->lna_gain == INT_MIN)
+ rc = r820t_write_reg_mask(priv, 0x05, 0x00, 0x10);
+ else
+ rc = r820t_write_reg_mask(priv, 0x05,
+ 0x10 | ctrl->lna_gain, 0x1f);
+ if (rc < 0)
+ goto err;
+
+ if (ctrl->mixer_gain == INT_MIN)
+ rc = r820t_write_reg_mask(priv, 0x07, 0x10, 0x10);
+ else
+ rc = r820t_write_reg_mask(priv, 0x07,
+ 0x00 | ctrl->mixer_gain, 0x1f);
+ if (rc < 0)
+ goto err;
+
+ if (ctrl->if_gain == INT_MIN)
+ rc = r820t_write_reg_mask(priv, 0x0c, 0x10, 0x10);
+ else
+ rc = r820t_write_reg_mask(priv, 0x0c,
+ 0x00 | ctrl->if_gain, 0x1f);
+err:
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ return rc;
+}
+
static int generic_set_freq(struct dvb_frontend *fe,
u32 freq /* in HZ */,
unsigned bw,
@@ -2275,6 +2312,7 @@ static const struct dvb_tuner_ops r820t_tuner_ops = {
.release = r820t_release,
.sleep = r820t_sleep,
.set_params = r820t_set_params,
+ .set_config = r820t_set_config,
.set_analog_params = r820t_set_analog_freq,
.get_if_frequency = r820t_get_if_frequency,
.get_rf_strength = r820t_signal,
diff --git a/drivers/media/tuners/r820t.h b/drivers/media/tuners/r820t.h
index 48af354..42c0d8e 100644
--- a/drivers/media/tuners/r820t.h
+++ b/drivers/media/tuners/r820t.h
@@ -42,6 +42,13 @@ struct r820t_config {
bool use_predetect;
};
+/* set INT_MIN for automode */
+struct r820t_ctrl {
+ int lna_gain;
+ int mixer_gain;
+ int if_gain;
+};
+
#if IS_ENABLED(CONFIG_MEDIA_TUNER_R820T)
struct dvb_frontend *r820t_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 43/86] rtl2832_sdr: expose R820 gain controls to user space
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (41 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 42/86] r820t: add manual gain controls Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 44/86] e4000: fix PLL calc to allow higher frequencies Antti Palosaari
` (44 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Provide R820 gain controls to userspace via V4L2 API. LNA, Mixer
and IF gain controls are offered, each one both manual and automode.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 41 ++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index ee72233..69fc996 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -26,6 +26,7 @@
#include "rtl2832_sdr.h"
#include "dvb_usb.h"
#include "e4000.h"
+#include "r820t.h"
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
@@ -947,6 +948,30 @@ err:
return ret;
};
+static int rtl2832_sdr_set_gain_r820t(struct rtl2832_sdr_state *s)
+{
+ int ret;
+ struct dvb_frontend *fe = s->fe;
+ struct r820t_ctrl ctrl;
+ dev_dbg(&s->udev->dev, "%s: lna=%d mixer=%d if=%d\n", __func__,
+ s->lna_gain->val, s->mixer_gain->val, s->if_gain->val);
+
+ ctrl.lna_gain = s->lna_gain_auto->val ? INT_MIN : s->lna_gain->val;
+ ctrl.mixer_gain = s->mixer_gain_auto->val ? INT_MIN : s->mixer_gain->val;
+ ctrl.if_gain = s->if_gain_auto->val ? INT_MIN : s->if_gain->val;
+
+ if (fe->ops.tuner_ops.set_config) {
+ ret = fe->ops.tuner_ops.set_config(fe, &ctrl);
+ if (ret)
+ goto err;
+ }
+
+ return 0;
+err:
+ dev_dbg(&s->udev->dev, "%s: failed %d\n", __func__, ret);
+ return ret;
+};
+
static int rtl2832_sdr_set_gain(struct rtl2832_sdr_state *s)
{
int ret;
@@ -955,6 +980,9 @@ static int rtl2832_sdr_set_gain(struct rtl2832_sdr_state *s)
case RTL2832_TUNER_E4000:
ret = rtl2832_sdr_set_gain_e4000(s);
break;
+ case RTL2832_TUNER_R820T:
+ ret = rtl2832_sdr_set_gain_r820t(s);
+ break;
default:
ret = 0;
}
@@ -1442,6 +1470,19 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
s->if_gain = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_IF_GAIN, 0, 54, 1, 0);
v4l2_ctrl_auto_cluster(2, &s->if_gain_auto, 0, false);
break;
+ case RTL2832_TUNER_R820T:
+ v4l2_ctrl_handler_init(&s->hdl, 7);
+ s->lna_gain_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_LNA_GAIN_AUTO, 0, 1, 1, 1);
+ s->lna_gain = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_LNA_GAIN, 0, 15, 1, 6);
+ v4l2_ctrl_auto_cluster(2, &s->lna_gain_auto, 0, false);
+ s->mixer_gain_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_MIXER_GAIN_AUTO, 0, 1, 1, 1);
+ s->mixer_gain = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_MIXER_GAIN, 0, 15, 1, 5);
+ v4l2_ctrl_auto_cluster(2, &s->mixer_gain_auto, 0, false);
+ s->if_gain_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_IF_GAIN_AUTO, 0, 1, 1, 1);
+ s->if_gain = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_IF_GAIN, 0, 15, 1, 4);
+ v4l2_ctrl_auto_cluster(2, &s->if_gain_auto, 0, false);
+ s->ctrl_tuner_bw = v4l2_ctrl_new_custom(&s->hdl, &ctrl_tuner_bw, NULL);
+ break;
default:
v4l2_ctrl_handler_init(&s->hdl, 1);
s->ctrl_tuner_bw = v4l2_ctrl_new_custom(&s->hdl, &ctrl_tuner_bw, NULL);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 44/86] e4000: fix PLL calc to allow higher frequencies
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (42 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 43/86] rtl2832_sdr: expose R820 gain controls to user space Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 45/86] msi3101: fix device caps to advertise SDR receiver Antti Palosaari
` (43 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
There was 32-bit overflow on VCO frequency calculation which blocks
tuning to 1073 - 1104 MHz. Use 64 bit number in order to avoid VCO
frequency overflow.
After that fix device in question tunes to following range:
60 - 1104 MHz
1250 - 2207 MHz
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/tuners/e4000.c | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)
diff --git a/drivers/media/tuners/e4000.c b/drivers/media/tuners/e4000.c
index 651de11..9187190 100644
--- a/drivers/media/tuners/e4000.c
+++ b/drivers/media/tuners/e4000.c
@@ -221,11 +221,11 @@ static int e4000_set_params(struct dvb_frontend *fe)
struct e4000_priv *priv = fe->tuner_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret, i, sigma_delta;
- unsigned int f_vco;
+ u64 f_vco;
u8 buf[5], i_data[4], q_data[4];
dev_dbg(&priv->client->dev,
- "%s: delivery_system=%d frequency=%d bandwidth_hz=%d\n",
+ "%s: delivery_system=%d frequency=%u bandwidth_hz=%u\n",
__func__, c->delivery_system, c->frequency,
c->bandwidth_hz);
@@ -248,20 +248,16 @@ static int e4000_set_params(struct dvb_frontend *fe)
goto err;
}
- /*
- * Note: Currently f_vco overflows when c->frequency is 1 073 741 824 Hz
- * or more.
- */
- f_vco = c->frequency * e4000_pll_lut[i].mul;
+ f_vco = 1ull * c->frequency * e4000_pll_lut[i].mul;
sigma_delta = div_u64(0x10000ULL * (f_vco % priv->clock), priv->clock);
- buf[0] = f_vco / priv->clock;
+ buf[0] = div_u64(f_vco, priv->clock);
buf[1] = (sigma_delta >> 0) & 0xff;
buf[2] = (sigma_delta >> 8) & 0xff;
buf[3] = 0x00;
buf[4] = e4000_pll_lut[i].div;
dev_dbg(&priv->client->dev,
- "%s: f_vco=%u pll div=%d sigma_delta=%04x\n",
+ "%s: f_vco=%llu pll div=%d sigma_delta=%04x\n",
__func__, f_vco, buf[0], sigma_delta);
ret = e4000_wr_regs(priv, 0x09, buf, 5);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 45/86] msi3101: fix device caps to advertise SDR receiver
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (43 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 44/86] e4000: fix PLL calc to allow higher frequencies Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 46/86] rtl2832_sdr: " Antti Palosaari
` (42 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Advertise device as a SDR receiver, not video. After that libv4l
accepts opening device.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/msi3101/sdr-msi3101.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index e8dfcac..0a2bb12 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -843,7 +843,7 @@ static int msi3101_querycap(struct file *file, void *fh,
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_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
+ 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;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 46/86] rtl2832_sdr: fix device caps to advertise SDR receiver
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (44 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 45/86] msi3101: fix device caps to advertise SDR receiver Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 47/86] msi3101: add default FMT and ADC frequency Antti Palosaari
` (41 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Advertise device as a SDR receiver, not video. After that libv4l
accepts opening device.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index 69fc996..15c562e3 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -609,7 +609,7 @@ static int rtl2832_sdr_querycap(struct file *file, void *fh,
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_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
+ 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;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 47/86] msi3101: add default FMT and ADC frequency
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (45 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 46/86] rtl2832_sdr: " Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 48/86] msi3101: sleep USB ADC and tuner when streaming is stopped Antti Palosaari
` (40 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Default ADC to smallest/worst possible configuration on probe.
Also enhance some FMT debug logs.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/msi3101/sdr-msi3101.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index 0a2bb12..061c705 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -1339,7 +1339,7 @@ static int msi3101_enum_fmt_sdr_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
struct msi3101_state *s = video_drvdata(file);
- dev_dbg(&s->udev->dev, "%s:\n", __func__);
+ dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, f->index);
if (f->index >= NUM_FORMATS)
return -EINVAL;
@@ -1354,7 +1354,8 @@ 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__);
+ dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
+ (char *)&s->pixelformat);
f->fmt.sdr.pixelformat = s->pixelformat;
@@ -1631,8 +1632,9 @@ static int msi3101_probe(struct usb_interface *intf,
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_adc[0].rangelow;
+ s->pixelformat = V4L2_PIX_FMT_SDR_U8;
/* Init videobuf2 queue structure */
s->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 48/86] msi3101: sleep USB ADC and tuner when streaming is stopped
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (46 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 47/86] msi3101: add default FMT and ADC frequency Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 49/86] DocBook: document RF tuner gain controls Antti Palosaari
` (39 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Put USB IF / ADC and RF tuner to sleep when device is not streaming.
It uses around 115 mA power from USB when active, which drops to
32 mA on idle after that patch.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/msi3101/sdr-msi3101.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index 061c705..0606941 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -977,8 +977,8 @@ static int msi3101_set_usb_adc(struct msi3101_state *s)
* Synthesizer config is just a educated guess...
*
* [7:0] 0x03, register address
- * [8] 1, always
- * [9] ?
+ * [8] 1, power control
+ * [9] ?, power control
* [12:10] output divider
* [13] 0 ?
* [14] 0 ?
@@ -1321,6 +1321,12 @@ static int msi3101_stop_streaming(struct vb2_queue *vq)
msleep(20);
msi3101_ctrl_msg(s, CMD_STOP_STREAMING, 0);
+ /* sleep USB IF / ADC */
+ msi3101_ctrl_msg(s, CMD_WREG, 0x01000003);
+
+ /* sleep tuner */
+ msi3101_tuner_write(s, 0x000000);
+
mutex_unlock(&s->v4l2_lock);
return 0;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 49/86] DocBook: document RF tuner gain controls
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (47 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 48/86] msi3101: sleep USB ADC and tuner when streaming is stopped Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 50/86] DocBook: V4L: add V4L2_SDR_FMT_CU8 - 'CU08' Antti Palosaari
` (38 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari, Hans Verkuil
Add documentation for LNA, mixer and IF gain controls. These
controls are RF tuner specific.
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
---
Documentation/DocBook/media/v4l/controls.xml | 91 ++++++++++++++++++++++++++++
1 file changed, 91 insertions(+)
diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index a5a3188..0145341 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -4971,4 +4971,95 @@ defines possible values for de-emphasis. Here they are:</entry>
</table>
</section>
+
+ <section id="rf-tuner-controls">
+ <title>RF Tuner Control Reference</title>
+
+ <para>The RF Tuner (RF_TUNER) class includes controls for common features
+of devices having RF tuner.</para>
+
+ <table pgwide="1" frame="none" id="rf-tuner-control-id">
+ <title>RF_TUNER Control IDs</title>
+
+ <tgroup cols="4">
+ <colspec colname="c1" colwidth="1*" />
+ <colspec colname="c2" colwidth="6*" />
+ <colspec colname="c3" colwidth="2*" />
+ <colspec colname="c4" colwidth="6*" />
+ <spanspec namest="c1" nameend="c2" spanname="id" />
+ <spanspec namest="c2" nameend="c4" spanname="descr" />
+ <thead>
+ <row>
+ <entry spanname="id" align="left">ID</entry>
+ <entry align="left">Type</entry>
+ </row>
+ <row rowsep="1">
+ <entry spanname="descr" align="left">Description</entry>
+ </row>
+ </thead>
+ <tbody valign="top">
+ <row><entry></entry></row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_RF_TUNER_CLASS</constant> </entry>
+ <entry>class</entry>
+ </row><row><entry spanname="descr">The RF_TUNER class
+descriptor. Calling &VIDIOC-QUERYCTRL; for this control will return a
+description of this control class.</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_LNA_GAIN_AUTO</constant> </entry>
+ <entry>boolean</entry>
+ </row>
+ <row>
+ <entry spanname="descr">Enables/disables LNA automatic gain control (AGC)</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_MIXER_GAIN_AUTO</constant> </entry>
+ <entry>boolean</entry>
+ </row>
+ <row>
+ <entry spanname="descr">Enables/disables mixer automatic gain control (AGC)</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_IF_GAIN_AUTO</constant> </entry>
+ <entry>boolean</entry>
+ </row>
+ <row>
+ <entry spanname="descr">Enables/disables IF automatic gain control (AGC)</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_LNA_GAIN</constant> </entry>
+ <entry>integer</entry>
+ </row>
+ <row>
+ <entry spanname="descr">LNA (low noise amplifier) gain is first
+gain stage on the RF tuner signal path. It is located very close to tuner
+antenna input. Used when <constant>V4L2_CID_LNA_GAIN_AUTO</constant> is not set.
+The range and step are driver-specific.</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_MIXER_GAIN</constant> </entry>
+ <entry>integer</entry>
+ </row>
+ <row>
+ <entry spanname="descr">Mixer gain is second gain stage on the RF
+tuner signal path. It is located inside mixer block, where RF signal is
+down-converted by the mixer. Used when <constant>V4L2_CID_MIXER_GAIN_AUTO</constant>
+is not set. The range and step are driver-specific.</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_IF_GAIN</constant> </entry>
+ <entry>integer</entry>
+ </row>
+ <row>
+ <entry spanname="descr">IF gain is last gain stage on the RF tuner
+signal path. It is located on output of RF tuner. It controls signal level of
+intermediate frequency output or baseband output. Used when
+<constant>V4L2_CID_IF_GAIN_AUTO</constant> is not set. The range and step are
+driver-specific.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
</section>
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 50/86] DocBook: V4L: add V4L2_SDR_FMT_CU8 - 'CU08'
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (48 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 49/86] DocBook: document RF tuner gain controls Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 51/86] DocBook: V4L: add V4L2_SDR_FMT_CU16LE - 'CU16' Antti Palosaari
` (37 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari, Hans Verkuil
Document V4L2_SDR_FMT_CU8 SDR format.
It is complex unsigned 8-bit IQ sample. Used by software defined
radio devices.
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
---
.../DocBook/media/v4l/pixfmt-sdr-cu08.xml | 44 ++++++++++++++++++++++
Documentation/DocBook/media/v4l/pixfmt.xml | 2 +
2 files changed, 46 insertions(+)
create mode 100644 Documentation/DocBook/media/v4l/pixfmt-sdr-cu08.xml
diff --git a/Documentation/DocBook/media/v4l/pixfmt-sdr-cu08.xml b/Documentation/DocBook/media/v4l/pixfmt-sdr-cu08.xml
new file mode 100644
index 0000000..2d80104
--- /dev/null
+++ b/Documentation/DocBook/media/v4l/pixfmt-sdr-cu08.xml
@@ -0,0 +1,44 @@
+<refentry id="V4L2-SDR-FMT-CU08">
+ <refmeta>
+ <refentrytitle>V4L2_SDR_FMT_CU8 ('CU08')</refentrytitle>
+ &manvol;
+ </refmeta>
+ <refnamediv>
+ <refname>
+ <constant>V4L2_SDR_FMT_CU8</constant>
+ </refname>
+ <refpurpose>Complex unsigned 8-bit IQ sample</refpurpose>
+ </refnamediv>
+ <refsect1>
+ <title>Description</title>
+ <para>
+This format contains sequence of complex number samples. Each complex number
+consist two parts, called In-phase and Quadrature (IQ). Both I and Q are
+represented as a 8 bit unsigned number. I value comes first and Q value after
+that.
+ </para>
+ <example>
+ <title><constant>V4L2_SDR_FMT_CU8</constant> 1 sample</title>
+ <formalpara>
+ <title>Byte Order.</title>
+ <para>Each cell is one byte.
+ <informaltable frame="none">
+ <tgroup cols="2" align="center">
+ <colspec align="left" colwidth="2*" />
+ <tbody valign="top">
+ <row>
+ <entry>start + 0:</entry>
+ <entry>I'<subscript>0</subscript></entry>
+ </row>
+ <row>
+ <entry>start + 1:</entry>
+ <entry>Q'<subscript>0</subscript></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ </formalpara>
+ </example>
+ </refsect1>
+</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml b/Documentation/DocBook/media/v4l/pixfmt.xml
index f586d34..40adcb8 100644
--- a/Documentation/DocBook/media/v4l/pixfmt.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt.xml
@@ -817,6 +817,8 @@ extended control <constant>V4L2_CID_MPEG_STREAM_TYPE</constant>, see
<para>These formats are used for <link linkend="sdr">SDR Capture</link>
interface only.</para>
+ &sub-sdr-cu08;
+
</section>
<section id="pixfmt-reserved">
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 51/86] DocBook: V4L: add V4L2_SDR_FMT_CU16LE - 'CU16'
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (49 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 50/86] DocBook: V4L: add V4L2_SDR_FMT_CU8 - 'CU08' Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 52/86] DocBook: media: document V4L2_CTRL_CLASS_RF_TUNER Antti Palosaari
` (36 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari, Hans Verkuil
Document V4L2_SDR_FMT_CU16LE format.
It is complex unsigned 16-bit little endian IQ sample. Used by
software defined radio devices.
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
---
.../DocBook/media/v4l/pixfmt-sdr-cu16le.xml | 46 ++++++++++++++++++++++
Documentation/DocBook/media/v4l/pixfmt.xml | 1 +
2 files changed, 47 insertions(+)
create mode 100644 Documentation/DocBook/media/v4l/pixfmt-sdr-cu16le.xml
diff --git a/Documentation/DocBook/media/v4l/pixfmt-sdr-cu16le.xml b/Documentation/DocBook/media/v4l/pixfmt-sdr-cu16le.xml
new file mode 100644
index 0000000..26288ff
--- /dev/null
+++ b/Documentation/DocBook/media/v4l/pixfmt-sdr-cu16le.xml
@@ -0,0 +1,46 @@
+<refentry id="V4L2-SDR-FMT-CU16LE">
+ <refmeta>
+ <refentrytitle>V4L2_SDR_FMT_CU16LE ('CU16')</refentrytitle>
+ &manvol;
+ </refmeta>
+ <refnamediv>
+ <refname>
+ <constant>V4L2_SDR_FMT_CU16LE</constant>
+ </refname>
+ <refpurpose>Complex unsigned 16-bit little endian IQ sample</refpurpose>
+ </refnamediv>
+ <refsect1>
+ <title>Description</title>
+ <para>
+This format contains sequence of complex number samples. Each complex number
+consist two parts, called In-phase and Quadrature (IQ). Both I and Q are
+represented as a 16 bit unsigned little endian number. I value comes first
+and Q value after that.
+ </para>
+ <example>
+ <title><constant>V4L2_SDR_FMT_CU16LE</constant> 1 sample</title>
+ <formalpara>
+ <title>Byte Order.</title>
+ <para>Each cell is one byte.
+ <informaltable frame="none">
+ <tgroup cols="3" align="center">
+ <colspec align="left" colwidth="2*" />
+ <tbody valign="top">
+ <row>
+ <entry>start + 0:</entry>
+ <entry>I'<subscript>0[7:0]</subscript></entry>
+ <entry>I'<subscript>0[15:8]</subscript></entry>
+ </row>
+ <row>
+ <entry>start + 2:</entry>
+ <entry>Q'<subscript>0[7:0]</subscript></entry>
+ <entry>Q'<subscript>0[15:8]</subscript></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ </formalpara>
+ </example>
+ </refsect1>
+</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml b/Documentation/DocBook/media/v4l/pixfmt.xml
index 40adcb8..f535d9b 100644
--- a/Documentation/DocBook/media/v4l/pixfmt.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt.xml
@@ -818,6 +818,7 @@ extended control <constant>V4L2_CID_MPEG_STREAM_TYPE</constant>, see
interface only.</para>
&sub-sdr-cu08;
+ &sub-sdr-cu16le;
</section>
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 52/86] DocBook: media: document V4L2_CTRL_CLASS_RF_TUNER
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (50 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 51/86] DocBook: V4L: add V4L2_SDR_FMT_CU16LE - 'CU16' Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 53/86] xc2028: silence compiler warnings Antti Palosaari
` (35 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari, Hans Verkuil
It is class for RF tuner specific controls, like gain controls,
filters, signal strength.
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
index b3bb957..e9f6735 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
@@ -327,7 +327,12 @@ These controls are described in <xref
These controls are described in <xref
linkend="fm-rx-controls" />.</entry>
</row>
-
+ <row>
+ <entry><constant>V4L2_CTRL_CLASS_RF_TUNER</constant></entry>
+ <entry>0xa20000</entry>
+ <entry>The class containing RF tuner controls.
+These controls are described in <xref linkend="rf-tuner-controls" />.</entry>
+ </row>
</tbody>
</tgroup>
</table>
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 53/86] xc2028: silence compiler warnings
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (51 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 52/86] DocBook: media: document V4L2_CTRL_CLASS_RF_TUNER Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:48 ` [REVIEW PATCH 54/86] v4l: add RF tuner channel bandwidth control Antti Palosaari
` (34 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari, Mauro Carvalho Chehab
There is now new tuner types which are not handled on that switch-case.
Print error if unknown tuner type is meet.
drivers/media/tuners/tuner-xc2028.c: In function ‘generic_set_freq’:
drivers/media/tuners/tuner-xc2028.c:1037:2: warning: enumeration value ‘V4L2_TUNER_ADC’ not handled in switch [-Wswitch]
switch (new_type) {
^
drivers/media/tuners/tuner-xc2028.c:1037:2: warning: enumeration value ‘V4L2_TUNER_RF’ not handled in switch [-Wswitch]
Cc: Mauro Carvalho Chehab <m.chehab@samsung.com>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/tuners/tuner-xc2028.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/media/tuners/tuner-xc2028.c b/drivers/media/tuners/tuner-xc2028.c
index cca508d..76a8165 100644
--- a/drivers/media/tuners/tuner-xc2028.c
+++ b/drivers/media/tuners/tuner-xc2028.c
@@ -1107,6 +1107,9 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
offset += 200000;
}
#endif
+ default:
+ tuner_err("Unsupported tuner type %d.\n", new_type);
+ break;
}
div = (freq - offset + DIV / 2) / DIV;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 54/86] v4l: add RF tuner channel bandwidth control
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (52 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 53/86] xc2028: silence compiler warnings Antti Palosaari
@ 2014-02-09 8:48 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 55/86] msi3101: implement tuner " Antti Palosaari
` (33 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:48 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari, Hans Verkuil
Modern silicon RF tuners has one or more adjustable filters on
signal path, in order to filter noise from desired radio channel.
Add channel bandwidth control to tell the driver which is radio
channel width we want receive. Filters could be then adjusted by
the driver or hardware, using RF frequency and channel bandwidth
as a base of filter calculations.
On automatic mode (normal mode), bandwidth is calculated from sampling
rate or tuning info got from userspace. That new control gives
possibility to set manual mode and let user have more control for
filters.
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/v4l2-core/v4l2-ctrls.c | 4 ++++
include/uapi/linux/v4l2-controls.h | 2 ++
2 files changed, 6 insertions(+)
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index d201f61..e44722b 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -865,6 +865,8 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_MIXER_GAIN: return "Mixer Gain";
case V4L2_CID_IF_GAIN_AUTO: return "IF Gain, Auto";
case V4L2_CID_IF_GAIN: return "IF Gain";
+ case V4L2_CID_BANDWIDTH_AUTO: return "Channel Bandwidth, Auto";
+ case V4L2_CID_BANDWIDTH: return "Channel Bandwidth";
default:
return NULL;
}
@@ -917,6 +919,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_LNA_GAIN_AUTO:
case V4L2_CID_MIXER_GAIN_AUTO:
case V4L2_CID_IF_GAIN_AUTO:
+ case V4L2_CID_BANDWIDTH_AUTO:
*type = V4L2_CTRL_TYPE_BOOLEAN;
*min = 0;
*max = *step = 1;
@@ -1078,6 +1081,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_LNA_GAIN:
case V4L2_CID_MIXER_GAIN:
case V4L2_CID_IF_GAIN:
+ case V4L2_CID_BANDWIDTH:
*flags |= V4L2_CTRL_FLAG_SLIDER;
break;
case V4L2_CID_PAN_RELATIVE:
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 076fa34..3cf68a6 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -905,5 +905,7 @@ enum v4l2_deemphasis {
#define V4L2_CID_MIXER_GAIN (V4L2_CID_RF_TUNER_CLASS_BASE + 4)
#define V4L2_CID_IF_GAIN_AUTO (V4L2_CID_RF_TUNER_CLASS_BASE + 5)
#define V4L2_CID_IF_GAIN (V4L2_CID_RF_TUNER_CLASS_BASE + 6)
+#define V4L2_CID_BANDWIDTH_AUTO (V4L2_CID_RF_TUNER_CLASS_BASE + 7)
+#define V4L2_CID_BANDWIDTH (V4L2_CID_RF_TUNER_CLASS_BASE + 8)
#endif
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 55/86] msi3101: implement tuner bandwidth control
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (53 preceding siblings ...)
2014-02-09 8:48 ` [REVIEW PATCH 54/86] v4l: add RF tuner channel bandwidth control Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 56/86] rtl2832_sdr: " Antti Palosaari
` (32 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Implement control that user could adjust tuner filters manually,
if he wish.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/msi3101/sdr-msi3101.c | 44 ++++++++++++++---------------
1 file changed, 22 insertions(+), 22 deletions(-)
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index 0606941..49e5bd1 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -52,8 +52,6 @@
#define MAX_ISOC_ERRORS 20
/* TODO: These should be moved to V4L2 API */
-#define MSI3101_CID_TUNER_BW ((V4L2_CID_USER_BASE | 0xf000) + 11)
-
#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 */
@@ -157,13 +155,14 @@ struct msi3101_state {
/* Controls */
struct v4l2_ctrl_handler hdl;
+ struct v4l2_ctrl *bandwidth_auto;
+ struct v4l2_ctrl *bandwidth;
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_auto;
struct v4l2_ctrl *if_gain;
- struct v4l2_ctrl *ctrl_tuner_bw;
u32 next_sample; /* for track lost packets */
u32 sample; /* for sample rate calc */
@@ -1131,7 +1130,7 @@ static int msi3101_set_tuner(struct msi3101_state *s)
{5000000, 0x04}, /* 5 MHz */
{6000000, 0x05}, /* 6 MHz */
{7000000, 0x06}, /* 7 MHz */
- { ~0U, 0x07}, /* 8 MHz */
+ {8000000, 0x07}, /* 8 MHz */
};
unsigned int f_rf = s->f_tuner;
@@ -1140,7 +1139,7 @@ static int msi3101_set_tuner(struct msi3101_state *s)
* bandwidth (Hz)
* 200000, 300000, 600000, 1536000, 5000000, 6000000, 7000000, 8000000
*/
- unsigned int bandwidth = s->ctrl_tuner_bw->val;
+ unsigned int bandwidth;
/*
* intermediate frequency (Hz)
@@ -1149,8 +1148,8 @@ static int msi3101_set_tuner(struct msi3101_state *s)
unsigned int f_if = 0;
dev_dbg(&s->udev->dev,
- "%s: f_rf=%d bandwidth=%d f_if=%d\n",
- __func__, f_rf, bandwidth, f_if);
+ "%s: f_rf=%d f_if=%d\n",
+ __func__, f_rf, f_if);
ret = -EINVAL;
@@ -1181,9 +1180,13 @@ static int msi3101_set_tuner(struct msi3101_state *s)
if (i == ARRAY_SIZE(if_freq_lut))
goto err;
- /* user has not requested bandwidth, set some reasonable */
- if (bandwidth == 0)
+ /* filters */
+ if (s->bandwidth_auto->val)
bandwidth = s->f_adc;
+ else
+ bandwidth = s->bandwidth->val;
+
+ bandwidth = clamp(bandwidth, 200000U, 8000000U);
for (i = 0; i < ARRAY_SIZE(bandwidth_lut); i++) {
if (bandwidth <= bandwidth_lut[i].freq) {
@@ -1195,6 +1198,8 @@ static int msi3101_set_tuner(struct msi3101_state *s)
if (i == ARRAY_SIZE(bandwidth_lut))
goto err;
+ s->bandwidth->val = bandwidth_lut[i].freq;
+
dev_dbg(&s->udev->dev, "%s: bandwidth selected=%d\n",
__func__, bandwidth_lut[i].freq);
@@ -1580,7 +1585,8 @@ static int msi3101_s_ctrl(struct v4l2_ctrl *ctrl)
ctrl->minimum, ctrl->maximum, ctrl->step);
switch (ctrl->id) {
- case MSI3101_CID_TUNER_BW:
+ case V4L2_CID_BANDWIDTH_AUTO:
+ case V4L2_CID_BANDWIDTH:
ret = msi3101_set_tuner(s);
break;
case V4L2_CID_LNA_GAIN:
@@ -1617,16 +1623,6 @@ static int msi3101_probe(struct usb_interface *intf,
struct msi3101_state *s = NULL;
const struct v4l2_ctrl_ops *ops = &msi3101_ctrl_ops;
int ret;
- 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 Bandwidth",
- .min = 0,
- .max = 8000000,
- .def = 0,
- .step = 1,
- };
s = kzalloc(sizeof(struct msi3101_state), GFP_KERNEL);
if (s == NULL) {
@@ -1664,8 +1660,12 @@ static int msi3101_probe(struct usb_interface *intf,
video_set_drvdata(&s->vdev, s);
/* Register controls */
- v4l2_ctrl_handler_init(&s->hdl, 4);
- s->ctrl_tuner_bw = v4l2_ctrl_new_custom(&s->hdl, &ctrl_tuner_bw, NULL);
+ v4l2_ctrl_handler_init(&s->hdl, 5);
+ s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops,
+ V4L2_CID_BANDWIDTH_AUTO, 0, 1, 1, 1);
+ s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops,
+ V4L2_CID_BANDWIDTH, 0, 8000000, 1, 0);
+ v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false);
s->lna_gain = v4l2_ctrl_new_std(&s->hdl, ops,
V4L2_CID_LNA_GAIN, 0, 1, 1, 1);
s->mixer_gain = v4l2_ctrl_new_std(&s->hdl, ops,
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 56/86] rtl2832_sdr: implement tuner bandwidth control
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (54 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 55/86] msi3101: implement tuner " Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 57/86] msi001: Mirics MSi001 silicon tuner driver Antti Palosaari
` (31 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Implement control that user could adjust tuner filters manually,
if he wish.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 71 ++++++++++++------------
1 file changed, 37 insertions(+), 34 deletions(-)
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index 15c562e3..1dfe653 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -38,9 +38,6 @@
#include <linux/math64.h>
/* TODO: These should be moved to V4L2 API */
-#define RTL2832_SDR_CID_TUNER_BW ((V4L2_CID_USER_BASE | 0xf000) + 11)
-#define RTL2832_SDR_CID_TUNER_GAIN ((V4L2_CID_USER_BASE | 0xf000) + 13)
-
#define V4L2_PIX_FMT_SDR_U8 v4l2_fourcc('D', 'U', '0', '8')
#define V4L2_PIX_FMT_SDR_U16LE v4l2_fourcc('D', 'U', '1', '6')
@@ -150,13 +147,14 @@ struct rtl2832_sdr_state {
/* Controls */
struct v4l2_ctrl_handler hdl;
+ struct v4l2_ctrl *bandwidth_auto;
+ struct v4l2_ctrl *bandwidth;
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_auto;
struct v4l2_ctrl *if_gain;
- struct v4l2_ctrl *ctrl_tuner_bw;
/* for sample rate calc */
unsigned int sample;
@@ -1003,12 +1001,23 @@ static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s)
/*
* bandwidth (Hz)
*/
- unsigned int bandwidth = s->ctrl_tuner_bw->val;
+ unsigned int bandwidth;
- dev_dbg(&s->udev->dev,
- "%s: f_rf=%u bandwidth=%d\n",
+ /* filters */
+ if (s->bandwidth_auto->val)
+ bandwidth = s->f_adc;
+ else
+ bandwidth = s->bandwidth->val;
+
+ s->bandwidth->val = bandwidth;
+
+ dev_dbg(&s->udev->dev, "%s: f_rf=%u bandwidth=%d\n",
__func__, f_rf, bandwidth);
+ c->bandwidth_hz = bandwidth;
+ c->frequency = f_rf;
+ c->delivery_system = SYS_DVBT;
+
if (f_rf == 0)
return 0;
@@ -1018,14 +1027,6 @@ static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s)
if (fe->ops.tuner_ops.init)
fe->ops.tuner_ops.init(fe);
- /* user has not requested bandwidth so calculate automatically */
- if (bandwidth == 0)
- bandwidth = s->f_adc;
-
- c->bandwidth_hz = bandwidth;
- c->frequency = f_rf;
- c->delivery_system = SYS_DVBT;
-
if (fe->ops.tuner_ops.set_params)
fe->ops.tuner_ops.set_params(fe);
@@ -1368,8 +1369,8 @@ static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl)
ctrl->minimum, ctrl->maximum, ctrl->step);
switch (ctrl->id) {
- case RTL2832_SDR_CID_TUNER_BW:
- case RTL2832_SDR_CID_TUNER_GAIN:
+ case V4L2_CID_BANDWIDTH_AUTO:
+ case V4L2_CID_BANDWIDTH:
ret = rtl2832_sdr_set_tuner(s);
break;
case V4L2_CID_LNA_GAIN_AUTO:
@@ -1409,16 +1410,6 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
struct rtl2832_sdr_state *s;
const struct v4l2_ctrl_ops *ops = &rtl2832_sdr_ctrl_ops;
struct dvb_usb_device *d = i2c_get_adapdata(i2c);
- static const struct v4l2_ctrl_config ctrl_tuner_bw = {
- .ops = &rtl2832_sdr_ctrl_ops,
- .id = RTL2832_SDR_CID_TUNER_BW,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Tuner BW",
- .min = 0,
- .max = INT_MAX,
- .def = 0,
- .step = 1,
- };
s = kzalloc(sizeof(struct rtl2832_sdr_state), GFP_KERNEL);
if (s == NULL) {
@@ -1458,8 +1449,10 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
/* Register controls */
switch (s->cfg->tuner) {
case RTL2832_TUNER_E4000:
- v4l2_ctrl_handler_init(&s->hdl, 7);
- s->ctrl_tuner_bw = v4l2_ctrl_new_custom(&s->hdl, &ctrl_tuner_bw, NULL);
+ v4l2_ctrl_handler_init(&s->hdl, 8);
+ s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_BANDWIDTH_AUTO, 0, 1, 1, 1);
+ s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_BANDWIDTH, 4300000, 11000000, 100000, 4300000);
+ v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false);
s->lna_gain_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_LNA_GAIN_AUTO, 0, 1, 1, 1);
s->lna_gain = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_LNA_GAIN, 0, 15, 1, 10);
v4l2_ctrl_auto_cluster(2, &s->lna_gain_auto, 0, false);
@@ -1471,7 +1464,10 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
v4l2_ctrl_auto_cluster(2, &s->if_gain_auto, 0, false);
break;
case RTL2832_TUNER_R820T:
- v4l2_ctrl_handler_init(&s->hdl, 7);
+ v4l2_ctrl_handler_init(&s->hdl, 8);
+ s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_BANDWIDTH_AUTO, 0, 1, 1, 1);
+ s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_BANDWIDTH, 0, 8000000, 100000, 0);
+ v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false);
s->lna_gain_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_LNA_GAIN_AUTO, 0, 1, 1, 1);
s->lna_gain = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_LNA_GAIN, 0, 15, 1, 6);
v4l2_ctrl_auto_cluster(2, &s->lna_gain_auto, 0, false);
@@ -1481,12 +1477,19 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
s->if_gain_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_IF_GAIN_AUTO, 0, 1, 1, 1);
s->if_gain = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_IF_GAIN, 0, 15, 1, 4);
v4l2_ctrl_auto_cluster(2, &s->if_gain_auto, 0, false);
- s->ctrl_tuner_bw = v4l2_ctrl_new_custom(&s->hdl, &ctrl_tuner_bw, NULL);
break;
- default:
- v4l2_ctrl_handler_init(&s->hdl, 1);
- s->ctrl_tuner_bw = v4l2_ctrl_new_custom(&s->hdl, &ctrl_tuner_bw, NULL);
+ case RTL2832_TUNER_FC0012:
+ case RTL2832_TUNER_FC0013:
+ v4l2_ctrl_handler_init(&s->hdl, 2);
+ s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_BANDWIDTH_AUTO, 0, 1, 1, 1);
+ s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_BANDWIDTH, 6000000, 8000000, 1000000, 6000000);
+ v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false);
break;
+ default:
+ v4l2_ctrl_handler_init(&s->hdl, 0);
+ dev_notice(&s->udev->dev, "%s: Unsupported tuner\n",
+ KBUILD_MODNAME);
+ goto err_free_controls;
}
if (s->hdl.error) {
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 57/86] msi001: Mirics MSi001 silicon tuner driver
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (55 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 56/86] rtl2832_sdr: " Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 58/86] msi3101: use msi001 " Antti Palosaari
` (30 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
That RF tuner driver is bound via SPI bus model and it implements V4L
subdev API. I split it out from MSi3101 SDR driver.
MSi3101 = MSi2500 + MSi001.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/msi3101/Kconfig | 4 +
drivers/staging/media/msi3101/Makefile | 1 +
drivers/staging/media/msi3101/msi001.c | 481 +++++++++++++++++++++++++++++++++
3 files changed, 486 insertions(+)
create mode 100644 drivers/staging/media/msi3101/msi001.c
diff --git a/drivers/staging/media/msi3101/Kconfig b/drivers/staging/media/msi3101/Kconfig
index 0c349c8..97d5210 100644
--- a/drivers/staging/media/msi3101/Kconfig
+++ b/drivers/staging/media/msi3101/Kconfig
@@ -3,3 +3,7 @@ config USB_MSI3101
depends on USB && VIDEO_DEV && VIDEO_V4L2
select VIDEOBUF2_CORE
select VIDEOBUF2_VMALLOC
+
+config MEDIA_TUNER_MSI001
+ tristate "Mirics MSi001"
+ depends on VIDEO_V4L2 && SPI
diff --git a/drivers/staging/media/msi3101/Makefile b/drivers/staging/media/msi3101/Makefile
index 3730654..daf4f58 100644
--- a/drivers/staging/media/msi3101/Makefile
+++ b/drivers/staging/media/msi3101/Makefile
@@ -1 +1,2 @@
obj-$(CONFIG_USB_MSI3101) += sdr-msi3101.o
+obj-$(CONFIG_MEDIA_TUNER_MSI001) += msi001.o
diff --git a/drivers/staging/media/msi3101/msi001.c b/drivers/staging/media/msi3101/msi001.c
new file mode 100644
index 0000000..5c5bb52
--- /dev/null
+++ b/drivers/staging/media/msi3101/msi001.c
@@ -0,0 +1,481 @@
+/*
+ * Mirics MSi001 silicon tuner driver
+ *
+ * Copyright (C) 2013 Antti Palosaari <crope@iki.fi>
+ * 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/gcd.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+static const struct v4l2_frequency_band bands[] = {
+ {
+ .type = V4L2_TUNER_RF,
+ .index = 0,
+ .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+ .rangelow = 49000000,
+ .rangehigh = 263000000,
+ }, {
+ .type = V4L2_TUNER_RF,
+ .index = 1,
+ .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+ .rangelow = 390000000,
+ .rangehigh = 960000000,
+ },
+};
+
+struct msi001 {
+ struct spi_device *spi;
+ struct v4l2_subdev sd;
+
+ /* Controls */
+ struct v4l2_ctrl_handler hdl;
+ struct v4l2_ctrl *bandwidth_auto;
+ struct v4l2_ctrl *bandwidth;
+ struct v4l2_ctrl *lna_gain;
+ struct v4l2_ctrl *mixer_gain;
+ struct v4l2_ctrl *if_gain;
+
+ unsigned int f_tuner;
+};
+
+static inline struct msi001 *sd_to_msi001(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct msi001, sd);
+}
+
+static int msi001_wreg(struct msi001 *s, u32 data)
+{
+ /* Register format: 4 bits addr + 20 bits value */
+ return spi_write(s->spi, &data, 3);
+};
+
+static int msi001_set_gain(struct msi001 *s, int lna_gain, int mixer_gain,
+ int if_gain)
+{
+ int ret;
+ u32 reg;
+ dev_dbg(&s->spi->dev, "%s: lna=%d mixer=%d if=%d\n", __func__,
+ lna_gain, mixer_gain, if_gain);
+
+ reg = 1 << 0;
+ reg |= (59 - if_gain) << 4;
+ reg |= 0 << 10;
+ reg |= (1 - mixer_gain) << 12;
+ reg |= (1 - lna_gain) << 13;
+ reg |= 4 << 14;
+ reg |= 0 << 17;
+ ret = msi001_wreg(s, reg);
+ if (ret)
+ goto err;
+
+ return 0;
+err:
+ dev_dbg(&s->spi->dev, "%s: failed %d\n", __func__, ret);
+ return ret;
+};
+
+static int msi001_set_tuner(struct msi001 *s)
+{
+ int ret, i;
+ unsigned int n, m, thresh, frac, vco_step, tmp, f_if1;
+ u32 reg;
+ u64 f_vco, tmp64;
+ u8 mode, filter_mode, lo_div;
+ static const struct {
+ u32 rf;
+ u8 mode;
+ u8 lo_div;
+ } band_lut[] = {
+ { 50000000, 0xe1, 16}, /* AM_MODE2, antenna 2 */
+ {108000000, 0x42, 32}, /* VHF_MODE */
+ {330000000, 0x44, 16}, /* B3_MODE */
+ {960000000, 0x48, 4}, /* B45_MODE */
+ { ~0U, 0x50, 2}, /* BL_MODE */
+ };
+ static const struct {
+ u32 freq;
+ u8 filter_mode;
+ } if_freq_lut[] = {
+ { 0, 0x03}, /* Zero IF */
+ { 450000, 0x02}, /* 450 kHz IF */
+ {1620000, 0x01}, /* 1.62 MHz IF */
+ {2048000, 0x00}, /* 2.048 MHz IF */
+ };
+ static const struct {
+ u32 freq;
+ u8 val;
+ } bandwidth_lut[] = {
+ { 200000, 0x00}, /* 200 kHz */
+ { 300000, 0x01}, /* 300 kHz */
+ { 600000, 0x02}, /* 600 kHz */
+ {1536000, 0x03}, /* 1.536 MHz */
+ {5000000, 0x04}, /* 5 MHz */
+ {6000000, 0x05}, /* 6 MHz */
+ {7000000, 0x06}, /* 7 MHz */
+ {8000000, 0x07}, /* 8 MHz */
+ };
+
+ unsigned int f_rf = s->f_tuner;
+
+ /*
+ * bandwidth (Hz)
+ * 200000, 300000, 600000, 1536000, 5000000, 6000000, 7000000, 8000000
+ */
+ unsigned int bandwidth;
+
+ /*
+ * intermediate frequency (Hz)
+ * 0, 450000, 1620000, 2048000
+ */
+ unsigned int f_if = 0;
+ #define F_REF 24000000
+ #define R_REF 4
+ #define F_OUT_STEP 1
+
+ dev_dbg(&s->spi->dev,
+ "%s: f_rf=%d f_if=%d\n",
+ __func__, f_rf, f_if);
+
+ for (i = 0; i < ARRAY_SIZE(band_lut); i++) {
+ if (f_rf <= band_lut[i].rf) {
+ mode = band_lut[i].mode;
+ lo_div = band_lut[i].lo_div;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(band_lut)) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* AM_MODE is upconverted */
+ if ((mode >> 0) & 0x1)
+ f_if1 = 5 * F_REF;
+ else
+ f_if1 = 0;
+
+ for (i = 0; i < ARRAY_SIZE(if_freq_lut); i++) {
+ if (f_if == if_freq_lut[i].freq) {
+ filter_mode = if_freq_lut[i].filter_mode;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(if_freq_lut)) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* filters */
+ bandwidth = s->bandwidth->val;
+ bandwidth = clamp(bandwidth, 200000U, 8000000U);
+
+ for (i = 0; i < ARRAY_SIZE(bandwidth_lut); i++) {
+ if (bandwidth <= bandwidth_lut[i].freq) {
+ bandwidth = bandwidth_lut[i].val;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(bandwidth_lut)) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ s->bandwidth->val = bandwidth_lut[i].freq;
+
+ dev_dbg(&s->spi->dev, "%s: bandwidth selected=%d\n",
+ __func__, bandwidth_lut[i].freq);
+
+ f_vco = (f_rf + f_if + f_if1) * lo_div;
+ tmp64 = f_vco;
+ m = do_div(tmp64, F_REF * R_REF);
+ n = (unsigned int) tmp64;
+
+ vco_step = F_OUT_STEP * lo_div;
+ thresh = (F_REF * R_REF) / vco_step;
+ frac = 1ul * thresh * m / (F_REF * R_REF);
+
+ /* Find out greatest common divisor and divide to smaller. */
+ tmp = gcd(thresh, frac);
+ thresh /= tmp;
+ frac /= tmp;
+
+ /* Force divide to reg max. Resolution will be reduced. */
+ tmp = DIV_ROUND_UP(thresh, 4095);
+ thresh = DIV_ROUND_CLOSEST(thresh, tmp);
+ frac = DIV_ROUND_CLOSEST(frac, tmp);
+
+ /* calc real RF set */
+ tmp = 1ul * F_REF * R_REF * n;
+ tmp += 1ul * F_REF * R_REF * frac / thresh;
+ tmp /= lo_div;
+
+ dev_dbg(&s->spi->dev,
+ "%s: rf=%u:%u n=%d thresh=%d frac=%d\n",
+ __func__, f_rf, tmp, n, thresh, frac);
+
+ ret = msi001_wreg(s, 0x00000e);
+ if (ret)
+ goto err;
+
+ ret = msi001_wreg(s, 0x000003);
+ if (ret)
+ goto err;
+
+ reg = 0 << 0;
+ reg |= mode << 4;
+ reg |= filter_mode << 12;
+ reg |= bandwidth << 14;
+ reg |= 0x02 << 17;
+ reg |= 0x00 << 20;
+ ret = msi001_wreg(s, reg);
+ if (ret)
+ goto err;
+
+ reg = 5 << 0;
+ reg |= thresh << 4;
+ reg |= 1 << 19;
+ reg |= 1 << 21;
+ ret = msi001_wreg(s, reg);
+ if (ret)
+ goto err;
+
+ reg = 2 << 0;
+ reg |= frac << 4;
+ reg |= n << 16;
+ ret = msi001_wreg(s, reg);
+ if (ret)
+ goto err;
+
+ ret = msi001_set_gain(s, s->lna_gain->cur.val, s->mixer_gain->cur.val,
+ s->if_gain->cur.val);
+ if (ret)
+ goto err;
+
+ reg = 6 << 0;
+ reg |= 63 << 4;
+ reg |= 4095 << 10;
+ ret = msi001_wreg(s, reg);
+ if (ret)
+ goto err;
+
+ return 0;
+err:
+ dev_dbg(&s->spi->dev, "%s: failed %d\n", __func__, ret);
+ return ret;
+};
+
+static int msi001_s_power(struct v4l2_subdev *sd, int on)
+{
+ struct msi001 *s = sd_to_msi001(sd);
+ int ret;
+ dev_dbg(&s->spi->dev, "%s: on=%d\n", __func__, on);
+
+ if (on)
+ ret = 0;
+ else
+ ret = msi001_wreg(s, 0x000000);
+
+ return ret;
+}
+
+static const struct v4l2_subdev_core_ops msi001_core_ops = {
+ .s_power = msi001_s_power,
+};
+
+static int msi001_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v)
+{
+ struct msi001 *s = sd_to_msi001(sd);
+ dev_dbg(&s->spi->dev, "%s: index=%d\n", __func__, v->index);
+
+ strlcpy(v->name, "Mirics MSi001", sizeof(v->name));
+ v->type = V4L2_TUNER_RF;
+ v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+ v->rangelow = 49000000;
+ v->rangehigh = 960000000;
+
+ return 0;
+}
+
+static int msi001_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *v)
+{
+ struct msi001 *s = sd_to_msi001(sd);
+ dev_dbg(&s->spi->dev, "%s: index=%d\n", __func__, v->index);
+ return 0;
+}
+
+static int msi001_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
+{
+ struct msi001 *s = sd_to_msi001(sd);
+ dev_dbg(&s->spi->dev, "%s: tuner=%d\n", __func__, f->tuner);
+ f->frequency = s->f_tuner;
+ return 0;
+}
+
+static int msi001_s_frequency(struct v4l2_subdev *sd,
+ const struct v4l2_frequency *f)
+{
+ struct msi001 *s = sd_to_msi001(sd);
+ unsigned int band;
+ dev_dbg(&s->spi->dev, "%s: tuner=%d type=%d frequency=%u\n",
+ __func__, f->tuner, f->type, f->frequency);
+
+ if (f->frequency < ((bands[0].rangehigh + bands[1].rangelow) / 2))
+ band = 0;
+ else
+ band = 1;
+ s->f_tuner = clamp_t(unsigned int, f->frequency,
+ bands[band].rangelow, bands[band].rangehigh);
+
+ return msi001_set_tuner(s);
+}
+
+static const struct v4l2_subdev_tuner_ops msi001_tuner_ops = {
+ .g_tuner = msi001_g_tuner,
+ .s_tuner = msi001_s_tuner,
+ .g_frequency = msi001_g_frequency,
+ .s_frequency = msi001_s_frequency,
+};
+
+static const struct v4l2_subdev_ops msi001_ops = {
+ .core = &msi001_core_ops,
+ .tuner = &msi001_tuner_ops,
+};
+
+static int msi001_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct msi001 *s = container_of(ctrl->handler, struct msi001, hdl);
+
+ int ret;
+ dev_dbg(&s->spi->dev,
+ "%s: id=%d name=%s val=%d min=%d max=%d step=%d\n",
+ __func__, ctrl->id, ctrl->name, ctrl->val,
+ ctrl->minimum, ctrl->maximum, ctrl->step);
+
+ switch (ctrl->id) {
+ case V4L2_CID_BANDWIDTH_AUTO:
+ case V4L2_CID_BANDWIDTH:
+ ret = msi001_set_tuner(s);
+ break;
+ case V4L2_CID_LNA_GAIN:
+ ret = msi001_set_gain(s, s->lna_gain->val,
+ s->mixer_gain->cur.val, s->if_gain->cur.val);
+ break;
+ case V4L2_CID_MIXER_GAIN:
+ ret = msi001_set_gain(s, s->lna_gain->cur.val,
+ s->mixer_gain->val, s->if_gain->cur.val);
+ break;
+ case V4L2_CID_IF_GAIN:
+ ret = msi001_set_gain(s, s->lna_gain->cur.val,
+ s->mixer_gain->cur.val, s->if_gain->val);
+ break;
+ default:
+ dev_dbg(&s->spi->dev, "%s: unkown control %d\n",
+ __func__, ctrl->id);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static const struct v4l2_ctrl_ops msi001_ctrl_ops = {
+ .s_ctrl = msi001_s_ctrl,
+};
+
+static int msi001_probe(struct spi_device *spi)
+{
+ struct msi001 *s;
+ int ret;
+ dev_dbg(&spi->dev, "%s:\n", __func__);
+
+ s = kzalloc(sizeof(struct msi001), GFP_KERNEL);
+ if (s == NULL) {
+ ret = -ENOMEM;
+ dev_dbg(&spi->dev, "Could not allocate memory for msi001\n");
+ goto err_kfree;
+ }
+
+ s->spi = spi;
+ v4l2_spi_subdev_init(&s->sd, spi, &msi001_ops);
+
+ /* Register controls */
+ v4l2_ctrl_handler_init(&s->hdl, 5);
+ s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, &msi001_ctrl_ops,
+ V4L2_CID_BANDWIDTH_AUTO, 0, 1, 1, 1);
+ s->bandwidth = v4l2_ctrl_new_std(&s->hdl, &msi001_ctrl_ops,
+ V4L2_CID_BANDWIDTH, 200000, 8000000, 1, 200000);
+ v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false);
+ s->lna_gain = v4l2_ctrl_new_std(&s->hdl, &msi001_ctrl_ops,
+ V4L2_CID_LNA_GAIN, 0, 1, 1, 1);
+ s->mixer_gain = v4l2_ctrl_new_std(&s->hdl, &msi001_ctrl_ops,
+ V4L2_CID_MIXER_GAIN, 0, 1, 1, 1);
+ s->if_gain = v4l2_ctrl_new_std(&s->hdl, &msi001_ctrl_ops,
+ V4L2_CID_IF_GAIN, 0, 59, 1, 0);
+ if (s->hdl.error) {
+ ret = s->hdl.error;
+ dev_err(&s->spi->dev, "Could not initialize controls\n");
+ /* control init failed, free handler */
+ goto err_ctrl_handler_free;
+ }
+
+ s->sd.ctrl_handler = &s->hdl;
+ return 0;
+
+err_ctrl_handler_free:
+ v4l2_ctrl_handler_free(&s->hdl);
+err_kfree:
+ kfree(s);
+ return ret;
+}
+
+static int msi001_remove(struct spi_device *spi)
+{
+ struct v4l2_subdev *sd = spi_get_drvdata(spi);
+ struct msi001 *s = sd_to_msi001(sd);
+ dev_dbg(&spi->dev, "%s:\n", __func__);
+
+ /*
+ * Registered by v4l2_spi_new_subdev() from master driver, but we must
+ * unregister it from here. Weird.
+ */
+ v4l2_device_unregister_subdev(&s->sd);
+ v4l2_ctrl_handler_free(&s->hdl);
+ kfree(s);
+ return 0;
+}
+
+static const struct spi_device_id msi001_id[] = {
+ {"msi001", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(spi, msi001_id);
+
+static struct spi_driver msi001_driver = {
+ .driver = {
+ .name = "msi001",
+ .owner = THIS_MODULE,
+ },
+ .probe = msi001_probe,
+ .remove = msi001_remove,
+ .id_table = msi001_id,
+};
+module_spi_driver(msi001_driver);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Mirics MSi001");
+MODULE_LICENSE("GPL");
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 58/86] msi3101: use msi001 tuner driver
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (56 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 57/86] msi001: Mirics MSi001 silicon tuner driver Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 59/86] MAINTAINERS: add msi001 driver Antti Palosaari
` (29 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Remove MSi001 RF tuner related code as MSi001 functionality is moved
to own driver.
Implement SPI master adapter.
Attach MSi001 driver via SPI / V4L subdev framework.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/msi3101/Kconfig | 3 +-
drivers/staging/media/msi3101/sdr-msi3101.c | 438 ++++++++--------------------
2 files changed, 122 insertions(+), 319 deletions(-)
diff --git a/drivers/staging/media/msi3101/Kconfig b/drivers/staging/media/msi3101/Kconfig
index 97d5210..de0b3bb 100644
--- a/drivers/staging/media/msi3101/Kconfig
+++ b/drivers/staging/media/msi3101/Kconfig
@@ -1,8 +1,9 @@
config USB_MSI3101
tristate "Mirics MSi3101 SDR Dongle"
- depends on USB && VIDEO_DEV && VIDEO_V4L2
+ depends on USB && VIDEO_DEV && VIDEO_V4L2 && SPI
select VIDEOBUF2_CORE
select VIDEOBUF2_VMALLOC
+ select MEDIA_TUNER_MSI001
config MEDIA_TUNER_MSI001
tristate "Mirics MSi001"
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index 49e5bd1..6159d88 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -25,7 +25,6 @@
#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/gcd.h>
#include <asm/div64.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
@@ -33,6 +32,7 @@
#include <media/v4l2-event.h>
#include <linux/usb.h>
#include <media/videobuf2-vmalloc.h>
+#include <linux/spi/spi.h>
/*
* iConfiguration 0
@@ -130,6 +130,8 @@ struct msi3101_frame_buf {
struct msi3101_state {
struct video_device vdev;
struct v4l2_device v4l2_dev;
+ struct v4l2_subdev *v4l2_subdev;
+ struct spi_master *master;
/* videobuf2 queue and queued buffers list */
struct vb2_queue vb_queue;
@@ -143,7 +145,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;
+ unsigned int f_adc;
u32 pixelformat;
unsigned int isoc_errors; /* number of contiguous ISOC errors */
@@ -155,14 +157,6 @@ struct msi3101_state {
/* Controls */
struct v4l2_ctrl_handler hdl;
- struct v4l2_ctrl *bandwidth_auto;
- struct v4l2_ctrl *bandwidth;
- 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_auto;
- struct v4l2_ctrl *if_gain;
u32 next_sample; /* for track lost packets */
u32 sample; /* for sample rate calc */
@@ -824,9 +818,9 @@ static void msi3101_disconnect(struct usb_interface *intf)
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);
+ spi_unregister_master(s->master);
mutex_unlock(&s->v4l2_lock);
mutex_unlock(&s->vb_queue_lock);
@@ -926,20 +920,25 @@ static int msi3101_ctrl_msg(struct msi3101_state *s, u8 cmd, u32 data)
return ret;
};
-static int msi3101_tuner_write(struct msi3101_state *s, u32 data)
-{
- return msi3101_ctrl_msg(s, CMD_WREG, data << 8 | 0x09);
-};
-
#define F_REF 24000000
#define DIV_R_IN 2
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;
+ struct v4l2_ctrl *bandwidth_auto;
+ struct v4l2_ctrl *bandwidth;
f_sr = s->f_adc;
+ /* set tuner, subdev, filters according to sampling rate */
+ bandwidth_auto = v4l2_ctrl_find(&s->hdl, V4L2_CID_BANDWIDTH_AUTO);
+ bandwidth = v4l2_ctrl_find(&s->hdl, V4L2_CID_BANDWIDTH);
+ if (v4l2_ctrl_g_ctrl(bandwidth_auto)) {
+ bandwidth = v4l2_ctrl_find(&s->hdl, V4L2_CID_BANDWIDTH);
+ v4l2_ctrl_s_ctrl(bandwidth, s->f_adc);
+ }
+
/* select stream format */
switch (s->pixelformat) {
case V4L2_PIX_FMT_SDR_U8:
@@ -1068,222 +1067,6 @@ err:
return ret;
};
-static int msi3101_set_gain(struct msi3101_state *s)
-{
- int ret;
- u32 reg;
- dev_dbg(&s->udev->dev, "%s: lna=%d mixer=%d if=%d\n", __func__,
- s->lna_gain->val, s->mixer_gain->val, s->if_gain->val);
-
- reg = 1 << 0;
- reg |= (59 - s->if_gain->val) << 4;
- reg |= 0 << 10;
- reg |= (1 - s->mixer_gain->val) << 12;
- reg |= (1 - s->lna_gain->val) << 13;
- reg |= 4 << 14;
- reg |= 0 << 17;
- ret = msi3101_tuner_write(s, reg);
- if (ret)
- goto err;
-
- return 0;
-err:
- dev_dbg(&s->udev->dev, "%s: failed %d\n", __func__, ret);
- return ret;
-};
-
-static int msi3101_set_tuner(struct msi3101_state *s)
-{
- int ret, i;
- unsigned int n, m, thresh, frac, vco_step, tmp, f_if1;
- u32 reg;
- u64 f_vco, tmp64;
- u8 mode, filter_mode, lo_div;
- static const struct {
- u32 rf;
- u8 mode;
- u8 lo_div;
- } band_lut[] = {
- { 50000000, 0xe1, 16}, /* AM_MODE2, antenna 2 */
- {108000000, 0x42, 32}, /* VHF_MODE */
- {330000000, 0x44, 16}, /* B3_MODE */
- {960000000, 0x48, 4}, /* B45_MODE */
- { ~0U, 0x50, 2}, /* BL_MODE */
- };
- static const struct {
- u32 freq;
- u8 filter_mode;
- } if_freq_lut[] = {
- { 0, 0x03}, /* Zero IF */
- { 450000, 0x02}, /* 450 kHz IF */
- {1620000, 0x01}, /* 1.62 MHz IF */
- {2048000, 0x00}, /* 2.048 MHz IF */
- };
- static const struct {
- u32 freq;
- u8 val;
- } bandwidth_lut[] = {
- { 200000, 0x00}, /* 200 kHz */
- { 300000, 0x01}, /* 300 kHz */
- { 600000, 0x02}, /* 600 kHz */
- {1536000, 0x03}, /* 1.536 MHz */
- {5000000, 0x04}, /* 5 MHz */
- {6000000, 0x05}, /* 6 MHz */
- {7000000, 0x06}, /* 7 MHz */
- {8000000, 0x07}, /* 8 MHz */
- };
-
- unsigned int f_rf = s->f_tuner;
-
- /*
- * bandwidth (Hz)
- * 200000, 300000, 600000, 1536000, 5000000, 6000000, 7000000, 8000000
- */
- unsigned int bandwidth;
-
- /*
- * intermediate frequency (Hz)
- * 0, 450000, 1620000, 2048000
- */
- unsigned int f_if = 0;
-
- dev_dbg(&s->udev->dev,
- "%s: f_rf=%d f_if=%d\n",
- __func__, f_rf, f_if);
-
- ret = -EINVAL;
-
- for (i = 0; i < ARRAY_SIZE(band_lut); i++) {
- if (f_rf <= band_lut[i].rf) {
- mode = band_lut[i].mode;
- lo_div = band_lut[i].lo_div;
- break;
- }
- }
-
- if (i == ARRAY_SIZE(band_lut))
- goto err;
-
- /* AM_MODE is upconverted */
- if ((mode >> 0) & 0x1)
- f_if1 = 5 * F_REF;
- else
- f_if1 = 0;
-
- for (i = 0; i < ARRAY_SIZE(if_freq_lut); i++) {
- if (f_if == if_freq_lut[i].freq) {
- filter_mode = if_freq_lut[i].filter_mode;
- break;
- }
- }
-
- if (i == ARRAY_SIZE(if_freq_lut))
- goto err;
-
- /* filters */
- if (s->bandwidth_auto->val)
- bandwidth = s->f_adc;
- else
- bandwidth = s->bandwidth->val;
-
- bandwidth = clamp(bandwidth, 200000U, 8000000U);
-
- for (i = 0; i < ARRAY_SIZE(bandwidth_lut); i++) {
- if (bandwidth <= bandwidth_lut[i].freq) {
- bandwidth = bandwidth_lut[i].val;
- break;
- }
- }
-
- if (i == ARRAY_SIZE(bandwidth_lut))
- goto err;
-
- s->bandwidth->val = bandwidth_lut[i].freq;
-
- dev_dbg(&s->udev->dev, "%s: bandwidth selected=%d\n",
- __func__, bandwidth_lut[i].freq);
-
-#define F_OUT_STEP 1
-#define R_REF 4
- f_vco = (f_rf + f_if + f_if1) * lo_div;
-
- tmp64 = f_vco;
- m = do_div(tmp64, F_REF * R_REF);
- n = (unsigned int) tmp64;
-
- vco_step = F_OUT_STEP * lo_div;
- thresh = (F_REF * R_REF) / vco_step;
- frac = 1ul * thresh * m / (F_REF * R_REF);
-
- /* Find out greatest common divisor and divide to smaller. */
- tmp = gcd(thresh, frac);
- thresh /= tmp;
- frac /= tmp;
-
- /* Force divide to reg max. Resolution will be reduced. */
- tmp = DIV_ROUND_UP(thresh, 4095);
- thresh = DIV_ROUND_CLOSEST(thresh, tmp);
- frac = DIV_ROUND_CLOSEST(frac, tmp);
-
- /* calc real RF set */
- tmp = 1ul * F_REF * R_REF * n;
- tmp += 1ul * F_REF * R_REF * frac / thresh;
- tmp /= lo_div;
-
- dev_dbg(&s->udev->dev,
- "%s: rf=%u:%u n=%d thresh=%d frac=%d\n",
- __func__, f_rf, tmp, n, thresh, frac);
-
- ret = msi3101_tuner_write(s, 0x00000e);
- if (ret)
- goto err;
-
- ret = msi3101_tuner_write(s, 0x000003);
- if (ret)
- goto err;
-
- reg = 0 << 0;
- reg |= mode << 4;
- reg |= filter_mode << 12;
- reg |= bandwidth << 14;
- reg |= 0x02 << 17;
- reg |= 0x00 << 20;
- ret = msi3101_tuner_write(s, reg);
- if (ret)
- goto err;
-
- reg = 5 << 0;
- reg |= thresh << 4;
- reg |= 1 << 19;
- reg |= 1 << 21;
- ret = msi3101_tuner_write(s, reg);
- if (ret)
- goto err;
-
- reg = 2 << 0;
- reg |= frac << 4;
- reg |= n << 16;
- ret = msi3101_tuner_write(s, reg);
- if (ret)
- goto err;
-
- ret = msi3101_set_gain(s);
- if (ret)
- goto err;
-
- reg = 6 << 0;
- reg |= 63 << 4;
- reg |= 4095 << 10;
- ret = msi3101_tuner_write(s, reg);
- if (ret)
- goto err;
-
- return 0;
-err:
- dev_dbg(&s->udev->dev, "%s: failed %d\n", __func__, ret);
- return ret;
-};
-
static int msi3101_start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct msi3101_state *s = vb2_get_drv_priv(vq);
@@ -1296,6 +1079,9 @@ static int msi3101_start_streaming(struct vb2_queue *vq, unsigned int count)
if (mutex_lock_interruptible(&s->v4l2_lock))
return -ERESTARTSYS;
+ /* wake-up tuner */
+ v4l2_subdev_call(s->v4l2_subdev, core, s_power, 1);
+
ret = msi3101_set_usb_adc(s);
ret = msi3101_isoc_init(s);
@@ -1330,7 +1116,7 @@ static int msi3101_stop_streaming(struct vb2_queue *vq)
msi3101_ctrl_msg(s, CMD_WREG, 0x01000003);
/* sleep tuner */
- msi3101_tuner_write(s, 0x000000);
+ v4l2_subdev_call(s->v4l2_subdev, core, s_power, 0);
mutex_unlock(&s->v4l2_lock);
@@ -1420,33 +1206,39 @@ static int msi3101_s_tuner(struct file *file, void *priv,
const struct v4l2_tuner *v)
{
struct msi3101_state *s = video_drvdata(file);
- dev_dbg(&s->udev->dev, "%s:\n", __func__);
+ int ret;
+ dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index);
- return 0;
+ if (v->index == 0)
+ ret = 0;
+ else if (v->index == 1)
+ ret = v4l2_subdev_call(s->v4l2_subdev, tuner, s_tuner, v);
+ else
+ ret = -EINVAL;
+
+ return ret;
}
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__);
+ int ret;
+ dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index);
if (v->index == 0) {
- strlcpy(v->name, "ADC: Mirics MSi2500", sizeof(v->name));
+ strlcpy(v->name, "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;
+ ret = 0;
} else if (v->index == 1) {
- strlcpy(v->name, "RF: Mirics MSi001", sizeof(v->name));
- v->type = V4L2_TUNER_RF;
- v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
- v->rangelow = 49000000;
- v->rangehigh = 960000000;
+ ret = v4l2_subdev_call(s->v4l2_subdev, tuner, g_tuner, v);
} else {
- return -EINVAL;
+ ret = -EINVAL;
}
- return 0;
+ return ret;
}
static int msi3101_g_frequency(struct file *file, void *priv,
@@ -1457,12 +1249,14 @@ static int msi3101_g_frequency(struct file *file, void *priv,
dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n",
__func__, f->tuner, f->type);
- if (f->tuner == 0)
+ if (f->tuner == 0) {
f->frequency = s->f_adc;
- else if (f->tuner == 1)
- f->frequency = s->f_tuner;
- else
- return -EINVAL;
+ ret = 0;
+ } else if (f->tuner == 1) {
+ ret = v4l2_subdev_call(s->v4l2_subdev, tuner, g_frequency, f);
+ } else {
+ ret = -EINVAL;
+ }
return ret;
}
@@ -1471,7 +1265,7 @@ static int msi3101_s_frequency(struct file *file, void *priv,
const struct v4l2_frequency *f)
{
struct msi3101_state *s = video_drvdata(file);
- int ret, band;
+ int ret;
dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n",
__func__, f->tuner, f->type, f->frequency);
@@ -1483,19 +1277,9 @@ static int msi3101_s_frequency(struct file *file, void *priv,
__func__, s->f_adc);
ret = msi3101_set_usb_adc(s);
} else if (f->tuner == 1) {
- #define BAND_RF_0 ((bands_rf[0].rangehigh + bands_rf[1].rangelow) / 2)
- if (f->frequency < BAND_RF_0)
- band = 0;
- else
- band = 1;
- s->f_tuner = clamp_t(unsigned int, f->frequency,
- bands_rf[band].rangelow,
- bands_rf[band].rangehigh);
- dev_dbg(&s->udev->dev, "%s: RF frequency=%u Hz\n",
- __func__, f->frequency);
- ret = msi3101_set_tuner(s);
+ ret = v4l2_subdev_call(s->v4l2_subdev, tuner, s_frequency, f);
} else {
- return -EINVAL;
+ ret = -EINVAL;
}
return ret;
@@ -1514,6 +1298,7 @@ static int msi3101_enum_freq_bands(struct file *file, void *priv,
*band = bands_adc[band->index];
} else if (band->tuner == 1) {
+ /* TODO: add that to v4l2_subdev_tuner_ops */
if (band->index >= ARRAY_SIZE(bands_rf))
return -EINVAL;
@@ -1570,40 +1355,6 @@ 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)
-{
- struct msi3101_state *s =
- container_of(ctrl->handler, struct msi3101_state,
- hdl);
- int ret;
- dev_dbg(&s->udev->dev,
- "%s: id=%d name=%s val=%d min=%d max=%d step=%d\n",
- __func__, ctrl->id, ctrl->name, ctrl->val,
- ctrl->minimum, ctrl->maximum, ctrl->step);
-
- switch (ctrl->id) {
- case V4L2_CID_BANDWIDTH_AUTO:
- case V4L2_CID_BANDWIDTH:
- ret = msi3101_set_tuner(s);
- break;
- case V4L2_CID_LNA_GAIN:
- case V4L2_CID_MIXER_GAIN:
- case V4L2_CID_IF_GAIN:
- ret = msi3101_set_gain(s);
- break;
- default:
- dev_dbg(&s->udev->dev, "%s: EINVAL\n", __func__);
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-static const struct v4l2_ctrl_ops msi3101_ctrl_ops = {
- .s_ctrl = msi3101_s_ctrl,
};
static void msi3101_video_release(struct v4l2_device *v)
@@ -1616,13 +1367,43 @@ static void msi3101_video_release(struct v4l2_device *v)
kfree(s);
}
+static int msi3101_transfer_one_message(struct spi_master *master,
+ struct spi_message *m)
+{
+ struct msi3101_state *s = spi_master_get_devdata(master);
+ struct spi_transfer *t;
+ int ret = 0;
+ u32 data;
+
+ list_for_each_entry(t, &m->transfers, transfer_list) {
+ dev_dbg(&s->udev->dev, "%s: msg=%*ph\n",
+ __func__, t->len, t->tx_buf);
+ data = 0x09; /* reg 9 is SPI adapter */
+ data |= ((u8 *)t->tx_buf)[0] << 8;
+ data |= ((u8 *)t->tx_buf)[1] << 16;
+ data |= ((u8 *)t->tx_buf)[2] << 24;
+ ret = msi3101_ctrl_msg(s, CMD_WREG, data);
+ }
+
+ m->status = ret;
+ spi_finalize_current_message(master);
+ return ret;
+}
+
static int msi3101_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct msi3101_state *s = NULL;
- const struct v4l2_ctrl_ops *ops = &msi3101_ctrl_ops;
+ struct v4l2_subdev *sd;
+ struct spi_master *master;
int ret;
+ static struct spi_board_info board_info = {
+ .modalias = "msi001",
+ .bus_num = 0,
+ .chip_select = 0,
+ .max_speed_hz = 12000000,
+ };
s = kzalloc(sizeof(struct msi3101_state), GFP_KERNEL);
if (s == NULL) {
@@ -1659,34 +1440,53 @@ static int msi3101_probe(struct usb_interface *intf,
set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev.flags);
video_set_drvdata(&s->vdev, s);
- /* Register controls */
- v4l2_ctrl_handler_init(&s->hdl, 5);
- s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops,
- V4L2_CID_BANDWIDTH_AUTO, 0, 1, 1, 1);
- s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops,
- V4L2_CID_BANDWIDTH, 0, 8000000, 1, 0);
- v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false);
- s->lna_gain = v4l2_ctrl_new_std(&s->hdl, ops,
- V4L2_CID_LNA_GAIN, 0, 1, 1, 1);
- s->mixer_gain = v4l2_ctrl_new_std(&s->hdl, ops,
- V4L2_CID_MIXER_GAIN, 0, 1, 1, 1);
- s->if_gain = v4l2_ctrl_new_std(&s->hdl, ops,
- V4L2_CID_IF_GAIN, 0, 59, 1, 0);
- if (s->hdl.error) {
- ret = s->hdl.error;
- dev_err(&s->udev->dev, "Could not initialize controls\n");
- goto err_free_controls;
- }
-
/* Register the v4l2_device structure */
s->v4l2_dev.release = msi3101_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;
+ }
+
+ /* SPI master adapter */
+ master = spi_alloc_master(&s->udev->dev, 0);
+ if (master == NULL) {
+ ret = -ENOMEM;
+ goto err_unregister_v4l2_dev;
+ }
+
+ s->master = master;
+ master->bus_num = 0;
+ master->num_chipselect = 1;
+ master->transfer_one_message = msi3101_transfer_one_message;
+ spi_master_set_devdata(master, s);
+ ret = spi_register_master(master);
+ if (ret) {
+ spi_master_put(master);
+ goto err_unregister_v4l2_dev;
+ }
+
+ /* load v4l2 subdevice */
+ sd = v4l2_spi_new_subdev(&s->v4l2_dev, master, &board_info);
+ s->v4l2_subdev = sd;
+ if (sd == NULL) {
+ dev_err(&s->udev->dev, "cannot get v4l2 subdevice\n");
+ ret = -ENODEV;
+ goto err_unregister_master;
+ }
+
+ /* Register controls */
+ v4l2_ctrl_handler_init(&s->hdl, 0);
+ if (s->hdl.error) {
+ ret = s->hdl.error;
+ dev_err(&s->udev->dev, "Could not initialize controls\n");
goto err_free_controls;
}
+ /* currently all controls are from subdev */
+ v4l2_ctrl_add_handler(&s->hdl, sd->ctrl_handler, NULL);
+
s->v4l2_dev.ctrl_handler = &s->hdl;
s->vdev.v4l2_dev = &s->v4l2_dev;
s->vdev.lock = &s->v4l2_lock;
@@ -1703,10 +1503,12 @@ static int msi3101_probe(struct usb_interface *intf,
return 0;
-err_unregister_v4l2_dev:
- v4l2_device_unregister(&s->v4l2_dev);
err_free_controls:
v4l2_ctrl_handler_free(&s->hdl);
+err_unregister_master:
+ spi_unregister_master(s->master);
+err_unregister_v4l2_dev:
+ v4l2_device_unregister(&s->v4l2_dev);
err_free_mem:
kfree(s);
return ret;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 59/86] MAINTAINERS: add msi001 driver
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (57 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 58/86] msi3101: use msi001 " Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 60/86] MAINTAINERS: add msi3101 driver Antti Palosaari
` (28 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Mirics MSi001 silicon tuner driver. Currently in staging as SDR API
is not ready.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
MAINTAINERS | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index b2cf5cf..15ebabb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5757,6 +5757,16 @@ L: platform-driver-x86@vger.kernel.org
S: Supported
F: drivers/platform/x86/msi-wmi.c
+MSI001 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/staging/media/msi3101/msi001*
+
MT9M032 APTINA SENSOR DRIVER
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
L: linux-media@vger.kernel.org
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 60/86] MAINTAINERS: add msi3101 driver
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (58 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 59/86] MAINTAINERS: add msi001 driver Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 61/86] MAINTAINERS: add rtl2832_sdr driver Antti Palosaari
` (27 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Mirics MSi2500 (MSi3101) SDR ADC + USB interface driver. Currently
in staging as SDR API is not ready.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
MAINTAINERS | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 15ebabb..f03772a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5767,6 +5767,16 @@ T: git git://linuxtv.org/anttip/media_tree.git
S: Maintained
F: drivers/staging/media/msi3101/msi001*
+MSI3101 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/staging/media/msi3101/sdr-msi3101*
+
MT9M032 APTINA SENSOR DRIVER
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
L: linux-media@vger.kernel.org
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 61/86] MAINTAINERS: add rtl2832_sdr driver
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (59 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 60/86] MAINTAINERS: add msi3101 driver Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 62/86] rtl28xxu: attach SDR module later Antti Palosaari
` (26 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Realtek RTL2832 SDR driver. Currently in staging as SDR API is not
ready.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
MAINTAINERS | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index f03772a..0ed943a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7338,6 +7338,16 @@ T: git git://linuxtv.org/anttip/media_tree.git
S: Maintained
F: drivers/media/dvb-frontends/rtl2832*
+RTL2832_SDR 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/staging/media/rtl2832u_sdr/rtl2832_sdr*
+
RTL8180 WIRELESS DRIVER
M: "John W. Linville" <linville@tuxdriver.com>
L: linux-wireless@vger.kernel.org
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 62/86] rtl28xxu: attach SDR module later
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (60 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 61/86] MAINTAINERS: add rtl2832_sdr driver Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 63/86] e4000: implement controls via v4l2 control framework Antti Palosaari
` (25 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
SDR module was attached between demod and tuner. Change it happen
after tuner attached. We are going to implement V4L controls for
tuner drivers and those controls are loaded during SDR attach. Due to
that (tuner controls), tuner driver must be loaded before SDR module.
Also as we are here, limit SDR module loading only for those tuners
we support.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 21 +++++++++++++++++----
1 file changed, 17 insertions(+), 4 deletions(-)
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index 76cf0de..73348bf 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -777,10 +777,6 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
/* set fe callback */
adap->fe[0]->callback = rtl2832u_frontend_callback;
- /* attach SDR */
- dvb_attach(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
- rtl2832_config);
-
return 0;
err:
dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
@@ -906,6 +902,10 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
* that to the tuner driver */
adap->fe[0]->ops.read_signal_strength =
adap->fe[0]->ops.tuner_ops.get_rf_strength;
+
+ /* attach SDR */
+ dvb_attach(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
+ &rtl28xxu_rtl2832_fc0012_config);
return 0;
break;
case TUNER_RTL2832_FC0013:
@@ -915,6 +915,10 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
/* fc0013 also supports signal strength reading */
adap->fe[0]->ops.read_signal_strength =
adap->fe[0]->ops.tuner_ops.get_rf_strength;
+
+ /* attach SDR */
+ dvb_attach(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
+ &rtl28xxu_rtl2832_fc0013_config);
return 0;
case TUNER_RTL2832_E4000: {
struct e4000_config e4000_config = {
@@ -928,6 +932,11 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
request_module("e4000");
priv->client = i2c_new_device(&d->i2c_adap, &info);
+
+ /* attach SDR */
+ dvb_attach(rtl2832_sdr_attach, adap->fe[0],
+ &d->i2c_adap,
+ &rtl28xxu_rtl2832_e4000_config);
}
break;
case TUNER_RTL2832_FC2580:
@@ -954,6 +963,10 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
/* Use tuner to get the signal strength */
adap->fe[0]->ops.read_signal_strength =
adap->fe[0]->ops.tuner_ops.get_rf_strength;
+
+ /* attach SDR */
+ dvb_attach(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
+ &rtl28xxu_rtl2832_r820t_config);
break;
case TUNER_RTL2832_R828D:
/* power off mn88472 demod on GPIO0 */
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 63/86] e4000: implement controls via v4l2 control framework
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (61 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 62/86] rtl28xxu: attach SDR module later Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 64/86] rtl2832_sdr: use E4000 tuner controls via V4L framework Antti Palosaari
` (24 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari, Mauro Carvalho Chehab, Hans Verkuil
Implement gain and bandwidth controls using v4l2 control framework.
Pointer to control handler is provided by exported symbol.
Cc: Mauro Carvalho Chehab <m.chehab@samsung.com>
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/tuners/e4000.c | 210 +++++++++++++++++++++++++++++++++++++-
drivers/media/tuners/e4000.h | 14 +++
drivers/media/tuners/e4000_priv.h | 12 +++
3 files changed, 235 insertions(+), 1 deletion(-)
diff --git a/drivers/media/tuners/e4000.c b/drivers/media/tuners/e4000.c
index 9187190..77318e9 100644
--- a/drivers/media/tuners/e4000.c
+++ b/drivers/media/tuners/e4000.c
@@ -448,6 +448,178 @@ err:
return ret;
}
+static int e4000_set_lna_gain(struct dvb_frontend *fe)
+{
+ struct e4000_priv *priv = fe->tuner_priv;
+ int ret;
+ u8 u8tmp;
+ dev_dbg(&priv->client->dev, "%s: lna auto=%d->%d val=%d->%d\n",
+ __func__, priv->lna_gain_auto->cur.val,
+ priv->lna_gain_auto->val, priv->lna_gain->cur.val,
+ priv->lna_gain->val);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ if (priv->lna_gain_auto->val && priv->if_gain_auto->cur.val)
+ u8tmp = 0x17;
+ else if (priv->lna_gain_auto->val)
+ u8tmp = 0x19;
+ else if (priv->if_gain_auto->cur.val)
+ u8tmp = 0x16;
+ else
+ u8tmp = 0x10;
+
+ ret = e4000_wr_reg(priv, 0x1a, u8tmp);
+ if (ret)
+ goto err;
+
+ if (priv->lna_gain_auto->val == false) {
+ ret = e4000_wr_reg(priv, 0x14, priv->lna_gain->val);
+ if (ret)
+ goto err;
+ }
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ return 0;
+err:
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
+ return ret;
+}
+
+static int e4000_set_mixer_gain(struct dvb_frontend *fe)
+{
+ struct e4000_priv *priv = fe->tuner_priv;
+ int ret;
+ u8 u8tmp;
+ dev_dbg(&priv->client->dev, "%s: mixer auto=%d->%d val=%d->%d\n",
+ __func__, priv->mixer_gain_auto->cur.val,
+ priv->mixer_gain_auto->val, priv->mixer_gain->cur.val,
+ priv->mixer_gain->val);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ if (priv->mixer_gain_auto->val)
+ u8tmp = 0x15;
+ else
+ u8tmp = 0x14;
+
+ ret = e4000_wr_reg(priv, 0x20, u8tmp);
+ if (ret)
+ goto err;
+
+ if (priv->mixer_gain_auto->val == false) {
+ ret = e4000_wr_reg(priv, 0x15, priv->mixer_gain->val);
+ if (ret)
+ goto err;
+ }
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ return 0;
+err:
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
+ return ret;
+}
+
+static int e4000_set_if_gain(struct dvb_frontend *fe)
+{
+ struct e4000_priv *priv = fe->tuner_priv;
+ int ret;
+ u8 buf[2];
+ u8 u8tmp;
+ dev_dbg(&priv->client->dev, "%s: if auto=%d->%d val=%d->%d\n",
+ __func__, priv->if_gain_auto->cur.val,
+ priv->if_gain_auto->val, priv->if_gain->cur.val,
+ priv->if_gain->val);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ if (priv->if_gain_auto->val && priv->lna_gain_auto->cur.val)
+ u8tmp = 0x17;
+ else if (priv->lna_gain_auto->cur.val)
+ u8tmp = 0x19;
+ else if (priv->if_gain_auto->val)
+ u8tmp = 0x16;
+ else
+ u8tmp = 0x10;
+
+ ret = e4000_wr_reg(priv, 0x1a, u8tmp);
+ if (ret)
+ goto err;
+
+ if (priv->if_gain_auto->val == false) {
+ buf[0] = e4000_if_gain_lut[priv->if_gain->val].reg16_val;
+ buf[1] = e4000_if_gain_lut[priv->if_gain->val].reg17_val;
+ ret = e4000_wr_regs(priv, 0x16, buf, 2);
+ if (ret)
+ goto err;
+ }
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ return 0;
+err:
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
+ return ret;
+}
+
+static int e4000_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct e4000_priv *priv =
+ container_of(ctrl->handler, struct e4000_priv, hdl);
+ struct dvb_frontend *fe = priv->fe;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ int ret;
+ dev_dbg(&priv->client->dev,
+ "%s: id=%d name=%s val=%d min=%d max=%d step=%d\n",
+ __func__, ctrl->id, ctrl->name, ctrl->val,
+ ctrl->minimum, ctrl->maximum, ctrl->step);
+
+ switch (ctrl->id) {
+ case V4L2_CID_BANDWIDTH_AUTO:
+ case V4L2_CID_BANDWIDTH:
+ c->bandwidth_hz = priv->bandwidth->val;
+ ret = e4000_set_params(priv->fe);
+ break;
+ case V4L2_CID_LNA_GAIN_AUTO:
+ case V4L2_CID_LNA_GAIN:
+ ret = e4000_set_lna_gain(priv->fe);
+ break;
+ case V4L2_CID_MIXER_GAIN_AUTO:
+ case V4L2_CID_MIXER_GAIN:
+ ret = e4000_set_mixer_gain(priv->fe);
+ break;
+ case V4L2_CID_IF_GAIN_AUTO:
+ case V4L2_CID_IF_GAIN:
+ ret = e4000_set_if_gain(priv->fe);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static const struct v4l2_ctrl_ops e4000_ctrl_ops = {
+ .s_ctrl = e4000_s_ctrl,
+};
+
static const struct dvb_tuner_ops e4000_tuner_ops = {
.info = {
.name = "Elonics E4000",
@@ -463,6 +635,13 @@ static const struct dvb_tuner_ops e4000_tuner_ops = {
.get_if_frequency = e4000_get_if_frequency,
};
+struct v4l2_ctrl_handler *e4000_get_ctrl_handler(struct dvb_frontend *fe)
+{
+ struct e4000_priv *priv = fe->tuner_priv;
+ return &priv->hdl;
+}
+EXPORT_SYMBOL(e4000_get_ctrl_handler);
+
static int e4000_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -504,6 +683,35 @@ static int e4000_probe(struct i2c_client *client,
if (ret < 0)
goto err;
+ /* Register controls */
+ v4l2_ctrl_handler_init(&priv->hdl, 8);
+ priv->bandwidth_auto = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+ V4L2_CID_BANDWIDTH_AUTO, 0, 1, 1, 1);
+ priv->bandwidth = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+ V4L2_CID_BANDWIDTH, 4300000, 11000000, 100000, 4300000);
+ v4l2_ctrl_auto_cluster(2, &priv->bandwidth_auto, 0, false);
+ priv->lna_gain_auto = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+ V4L2_CID_LNA_GAIN_AUTO, 0, 1, 1, 1);
+ priv->lna_gain = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+ V4L2_CID_LNA_GAIN, 0, 15, 1, 10);
+ v4l2_ctrl_auto_cluster(2, &priv->lna_gain_auto, 0, false);
+ priv->mixer_gain_auto = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+ V4L2_CID_MIXER_GAIN_AUTO, 0, 1, 1, 1);
+ priv->mixer_gain = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+ V4L2_CID_MIXER_GAIN, 0, 1, 1, 1);
+ v4l2_ctrl_auto_cluster(2, &priv->mixer_gain_auto, 0, false);
+ priv->if_gain_auto = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+ V4L2_CID_IF_GAIN_AUTO, 0, 1, 1, 1);
+ priv->if_gain = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+ V4L2_CID_IF_GAIN, 0, 54, 1, 0);
+ v4l2_ctrl_auto_cluster(2, &priv->if_gain_auto, 0, false);
+ if (priv->hdl.error) {
+ ret = priv->hdl.error;
+ dev_err(&priv->client->dev, "Could not initialize controls\n");
+ v4l2_ctrl_handler_free(&priv->hdl);
+ goto err;
+ }
+
dev_info(&priv->client->dev,
"%s: Elonics E4000 successfully identified\n",
KBUILD_MODNAME);
@@ -533,7 +741,7 @@ static int e4000_remove(struct i2c_client *client)
struct dvb_frontend *fe = priv->fe;
dev_dbg(&client->dev, "%s:\n", __func__);
-
+ v4l2_ctrl_handler_free(&priv->hdl);
memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
fe->tuner_priv = NULL;
kfree(priv);
diff --git a/drivers/media/tuners/e4000.h b/drivers/media/tuners/e4000.h
index d95c472..d86de6d 100644
--- a/drivers/media/tuners/e4000.h
+++ b/drivers/media/tuners/e4000.h
@@ -46,4 +46,18 @@ struct e4000_ctrl {
int if_gain;
};
+#if IS_ENABLED(CONFIG_MEDIA_TUNER_E4000)
+extern struct v4l2_ctrl_handler *e4000_get_ctrl_handler(
+ struct dvb_frontend *fe
+);
+#else
+static inline struct v4l2_ctrl_handler *e4000_get_ctrl_handler(
+ struct dvb_frontend *fe
+)
+{
+ pr_warn("%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif
+
#endif
diff --git a/drivers/media/tuners/e4000_priv.h b/drivers/media/tuners/e4000_priv.h
index a75a383..8cc27b3 100644
--- a/drivers/media/tuners/e4000_priv.h
+++ b/drivers/media/tuners/e4000_priv.h
@@ -22,11 +22,23 @@
#define E4000_PRIV_H
#include "e4000.h"
+#include <media/v4l2-ctrls.h>
struct e4000_priv {
struct i2c_client *client;
u32 clock;
struct dvb_frontend *fe;
+
+ /* Controls */
+ struct v4l2_ctrl_handler hdl;
+ struct v4l2_ctrl *bandwidth_auto;
+ struct v4l2_ctrl *bandwidth;
+ 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_auto;
+ struct v4l2_ctrl *if_gain;
};
struct e4000_pll {
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 64/86] rtl2832_sdr: use E4000 tuner controls via V4L framework
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (62 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 63/86] e4000: implement controls via v4l2 control framework Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 65/86] e4000: remove .set_config() which was for controls Antti Palosaari
` (23 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari, Mauro Carvalho Chehab, Hans Verkuil
Use V4L2 control framework for E4000 tuner as it provides controls
that way now.
Cc: Mauro Carvalho Chehab <m.chehab@samsung.com>
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 92 +++++++++---------------
1 file changed, 34 insertions(+), 58 deletions(-)
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index 1dfe653..c26c084 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -922,30 +922,6 @@ err:
return;
};
-static int rtl2832_sdr_set_gain_e4000(struct rtl2832_sdr_state *s)
-{
- int ret;
- struct dvb_frontend *fe = s->fe;
- struct e4000_ctrl ctrl;
- dev_dbg(&s->udev->dev, "%s: lna=%d mixer=%d if=%d\n", __func__,
- s->lna_gain->val, s->mixer_gain->val, s->if_gain->val);
-
- ctrl.lna_gain = s->lna_gain_auto->val ? INT_MIN : s->lna_gain->val;
- ctrl.mixer_gain = s->mixer_gain_auto->val ? INT_MIN : s->mixer_gain->val;
- ctrl.if_gain = s->if_gain_auto->val ? INT_MIN : s->if_gain->val;
-
- if (fe->ops.tuner_ops.set_config) {
- ret = fe->ops.tuner_ops.set_config(fe, &ctrl);
- if (ret)
- goto err;
- }
-
- return 0;
-err:
- dev_dbg(&s->udev->dev, "%s: failed %d\n", __func__, ret);
- return ret;
-};
-
static int rtl2832_sdr_set_gain_r820t(struct rtl2832_sdr_state *s)
{
int ret;
@@ -975,9 +951,6 @@ static int rtl2832_sdr_set_gain(struct rtl2832_sdr_state *s)
int ret;
switch (s->cfg->tuner) {
- case RTL2832_TUNER_E4000:
- ret = rtl2832_sdr_set_gain_e4000(s);
- break;
case RTL2832_TUNER_R820T:
ret = rtl2832_sdr_set_gain_r820t(s);
break;
@@ -991,35 +964,33 @@ 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;
+ struct v4l2_ctrl *bandwidth_auto;
+ struct v4l2_ctrl *bandwidth;
int ret;
/*
* tuner RF (Hz)
*/
- unsigned int f_rf = s->f_tuner;
+ if (s->f_tuner == 0)
+ return 0;
/*
* bandwidth (Hz)
*/
- unsigned int bandwidth;
-
- /* filters */
- if (s->bandwidth_auto->val)
- bandwidth = s->f_adc;
- else
- bandwidth = s->bandwidth->val;
-
- s->bandwidth->val = bandwidth;
-
- dev_dbg(&s->udev->dev, "%s: f_rf=%u bandwidth=%d\n",
- __func__, f_rf, bandwidth);
+ bandwidth_auto = v4l2_ctrl_find(&s->hdl, V4L2_CID_BANDWIDTH_AUTO);
+ bandwidth = v4l2_ctrl_find(&s->hdl, V4L2_CID_BANDWIDTH);
+ if (v4l2_ctrl_g_ctrl(bandwidth_auto)) {
+ c->bandwidth_hz = s->f_adc;
+ v4l2_ctrl_s_ctrl(bandwidth, s->f_adc);
+ } else {
+ c->bandwidth_hz = v4l2_ctrl_g_ctrl(bandwidth);
+ }
- c->bandwidth_hz = bandwidth;
- c->frequency = f_rf;
+ c->frequency = s->f_tuner;
c->delivery_system = SYS_DVBT;
- if (f_rf == 0)
- return 0;
+ dev_dbg(&s->udev->dev, "%s: frequency=%u bandwidth=%d\n",
+ __func__, c->frequency, c->bandwidth_hz);
if (!test_bit(POWER_ON, &s->flags))
return 0;
@@ -1362,6 +1333,8 @@ static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl)
struct rtl2832_sdr_state *s =
container_of(ctrl->handler, struct rtl2832_sdr_state,
hdl);
+ struct dvb_frontend *fe = s->fe;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
dev_dbg(&s->udev->dev,
"%s: id=%d name=%s val=%d min=%d max=%d step=%d\n",
@@ -1371,7 +1344,18 @@ static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl)
switch (ctrl->id) {
case V4L2_CID_BANDWIDTH_AUTO:
case V4L2_CID_BANDWIDTH:
- ret = rtl2832_sdr_set_tuner(s);
+ if (s->bandwidth_auto->val)
+ s->bandwidth->val = s->f_adc;
+
+ c->bandwidth_hz = s->bandwidth->val;
+
+ if (!test_bit(POWER_ON, &s->flags))
+ return 0;
+
+ if (fe->ops.tuner_ops.set_params)
+ ret = fe->ops.tuner_ops.set_params(fe);
+ else
+ ret = 0;
break;
case V4L2_CID_LNA_GAIN_AUTO:
case V4L2_CID_LNA_GAIN:
@@ -1410,6 +1394,7 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
struct rtl2832_sdr_state *s;
const struct v4l2_ctrl_ops *ops = &rtl2832_sdr_ctrl_ops;
struct dvb_usb_device *d = i2c_get_adapdata(i2c);
+ struct v4l2_ctrl_handler *hdl;
s = kzalloc(sizeof(struct rtl2832_sdr_state), GFP_KERNEL);
if (s == NULL) {
@@ -1449,19 +1434,10 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
/* Register controls */
switch (s->cfg->tuner) {
case RTL2832_TUNER_E4000:
- v4l2_ctrl_handler_init(&s->hdl, 8);
- s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_BANDWIDTH_AUTO, 0, 1, 1, 1);
- s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_BANDWIDTH, 4300000, 11000000, 100000, 4300000);
- v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false);
- s->lna_gain_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_LNA_GAIN_AUTO, 0, 1, 1, 1);
- s->lna_gain = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_LNA_GAIN, 0, 15, 1, 10);
- v4l2_ctrl_auto_cluster(2, &s->lna_gain_auto, 0, false);
- s->mixer_gain_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_MIXER_GAIN_AUTO, 0, 1, 1, 1);
- s->mixer_gain = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_MIXER_GAIN, 0, 1, 1, 1);
- v4l2_ctrl_auto_cluster(2, &s->mixer_gain_auto, 0, false);
- s->if_gain_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_IF_GAIN_AUTO, 0, 1, 1, 1);
- s->if_gain = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_IF_GAIN, 0, 54, 1, 0);
- v4l2_ctrl_auto_cluster(2, &s->if_gain_auto, 0, false);
+ hdl = e4000_get_ctrl_handler(fe);
+ v4l2_ctrl_handler_init(&s->hdl, 0);
+ if (hdl)
+ v4l2_ctrl_add_handler(&s->hdl, hdl, NULL);
break;
case RTL2832_TUNER_R820T:
v4l2_ctrl_handler_init(&s->hdl, 8);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 65/86] e4000: remove .set_config() which was for controls
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (63 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 64/86] rtl2832_sdr: use E4000 tuner controls via V4L framework Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 66/86] rtl28xxu: fix switch-case style issue Antti Palosaari
` (22 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari, Mauro Carvalho Chehab
That custom DVB callback is not needed anymore for setting gain
controls as those are now implemented using V4L2 control framework.
That change was proposed by Mauro.
Cc: Mauro Carvalho Chehab <m.chehab@samsung.com>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/tuners/e4000.c | 68 --------------------------------------------
drivers/media/tuners/e4000.h | 6 ----
2 files changed, 74 deletions(-)
diff --git a/drivers/media/tuners/e4000.c b/drivers/media/tuners/e4000.c
index 77318e9..019dc62 100644
--- a/drivers/media/tuners/e4000.c
+++ b/drivers/media/tuners/e4000.c
@@ -381,73 +381,6 @@ static int e4000_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
return 0;
}
-static int e4000_set_config(struct dvb_frontend *fe, void *priv_cfg)
-{
- struct e4000_priv *priv = fe->tuner_priv;
- struct e4000_ctrl *ctrl = priv_cfg;
- int ret;
- u8 buf[2];
- u8 u8tmp;
- dev_dbg(&priv->client->dev, "%s: lna=%d mixer=%d if=%d\n", __func__,
- ctrl->lna_gain, ctrl->mixer_gain, ctrl->if_gain);
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
-
- if (ctrl->lna_gain == INT_MIN && ctrl->if_gain == INT_MIN)
- u8tmp = 0x17;
- else if (ctrl->lna_gain == INT_MIN)
- u8tmp = 0x19;
- else if (ctrl->if_gain == INT_MIN)
- u8tmp = 0x16;
- else
- u8tmp = 0x10;
-
- ret = e4000_wr_reg(priv, 0x1a, u8tmp);
- if (ret)
- goto err;
-
- if (ctrl->mixer_gain == INT_MIN)
- u8tmp = 0x15;
- else
- u8tmp = 0x14;
-
- ret = e4000_wr_reg(priv, 0x20, u8tmp);
- if (ret)
- goto err;
-
- if (ctrl->lna_gain != INT_MIN) {
- ret = e4000_wr_reg(priv, 0x14, ctrl->lna_gain);
- if (ret)
- goto err;
- }
-
- if (ctrl->mixer_gain != INT_MIN) {
- ret = e4000_wr_reg(priv, 0x15, ctrl->mixer_gain);
- if (ret)
- goto err;
- }
-
- if (ctrl->if_gain != INT_MIN) {
- buf[0] = e4000_if_gain_lut[ctrl->if_gain].reg16_val;
- buf[1] = e4000_if_gain_lut[ctrl->if_gain].reg17_val;
- ret = e4000_wr_regs(priv, 0x16, buf, 2);
- if (ret)
- goto err;
- }
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
-
- return 0;
-err:
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
-
- dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
- return ret;
-}
-
static int e4000_set_lna_gain(struct dvb_frontend *fe)
{
struct e4000_priv *priv = fe->tuner_priv;
@@ -630,7 +563,6 @@ static const struct dvb_tuner_ops e4000_tuner_ops = {
.init = e4000_init,
.sleep = e4000_sleep,
.set_params = e4000_set_params,
- .set_config = e4000_set_config,
.get_if_frequency = e4000_get_if_frequency,
};
diff --git a/drivers/media/tuners/e4000.h b/drivers/media/tuners/e4000.h
index d86de6d..989f2ea 100644
--- a/drivers/media/tuners/e4000.h
+++ b/drivers/media/tuners/e4000.h
@@ -40,12 +40,6 @@ struct e4000_config {
u32 clock;
};
-struct e4000_ctrl {
- int lna_gain;
- int mixer_gain;
- int if_gain;
-};
-
#if IS_ENABLED(CONFIG_MEDIA_TUNER_E4000)
extern struct v4l2_ctrl_handler *e4000_get_ctrl_handler(
struct dvb_frontend *fe
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 66/86] rtl28xxu: fix switch-case style issue
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (64 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 65/86] e4000: remove .set_config() which was for controls Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 67/86] v4l: reorganize RF tuner control ID numbers Antti Palosaari
` (21 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Use break, not return, for every case.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index 73348bf..afafe92 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -906,7 +906,6 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
/* attach SDR */
dvb_attach(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
&rtl28xxu_rtl2832_fc0012_config);
- return 0;
break;
case TUNER_RTL2832_FC0013:
fe = dvb_attach(fc0013_attach, adap->fe[0],
@@ -919,7 +918,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
/* attach SDR */
dvb_attach(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
&rtl28xxu_rtl2832_fc0013_config);
- return 0;
+ break;
case TUNER_RTL2832_E4000: {
struct e4000_config e4000_config = {
.fe = adap->fe[0],
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 67/86] v4l: reorganize RF tuner control ID numbers
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (65 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 66/86] rtl28xxu: fix switch-case style issue Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 68/86] DocBook: document RF tuner bandwidth controls Antti Palosaari
` (20 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari, Hans Verkuil
It appears that controls are ordered by ID number. Change order of
controls by reorganizing assigned IDs now as we can. It is not
reasonable possible after the API is released. Leave some spare
space between IDs too for future extensions.
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
include/uapi/linux/v4l2-controls.h | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 3cf68a6..cc488c3 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -899,13 +899,13 @@ enum v4l2_deemphasis {
#define V4L2_CID_RF_TUNER_CLASS_BASE (V4L2_CTRL_CLASS_RF_TUNER | 0x900)
#define V4L2_CID_RF_TUNER_CLASS (V4L2_CTRL_CLASS_RF_TUNER | 1)
-#define V4L2_CID_LNA_GAIN_AUTO (V4L2_CID_RF_TUNER_CLASS_BASE + 1)
-#define V4L2_CID_LNA_GAIN (V4L2_CID_RF_TUNER_CLASS_BASE + 2)
-#define V4L2_CID_MIXER_GAIN_AUTO (V4L2_CID_RF_TUNER_CLASS_BASE + 3)
-#define V4L2_CID_MIXER_GAIN (V4L2_CID_RF_TUNER_CLASS_BASE + 4)
-#define V4L2_CID_IF_GAIN_AUTO (V4L2_CID_RF_TUNER_CLASS_BASE + 5)
-#define V4L2_CID_IF_GAIN (V4L2_CID_RF_TUNER_CLASS_BASE + 6)
-#define V4L2_CID_BANDWIDTH_AUTO (V4L2_CID_RF_TUNER_CLASS_BASE + 7)
-#define V4L2_CID_BANDWIDTH (V4L2_CID_RF_TUNER_CLASS_BASE + 8)
+#define V4L2_CID_BANDWIDTH_AUTO (V4L2_CID_RF_TUNER_CLASS_BASE + 11)
+#define V4L2_CID_BANDWIDTH (V4L2_CID_RF_TUNER_CLASS_BASE + 12)
+#define V4L2_CID_LNA_GAIN_AUTO (V4L2_CID_RF_TUNER_CLASS_BASE + 41)
+#define V4L2_CID_LNA_GAIN (V4L2_CID_RF_TUNER_CLASS_BASE + 42)
+#define V4L2_CID_MIXER_GAIN_AUTO (V4L2_CID_RF_TUNER_CLASS_BASE + 51)
+#define V4L2_CID_MIXER_GAIN (V4L2_CID_RF_TUNER_CLASS_BASE + 52)
+#define V4L2_CID_IF_GAIN_AUTO (V4L2_CID_RF_TUNER_CLASS_BASE + 61)
+#define V4L2_CID_IF_GAIN (V4L2_CID_RF_TUNER_CLASS_BASE + 62)
#endif
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 68/86] DocBook: document RF tuner bandwidth controls
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (66 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 67/86] v4l: reorganize RF tuner control ID numbers Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 69/86] v4l: uapi: add SDR formats CU8 and CU16LE Antti Palosaari
` (19 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari, Hans Verkuil
Add documentation for RF tuner bandwidth controls. These controls are
used to set filters on tuner signal path.
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
Documentation/DocBook/media/v4l/controls.xml | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index 0145341..345b6e5 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -5007,6 +5007,25 @@ descriptor. Calling &VIDIOC-QUERYCTRL; for this control will return a
description of this control class.</entry>
</row>
<row>
+ <entry spanname="id"><constant>V4L2_CID_BANDWIDTH_AUTO</constant> </entry>
+ <entry>boolean</entry>
+ </row>
+ <row>
+ <entry spanname="descr">Enables/disables tuner radio channel
+bandwidth configuration. In automatic mode bandwidth configuration is performed
+by the driver.</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_BANDWIDTH</constant> </entry>
+ <entry>integer</entry>
+ </row>
+ <row>
+ <entry spanname="descr">Filter(s) on tuner signal path are used to
+filter signal according to receiving party needs. Driver configures filters to
+fulfill desired bandwidth requirement. Used when V4L2_CID_BANDWIDTH_AUTO is not
+set. The range and step are driver-specific.</entry>
+ </row>
+ <row>
<entry spanname="id"><constant>V4L2_CID_LNA_GAIN_AUTO</constant> </entry>
<entry>boolean</entry>
</row>
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 69/86] v4l: uapi: add SDR formats CU8 and CU16LE
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (67 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 68/86] DocBook: document RF tuner bandwidth controls Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 70/86] msi3101: use formats defined in V4L2 API Antti Palosaari
` (18 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari, Hans Verkuil
V4L2_SDR_FMT_CU8 — Complex unsigned 8-bit IQ sample
V4L2_SDR_FMT_CU16LE — Complex unsigned 16-bit little endian IQ sample
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
include/uapi/linux/videodev2.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 27fedfe..3411215 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -436,6 +436,10 @@ struct v4l2_pix_format {
#define V4L2_PIX_FMT_SE401 v4l2_fourcc('S', '4', '0', '1') /* se401 janggu compressed rgb */
#define V4L2_PIX_FMT_S5C_UYVY_JPG v4l2_fourcc('S', '5', 'C', 'I') /* S5C73M3 interleaved UYVY/JPEG */
+/* SDR formats - used only for Software Defined Radio devices */
+#define V4L2_SDR_FMT_CU8 v4l2_fourcc('C', 'U', '0', '8') /* IQ u8 */
+#define V4L2_SDR_FMT_CU16LE v4l2_fourcc('C', 'U', '1', '6') /* IQ u16le */
+
/*
* F O R M A T E N U M E R A T I O N
*/
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 70/86] msi3101: use formats defined in V4L2 API
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (68 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 69/86] v4l: uapi: add SDR formats CU8 and CU16LE Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 71/86] rtl2832_sdr: " Antti Palosaari
` (17 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Switch new formats V4L2_SDR_FMT_CU8 and V4L2_SDR_FMT_CU16LE as those
are now defined in API.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/msi3101/sdr-msi3101.c | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index 6159d88..f996220 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -52,8 +52,6 @@
#define MAX_ISOC_ERRORS 20
/* TODO: These should be moved to V4L2 API */
-#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 */
@@ -97,11 +95,11 @@ struct msi3101_format {
/* format descriptions for capture and preview */
static struct msi3101_format formats[] = {
{
- .name = "8-bit unsigned",
- .pixelformat = V4L2_PIX_FMT_SDR_U8,
+ .name = "IQ U8",
+ .pixelformat = V4L2_SDR_FMT_CU8,
}, {
- .name = "16-bit unsigned little endian",
- .pixelformat = V4L2_PIX_FMT_SDR_U16LE,
+ .name = "IQ U16LE",
+ .pixelformat = V4L2_SDR_FMT_CU16LE,
#if 0
}, {
.name = "8-bit signed",
@@ -941,11 +939,11 @@ static int msi3101_set_usb_adc(struct msi3101_state *s)
/* select stream format */
switch (s->pixelformat) {
- case V4L2_PIX_FMT_SDR_U8:
+ case V4L2_SDR_FMT_CU8:
s->convert_stream = msi3101_convert_stream_504_u8;
reg7 = 0x000c9407;
break;
- case V4L2_PIX_FMT_SDR_U16LE:
+ case V4L2_SDR_FMT_CU16LE:
s->convert_stream = msi3101_convert_stream_252_u16;
reg7 = 0x00009407;
break;
@@ -1417,7 +1415,7 @@ static int msi3101_probe(struct usb_interface *intf,
INIT_LIST_HEAD(&s->queued_bufs);
s->udev = udev;
s->f_adc = bands_adc[0].rangelow;
- s->pixelformat = V4L2_PIX_FMT_SDR_U8;
+ s->pixelformat = V4L2_SDR_FMT_CU8;
/* Init videobuf2 queue structure */
s->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 71/86] rtl2832_sdr: use formats defined in V4L2 API
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (69 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 70/86] msi3101: use formats defined in V4L2 API Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 72/86] v4l: add enum_freq_bands support to tuner sub-device Antti Palosaari
` (16 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Switch new formats V4L2_SDR_FMT_CU8 and V4L2_SDR_FMT_CU16LE as those
are now defined in API.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 18 +++++++-----------
1 file changed, 7 insertions(+), 11 deletions(-)
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index c26c084..e89abd8 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -37,10 +37,6 @@
#include <linux/jiffies.h>
#include <linux/math64.h>
-/* TODO: These should be moved to V4L2 API */
-#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)
@@ -90,11 +86,11 @@ struct rtl2832_sdr_format {
static struct rtl2832_sdr_format formats[] = {
{
- .name = "8-bit unsigned",
- .pixelformat = V4L2_PIX_FMT_SDR_U8,
+ .name = "IQ U8",
+ .pixelformat = V4L2_SDR_FMT_CU8,
}, {
- .name = "16-bit unsigned little endian",
- .pixelformat = V4L2_PIX_FMT_SDR_U16LE,
+ .name = "IQ U16LE (emulated)",
+ .pixelformat = V4L2_SDR_FMT_CU16LE,
},
};
@@ -346,11 +342,11 @@ static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s,
{
unsigned int dst_len;
- if (s->pixelformat == V4L2_PIX_FMT_SDR_U8) {
+ if (s->pixelformat == V4L2_SDR_FMT_CU8) {
/* native stream, no need to convert */
memcpy(dst, src, src_len);
dst_len = src_len;
- } else if (s->pixelformat == V4L2_PIX_FMT_SDR_U16LE) {
+ } else if (s->pixelformat == V4L2_SDR_FMT_CU16LE) {
/* convert u8 to u16 */
unsigned int i;
u16 *u16dst = dst;
@@ -1410,7 +1406,7 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
s->i2c = i2c;
s->cfg = cfg;
s->f_adc = bands_adc[0].rangelow;
- s->pixelformat = V4L2_PIX_FMT_SDR_U8;
+ s->pixelformat = V4L2_SDR_FMT_CU8;
mutex_init(&s->v4l2_lock);
mutex_init(&s->vb_queue_lock);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 72/86] v4l: add enum_freq_bands support to tuner sub-device
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (70 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 71/86] rtl2832_sdr: " Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 73/86] msi001: implement .enum_freq_bands() Antti Palosaari
` (15 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari, Hans Verkuil
Add VIDIOC_ENUM_FREQ_BANDS, enumerate supported frequency bands,
IOCTL support for sub-device tuners too.
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
include/media/v4l2-subdev.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index d67210a..4682aad 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -192,6 +192,7 @@ struct v4l2_subdev_tuner_ops {
int (*s_radio)(struct v4l2_subdev *sd);
int (*s_frequency)(struct v4l2_subdev *sd, const struct v4l2_frequency *freq);
int (*g_frequency)(struct v4l2_subdev *sd, struct v4l2_frequency *freq);
+ int (*enum_freq_bands)(struct v4l2_subdev *sd, struct v4l2_frequency_band *band);
int (*g_tuner)(struct v4l2_subdev *sd, struct v4l2_tuner *vt);
int (*s_tuner)(struct v4l2_subdev *sd, const struct v4l2_tuner *vt);
int (*g_modulator)(struct v4l2_subdev *sd, struct v4l2_modulator *vm);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 73/86] msi001: implement .enum_freq_bands()
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (71 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 72/86] v4l: add enum_freq_bands support to tuner sub-device Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 74/86] msi3101: provide RF tuner bands from sub-device Antti Palosaari
` (14 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari, Hans Verkuil
Implement .enum_freq_bands() in order to provide
VIDIOC_ENUM_FREQ_BANDS IOCTL from sub-device.
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/msi3101/msi001.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/drivers/staging/media/msi3101/msi001.c b/drivers/staging/media/msi3101/msi001.c
index 5c5bb52..da7a34d 100644
--- a/drivers/staging/media/msi3101/msi001.c
+++ b/drivers/staging/media/msi3101/msi001.c
@@ -345,11 +345,29 @@ static int msi001_s_frequency(struct v4l2_subdev *sd,
return msi001_set_tuner(s);
}
+static int msi001_enum_freq_bands(struct v4l2_subdev *sd,
+ struct v4l2_frequency_band *band)
+{
+ struct msi001 *s = sd_to_msi001(sd);
+ dev_dbg(&s->spi->dev, "%s: tuner=%d type=%d index=%d\n",
+ __func__, band->tuner, band->type, band->index);
+
+ if (band->index >= ARRAY_SIZE(bands))
+ return -EINVAL;
+
+ band->capability = bands[band->index].capability;
+ band->rangelow = bands[band->index].rangelow;
+ band->rangehigh = bands[band->index].rangehigh;
+
+ return 0;
+}
+
static const struct v4l2_subdev_tuner_ops msi001_tuner_ops = {
.g_tuner = msi001_g_tuner,
.s_tuner = msi001_s_tuner,
.g_frequency = msi001_g_frequency,
.s_frequency = msi001_s_frequency,
+ .enum_freq_bands = msi001_enum_freq_bands,
};
static const struct v4l2_subdev_ops msi001_ops = {
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 74/86] msi3101: provide RF tuner bands from sub-device
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (72 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 73/86] msi001: implement .enum_freq_bands() Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 75/86] r820t/rtl2832u_sdr: implement gains using v4l2 controls Antti Palosaari
` (13 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Let the msi001 tuner driver report its frequency bands.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/msi3101/sdr-msi3101.c | 48 +++++++++--------------------
1 file changed, 15 insertions(+), 33 deletions(-)
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index f996220..158cbe0 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -57,7 +57,7 @@
#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[] = {
+static const struct v4l2_frequency_band bands[] = {
{
.tuner = 0,
.type = V4L2_TUNER_ADC,
@@ -68,24 +68,6 @@ static const struct v4l2_frequency_band bands_adc[] = {
},
};
-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 = 49000000,
- .rangehigh = 263000000,
- }, {
- .tuner = 1,
- .type = V4L2_TUNER_RF,
- .index = 1,
- .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
- .rangelow = 390000000,
- .rangehigh = 960000000,
- },
-};
-
/* stream formats */
struct msi3101_format {
char *name;
@@ -1269,8 +1251,8 @@ static int msi3101_s_frequency(struct file *file, void *priv,
if (f->tuner == 0) {
s->f_adc = clamp_t(unsigned int, f->frequency,
- bands_adc[0].rangelow,
- bands_adc[0].rangehigh);
+ bands[0].rangelow,
+ bands[0].rangehigh);
dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n",
__func__, s->f_adc);
ret = msi3101_set_usb_adc(s);
@@ -1287,25 +1269,25 @@ static int msi3101_enum_freq_bands(struct file *file, void *priv,
struct v4l2_frequency_band *band)
{
struct msi3101_state *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_adc))
- return -EINVAL;
-
- *band = bands_adc[band->index];
+ if (band->index >= ARRAY_SIZE(bands)) {
+ ret = -EINVAL;
+ } else {
+ *band = bands[band->index];
+ ret = 0;
+ }
} else if (band->tuner == 1) {
- /* TODO: add that to v4l2_subdev_tuner_ops */
- if (band->index >= ARRAY_SIZE(bands_rf))
- return -EINVAL;
-
- *band = bands_rf[band->index];
+ ret = v4l2_subdev_call(s->v4l2_subdev, tuner,
+ enum_freq_bands, band);
} else {
- return -EINVAL;
+ ret = -EINVAL;
}
- return 0;
+ return ret;
}
static const struct v4l2_ioctl_ops msi3101_ioctl_ops = {
@@ -1414,7 +1396,7 @@ static int msi3101_probe(struct usb_interface *intf,
spin_lock_init(&s->queued_bufs_lock);
INIT_LIST_HEAD(&s->queued_bufs);
s->udev = udev;
- s->f_adc = bands_adc[0].rangelow;
+ s->f_adc = bands[0].rangelow;
s->pixelformat = V4L2_SDR_FMT_CU8;
/* Init videobuf2 queue structure */
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 75/86] r820t/rtl2832u_sdr: implement gains using v4l2 controls
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (73 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 74/86] msi3101: provide RF tuner bands from sub-device Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 76/86] v4l: add control for RF tuner PLL lock flag Antti Palosaari
` (12 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari, Mauro Carvalho Chehab, Hans Verkuil
Implement gain controls using v4l2 control framework.
Pointer to control handler is provided by exported symbol.
Cc: Mauro Carvalho Chehab <m.chehab@samsung.com>
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/tuners/r820t.c | 175 ++++++++++++++++++-----
drivers/media/tuners/r820t.h | 17 ++-
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 72 +---------
3 files changed, 151 insertions(+), 113 deletions(-)
diff --git a/drivers/media/tuners/r820t.c b/drivers/media/tuners/r820t.c
index 231c614..5150a18 100644
--- a/drivers/media/tuners/r820t.c
+++ b/drivers/media/tuners/r820t.c
@@ -36,6 +36,7 @@
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/bitrev.h>
+#include <media/v4l2-ctrls.h>
#include "tuner-i2c.h"
#include "r820t.h"
@@ -80,6 +81,7 @@ struct r820t_sect_type {
struct r820t_priv {
struct list_head hybrid_tuner_instance_list;
+ struct dvb_frontend *fe;
const struct r820t_config *cfg;
struct tuner_i2c_props i2c_props;
struct mutex lock;
@@ -100,6 +102,15 @@ struct r820t_priv {
enum v4l2_tuner_type type;
v4l2_std_id std;
u32 bw; /* in MHz */
+
+ /* 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_auto;
+ struct v4l2_ctrl *if_gain;
};
struct r820t_freq_range {
@@ -1251,43 +1262,6 @@ static int r820t_set_gain_mode(struct r820t_priv *priv,
}
#endif
-static int r820t_set_config(struct dvb_frontend *fe, void *priv_cfg)
-{
- struct r820t_priv *priv = fe->tuner_priv;
- struct r820t_ctrl *ctrl = priv_cfg;
- int rc;
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
-
- if (ctrl->lna_gain == INT_MIN)
- rc = r820t_write_reg_mask(priv, 0x05, 0x00, 0x10);
- else
- rc = r820t_write_reg_mask(priv, 0x05,
- 0x10 | ctrl->lna_gain, 0x1f);
- if (rc < 0)
- goto err;
-
- if (ctrl->mixer_gain == INT_MIN)
- rc = r820t_write_reg_mask(priv, 0x07, 0x10, 0x10);
- else
- rc = r820t_write_reg_mask(priv, 0x07,
- 0x00 | ctrl->mixer_gain, 0x1f);
- if (rc < 0)
- goto err;
-
- if (ctrl->if_gain == INT_MIN)
- rc = r820t_write_reg_mask(priv, 0x0c, 0x10, 0x10);
- else
- rc = r820t_write_reg_mask(priv, 0x0c,
- 0x00 | ctrl->if_gain, 0x1f);
-err:
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
-
- return rc;
-}
-
static int generic_set_freq(struct dvb_frontend *fe,
u32 freq /* in HZ */,
unsigned bw,
@@ -2292,8 +2266,10 @@ static int r820t_release(struct dvb_frontend *fe)
mutex_lock(&r820t_list_mutex);
- if (priv)
+ if (priv) {
+ v4l2_ctrl_handler_free(&priv->hdl);
hybrid_tuner_release_state(priv);
+ }
mutex_unlock(&r820t_list_mutex);
@@ -2302,6 +2278,96 @@ static int r820t_release(struct dvb_frontend *fe)
return 0;
}
+static int r820t_set_lna_gain(struct r820t_priv *priv)
+{
+ struct dvb_frontend *fe = priv->fe;
+ int rc;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ if (priv->lna_gain_auto->val)
+ rc = r820t_write_reg_mask(priv, 0x05, 0x00, 0x10);
+ else
+ rc = r820t_write_reg_mask(priv, 0x05,
+ 0x10 | priv->lna_gain->val, 0x1f);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ return rc;
+}
+
+static int r820t_set_mixer_gain(struct r820t_priv *priv)
+{
+ struct dvb_frontend *fe = priv->fe;
+ int rc;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ if (priv->mixer_gain_auto->val)
+ rc = r820t_write_reg_mask(priv, 0x07, 0x10, 0x10);
+ else
+ rc = r820t_write_reg_mask(priv, 0x07,
+ 0x00 | priv->mixer_gain->val, 0x1f);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ return rc;
+}
+
+static int r820t_set_if_gain(struct r820t_priv *priv)
+{
+ struct dvb_frontend *fe = priv->fe;
+ int rc;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ if (priv->if_gain_auto->val)
+ rc = r820t_write_reg_mask(priv, 0x0c, 0x10, 0x10);
+ else
+ rc = r820t_write_reg_mask(priv, 0x0c,
+ 0x00 | priv->if_gain->val, 0x1f);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ return rc;
+}
+
+static int r820t_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct r820t_priv *priv =
+ container_of(ctrl->handler, struct r820t_priv, hdl);
+ int rc;
+
+ switch (ctrl->id) {
+ case V4L2_CID_LNA_GAIN_AUTO:
+ case V4L2_CID_LNA_GAIN:
+ rc = r820t_set_lna_gain(priv);
+ break;
+ case V4L2_CID_MIXER_GAIN_AUTO:
+ case V4L2_CID_MIXER_GAIN:
+ rc = r820t_set_mixer_gain(priv);
+ break;
+ case V4L2_CID_IF_GAIN_AUTO:
+ case V4L2_CID_IF_GAIN:
+ rc = r820t_set_if_gain(priv);
+ break;
+ default:
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+static const struct v4l2_ctrl_ops r820t_ctrl_ops = {
+ .s_ctrl = r820t_s_ctrl,
+};
+
static const struct dvb_tuner_ops r820t_tuner_ops = {
.info = {
.name = "Rafael Micro R820T",
@@ -2312,12 +2378,18 @@ static const struct dvb_tuner_ops r820t_tuner_ops = {
.release = r820t_release,
.sleep = r820t_sleep,
.set_params = r820t_set_params,
- .set_config = r820t_set_config,
.set_analog_params = r820t_set_analog_freq,
.get_if_frequency = r820t_get_if_frequency,
.get_rf_strength = r820t_signal,
};
+struct v4l2_ctrl_handler *r820t_get_ctrl_handler(struct dvb_frontend *fe)
+{
+ struct r820t_priv *priv = fe->tuner_priv;
+ return &priv->hdl;
+}
+EXPORT_SYMBOL(r820t_get_ctrl_handler);
+
struct dvb_frontend *r820t_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
const struct r820t_config *cfg)
@@ -2352,6 +2424,8 @@ struct dvb_frontend *r820t_attach(struct dvb_frontend *fe,
break;
}
+ priv->fe = fe;
+
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
@@ -2364,6 +2438,29 @@ struct dvb_frontend *r820t_attach(struct dvb_frontend *fe,
if (rc < 0)
goto err;
+ /* Register controls */
+ v4l2_ctrl_handler_init(&priv->hdl, 6);
+ priv->lna_gain_auto = v4l2_ctrl_new_std(&priv->hdl, &r820t_ctrl_ops,
+ V4L2_CID_LNA_GAIN_AUTO, 0, 1, 1, 1);
+ priv->lna_gain = v4l2_ctrl_new_std(&priv->hdl, &r820t_ctrl_ops,
+ V4L2_CID_LNA_GAIN, 0, 15, 1, 6);
+ v4l2_ctrl_auto_cluster(2, &priv->lna_gain_auto, 0, false);
+ priv->mixer_gain_auto = v4l2_ctrl_new_std(&priv->hdl, &r820t_ctrl_ops,
+ V4L2_CID_MIXER_GAIN_AUTO, 0, 1, 1, 1);
+ priv->mixer_gain = v4l2_ctrl_new_std(&priv->hdl, &r820t_ctrl_ops,
+ V4L2_CID_MIXER_GAIN, 0, 15, 1, 5);
+ v4l2_ctrl_auto_cluster(2, &priv->mixer_gain_auto, 0, false);
+ priv->if_gain_auto = v4l2_ctrl_new_std(&priv->hdl, &r820t_ctrl_ops,
+ V4L2_CID_IF_GAIN_AUTO, 0, 1, 1, 1);
+ priv->if_gain = v4l2_ctrl_new_std(&priv->hdl, &r820t_ctrl_ops,
+ V4L2_CID_IF_GAIN, 0, 15, 1, 4);
+ v4l2_ctrl_auto_cluster(2, &priv->if_gain_auto, 0, false);
+ if (priv->hdl.error) {
+ rc = priv->hdl.error;
+ tuner_info("Could not initialize controls\n");
+ goto err;
+ }
+
tuner_info("Rafael Micro r820t successfully identified\n");
if (fe->ops.i2c_gate_ctrl)
diff --git a/drivers/media/tuners/r820t.h b/drivers/media/tuners/r820t.h
index 42c0d8e..b61d6ea 100644
--- a/drivers/media/tuners/r820t.h
+++ b/drivers/media/tuners/r820t.h
@@ -42,17 +42,13 @@ struct r820t_config {
bool use_predetect;
};
-/* set INT_MIN for automode */
-struct r820t_ctrl {
- int lna_gain;
- int mixer_gain;
- int if_gain;
-};
-
#if IS_ENABLED(CONFIG_MEDIA_TUNER_R820T)
struct dvb_frontend *r820t_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
const struct r820t_config *cfg);
+
+extern struct v4l2_ctrl_handler *r820t_get_ctrl_handler(
+ struct dvb_frontend *fe);
#else
static inline struct dvb_frontend *r820t_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
@@ -61,6 +57,13 @@ static inline struct dvb_frontend *r820t_attach(struct dvb_frontend *fe,
pr_warn("%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
+
+static inline struct v4l2_ctrl_handler *r820t_get_ctrl_handler(
+ struct dvb_frontend *fe)
+{
+ pr_warn("%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
#endif
#endif
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index e89abd8..0d96aea 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -145,12 +145,6 @@ struct rtl2832_sdr_state {
struct v4l2_ctrl_handler hdl;
struct v4l2_ctrl *bandwidth_auto;
struct v4l2_ctrl *bandwidth;
- 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_auto;
- struct v4l2_ctrl *if_gain;
/* for sample rate calc */
unsigned int sample;
@@ -918,51 +912,12 @@ err:
return;
};
-static int rtl2832_sdr_set_gain_r820t(struct rtl2832_sdr_state *s)
-{
- int ret;
- struct dvb_frontend *fe = s->fe;
- struct r820t_ctrl ctrl;
- dev_dbg(&s->udev->dev, "%s: lna=%d mixer=%d if=%d\n", __func__,
- s->lna_gain->val, s->mixer_gain->val, s->if_gain->val);
-
- ctrl.lna_gain = s->lna_gain_auto->val ? INT_MIN : s->lna_gain->val;
- ctrl.mixer_gain = s->mixer_gain_auto->val ? INT_MIN : s->mixer_gain->val;
- ctrl.if_gain = s->if_gain_auto->val ? INT_MIN : s->if_gain->val;
-
- if (fe->ops.tuner_ops.set_config) {
- ret = fe->ops.tuner_ops.set_config(fe, &ctrl);
- if (ret)
- goto err;
- }
-
- return 0;
-err:
- dev_dbg(&s->udev->dev, "%s: failed %d\n", __func__, ret);
- return ret;
-};
-
-static int rtl2832_sdr_set_gain(struct rtl2832_sdr_state *s)
-{
- int ret;
-
- switch (s->cfg->tuner) {
- case RTL2832_TUNER_R820T:
- ret = rtl2832_sdr_set_gain_r820t(s);
- break;
- default:
- ret = 0;
- }
- return ret;
-}
-
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;
struct v4l2_ctrl *bandwidth_auto;
struct v4l2_ctrl *bandwidth;
- int ret;
/*
* tuner RF (Hz)
@@ -997,8 +952,6 @@ static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s)
if (fe->ops.tuner_ops.set_params)
fe->ops.tuner_ops.set_params(fe);
- ret = rtl2832_sdr_set_gain(s);
-
return 0;
};
@@ -1202,7 +1155,7 @@ static int rtl2832_sdr_s_frequency(struct file *file, void *priv,
__func__, f->frequency);
ret = rtl2832_sdr_set_tuner(s);
} else {
- return -EINVAL;
+ ret = -EINVAL;
}
return ret;
@@ -1353,15 +1306,6 @@ static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl)
else
ret = 0;
break;
- case V4L2_CID_LNA_GAIN_AUTO:
- case V4L2_CID_LNA_GAIN:
- case V4L2_CID_MIXER_GAIN_AUTO:
- case V4L2_CID_MIXER_GAIN:
- case V4L2_CID_IF_GAIN_AUTO:
- case V4L2_CID_IF_GAIN:
- dev_dbg(&s->udev->dev, "%s: GAIN IOCTL\n", __func__);
- ret = rtl2832_sdr_set_gain(s);
- break;
default:
ret = -EINVAL;
}
@@ -1436,19 +1380,13 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
v4l2_ctrl_add_handler(&s->hdl, hdl, NULL);
break;
case RTL2832_TUNER_R820T:
- v4l2_ctrl_handler_init(&s->hdl, 8);
+ v4l2_ctrl_handler_init(&s->hdl, 2);
s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_BANDWIDTH_AUTO, 0, 1, 1, 1);
s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_BANDWIDTH, 0, 8000000, 100000, 0);
v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false);
- s->lna_gain_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_LNA_GAIN_AUTO, 0, 1, 1, 1);
- s->lna_gain = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_LNA_GAIN, 0, 15, 1, 6);
- v4l2_ctrl_auto_cluster(2, &s->lna_gain_auto, 0, false);
- s->mixer_gain_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_MIXER_GAIN_AUTO, 0, 1, 1, 1);
- s->mixer_gain = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_MIXER_GAIN, 0, 15, 1, 5);
- v4l2_ctrl_auto_cluster(2, &s->mixer_gain_auto, 0, false);
- s->if_gain_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_IF_GAIN_AUTO, 0, 1, 1, 1);
- s->if_gain = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_IF_GAIN, 0, 15, 1, 4);
- v4l2_ctrl_auto_cluster(2, &s->if_gain_auto, 0, false);
+ hdl = r820t_get_ctrl_handler(fe);
+ if (hdl)
+ v4l2_ctrl_add_handler(&s->hdl, hdl, NULL);
break;
case RTL2832_TUNER_FC0012:
case RTL2832_TUNER_FC0013:
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 76/86] v4l: add control for RF tuner PLL lock flag
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (74 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 75/86] r820t/rtl2832u_sdr: implement gains using v4l2 controls Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 77/86] e4000: implement PLL lock v4l control Antti Palosaari
` (11 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari, Mauro Carvalho Chehab, Hans Verkuil
Add volatile boolean control to indicate if tuner frequency synthesizer
is locked to requested frequency. That means tuner is able to receive
given frequency. Control is named as "PLL lock", since frequency
synthesizers are based of phase-locked-loop. Maybe more general name
could be wise still?
Cc: Mauro Carvalho Chehab <m.chehab@samsung.com>
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/v4l2-core/v4l2-ctrls.c | 5 +++++
include/uapi/linux/v4l2-controls.h | 1 +
2 files changed, 6 insertions(+)
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index e44722b..dc6cba4 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -867,6 +867,7 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_IF_GAIN: return "IF Gain";
case V4L2_CID_BANDWIDTH_AUTO: return "Channel Bandwidth, Auto";
case V4L2_CID_BANDWIDTH: return "Channel Bandwidth";
+ case V4L2_CID_PLL_LOCK: return "PLL Lock";
default:
return NULL;
}
@@ -920,6 +921,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_MIXER_GAIN_AUTO:
case V4L2_CID_IF_GAIN_AUTO:
case V4L2_CID_BANDWIDTH_AUTO:
+ case V4L2_CID_PLL_LOCK:
*type = V4L2_CTRL_TYPE_BOOLEAN;
*min = 0;
*max = *step = 1;
@@ -1100,6 +1102,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_DV_RX_POWER_PRESENT:
*flags |= V4L2_CTRL_FLAG_READ_ONLY;
break;
+ case V4L2_CID_PLL_LOCK:
+ *flags |= V4L2_CTRL_FLAG_VOLATILE;
+ break;
}
}
EXPORT_SYMBOL(v4l2_ctrl_fill);
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index cc488c3..06918c9 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -907,5 +907,6 @@ enum v4l2_deemphasis {
#define V4L2_CID_MIXER_GAIN (V4L2_CID_RF_TUNER_CLASS_BASE + 52)
#define V4L2_CID_IF_GAIN_AUTO (V4L2_CID_RF_TUNER_CLASS_BASE + 61)
#define V4L2_CID_IF_GAIN (V4L2_CID_RF_TUNER_CLASS_BASE + 62)
+#define V4L2_CID_PLL_LOCK (V4L2_CID_RF_TUNER_CLASS_BASE + 91)
#endif
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 77/86] e4000: implement PLL lock v4l control
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (75 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 76/86] v4l: add control for RF tuner PLL lock flag Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 78/86] DocBook: media: document PLL lock control Antti Palosaari
` (10 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari, Mauro Carvalho Chehab, Hans Verkuil
Implement PLL lock control to get PLL lock flag status from tuner
synthesizer.
Cc: Mauro Carvalho Chehab <m.chehab@samsung.com>
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/tuners/e4000.c | 53 ++++++++++++++++++++++++++++++++++++++-
drivers/media/tuners/e4000_priv.h | 2 ++
2 files changed, 54 insertions(+), 1 deletion(-)
diff --git a/drivers/media/tuners/e4000.c b/drivers/media/tuners/e4000.c
index 019dc62..662e19a1 100644
--- a/drivers/media/tuners/e4000.c
+++ b/drivers/media/tuners/e4000.c
@@ -181,6 +181,8 @@ static int e4000_init(struct dvb_frontend *fe)
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
+ priv->active = true;
+
return 0;
err:
if (fe->ops.i2c_gate_ctrl)
@@ -197,6 +199,8 @@ static int e4000_sleep(struct dvb_frontend *fe)
dev_dbg(&priv->client->dev, "%s:\n", __func__);
+ priv->active = false;
+
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
@@ -512,6 +516,50 @@ err:
return ret;
}
+static int e4000_pll_lock(struct dvb_frontend *fe)
+{
+ struct e4000_priv *priv = fe->tuner_priv;
+ int ret;
+ u8 u8tmp;
+
+ if (priv->active == false)
+ return 0;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ ret = e4000_rd_reg(priv, 0x07, &u8tmp);
+ if (ret)
+ goto err;
+
+ priv->pll_lock->val = (u8tmp & 0x01);
+err:
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ if (ret)
+ dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static int e4000_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct e4000_priv *priv =
+ container_of(ctrl->handler, struct e4000_priv, hdl);
+ int ret;
+
+ switch (ctrl->id) {
+ case V4L2_CID_PLL_LOCK:
+ ret = e4000_pll_lock(priv->fe);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
static int e4000_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct e4000_priv *priv =
@@ -550,6 +598,7 @@ static int e4000_s_ctrl(struct v4l2_ctrl *ctrl)
}
static const struct v4l2_ctrl_ops e4000_ctrl_ops = {
+ .g_volatile_ctrl = e4000_g_volatile_ctrl,
.s_ctrl = e4000_s_ctrl,
};
@@ -616,7 +665,7 @@ static int e4000_probe(struct i2c_client *client,
goto err;
/* Register controls */
- v4l2_ctrl_handler_init(&priv->hdl, 8);
+ v4l2_ctrl_handler_init(&priv->hdl, 9);
priv->bandwidth_auto = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
V4L2_CID_BANDWIDTH_AUTO, 0, 1, 1, 1);
priv->bandwidth = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
@@ -637,6 +686,8 @@ static int e4000_probe(struct i2c_client *client,
priv->if_gain = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
V4L2_CID_IF_GAIN, 0, 54, 1, 0);
v4l2_ctrl_auto_cluster(2, &priv->if_gain_auto, 0, false);
+ priv->pll_lock = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+ V4L2_CID_PLL_LOCK, 0, 1, 1, 0);
if (priv->hdl.error) {
ret = priv->hdl.error;
dev_err(&priv->client->dev, "Could not initialize controls\n");
diff --git a/drivers/media/tuners/e4000_priv.h b/drivers/media/tuners/e4000_priv.h
index 8cc27b3..d41dbcc 100644
--- a/drivers/media/tuners/e4000_priv.h
+++ b/drivers/media/tuners/e4000_priv.h
@@ -28,6 +28,7 @@ struct e4000_priv {
struct i2c_client *client;
u32 clock;
struct dvb_frontend *fe;
+ bool active;
/* Controls */
struct v4l2_ctrl_handler hdl;
@@ -39,6 +40,7 @@ struct e4000_priv {
struct v4l2_ctrl *mixer_gain;
struct v4l2_ctrl *if_gain_auto;
struct v4l2_ctrl *if_gain;
+ struct v4l2_ctrl *pll_lock;
};
struct e4000_pll {
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 78/86] DocBook: media: document PLL lock control
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (76 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 77/86] e4000: implement PLL lock v4l control Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 79/86] rtl2832: provide muxed I2C adapter Antti Palosaari
` (9 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari, Mauro Carvalho Chehab, Hans Verkuil
Document PLL lock V4L2 control. It is read only RF tuner control
which is used to inform if tuner is receiving frequency or not.
Cc: Mauro Carvalho Chehab <m.chehab@samsung.com>
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
Documentation/DocBook/media/v4l/controls.xml | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index 345b6e5..e6d4b50 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -5077,6 +5077,15 @@ intermediate frequency output or baseband output. Used when
<constant>V4L2_CID_IF_GAIN_AUTO</constant> is not set. The range and step are
driver-specific.</entry>
</row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_PLL_LOCK</constant> </entry>
+ <entry>boolean</entry>
+ </row>
+ <row>
+ <entry spanname="descr">Is synthesizer PLL locked? RF tuner is
+receiving given frequency when that control is set. This is a read-only control.
+</entry>
+ </row>
</tbody>
</tgroup>
</table>
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 79/86] rtl2832: provide muxed I2C adapter
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (77 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 78/86] DocBook: media: document PLL lock control Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 80/86] rtl2832: add muxed I2C adapter for demod itself Antti Palosaari
` (8 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
RTL2832 provides gated / repeater I2C adapter for tuner.
Implement it as a muxed I2C adapter.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/dvb-frontends/Kconfig | 2 +-
drivers/media/dvb-frontends/rtl2832.c | 26 ++++++++++++++++++++++++++
drivers/media/dvb-frontends/rtl2832.h | 13 +++++++++++++
drivers/media/dvb-frontends/rtl2832_priv.h | 2 ++
4 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index dd12a1e..d701488 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -441,7 +441,7 @@ config DVB_RTL2830
config DVB_RTL2832
tristate "Realtek RTL2832 DVB-T"
- depends on DVB_CORE && I2C
+ depends on DVB_CORE && I2C && I2C_MUX
default m if !MEDIA_SUBDRV_AUTOSELECT
help
Say Y when you want to support this frontend.
diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c
index 00e63b9..dc46cf0 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -891,9 +891,29 @@ static void rtl2832_release(struct dvb_frontend *fe)
struct rtl2832_priv *priv = fe->demodulator_priv;
dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+ i2c_del_mux_adapter(priv->i2c_adapter);
kfree(priv);
}
+static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan)
+{
+ struct rtl2832_priv *priv = mux_priv;
+ return rtl2832_i2c_gate_ctrl(&priv->fe, 1);
+}
+
+static int rtl2832_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan)
+{
+ struct rtl2832_priv *priv = mux_priv;
+ return rtl2832_i2c_gate_ctrl(&priv->fe, 0);
+}
+
+struct i2c_adapter *rtl2832_get_i2c_adapter(struct dvb_frontend *fe)
+{
+ struct rtl2832_priv *priv = fe->demodulator_priv;
+ return priv->i2c_adapter;
+}
+EXPORT_SYMBOL(rtl2832_get_i2c_adapter);
+
struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
struct i2c_adapter *i2c)
{
@@ -918,6 +938,12 @@ struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
if (ret)
goto err;
+ /* create muxed i2c adapter */
+ priv->i2c_adapter = i2c_add_mux_adapter(i2c, &i2c->dev, priv, 0, 0, 0,
+ rtl2832_select, rtl2832_deselect);
+ if (priv->i2c_adapter == NULL)
+ goto err;
+
/* create dvb_frontend */
memcpy(&priv->fe.ops, &rtl2832_ops, sizeof(struct dvb_frontend_ops));
priv->fe.demodulator_priv = priv;
diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h
index fa4e5f6..a9202d7 100644
--- a/drivers/media/dvb-frontends/rtl2832.h
+++ b/drivers/media/dvb-frontends/rtl2832.h
@@ -55,7 +55,13 @@ struct dvb_frontend *rtl2832_attach(
const struct rtl2832_config *cfg,
struct i2c_adapter *i2c
);
+
+extern struct i2c_adapter *rtl2832_get_i2c_adapter(
+ struct dvb_frontend *fe
+);
+
#else
+
static inline struct dvb_frontend *rtl2832_attach(
const struct rtl2832_config *config,
struct i2c_adapter *i2c
@@ -64,6 +70,13 @@ static inline struct dvb_frontend *rtl2832_attach(
pr_warn("%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
+
+static inline struct i2c_adapter *rtl2832_get_i2c_adapter(
+ struct dvb_frontend *fe
+)
+{
+ return NULL;
+}
#endif
diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h
index 4c845af..ec26c92 100644
--- a/drivers/media/dvb-frontends/rtl2832_priv.h
+++ b/drivers/media/dvb-frontends/rtl2832_priv.h
@@ -23,9 +23,11 @@
#include "dvb_frontend.h"
#include "rtl2832.h"
+#include <linux/i2c-mux.h>
struct rtl2832_priv {
struct i2c_adapter *i2c;
+ struct i2c_adapter *i2c_adapter;
struct dvb_frontend fe;
struct rtl2832_config cfg;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 80/86] rtl2832: add muxed I2C adapter for demod itself
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (78 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 79/86] rtl2832: provide muxed I2C adapter Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 81/86] rtl2832: Fix deadlock on i2c mux select function Antti Palosaari
` (7 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
There was a deadlock between master I2C adapter and muxed I2C
adapter. Implement two I2C muxed I2C adapters and leave master
alone, just only for offering I2C adapter for these mux adapters.
Reported-by: Luis Alves <ljalvs@gmail.com>
Reported-by: Benjamin Larsson <benjamin@southpole.se>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/dvb-frontends/rtl2832.c | 71 ++++++++++++++++++++++++------
drivers/media/dvb-frontends/rtl2832_priv.h | 1 +
2 files changed, 58 insertions(+), 14 deletions(-)
diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c
index dc46cf0..c0366a8 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -180,7 +180,7 @@ static int rtl2832_wr(struct rtl2832_priv *priv, u8 reg, u8 *val, int len)
buf[0] = reg;
memcpy(&buf[1], val, len);
- ret = i2c_transfer(priv->i2c, msg, 1);
+ ret = i2c_transfer(priv->i2c_adapter, msg, 1);
if (ret == 1) {
ret = 0;
} else {
@@ -210,7 +210,7 @@ static int rtl2832_rd(struct rtl2832_priv *priv, u8 reg, u8 *val, int len)
}
};
- ret = i2c_transfer(priv->i2c, msg, 2);
+ ret = i2c_transfer(priv->i2c_adapter, msg, 2);
if (ret == 2) {
ret = 0;
} else {
@@ -891,26 +891,61 @@ static void rtl2832_release(struct dvb_frontend *fe)
struct rtl2832_priv *priv = fe->demodulator_priv;
dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+ i2c_del_mux_adapter(priv->i2c_adapter_tuner);
i2c_del_mux_adapter(priv->i2c_adapter);
kfree(priv);
}
-static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan)
+static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
{
struct rtl2832_priv *priv = mux_priv;
- return rtl2832_i2c_gate_ctrl(&priv->fe, 1);
-}
+ int ret;
+ u8 buf[2];
+ struct i2c_msg msg[1] = {
+ {
+ .addr = priv->cfg.i2c_addr,
+ .flags = 0,
+ .len = sizeof(buf),
+ .buf = buf,
+ }
+ };
-static int rtl2832_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan)
-{
- struct rtl2832_priv *priv = mux_priv;
- return rtl2832_i2c_gate_ctrl(&priv->fe, 0);
+ if (priv->i2c_gate_state == chan_id)
+ return 0;
+
+ /* select reg bank 1 */
+ buf[0] = 0x00;
+ buf[1] = 0x01;
+
+ ret = i2c_transfer(adap, msg, 1);
+ if (ret != 1)
+ goto err;
+
+ priv->page = 1;
+
+ /* open or close I2C repeater gate */
+ buf[0] = 0x01;
+ if (chan_id == 1)
+ buf[1] = 0x18; /* open */
+ else
+ buf[1] = 0x10; /* close */
+
+ ret = i2c_transfer(adap, msg, 1);
+ if (ret != 1)
+ goto err;
+
+ priv->i2c_gate_state = chan_id;
+
+ return 0;
+err:
+ dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+ return -EREMOTEIO;
}
struct i2c_adapter *rtl2832_get_i2c_adapter(struct dvb_frontend *fe)
{
struct rtl2832_priv *priv = fe->demodulator_priv;
- return priv->i2c_adapter;
+ return priv->i2c_adapter_tuner;
}
EXPORT_SYMBOL(rtl2832_get_i2c_adapter);
@@ -933,15 +968,21 @@ struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
priv->tuner = cfg->tuner;
memcpy(&priv->cfg, cfg, sizeof(struct rtl2832_config));
+ /* create muxed i2c adapter for demod itself */
+ priv->i2c_adapter = i2c_add_mux_adapter(i2c, &i2c->dev, priv, 0, 0, 0,
+ rtl2832_select, NULL);
+ if (priv->i2c_adapter == NULL)
+ goto err;
+
/* check if the demod is there */
ret = rtl2832_rd_reg(priv, 0x00, 0x0, &tmp);
if (ret)
goto err;
- /* create muxed i2c adapter */
- priv->i2c_adapter = i2c_add_mux_adapter(i2c, &i2c->dev, priv, 0, 0, 0,
- rtl2832_select, rtl2832_deselect);
- if (priv->i2c_adapter == NULL)
+ /* create muxed i2c adapter for demod tuner bus */
+ priv->i2c_adapter_tuner = i2c_add_mux_adapter(i2c, &i2c->dev, priv,
+ 0, 1, 0, rtl2832_select, NULL);
+ if (priv->i2c_adapter_tuner == NULL)
goto err;
/* create dvb_frontend */
@@ -954,6 +995,8 @@ struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
return &priv->fe;
err:
dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
+ if (priv && priv->i2c_adapter)
+ i2c_del_mux_adapter(priv->i2c_adapter);
kfree(priv);
return NULL;
}
diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h
index ec26c92..8b7c1ae 100644
--- a/drivers/media/dvb-frontends/rtl2832_priv.h
+++ b/drivers/media/dvb-frontends/rtl2832_priv.h
@@ -28,6 +28,7 @@
struct rtl2832_priv {
struct i2c_adapter *i2c;
struct i2c_adapter *i2c_adapter;
+ struct i2c_adapter *i2c_adapter_tuner;
struct dvb_frontend fe;
struct rtl2832_config cfg;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 81/86] rtl2832: Fix deadlock on i2c mux select function.
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (79 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 80/86] rtl2832: add muxed I2C adapter for demod itself Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 82/86] rtl2832: implement delayed I2C gate close Antti Palosaari
` (6 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Luis Alves, Antti Palosaari
From: Luis Alves <ljalvs@gmail.com>
Signed-off-by: Luis Alves <ljalvs@gmail.com>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/dvb-frontends/rtl2832.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c
index c0366a8..cfc5438 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -917,7 +917,7 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
buf[0] = 0x00;
buf[1] = 0x01;
- ret = i2c_transfer(adap, msg, 1);
+ ret = __i2c_transfer(adap, msg, 1);
if (ret != 1)
goto err;
@@ -930,7 +930,7 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
else
buf[1] = 0x10; /* close */
- ret = i2c_transfer(adap, msg, 1);
+ ret = __i2c_transfer(adap, msg, 1);
if (ret != 1)
goto err;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 82/86] rtl2832: implement delayed I2C gate close
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (80 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 81/86] rtl2832: Fix deadlock on i2c mux select function Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 83/86] rtl28xxu: use muxed RTL2832 I2C adapters for E4000 and RTL2832_SDR Antti Palosaari
` (5 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Delay possible I2C gate close a little bit in order to see if there
is next message coming to tuner in a sequence.
Also, export private muxed I2C adapter. That is aimed only for SDR
extension module as SDR belongs to same RTL2832 physical I2C bus (it
is physically property of RTL2832, whilst it is own kernel module).
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/dvb-frontends/rtl2832.c | 92 +++++++++++++++++++++++++++++-
drivers/media/dvb-frontends/rtl2832.h | 12 ++++
drivers/media/dvb-frontends/rtl2832_priv.h | 1 +
3 files changed, 102 insertions(+), 3 deletions(-)
diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c
index cfc5438..fdbed35 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -891,16 +891,65 @@ static void rtl2832_release(struct dvb_frontend *fe)
struct rtl2832_priv *priv = fe->demodulator_priv;
dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+ cancel_delayed_work_sync(&priv->i2c_gate_work);
i2c_del_mux_adapter(priv->i2c_adapter_tuner);
i2c_del_mux_adapter(priv->i2c_adapter);
kfree(priv);
}
+/*
+ * Delay mechanism to avoid unneeded I2C gate open / close. Gate close is
+ * delayed here a little bit in order to see if there is sequence of I2C
+ * messages sent to same I2C bus.
+ * We must use unlocked version of __i2c_transfer() in order to avoid deadlock
+ * as lock is already taken by calling muxed i2c_transfer().
+ */
+static void rtl2832_i2c_gate_work(struct work_struct *work)
+{
+ struct rtl2832_priv *priv = container_of(work,
+ struct rtl2832_priv, i2c_gate_work.work);
+ struct i2c_adapter *adap = priv->i2c;
+ int ret;
+ u8 buf[2];
+ struct i2c_msg msg[1] = {
+ {
+ .addr = priv->cfg.i2c_addr,
+ .flags = 0,
+ .len = sizeof(buf),
+ .buf = buf,
+ }
+ };
+
+ /* select reg bank 1 */
+ buf[0] = 0x00;
+ buf[1] = 0x01;
+ ret = __i2c_transfer(adap, msg, 1);
+ if (ret != 1)
+ goto err;
+
+ priv->page = 1;
+
+ /* close I2C repeater gate */
+ buf[0] = 0x01;
+ buf[1] = 0x10;
+ ret = __i2c_transfer(adap, msg, 1);
+ if (ret != 1)
+ goto err;
+
+ priv->i2c_gate_state = 0;
+
+ return;
+err:
+ dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+
+ return;
+}
+
static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
{
struct rtl2832_priv *priv = mux_priv;
int ret;
- u8 buf[2];
+ u8 buf[2], val;
struct i2c_msg msg[1] = {
{
.addr = priv->cfg.i2c_addr,
@@ -909,6 +958,22 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
.buf = buf,
}
};
+ struct i2c_msg msg_rd[2] = {
+ {
+ .addr = priv->cfg.i2c_addr,
+ .flags = 0,
+ .len = 1,
+ .buf = "\x01",
+ }, {
+ .addr = priv->cfg.i2c_addr,
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = &val,
+ }
+ };
+
+ /* terminate possible gate closing */
+ cancel_delayed_work_sync(&priv->i2c_gate_work);
if (priv->i2c_gate_state == chan_id)
return 0;
@@ -916,13 +981,17 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
/* select reg bank 1 */
buf[0] = 0x00;
buf[1] = 0x01;
-
ret = __i2c_transfer(adap, msg, 1);
if (ret != 1)
goto err;
priv->page = 1;
+ /* we must read that register, otherwise there will be errors */
+ ret = __i2c_transfer(adap, msg_rd, 2);
+ if (ret != 2)
+ goto err;
+
/* open or close I2C repeater gate */
buf[0] = 0x01;
if (chan_id == 1)
@@ -939,9 +1008,18 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
return 0;
err:
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+
return -EREMOTEIO;
}
+static int rtl2832_deselect(struct i2c_adapter *adap, void *mux_priv,
+ u32 chan_id)
+{
+ struct rtl2832_priv *priv = mux_priv;
+ schedule_delayed_work(&priv->i2c_gate_work, usecs_to_jiffies(100));
+ return 0;
+}
+
struct i2c_adapter *rtl2832_get_i2c_adapter(struct dvb_frontend *fe)
{
struct rtl2832_priv *priv = fe->demodulator_priv;
@@ -949,6 +1027,13 @@ struct i2c_adapter *rtl2832_get_i2c_adapter(struct dvb_frontend *fe)
}
EXPORT_SYMBOL(rtl2832_get_i2c_adapter);
+struct i2c_adapter *rtl2832_get_private_i2c_adapter(struct dvb_frontend *fe)
+{
+ struct rtl2832_priv *priv = fe->demodulator_priv;
+ return priv->i2c_adapter;
+}
+EXPORT_SYMBOL(rtl2832_get_private_i2c_adapter);
+
struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
struct i2c_adapter *i2c)
{
@@ -967,6 +1052,7 @@ struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
priv->i2c = i2c;
priv->tuner = cfg->tuner;
memcpy(&priv->cfg, cfg, sizeof(struct rtl2832_config));
+ INIT_DELAYED_WORK(&priv->i2c_gate_work, rtl2832_i2c_gate_work);
/* create muxed i2c adapter for demod itself */
priv->i2c_adapter = i2c_add_mux_adapter(i2c, &i2c->dev, priv, 0, 0, 0,
@@ -981,7 +1067,7 @@ struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
/* create muxed i2c adapter for demod tuner bus */
priv->i2c_adapter_tuner = i2c_add_mux_adapter(i2c, &i2c->dev, priv,
- 0, 1, 0, rtl2832_select, NULL);
+ 0, 1, 0, rtl2832_select, rtl2832_deselect);
if (priv->i2c_adapter_tuner == NULL)
goto err;
diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h
index a9202d7..cb3b6b0 100644
--- a/drivers/media/dvb-frontends/rtl2832.h
+++ b/drivers/media/dvb-frontends/rtl2832.h
@@ -60,6 +60,10 @@ extern struct i2c_adapter *rtl2832_get_i2c_adapter(
struct dvb_frontend *fe
);
+extern struct i2c_adapter *rtl2832_get_private_i2c_adapter(
+ struct dvb_frontend *fe
+);
+
#else
static inline struct dvb_frontend *rtl2832_attach(
@@ -77,6 +81,14 @@ static inline struct i2c_adapter *rtl2832_get_i2c_adapter(
{
return NULL;
}
+
+static inline struct i2c_adapter *rtl2832_get_private_i2c_adapter(
+ struct dvb_frontend *fe
+)
+{
+ return NULL;
+}
+
#endif
diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h
index 8b7c1ae..ae469f0 100644
--- a/drivers/media/dvb-frontends/rtl2832_priv.h
+++ b/drivers/media/dvb-frontends/rtl2832_priv.h
@@ -37,6 +37,7 @@ struct rtl2832_priv {
u8 tuner;
u8 page; /* active register page */
+ struct delayed_work i2c_gate_work;
};
struct rtl2832_reg_entry {
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 83/86] rtl28xxu: use muxed RTL2832 I2C adapters for E4000 and RTL2832_SDR
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (81 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 82/86] rtl2832: implement delayed I2C gate close Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 84/86] e4000: get rid of DVB i2c_gate_ctrl() Antti Palosaari
` (4 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
RTL2832 driver provides muxed I2C adapters for tuner bus I2C gate
control. Pass those adapters to rtl2832_sdr and e4000 modules in order
to get rid of proprietary DVB .i2c_gate_ctrl() callback use.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 12 ++++++++++--
drivers/media/usb/dvb-usb-v2/rtl28xxu.h | 1 +
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index afafe92..e04a3e9 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -774,6 +774,9 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
goto err;
}
+ /* RTL2832 I2C repeater */
+ priv->demod_i2c_adapter = rtl2832_get_i2c_adapter(adap->fe[0]);
+
/* set fe callback */
adap->fe[0]->callback = rtl2832u_frontend_callback;
@@ -920,6 +923,8 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
&rtl28xxu_rtl2832_fc0013_config);
break;
case TUNER_RTL2832_E4000: {
+ struct i2c_adapter *i2c_adap_internal =
+ rtl2832_get_private_i2c_adapter(adap->fe[0]);
struct e4000_config e4000_config = {
.fe = adap->fe[0],
.clock = 28800000,
@@ -930,11 +935,14 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
info.platform_data = &e4000_config;
request_module("e4000");
- priv->client = i2c_new_device(&d->i2c_adap, &info);
+ priv->client = i2c_new_device(priv->demod_i2c_adapter,
+ &info);
+
+ i2c_set_adapdata(i2c_adap_internal, d);
/* attach SDR */
dvb_attach(rtl2832_sdr_attach, adap->fe[0],
- &d->i2c_adap,
+ i2c_adap_internal,
&rtl28xxu_rtl2832_e4000_config);
}
break;
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
index 367aca1..a26cab1 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
@@ -55,6 +55,7 @@ struct rtl28xxu_priv {
u8 tuner;
char *tuner_name;
u8 page; /* integrated demod active register page */
+ struct i2c_adapter *demod_i2c_adapter;
bool rc_active;
struct i2c_client *client;
};
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 84/86] e4000: get rid of DVB i2c_gate_ctrl()
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (82 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 83/86] rtl28xxu: use muxed RTL2832 I2C adapters for E4000 and RTL2832_SDR Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 85/86] rtl2832_sdr: do not init tuner when only freq is changed Antti Palosaari
` (3 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Gate control is now implemented by rtl2832 I2C adapter so we do not
need proprietary DVB i2c_gate_ctrl() anymore.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/tuners/e4000.c | 106 +++++++++----------------------------------
1 file changed, 21 insertions(+), 85 deletions(-)
diff --git a/drivers/media/tuners/e4000.c b/drivers/media/tuners/e4000.c
index 662e19a1..e3e3b7e 100644
--- a/drivers/media/tuners/e4000.c
+++ b/drivers/media/tuners/e4000.c
@@ -119,9 +119,6 @@ static int e4000_init(struct dvb_frontend *fe)
dev_dbg(&priv->client->dev, "%s:\n", __func__);
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
-
/* dummy I2C to ensure I2C wakes up */
ret = e4000_wr_reg(priv, 0x02, 0x40);
@@ -178,17 +175,11 @@ static int e4000_init(struct dvb_frontend *fe)
if (ret < 0)
goto err;
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
-
priv->active = true;
-
- return 0;
err:
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
+ if (ret)
+ dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
- dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
@@ -201,22 +192,13 @@ static int e4000_sleep(struct dvb_frontend *fe)
priv->active = false;
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
-
ret = e4000_wr_reg(priv, 0x00, 0x00);
if (ret < 0)
goto err;
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
-
- return 0;
err:
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
+ if (ret)
+ dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
- dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
@@ -233,9 +215,6 @@ static int e4000_set_params(struct dvb_frontend *fe)
__func__, c->delivery_system, c->frequency,
c->bandwidth_hz);
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
-
/* gain control manual */
ret = e4000_wr_reg(priv, 0x1a, 0x00);
if (ret < 0)
@@ -361,16 +340,10 @@ static int e4000_set_params(struct dvb_frontend *fe)
ret = e4000_wr_reg(priv, 0x1a, 0x17);
if (ret < 0)
goto err;
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
-
- return 0;
err:
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
+ if (ret)
+ dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
- dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
@@ -390,14 +363,12 @@ static int e4000_set_lna_gain(struct dvb_frontend *fe)
struct e4000_priv *priv = fe->tuner_priv;
int ret;
u8 u8tmp;
+
dev_dbg(&priv->client->dev, "%s: lna auto=%d->%d val=%d->%d\n",
__func__, priv->lna_gain_auto->cur.val,
priv->lna_gain_auto->val, priv->lna_gain->cur.val,
priv->lna_gain->val);
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
-
if (priv->lna_gain_auto->val && priv->if_gain_auto->cur.val)
u8tmp = 0x17;
else if (priv->lna_gain_auto->val)
@@ -416,16 +387,10 @@ static int e4000_set_lna_gain(struct dvb_frontend *fe)
if (ret)
goto err;
}
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
-
- return 0;
err:
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
+ if (ret)
+ dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
- dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
@@ -434,14 +399,12 @@ static int e4000_set_mixer_gain(struct dvb_frontend *fe)
struct e4000_priv *priv = fe->tuner_priv;
int ret;
u8 u8tmp;
+
dev_dbg(&priv->client->dev, "%s: mixer auto=%d->%d val=%d->%d\n",
__func__, priv->mixer_gain_auto->cur.val,
priv->mixer_gain_auto->val, priv->mixer_gain->cur.val,
priv->mixer_gain->val);
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
-
if (priv->mixer_gain_auto->val)
u8tmp = 0x15;
else
@@ -456,16 +419,10 @@ static int e4000_set_mixer_gain(struct dvb_frontend *fe)
if (ret)
goto err;
}
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
-
- return 0;
err:
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
+ if (ret)
+ dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
- dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
@@ -475,14 +432,12 @@ static int e4000_set_if_gain(struct dvb_frontend *fe)
int ret;
u8 buf[2];
u8 u8tmp;
+
dev_dbg(&priv->client->dev, "%s: if auto=%d->%d val=%d->%d\n",
__func__, priv->if_gain_auto->cur.val,
priv->if_gain_auto->val, priv->if_gain->cur.val,
priv->if_gain->val);
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
-
if (priv->if_gain_auto->val && priv->lna_gain_auto->cur.val)
u8tmp = 0x17;
else if (priv->lna_gain_auto->cur.val)
@@ -503,16 +458,10 @@ static int e4000_set_if_gain(struct dvb_frontend *fe)
if (ret)
goto err;
}
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
-
- return 0;
err:
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
+ if (ret)
+ dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
- dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
@@ -525,18 +474,12 @@ static int e4000_pll_lock(struct dvb_frontend *fe)
if (priv->active == false)
return 0;
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
-
ret = e4000_rd_reg(priv, 0x07, &u8tmp);
if (ret)
goto err;
priv->pll_lock->val = (u8tmp & 0x01);
err:
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
-
if (ret)
dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
@@ -567,6 +510,7 @@ static int e4000_s_ctrl(struct v4l2_ctrl *ctrl)
struct dvb_frontend *fe = priv->fe;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
+
dev_dbg(&priv->client->dev,
"%s: id=%d name=%s val=%d min=%d max=%d step=%d\n",
__func__, ctrl->id, ctrl->name, ctrl->val,
@@ -632,9 +576,6 @@ static int e4000_probe(struct i2c_client *client,
int ret;
u8 chip_id;
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
-
priv = kzalloc(sizeof(struct e4000_priv), GFP_KERNEL);
if (!priv) {
ret = -ENOMEM;
@@ -702,19 +643,13 @@ static int e4000_probe(struct i2c_client *client,
fe->tuner_priv = priv;
memcpy(&fe->ops.tuner_ops, &e4000_tuner_ops,
sizeof(struct dvb_tuner_ops));
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
-
i2c_set_clientdata(client, priv);
-
- return 0;
err:
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
+ if (ret) {
+ dev_dbg(&client->dev, "%s: failed=%d\n", __func__, ret);
+ kfree(priv);
+ }
- dev_dbg(&client->dev, "%s: failed=%d\n", __func__, ret);
- kfree(priv);
return ret;
}
@@ -724,6 +659,7 @@ static int e4000_remove(struct i2c_client *client)
struct dvb_frontend *fe = priv->fe;
dev_dbg(&client->dev, "%s:\n", __func__);
+
v4l2_ctrl_handler_free(&priv->hdl);
memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
fe->tuner_priv = NULL;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 85/86] rtl2832_sdr: do not init tuner when only freq is changed
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (83 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 84/86] e4000: get rid of DVB i2c_gate_ctrl() Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 8:49 ` [REVIEW PATCH 86/86] e4000: convert to Regmap API Antti Palosaari
` (2 subsequent siblings)
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari
Initializing whole tuner every time when frequency is changed is wrong
and unnecessary. Init tuner only when streaming is started. Change
other parameters runtime.
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 25 +++++++++++++++++++-----
1 file changed, 20 insertions(+), 5 deletions(-)
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
index 0d96aea..cc554f7 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
@@ -912,7 +912,7 @@ err:
return;
};
-static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s)
+static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_state *s)
{
struct dvb_frontend *fe = s->fe;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -946,15 +946,24 @@ static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s)
if (!test_bit(POWER_ON, &s->flags))
return 0;
- if (fe->ops.tuner_ops.init)
- fe->ops.tuner_ops.init(fe);
-
if (fe->ops.tuner_ops.set_params)
fe->ops.tuner_ops.set_params(fe);
return 0;
};
+static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s)
+{
+ struct dvb_frontend *fe = s->fe;
+
+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+ if (fe->ops.tuner_ops.init)
+ fe->ops.tuner_ops.init(fe);
+
+ return 0;
+};
+
static void rtl2832_sdr_unset_tuner(struct rtl2832_sdr_state *s)
{
struct dvb_frontend *fe = s->fe;
@@ -988,6 +997,10 @@ static int rtl2832_sdr_start_streaming(struct vb2_queue *vq, unsigned int count)
if (ret)
goto err;
+ ret = rtl2832_sdr_set_tuner_freq(s);
+ if (ret)
+ goto err;
+
ret = rtl2832_sdr_set_adc(s);
if (ret)
goto err;
@@ -1127,6 +1140,7 @@ static int rtl2832_sdr_s_frequency(struct file *file, void *priv,
{
struct rtl2832_sdr_state *s = video_drvdata(file);
int ret, band;
+
dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n",
__func__, f->tuner, f->type, f->frequency);
@@ -1153,7 +1167,8 @@ static int rtl2832_sdr_s_frequency(struct file *file, void *priv,
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);
+
+ ret = rtl2832_sdr_set_tuner_freq(s);
} else {
ret = -EINVAL;
}
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* [REVIEW PATCH 86/86] e4000: convert to Regmap API
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (84 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 85/86] rtl2832_sdr: do not init tuner when only freq is changed Antti Palosaari
@ 2014-02-09 8:49 ` Antti Palosaari
2014-02-09 17:08 ` [REVIEW PATCH 00/86] SDR tree Anca Emanuel
2014-02-10 9:43 ` Hans Verkuil
87 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-09 8:49 UTC (permalink / raw)
To: linux-media; +Cc: Antti Palosaari, Mauro Carvalho Chehab, Hans Verkuil
That comes possible after driver was converted to kernel I2C model
(I2C binding & proper I2C client with no gate control hack). All
nasty low level I2C routines are now covered by regmap.
Also some variable renaming and minor functionality changes.
Cc: Mauro Carvalho Chehab <m.chehab@samsung.com>
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
drivers/media/tuners/Kconfig | 1 +
drivers/media/tuners/e4000.c | 442 ++++++++++++++++----------------------
drivers/media/tuners/e4000_priv.h | 4 +-
3 files changed, 184 insertions(+), 263 deletions(-)
diff --git a/drivers/media/tuners/Kconfig b/drivers/media/tuners/Kconfig
index ba2e365..a128488 100644
--- a/drivers/media/tuners/Kconfig
+++ b/drivers/media/tuners/Kconfig
@@ -204,6 +204,7 @@ config MEDIA_TUNER_TDA18212
config MEDIA_TUNER_E4000
tristate "Elonics E4000 silicon tuner"
depends on MEDIA_SUPPORT && I2C
+ select REGMAP_I2C
default m if !MEDIA_SUBDRV_AUTOSELECT
help
Elonics E4000 silicon tuner driver.
diff --git a/drivers/media/tuners/e4000.c b/drivers/media/tuners/e4000.c
index e3e3b7e..0d516ad 100644
--- a/drivers/media/tuners/e4000.c
+++ b/drivers/media/tuners/e4000.c
@@ -21,203 +21,112 @@
#include "e4000_priv.h"
#include <linux/math64.h>
-/* Max transfer size done by I2C transfer functions */
-#define MAX_XFER_SIZE 64
-
-/* write multiple registers */
-static int e4000_wr_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len)
-{
- int ret;
- u8 buf[MAX_XFER_SIZE];
- struct i2c_msg msg[1] = {
- {
- .addr = priv->client->addr,
- .flags = 0,
- .len = 1 + len,
- .buf = buf,
- }
- };
-
- if (1 + len > sizeof(buf)) {
- dev_warn(&priv->client->dev,
- "%s: i2c wr reg=%04x: len=%d is too big!\n",
- KBUILD_MODNAME, reg, len);
- return -EINVAL;
- }
-
- buf[0] = reg;
- memcpy(&buf[1], val, len);
-
- ret = i2c_transfer(priv->client->adapter, msg, 1);
- if (ret == 1) {
- ret = 0;
- } else {
- dev_warn(&priv->client->dev,
- "%s: i2c wr failed=%d reg=%02x len=%d\n",
- KBUILD_MODNAME, ret, reg, len);
- ret = -EREMOTEIO;
- }
- return ret;
-}
-
-/* read multiple registers */
-static int e4000_rd_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len)
-{
- int ret;
- u8 buf[MAX_XFER_SIZE];
- struct i2c_msg msg[2] = {
- {
- .addr = priv->client->addr,
- .flags = 0,
- .len = 1,
- .buf = ®,
- }, {
- .addr = priv->client->addr,
- .flags = I2C_M_RD,
- .len = len,
- .buf = buf,
- }
- };
-
- if (len > sizeof(buf)) {
- dev_warn(&priv->client->dev,
- "%s: i2c rd reg=%04x: len=%d is too big!\n",
- KBUILD_MODNAME, reg, len);
- return -EINVAL;
- }
-
- ret = i2c_transfer(priv->client->adapter, msg, 2);
- if (ret == 2) {
- memcpy(val, buf, len);
- ret = 0;
- } else {
- dev_warn(&priv->client->dev,
- "%s: i2c rd failed=%d reg=%02x len=%d\n",
- KBUILD_MODNAME, ret, reg, len);
- ret = -EREMOTEIO;
- }
-
- return ret;
-}
-
-/* write single register */
-static int e4000_wr_reg(struct e4000_priv *priv, u8 reg, u8 val)
-{
- return e4000_wr_regs(priv, reg, &val, 1);
-}
-
-/* read single register */
-static int e4000_rd_reg(struct e4000_priv *priv, u8 reg, u8 *val)
-{
- return e4000_rd_regs(priv, reg, val, 1);
-}
-
static int e4000_init(struct dvb_frontend *fe)
{
- struct e4000_priv *priv = fe->tuner_priv;
+ struct e4000 *s = fe->tuner_priv;
int ret;
- dev_dbg(&priv->client->dev, "%s:\n", __func__);
+ dev_dbg(&s->client->dev, "%s:\n", __func__);
/* dummy I2C to ensure I2C wakes up */
- ret = e4000_wr_reg(priv, 0x02, 0x40);
+ ret = regmap_write(s->regmap, 0x02, 0x40);
/* reset */
- ret = e4000_wr_reg(priv, 0x00, 0x01);
- if (ret < 0)
+ ret = regmap_write(s->regmap, 0x00, 0x01);
+ if (ret)
goto err;
/* disable output clock */
- ret = e4000_wr_reg(priv, 0x06, 0x00);
- if (ret < 0)
+ ret = regmap_write(s->regmap, 0x06, 0x00);
+ if (ret)
goto err;
- ret = e4000_wr_reg(priv, 0x7a, 0x96);
- if (ret < 0)
+ ret = regmap_write(s->regmap, 0x7a, 0x96);
+ if (ret)
goto err;
/* configure gains */
- ret = e4000_wr_regs(priv, 0x7e, "\x01\xfe", 2);
- if (ret < 0)
+ ret = regmap_bulk_write(s->regmap, 0x7e, "\x01\xfe", 2);
+ if (ret)
goto err;
- ret = e4000_wr_reg(priv, 0x82, 0x00);
- if (ret < 0)
+ ret = regmap_write(s->regmap, 0x82, 0x00);
+ if (ret)
goto err;
- ret = e4000_wr_reg(priv, 0x24, 0x05);
- if (ret < 0)
+ ret = regmap_write(s->regmap, 0x24, 0x05);
+ if (ret)
goto err;
- ret = e4000_wr_regs(priv, 0x87, "\x20\x01", 2);
- if (ret < 0)
+ ret = regmap_bulk_write(s->regmap, 0x87, "\x20\x01", 2);
+ if (ret)
goto err;
- ret = e4000_wr_regs(priv, 0x9f, "\x7f\x07", 2);
- if (ret < 0)
+ ret = regmap_bulk_write(s->regmap, 0x9f, "\x7f\x07", 2);
+ if (ret)
goto err;
/* DC offset control */
- ret = e4000_wr_reg(priv, 0x2d, 0x1f);
- if (ret < 0)
+ ret = regmap_write(s->regmap, 0x2d, 0x1f);
+ if (ret)
goto err;
- ret = e4000_wr_regs(priv, 0x70, "\x01\x01", 2);
- if (ret < 0)
+ ret = regmap_bulk_write(s->regmap, 0x70, "\x01\x01", 2);
+ if (ret)
goto err;
/* gain control */
- ret = e4000_wr_reg(priv, 0x1a, 0x17);
- if (ret < 0)
+ ret = regmap_write(s->regmap, 0x1a, 0x17);
+ if (ret)
goto err;
- ret = e4000_wr_reg(priv, 0x1f, 0x1a);
- if (ret < 0)
+ ret = regmap_write(s->regmap, 0x1f, 0x1a);
+ if (ret)
goto err;
- priv->active = true;
+ s->active = true;
err:
if (ret)
- dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
+ dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
static int e4000_sleep(struct dvb_frontend *fe)
{
- struct e4000_priv *priv = fe->tuner_priv;
+ struct e4000 *s = fe->tuner_priv;
int ret;
- dev_dbg(&priv->client->dev, "%s:\n", __func__);
+ dev_dbg(&s->client->dev, "%s:\n", __func__);
- priv->active = false;
+ s->active = false;
- ret = e4000_wr_reg(priv, 0x00, 0x00);
- if (ret < 0)
+ ret = regmap_write(s->regmap, 0x00, 0x00);
+ if (ret)
goto err;
err:
if (ret)
- dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
+ dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
static int e4000_set_params(struct dvb_frontend *fe)
{
- struct e4000_priv *priv = fe->tuner_priv;
+ struct e4000 *s = fe->tuner_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret, i, sigma_delta;
u64 f_vco;
u8 buf[5], i_data[4], q_data[4];
- dev_dbg(&priv->client->dev,
+ dev_dbg(&s->client->dev,
"%s: delivery_system=%d frequency=%u bandwidth_hz=%u\n",
__func__, c->delivery_system, c->frequency,
c->bandwidth_hz);
/* gain control manual */
- ret = e4000_wr_reg(priv, 0x1a, 0x00);
- if (ret < 0)
+ ret = regmap_write(s->regmap, 0x1a, 0x00);
+ if (ret)
goto err;
/* PLL */
@@ -232,19 +141,19 @@ static int e4000_set_params(struct dvb_frontend *fe)
}
f_vco = 1ull * c->frequency * e4000_pll_lut[i].mul;
- sigma_delta = div_u64(0x10000ULL * (f_vco % priv->clock), priv->clock);
- buf[0] = div_u64(f_vco, priv->clock);
+ sigma_delta = div_u64(0x10000ULL * (f_vco % s->clock), s->clock);
+ buf[0] = div_u64(f_vco, s->clock);
buf[1] = (sigma_delta >> 0) & 0xff;
buf[2] = (sigma_delta >> 8) & 0xff;
buf[3] = 0x00;
buf[4] = e4000_pll_lut[i].div;
- dev_dbg(&priv->client->dev,
+ dev_dbg(&s->client->dev,
"%s: f_vco=%llu pll div=%d sigma_delta=%04x\n",
__func__, f_vco, buf[0], sigma_delta);
- ret = e4000_wr_regs(priv, 0x09, buf, 5);
- if (ret < 0)
+ ret = regmap_bulk_write(s->regmap, 0x09, buf, 5);
+ if (ret)
goto err;
/* LNA filter (RF filter) */
@@ -258,8 +167,8 @@ static int e4000_set_params(struct dvb_frontend *fe)
goto err;
}
- ret = e4000_wr_reg(priv, 0x10, e400_lna_filter_lut[i].val);
- if (ret < 0)
+ ret = regmap_write(s->regmap, 0x10, e400_lna_filter_lut[i].val);
+ if (ret)
goto err;
/* IF filters */
@@ -276,8 +185,8 @@ static int e4000_set_params(struct dvb_frontend *fe)
buf[0] = e4000_if_filter_lut[i].reg11_val;
buf[1] = e4000_if_filter_lut[i].reg12_val;
- ret = e4000_wr_regs(priv, 0x11, buf, 2);
- if (ret < 0)
+ ret = regmap_bulk_write(s->regmap, 0x11, buf, 2);
+ if (ret)
goto err;
/* frequency band */
@@ -291,34 +200,34 @@ static int e4000_set_params(struct dvb_frontend *fe)
goto err;
}
- ret = e4000_wr_reg(priv, 0x07, e4000_band_lut[i].reg07_val);
- if (ret < 0)
+ ret = regmap_write(s->regmap, 0x07, e4000_band_lut[i].reg07_val);
+ if (ret)
goto err;
- ret = e4000_wr_reg(priv, 0x78, e4000_band_lut[i].reg78_val);
- if (ret < 0)
+ ret = regmap_write(s->regmap, 0x78, e4000_band_lut[i].reg78_val);
+ if (ret)
goto err;
/* DC offset */
for (i = 0; i < 4; i++) {
if (i == 0)
- ret = e4000_wr_regs(priv, 0x15, "\x00\x7e\x24", 3);
+ ret = regmap_bulk_write(s->regmap, 0x15, "\x00\x7e\x24", 3);
else if (i == 1)
- ret = e4000_wr_regs(priv, 0x15, "\x00\x7f", 2);
+ ret = regmap_bulk_write(s->regmap, 0x15, "\x00\x7f", 2);
else if (i == 2)
- ret = e4000_wr_regs(priv, 0x15, "\x01", 1);
+ ret = regmap_bulk_write(s->regmap, 0x15, "\x01", 1);
else
- ret = e4000_wr_regs(priv, 0x16, "\x7e", 1);
+ ret = regmap_bulk_write(s->regmap, 0x16, "\x7e", 1);
- if (ret < 0)
+ if (ret)
goto err;
- ret = e4000_wr_reg(priv, 0x29, 0x01);
- if (ret < 0)
+ ret = regmap_write(s->regmap, 0x29, 0x01);
+ if (ret)
goto err;
- ret = e4000_rd_regs(priv, 0x2a, buf, 3);
- if (ret < 0)
+ ret = regmap_bulk_read(s->regmap, 0x2a, buf, 3);
+ if (ret)
goto err;
i_data[i] = (((buf[2] >> 0) & 0x3) << 6) | (buf[0] & 0x3f);
@@ -328,30 +237,30 @@ static int e4000_set_params(struct dvb_frontend *fe)
swap(q_data[2], q_data[3]);
swap(i_data[2], i_data[3]);
- ret = e4000_wr_regs(priv, 0x50, q_data, 4);
- if (ret < 0)
+ ret = regmap_bulk_write(s->regmap, 0x50, q_data, 4);
+ if (ret)
goto err;
- ret = e4000_wr_regs(priv, 0x60, i_data, 4);
- if (ret < 0)
+ ret = regmap_bulk_write(s->regmap, 0x60, i_data, 4);
+ if (ret)
goto err;
/* gain control auto */
- ret = e4000_wr_reg(priv, 0x1a, 0x17);
- if (ret < 0)
+ ret = regmap_write(s->regmap, 0x1a, 0x17);
+ if (ret)
goto err;
err:
if (ret)
- dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
+ dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
static int e4000_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
{
- struct e4000_priv *priv = fe->tuner_priv;
+ struct e4000 *s = fe->tuner_priv;
- dev_dbg(&priv->client->dev, "%s:\n", __func__);
+ dev_dbg(&s->client->dev, "%s:\n", __func__);
*frequency = 0; /* Zero-IF */
@@ -360,143 +269,144 @@ static int e4000_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
static int e4000_set_lna_gain(struct dvb_frontend *fe)
{
- struct e4000_priv *priv = fe->tuner_priv;
+ struct e4000 *s = fe->tuner_priv;
int ret;
u8 u8tmp;
- dev_dbg(&priv->client->dev, "%s: lna auto=%d->%d val=%d->%d\n",
- __func__, priv->lna_gain_auto->cur.val,
- priv->lna_gain_auto->val, priv->lna_gain->cur.val,
- priv->lna_gain->val);
+ dev_dbg(&s->client->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);
- if (priv->lna_gain_auto->val && priv->if_gain_auto->cur.val)
+ if (s->lna_gain_auto->val && s->if_gain_auto->cur.val)
u8tmp = 0x17;
- else if (priv->lna_gain_auto->val)
+ else if (s->lna_gain_auto->val)
u8tmp = 0x19;
- else if (priv->if_gain_auto->cur.val)
+ else if (s->if_gain_auto->cur.val)
u8tmp = 0x16;
else
u8tmp = 0x10;
- ret = e4000_wr_reg(priv, 0x1a, u8tmp);
+ ret = regmap_write(s->regmap, 0x1a, u8tmp);
if (ret)
goto err;
- if (priv->lna_gain_auto->val == false) {
- ret = e4000_wr_reg(priv, 0x14, priv->lna_gain->val);
+ if (s->lna_gain_auto->val == false) {
+ ret = regmap_write(s->regmap, 0x14, s->lna_gain->val);
if (ret)
goto err;
}
err:
if (ret)
- dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
+ dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
static int e4000_set_mixer_gain(struct dvb_frontend *fe)
{
- struct e4000_priv *priv = fe->tuner_priv;
+ struct e4000 *s = fe->tuner_priv;
int ret;
u8 u8tmp;
- dev_dbg(&priv->client->dev, "%s: mixer auto=%d->%d val=%d->%d\n",
- __func__, priv->mixer_gain_auto->cur.val,
- priv->mixer_gain_auto->val, priv->mixer_gain->cur.val,
- priv->mixer_gain->val);
+ dev_dbg(&s->client->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);
- if (priv->mixer_gain_auto->val)
+ if (s->mixer_gain_auto->val)
u8tmp = 0x15;
else
u8tmp = 0x14;
- ret = e4000_wr_reg(priv, 0x20, u8tmp);
+ ret = regmap_write(s->regmap, 0x20, u8tmp);
if (ret)
goto err;
- if (priv->mixer_gain_auto->val == false) {
- ret = e4000_wr_reg(priv, 0x15, priv->mixer_gain->val);
+ if (s->mixer_gain_auto->val == false) {
+ ret = regmap_write(s->regmap, 0x15, s->mixer_gain->val);
if (ret)
goto err;
}
err:
if (ret)
- dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
+ dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
static int e4000_set_if_gain(struct dvb_frontend *fe)
{
- struct e4000_priv *priv = fe->tuner_priv;
+ struct e4000 *s = fe->tuner_priv;
int ret;
u8 buf[2];
u8 u8tmp;
- dev_dbg(&priv->client->dev, "%s: if auto=%d->%d val=%d->%d\n",
- __func__, priv->if_gain_auto->cur.val,
- priv->if_gain_auto->val, priv->if_gain->cur.val,
- priv->if_gain->val);
+ dev_dbg(&s->client->dev, "%s: if auto=%d->%d val=%d->%d\n",
+ __func__, s->if_gain_auto->cur.val,
+ s->if_gain_auto->val, s->if_gain->cur.val,
+ s->if_gain->val);
- if (priv->if_gain_auto->val && priv->lna_gain_auto->cur.val)
+ if (s->if_gain_auto->val && s->lna_gain_auto->cur.val)
u8tmp = 0x17;
- else if (priv->lna_gain_auto->cur.val)
+ else if (s->lna_gain_auto->cur.val)
u8tmp = 0x19;
- else if (priv->if_gain_auto->val)
+ else if (s->if_gain_auto->val)
u8tmp = 0x16;
else
u8tmp = 0x10;
- ret = e4000_wr_reg(priv, 0x1a, u8tmp);
+ ret = regmap_write(s->regmap, 0x1a, u8tmp);
if (ret)
goto err;
- if (priv->if_gain_auto->val == false) {
- buf[0] = e4000_if_gain_lut[priv->if_gain->val].reg16_val;
- buf[1] = e4000_if_gain_lut[priv->if_gain->val].reg17_val;
- ret = e4000_wr_regs(priv, 0x16, buf, 2);
+ if (s->if_gain_auto->val == false) {
+ buf[0] = e4000_if_gain_lut[s->if_gain->val].reg16_val;
+ buf[1] = e4000_if_gain_lut[s->if_gain->val].reg17_val;
+ ret = regmap_bulk_write(s->regmap, 0x16, buf, 2);
if (ret)
goto err;
}
err:
if (ret)
- dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
+ dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
static int e4000_pll_lock(struct dvb_frontend *fe)
{
- struct e4000_priv *priv = fe->tuner_priv;
+ struct e4000 *s = fe->tuner_priv;
int ret;
- u8 u8tmp;
-
- if (priv->active == false)
- return 0;
+ unsigned int utmp;
- ret = e4000_rd_reg(priv, 0x07, &u8tmp);
+ ret = regmap_read(s->regmap, 0x07, &utmp);
if (ret)
goto err;
- priv->pll_lock->val = (u8tmp & 0x01);
+ s->pll_lock->val = (utmp & 0x01);
err:
if (ret)
- dev_dbg(&priv->client->dev, "%s: failed=%d\n", __func__, ret);
+ dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
static int e4000_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
{
- struct e4000_priv *priv =
- container_of(ctrl->handler, struct e4000_priv, hdl);
+ struct e4000 *s = container_of(ctrl->handler, struct e4000, hdl);
int ret;
+ if (s->active == false)
+ return 0;
+
switch (ctrl->id) {
case V4L2_CID_PLL_LOCK:
- ret = e4000_pll_lock(priv->fe);
+ ret = e4000_pll_lock(s->fe);
break;
default:
+ dev_dbg(&s->client->dev, "%s: unknown ctrl: id=%d name=%s\n",
+ __func__, ctrl->id, ctrl->name);
ret = -EINVAL;
}
@@ -505,36 +415,35 @@ static int e4000_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
static int e4000_s_ctrl(struct v4l2_ctrl *ctrl)
{
- struct e4000_priv *priv =
- container_of(ctrl->handler, struct e4000_priv, hdl);
- struct dvb_frontend *fe = priv->fe;
+ struct e4000 *s = container_of(ctrl->handler, struct e4000, hdl);
+ struct dvb_frontend *fe = s->fe;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
- dev_dbg(&priv->client->dev,
- "%s: id=%d name=%s val=%d min=%d max=%d step=%d\n",
- __func__, ctrl->id, ctrl->name, ctrl->val,
- ctrl->minimum, ctrl->maximum, ctrl->step);
+ if (s->active == false)
+ return 0;
switch (ctrl->id) {
case V4L2_CID_BANDWIDTH_AUTO:
case V4L2_CID_BANDWIDTH:
- c->bandwidth_hz = priv->bandwidth->val;
- ret = e4000_set_params(priv->fe);
+ c->bandwidth_hz = s->bandwidth->val;
+ ret = e4000_set_params(s->fe);
break;
case V4L2_CID_LNA_GAIN_AUTO:
case V4L2_CID_LNA_GAIN:
- ret = e4000_set_lna_gain(priv->fe);
+ ret = e4000_set_lna_gain(s->fe);
break;
case V4L2_CID_MIXER_GAIN_AUTO:
case V4L2_CID_MIXER_GAIN:
- ret = e4000_set_mixer_gain(priv->fe);
+ ret = e4000_set_mixer_gain(s->fe);
break;
case V4L2_CID_IF_GAIN_AUTO:
case V4L2_CID_IF_GAIN:
- ret = e4000_set_if_gain(priv->fe);
+ ret = e4000_set_if_gain(s->fe);
break;
default:
+ dev_dbg(&s->client->dev, "%s: unknown ctrl: id=%d name=%s\n",
+ __func__, ctrl->id, ctrl->name);
ret = -EINVAL;
}
@@ -562,8 +471,8 @@ static const struct dvb_tuner_ops e4000_tuner_ops = {
struct v4l2_ctrl_handler *e4000_get_ctrl_handler(struct dvb_frontend *fe)
{
- struct e4000_priv *priv = fe->tuner_priv;
- return &priv->hdl;
+ struct e4000 *s = fe->tuner_priv;
+ return &s->hdl;
}
EXPORT_SYMBOL(e4000_get_ctrl_handler);
@@ -572,82 +481,91 @@ static int e4000_probe(struct i2c_client *client,
{
struct e4000_config *cfg = client->dev.platform_data;
struct dvb_frontend *fe = cfg->fe;
- struct e4000_priv *priv;
+ struct e4000 *s;
int ret;
- u8 chip_id;
+ unsigned int utmp;
+ static const struct regmap_config regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0xff,
+ };
- priv = kzalloc(sizeof(struct e4000_priv), GFP_KERNEL);
- if (!priv) {
+ s = kzalloc(sizeof(struct e4000), GFP_KERNEL);
+ if (!s) {
ret = -ENOMEM;
dev_err(&client->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME);
goto err;
}
- priv->clock = cfg->clock;
- priv->client = client;
- priv->fe = cfg->fe;
+ s->clock = cfg->clock;
+ s->client = client;
+ s->fe = cfg->fe;
+ s->regmap = devm_regmap_init_i2c(client, ®map_config);
+ if (IS_ERR(s->regmap)) {
+ ret = PTR_ERR(s->regmap);
+ goto err;
+ }
/* check if the tuner is there */
- ret = e4000_rd_reg(priv, 0x02, &chip_id);
- if (ret < 0)
+ ret = regmap_read(s->regmap, 0x02, &utmp);
+ if (ret)
goto err;
- dev_dbg(&priv->client->dev,
- "%s: chip_id=%02x\n", __func__, chip_id);
+ dev_dbg(&s->client->dev, "%s: chip id=%02x\n", __func__, utmp);
- if (chip_id != 0x40) {
+ if (utmp != 0x40) {
ret = -ENODEV;
goto err;
}
/* put sleep as chip seems to be in normal mode by default */
- ret = e4000_wr_reg(priv, 0x00, 0x00);
- if (ret < 0)
+ ret = regmap_write(s->regmap, 0x00, 0x00);
+ if (ret)
goto err;
/* Register controls */
- v4l2_ctrl_handler_init(&priv->hdl, 9);
- priv->bandwidth_auto = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+ v4l2_ctrl_handler_init(&s->hdl, 9);
+ s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, &e4000_ctrl_ops,
V4L2_CID_BANDWIDTH_AUTO, 0, 1, 1, 1);
- priv->bandwidth = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+ s->bandwidth = v4l2_ctrl_new_std(&s->hdl, &e4000_ctrl_ops,
V4L2_CID_BANDWIDTH, 4300000, 11000000, 100000, 4300000);
- v4l2_ctrl_auto_cluster(2, &priv->bandwidth_auto, 0, false);
- priv->lna_gain_auto = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+ v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false);
+ s->lna_gain_auto = v4l2_ctrl_new_std(&s->hdl, &e4000_ctrl_ops,
V4L2_CID_LNA_GAIN_AUTO, 0, 1, 1, 1);
- priv->lna_gain = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+ s->lna_gain = v4l2_ctrl_new_std(&s->hdl, &e4000_ctrl_ops,
V4L2_CID_LNA_GAIN, 0, 15, 1, 10);
- v4l2_ctrl_auto_cluster(2, &priv->lna_gain_auto, 0, false);
- priv->mixer_gain_auto = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+ v4l2_ctrl_auto_cluster(2, &s->lna_gain_auto, 0, false);
+ s->mixer_gain_auto = v4l2_ctrl_new_std(&s->hdl, &e4000_ctrl_ops,
V4L2_CID_MIXER_GAIN_AUTO, 0, 1, 1, 1);
- priv->mixer_gain = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+ s->mixer_gain = v4l2_ctrl_new_std(&s->hdl, &e4000_ctrl_ops,
V4L2_CID_MIXER_GAIN, 0, 1, 1, 1);
- v4l2_ctrl_auto_cluster(2, &priv->mixer_gain_auto, 0, false);
- priv->if_gain_auto = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+ v4l2_ctrl_auto_cluster(2, &s->mixer_gain_auto, 0, false);
+ s->if_gain_auto = v4l2_ctrl_new_std(&s->hdl, &e4000_ctrl_ops,
V4L2_CID_IF_GAIN_AUTO, 0, 1, 1, 1);
- priv->if_gain = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+ s->if_gain = v4l2_ctrl_new_std(&s->hdl, &e4000_ctrl_ops,
V4L2_CID_IF_GAIN, 0, 54, 1, 0);
- v4l2_ctrl_auto_cluster(2, &priv->if_gain_auto, 0, false);
- priv->pll_lock = v4l2_ctrl_new_std(&priv->hdl, &e4000_ctrl_ops,
+ v4l2_ctrl_auto_cluster(2, &s->if_gain_auto, 0, false);
+ s->pll_lock = v4l2_ctrl_new_std(&s->hdl, &e4000_ctrl_ops,
V4L2_CID_PLL_LOCK, 0, 1, 1, 0);
- if (priv->hdl.error) {
- ret = priv->hdl.error;
- dev_err(&priv->client->dev, "Could not initialize controls\n");
- v4l2_ctrl_handler_free(&priv->hdl);
+ if (s->hdl.error) {
+ ret = s->hdl.error;
+ dev_err(&s->client->dev, "Could not initialize controls\n");
+ v4l2_ctrl_handler_free(&s->hdl);
goto err;
}
- dev_info(&priv->client->dev,
+ dev_info(&s->client->dev,
"%s: Elonics E4000 successfully identified\n",
KBUILD_MODNAME);
- fe->tuner_priv = priv;
+ fe->tuner_priv = s;
memcpy(&fe->ops.tuner_ops, &e4000_tuner_ops,
sizeof(struct dvb_tuner_ops));
- i2c_set_clientdata(client, priv);
+ i2c_set_clientdata(client, s);
err:
if (ret) {
dev_dbg(&client->dev, "%s: failed=%d\n", __func__, ret);
- kfree(priv);
+ kfree(s);
}
return ret;
@@ -655,15 +573,15 @@ err:
static int e4000_remove(struct i2c_client *client)
{
- struct e4000_priv *priv = i2c_get_clientdata(client);
- struct dvb_frontend *fe = priv->fe;
+ struct e4000 *s = i2c_get_clientdata(client);
+ struct dvb_frontend *fe = s->fe;
dev_dbg(&client->dev, "%s:\n", __func__);
- v4l2_ctrl_handler_free(&priv->hdl);
+ v4l2_ctrl_handler_free(&s->hdl);
memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
fe->tuner_priv = NULL;
- kfree(priv);
+ kfree(s);
return 0;
}
diff --git a/drivers/media/tuners/e4000_priv.h b/drivers/media/tuners/e4000_priv.h
index d41dbcc..ee36de1 100644
--- a/drivers/media/tuners/e4000_priv.h
+++ b/drivers/media/tuners/e4000_priv.h
@@ -23,9 +23,11 @@
#include "e4000.h"
#include <media/v4l2-ctrls.h>
+#include <linux/regmap.h>
-struct e4000_priv {
+struct e4000 {
struct i2c_client *client;
+ struct regmap *regmap;
u32 clock;
struct dvb_frontend *fe;
bool active;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 91+ messages in thread* Re: [REVIEW PATCH 00/86] SDR tree
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (85 preceding siblings ...)
2014-02-09 8:49 ` [REVIEW PATCH 86/86] e4000: convert to Regmap API Antti Palosaari
@ 2014-02-09 17:08 ` Anca Emanuel
2014-02-10 9:43 ` Hans Verkuil
87 siblings, 0 replies; 91+ messages in thread
From: Anca Emanuel @ 2014-02-09 17:08 UTC (permalink / raw)
To: Antti Palosaari; +Cc: linux-media
On Sun, Feb 9, 2014 at 10:48 AM, Antti Palosaari <crope@iki.fi> wrote:
> That is everything I have on my SDR queue. There is drivers for Mirics
> MSi3101 and Realtek RTL2832U based devices. These drivers are still on
> staging and I am not going to move those out of staging very soon as I
> want get some experiments first.
>
> That set is available via Git:
> http://git.linuxtv.org/anttip/media_tree.git/shortlog/refs/heads/sdr_review
>
>
> Simplest way to test it in practice is listen FM radio using SDRSharp as a radio player.
> I made simple plug-in for that:
> https://github.com/palosaari/sdrsharp-v4l2
>
> That plug-in supports currently only on 64-bit Kernel...
>
>
> Installation is this simple (Fedora 20):
>
> $ sudo yum install mono-core monodevelop
> $ svn co https://subversion.assembla.com/svn/sdrsharp/trunk sdrsharp
> $ cd sdrsharp
> $ git clone https://github.com/palosaari/sdrsharp-v4l2.git V4L2
> $ sed -i 's/Format Version 12\.00/Format Version 11\.00/' SDRSharp.sln
>
> * Add following line to SDRSharp/App.config file inside frontendPlugins tag
> <add key="Linux Kernel V4L2" value="SDRSharp.V4L2.LibV4LIO,SDRSharp.V4L2" />
>
> $ monodevelop SDRSharp.sln
> * View > Default
> * Solution SDRSharp > Add > Add Existing Project... > V4L2 > SDRSharp.V4L2.csproj
> * Select Release|x86
> * Build > Build All
> * File > Quit
> $ mono Release/SDRSharp.exe
ok, you have the freedom to do an .exe
If that is what you want.
There is projects with graphical interface that can be used on linux,
mac and windows such as qt.
Example: subsurface.
please nuke mono, or any other Microsoft "technology".
be informed about the amount of money they make of suing Android.
>
>
> regards
> Antti
>
>
> Antti Palosaari (85):
> rtl2832_sdr: Realtek RTL2832 SDR driver module
> rtl28xxu: attach SDR extension module
> rtl2832_sdr: use config struct from rtl2832 module
> rtl2832_sdr: initial support for R820T tuner
> rtl2832_sdr: use get_if_frequency()
> rtl2832_sdr: implement sampling rate
> rtl2832_sdr: initial support for FC0012 tuner
> rtl2832_sdr: initial support for FC0013 tuner
> rtl28xxu: constify demod config structs
> rtl2832: remove unused if_dvbt config parameter
> rtl2832: style changes and minor cleanup
> rtl2832_sdr: pixel format for SDR
> rtl2832_sdr: implement FMT IOCTLs
> msi3101: add signed 8-bit pixel format for SDR
> msi3101: implement FMT IOCTLs
> msi3101: move format 384 conversion to libv4lconvert
> msi3101: move format 336 conversion to libv4lconvert
> msi3101: move format 252 conversion to libv4lconvert
> rtl28xxu: add module parameter to disable IR
> rtl2832_sdr: increase USB buffers
> 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
> rtl2832_sdr: return NULL on rtl2832_sdr_attach failure
> rtl2832_sdr: calculate bandwidth if not set by user
> rtl2832_sdr: clamp ADC frequency to valid range always
> rtl2832_sdr: improve ADC device programming logic
> rtl2832_sdr: remove FMT buffer type checks
> rtl2832_sdr: switch FM to DAB mode
> msi3101: calculate tuner filters
> msi3101: remove FMT buffer type checks
> msi3101: improve ADC config stream format selection
> msi3101: clamp ADC and RF to valid range
> msi3101: disable all but u8 and u16le formats
> v4l: add RF tuner gain controls
> msi3101: use standard V4L gain controls
> e4000: convert DVB tuner to I2C driver model
> e4000: add manual gain controls
> rtl2832_sdr: expose E4000 gain controls to user space
> r820t: add manual gain controls
> rtl2832_sdr: expose R820 gain controls to user space
> e4000: fix PLL calc to allow higher frequencies
> msi3101: fix device caps to advertise SDR receiver
> rtl2832_sdr: fix device caps to advertise SDR receiver
> msi3101: add default FMT and ADC frequency
> msi3101: sleep USB ADC and tuner when streaming is stopped
> DocBook: document RF tuner gain controls
> DocBook: V4L: add V4L2_SDR_FMT_CU8 - 'CU08'
> DocBook: V4L: add V4L2_SDR_FMT_CU16LE - 'CU16'
> DocBook: media: document V4L2_CTRL_CLASS_RF_TUNER
> xc2028: silence compiler warnings
> v4l: add RF tuner channel bandwidth control
> msi3101: implement tuner bandwidth control
> rtl2832_sdr: implement tuner bandwidth control
> msi001: Mirics MSi001 silicon tuner driver
> msi3101: use msi001 tuner driver
> MAINTAINERS: add msi001 driver
> MAINTAINERS: add msi3101 driver
> MAINTAINERS: add rtl2832_sdr driver
> rtl28xxu: attach SDR module later
> e4000: implement controls via v4l2 control framework
> rtl2832_sdr: use E4000 tuner controls via V4L framework
> e4000: remove .set_config() which was for controls
> rtl28xxu: fix switch-case style issue
> v4l: reorganize RF tuner control ID numbers
> DocBook: document RF tuner bandwidth controls
> v4l: uapi: add SDR formats CU8 and CU16LE
> msi3101: use formats defined in V4L2 API
> rtl2832_sdr: use formats defined in V4L2 API
> v4l: add enum_freq_bands support to tuner sub-device
> msi001: implement .enum_freq_bands()
> msi3101: provide RF tuner bands from sub-device
> r820t/rtl2832u_sdr: implement gains using v4l2 controls
> v4l: add control for RF tuner PLL lock flag
> e4000: implement PLL lock v4l control
> DocBook: media: document PLL lock control
> rtl2832: provide muxed I2C adapter
> rtl2832: add muxed I2C adapter for demod itself
> rtl2832: implement delayed I2C gate close
> rtl28xxu: use muxed RTL2832 I2C adapters for E4000 and RTL2832_SDR
> e4000: get rid of DVB i2c_gate_ctrl()
> rtl2832_sdr: do not init tuner when only freq is changed
> e4000: convert to Regmap API
>
> Luis Alves (1):
> rtl2832: Fix deadlock on i2c mux select function.
>
> Documentation/DocBook/media/v4l/controls.xml | 119 ++
> .../DocBook/media/v4l/pixfmt-sdr-cu08.xml | 44 +
> .../DocBook/media/v4l/pixfmt-sdr-cu16le.xml | 46 +
> Documentation/DocBook/media/v4l/pixfmt.xml | 3 +
> .../DocBook/media/v4l/vidioc-g-ext-ctrls.xml | 7 +-
> MAINTAINERS | 30 +
> drivers/media/dvb-frontends/Kconfig | 2 +-
> drivers/media/dvb-frontends/rtl2832.c | 191 ++-
> drivers/media/dvb-frontends/rtl2832.h | 34 +-
> drivers/media/dvb-frontends/rtl2832_priv.h | 54 +-
> drivers/media/tuners/Kconfig | 1 +
> drivers/media/tuners/e4000.c | 598 +++++---
> drivers/media/tuners/e4000.h | 21 +-
> drivers/media/tuners/e4000_priv.h | 86 +-
> drivers/media/tuners/r820t.c | 137 +-
> drivers/media/tuners/r820t.h | 10 +
> drivers/media/tuners/tuner-xc2028.c | 3 +
> drivers/media/usb/dvb-usb-v2/Makefile | 1 +
> drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 99 +-
> drivers/media/usb/dvb-usb-v2/rtl28xxu.h | 2 +
> drivers/media/v4l2-core/v4l2-ctrls.c | 24 +
> drivers/staging/media/Kconfig | 2 +
> drivers/staging/media/Makefile | 2 +
> drivers/staging/media/msi3101/Kconfig | 7 +-
> drivers/staging/media/msi3101/Makefile | 1 +
> drivers/staging/media/msi3101/msi001.c | 499 +++++++
> drivers/staging/media/msi3101/sdr-msi3101.c | 1558 +++++++-------------
> drivers/staging/media/rtl2832u_sdr/Kconfig | 7 +
> drivers/staging/media/rtl2832u_sdr/Makefile | 6 +
> drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 1476 +++++++++++++++++++
> drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h | 51 +
> include/media/v4l2-subdev.h | 1 +
> include/uapi/linux/v4l2-controls.h | 14 +
> include/uapi/linux/videodev2.h | 4 +
> 34 files changed, 3825 insertions(+), 1315 deletions(-)
> create mode 100644 Documentation/DocBook/media/v4l/pixfmt-sdr-cu08.xml
> create mode 100644 Documentation/DocBook/media/v4l/pixfmt-sdr-cu16le.xml
> create mode 100644 drivers/staging/media/msi3101/msi001.c
> create mode 100644 drivers/staging/media/rtl2832u_sdr/Kconfig
> create mode 100644 drivers/staging/media/rtl2832u_sdr/Makefile
> create mode 100644 drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
> create mode 100644 drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h
>
> --
> 1.8.5.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 91+ messages in thread* Re: [REVIEW PATCH 00/86] SDR tree
2014-02-09 8:48 [REVIEW PATCH 00/86] SDR tree Antti Palosaari
` (86 preceding siblings ...)
2014-02-09 17:08 ` [REVIEW PATCH 00/86] SDR tree Anca Emanuel
@ 2014-02-10 9:43 ` Hans Verkuil
2014-02-10 10:06 ` Gianluca Gennari
87 siblings, 1 reply; 91+ messages in thread
From: Hans Verkuil @ 2014-02-10 9:43 UTC (permalink / raw)
To: Antti Palosaari; +Cc: linux-media
Hi Antti,
I have a few questions about this patch series:
First of all, would this work for a rtl2838 as well or is this really 2832u
specific? I've got a 2838... If it is 2832u specific, then do you know which
product has it? It would be useful for me to have a usb stick with which I can
test SDR.
Secondly, this is a very awkward patch series to review, it really needs some
reorganization.
The rtl2832u_sdr driver is completely new, so just add the final version in one
single patch. I'm not interested in the intermediate steps as it is new anyway.
Any v4l core changes (new formats, docbook, controls, etc.) should come first in
the patch series so that driver patches can directly build on those. It's also
nice for me as a reviewer to have them first since core patches need more careful
review. Since all the core stuff is available for later driver patches, it is
probably also possible to merge patches together. E.g. instead of adding custom
support for a feature to a driver, then adding core support for it, then converting
the custom support to the core support in the driver, just can just add the new
feature directly using core support.
The reason is that it is hard to review core if you first see a half-finished
version and only later the final version (i.e. the one you really should be
reviewing).
I know, it's a lot of work but it pays itself by getting things merged much
quicker. As it stands now I am not going to review it, it's too messy.
Also, where possible group all patches modifying the same driver together, that
way I don't have to switch back-and-forth between drivers.
Oh, one thing I noticed in the rtl2832_sdr driver in the stop_streaming callback:
it can return an error. Be aware that the error code is not checked at all. The
stop_streaming callback really should be changed to a void function. Stopping
streaming is one of those things that should always succeed.
Regards,
Hans
On 02/09/2014 09:48 AM, Antti Palosaari wrote:
> That is everything I have on my SDR queue. There is drivers for Mirics
> MSi3101 and Realtek RTL2832U based devices. These drivers are still on
> staging and I am not going to move those out of staging very soon as I
> want get some experiments first.
>
> That set is available via Git:
> http://git.linuxtv.org/anttip/media_tree.git/shortlog/refs/heads/sdr_review
>
>
> Simplest way to test it in practice is listen FM radio using SDRSharp as a radio player.
> I made simple plug-in for that:
> https://github.com/palosaari/sdrsharp-v4l2
>
> That plug-in supports currently only on 64-bit Kernel...
>
>
> Installation is this simple (Fedora 20):
>
> $ sudo yum install mono-core monodevelop
> $ svn co https://subversion.assembla.com/svn/sdrsharp/trunk sdrsharp
> $ cd sdrsharp
> $ git clone https://github.com/palosaari/sdrsharp-v4l2.git V4L2
> $ sed -i 's/Format Version 12\.00/Format Version 11\.00/' SDRSharp.sln
>
> * Add following line to SDRSharp/App.config file inside frontendPlugins tag
> <add key="Linux Kernel V4L2" value="SDRSharp.V4L2.LibV4LIO,SDRSharp.V4L2" />
>
> $ monodevelop SDRSharp.sln
> * View > Default
> * Solution SDRSharp > Add > Add Existing Project... > V4L2 > SDRSharp.V4L2.csproj
> * Select Release|x86
> * Build > Build All
> * File > Quit
> $ mono Release/SDRSharp.exe
>
>
> regards
> Antti
>
>
> Antti Palosaari (85):
> rtl2832_sdr: Realtek RTL2832 SDR driver module
> rtl28xxu: attach SDR extension module
> rtl2832_sdr: use config struct from rtl2832 module
> rtl2832_sdr: initial support for R820T tuner
> rtl2832_sdr: use get_if_frequency()
> rtl2832_sdr: implement sampling rate
> rtl2832_sdr: initial support for FC0012 tuner
> rtl2832_sdr: initial support for FC0013 tuner
> rtl28xxu: constify demod config structs
> rtl2832: remove unused if_dvbt config parameter
> rtl2832: style changes and minor cleanup
> rtl2832_sdr: pixel format for SDR
> rtl2832_sdr: implement FMT IOCTLs
> msi3101: add signed 8-bit pixel format for SDR
> msi3101: implement FMT IOCTLs
> msi3101: move format 384 conversion to libv4lconvert
> msi3101: move format 336 conversion to libv4lconvert
> msi3101: move format 252 conversion to libv4lconvert
> rtl28xxu: add module parameter to disable IR
> rtl2832_sdr: increase USB buffers
> 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
> rtl2832_sdr: return NULL on rtl2832_sdr_attach failure
> rtl2832_sdr: calculate bandwidth if not set by user
> rtl2832_sdr: clamp ADC frequency to valid range always
> rtl2832_sdr: improve ADC device programming logic
> rtl2832_sdr: remove FMT buffer type checks
> rtl2832_sdr: switch FM to DAB mode
> msi3101: calculate tuner filters
> msi3101: remove FMT buffer type checks
> msi3101: improve ADC config stream format selection
> msi3101: clamp ADC and RF to valid range
> msi3101: disable all but u8 and u16le formats
> v4l: add RF tuner gain controls
> msi3101: use standard V4L gain controls
> e4000: convert DVB tuner to I2C driver model
> e4000: add manual gain controls
> rtl2832_sdr: expose E4000 gain controls to user space
> r820t: add manual gain controls
> rtl2832_sdr: expose R820 gain controls to user space
> e4000: fix PLL calc to allow higher frequencies
> msi3101: fix device caps to advertise SDR receiver
> rtl2832_sdr: fix device caps to advertise SDR receiver
> msi3101: add default FMT and ADC frequency
> msi3101: sleep USB ADC and tuner when streaming is stopped
> DocBook: document RF tuner gain controls
> DocBook: V4L: add V4L2_SDR_FMT_CU8 - 'CU08'
> DocBook: V4L: add V4L2_SDR_FMT_CU16LE - 'CU16'
> DocBook: media: document V4L2_CTRL_CLASS_RF_TUNER
> xc2028: silence compiler warnings
> v4l: add RF tuner channel bandwidth control
> msi3101: implement tuner bandwidth control
> rtl2832_sdr: implement tuner bandwidth control
> msi001: Mirics MSi001 silicon tuner driver
> msi3101: use msi001 tuner driver
> MAINTAINERS: add msi001 driver
> MAINTAINERS: add msi3101 driver
> MAINTAINERS: add rtl2832_sdr driver
> rtl28xxu: attach SDR module later
> e4000: implement controls via v4l2 control framework
> rtl2832_sdr: use E4000 tuner controls via V4L framework
> e4000: remove .set_config() which was for controls
> rtl28xxu: fix switch-case style issue
> v4l: reorganize RF tuner control ID numbers
> DocBook: document RF tuner bandwidth controls
> v4l: uapi: add SDR formats CU8 and CU16LE
> msi3101: use formats defined in V4L2 API
> rtl2832_sdr: use formats defined in V4L2 API
> v4l: add enum_freq_bands support to tuner sub-device
> msi001: implement .enum_freq_bands()
> msi3101: provide RF tuner bands from sub-device
> r820t/rtl2832u_sdr: implement gains using v4l2 controls
> v4l: add control for RF tuner PLL lock flag
> e4000: implement PLL lock v4l control
> DocBook: media: document PLL lock control
> rtl2832: provide muxed I2C adapter
> rtl2832: add muxed I2C adapter for demod itself
> rtl2832: implement delayed I2C gate close
> rtl28xxu: use muxed RTL2832 I2C adapters for E4000 and RTL2832_SDR
> e4000: get rid of DVB i2c_gate_ctrl()
> rtl2832_sdr: do not init tuner when only freq is changed
> e4000: convert to Regmap API
>
> Luis Alves (1):
> rtl2832: Fix deadlock on i2c mux select function.
>
> Documentation/DocBook/media/v4l/controls.xml | 119 ++
> .../DocBook/media/v4l/pixfmt-sdr-cu08.xml | 44 +
> .../DocBook/media/v4l/pixfmt-sdr-cu16le.xml | 46 +
> Documentation/DocBook/media/v4l/pixfmt.xml | 3 +
> .../DocBook/media/v4l/vidioc-g-ext-ctrls.xml | 7 +-
> MAINTAINERS | 30 +
> drivers/media/dvb-frontends/Kconfig | 2 +-
> drivers/media/dvb-frontends/rtl2832.c | 191 ++-
> drivers/media/dvb-frontends/rtl2832.h | 34 +-
> drivers/media/dvb-frontends/rtl2832_priv.h | 54 +-
> drivers/media/tuners/Kconfig | 1 +
> drivers/media/tuners/e4000.c | 598 +++++---
> drivers/media/tuners/e4000.h | 21 +-
> drivers/media/tuners/e4000_priv.h | 86 +-
> drivers/media/tuners/r820t.c | 137 +-
> drivers/media/tuners/r820t.h | 10 +
> drivers/media/tuners/tuner-xc2028.c | 3 +
> drivers/media/usb/dvb-usb-v2/Makefile | 1 +
> drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 99 +-
> drivers/media/usb/dvb-usb-v2/rtl28xxu.h | 2 +
> drivers/media/v4l2-core/v4l2-ctrls.c | 24 +
> drivers/staging/media/Kconfig | 2 +
> drivers/staging/media/Makefile | 2 +
> drivers/staging/media/msi3101/Kconfig | 7 +-
> drivers/staging/media/msi3101/Makefile | 1 +
> drivers/staging/media/msi3101/msi001.c | 499 +++++++
> drivers/staging/media/msi3101/sdr-msi3101.c | 1558 +++++++-------------
> drivers/staging/media/rtl2832u_sdr/Kconfig | 7 +
> drivers/staging/media/rtl2832u_sdr/Makefile | 6 +
> drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c | 1476 +++++++++++++++++++
> drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h | 51 +
> include/media/v4l2-subdev.h | 1 +
> include/uapi/linux/v4l2-controls.h | 14 +
> include/uapi/linux/videodev2.h | 4 +
> 34 files changed, 3825 insertions(+), 1315 deletions(-)
> create mode 100644 Documentation/DocBook/media/v4l/pixfmt-sdr-cu08.xml
> create mode 100644 Documentation/DocBook/media/v4l/pixfmt-sdr-cu16le.xml
> create mode 100644 drivers/staging/media/msi3101/msi001.c
> create mode 100644 drivers/staging/media/rtl2832u_sdr/Kconfig
> create mode 100644 drivers/staging/media/rtl2832u_sdr/Makefile
> create mode 100644 drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
> create mode 100644 drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h
>
^ permalink raw reply [flat|nested] 91+ messages in thread* Re: [REVIEW PATCH 00/86] SDR tree
2014-02-10 9:43 ` Hans Verkuil
@ 2014-02-10 10:06 ` Gianluca Gennari
2014-02-10 10:27 ` Antti Palosaari
0 siblings, 1 reply; 91+ messages in thread
From: Gianluca Gennari @ 2014-02-10 10:06 UTC (permalink / raw)
To: Hans Verkuil; +Cc: Antti Palosaari, linux-media
Hi Hans,
> First of all, would this work for a rtl2838 as well or is this really 2832u
> specific? I've got a 2838... If it is 2832u specific, then do you know which
> product has it? It would be useful for me to have a usb stick with which I can
> test SDR.
regarding this question, 2838 is just another USB Id for rtl2832u
devices based on reference design. I have one with rtl2832u + e4000
tuner, so probably your stick is fine for SDR.
Realtek makes several different demodulators with similar codenames:
- 2830/2832 DVB-T
- 2836 DTMB
- 2840 DVB-C
see here for more info:
http://www.realtek.com.tw/products/productsView.aspx?Langid=1&PNid=7&PFid=22&Level=3&Conn=2
Regards,
Gianluca
^ permalink raw reply [flat|nested] 91+ messages in thread
* Re: [REVIEW PATCH 00/86] SDR tree
2014-02-10 10:06 ` Gianluca Gennari
@ 2014-02-10 10:27 ` Antti Palosaari
0 siblings, 0 replies; 91+ messages in thread
From: Antti Palosaari @ 2014-02-10 10:27 UTC (permalink / raw)
To: gennarone, Hans Verkuil; +Cc: linux-media
On 10.02.2014 12:06, Gianluca Gennari wrote:
> Hi Hans,
>
>> First of all, would this work for a rtl2838 as well or is this really 2832u
>> specific? I've got a 2838... If it is 2832u specific, then do you know which
>> product has it? It would be useful for me to have a usb stick with which I can
>> test SDR.
>
> regarding this question, 2838 is just another USB Id for rtl2832u
> devices based on reference design. I have one with rtl2832u + e4000
> tuner, so probably your stick is fine for SDR.
>
> Realtek makes several different demodulators with similar codenames:
> - 2830/2832 DVB-T
> - 2836 DTMB
> - 2840 DVB-C
>
> see here for more info:
> http://www.realtek.com.tw/products/productsView.aspx?Langid=1&PNid=7&PFid=22&Level=3&Conn=2
Yeah, demod chips are just like that. Then these are integrated like that:
RT2831U = USB-interface + RTL2830 DVB-T demod
RT2832U = USB-interface + RTL2832 DVB-T demod
RT2832P = USB-interface + RTL2832 DVB-T demod + TS interface
USB-interface used is pretty same for all these, thus it is split to own
driver named dvb_usb_rtl28xxu.
SDR functionality is property of RTL2832 demodulator, but I decided to
split it to own driver too.
Currently that SDR driver has support for devices having following RF
tuners: e4000, r820t, fc0012 and fc0013. So if Hans has a device having
some of those tuners, it should work.
regards
Antti
--
http://palosaari.fi/
^ permalink raw reply [flat|nested] 91+ messages in thread