From 77cf393434898d1299c77c32bdd0629b2b4df170 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 27 Apr 2012 13:28:34 -0300 Subject: [PATCH] [media] radio-mr800: add support for stereo and signal detection Thanks to an older driver by Faidon Liambotis (as noted in the radio-mr800 comment block at the start) for figuring out how to get the signal/stereo state. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 43 ++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 0a96eda..0b39a8c 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -103,6 +103,7 @@ devices, that would be 76 and 91. */ * List isn't full and will be updated with implementation of new functions */ #define AMRADIO_SET_FREQ 0xa4 +#define AMRADIO_GET_SIGNAL 0xa7 #define AMRADIO_SET_MUTE 0xab #define AMRADIO_SET_MONO 0xae @@ -236,6 +237,35 @@ static int amradio_set_stereo(struct amradio_device *radio, char argument) return 0; } +static int amradio_get_stat(struct amradio_device *radio, bool *is_stereo, u32 *signal) +{ + int retval; + int size; + + radio->buffer[0] = 0x00; + radio->buffer[1] = 0x55; + radio->buffer[2] = 0xaa; + radio->buffer[3] = 0x00; + radio->buffer[4] = AMRADIO_GET_SIGNAL; + radio->buffer[5] = 0x00; + radio->buffer[6] = 0x00; + radio->buffer[7] = 0x08; + + retval = usb_bulk_msg(radio->usbdev, usb_sndbulkpipe(radio->usbdev, 0x02), + radio->buffer, BUFFER_LENGTH, &size, USB_TIMEOUT); + if (!retval) + retval = usb_bulk_msg(radio->usbdev, usb_rcvbulkpipe(radio->usbdev, 0x81), + radio->buffer, BUFFER_LENGTH, &size, USB_TIMEOUT); + + if (retval || size != BUFFER_LENGTH) { + amradio_dev_warn(&radio->vdev.dev, "get stat failed\n"); + return retval; + } + *is_stereo = radio->buffer[2] >> 7; + *signal = (radio->buffer[3] & 0xf0) << 8; + return 0; +} + /* Handle unplugging the device. * We call video_unregister_device in any case. * The last function called in this procedure is @@ -272,20 +302,23 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { struct amradio_device *radio = video_drvdata(file); + bool is_stereo = false; + int retval; if (v->index > 0) return -EINVAL; + v->signal = 0; + retval = amradio_get_stat(radio, &is_stereo, &v->signal); + if (retval) + return retval; + strcpy(v->name, "FM"); v->type = V4L2_TUNER_RADIO; v->rangelow = FREQ_MIN * FREQ_MUL; v->rangehigh = FREQ_MAX * FREQ_MUL; v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; - /* We do not know how to get hold of the stereo indicator, so - all we can do is give back both mono and stereo, which - effectively means that we don't know. */ - v->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; - v->signal = 0xffff; + v->rxsubchans = is_stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; v->audmode = radio->stereo ? V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO; return 0; -- 2.7.4