Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Linux V4L2 radio driver for the Griffin radioSHARK USB radio receiver
0003  *
0004  * Note the radioSHARK offers the audio through a regular USB audio device,
0005  * this driver only handles the tuning.
0006  *
0007  * The info necessary to drive the shark was taken from the small userspace
0008  * shark.c program by Michael Rolig, which he kindly placed in the Public
0009  * Domain.
0010  *
0011  * Copyright (c) 2012 Hans de Goede <hdegoede@redhat.com>
0012  *
0013  * This program is free software; you can redistribute it and/or modify
0014  * it under the terms of the GNU General Public License as published by
0015  * the Free Software Foundation; either version 2 of the License, or
0016  * (at your option) any later version.
0017  *
0018  * This program is distributed in the hope that it will be useful,
0019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0021  * GNU General Public License for more details.
0022 */
0023 
0024 #include <linux/init.h>
0025 #include <linux/kernel.h>
0026 #include <linux/leds.h>
0027 #include <linux/module.h>
0028 #include <linux/slab.h>
0029 #include <linux/usb.h>
0030 #include <linux/workqueue.h>
0031 #include <media/v4l2-device.h>
0032 #include <media/drv-intf/tea575x.h>
0033 
0034 #if defined(CONFIG_LEDS_CLASS) || \
0035     (defined(CONFIG_LEDS_CLASS_MODULE) && defined(CONFIG_RADIO_SHARK_MODULE))
0036 #define SHARK_USE_LEDS 1
0037 #endif
0038 
0039 /*
0040  * Version Information
0041  */
0042 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
0043 MODULE_DESCRIPTION("Griffin radioSHARK, USB radio receiver driver");
0044 MODULE_LICENSE("GPL");
0045 
0046 #define SHARK_IN_EP     0x83
0047 #define SHARK_OUT_EP        0x05
0048 
0049 #define TEA575X_BIT_MONO    (1<<22)     /* 0 = stereo, 1 = mono */
0050 #define TEA575X_BIT_BAND_MASK   (3<<20)
0051 #define TEA575X_BIT_BAND_FM (0<<20)
0052 
0053 #define TB_LEN 6
0054 #define DRV_NAME "radioshark"
0055 
0056 #define v4l2_dev_to_shark(d) container_of(d, struct shark_device, v4l2_dev)
0057 
0058 /* Note BLUE_IS_PULSE comes after NO_LEDS as it is a status bit, not a LED */
0059 enum { BLUE_LED, BLUE_PULSE_LED, RED_LED, NO_LEDS, BLUE_IS_PULSE };
0060 
0061 struct shark_device {
0062     struct usb_device *usbdev;
0063     struct v4l2_device v4l2_dev;
0064     struct snd_tea575x tea;
0065 
0066 #ifdef SHARK_USE_LEDS
0067     struct work_struct led_work;
0068     struct led_classdev leds[NO_LEDS];
0069     char led_names[NO_LEDS][32];
0070     atomic_t brightness[NO_LEDS];
0071     unsigned long brightness_new;
0072 #endif
0073 
0074     u8 *transfer_buffer;
0075     u32 last_val;
0076 };
0077 
0078 static atomic_t shark_instance = ATOMIC_INIT(0);
0079 
0080 static void shark_write_val(struct snd_tea575x *tea, u32 val)
0081 {
0082     struct shark_device *shark = tea->private_data;
0083     int i, res, actual_len;
0084 
0085     /* Avoid unnecessary (slow) USB transfers */
0086     if (shark->last_val == val)
0087         return;
0088 
0089     memset(shark->transfer_buffer, 0, TB_LEN);
0090     shark->transfer_buffer[0] = 0xc0; /* Write shift register command */
0091     for (i = 0; i < 4; i++)
0092         shark->transfer_buffer[i] |= (val >> (24 - i * 8)) & 0xff;
0093 
0094     res = usb_interrupt_msg(shark->usbdev,
0095                 usb_sndintpipe(shark->usbdev, SHARK_OUT_EP),
0096                 shark->transfer_buffer, TB_LEN,
0097                 &actual_len, 1000);
0098     if (res >= 0)
0099         shark->last_val = val;
0100     else
0101         v4l2_err(&shark->v4l2_dev, "set-freq error: %d\n", res);
0102 }
0103 
0104 static u32 shark_read_val(struct snd_tea575x *tea)
0105 {
0106     struct shark_device *shark = tea->private_data;
0107     int i, res, actual_len;
0108     u32 val = 0;
0109 
0110     memset(shark->transfer_buffer, 0, TB_LEN);
0111     shark->transfer_buffer[0] = 0x80;
0112     res = usb_interrupt_msg(shark->usbdev,
0113                 usb_sndintpipe(shark->usbdev, SHARK_OUT_EP),
0114                 shark->transfer_buffer, TB_LEN,
0115                 &actual_len, 1000);
0116     if (res < 0) {
0117         v4l2_err(&shark->v4l2_dev, "request-status error: %d\n", res);
0118         return shark->last_val;
0119     }
0120 
0121     res = usb_interrupt_msg(shark->usbdev,
0122                 usb_rcvintpipe(shark->usbdev, SHARK_IN_EP),
0123                 shark->transfer_buffer, TB_LEN,
0124                 &actual_len, 1000);
0125     if (res < 0) {
0126         v4l2_err(&shark->v4l2_dev, "get-status error: %d\n", res);
0127         return shark->last_val;
0128     }
0129 
0130     for (i = 0; i < 4; i++)
0131         val |= shark->transfer_buffer[i] << (24 - i * 8);
0132 
0133     shark->last_val = val;
0134 
0135     /*
0136      * The shark does not allow actually reading the stereo / mono pin :(
0137      * So assume that when we're tuned to an FM station and mono has not
0138      * been requested, that we're receiving stereo.
0139      */
0140     if (((val & TEA575X_BIT_BAND_MASK) == TEA575X_BIT_BAND_FM) &&
0141         !(val & TEA575X_BIT_MONO))
0142         shark->tea.stereo = true;
0143     else
0144         shark->tea.stereo = false;
0145 
0146     return val;
0147 }
0148 
0149 static const struct snd_tea575x_ops shark_tea_ops = {
0150     .write_val = shark_write_val,
0151     .read_val  = shark_read_val,
0152 };
0153 
0154 #ifdef SHARK_USE_LEDS
0155 static void shark_led_work(struct work_struct *work)
0156 {
0157     struct shark_device *shark =
0158         container_of(work, struct shark_device, led_work);
0159     int i, res, brightness, actual_len;
0160 
0161     for (i = 0; i < 3; i++) {
0162         if (!test_and_clear_bit(i, &shark->brightness_new))
0163             continue;
0164 
0165         brightness = atomic_read(&shark->brightness[i]);
0166         memset(shark->transfer_buffer, 0, TB_LEN);
0167         if (i != RED_LED) {
0168             shark->transfer_buffer[0] = 0xA0 + i;
0169             shark->transfer_buffer[1] = brightness;
0170         } else
0171             shark->transfer_buffer[0] = brightness ? 0xA9 : 0xA8;
0172         res = usb_interrupt_msg(shark->usbdev,
0173                     usb_sndintpipe(shark->usbdev, 0x05),
0174                     shark->transfer_buffer, TB_LEN,
0175                     &actual_len, 1000);
0176         if (res < 0)
0177             v4l2_err(&shark->v4l2_dev, "set LED %s error: %d\n",
0178                  shark->led_names[i], res);
0179     }
0180 }
0181 
0182 static void shark_led_set_blue(struct led_classdev *led_cdev,
0183                    enum led_brightness value)
0184 {
0185     struct shark_device *shark =
0186         container_of(led_cdev, struct shark_device, leds[BLUE_LED]);
0187 
0188     atomic_set(&shark->brightness[BLUE_LED], value);
0189     set_bit(BLUE_LED, &shark->brightness_new);
0190     clear_bit(BLUE_IS_PULSE, &shark->brightness_new);
0191     schedule_work(&shark->led_work);
0192 }
0193 
0194 static void shark_led_set_blue_pulse(struct led_classdev *led_cdev,
0195                      enum led_brightness value)
0196 {
0197     struct shark_device *shark = container_of(led_cdev,
0198                 struct shark_device, leds[BLUE_PULSE_LED]);
0199 
0200     atomic_set(&shark->brightness[BLUE_PULSE_LED], 256 - value);
0201     set_bit(BLUE_PULSE_LED, &shark->brightness_new);
0202     set_bit(BLUE_IS_PULSE, &shark->brightness_new);
0203     schedule_work(&shark->led_work);
0204 }
0205 
0206 static void shark_led_set_red(struct led_classdev *led_cdev,
0207                   enum led_brightness value)
0208 {
0209     struct shark_device *shark =
0210         container_of(led_cdev, struct shark_device, leds[RED_LED]);
0211 
0212     atomic_set(&shark->brightness[RED_LED], value);
0213     set_bit(RED_LED, &shark->brightness_new);
0214     schedule_work(&shark->led_work);
0215 }
0216 
0217 static const struct led_classdev shark_led_templates[NO_LEDS] = {
0218     [BLUE_LED] = {
0219         .name       = "%s:blue:",
0220         .brightness = LED_OFF,
0221         .max_brightness = 127,
0222         .brightness_set = shark_led_set_blue,
0223     },
0224     [BLUE_PULSE_LED] = {
0225         .name       = "%s:blue-pulse:",
0226         .brightness = LED_OFF,
0227         .max_brightness = 255,
0228         .brightness_set = shark_led_set_blue_pulse,
0229     },
0230     [RED_LED] = {
0231         .name       = "%s:red:",
0232         .brightness = LED_OFF,
0233         .max_brightness = 1,
0234         .brightness_set = shark_led_set_red,
0235     },
0236 };
0237 
0238 static int shark_register_leds(struct shark_device *shark, struct device *dev)
0239 {
0240     int i, retval;
0241 
0242     atomic_set(&shark->brightness[BLUE_LED], 127);
0243     INIT_WORK(&shark->led_work, shark_led_work);
0244     for (i = 0; i < NO_LEDS; i++) {
0245         shark->leds[i] = shark_led_templates[i];
0246         snprintf(shark->led_names[i], sizeof(shark->led_names[0]),
0247              shark->leds[i].name, shark->v4l2_dev.name);
0248         shark->leds[i].name = shark->led_names[i];
0249         retval = led_classdev_register(dev, &shark->leds[i]);
0250         if (retval) {
0251             v4l2_err(&shark->v4l2_dev,
0252                  "couldn't register led: %s\n",
0253                  shark->led_names[i]);
0254             return retval;
0255         }
0256     }
0257     return 0;
0258 }
0259 
0260 static void shark_unregister_leds(struct shark_device *shark)
0261 {
0262     int i;
0263 
0264     for (i = 0; i < NO_LEDS; i++)
0265         led_classdev_unregister(&shark->leds[i]);
0266 
0267     cancel_work_sync(&shark->led_work);
0268 }
0269 
0270 static inline void shark_resume_leds(struct shark_device *shark)
0271 {
0272     if (test_bit(BLUE_IS_PULSE, &shark->brightness_new))
0273         set_bit(BLUE_PULSE_LED, &shark->brightness_new);
0274     else
0275         set_bit(BLUE_LED, &shark->brightness_new);
0276     set_bit(RED_LED, &shark->brightness_new);
0277     schedule_work(&shark->led_work);
0278 }
0279 #else
0280 static int shark_register_leds(struct shark_device *shark, struct device *dev)
0281 {
0282     v4l2_warn(&shark->v4l2_dev,
0283           "CONFIG_LEDS_CLASS not enabled, LED support disabled\n");
0284     return 0;
0285 }
0286 static inline void shark_unregister_leds(struct shark_device *shark) { }
0287 static inline void shark_resume_leds(struct shark_device *shark) { }
0288 #endif
0289 
0290 static void usb_shark_disconnect(struct usb_interface *intf)
0291 {
0292     struct v4l2_device *v4l2_dev = usb_get_intfdata(intf);
0293     struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev);
0294 
0295     mutex_lock(&shark->tea.mutex);
0296     v4l2_device_disconnect(&shark->v4l2_dev);
0297     snd_tea575x_exit(&shark->tea);
0298     mutex_unlock(&shark->tea.mutex);
0299 
0300     shark_unregister_leds(shark);
0301 
0302     v4l2_device_put(&shark->v4l2_dev);
0303 }
0304 
0305 static void usb_shark_release(struct v4l2_device *v4l2_dev)
0306 {
0307     struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev);
0308 
0309     v4l2_device_unregister(&shark->v4l2_dev);
0310     kfree(shark->transfer_buffer);
0311     kfree(shark);
0312 }
0313 
0314 static int usb_shark_probe(struct usb_interface *intf,
0315                const struct usb_device_id *id)
0316 {
0317     struct shark_device *shark;
0318     int retval = -ENOMEM;
0319 
0320     shark = kzalloc(sizeof(struct shark_device), GFP_KERNEL);
0321     if (!shark)
0322         return retval;
0323 
0324     shark->transfer_buffer = kmalloc(TB_LEN, GFP_KERNEL);
0325     if (!shark->transfer_buffer)
0326         goto err_alloc_buffer;
0327 
0328     v4l2_device_set_name(&shark->v4l2_dev, DRV_NAME, &shark_instance);
0329 
0330     retval = shark_register_leds(shark, &intf->dev);
0331     if (retval)
0332         goto err_reg_leds;
0333 
0334     shark->v4l2_dev.release = usb_shark_release;
0335     retval = v4l2_device_register(&intf->dev, &shark->v4l2_dev);
0336     if (retval) {
0337         v4l2_err(&shark->v4l2_dev, "couldn't register v4l2_device\n");
0338         goto err_reg_dev;
0339     }
0340 
0341     shark->usbdev = interface_to_usbdev(intf);
0342     shark->tea.v4l2_dev = &shark->v4l2_dev;
0343     shark->tea.private_data = shark;
0344     shark->tea.radio_nr = -1;
0345     shark->tea.ops = &shark_tea_ops;
0346     shark->tea.cannot_mute = true;
0347     shark->tea.has_am = true;
0348     strscpy(shark->tea.card, "Griffin radioSHARK",
0349         sizeof(shark->tea.card));
0350     usb_make_path(shark->usbdev, shark->tea.bus_info,
0351         sizeof(shark->tea.bus_info));
0352 
0353     retval = snd_tea575x_init(&shark->tea, THIS_MODULE);
0354     if (retval) {
0355         v4l2_err(&shark->v4l2_dev, "couldn't init tea5757\n");
0356         goto err_init_tea;
0357     }
0358 
0359     return 0;
0360 
0361 err_init_tea:
0362     v4l2_device_unregister(&shark->v4l2_dev);
0363 err_reg_dev:
0364     shark_unregister_leds(shark);
0365 err_reg_leds:
0366     kfree(shark->transfer_buffer);
0367 err_alloc_buffer:
0368     kfree(shark);
0369 
0370     return retval;
0371 }
0372 
0373 #ifdef CONFIG_PM
0374 static int usb_shark_suspend(struct usb_interface *intf, pm_message_t message)
0375 {
0376     return 0;
0377 }
0378 
0379 static int usb_shark_resume(struct usb_interface *intf)
0380 {
0381     struct v4l2_device *v4l2_dev = usb_get_intfdata(intf);
0382     struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev);
0383 
0384     mutex_lock(&shark->tea.mutex);
0385     snd_tea575x_set_freq(&shark->tea);
0386     mutex_unlock(&shark->tea.mutex);
0387 
0388     shark_resume_leds(shark);
0389 
0390     return 0;
0391 }
0392 #endif
0393 
0394 /* Specify the bcdDevice value, as the radioSHARK and radioSHARK2 share ids */
0395 static const struct usb_device_id usb_shark_device_table[] = {
0396     { .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
0397              USB_DEVICE_ID_MATCH_INT_CLASS,
0398       .idVendor     = 0x077d,
0399       .idProduct    = 0x627a,
0400       .bcdDevice_lo = 0x0001,
0401       .bcdDevice_hi = 0x0001,
0402       .bInterfaceClass = 3,
0403     },
0404     { }
0405 };
0406 MODULE_DEVICE_TABLE(usb, usb_shark_device_table);
0407 
0408 static struct usb_driver usb_shark_driver = {
0409     .name           = DRV_NAME,
0410     .probe          = usb_shark_probe,
0411     .disconnect     = usb_shark_disconnect,
0412     .id_table       = usb_shark_device_table,
0413 #ifdef CONFIG_PM
0414     .suspend        = usb_shark_suspend,
0415     .resume         = usb_shark_resume,
0416     .reset_resume       = usb_shark_resume,
0417 #endif
0418 };
0419 module_usb_driver(usb_shark_driver);