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)
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;
ret = rtl2832_sdr_wr_regs(dev, 0x00e, "\xfc", 1);
ret = rtl2832_sdr_wr_regs(dev, 0x011, "\xf4", 1);
break;
+ case RTL2832_SDR_TUNER_FC2580:
+ ret = rtl2832_sdr_wr_regs(dev, 0x112, "\x39", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x102, "\x40", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x103, "\x5a", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x1c7, "\x2c", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x104, "\xcc", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x105, "\xbe", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x1c8, "\x16", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x106, "\x35", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x1c9, "\x21", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x1ca, "\x21", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x1cb, "\x00", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x107, "\x40", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x1cd, "\x10", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x1ce, "\x10", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x108, "\x80", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x109, "\x7f", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x10a, "\x9c", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x10b, "\x7f", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x00e, "\xfc", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x00e, "\xfc", 1);
+ ret = rtl2832_sdr_wr_regs(dev, 0x011, "\xe9\xf4", 2);
+ break;
default:
dev_notice(&pdev->dev, "Unsupported tuner\n");
}
if (!test_bit(POWER_ON, &dev->flags))
return 0;
- if (fe->ops.tuner_ops.set_params)
- fe->ops.tuner_ops.set_params(fe);
+ 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;
};
set_bit(POWER_ON, &dev->flags);
- ret = rtl2832_sdr_set_tuner(dev);
+ /* wake-up tuner */
+ if (V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, core, s_power))
+ ret = v4l2_subdev_call(dev->v4l2_subdev, core, s_power, 1);
+ else
+ ret = rtl2832_sdr_set_tuner(dev);
if (ret)
goto err;
rtl2832_sdr_free_stream_bufs(dev);
rtl2832_sdr_cleanup_queued_bufs(dev);
rtl2832_sdr_unset_adc(dev);
- rtl2832_sdr_unset_tuner(dev);
+
+ /* sleep tuner */
+ if (V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, core, s_power))
+ v4l2_subdev_call(dev->v4l2_subdev, core, s_power, 0);
+ else
+ rtl2832_sdr_unset_tuner(dev);
clear_bit(POWER_ON, &dev->flags);
{
struct rtl2832_sdr_dev *dev = video_drvdata(file);
struct platform_device *pdev = dev->pdev;
+ int ret;
dev_dbg(&pdev->dev, "index=%d type=%d\n", v->index, v->type);
v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
v->rangelow = 300000;
v->rangehigh = 3200000;
+ ret = 0;
+ } else if (v->index == 1 &&
+ V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, tuner, g_tuner)) {
+ ret = v4l2_subdev_call(dev->v4l2_subdev, tuner, g_tuner, v);
} 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;
+ ret = 0;
} else {
- return -EINVAL;
+ ret = -EINVAL;
}
-
- return 0;
+ return ret;
}
static int rtl2832_sdr_s_tuner(struct file *file, void *priv,
{
struct rtl2832_sdr_dev *dev = video_drvdata(file);
struct platform_device *pdev = dev->pdev;
+ int ret;
dev_dbg(&pdev->dev, "\n");
- if (v->index > 1)
- return -EINVAL;
- return 0;
+ if (v->index == 0) {
+ ret = 0;
+ } else if (v->index == 1 &&
+ V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, tuner, s_tuner)) {
+ ret = v4l2_subdev_call(dev->v4l2_subdev, tuner, s_tuner, v);
+ } else if (v->index == 1) {
+ ret = 0;
+ } else {
+ ret = -EINVAL;
+ }
+ return ret;
}
static int rtl2832_sdr_enum_freq_bands(struct file *file, void *priv,
{
struct rtl2832_sdr_dev *dev = video_drvdata(file);
struct platform_device *pdev = dev->pdev;
+ int ret;
dev_dbg(&pdev->dev, "tuner=%d type=%d index=%d\n",
band->tuner, band->type, band->index);
return -EINVAL;
*band = bands_adc[band->index];
+ ret = 0;
+ } else if (band->tuner == 1 &&
+ V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, tuner, enum_freq_bands)) {
+ ret = v4l2_subdev_call(dev->v4l2_subdev, tuner, enum_freq_bands, band);
} else if (band->tuner == 1) {
if (band->index >= ARRAY_SIZE(bands_fm))
return -EINVAL;
*band = bands_fm[band->index];
+ ret = 0;
} else {
- return -EINVAL;
+ ret = -EINVAL;
}
-
- return 0;
+ return ret;
}
static int rtl2832_sdr_g_frequency(struct file *file, void *priv,
{
struct rtl2832_sdr_dev *dev = video_drvdata(file);
struct platform_device *pdev = dev->pdev;
- int ret = 0;
+ int ret;
dev_dbg(&pdev->dev, "tuner=%d type=%d\n", f->tuner, f->type);
if (f->tuner == 0) {
f->frequency = dev->f_adc;
f->type = V4L2_TUNER_ADC;
+ ret = 0;
+ } else if (f->tuner == 1 &&
+ V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, tuner, g_frequency)) {
+ f->type = V4L2_TUNER_RF;
+ ret = v4l2_subdev_call(dev->v4l2_subdev, tuner, g_frequency, f);
} else if (f->tuner == 1) {
f->frequency = dev->f_tuner;
f->type = V4L2_TUNER_RF;
+ ret = 0;
} else {
- return -EINVAL;
+ ret = -EINVAL;
}
-
return ret;
}
band = 2;
dev->f_adc = clamp_t(unsigned int, f->frequency,
- bands_adc[band].rangelow,
- bands_adc[band].rangehigh);
+ bands_adc[band].rangelow,
+ bands_adc[band].rangehigh);
dev_dbg(&pdev->dev, "ADC frequency=%u Hz\n", dev->f_adc);
ret = rtl2832_sdr_set_adc(dev);
+ } else if (f->tuner == 1 &&
+ V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, tuner, s_frequency)) {
+ ret = v4l2_subdev_call(dev->v4l2_subdev, tuner, s_frequency, f);
} else if (f->tuner == 1) {
dev->f_tuner = clamp_t(unsigned int, f->frequency,
bands_fm[0].rangelow,
} else {
ret = -EINVAL;
}
-
return ret;
}
/* setup the state */
subdev = pdata->v4l2_subdev;
+ dev->v4l2_subdev = pdata->v4l2_subdev;
dev->pdev = pdev;
dev->udev = pdata->dvb_usb_device->udev;
dev->f_adc = bands_adc[0].rangelow;
6000000);
v4l2_ctrl_auto_cluster(2, &dev->bandwidth_auto, 0, false);
break;
+ case RTL2832_SDR_TUNER_FC2580:
+ v4l2_ctrl_handler_init(&dev->hdl, 2);
+ if (subdev)
+ v4l2_ctrl_add_handler(&dev->hdl, subdev->ctrl_handler,
+ NULL);
+ break;
default:
v4l2_ctrl_handler_init(&dev->hdl, 0);
dev_err(&pdev->dev, "Unsupported tuner\n");