diff options
-rw-r--r-- | sound/usb/line6/Kconfig | 2 | ||||
-rw-r--r-- | sound/usb/line6/toneport.c | 163 |
2 files changed, 91 insertions, 74 deletions
diff --git a/sound/usb/line6/Kconfig b/sound/usb/line6/Kconfig index af20947e0bda..f4585d378ef3 100644 --- a/sound/usb/line6/Kconfig +++ b/sound/usb/line6/Kconfig | |||
@@ -29,6 +29,8 @@ config SND_USB_PODHD | |||
29 | config SND_USB_TONEPORT | 29 | config SND_USB_TONEPORT |
30 | tristate "TonePort GX, UX1 and UX2 USB support" | 30 | tristate "TonePort GX, UX1 and UX2 USB support" |
31 | select SND_USB_LINE6 | 31 | select SND_USB_LINE6 |
32 | select NEW_LEDS | ||
33 | select LEDS_CLASS | ||
32 | help | 34 | help |
33 | This is a driver for TonePort GX, UX1 and UX2 devices. | 35 | This is a driver for TonePort GX, UX1 and UX2 devices. |
34 | 36 | ||
diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c index 9a4f5403569e..9a769463f7bf 100644 --- a/sound/usb/line6/toneport.c +++ b/sound/usb/line6/toneport.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/usb.h> | 14 | #include <linux/usb.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/leds.h> | ||
17 | #include <sound/core.h> | 18 | #include <sound/core.h> |
18 | #include <sound/control.h> | 19 | #include <sound/control.h> |
19 | 20 | ||
@@ -32,6 +33,15 @@ enum line6_device_type { | |||
32 | LINE6_TONEPORT_UX2, | 33 | LINE6_TONEPORT_UX2, |
33 | }; | 34 | }; |
34 | 35 | ||
36 | struct usb_line6_toneport; | ||
37 | |||
38 | struct toneport_led { | ||
39 | struct led_classdev dev; | ||
40 | char name[64]; | ||
41 | struct usb_line6_toneport *toneport; | ||
42 | bool registered; | ||
43 | }; | ||
44 | |||
35 | struct usb_line6_toneport { | 45 | struct usb_line6_toneport { |
36 | /** | 46 | /** |
37 | Generic Line 6 USB data. | 47 | Generic Line 6 USB data. |
@@ -62,6 +72,9 @@ struct usb_line6_toneport { | |||
62 | Device type. | 72 | Device type. |
63 | */ | 73 | */ |
64 | enum line6_device_type type; | 74 | enum line6_device_type type; |
75 | |||
76 | /* LED instances */ | ||
77 | struct toneport_led leds[2]; | ||
65 | }; | 78 | }; |
66 | 79 | ||
67 | static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2); | 80 | 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 = { | |||
117 | .bytes_per_frame = 4 | 130 | .bytes_per_frame = 4 |
118 | }; | 131 | }; |
119 | 132 | ||
120 | /* | ||
121 | For the led on Guitarport. | ||
122 | Brightness goes from 0x00 to 0x26. Set a value above this to have led | ||
123 | blink. | ||
124 | (void cmd_0x02(byte red, byte green) | ||
125 | */ | ||
126 | static int led_red = 0x00; | ||
127 | static int led_green = 0x26; | ||
128 | |||
129 | static const struct { | 133 | static const struct { |
130 | const char *name; | 134 | const char *name; |
131 | int code; | 135 | int code; |
@@ -136,62 +140,6 @@ static const struct { | |||
136 | {"Inst & Mic", 0x0901} | 140 | {"Inst & Mic", 0x0901} |
137 | }; | 141 | }; |
138 | 142 | ||
139 | static bool toneport_has_led(enum line6_device_type type) | ||
140 | { | ||
141 | return | ||
142 | (type == LINE6_GUITARPORT) || | ||
143 | (type == LINE6_TONEPORT_GX); | ||
144 | /* add your device here if you are missing support for the LEDs */ | ||
145 | } | ||
146 | |||
147 | static void toneport_update_led(struct device *dev) | ||
148 | { | ||
149 | struct usb_interface *interface = to_usb_interface(dev); | ||
150 | struct usb_line6_toneport *tp = usb_get_intfdata(interface); | ||
151 | struct usb_line6 *line6; | ||
152 | |||
153 | if (!tp) | ||
154 | return; | ||
155 | |||
156 | line6 = &tp->line6; | ||
157 | if (line6) | ||
158 | toneport_send_cmd(line6->usbdev, (led_red << 8) | 0x0002, | ||
159 | led_green); | ||
160 | } | ||
161 | |||
162 | static ssize_t toneport_set_led_red(struct device *dev, | ||
163 | struct device_attribute *attr, | ||
164 | const char *buf, size_t count) | ||
165 | { | ||
166 | int retval; | ||
167 | |||
168 | retval = kstrtoint(buf, 10, &led_red); | ||
169 | if (retval) | ||
170 | return retval; | ||
171 | |||
172 | toneport_update_led(dev); | ||
173 | return count; | ||
174 | } | ||
175 | |||
176 | static ssize_t toneport_set_led_green(struct device *dev, | ||
177 | struct device_attribute *attr, | ||
178 | const char *buf, size_t count) | ||
179 | { | ||
180 | int retval; | ||
181 | |||
182 | retval = kstrtoint(buf, 10, &led_green); | ||
183 | if (retval) | ||
184 | return retval; | ||
185 | |||
186 | toneport_update_led(dev); | ||
187 | return count; | ||
188 | } | ||
189 | |||
190 | static DEVICE_ATTR(led_red, S_IWUSR | S_IRUGO, line6_nop_read, | ||
191 | toneport_set_led_red); | ||
192 | static DEVICE_ATTR(led_green, S_IWUSR | S_IRUGO, line6_nop_read, | ||
193 | toneport_set_led_green); | ||
194 | |||
195 | static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2) | 143 | static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2) |
196 | { | 144 | { |
197 | int ret; | 145 | int ret; |
@@ -330,6 +278,78 @@ static struct snd_kcontrol_new toneport_control_source = { | |||
330 | }; | 278 | }; |
331 | 279 | ||
332 | /* | 280 | /* |
281 | For the led on Guitarport. | ||
282 | Brightness goes from 0x00 to 0x26. Set a value above this to have led | ||
283 | blink. | ||
284 | (void cmd_0x02(byte red, byte green) | ||
285 | */ | ||
286 | |||
287 | static bool toneport_has_led(enum line6_device_type type) | ||
288 | { | ||
289 | return | ||
290 | (type == LINE6_GUITARPORT) || | ||
291 | (type == LINE6_TONEPORT_GX); | ||
292 | /* add your device here if you are missing support for the LEDs */ | ||
293 | } | ||
294 | |||
295 | static const char * const led_colors[2] = { "red", "green" }; | ||
296 | static const int led_init_vals[2] = { 0x00, 0x26 }; | ||
297 | |||
298 | static void toneport_update_led(struct usb_line6_toneport *toneport) | ||
299 | { | ||
300 | toneport_send_cmd(toneport->line6.usbdev, | ||
301 | (toneport->leds[0].dev.brightness << 8) | 0x0002, | ||
302 | toneport->leds[1].dev.brightness); | ||
303 | } | ||
304 | |||
305 | static void toneport_led_brightness_set(struct led_classdev *led_cdev, | ||
306 | enum led_brightness brightness) | ||
307 | { | ||
308 | struct toneport_led *leds = | ||
309 | container_of(led_cdev, struct toneport_led, dev); | ||
310 | toneport_update_led(leds->toneport); | ||
311 | } | ||
312 | |||
313 | static int toneport_init_leds(struct usb_line6_toneport *toneport) | ||
314 | { | ||
315 | struct device *dev = &toneport->line6.usbdev->dev; | ||
316 | int i, err; | ||
317 | |||
318 | for (i = 0; i < 2; i++) { | ||
319 | struct toneport_led *led = &toneport->leds[i]; | ||
320 | struct led_classdev *leddev = &led->dev; | ||
321 | |||
322 | led->toneport = toneport; | ||
323 | snprintf(led->name, sizeof(led->name), "%s::%s", | ||
324 | dev_name(dev), led_colors[i]); | ||
325 | leddev->name = led->name; | ||
326 | leddev->brightness = led_init_vals[i]; | ||
327 | leddev->max_brightness = 0x26; | ||
328 | leddev->brightness_set = toneport_led_brightness_set; | ||
329 | err = led_classdev_register(dev, leddev); | ||
330 | if (err) | ||
331 | return err; | ||
332 | led->registered = true; | ||
333 | } | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | static void toneport_remove_leds(struct usb_line6_toneport *toneport) | ||
339 | { | ||
340 | struct toneport_led *led; | ||
341 | int i; | ||
342 | |||
343 | for (i = 0; i < 2; i++) { | ||
344 | led = &toneport->leds[i]; | ||
345 | if (!led->registered) | ||
346 | break; | ||
347 | led_classdev_unregister(&led->dev); | ||
348 | led->registered = false; | ||
349 | } | ||
350 | } | ||
351 | |||
352 | /* | ||
333 | Setup Toneport device. | 353 | Setup Toneport device. |
334 | */ | 354 | */ |
335 | static void toneport_setup(struct usb_line6_toneport *toneport) | 355 | static void toneport_setup(struct usb_line6_toneport *toneport) |
@@ -359,7 +379,7 @@ static void toneport_setup(struct usb_line6_toneport *toneport) | |||
359 | } | 379 | } |
360 | 380 | ||
361 | if (toneport_has_led(toneport->type)) | 381 | if (toneport_has_led(toneport->type)) |
362 | toneport_update_led(&usbdev->dev); | 382 | toneport_update_led(toneport); |
363 | 383 | ||
364 | mod_timer(&toneport->timer, jiffies + TONEPORT_PCM_DELAY * HZ); | 384 | mod_timer(&toneport->timer, jiffies + TONEPORT_PCM_DELAY * HZ); |
365 | } | 385 | } |
@@ -374,10 +394,8 @@ static void line6_toneport_disconnect(struct usb_interface *interface) | |||
374 | toneport = usb_get_intfdata(interface); | 394 | toneport = usb_get_intfdata(interface); |
375 | del_timer_sync(&toneport->timer); | 395 | del_timer_sync(&toneport->timer); |
376 | 396 | ||
377 | if (toneport_has_led(toneport->type)) { | 397 | if (toneport_has_led(toneport->type)) |
378 | device_remove_file(&interface->dev, &dev_attr_led_red); | 398 | toneport_remove_leds(toneport); |
379 | device_remove_file(&interface->dev, &dev_attr_led_green); | ||
380 | } | ||
381 | } | 399 | } |
382 | 400 | ||
383 | 401 | ||
@@ -428,10 +446,7 @@ static int toneport_init(struct usb_interface *interface, | |||
428 | line6_read_data(line6, 0x80c2, &toneport->firmware_version, 1); | 446 | line6_read_data(line6, 0x80c2, &toneport->firmware_version, 1); |
429 | 447 | ||
430 | if (toneport_has_led(toneport->type)) { | 448 | if (toneport_has_led(toneport->type)) { |
431 | err = device_create_file(&interface->dev, &dev_attr_led_red); | 449 | err = toneport_init_leds(toneport); |
432 | if (err < 0) | ||
433 | return err; | ||
434 | err = device_create_file(&interface->dev, &dev_attr_led_green); | ||
435 | if (err < 0) | 450 | if (err < 0) |
436 | return err; | 451 | return err; |
437 | } | 452 | } |