diff options
Diffstat (limited to '')
-rw-r--r-- | drivers/media/dvb-frontends/rtl2832_sdr.c (renamed from drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c) | 100 |
1 files changed, 77 insertions, 23 deletions
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c index 093df6b6ae35..023e0f49c786 100644 --- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c +++ b/drivers/media/dvb-frontends/rtl2832_sdr.c @@ -35,6 +35,10 @@ #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)"); + #define MAX_BULK_BUFS (10) #define BULK_BUFFER_SIZE (128 * 512) @@ -80,15 +84,18 @@ static const struct v4l2_frequency_band bands_fm[] = { struct rtl2832_sdr_format { char *name; u32 pixelformat; + u32 buffersize; }; static struct rtl2832_sdr_format formats[] = { { - .name = "IQ U8", - .pixelformat = V4L2_SDR_FMT_CU8, + .name = "Complex U8", + .pixelformat = V4L2_SDR_FMT_CU8, + .buffersize = BULK_BUFFER_SIZE, }, { - .name = "IQ U16LE (emulated)", + .name = "Complex U16LE (emulated)", .pixelformat = V4L2_SDR_FMT_CU16LE, + .buffersize = BULK_BUFFER_SIZE * 2, }, }; @@ -139,6 +146,8 @@ struct rtl2832_sdr_state { unsigned int f_adc, f_tuner; u32 pixelformat; + u32 buffersize; + unsigned int num_formats; /* Controls */ struct v4l2_ctrl_handler hdl; @@ -348,6 +357,7 @@ static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s, /* 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; @@ -359,6 +369,7 @@ static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s, if (unlikely(time_is_before_jiffies(s->jiffies_next))) { #define MSECS 10000UL unsigned int samples = s->sample - s->sample_measured; + s->jiffies_next = jiffies + msecs_to_jiffies(MSECS); s->sample_measured = s->sample; dev_dbg(&s->udev->dev, @@ -560,11 +571,13 @@ static int rtl2832_sdr_alloc_urbs(struct rtl2832_sdr_state *s) 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); @@ -577,6 +590,7 @@ static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_state *s) 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); @@ -598,6 +612,7 @@ 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)); @@ -615,14 +630,14 @@ static int rtl2832_sdr_queue_setup(struct vb2_queue *vq, 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); /* Need at least 8 buffers */ if (vq->num_buffers + *nbuffers < 8) *nbuffers = 8 - vq->num_buffers; *nplanes = 1; - /* 2 = max 16-bit sample returned */ - sizes[0] = PAGE_ALIGN(BULK_BUFFER_SIZE * 2); + sizes[0] = PAGE_ALIGN(s->buffersize); dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n", __func__, *nbuffers, sizes[0]); return 0; @@ -665,6 +680,7 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s) 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)) @@ -935,7 +951,8 @@ static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_state *s) /* * bandwidth (Hz) */ - bandwidth_auto = v4l2_ctrl_find(&s->hdl, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO); + bandwidth_auto = v4l2_ctrl_find(&s->hdl, + V4L2_CID_RF_TUNER_BANDWIDTH_AUTO); bandwidth = v4l2_ctrl_find(&s->hdl, V4L2_CID_RF_TUNER_BANDWIDTH); if (v4l2_ctrl_g_ctrl(bandwidth_auto)) { c->bandwidth_hz = s->f_adc; @@ -987,6 +1004,7 @@ 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) @@ -1035,6 +1053,7 @@ err: static void 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__); mutex_lock(&s->v4l2_lock); @@ -1068,6 +1087,7 @@ static int rtl2832_sdr_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: index=%d type=%d\n", __func__, v->index, v->type); @@ -1094,6 +1114,7 @@ static int rtl2832_sdr_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__); if (v->index > 1) @@ -1105,6 +1126,7 @@ 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: tuner=%d type=%d index=%d\n", __func__, band->tuner, band->type, band->index); @@ -1130,6 +1152,7 @@ static int rtl2832_sdr_g_frequency(struct file *file, void *priv, { struct rtl2832_sdr_state *s = video_drvdata(file); int ret = 0; + dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n", __func__, f->tuner, f->type); @@ -1193,9 +1216,10 @@ 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 >= NUM_FORMATS) + if (f->index >= s->num_formats) return -EINVAL; strlcpy(f->description, formats[f->index].name, sizeof(f->description)); @@ -1208,9 +1232,12 @@ 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__); f->fmt.sdr.pixelformat = s->pixelformat; + f->fmt.sdr.buffersize = s->buffersize; + memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved)); return 0; @@ -1222,6 +1249,7 @@ static int rtl2832_sdr_s_fmt_sdr_cap(struct file *file, void *priv, 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.sdr.pixelformat); @@ -1229,15 +1257,19 @@ static int rtl2832_sdr_s_fmt_sdr_cap(struct file *file, void *priv, return -EBUSY; memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved)); - for (i = 0; i < NUM_FORMATS; i++) { + for (i = 0; i < s->num_formats; i++) { if (formats[i].pixelformat == f->fmt.sdr.pixelformat) { - s->pixelformat = f->fmt.sdr.pixelformat; + s->pixelformat = formats[i].pixelformat; + s->buffersize = formats[i].buffersize; + f->fmt.sdr.buffersize = formats[i].buffersize; return 0; } } - f->fmt.sdr.pixelformat = formats[0].pixelformat; s->pixelformat = formats[0].pixelformat; + s->buffersize = formats[0].buffersize; + f->fmt.sdr.pixelformat = formats[0].pixelformat; + f->fmt.sdr.buffersize = formats[0].buffersize; return 0; } @@ -1247,16 +1279,20 @@ static int rtl2832_sdr_try_fmt_sdr_cap(struct file *file, void *priv, { 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.sdr.pixelformat); memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved)); - for (i = 0; i < NUM_FORMATS; i++) { - if (formats[i].pixelformat == f->fmt.sdr.pixelformat) + for (i = 0; i < s->num_formats; i++) { + if (formats[i].pixelformat == f->fmt.sdr.pixelformat) { + f->fmt.sdr.buffersize = formats[i].buffersize; return 0; + } } f->fmt.sdr.pixelformat = formats[0].pixelformat; + f->fmt.sdr.buffersize = formats[0].buffersize; return 0; } @@ -1316,8 +1352,9 @@ static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl) 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", + "%s: id=%d name=%s val=%d min=%lld max=%lld step=%lld\n", __func__, ctrl->id, ctrl->name, ctrl->val, ctrl->minimum, ctrl->maximum, ctrl->step); @@ -1327,14 +1364,16 @@ static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl) /* TODO: these controls should be moved to tuner drivers */ if (s->bandwidth_auto->val) { /* Round towards the closest legal value */ - s32 val = s->f_adc + s->bandwidth->step / 2; + s32 val = s->f_adc + div_u64(s->bandwidth->step, 2); u32 offset; - val = clamp(val, s->bandwidth->minimum, s->bandwidth->maximum); + + val = clamp_t(s32, val, s->bandwidth->minimum, + s->bandwidth->maximum); offset = val - s->bandwidth->minimum; - offset = s->bandwidth->step * (offset / s->bandwidth->step); + offset = s->bandwidth->step * + div_u64(offset, s->bandwidth->step); s->bandwidth->val = s->bandwidth->minimum + offset; } - c->bandwidth_hz = s->bandwidth->val; if (!test_bit(POWER_ON, &s->flags)) @@ -1390,7 +1429,11 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, s->cfg = cfg; s->f_adc = bands_adc[0].rangelow; s->f_tuner = bands_fm[0].rangelow; - s->pixelformat = V4L2_SDR_FMT_CU8; + s->pixelformat = formats[0].pixelformat; + s->buffersize = formats[0].buffersize; + s->num_formats = NUM_FORMATS; + if (rtl2832_sdr_emulated_fmt == false) + s->num_formats -= 1; mutex_init(&s->v4l2_lock); mutex_init(&s->vb_queue_lock); @@ -1420,15 +1463,24 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, break; case RTL2832_TUNER_R820T: v4l2_ctrl_handler_init(&s->hdl, 2); - s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1); - s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH, 0, 8000000, 100000, 0); + s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops, + V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, + 0, 1, 1, 1); + s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops, + V4L2_CID_RF_TUNER_BANDWIDTH, + 0, 8000000, 100000, 0); v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false); break; 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_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1); - s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH, 6000000, 8000000, 1000000, 6000000); + s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops, + V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, + 0, 1, 1, 1); + s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops, + V4L2_CID_RF_TUNER_BANDWIDTH, + 6000000, 8000000, 1000000, + 6000000); v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false); break; default: @@ -1448,7 +1500,6 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, 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 */ @@ -1480,6 +1531,9 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, dev_info(&s->i2c->dev, "%s: Realtek RTL2832 SDR attached\n", KBUILD_MODNAME); + dev_notice(&s->udev->dev, + "%s: SDR API is still slightly experimental and functionality changes may follow\n", + KBUILD_MODNAME); return fe; err_unregister_v4l2_dev: |