linux/drivers/media/radio/radio-mr800.c
<<
>>
Prefs
   1/*
   2 * A driver for the AverMedia MR 800 USB FM radio. This device plugs
   3 * into both the USB and an analog audio input, so this thing
   4 * only deals with initialization and frequency setting, the
   5 * audio data has to be handled by a sound driver.
   6 *
   7 * Copyright (c) 2008 Alexey Klimov <klimov.linux@gmail.com>
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License as published by
  11 * the Free Software Foundation; either version 2 of the License, or
  12 * (at your option) any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; if not, write to the Free Software
  21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22 */
  23
  24/*
  25 * Big thanks to authors and contributors of dsbr100.c and radio-si470x.c
  26 *
  27 * When work was looked pretty good, i discover this:
  28 * http://av-usbradio.sourceforge.net/index.php
  29 * http://sourceforge.net/projects/av-usbradio/
  30 * Latest release of theirs project was in 2005.
  31 * Probably, this driver could be improved through using their
  32 * achievements (specifications given).
  33 * Also, Faidon Liambotis <paravoid@debian.org> wrote nice driver for this radio
  34 * in 2007. He allowed to use his driver to improve current mr800 radio driver.
  35 * http://kerneltrap.org/mailarchive/linux-usb-devel/2007/10/11/342492
  36 *
  37 * Version 0.01:        First working version.
  38 *                      It's required to blacklist AverMedia USB Radio
  39 *                      in usbhid/hid-quirks.c
  40 * Version 0.10:        A lot of cleanups and fixes: unpluging the device,
  41 *                      few mutex locks were added, codinstyle issues, etc.
  42 *                      Added stereo support. Thanks to
  43 *                      Douglas Schilling Landgraf <dougsland@gmail.com> and
  44 *                      David Ellingsworth <david@identd.dyndns.org>
  45 *                      for discussion, help and support.
  46 * Version 0.11:        Converted to v4l2_device.
  47 *
  48 * Many things to do:
  49 *      - Correct power management of device (suspend & resume)
  50 *      - Add code for scanning and smooth tuning
  51 *      - Add code for sensitivity value
  52 *      - Correct mistakes
  53 *      - In Japan another FREQ_MIN and FREQ_MAX
  54 */
  55
  56/* kernel includes */
  57#include <linux/kernel.h>
  58#include <linux/module.h>
  59#include <linux/init.h>
  60#include <linux/slab.h>
  61#include <linux/input.h>
  62#include <linux/videodev2.h>
  63#include <media/v4l2-device.h>
  64#include <media/v4l2-ioctl.h>
  65#include <linux/usb.h>
  66#include <linux/version.h>      /* for KERNEL_VERSION MACRO */
  67#include <linux/mutex.h>
  68
  69/* driver and module definitions */
  70#define DRIVER_AUTHOR "Alexey Klimov <klimov.linux@gmail.com>"
  71#define DRIVER_DESC "AverMedia MR 800 USB FM radio driver"
  72#define DRIVER_VERSION "0.11"
  73#define RADIO_VERSION KERNEL_VERSION(0, 1, 1)
  74
  75MODULE_AUTHOR(DRIVER_AUTHOR);
  76MODULE_DESCRIPTION(DRIVER_DESC);
  77MODULE_LICENSE("GPL");
  78
  79#define USB_AMRADIO_VENDOR 0x07ca
  80#define USB_AMRADIO_PRODUCT 0xb800
  81
  82/* dev_warn macro with driver name */
  83#define MR800_DRIVER_NAME "radio-mr800"
  84#define amradio_dev_warn(dev, fmt, arg...)                              \
  85                dev_warn(dev, MR800_DRIVER_NAME " - " fmt, ##arg)
  86
  87#define amradio_dev_err(dev, fmt, arg...) \
  88                dev_err(dev, MR800_DRIVER_NAME " - " fmt, ##arg)
  89
  90/* Probably USB_TIMEOUT should be modified in module parameter */
  91#define BUFFER_LENGTH 8
  92#define USB_TIMEOUT 500
  93
  94/* Frequency limits in MHz -- these are European values.  For Japanese
  95devices, that would be 76 and 91.  */
  96#define FREQ_MIN  87.5
  97#define FREQ_MAX 108.0
  98#define FREQ_MUL 16000
  99
 100/*
 101 * Commands that device should understand
 102 * List isnt full and will be updated with implementation of new functions
 103 */
 104#define AMRADIO_SET_FREQ        0xa4
 105#define AMRADIO_SET_MUTE        0xab
 106#define AMRADIO_SET_MONO        0xae
 107
 108/* Comfortable defines for amradio_set_mute */
 109#define AMRADIO_START           0x00
 110#define AMRADIO_STOP            0x01
 111
 112/* Comfortable defines for amradio_set_stereo */
 113#define WANT_STEREO             0x00
 114#define WANT_MONO               0x01
 115
 116/* module parameter */
 117static int radio_nr = -1;
 118module_param(radio_nr, int, 0);
 119MODULE_PARM_DESC(radio_nr, "Radio Nr");
 120
 121static int usb_amradio_probe(struct usb_interface *intf,
 122                             const struct usb_device_id *id);
 123static void usb_amradio_disconnect(struct usb_interface *intf);
 124static int usb_amradio_open(struct file *file);
 125static int usb_amradio_close(struct file *file);
 126static int usb_amradio_suspend(struct usb_interface *intf,
 127                                pm_message_t message);
 128static int usb_amradio_resume(struct usb_interface *intf);
 129
 130/* Data for one (physical) device */
 131struct amradio_device {
 132        /* reference to USB and video device */
 133        struct usb_device *usbdev;
 134        struct usb_interface *intf;
 135        struct video_device videodev;
 136        struct v4l2_device v4l2_dev;
 137
 138        unsigned char *buffer;
 139        struct mutex lock;      /* buffer locking */
 140        int curfreq;
 141        int stereo;
 142        int muted;
 143        int initialized;
 144};
 145
 146static inline struct amradio_device *to_amradio_dev(struct v4l2_device *v4l2_dev)
 147{
 148        return container_of(v4l2_dev, struct amradio_device, v4l2_dev);
 149}
 150
 151/* USB Device ID List */
 152static struct usb_device_id usb_amradio_device_table[] = {
 153        {USB_DEVICE_AND_INTERFACE_INFO(USB_AMRADIO_VENDOR, USB_AMRADIO_PRODUCT,
 154                                                        USB_CLASS_HID, 0, 0) },
 155        { }                                             /* Terminating entry */
 156};
 157
 158MODULE_DEVICE_TABLE(usb, usb_amradio_device_table);
 159
 160/* USB subsystem interface */
 161static struct usb_driver usb_amradio_driver = {
 162        .name                   = MR800_DRIVER_NAME,
 163        .probe                  = usb_amradio_probe,
 164        .disconnect             = usb_amradio_disconnect,
 165        .suspend                = usb_amradio_suspend,
 166        .resume                 = usb_amradio_resume,
 167        .reset_resume           = usb_amradio_resume,
 168        .id_table               = usb_amradio_device_table,
 169        .supports_autosuspend   = 1,
 170};
 171
 172/* switch on/off the radio. Send 8 bytes to device */
 173static int amradio_set_mute(struct amradio_device *radio, char argument)
 174{
 175        int retval;
 176        int size;
 177
 178        radio->buffer[0] = 0x00;
 179        radio->buffer[1] = 0x55;
 180        radio->buffer[2] = 0xaa;
 181        radio->buffer[3] = 0x00;
 182        radio->buffer[4] = AMRADIO_SET_MUTE;
 183        radio->buffer[5] = argument;
 184        radio->buffer[6] = 0x00;
 185        radio->buffer[7] = 0x00;
 186
 187        retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
 188                (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
 189
 190        if (retval < 0 || size != BUFFER_LENGTH) {
 191                amradio_dev_warn(&radio->videodev.dev, "set mute failed\n");
 192                return retval;
 193        }
 194
 195        radio->muted = argument;
 196
 197        return retval;
 198}
 199
 200/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
 201static int amradio_setfreq(struct amradio_device *radio, int freq)
 202{
 203        int retval;
 204        int size;
 205        unsigned short freq_send = 0x10 + (freq >> 3) / 25;
 206
 207        radio->buffer[0] = 0x00;
 208        radio->buffer[1] = 0x55;
 209        radio->buffer[2] = 0xaa;
 210        radio->buffer[3] = 0x03;
 211        radio->buffer[4] = AMRADIO_SET_FREQ;
 212        radio->buffer[5] = 0x00;
 213        radio->buffer[6] = 0x00;
 214        radio->buffer[7] = 0x08;
 215
 216        retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
 217                (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
 218
 219        if (retval < 0 || size != BUFFER_LENGTH)
 220                goto out_err;
 221
 222        /* frequency is calculated from freq_send and placed in first 2 bytes */
 223        radio->buffer[0] = (freq_send >> 8) & 0xff;
 224        radio->buffer[1] = freq_send & 0xff;
 225        radio->buffer[2] = 0x01;
 226        radio->buffer[3] = 0x00;
 227        radio->buffer[4] = 0x00;
 228        /* 5 and 6 bytes of buffer already = 0x00 */
 229        radio->buffer[7] = 0x00;
 230
 231        retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
 232                (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
 233
 234        if (retval < 0 || size != BUFFER_LENGTH)
 235                goto out_err;
 236
 237        radio->curfreq = freq;
 238        goto out;
 239
 240out_err:
 241        amradio_dev_warn(&radio->videodev.dev, "set frequency failed\n");
 242out:
 243        return retval;
 244}
 245
 246static int amradio_set_stereo(struct amradio_device *radio, char argument)
 247{
 248        int retval;
 249        int size;
 250
 251        radio->buffer[0] = 0x00;
 252        radio->buffer[1] = 0x55;
 253        radio->buffer[2] = 0xaa;
 254        radio->buffer[3] = 0x00;
 255        radio->buffer[4] = AMRADIO_SET_MONO;
 256        radio->buffer[5] = argument;
 257        radio->buffer[6] = 0x00;
 258        radio->buffer[7] = 0x00;
 259
 260        retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
 261                (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
 262
 263        if (retval < 0 || size != BUFFER_LENGTH) {
 264                amradio_dev_warn(&radio->videodev.dev, "set stereo failed\n");
 265                return retval;
 266        }
 267
 268        if (argument == WANT_STEREO)
 269                radio->stereo = 1;
 270        else
 271                radio->stereo = 0;
 272
 273        return retval;
 274}
 275
 276/* Handle unplugging the device.
 277 * We call video_unregister_device in any case.
 278 * The last function called in this procedure is
 279 * usb_amradio_device_release.
 280 */
 281static void usb_amradio_disconnect(struct usb_interface *intf)
 282{
 283        struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf));
 284
 285        mutex_lock(&radio->lock);
 286        /* increase the device node's refcount */
 287        get_device(&radio->videodev.dev);
 288        v4l2_device_disconnect(&radio->v4l2_dev);
 289        video_unregister_device(&radio->videodev);
 290        mutex_unlock(&radio->lock);
 291        /* decrease the device node's refcount, allowing it to be released */
 292        put_device(&radio->videodev.dev);
 293}
 294
 295/* vidioc_querycap - query device capabilities */
 296static int vidioc_querycap(struct file *file, void *priv,
 297                                        struct v4l2_capability *v)
 298{
 299        struct amradio_device *radio = file->private_data;
 300
 301        strlcpy(v->driver, "radio-mr800", sizeof(v->driver));
 302        strlcpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card));
 303        usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
 304        v->version = RADIO_VERSION;
 305        v->capabilities = V4L2_CAP_TUNER;
 306        return 0;
 307}
 308
 309/* vidioc_g_tuner - get tuner attributes */
 310static int vidioc_g_tuner(struct file *file, void *priv,
 311                                struct v4l2_tuner *v)
 312{
 313        struct amradio_device *radio = file->private_data;
 314        int retval;
 315
 316        if (v->index > 0)
 317                return -EINVAL;
 318
 319/* TODO: Add function which look is signal stereo or not
 320 *      amradio_getstat(radio);
 321 */
 322
 323/* we call amradio_set_stereo to set radio->stereo
 324 * Honestly, amradio_getstat should cover this in future and
 325 * amradio_set_stereo shouldn't be here
 326 */
 327        retval = amradio_set_stereo(radio, WANT_STEREO);
 328
 329        strcpy(v->name, "FM");
 330        v->type = V4L2_TUNER_RADIO;
 331        v->rangelow = FREQ_MIN * FREQ_MUL;
 332        v->rangehigh = FREQ_MAX * FREQ_MUL;
 333        v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
 334        v->capability = V4L2_TUNER_CAP_LOW;
 335        if (radio->stereo)
 336                v->audmode = V4L2_TUNER_MODE_STEREO;
 337        else
 338                v->audmode = V4L2_TUNER_MODE_MONO;
 339        v->signal = 0xffff;     /* Can't get the signal strength, sad.. */
 340        v->afc = 0; /* Don't know what is this */
 341
 342        return retval;
 343}
 344
 345/* vidioc_s_tuner - set tuner attributes */
 346static int vidioc_s_tuner(struct file *file, void *priv,
 347                                struct v4l2_tuner *v)
 348{
 349        struct amradio_device *radio = file->private_data;
 350        int retval = -EINVAL;
 351
 352        if (v->index > 0)
 353                return -EINVAL;
 354
 355        /* mono/stereo selector */
 356        switch (v->audmode) {
 357        case V4L2_TUNER_MODE_MONO:
 358                retval = amradio_set_stereo(radio, WANT_MONO);
 359                break;
 360        case V4L2_TUNER_MODE_STEREO:
 361                retval = amradio_set_stereo(radio, WANT_STEREO);
 362                break;
 363        }
 364
 365        return retval;
 366}
 367
 368/* vidioc_s_frequency - set tuner radio frequency */
 369static int vidioc_s_frequency(struct file *file, void *priv,
 370                                struct v4l2_frequency *f)
 371{
 372        struct amradio_device *radio = file->private_data;
 373
 374        if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
 375                return -EINVAL;
 376        return amradio_setfreq(radio, f->frequency);
 377}
 378
 379/* vidioc_g_frequency - get tuner radio frequency */
 380static int vidioc_g_frequency(struct file *file, void *priv,
 381                                struct v4l2_frequency *f)
 382{
 383        struct amradio_device *radio = file->private_data;
 384
 385        if (f->tuner != 0)
 386                return -EINVAL;
 387        f->type = V4L2_TUNER_RADIO;
 388        f->frequency = radio->curfreq;
 389
 390        return 0;
 391}
 392
 393/* vidioc_queryctrl - enumerate control items */
 394static int vidioc_queryctrl(struct file *file, void *priv,
 395                                struct v4l2_queryctrl *qc)
 396{
 397        switch (qc->id) {
 398        case V4L2_CID_AUDIO_MUTE:
 399                return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
 400        }
 401
 402        return -EINVAL;
 403}
 404
 405/* vidioc_g_ctrl - get the value of a control */
 406static int vidioc_g_ctrl(struct file *file, void *priv,
 407                                struct v4l2_control *ctrl)
 408{
 409        struct amradio_device *radio = file->private_data;
 410
 411        switch (ctrl->id) {
 412        case V4L2_CID_AUDIO_MUTE:
 413                ctrl->value = radio->muted;
 414                return 0;
 415        }
 416
 417        return -EINVAL;
 418}
 419
 420/* vidioc_s_ctrl - set the value of a control */
 421static int vidioc_s_ctrl(struct file *file, void *priv,
 422                                struct v4l2_control *ctrl)
 423{
 424        struct amradio_device *radio = file->private_data;
 425        int retval = -EINVAL;
 426
 427        switch (ctrl->id) {
 428        case V4L2_CID_AUDIO_MUTE:
 429                if (ctrl->value)
 430                        retval = amradio_set_mute(radio, AMRADIO_STOP);
 431                else
 432                        retval = amradio_set_mute(radio, AMRADIO_START);
 433
 434                break;
 435        }
 436
 437        return retval;
 438}
 439
 440/* vidioc_g_audio - get audio attributes */
 441static int vidioc_g_audio(struct file *file, void *priv,
 442                                struct v4l2_audio *a)
 443{
 444        if (a->index > 1)
 445                return -EINVAL;
 446
 447        strcpy(a->name, "Radio");
 448        a->capability = V4L2_AUDCAP_STEREO;
 449        return 0;
 450}
 451
 452/* vidioc_s_audio - set audio attributes  */
 453static int vidioc_s_audio(struct file *file, void *priv,
 454                                        struct v4l2_audio *a)
 455{
 456        if (a->index != 0)
 457                return -EINVAL;
 458        return 0;
 459}
 460
 461/* vidioc_g_input - get input */
 462static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
 463{
 464        *i = 0;
 465        return 0;
 466}
 467
 468/* vidioc_s_input - set input */
 469static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
 470{
 471        if (i != 0)
 472                return -EINVAL;
 473        return 0;
 474}
 475
 476static int usb_amradio_init(struct amradio_device *radio)
 477{
 478        int retval;
 479
 480        retval = amradio_set_mute(radio, AMRADIO_STOP);
 481        if (retval)
 482                goto out_err;
 483
 484        retval = amradio_set_stereo(radio, WANT_STEREO);
 485        if (retval)
 486                goto out_err;
 487
 488        radio->initialized = 1;
 489        goto out;
 490
 491out_err:
 492        amradio_dev_err(&radio->videodev.dev, "initialization failed\n");
 493out:
 494        return retval;
 495}
 496
 497/* open device - amradio_start() and amradio_setfreq() */
 498static int usb_amradio_open(struct file *file)
 499{
 500        struct amradio_device *radio = video_drvdata(file);
 501        int retval;
 502
 503        file->private_data = radio;
 504        retval = usb_autopm_get_interface(radio->intf);
 505        if (retval)
 506                return retval;
 507
 508        if (unlikely(!radio->initialized)) {
 509                retval = usb_amradio_init(radio);
 510                if (retval)
 511                        usb_autopm_put_interface(radio->intf);
 512        }
 513        return retval;
 514}
 515
 516/*close device */
 517static int usb_amradio_close(struct file *file)
 518{
 519        struct amradio_device *radio = file->private_data;
 520
 521        if (video_is_registered(&radio->videodev))
 522                usb_autopm_put_interface(radio->intf);
 523        return 0;
 524}
 525
 526/* Suspend device - stop device. Need to be checked and fixed */
 527static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message)
 528{
 529        struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf));
 530
 531        mutex_lock(&radio->lock);
 532        if (!radio->muted && radio->initialized) {
 533                amradio_set_mute(radio, AMRADIO_STOP);
 534                radio->muted = 0;
 535        }
 536        mutex_unlock(&radio->lock);
 537
 538        dev_info(&intf->dev, "going into suspend..\n");
 539        return 0;
 540}
 541
 542/* Resume device - start device. Need to be checked and fixed */
 543static int usb_amradio_resume(struct usb_interface *intf)
 544{
 545        struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf));
 546
 547        mutex_lock(&radio->lock);
 548        if (unlikely(!radio->initialized))
 549                goto unlock;
 550
 551        if (radio->stereo)
 552                amradio_set_stereo(radio, WANT_STEREO);
 553        else
 554                amradio_set_stereo(radio, WANT_MONO);
 555
 556        amradio_setfreq(radio, radio->curfreq);
 557
 558        if (!radio->muted)
 559                amradio_set_mute(radio, AMRADIO_START);
 560
 561unlock:
 562        mutex_unlock(&radio->lock);
 563
 564        dev_info(&intf->dev, "coming out of suspend..\n");
 565        return 0;
 566}
 567
 568/* File system interface */
 569static const struct v4l2_file_operations usb_amradio_fops = {
 570        .owner          = THIS_MODULE,
 571        .open           = usb_amradio_open,
 572        .release        = usb_amradio_close,
 573        .unlocked_ioctl = video_ioctl2,
 574};
 575
 576static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = {
 577        .vidioc_querycap    = vidioc_querycap,
 578        .vidioc_g_tuner     = vidioc_g_tuner,
 579        .vidioc_s_tuner     = vidioc_s_tuner,
 580        .vidioc_g_frequency = vidioc_g_frequency,
 581        .vidioc_s_frequency = vidioc_s_frequency,
 582        .vidioc_queryctrl   = vidioc_queryctrl,
 583        .vidioc_g_ctrl      = vidioc_g_ctrl,
 584        .vidioc_s_ctrl      = vidioc_s_ctrl,
 585        .vidioc_g_audio     = vidioc_g_audio,
 586        .vidioc_s_audio     = vidioc_s_audio,
 587        .vidioc_g_input     = vidioc_g_input,
 588        .vidioc_s_input     = vidioc_s_input,
 589};
 590
 591static void usb_amradio_video_device_release(struct video_device *videodev)
 592{
 593        struct amradio_device *radio = video_get_drvdata(videodev);
 594
 595        /* free rest memory */
 596        kfree(radio->buffer);
 597        kfree(radio);
 598}
 599
 600/* check if the device is present and register with v4l and usb if it is */
 601static int usb_amradio_probe(struct usb_interface *intf,
 602                                const struct usb_device_id *id)
 603{
 604        struct amradio_device *radio;
 605        int retval = 0;
 606
 607        radio = kzalloc(sizeof(struct amradio_device), GFP_KERNEL);
 608
 609        if (!radio) {
 610                dev_err(&intf->dev, "kmalloc for amradio_device failed\n");
 611                retval = -ENOMEM;
 612                goto err;
 613        }
 614
 615        radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
 616
 617        if (!radio->buffer) {
 618                dev_err(&intf->dev, "kmalloc for radio->buffer failed\n");
 619                retval = -ENOMEM;
 620                goto err_nobuf;
 621        }
 622
 623        retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev);
 624        if (retval < 0) {
 625                dev_err(&intf->dev, "couldn't register v4l2_device\n");
 626                goto err_v4l2;
 627        }
 628
 629        mutex_init(&radio->lock);
 630
 631        strlcpy(radio->videodev.name, radio->v4l2_dev.name,
 632                sizeof(radio->videodev.name));
 633        radio->videodev.v4l2_dev = &radio->v4l2_dev;
 634        radio->videodev.fops = &usb_amradio_fops;
 635        radio->videodev.ioctl_ops = &usb_amradio_ioctl_ops;
 636        radio->videodev.release = usb_amradio_video_device_release;
 637        radio->videodev.lock = &radio->lock;
 638
 639        radio->usbdev = interface_to_usbdev(intf);
 640        radio->intf = intf;
 641        radio->curfreq = 95.16 * FREQ_MUL;
 642
 643        video_set_drvdata(&radio->videodev, radio);
 644
 645        retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO,
 646                                        radio_nr);
 647        if (retval < 0) {
 648                dev_err(&intf->dev, "could not register video device\n");
 649                goto err_vdev;
 650        }
 651
 652        return 0;
 653
 654err_vdev:
 655        v4l2_device_unregister(&radio->v4l2_dev);
 656err_v4l2:
 657        kfree(radio->buffer);
 658err_nobuf:
 659        kfree(radio);
 660err:
 661        return retval;
 662}
 663
 664static int __init amradio_init(void)
 665{
 666        int retval = usb_register(&usb_amradio_driver);
 667
 668        pr_info(KBUILD_MODNAME
 669                ": version " DRIVER_VERSION " " DRIVER_DESC "\n");
 670
 671        if (retval)
 672                pr_err(KBUILD_MODNAME
 673                        ": usb_register failed. Error number %d\n", retval);
 674
 675        return retval;
 676}
 677
 678static void __exit amradio_exit(void)
 679{
 680        usb_deregister(&usb_amradio_driver);
 681}
 682
 683module_init(amradio_init);
 684module_exit(amradio_exit);
 685
 686