linux/drivers/media/radio/radio-ma901.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Driver for the MasterKit MA901 USB FM radio. This device plugs
   4 * into the USB port and an analog audio input or headphones, so this thing
   5 * only deals with initialization, frequency setting, volume.
   6 *
   7 * Copyright (c) 2012 Alexey Klimov <klimov.linux@gmail.com>
   8 */
   9
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/init.h>
  13#include <linux/slab.h>
  14#include <linux/input.h>
  15#include <linux/videodev2.h>
  16#include <media/v4l2-device.h>
  17#include <media/v4l2-ioctl.h>
  18#include <media/v4l2-ctrls.h>
  19#include <media/v4l2-event.h>
  20#include <linux/usb.h>
  21#include <linux/mutex.h>
  22
  23#define DRIVER_AUTHOR "Alexey Klimov <klimov.linux@gmail.com>"
  24#define DRIVER_DESC "Masterkit MA901 USB FM radio driver"
  25#define DRIVER_VERSION "0.0.1"
  26
  27MODULE_AUTHOR(DRIVER_AUTHOR);
  28MODULE_DESCRIPTION(DRIVER_DESC);
  29MODULE_LICENSE("GPL");
  30MODULE_VERSION(DRIVER_VERSION);
  31
  32#define USB_MA901_VENDOR  0x16c0
  33#define USB_MA901_PRODUCT 0x05df
  34
  35/* dev_warn macro with driver name */
  36#define MA901_DRIVER_NAME "radio-ma901"
  37#define ma901radio_dev_warn(dev, fmt, arg...)                           \
  38                dev_warn(dev, MA901_DRIVER_NAME " - " fmt, ##arg)
  39
  40#define ma901radio_dev_err(dev, fmt, arg...) \
  41                dev_err(dev, MA901_DRIVER_NAME " - " fmt, ##arg)
  42
  43/* Probably USB_TIMEOUT should be modified in module parameter */
  44#define BUFFER_LENGTH 8
  45#define USB_TIMEOUT 500
  46
  47#define FREQ_MIN  87.5
  48#define FREQ_MAX 108.0
  49#define FREQ_MUL 16000
  50
  51#define MA901_VOLUME_MAX 16
  52#define MA901_VOLUME_MIN 0
  53
  54/* Commands that device should understand
  55 * List isn't full and will be updated with implementation of new functions
  56 */
  57#define MA901_RADIO_SET_FREQ            0x03
  58#define MA901_RADIO_SET_VOLUME          0x04
  59#define MA901_RADIO_SET_MONO_STEREO     0x05
  60
  61/* Comfortable defines for ma901radio_set_stereo */
  62#define MA901_WANT_STEREO               0x50
  63#define MA901_WANT_MONO                 0xd0
  64
  65/* module parameter */
  66static int radio_nr = -1;
  67module_param(radio_nr, int, 0);
  68MODULE_PARM_DESC(radio_nr, "Radio file number");
  69
  70/* Data for one (physical) device */
  71struct ma901radio_device {
  72        /* reference to USB and video device */
  73        struct usb_device *usbdev;
  74        struct usb_interface *intf;
  75        struct video_device vdev;
  76        struct v4l2_device v4l2_dev;
  77        struct v4l2_ctrl_handler hdl;
  78
  79        u8 *buffer;
  80        struct mutex lock;      /* buffer locking */
  81        int curfreq;
  82        u16 volume;
  83        int stereo;
  84        bool muted;
  85};
  86
  87static inline struct ma901radio_device *to_ma901radio_dev(struct v4l2_device *v4l2_dev)
  88{
  89        return container_of(v4l2_dev, struct ma901radio_device, v4l2_dev);
  90}
  91
  92/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
  93static int ma901radio_set_freq(struct ma901radio_device *radio, int freq)
  94{
  95        unsigned int freq_send = 0x300 + (freq >> 5) / 25;
  96        int retval;
  97
  98        radio->buffer[0] = 0x0a;
  99        radio->buffer[1] = MA901_RADIO_SET_FREQ;
 100        radio->buffer[2] = ((freq_send >> 8) & 0xff) + 0x80;
 101        radio->buffer[3] = freq_send & 0xff;
 102        radio->buffer[4] = 0x00;
 103        radio->buffer[5] = 0x00;
 104        radio->buffer[6] = 0x00;
 105        radio->buffer[7] = 0x00;
 106
 107        retval = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0),
 108                                9, 0x21, 0x0300, 0,
 109                                radio->buffer, BUFFER_LENGTH, USB_TIMEOUT);
 110        if (retval < 0)
 111                return retval;
 112
 113        radio->curfreq = freq;
 114        return 0;
 115}
 116
 117static int ma901radio_set_volume(struct ma901radio_device *radio, u16 vol_to_set)
 118{
 119        int retval;
 120
 121        radio->buffer[0] = 0x0a;
 122        radio->buffer[1] = MA901_RADIO_SET_VOLUME;
 123        radio->buffer[2] = 0xc2;
 124        radio->buffer[3] = vol_to_set + 0x20;
 125        radio->buffer[4] = 0x00;
 126        radio->buffer[5] = 0x00;
 127        radio->buffer[6] = 0x00;
 128        radio->buffer[7] = 0x00;
 129
 130        retval = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0),
 131                                9, 0x21, 0x0300, 0,
 132                                radio->buffer, BUFFER_LENGTH, USB_TIMEOUT);
 133        if (retval < 0)
 134                return retval;
 135
 136        radio->volume = vol_to_set;
 137        return retval;
 138}
 139
 140static int ma901_set_stereo(struct ma901radio_device *radio, u8 stereo)
 141{
 142        int retval;
 143
 144        radio->buffer[0] = 0x0a;
 145        radio->buffer[1] = MA901_RADIO_SET_MONO_STEREO;
 146        radio->buffer[2] = stereo;
 147        radio->buffer[3] = 0x00;
 148        radio->buffer[4] = 0x00;
 149        radio->buffer[5] = 0x00;
 150        radio->buffer[6] = 0x00;
 151        radio->buffer[7] = 0x00;
 152
 153        retval = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0),
 154                                9, 0x21, 0x0300, 0,
 155                                radio->buffer, BUFFER_LENGTH, USB_TIMEOUT);
 156
 157        if (retval < 0)
 158                return retval;
 159
 160        if (stereo == MA901_WANT_STEREO)
 161                radio->stereo = V4L2_TUNER_MODE_STEREO;
 162        else
 163                radio->stereo = V4L2_TUNER_MODE_MONO;
 164
 165        return retval;
 166}
 167
 168/* Handle unplugging the device.
 169 * We call video_unregister_device in any case.
 170 * The last function called in this procedure is
 171 * usb_ma901radio_device_release.
 172 */
 173static void usb_ma901radio_disconnect(struct usb_interface *intf)
 174{
 175        struct ma901radio_device *radio = to_ma901radio_dev(usb_get_intfdata(intf));
 176
 177        mutex_lock(&radio->lock);
 178        video_unregister_device(&radio->vdev);
 179        usb_set_intfdata(intf, NULL);
 180        v4l2_device_disconnect(&radio->v4l2_dev);
 181        mutex_unlock(&radio->lock);
 182        v4l2_device_put(&radio->v4l2_dev);
 183}
 184
 185/* vidioc_querycap - query device capabilities */
 186static int vidioc_querycap(struct file *file, void *priv,
 187                                        struct v4l2_capability *v)
 188{
 189        struct ma901radio_device *radio = video_drvdata(file);
 190
 191        strscpy(v->driver, "radio-ma901", sizeof(v->driver));
 192        strscpy(v->card, "Masterkit MA901 USB FM Radio", sizeof(v->card));
 193        usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
 194        return 0;
 195}
 196
 197/* vidioc_g_tuner - get tuner attributes */
 198static int vidioc_g_tuner(struct file *file, void *priv,
 199                                struct v4l2_tuner *v)
 200{
 201        struct ma901radio_device *radio = video_drvdata(file);
 202
 203        if (v->index > 0)
 204                return -EINVAL;
 205
 206        v->signal = 0;
 207
 208        /* TODO: the same words like in _probe() goes here.
 209         * When receiving of stats will be implemented then we can call
 210         * ma901radio_get_stat().
 211         * retval = ma901radio_get_stat(radio, &is_stereo, &v->signal);
 212         */
 213
 214        strscpy(v->name, "FM", sizeof(v->name));
 215        v->type = V4L2_TUNER_RADIO;
 216        v->rangelow = FREQ_MIN * FREQ_MUL;
 217        v->rangehigh = FREQ_MAX * FREQ_MUL;
 218        v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
 219        /* v->rxsubchans = is_stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; */
 220        v->audmode = radio->stereo ?
 221                V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO;
 222        return 0;
 223}
 224
 225/* vidioc_s_tuner - set tuner attributes */
 226static int vidioc_s_tuner(struct file *file, void *priv,
 227                                const struct v4l2_tuner *v)
 228{
 229        struct ma901radio_device *radio = video_drvdata(file);
 230
 231        if (v->index > 0)
 232                return -EINVAL;
 233
 234        /* mono/stereo selector */
 235        switch (v->audmode) {
 236        case V4L2_TUNER_MODE_MONO:
 237                return ma901_set_stereo(radio, MA901_WANT_MONO);
 238        default:
 239                return ma901_set_stereo(radio, MA901_WANT_STEREO);
 240        }
 241}
 242
 243/* vidioc_s_frequency - set tuner radio frequency */
 244static int vidioc_s_frequency(struct file *file, void *priv,
 245                                const struct v4l2_frequency *f)
 246{
 247        struct ma901radio_device *radio = video_drvdata(file);
 248
 249        if (f->tuner != 0)
 250                return -EINVAL;
 251
 252        return ma901radio_set_freq(radio, clamp_t(unsigned, f->frequency,
 253                                FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL));
 254}
 255
 256/* vidioc_g_frequency - get tuner radio frequency */
 257static int vidioc_g_frequency(struct file *file, void *priv,
 258                                struct v4l2_frequency *f)
 259{
 260        struct ma901radio_device *radio = video_drvdata(file);
 261
 262        if (f->tuner != 0)
 263                return -EINVAL;
 264        f->frequency = radio->curfreq;
 265
 266        return 0;
 267}
 268
 269static int usb_ma901radio_s_ctrl(struct v4l2_ctrl *ctrl)
 270{
 271        struct ma901radio_device *radio =
 272                container_of(ctrl->handler, struct ma901radio_device, hdl);
 273
 274        switch (ctrl->id) {
 275        case V4L2_CID_AUDIO_VOLUME:     /* set volume */
 276                return ma901radio_set_volume(radio, (u16)ctrl->val);
 277        }
 278
 279        return -EINVAL;
 280}
 281
 282/* TODO: Should we really need to implement suspend and resume functions?
 283 * Radio has it's own memory and will continue playing if power is present
 284 * on usb port and on resume it will start to play again based on freq, volume
 285 * values in device memory.
 286 */
 287static int usb_ma901radio_suspend(struct usb_interface *intf, pm_message_t message)
 288{
 289        return 0;
 290}
 291
 292static int usb_ma901radio_resume(struct usb_interface *intf)
 293{
 294        return 0;
 295}
 296
 297static const struct v4l2_ctrl_ops usb_ma901radio_ctrl_ops = {
 298        .s_ctrl = usb_ma901radio_s_ctrl,
 299};
 300
 301/* File system interface */
 302static const struct v4l2_file_operations usb_ma901radio_fops = {
 303        .owner          = THIS_MODULE,
 304        .open           = v4l2_fh_open,
 305        .release        = v4l2_fh_release,
 306        .poll           = v4l2_ctrl_poll,
 307        .unlocked_ioctl = video_ioctl2,
 308};
 309
 310static const struct v4l2_ioctl_ops usb_ma901radio_ioctl_ops = {
 311        .vidioc_querycap    = vidioc_querycap,
 312        .vidioc_g_tuner     = vidioc_g_tuner,
 313        .vidioc_s_tuner     = vidioc_s_tuner,
 314        .vidioc_g_frequency = vidioc_g_frequency,
 315        .vidioc_s_frequency = vidioc_s_frequency,
 316        .vidioc_log_status  = v4l2_ctrl_log_status,
 317        .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
 318        .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 319};
 320
 321static void usb_ma901radio_release(struct v4l2_device *v4l2_dev)
 322{
 323        struct ma901radio_device *radio = to_ma901radio_dev(v4l2_dev);
 324
 325        v4l2_ctrl_handler_free(&radio->hdl);
 326        v4l2_device_unregister(&radio->v4l2_dev);
 327        kfree(radio->buffer);
 328        kfree(radio);
 329}
 330
 331/* check if the device is present and register with v4l and usb if it is */
 332static int usb_ma901radio_probe(struct usb_interface *intf,
 333                                const struct usb_device_id *id)
 334{
 335        struct usb_device *dev = interface_to_usbdev(intf);
 336        struct ma901radio_device *radio;
 337        int retval = 0;
 338
 339        /* Masterkit MA901 usb radio has the same USB ID as many others
 340         * Atmel V-USB devices. Let's make additional checks to be sure
 341         * that this is our device.
 342         */
 343
 344        if (dev->product && dev->manufacturer &&
 345                (strncmp(dev->product, "MA901", 5) != 0
 346                || strncmp(dev->manufacturer, "www.masterkit.ru", 16) != 0))
 347                return -ENODEV;
 348
 349        radio = kzalloc(sizeof(struct ma901radio_device), GFP_KERNEL);
 350        if (!radio) {
 351                dev_err(&intf->dev, "kzalloc for ma901radio_device failed\n");
 352                retval = -ENOMEM;
 353                goto err;
 354        }
 355
 356        radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
 357        if (!radio->buffer) {
 358                dev_err(&intf->dev, "kmalloc for radio->buffer failed\n");
 359                retval = -ENOMEM;
 360                goto err_nobuf;
 361        }
 362
 363        retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev);
 364        if (retval < 0) {
 365                dev_err(&intf->dev, "couldn't register v4l2_device\n");
 366                goto err_v4l2;
 367        }
 368
 369        v4l2_ctrl_handler_init(&radio->hdl, 1);
 370
 371        /* TODO:It looks like this radio doesn't have mute/unmute control
 372         * and windows program just emulate it using volume control.
 373         * Let's plan to do the same in this driver.
 374         *
 375         * v4l2_ctrl_new_std(&radio->hdl, &usb_ma901radio_ctrl_ops,
 376         *                V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
 377         */
 378
 379        v4l2_ctrl_new_std(&radio->hdl, &usb_ma901radio_ctrl_ops,
 380                          V4L2_CID_AUDIO_VOLUME, MA901_VOLUME_MIN,
 381                          MA901_VOLUME_MAX, 1, MA901_VOLUME_MAX);
 382
 383        if (radio->hdl.error) {
 384                retval = radio->hdl.error;
 385                dev_err(&intf->dev, "couldn't register control\n");
 386                goto err_ctrl;
 387        }
 388        mutex_init(&radio->lock);
 389
 390        radio->v4l2_dev.ctrl_handler = &radio->hdl;
 391        radio->v4l2_dev.release = usb_ma901radio_release;
 392        strscpy(radio->vdev.name, radio->v4l2_dev.name,
 393                sizeof(radio->vdev.name));
 394        radio->vdev.v4l2_dev = &radio->v4l2_dev;
 395        radio->vdev.fops = &usb_ma901radio_fops;
 396        radio->vdev.ioctl_ops = &usb_ma901radio_ioctl_ops;
 397        radio->vdev.release = video_device_release_empty;
 398        radio->vdev.lock = &radio->lock;
 399        radio->vdev.device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER;
 400
 401        radio->usbdev = interface_to_usbdev(intf);
 402        radio->intf = intf;
 403        usb_set_intfdata(intf, &radio->v4l2_dev);
 404        radio->curfreq = 95.21 * FREQ_MUL;
 405
 406        video_set_drvdata(&radio->vdev, radio);
 407
 408        /* TODO: we can get some statistics (freq, volume) from device
 409         * but it's not implemented yet. After insertion in usb-port radio
 410         * setups frequency and starts playing without any initialization.
 411         * So we don't call usb_ma901radio_init/get_stat() here.
 412         * retval = usb_ma901radio_init(radio);
 413         */
 414
 415        retval = video_register_device(&radio->vdev, VFL_TYPE_RADIO,
 416                                        radio_nr);
 417        if (retval < 0) {
 418                dev_err(&intf->dev, "could not register video device\n");
 419                goto err_vdev;
 420        }
 421
 422        return 0;
 423
 424err_vdev:
 425        v4l2_ctrl_handler_free(&radio->hdl);
 426err_ctrl:
 427        v4l2_device_unregister(&radio->v4l2_dev);
 428err_v4l2:
 429        kfree(radio->buffer);
 430err_nobuf:
 431        kfree(radio);
 432err:
 433        return retval;
 434}
 435
 436/* USB Device ID List */
 437static const struct usb_device_id usb_ma901radio_device_table[] = {
 438        { USB_DEVICE_AND_INTERFACE_INFO(USB_MA901_VENDOR, USB_MA901_PRODUCT,
 439                                                        USB_CLASS_HID, 0, 0) },
 440        { }                                             /* Terminating entry */
 441};
 442
 443MODULE_DEVICE_TABLE(usb, usb_ma901radio_device_table);
 444
 445/* USB subsystem interface */
 446static struct usb_driver usb_ma901radio_driver = {
 447        .name                   = MA901_DRIVER_NAME,
 448        .probe                  = usb_ma901radio_probe,
 449        .disconnect             = usb_ma901radio_disconnect,
 450        .suspend                = usb_ma901radio_suspend,
 451        .resume                 = usb_ma901radio_resume,
 452        .reset_resume           = usb_ma901radio_resume,
 453        .id_table               = usb_ma901radio_device_table,
 454};
 455
 456module_usb_driver(usb_ma901radio_driver);
 457