diff options
author | Takashi Iwai <tiwai@suse.de> | 2015-01-28 07:24:41 +0100 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2015-01-28 07:24:41 +0100 |
commit | 5e0ddd07fa8fcbb84faac666d36ff9c37449a849 (patch) | |
tree | 29ff039af456f0aed5280943bc9e1593893b5b21 /sound/usb/line6/toneport.c | |
parent | 1001fb810b1295d0600c0c6bdcb17889460470a5 (diff) | |
parent | 247d95ee6dd22e5323ecf7a73ff64110ef2fa2da (diff) | |
download | linux-5e0ddd07fa8fcbb84faac666d36ff9c37449a849.tar.bz2 |
Merge branch 'topic/line6' into for-next
Diffstat (limited to 'sound/usb/line6/toneport.c')
-rw-r--r-- | sound/usb/line6/toneport.c | 216 |
1 files changed, 113 insertions, 103 deletions
diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c index c1f61cde52ab..819e06b3f3db 100644 --- a/sound/usb/line6/toneport.c +++ b/sound/usb/line6/toneport.c @@ -14,6 +14,7 @@ #include <linux/usb.h> #include <linux/slab.h> #include <linux/module.h> +#include <linux/leds.h> #include <sound/core.h> #include <sound/control.h> @@ -32,6 +33,15 @@ enum line6_device_type { LINE6_TONEPORT_UX2, }; +struct usb_line6_toneport; + +struct toneport_led { + struct led_classdev dev; + char name[64]; + struct usb_line6_toneport *toneport; + bool registered; +}; + struct usb_line6_toneport { /** Generic Line 6 USB data. @@ -62,6 +72,9 @@ struct usb_line6_toneport { Device type. */ enum line6_device_type type; + + /* LED instances */ + struct toneport_led leds[2]; }; static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2); @@ -117,15 +130,6 @@ static struct line6_pcm_properties toneport_pcm_properties = { .bytes_per_frame = 4 }; -/* - For the led on Guitarport. - Brightness goes from 0x00 to 0x26. Set a value above this to have led - blink. - (void cmd_0x02(byte red, byte green) -*/ -static int led_red = 0x00; -static int led_green = 0x26; - static const struct { const char *name; int code; @@ -136,62 +140,6 @@ static const struct { {"Inst & Mic", 0x0901} }; -static bool toneport_has_led(enum line6_device_type type) -{ - return - (type == LINE6_GUITARPORT) || - (type == LINE6_TONEPORT_GX); - /* add your device here if you are missing support for the LEDs */ -} - -static void toneport_update_led(struct device *dev) -{ - struct usb_interface *interface = to_usb_interface(dev); - struct usb_line6_toneport *tp = usb_get_intfdata(interface); - struct usb_line6 *line6; - - if (!tp) - return; - - line6 = &tp->line6; - if (line6) - toneport_send_cmd(line6->usbdev, (led_red << 8) | 0x0002, - led_green); -} - -static ssize_t toneport_set_led_red(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int retval; - - retval = kstrtoint(buf, 10, &led_red); - if (retval) - return retval; - - toneport_update_led(dev); - return count; -} - -static ssize_t toneport_set_led_green(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int retval; - - retval = kstrtoint(buf, 10, &led_green); - if (retval) - return retval; - - toneport_update_led(dev); - return count; -} - -static DEVICE_ATTR(led_red, S_IWUSR | S_IRUGO, line6_nop_read, - toneport_set_led_red); -static DEVICE_ATTR(led_green, S_IWUSR | S_IRUGO, line6_nop_read, - toneport_set_led_green); - static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2) { int ret; @@ -234,16 +182,23 @@ static int snd_toneport_monitor_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); + int err; if (ucontrol->value.integer.value[0] == line6pcm->volume_monitor) return 0; line6pcm->volume_monitor = ucontrol->value.integer.value[0]; - if (line6pcm->volume_monitor > 0) - line6_pcm_acquire(line6pcm, LINE6_BITS_PCM_MONITOR); - else - line6_pcm_release(line6pcm, LINE6_BITS_PCM_MONITOR); + if (line6pcm->volume_monitor > 0) { + err = line6_pcm_acquire(line6pcm, LINE6_STREAM_MONITOR); + if (err < 0) { + line6pcm->volume_monitor = 0; + line6_pcm_release(line6pcm, LINE6_STREAM_MONITOR); + return err; + } + } else { + line6_pcm_release(line6pcm, LINE6_STREAM_MONITOR); + } return 1; } @@ -304,7 +259,7 @@ static void toneport_start_pcm(unsigned long arg) struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)arg; struct usb_line6 *line6 = &toneport->line6; - line6_pcm_acquire(line6->line6pcm, LINE6_BITS_PCM_MONITOR); + line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR); } /* control definition */ @@ -330,6 +285,78 @@ static struct snd_kcontrol_new toneport_control_source = { }; /* + For the led on Guitarport. + Brightness goes from 0x00 to 0x26. Set a value above this to have led + blink. + (void cmd_0x02(byte red, byte green) +*/ + +static bool toneport_has_led(enum line6_device_type type) +{ + return + (type == LINE6_GUITARPORT) || + (type == LINE6_TONEPORT_GX); + /* add your device here if you are missing support for the LEDs */ +} + +static const char * const led_colors[2] = { "red", "green" }; +static const int led_init_vals[2] = { 0x00, 0x26 }; + +static void toneport_update_led(struct usb_line6_toneport *toneport) +{ + toneport_send_cmd(toneport->line6.usbdev, + (toneport->leds[0].dev.brightness << 8) | 0x0002, + toneport->leds[1].dev.brightness); +} + +static void toneport_led_brightness_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct toneport_led *leds = + container_of(led_cdev, struct toneport_led, dev); + toneport_update_led(leds->toneport); +} + +static int toneport_init_leds(struct usb_line6_toneport *toneport) +{ + struct device *dev = &toneport->line6.usbdev->dev; + int i, err; + + for (i = 0; i < 2; i++) { + struct toneport_led *led = &toneport->leds[i]; + struct led_classdev *leddev = &led->dev; + + led->toneport = toneport; + snprintf(led->name, sizeof(led->name), "%s::%s", + dev_name(dev), led_colors[i]); + leddev->name = led->name; + leddev->brightness = led_init_vals[i]; + leddev->max_brightness = 0x26; + leddev->brightness_set = toneport_led_brightness_set; + err = led_classdev_register(dev, leddev); + if (err) + return err; + led->registered = true; + } + + return 0; +} + +static void toneport_remove_leds(struct usb_line6_toneport *toneport) +{ + struct toneport_led *led; + int i; + + for (i = 0; i < 2; i++) { + led = &toneport->leds[i]; + if (!led->registered) + break; + led_classdev_unregister(&led->dev); + led->registered = false; + } +} + +/* Setup Toneport device. */ static void toneport_setup(struct usb_line6_toneport *toneport) @@ -359,42 +386,38 @@ static void toneport_setup(struct usb_line6_toneport *toneport) } if (toneport_has_led(toneport->type)) - toneport_update_led(&usbdev->dev); + toneport_update_led(toneport); + + mod_timer(&toneport->timer, jiffies + TONEPORT_PCM_DELAY * HZ); } /* Toneport device disconnected. */ -static void line6_toneport_disconnect(struct usb_interface *interface) +static void line6_toneport_disconnect(struct usb_line6 *line6) { - struct usb_line6_toneport *toneport; - u16 idProduct; - - if (interface == NULL) - return; + struct usb_line6_toneport *toneport = + (struct usb_line6_toneport *)line6; - toneport = usb_get_intfdata(interface); del_timer_sync(&toneport->timer); - idProduct = le16_to_cpu(toneport->line6.usbdev->descriptor.idProduct); - if (toneport_has_led(idProduct)) { - device_remove_file(&interface->dev, &dev_attr_led_red); - device_remove_file(&interface->dev, &dev_attr_led_green); - } + if (toneport_has_led(toneport->type)) + toneport_remove_leds(toneport); } /* Try to init Toneport device. */ -static int toneport_init(struct usb_interface *interface, - struct usb_line6 *line6) +static int toneport_init(struct usb_line6 *line6, + const struct usb_device_id *id) { int err; struct usb_line6_toneport *toneport = (struct usb_line6_toneport *) line6; - if ((interface == NULL) || (toneport == NULL)) - return -ENODEV; + toneport->type = id->driver_info; + setup_timer(&toneport->timer, toneport_start_pcm, + (unsigned long)toneport); line6->disconnect = line6_toneport_disconnect; @@ -431,20 +454,13 @@ static int toneport_init(struct usb_interface *interface, line6_read_data(line6, 0x80c2, &toneport->firmware_version, 1); if (toneport_has_led(toneport->type)) { - err = device_create_file(&interface->dev, &dev_attr_led_red); - if (err < 0) - return err; - err = device_create_file(&interface->dev, &dev_attr_led_green); + err = toneport_init_leds(toneport); if (err < 0) return err; } toneport_setup(toneport); - setup_timer(&toneport->timer, toneport_start_pcm, - (unsigned long)toneport); - mod_timer(&toneport->timer, jiffies + TONEPORT_PCM_DELAY * HZ); - /* register audio system: */ return snd_card_register(line6->card); } @@ -549,15 +565,9 @@ static const struct line6_properties toneport_properties_table[] = { static int toneport_probe(struct usb_interface *interface, const struct usb_device_id *id) { - struct usb_line6_toneport *toneport; - - toneport = kzalloc(sizeof(*toneport), GFP_KERNEL); - if (!toneport) - return -ENODEV; - toneport->type = id->driver_info; - return line6_probe(interface, &toneport->line6, + return line6_probe(interface, id, &toneport_properties_table[id->driver_info], - toneport_init); + toneport_init, sizeof(struct usb_line6_toneport)); } static struct usb_driver toneport_driver = { |