linux/drivers/media/radio/radio-shark2.c
<<
>>
Prefs
   1/*
   2 * Linux V4L2 radio driver for the Griffin radioSHARK2 USB radio receiver
   3 *
   4 * Note the radioSHARK2 offers the audio through a regular USB audio device,
   5 * this driver only handles the tuning.
   6 *
   7 * The info necessary to drive the shark2 was taken from the small userspace
   8 * shark2.c program by Hisaaki Shibata, which he kindly placed in the Public
   9 * Domain.
  10 *
  11 * Copyright (c) 2012 Hans de Goede <hdegoede@redhat.com>
  12 *
  13 * This program is free software; you can redistribute it and/or modify
  14 * it under the terms of the GNU General Public License as published by
  15 * the Free Software Foundation; either version 2 of the License, or
  16 * (at your option) any later version.
  17 *
  18 * This program is distributed in the hope that it will be useful,
  19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21 * GNU General Public License for more details.
  22 */
  23
  24#include <linux/init.h>
  25#include <linux/kernel.h>
  26#include <linux/leds.h>
  27#include <linux/module.h>
  28#include <linux/slab.h>
  29#include <linux/usb.h>
  30#include <linux/workqueue.h>
  31#include <media/v4l2-device.h>
  32#include "radio-tea5777.h"
  33
  34#if defined(CONFIG_LEDS_CLASS) || \
  35    (defined(CONFIG_LEDS_CLASS_MODULE) && defined(CONFIG_RADIO_SHARK2_MODULE))
  36#define SHARK_USE_LEDS 1
  37#endif
  38
  39MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
  40MODULE_DESCRIPTION("Griffin radioSHARK2, USB radio receiver driver");
  41MODULE_LICENSE("GPL");
  42
  43static int debug;
  44module_param(debug, int, 0);
  45MODULE_PARM_DESC(debug, "Debug level (0-1)");
  46
  47#define SHARK_IN_EP             0x83
  48#define SHARK_OUT_EP            0x05
  49
  50#define TB_LEN 7
  51#define DRV_NAME "radioshark2"
  52
  53#define v4l2_dev_to_shark(d) container_of(d, struct shark_device, v4l2_dev)
  54
  55enum { BLUE_LED, RED_LED, NO_LEDS };
  56
  57struct shark_device {
  58        struct usb_device *usbdev;
  59        struct v4l2_device v4l2_dev;
  60        struct radio_tea5777 tea;
  61
  62#ifdef SHARK_USE_LEDS
  63        struct work_struct led_work;
  64        struct led_classdev leds[NO_LEDS];
  65        char led_names[NO_LEDS][32];
  66        atomic_t brightness[NO_LEDS];
  67        unsigned long brightness_new;
  68#endif
  69
  70        u8 *transfer_buffer;
  71};
  72
  73static atomic_t shark_instance = ATOMIC_INIT(0);
  74
  75static int shark_write_reg(struct radio_tea5777 *tea, u64 reg)
  76{
  77        struct shark_device *shark = tea->private_data;
  78        int i, res, actual_len;
  79
  80        memset(shark->transfer_buffer, 0, TB_LEN);
  81        shark->transfer_buffer[0] = 0x81; /* Write register command */
  82        for (i = 0; i < 6; i++)
  83                shark->transfer_buffer[i + 1] = (reg >> (40 - i * 8)) & 0xff;
  84
  85        v4l2_dbg(1, debug, tea->v4l2_dev, "shark2-write: %*ph\n",
  86                 7, shark->transfer_buffer);
  87
  88        res = usb_interrupt_msg(shark->usbdev,
  89                                usb_sndintpipe(shark->usbdev, SHARK_OUT_EP),
  90                                shark->transfer_buffer, TB_LEN,
  91                                &actual_len, 1000);
  92        if (res < 0) {
  93                v4l2_err(tea->v4l2_dev, "write error: %d\n", res);
  94                return res;
  95        }
  96
  97        return 0;
  98}
  99
 100static int shark_read_reg(struct radio_tea5777 *tea, u32 *reg_ret)
 101{
 102        struct shark_device *shark = tea->private_data;
 103        int i, res, actual_len;
 104        u32 reg = 0;
 105
 106        memset(shark->transfer_buffer, 0, TB_LEN);
 107        shark->transfer_buffer[0] = 0x82;
 108        res = usb_interrupt_msg(shark->usbdev,
 109                                usb_sndintpipe(shark->usbdev, SHARK_OUT_EP),
 110                                shark->transfer_buffer, TB_LEN,
 111                                &actual_len, 1000);
 112        if (res < 0) {
 113                v4l2_err(tea->v4l2_dev, "request-read error: %d\n", res);
 114                return res;
 115        }
 116
 117        res = usb_interrupt_msg(shark->usbdev,
 118                                usb_rcvintpipe(shark->usbdev, SHARK_IN_EP),
 119                                shark->transfer_buffer, TB_LEN,
 120                                &actual_len, 1000);
 121        if (res < 0) {
 122                v4l2_err(tea->v4l2_dev, "read error: %d\n", res);
 123                return res;
 124        }
 125
 126        for (i = 0; i < 3; i++)
 127                reg |= shark->transfer_buffer[i] << (16 - i * 8);
 128
 129        v4l2_dbg(1, debug, tea->v4l2_dev, "shark2-read: %*ph\n",
 130                 3, shark->transfer_buffer);
 131
 132        *reg_ret = reg;
 133        return 0;
 134}
 135
 136static const struct radio_tea5777_ops shark_tea_ops = {
 137        .write_reg = shark_write_reg,
 138        .read_reg  = shark_read_reg,
 139};
 140
 141#ifdef SHARK_USE_LEDS
 142static void shark_led_work(struct work_struct *work)
 143{
 144        struct shark_device *shark =
 145                container_of(work, struct shark_device, led_work);
 146        int i, res, brightness, actual_len;
 147
 148        for (i = 0; i < 2; i++) {
 149                if (!test_and_clear_bit(i, &shark->brightness_new))
 150                        continue;
 151
 152                brightness = atomic_read(&shark->brightness[i]);
 153                memset(shark->transfer_buffer, 0, TB_LEN);
 154                shark->transfer_buffer[0] = 0x83 + i;
 155                shark->transfer_buffer[1] = brightness;
 156                res = usb_interrupt_msg(shark->usbdev,
 157                                        usb_sndintpipe(shark->usbdev,
 158                                                       SHARK_OUT_EP),
 159                                        shark->transfer_buffer, TB_LEN,
 160                                        &actual_len, 1000);
 161                if (res < 0)
 162                        v4l2_err(&shark->v4l2_dev, "set LED %s error: %d\n",
 163                                 shark->led_names[i], res);
 164        }
 165}
 166
 167static void shark_led_set_blue(struct led_classdev *led_cdev,
 168                               enum led_brightness value)
 169{
 170        struct shark_device *shark =
 171                container_of(led_cdev, struct shark_device, leds[BLUE_LED]);
 172
 173        atomic_set(&shark->brightness[BLUE_LED], value);
 174        set_bit(BLUE_LED, &shark->brightness_new);
 175        schedule_work(&shark->led_work);
 176}
 177
 178static void shark_led_set_red(struct led_classdev *led_cdev,
 179                              enum led_brightness value)
 180{
 181        struct shark_device *shark =
 182                container_of(led_cdev, struct shark_device, leds[RED_LED]);
 183
 184        atomic_set(&shark->brightness[RED_LED], value);
 185        set_bit(RED_LED, &shark->brightness_new);
 186        schedule_work(&shark->led_work);
 187}
 188
 189static const struct led_classdev shark_led_templates[NO_LEDS] = {
 190        [BLUE_LED] = {
 191                .name           = "%s:blue:",
 192                .brightness     = LED_OFF,
 193                .max_brightness = 127,
 194                .brightness_set = shark_led_set_blue,
 195        },
 196        [RED_LED] = {
 197                .name           = "%s:red:",
 198                .brightness     = LED_OFF,
 199                .max_brightness = 1,
 200                .brightness_set = shark_led_set_red,
 201        },
 202};
 203
 204static int shark_register_leds(struct shark_device *shark, struct device *dev)
 205{
 206        int i, retval;
 207
 208        atomic_set(&shark->brightness[BLUE_LED], 127);
 209        INIT_WORK(&shark->led_work, shark_led_work);
 210        for (i = 0; i < NO_LEDS; i++) {
 211                shark->leds[i] = shark_led_templates[i];
 212                snprintf(shark->led_names[i], sizeof(shark->led_names[0]),
 213                         shark->leds[i].name, shark->v4l2_dev.name);
 214                shark->leds[i].name = shark->led_names[i];
 215                retval = led_classdev_register(dev, &shark->leds[i]);
 216                if (retval) {
 217                        v4l2_err(&shark->v4l2_dev,
 218                                 "couldn't register led: %s\n",
 219                                 shark->led_names[i]);
 220                        return retval;
 221                }
 222        }
 223        return 0;
 224}
 225
 226static void shark_unregister_leds(struct shark_device *shark)
 227{
 228        int i;
 229
 230        for (i = 0; i < NO_LEDS; i++)
 231                led_classdev_unregister(&shark->leds[i]);
 232
 233        cancel_work_sync(&shark->led_work);
 234}
 235
 236static inline void shark_resume_leds(struct shark_device *shark)
 237{
 238        int i;
 239
 240        for (i = 0; i < NO_LEDS; i++)
 241                set_bit(i, &shark->brightness_new);
 242
 243        schedule_work(&shark->led_work);
 244}
 245#else
 246static int shark_register_leds(struct shark_device *shark, struct device *dev)
 247{
 248        v4l2_warn(&shark->v4l2_dev,
 249                  "CONFIG_LEDS_CLASS not enabled, LED support disabled\n");
 250        return 0;
 251}
 252static inline void shark_unregister_leds(struct shark_device *shark) { }
 253static inline void shark_resume_leds(struct shark_device *shark) { }
 254#endif
 255
 256static void usb_shark_disconnect(struct usb_interface *intf)
 257{
 258        struct v4l2_device *v4l2_dev = usb_get_intfdata(intf);
 259        struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev);
 260
 261        mutex_lock(&shark->tea.mutex);
 262        v4l2_device_disconnect(&shark->v4l2_dev);
 263        radio_tea5777_exit(&shark->tea);
 264        mutex_unlock(&shark->tea.mutex);
 265
 266        shark_unregister_leds(shark);
 267
 268        v4l2_device_put(&shark->v4l2_dev);
 269}
 270
 271static void usb_shark_release(struct v4l2_device *v4l2_dev)
 272{
 273        struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev);
 274
 275        v4l2_device_unregister(&shark->v4l2_dev);
 276        kfree(shark->transfer_buffer);
 277        kfree(shark);
 278}
 279
 280static int usb_shark_probe(struct usb_interface *intf,
 281                           const struct usb_device_id *id)
 282{
 283        struct shark_device *shark;
 284        int retval = -ENOMEM;
 285
 286        shark = kzalloc(sizeof(struct shark_device), GFP_KERNEL);
 287        if (!shark)
 288                return retval;
 289
 290        shark->transfer_buffer = kmalloc(TB_LEN, GFP_KERNEL);
 291        if (!shark->transfer_buffer)
 292                goto err_alloc_buffer;
 293
 294        v4l2_device_set_name(&shark->v4l2_dev, DRV_NAME, &shark_instance);
 295
 296        retval = shark_register_leds(shark, &intf->dev);
 297        if (retval)
 298                goto err_reg_leds;
 299
 300        shark->v4l2_dev.release = usb_shark_release;
 301        retval = v4l2_device_register(&intf->dev, &shark->v4l2_dev);
 302        if (retval) {
 303                v4l2_err(&shark->v4l2_dev, "couldn't register v4l2_device\n");
 304                goto err_reg_dev;
 305        }
 306
 307        shark->usbdev = interface_to_usbdev(intf);
 308        shark->tea.v4l2_dev = &shark->v4l2_dev;
 309        shark->tea.private_data = shark;
 310        shark->tea.ops = &shark_tea_ops;
 311        shark->tea.has_am = true;
 312        shark->tea.write_before_read = true;
 313        strscpy(shark->tea.card, "Griffin radioSHARK2",
 314                sizeof(shark->tea.card));
 315        usb_make_path(shark->usbdev, shark->tea.bus_info,
 316                sizeof(shark->tea.bus_info));
 317
 318        retval = radio_tea5777_init(&shark->tea, THIS_MODULE);
 319        if (retval) {
 320                v4l2_err(&shark->v4l2_dev, "couldn't init tea5777\n");
 321                goto err_init_tea;
 322        }
 323
 324        return 0;
 325
 326err_init_tea:
 327        v4l2_device_unregister(&shark->v4l2_dev);
 328err_reg_dev:
 329        shark_unregister_leds(shark);
 330err_reg_leds:
 331        kfree(shark->transfer_buffer);
 332err_alloc_buffer:
 333        kfree(shark);
 334
 335        return retval;
 336}
 337
 338#ifdef CONFIG_PM
 339static int usb_shark_suspend(struct usb_interface *intf, pm_message_t message)
 340{
 341        return 0;
 342}
 343
 344static int usb_shark_resume(struct usb_interface *intf)
 345{
 346        struct v4l2_device *v4l2_dev = usb_get_intfdata(intf);
 347        struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev);
 348        int ret;
 349
 350        mutex_lock(&shark->tea.mutex);
 351        ret = radio_tea5777_set_freq(&shark->tea);
 352        mutex_unlock(&shark->tea.mutex);
 353
 354        shark_resume_leds(shark);
 355
 356        return ret;
 357}
 358#endif
 359
 360/* Specify the bcdDevice value, as the radioSHARK and radioSHARK2 share ids */
 361static const struct usb_device_id usb_shark_device_table[] = {
 362        { .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
 363                         USB_DEVICE_ID_MATCH_INT_CLASS,
 364          .idVendor     = 0x077d,
 365          .idProduct    = 0x627a,
 366          .bcdDevice_lo = 0x0010,
 367          .bcdDevice_hi = 0x0010,
 368          .bInterfaceClass = 3,
 369        },
 370        { }
 371};
 372MODULE_DEVICE_TABLE(usb, usb_shark_device_table);
 373
 374static struct usb_driver usb_shark_driver = {
 375        .name                   = DRV_NAME,
 376        .probe                  = usb_shark_probe,
 377        .disconnect             = usb_shark_disconnect,
 378        .id_table               = usb_shark_device_table,
 379#ifdef CONFIG_PM
 380        .suspend                = usb_shark_suspend,
 381        .resume                 = usb_shark_resume,
 382        .reset_resume           = usb_shark_resume,
 383#endif
 384};
 385module_usb_driver(usb_shark_driver);
 386