#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>
#include <linux/regmap.h>
static bool rtl2832_sdr_emulated_fmt;
module_param_named(emulated_formats, rtl2832_sdr_emulated_fmt, bool, 0644);
MODULE_PARM_DESC(…) …;
#define V4L2_SUBDEV_HAS_OP(sd, o, f) …
#define MAX_BULK_BUFS …
#define BULK_BUFFER_SIZE …
static const struct v4l2_frequency_band bands_adc[] = …;
static const struct v4l2_frequency_band bands_fm[] = …;
struct rtl2832_sdr_format { … };
static struct rtl2832_sdr_format formats[] = …;
static const unsigned int NUM_FORMATS = …;
struct rtl2832_sdr_frame_buf { … };
struct rtl2832_sdr_dev { … };
static struct rtl2832_sdr_frame_buf *rtl2832_sdr_get_next_fill_buf(
struct rtl2832_sdr_dev *dev)
{ … }
static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_dev *dev,
void *dst, const u8 *src, unsigned int src_len)
{ … }
static void rtl2832_sdr_urb_complete(struct urb *urb)
{ … }
static int rtl2832_sdr_kill_urbs(struct rtl2832_sdr_dev *dev)
{ … }
static int rtl2832_sdr_submit_urbs(struct rtl2832_sdr_dev *dev)
{ … }
static int rtl2832_sdr_free_stream_bufs(struct rtl2832_sdr_dev *dev)
{ … }
static int rtl2832_sdr_alloc_stream_bufs(struct rtl2832_sdr_dev *dev)
{ … }
static int rtl2832_sdr_free_urbs(struct rtl2832_sdr_dev *dev)
{ … }
static int rtl2832_sdr_alloc_urbs(struct rtl2832_sdr_dev *dev)
{ … }
static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_dev *dev)
{ … }
static int rtl2832_sdr_querycap(struct file *file, void *fh,
struct v4l2_capability *cap)
{ … }
static int rtl2832_sdr_queue_setup(struct vb2_queue *vq,
unsigned int *nbuffers,
unsigned int *nplanes, unsigned int sizes[], struct device *alloc_devs[])
{ … }
static int rtl2832_sdr_buf_prepare(struct vb2_buffer *vb)
{ … }
static void rtl2832_sdr_buf_queue(struct vb2_buffer *vb)
{ … }
static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev *dev)
{
struct platform_device *pdev = dev->pdev;
struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
struct dvb_frontend *fe = pdata->dvb_frontend;
int ret;
unsigned int f_sr, f_if;
u8 buf[4], u8tmp1, u8tmp2;
u64 u64tmp;
u32 u32tmp;
dev_dbg(&pdev->dev, "f_adc=%u\n", dev->f_adc);
if (!test_bit(POWER_ON, &dev->flags))
return 0;
if (dev->f_adc == 0)
return 0;
f_sr = dev->f_adc;
ret = regmap_bulk_write(dev->regmap, 0x13e, "\x00\x00", 2);
if (ret)
goto err;
ret = regmap_bulk_write(dev->regmap, 0x115, "\x00\x00\x00\x00", 4);
if (ret)
goto err;
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;
u64tmp = f_if % pdata->clk;
u64tmp *= 0x400000;
u64tmp = div_u64(u64tmp, pdata->clk);
u64tmp = -u64tmp;
u32tmp = u64tmp & 0x3fffff;
dev_dbg(&pdev->dev, "f_if=%u if_ctl=%08x\n", f_if, u32tmp);
buf[0] = (u32tmp >> 16) & 0xff;
buf[1] = (u32tmp >> 8) & 0xff;
buf[2] = (u32tmp >> 0) & 0xff;
ret = regmap_bulk_write(dev->regmap, 0x119, buf, 3);
if (ret)
goto err;
if (f_if) {
u8tmp1 = 0x1a;
u8tmp2 = 0x8d;
} else {
u8tmp1 = 0x1b;
u8tmp2 = 0xcd;
}
ret = regmap_write(dev->regmap, 0x1b1, u8tmp1);
if (ret)
goto err;
ret = regmap_write(dev->regmap, 0x008, u8tmp2);
if (ret)
goto err;
ret = regmap_write(dev->regmap, 0x006, 0x80);
if (ret)
goto err;
u32tmp = div_u64(pdata->clk * 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 = regmap_bulk_write(dev->regmap, 0x19f, buf, 4);
if (ret)
goto err;
ret = regmap_bulk_write(dev->regmap, 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;
ret = regmap_bulk_write(dev->regmap, 0x017, "\x11\x10", 2);
if (ret)
goto err;
ret = regmap_write(dev->regmap, 0x019, 0x05);
if (ret)
goto err;
ret = regmap_bulk_write(dev->regmap, 0x01a,
"\x1b\x16\x0d\x06\x01\xff", 6);
if (ret)
goto err;
ret = regmap_bulk_write(dev->regmap, 0x192, "\x00\xf0\x0f", 3);
if (ret)
goto err;
ret = regmap_write(dev->regmap, 0x061, 0x60);
if (ret)
goto err;
switch (pdata->tuner) {
case RTL2832_SDR_TUNER_E4000:
ret = regmap_write(dev->regmap, 0x112, 0x5a);
ret = regmap_write(dev->regmap, 0x102, 0x40);
ret = regmap_write(dev->regmap, 0x103, 0x5a);
ret = regmap_write(dev->regmap, 0x1c7, 0x30);
ret = regmap_write(dev->regmap, 0x104, 0xd0);
ret = regmap_write(dev->regmap, 0x105, 0xbe);
ret = regmap_write(dev->regmap, 0x1c8, 0x18);
ret = regmap_write(dev->regmap, 0x106, 0x35);
ret = regmap_write(dev->regmap, 0x1c9, 0x21);
ret = regmap_write(dev->regmap, 0x1ca, 0x21);
ret = regmap_write(dev->regmap, 0x1cb, 0x00);
ret = regmap_write(dev->regmap, 0x107, 0x40);
ret = regmap_write(dev->regmap, 0x1cd, 0x10);
ret = regmap_write(dev->regmap, 0x1ce, 0x10);
ret = regmap_write(dev->regmap, 0x108, 0x80);
ret = regmap_write(dev->regmap, 0x109, 0x7f);
ret = regmap_write(dev->regmap, 0x10a, 0x80);
ret = regmap_write(dev->regmap, 0x10b, 0x7f);
ret = regmap_write(dev->regmap, 0x00e, 0xfc);
ret = regmap_write(dev->regmap, 0x00e, 0xfc);
ret = regmap_write(dev->regmap, 0x011, 0xd4);
ret = regmap_write(dev->regmap, 0x1e5, 0xf0);
ret = regmap_write(dev->regmap, 0x1d9, 0x00);
ret = regmap_write(dev->regmap, 0x1db, 0x00);
ret = regmap_write(dev->regmap, 0x1dd, 0x14);
ret = regmap_write(dev->regmap, 0x1de, 0xec);
ret = regmap_write(dev->regmap, 0x1d8, 0x0c);
ret = regmap_write(dev->regmap, 0x1e6, 0x02);
ret = regmap_write(dev->regmap, 0x1d7, 0x09);
ret = regmap_write(dev->regmap, 0x00d, 0x83);
ret = regmap_write(dev->regmap, 0x010, 0x49);
ret = regmap_write(dev->regmap, 0x00d, 0x87);
ret = regmap_write(dev->regmap, 0x00d, 0x85);
ret = regmap_write(dev->regmap, 0x013, 0x02);
break;
case RTL2832_SDR_TUNER_FC0012:
case RTL2832_SDR_TUNER_FC0013:
ret = regmap_write(dev->regmap, 0x112, 0x5a);
ret = regmap_write(dev->regmap, 0x102, 0x40);
ret = regmap_write(dev->regmap, 0x103, 0x5a);
ret = regmap_write(dev->regmap, 0x1c7, 0x2c);
ret = regmap_write(dev->regmap, 0x104, 0xcc);
ret = regmap_write(dev->regmap, 0x105, 0xbe);
ret = regmap_write(dev->regmap, 0x1c8, 0x16);
ret = regmap_write(dev->regmap, 0x106, 0x35);
ret = regmap_write(dev->regmap, 0x1c9, 0x21);
ret = regmap_write(dev->regmap, 0x1ca, 0x21);
ret = regmap_write(dev->regmap, 0x1cb, 0x00);
ret = regmap_write(dev->regmap, 0x107, 0x40);
ret = regmap_write(dev->regmap, 0x1cd, 0x10);
ret = regmap_write(dev->regmap, 0x1ce, 0x10);
ret = regmap_write(dev->regmap, 0x108, 0x80);
ret = regmap_write(dev->regmap, 0x109, 0x7f);
ret = regmap_write(dev->regmap, 0x10a, 0x80);
ret = regmap_write(dev->regmap, 0x10b, 0x7f);
ret = regmap_write(dev->regmap, 0x00e, 0xfc);
ret = regmap_write(dev->regmap, 0x00e, 0xfc);
ret = regmap_bulk_write(dev->regmap, 0x011, "\xe9\xbf", 2);
ret = regmap_write(dev->regmap, 0x1e5, 0xf0);
ret = regmap_write(dev->regmap, 0x1d9, 0x00);
ret = regmap_write(dev->regmap, 0x1db, 0x00);
ret = regmap_write(dev->regmap, 0x1dd, 0x11);
ret = regmap_write(dev->regmap, 0x1de, 0xef);
ret = regmap_write(dev->regmap, 0x1d8, 0x0c);
ret = regmap_write(dev->regmap, 0x1e6, 0x02);
ret = regmap_write(dev->regmap, 0x1d7, 0x09);
break;
case RTL2832_SDR_TUNER_R820T:
case RTL2832_SDR_TUNER_R828D:
ret = regmap_write(dev->regmap, 0x112, 0x5a);
ret = regmap_write(dev->regmap, 0x102, 0x40);
ret = regmap_write(dev->regmap, 0x115, 0x01);
ret = regmap_write(dev->regmap, 0x103, 0x80);
ret = regmap_write(dev->regmap, 0x1c7, 0x24);
ret = regmap_write(dev->regmap, 0x104, 0xcc);
ret = regmap_write(dev->regmap, 0x105, 0xbe);
ret = regmap_write(dev->regmap, 0x1c8, 0x14);
ret = regmap_write(dev->regmap, 0x106, 0x35);
ret = regmap_write(dev->regmap, 0x1c9, 0x21);
ret = regmap_write(dev->regmap, 0x1ca, 0x21);
ret = regmap_write(dev->regmap, 0x1cb, 0x00);
ret = regmap_write(dev->regmap, 0x107, 0x40);
ret = regmap_write(dev->regmap, 0x1cd, 0x10);
ret = regmap_write(dev->regmap, 0x1ce, 0x10);
ret = regmap_write(dev->regmap, 0x108, 0x80);
ret = regmap_write(dev->regmap, 0x109, 0x7f);
ret = regmap_write(dev->regmap, 0x10a, 0x80);
ret = regmap_write(dev->regmap, 0x10b, 0x7f);
ret = regmap_write(dev->regmap, 0x00e, 0xfc);
ret = regmap_write(dev->regmap, 0x00e, 0xfc);
ret = regmap_write(dev->regmap, 0x011, 0xf4);
break;
case RTL2832_SDR_TUNER_FC2580:
ret = regmap_write(dev->regmap, 0x112, 0x39);
ret = regmap_write(dev->regmap, 0x102, 0x40);
ret = regmap_write(dev->regmap, 0x103, 0x5a);
ret = regmap_write(dev->regmap, 0x1c7, 0x2c);
ret = regmap_write(dev->regmap, 0x104, 0xcc);
ret = regmap_write(dev->regmap, 0x105, 0xbe);
ret = regmap_write(dev->regmap, 0x1c8, 0x16);
ret = regmap_write(dev->regmap, 0x106, 0x35);
ret = regmap_write(dev->regmap, 0x1c9, 0x21);
ret = regmap_write(dev->regmap, 0x1ca, 0x21);
ret = regmap_write(dev->regmap, 0x1cb, 0x00);
ret = regmap_write(dev->regmap, 0x107, 0x40);
ret = regmap_write(dev->regmap, 0x1cd, 0x10);
ret = regmap_write(dev->regmap, 0x1ce, 0x10);
ret = regmap_write(dev->regmap, 0x108, 0x80);
ret = regmap_write(dev->regmap, 0x109, 0x7f);
ret = regmap_write(dev->regmap, 0x10a, 0x9c);
ret = regmap_write(dev->regmap, 0x10b, 0x7f);
ret = regmap_write(dev->regmap, 0x00e, 0xfc);
ret = regmap_write(dev->regmap, 0x00e, 0xfc);
ret = regmap_bulk_write(dev->regmap, 0x011, "\xe9\xf4", 2);
break;
default:
dev_notice(&pdev->dev, "Unsupported tuner\n");
}
ret = regmap_update_bits(dev->regmap, 0x101, 0x04, 0x04);
if (ret)
goto err;
ret = regmap_update_bits(dev->regmap, 0x101, 0x04, 0x00);
if (ret)
goto err;
err:
return ret;
};
static void rtl2832_sdr_unset_adc(struct rtl2832_sdr_dev *dev)
{
struct platform_device *pdev = dev->pdev;
int ret;
dev_dbg(&pdev->dev, "\n");
ret = regmap_write(dev->regmap, 0x061, 0xe0);
if (ret)
goto err;
ret = regmap_write(dev->regmap, 0x019, 0x20);
if (ret)
goto err;
ret = regmap_bulk_write(dev->regmap, 0x017, "\x11\x10", 2);
if (ret)
goto err;
ret = regmap_bulk_write(dev->regmap, 0x192, "\x00\x0f\xff", 3);
if (ret)
goto err;
ret = regmap_bulk_write(dev->regmap, 0x13e, "\x40\x00", 2);
if (ret)
goto err;
ret = regmap_bulk_write(dev->regmap, 0x115, "\x06\x3f\xce\xcc", 4);
if (ret)
goto err;
err:
return;
};
static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_dev *dev)
{
struct platform_device *pdev = dev->pdev;
struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
struct dvb_frontend *fe = pdata->dvb_frontend;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct v4l2_ctrl *bandwidth_auto;
struct v4l2_ctrl *bandwidth;
if (dev->f_tuner == 0)
return 0;
bandwidth_auto = v4l2_ctrl_find(&dev->hdl,
V4L2_CID_RF_TUNER_BANDWIDTH_AUTO);
bandwidth = v4l2_ctrl_find(&dev->hdl, V4L2_CID_RF_TUNER_BANDWIDTH);
if (v4l2_ctrl_g_ctrl(bandwidth_auto)) {
c->bandwidth_hz = dev->f_adc;
v4l2_ctrl_s_ctrl(bandwidth, dev->f_adc);
} else {
c->bandwidth_hz = v4l2_ctrl_g_ctrl(bandwidth);
}
c->frequency = dev->f_tuner;
c->delivery_system = SYS_DVBT;
dev_dbg(&pdev->dev, "frequency=%u bandwidth=%d\n",
c->frequency, c->bandwidth_hz);
if (!test_bit(POWER_ON, &dev->flags))
return 0;
if (!V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, tuner, s_frequency)) {
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_dev *dev)
{
struct platform_device *pdev = dev->pdev;
struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
struct dvb_frontend *fe = pdata->dvb_frontend;
dev_dbg(&pdev->dev, "\n");
if (fe->ops.tuner_ops.init)
fe->ops.tuner_ops.init(fe);
return 0;
};
static void rtl2832_sdr_unset_tuner(struct rtl2832_sdr_dev *dev)
{
struct platform_device *pdev = dev->pdev;
struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
struct dvb_frontend *fe = pdata->dvb_frontend;
dev_dbg(&pdev->dev, "\n");
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)
{ … }
static void rtl2832_sdr_stop_streaming(struct vb2_queue *vq)
{ … }
static const struct vb2_ops rtl2832_sdr_vb2_ops = …;
static int rtl2832_sdr_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{ … }
static int rtl2832_sdr_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)
{ … }
static int rtl2832_sdr_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{ … }
static int rtl2832_sdr_s_frequency(struct file *file, void *priv,
const struct v4l2_frequency *f)
{ … }
static int rtl2832_sdr_enum_fmt_sdr_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{ … }
static int rtl2832_sdr_g_fmt_sdr_cap(struct file *file, void *priv,
struct v4l2_format *f)
{ … }
static int rtl2832_sdr_s_fmt_sdr_cap(struct file *file, void *priv,
struct v4l2_format *f)
{ … }
static int rtl2832_sdr_try_fmt_sdr_cap(struct file *file, void *priv,
struct v4l2_format *f)
{ … }
static const struct v4l2_ioctl_ops rtl2832_sdr_ioctl_ops = …;
static const struct v4l2_file_operations rtl2832_sdr_fops = …;
static struct video_device rtl2832_sdr_template = …;
static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl)
{ … }
static const struct v4l2_ctrl_ops rtl2832_sdr_ctrl_ops = …;
static void rtl2832_sdr_video_release(struct v4l2_device *v)
{ … }
static int rtl2832_sdr_probe(struct platform_device *pdev)
{ … }
static void rtl2832_sdr_remove(struct platform_device *pdev)
{ … }
static struct platform_driver rtl2832_sdr_driver = …;
module_platform_driver(…) …;
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;