855 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * drivers/media/radio/si470x/radio-si470x-usb.c4 *5 * USB driver for radios with Silicon Labs Si470x FM Radio Receivers6 *7 * Copyright (c) 2009 Tobias Lorenz <tobias.lorenz@gmx.net>8 */9 10 11/*12 * ToDo:13 * - add firmware download/update support14 */15 16 17/* driver definitions */18#define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>"19#define DRIVER_CARD "Silicon Labs Si470x FM Radio"20#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"21#define DRIVER_VERSION "1.0.10"22 23/* kernel includes */24#include <linux/usb.h>25#include <linux/hid.h>26#include <linux/slab.h>27 28#include "radio-si470x.h"29 30 31/* USB Device ID List */32static const struct usb_device_id si470x_usb_driver_id_table[] = {33 /* Silicon Labs USB FM Radio Reference Design */34 { USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) },35 /* ADS/Tech FM Radio Receiver (formerly Instant FM Music) */36 { USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) },37 /* KWorld USB FM Radio SnapMusic Mobile 700 (FM700) */38 { USB_DEVICE_AND_INTERFACE_INFO(0x1b80, 0xd700, USB_CLASS_HID, 0, 0) },39 /* Sanei Electric, Inc. FM USB Radio (sold as DealExtreme.com PCear) */40 { USB_DEVICE_AND_INTERFACE_INFO(0x10c5, 0x819a, USB_CLASS_HID, 0, 0) },41 /* Axentia ALERT FM USB Receiver */42 { USB_DEVICE_AND_INTERFACE_INFO(0x12cf, 0x7111, USB_CLASS_HID, 0, 0) },43 /* Terminating entry */44 { }45};46MODULE_DEVICE_TABLE(usb, si470x_usb_driver_id_table);47 48 49 50/**************************************************************************51 * Module Parameters52 **************************************************************************/53 54/* Radio Nr */55static int radio_nr = -1;56module_param(radio_nr, int, 0444);57MODULE_PARM_DESC(radio_nr, "Radio Nr");58 59/* USB timeout */60static unsigned int usb_timeout = 500;61module_param(usb_timeout, uint, 0644);62MODULE_PARM_DESC(usb_timeout, "USB timeout (ms): *500*");63 64/* RDS buffer blocks */65static unsigned int rds_buf = 100;66module_param(rds_buf, uint, 0444);67MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");68 69/* RDS maximum block errors */70static unsigned short max_rds_errors = 1;71/* 0 means 0 errors requiring correction */72/* 1 means 1-2 errors requiring correction (used by original USBRadio.exe) */73/* 2 means 3-5 errors requiring correction */74/* 3 means 6+ errors or errors in checkword, correction not possible */75module_param(max_rds_errors, ushort, 0644);76MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*");77 78 79 80/**************************************************************************81 * USB HID Reports82 **************************************************************************/83 84/* Reports 1-16 give direct read/write access to the 16 Si470x registers */85/* with the (REPORT_ID - 1) corresponding to the register address across USB */86/* endpoint 0 using GET_REPORT and SET_REPORT */87#define REGISTER_REPORT_SIZE (RADIO_REGISTER_SIZE + 1)88#define REGISTER_REPORT(reg) ((reg) + 1)89 90/* Report 17 gives direct read/write access to the entire Si470x register */91/* map across endpoint 0 using GET_REPORT and SET_REPORT */92#define ENTIRE_REPORT_SIZE (RADIO_REGISTER_NUM * RADIO_REGISTER_SIZE + 1)93#define ENTIRE_REPORT 1794 95/* Report 18 is used to send the lowest 6 Si470x registers up the HID */96/* interrupt endpoint 1 to Windows every 20 milliseconds for status */97#define RDS_REPORT_SIZE (RDS_REGISTER_NUM * RADIO_REGISTER_SIZE + 1)98#define RDS_REPORT 1899 100/* Report 19: LED state */101#define LED_REPORT_SIZE 3102#define LED_REPORT 19103 104/* Report 19: stream */105#define STREAM_REPORT_SIZE 3106#define STREAM_REPORT 19107 108/* Report 20: scratch */109#define SCRATCH_PAGE_SIZE 63110#define SCRATCH_REPORT_SIZE (SCRATCH_PAGE_SIZE + 1)111#define SCRATCH_REPORT 20112 113/* Reports 19-22: flash upgrade of the C8051F321 */114#define WRITE_REPORT_SIZE 4115#define WRITE_REPORT 19116#define FLASH_REPORT_SIZE 64117#define FLASH_REPORT 20118#define CRC_REPORT_SIZE 3119#define CRC_REPORT 21120#define RESPONSE_REPORT_SIZE 2121#define RESPONSE_REPORT 22122 123/* Report 23: currently unused, but can accept 60 byte reports on the HID */124/* interrupt out endpoint 2 every 1 millisecond */125#define UNUSED_REPORT 23126 127#define MAX_REPORT_SIZE 64128 129 130 131/**************************************************************************132 * Software/Hardware Versions from Scratch Page133 **************************************************************************/134#define RADIO_HW_VERSION 1135 136 137 138/**************************************************************************139 * LED State Definitions140 **************************************************************************/141#define LED_COMMAND 0x35142 143#define NO_CHANGE_LED 0x00144#define ALL_COLOR_LED 0x01 /* streaming state */145#define BLINK_GREEN_LED 0x02 /* connect state */146#define BLINK_RED_LED 0x04147#define BLINK_ORANGE_LED 0x10 /* disconnect state */148#define SOLID_GREEN_LED 0x20 /* tuning/seeking state */149#define SOLID_RED_LED 0x40 /* bootload state */150#define SOLID_ORANGE_LED 0x80151 152 153 154/**************************************************************************155 * Stream State Definitions156 **************************************************************************/157#define STREAM_COMMAND 0x36158#define STREAM_VIDPID 0x00159#define STREAM_AUDIO 0xff160 161 162 163/**************************************************************************164 * Bootloader / Flash Commands165 **************************************************************************/166 167/* unique id sent to bootloader and required to put into a bootload state */168#define UNIQUE_BL_ID 0x34169 170/* mask for the flash data */171#define FLASH_DATA_MASK 0x55172 173/* bootloader commands */174#define GET_SW_VERSION_COMMAND 0x00175#define SET_PAGE_COMMAND 0x01176#define ERASE_PAGE_COMMAND 0x02177#define WRITE_PAGE_COMMAND 0x03178#define CRC_ON_PAGE_COMMAND 0x04179#define READ_FLASH_BYTE_COMMAND 0x05180#define RESET_DEVICE_COMMAND 0x06181#define GET_HW_VERSION_COMMAND 0x07182#define BLANK 0xff183 184/* bootloader command responses */185#define COMMAND_OK 0x01186#define COMMAND_FAILED 0x02187#define COMMAND_PENDING 0x03188 189 190 191/**************************************************************************192 * General Driver Functions - REGISTER_REPORTs193 **************************************************************************/194 195/*196 * si470x_get_report - receive a HID report197 */198static int si470x_get_report(struct si470x_device *radio, void *buf, int size)199{200 unsigned char *report = buf;201 int retval;202 203 retval = usb_control_msg(radio->usbdev,204 usb_rcvctrlpipe(radio->usbdev, 0),205 HID_REQ_GET_REPORT,206 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,207 report[0], 2,208 buf, size, usb_timeout);209 210 if (retval < 0)211 dev_warn(&radio->intf->dev,212 "si470x_get_report: usb_control_msg returned %d\n",213 retval);214 return retval;215}216 217 218/*219 * si470x_set_report - send a HID report220 */221static int si470x_set_report(struct si470x_device *radio, void *buf, int size)222{223 unsigned char *report = buf;224 int retval;225 226 retval = usb_control_msg(radio->usbdev,227 usb_sndctrlpipe(radio->usbdev, 0),228 HID_REQ_SET_REPORT,229 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,230 report[0], 2,231 buf, size, usb_timeout);232 233 if (retval < 0)234 dev_warn(&radio->intf->dev,235 "si470x_set_report: usb_control_msg returned %d\n",236 retval);237 return retval;238}239 240 241/*242 * si470x_get_register - read register243 */244static int si470x_get_register(struct si470x_device *radio, int regnr)245{246 int retval;247 248 radio->usb_buf[0] = REGISTER_REPORT(regnr);249 250 retval = si470x_get_report(radio, radio->usb_buf, REGISTER_REPORT_SIZE);251 252 if (retval >= 0)253 radio->registers[regnr] = get_unaligned_be16(&radio->usb_buf[1]);254 255 return (retval < 0) ? -EINVAL : 0;256}257 258 259/*260 * si470x_set_register - write register261 */262static int si470x_set_register(struct si470x_device *radio, int regnr)263{264 int retval;265 266 radio->usb_buf[0] = REGISTER_REPORT(regnr);267 put_unaligned_be16(radio->registers[regnr], &radio->usb_buf[1]);268 269 retval = si470x_set_report(radio, radio->usb_buf, REGISTER_REPORT_SIZE);270 271 return (retval < 0) ? -EINVAL : 0;272}273 274 275 276/**************************************************************************277 * General Driver Functions - ENTIRE_REPORT278 **************************************************************************/279 280/*281 * si470x_get_all_registers - read entire registers282 */283static int si470x_get_all_registers(struct si470x_device *radio)284{285 int retval;286 unsigned char regnr;287 288 radio->usb_buf[0] = ENTIRE_REPORT;289 290 retval = si470x_get_report(radio, radio->usb_buf, ENTIRE_REPORT_SIZE);291 292 if (retval >= 0)293 for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++)294 radio->registers[regnr] = get_unaligned_be16(295 &radio->usb_buf[regnr * RADIO_REGISTER_SIZE + 1]);296 297 return (retval < 0) ? -EINVAL : 0;298}299 300 301 302/**************************************************************************303 * General Driver Functions - LED_REPORT304 **************************************************************************/305 306/*307 * si470x_set_led_state - sets the led state308 */309static int si470x_set_led_state(struct si470x_device *radio,310 unsigned char led_state)311{312 int retval;313 314 radio->usb_buf[0] = LED_REPORT;315 radio->usb_buf[1] = LED_COMMAND;316 radio->usb_buf[2] = led_state;317 318 retval = si470x_set_report(radio, radio->usb_buf, LED_REPORT_SIZE);319 320 return (retval < 0) ? -EINVAL : 0;321}322 323 324 325/**************************************************************************326 * General Driver Functions - SCRATCH_REPORT327 **************************************************************************/328 329/*330 * si470x_get_scratch_versions - gets the scratch page and version infos331 */332static int si470x_get_scratch_page_versions(struct si470x_device *radio)333{334 int retval;335 336 radio->usb_buf[0] = SCRATCH_REPORT;337 338 retval = si470x_get_report(radio, radio->usb_buf, SCRATCH_REPORT_SIZE);339 340 if (retval < 0)341 dev_warn(&radio->intf->dev, "si470x_get_scratch: si470x_get_report returned %d\n",342 retval);343 else {344 radio->software_version = radio->usb_buf[1];345 radio->hardware_version = radio->usb_buf[2];346 }347 348 return (retval < 0) ? -EINVAL : 0;349}350 351 352 353/**************************************************************************354 * RDS Driver Functions355 **************************************************************************/356 357/*358 * si470x_int_in_callback - rds callback and processing function359 *360 * TODO: do we need to use mutex locks in some sections?361 */362static void si470x_int_in_callback(struct urb *urb)363{364 struct si470x_device *radio = urb->context;365 int retval;366 unsigned char regnr;367 unsigned char blocknum;368 unsigned short bler; /* rds block errors */369 unsigned short rds;370 unsigned char tmpbuf[3];371 372 if (urb->status) {373 if (urb->status == -ENOENT ||374 urb->status == -ECONNRESET ||375 urb->status == -ESHUTDOWN) {376 return;377 } else {378 dev_warn(&radio->intf->dev,379 "non-zero urb status (%d)\n", urb->status);380 goto resubmit; /* Maybe we can recover. */381 }382 }383 384 /* Sometimes the device returns len 0 packets */385 if (urb->actual_length != RDS_REPORT_SIZE)386 goto resubmit;387 388 radio->registers[STATUSRSSI] =389 get_unaligned_be16(&radio->int_in_buffer[1]);390 391 if (radio->registers[STATUSRSSI] & STATUSRSSI_STC)392 complete(&radio->completion);393 394 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS)) {395 /* Update RDS registers with URB data */396 for (regnr = 1; regnr < RDS_REGISTER_NUM; regnr++)397 radio->registers[STATUSRSSI + regnr] =398 get_unaligned_be16(&radio->int_in_buffer[399 regnr * RADIO_REGISTER_SIZE + 1]);400 /* get rds blocks */401 if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0) {402 /* No RDS group ready, better luck next time */403 goto resubmit;404 }405 if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSS) == 0) {406 /* RDS decoder not synchronized */407 goto resubmit;408 }409 for (blocknum = 0; blocknum < 4; blocknum++) {410 switch (blocknum) {411 default:412 bler = (radio->registers[STATUSRSSI] &413 STATUSRSSI_BLERA) >> 9;414 rds = radio->registers[RDSA];415 break;416 case 1:417 bler = (radio->registers[READCHAN] &418 READCHAN_BLERB) >> 14;419 rds = radio->registers[RDSB];420 break;421 case 2:422 bler = (radio->registers[READCHAN] &423 READCHAN_BLERC) >> 12;424 rds = radio->registers[RDSC];425 break;426 case 3:427 bler = (radio->registers[READCHAN] &428 READCHAN_BLERD) >> 10;429 rds = radio->registers[RDSD];430 break;431 }432 433 /* Fill the V4L2 RDS buffer */434 put_unaligned_le16(rds, &tmpbuf);435 tmpbuf[2] = blocknum; /* offset name */436 tmpbuf[2] |= blocknum << 3; /* received offset */437 if (bler > max_rds_errors)438 tmpbuf[2] |= 0x80; /* uncorrectable errors */439 else if (bler > 0)440 tmpbuf[2] |= 0x40; /* corrected error(s) */441 442 /* copy RDS block to internal buffer */443 memcpy(&radio->buffer[radio->wr_index], &tmpbuf, 3);444 radio->wr_index += 3;445 446 /* wrap write pointer */447 if (radio->wr_index >= radio->buf_size)448 radio->wr_index = 0;449 450 /* check for overflow */451 if (radio->wr_index == radio->rd_index) {452 /* increment and wrap read pointer */453 radio->rd_index += 3;454 if (radio->rd_index >= radio->buf_size)455 radio->rd_index = 0;456 }457 }458 if (radio->wr_index != radio->rd_index)459 wake_up_interruptible(&radio->read_queue);460 }461 462resubmit:463 /* Resubmit if we're still running. */464 if (radio->int_in_running && radio->usbdev) {465 retval = usb_submit_urb(radio->int_in_urb, GFP_ATOMIC);466 if (retval) {467 dev_warn(&radio->intf->dev,468 "resubmitting urb failed (%d)", retval);469 radio->int_in_running = 0;470 }471 }472 radio->status_rssi_auto_update = radio->int_in_running;473}474 475 476static int si470x_fops_open(struct file *file)477{478 return v4l2_fh_open(file);479}480 481static int si470x_fops_release(struct file *file)482{483 return v4l2_fh_release(file);484}485 486static void si470x_usb_release(struct v4l2_device *v4l2_dev)487{488 struct si470x_device *radio =489 container_of(v4l2_dev, struct si470x_device, v4l2_dev);490 491 usb_free_urb(radio->int_in_urb);492 v4l2_ctrl_handler_free(&radio->hdl);493 v4l2_device_unregister(&radio->v4l2_dev);494 kfree(radio->int_in_buffer);495 kfree(radio->buffer);496 kfree(radio->usb_buf);497 kfree(radio);498}499 500 501/**************************************************************************502 * Video4Linux Interface503 **************************************************************************/504 505/*506 * si470x_vidioc_querycap - query device capabilities507 */508static int si470x_vidioc_querycap(struct file *file, void *priv,509 struct v4l2_capability *capability)510{511 struct si470x_device *radio = video_drvdata(file);512 513 strscpy(capability->driver, DRIVER_NAME, sizeof(capability->driver));514 strscpy(capability->card, DRIVER_CARD, sizeof(capability->card));515 usb_make_path(radio->usbdev, capability->bus_info,516 sizeof(capability->bus_info));517 return 0;518}519 520 521static int si470x_start_usb(struct si470x_device *radio)522{523 int retval;524 525 /* initialize interrupt urb */526 usb_fill_int_urb(radio->int_in_urb, radio->usbdev,527 usb_rcvintpipe(radio->usbdev,528 radio->int_in_endpoint->bEndpointAddress),529 radio->int_in_buffer,530 le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize),531 si470x_int_in_callback,532 radio,533 radio->int_in_endpoint->bInterval);534 535 radio->int_in_running = 1;536 mb();537 538 retval = usb_submit_urb(radio->int_in_urb, GFP_KERNEL);539 if (retval) {540 dev_info(&radio->intf->dev,541 "submitting int urb failed (%d)\n", retval);542 radio->int_in_running = 0;543 }544 radio->status_rssi_auto_update = radio->int_in_running;545 546 /* start radio */547 retval = si470x_start(radio);548 if (retval < 0)549 return retval;550 551 v4l2_ctrl_handler_setup(&radio->hdl);552 553 return retval;554}555 556/**************************************************************************557 * USB Interface558 **************************************************************************/559 560/*561 * si470x_usb_driver_probe - probe for the device562 */563static int si470x_usb_driver_probe(struct usb_interface *intf,564 const struct usb_device_id *id)565{566 struct si470x_device *radio;567 struct usb_host_interface *iface_desc;568 struct usb_endpoint_descriptor *endpoint;569 int i, int_end_size, retval;570 unsigned char version_warning = 0;571 572 /* private data allocation and initialization */573 radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL);574 if (!radio) {575 retval = -ENOMEM;576 goto err_initial;577 }578 radio->usb_buf = kmalloc(MAX_REPORT_SIZE, GFP_KERNEL);579 if (radio->usb_buf == NULL) {580 retval = -ENOMEM;581 goto err_radio;582 }583 radio->usbdev = interface_to_usbdev(intf);584 radio->intf = intf;585 radio->band = 1; /* Default to 76 - 108 MHz */586 mutex_init(&radio->lock);587 init_completion(&radio->completion);588 589 radio->get_register = si470x_get_register;590 radio->set_register = si470x_set_register;591 radio->fops_open = si470x_fops_open;592 radio->fops_release = si470x_fops_release;593 radio->vidioc_querycap = si470x_vidioc_querycap;594 595 iface_desc = intf->cur_altsetting;596 597 /* Set up interrupt endpoint information. */598 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {599 endpoint = &iface_desc->endpoint[i].desc;600 if (usb_endpoint_is_int_in(endpoint))601 radio->int_in_endpoint = endpoint;602 }603 if (!radio->int_in_endpoint) {604 dev_info(&intf->dev, "could not find interrupt in endpoint\n");605 retval = -EIO;606 goto err_usbbuf;607 }608 609 int_end_size = le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize);610 611 radio->int_in_buffer = kmalloc(int_end_size, GFP_KERNEL);612 if (!radio->int_in_buffer) {613 dev_info(&intf->dev, "could not allocate int_in_buffer");614 retval = -ENOMEM;615 goto err_usbbuf;616 }617 618 radio->int_in_urb = usb_alloc_urb(0, GFP_KERNEL);619 if (!radio->int_in_urb) {620 retval = -ENOMEM;621 goto err_intbuffer;622 }623 624 radio->v4l2_dev.release = si470x_usb_release;625 626 /*627 * The si470x SiLabs reference design uses the same USB IDs as628 * 'Thanko's Raremono' si4734 based receiver. So check here which we629 * have: attempt to read the device ID from the si470x: the lower 12630 * bits should be 0x0242 for the si470x.631 *632 * We use this check to determine which device we are dealing with.633 */634 if (id->idVendor == 0x10c4 && id->idProduct == 0x818a) {635 retval = usb_control_msg(radio->usbdev,636 usb_rcvctrlpipe(radio->usbdev, 0),637 HID_REQ_GET_REPORT,638 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,639 1, 2,640 radio->usb_buf, 3, 500);641 if (retval != 3 ||642 (get_unaligned_be16(&radio->usb_buf[1]) & 0xfff) != 0x0242) {643 dev_info(&intf->dev, "this is not a si470x device.\n");644 retval = -ENODEV;645 goto err_urb;646 }647 }648 649 retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev);650 if (retval < 0) {651 dev_err(&intf->dev, "couldn't register v4l2_device\n");652 goto err_urb;653 }654 655 v4l2_ctrl_handler_init(&radio->hdl, 2);656 v4l2_ctrl_new_std(&radio->hdl, &si470x_ctrl_ops,657 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);658 v4l2_ctrl_new_std(&radio->hdl, &si470x_ctrl_ops,659 V4L2_CID_AUDIO_VOLUME, 0, 15, 1, 15);660 if (radio->hdl.error) {661 retval = radio->hdl.error;662 dev_err(&intf->dev, "couldn't register control\n");663 goto err_dev;664 }665 radio->videodev = si470x_viddev_template;666 radio->videodev.ctrl_handler = &radio->hdl;667 radio->videodev.lock = &radio->lock;668 radio->videodev.v4l2_dev = &radio->v4l2_dev;669 radio->videodev.release = video_device_release_empty;670 radio->videodev.device_caps =671 V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_READWRITE | V4L2_CAP_TUNER |672 V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE;673 video_set_drvdata(&radio->videodev, radio);674 675 /* get device and chip versions */676 if (si470x_get_all_registers(radio) < 0) {677 retval = -EIO;678 goto err_ctrl;679 }680 dev_info(&intf->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n",681 radio->registers[DEVICEID], radio->registers[SI_CHIPID]);682 if ((radio->registers[SI_CHIPID] & SI_CHIPID_FIRMWARE) < RADIO_FW_VERSION) {683 dev_warn(&intf->dev,684 "This driver is known to work with firmware version %u, but the device has firmware version %u.\n",685 RADIO_FW_VERSION,686 radio->registers[SI_CHIPID] & SI_CHIPID_FIRMWARE);687 version_warning = 1;688 }689 690 /* get software and hardware versions */691 if (si470x_get_scratch_page_versions(radio) < 0) {692 retval = -EIO;693 goto err_ctrl;694 }695 dev_info(&intf->dev, "software version %d, hardware version %d\n",696 radio->software_version, radio->hardware_version);697 if (radio->hardware_version < RADIO_HW_VERSION) {698 dev_warn(&intf->dev,699 "This driver is known to work with hardware version %u, but the device has hardware version %u.\n",700 RADIO_HW_VERSION,701 radio->hardware_version);702 version_warning = 1;703 }704 705 /* give out version warning */706 if (version_warning == 1) {707 dev_warn(&intf->dev,708 "If you have some trouble using this driver, please report to V4L ML at linux-media@vger.kernel.org\n");709 }710 711 /* set led to connect state */712 si470x_set_led_state(radio, BLINK_GREEN_LED);713 714 /* rds buffer allocation */715 radio->buf_size = rds_buf * 3;716 radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);717 if (!radio->buffer) {718 retval = -EIO;719 goto err_ctrl;720 }721 722 /* rds buffer configuration */723 radio->wr_index = 0;724 radio->rd_index = 0;725 init_waitqueue_head(&radio->read_queue);726 usb_set_intfdata(intf, radio);727 728 /* start radio */729 retval = si470x_start_usb(radio);730 if (retval < 0 && !radio->int_in_running)731 goto err_buf;732 else if (retval < 0) /* in case of radio->int_in_running == 1 */733 goto err_all;734 735 /* set initial frequency */736 si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */737 738 /* register video device */739 retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO,740 radio_nr);741 if (retval) {742 dev_err(&intf->dev, "Could not register video device\n");743 goto err_all;744 }745 746 return 0;747err_all:748 usb_kill_urb(radio->int_in_urb);749err_buf:750 kfree(radio->buffer);751err_ctrl:752 v4l2_ctrl_handler_free(&radio->hdl);753err_dev:754 v4l2_device_unregister(&radio->v4l2_dev);755err_urb:756 usb_free_urb(radio->int_in_urb);757err_intbuffer:758 kfree(radio->int_in_buffer);759err_usbbuf:760 kfree(radio->usb_buf);761err_radio:762 kfree(radio);763err_initial:764 return retval;765}766 767 768/*769 * si470x_usb_driver_suspend - suspend the device770 */771static int si470x_usb_driver_suspend(struct usb_interface *intf,772 pm_message_t message)773{774 struct si470x_device *radio = usb_get_intfdata(intf);775 776 dev_info(&intf->dev, "suspending now...\n");777 778 /* shutdown interrupt handler */779 if (radio->int_in_running) {780 radio->int_in_running = 0;781 if (radio->int_in_urb)782 usb_kill_urb(radio->int_in_urb);783 }784 785 /* cancel read processes */786 wake_up_interruptible(&radio->read_queue);787 788 /* stop radio */789 si470x_stop(radio);790 return 0;791}792 793 794/*795 * si470x_usb_driver_resume - resume the device796 */797static int si470x_usb_driver_resume(struct usb_interface *intf)798{799 struct si470x_device *radio = usb_get_intfdata(intf);800 int ret;801 802 dev_info(&intf->dev, "resuming now...\n");803 804 /* start radio */805 ret = si470x_start_usb(radio);806 if (ret == 0)807 v4l2_ctrl_handler_setup(&radio->hdl);808 809 return ret;810}811 812 813/*814 * si470x_usb_driver_disconnect - disconnect the device815 */816static void si470x_usb_driver_disconnect(struct usb_interface *intf)817{818 struct si470x_device *radio = usb_get_intfdata(intf);819 820 mutex_lock(&radio->lock);821 v4l2_device_disconnect(&radio->v4l2_dev);822 video_unregister_device(&radio->videodev);823 usb_kill_urb(radio->int_in_urb);824 usb_set_intfdata(intf, NULL);825 mutex_unlock(&radio->lock);826 v4l2_device_put(&radio->v4l2_dev);827}828 829 830/*831 * si470x_usb_driver - usb driver interface832 *833 * A note on suspend/resume: this driver had only empty suspend/resume834 * functions, and when I tried to test suspend/resume it always disconnected835 * instead of resuming (using my ADS InstantFM stick). So I've decided to836 * remove these callbacks until someone else with better hardware can837 * implement and test this.838 */839static struct usb_driver si470x_usb_driver = {840 .name = DRIVER_NAME,841 .probe = si470x_usb_driver_probe,842 .disconnect = si470x_usb_driver_disconnect,843 .suspend = si470x_usb_driver_suspend,844 .resume = si470x_usb_driver_resume,845 .reset_resume = si470x_usb_driver_resume,846 .id_table = si470x_usb_driver_id_table,847};848 849module_usb_driver(si470x_usb_driver);850 851MODULE_LICENSE("GPL");852MODULE_AUTHOR(DRIVER_AUTHOR);853MODULE_DESCRIPTION(DRIVER_DESC);854MODULE_VERSION(DRIVER_VERSION);855