/*
* 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
*
*/
#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-v4l2.h>
#include <media/videobuf2-vmalloc.h>
#include <linux/platform_device.h>
#include <linux/jiffies.h>
#include <linux/math64.h>
static bool rtl2832_sdr_emulated_fmt;
module_param_named(emulated_formats, rtl2832_sdr_emulated_fmt, bool, 0644);
MODULE_PARM_DESC(emulated_formats, "enable emulated formats (disappears in future)");
/* Original macro does not contain enough null pointer checks for our need */
#define V4L2_SUBDEV_HAS_OP(sd, o, f) \
((sd) && (sd)->ops && (sd)->ops->o && (sd)->ops->o->f)
#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;
u32 buffersize;
};
static struct rtl2832_sdr_format formats[] = {
{
.name = "Complex U8",
.pixelformat = V4L2_SDR_FMT_CU8,
.buffersize = BULK_BUFFER_SIZE,
}, {
.name = "Complex U16LE (emulated)",
.pixelformat = V4L2_SDR_FMT_CU16LE,
.buffersize = BULK_BUFFER_SIZE * 2,
},
};
static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
/* intermediate buffers with raw data from the USB device */
struct rtl2832_sdr_frame_buf {
/* common v4l buffer stuff -- must be first */
struct vb2_v4l2_buffer vb;
struct list_head list;
};
struct rtl2832_sdr_dev {
#define POWER_ON 0 /* BIT(0) */
#define URB_BUF 1 /* BIT(1) */
unsigned long flags;
struct platform_device *pdev;
struct video_device vdev;
struct v4l2_device v4l2_dev;
struct v4l2_subdev *v4l2_subdev;
/* videobuf2 queue and queued buffers list */
struct vb2_queue vb_queue;
struct list_head queued_bufs;
spinlock_t queued_bufs_lock; /* Protects queued_bufs */
unsigned sequence; /* buffer sequence counter */
/* 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;
unsigned int f_adc, f_tuner;
u32 pixelformat;
u32 buffersize;
unsigned int num_formats;
/* Controls */
struct v4l2_ctrl_handler hdl;
struct v4l2_ctrl *bandwidth_auto;
struct v4l2_ctrl *bandwidth;
/* for sample rate calc */
unsigned int sample;
unsigned int sample_measured;
unsigned long jiffies_next;
};
/* write multiple registers */
static int rtl2832_sdr_wr_regs(struct rtl2832_sdr_dev *dev, u16 reg,
const u8 *val, int len)
{
struct platform_device *pdev = dev->pdev;
struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
struct i2c_client *client = pdata->i2c_client;
return pdata->bulk_write(client, reg, val, len);
}
#if 0
/* read multiple registers */
static int rtl2832_sdr_rd_regs(struct rtl2832_sdr_dev *dev, u16 reg, u8 *val,
int len)
{
struct platform_device *pdev = dev->pdev;
struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
struct i2c_client *client = pdata->i2c_client;
return pdata->bulk_read(client, reg, val, len);
}
#endif
/* write single register */
static int rtl2832_sdr_wr_reg(struct rtl2832_sdr_dev *dev, u16 reg, u8 val)
{
return rtl2832_sdr_wr_regs(dev, reg, &val, 1);
}
/* write single register with mask */
static int rtl2832_sdr_wr_reg_mask(struct rtl2832_sdr_dev *dev, u16 reg,
u8 val, u8 mask)
{
struct platform_device *pdev = dev->pdev;
struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
struct i2c_client *client = pdata->i2c_client;
return pdata->update_bits(client, reg, mask, val);
}
/* Private functions */
static struct rtl2832_sdr_frame_buf *rtl2832_sdr_get_next_fill_buf(
struct rtl2832_sdr_dev *dev)
{
unsigned long flags;
struct rtl2832_sdr_frame_buf *buf = NULL;
spin_lock_irqsave(&dev->queued_bufs_lock, flags);
if (list_empty(&dev->queued_bufs))
goto leave;
buf = list_entry(dev->queued_bufs.next,
struct rtl2832_sdr_frame_buf, list);
list_del(&buf->list);
leave:
spin_unlock_irqrestore(&dev->queued_bufs_lock, flags);
return buf;
}
static unsigned int rtl2832_sdr_convert_stream(
|