ALSA: line6: Tidy up and typo fixes in comments
[firefly-linux-kernel-4.4.55.git] / sound / usb / line6 / variax.c
1 /*
2  * Line 6 Linux USB driver
3  *
4  * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5  *
6  *      This program is free software; you can redistribute it and/or
7  *      modify it under the terms of the GNU General Public License as
8  *      published by the Free Software Foundation, version 2.
9  *
10  */
11
12 #include <linux/slab.h>
13 #include <linux/spinlock.h>
14 #include <linux/usb.h>
15 #include <linux/wait.h>
16 #include <linux/module.h>
17 #include <sound/core.h>
18
19 #include "driver.h"
20 #include "usbdefs.h"
21
22 #define VARIAX_STARTUP_DELAY1 1000
23 #define VARIAX_STARTUP_DELAY3 100
24 #define VARIAX_STARTUP_DELAY4 100
25
26 /*
27         Stages of Variax startup procedure
28 */
29 enum {
30         VARIAX_STARTUP_INIT = 1,
31         VARIAX_STARTUP_VERSIONREQ,
32         VARIAX_STARTUP_WAIT,
33         VARIAX_STARTUP_ACTIVATE,
34         VARIAX_STARTUP_WORKQUEUE,
35         VARIAX_STARTUP_SETUP,
36         VARIAX_STARTUP_LAST = VARIAX_STARTUP_SETUP - 1
37 };
38
39 enum {
40         LINE6_PODXTLIVE_VARIAX,
41         LINE6_VARIAX
42 };
43
44 struct usb_line6_variax {
45         /* Generic Line 6 USB data */
46         struct usb_line6 line6;
47
48         /* Buffer for activation code */
49         unsigned char *buffer_activate;
50
51         /* Handler for device initialization */
52         struct work_struct startup_work;
53
54         /* Timers for device initialization */
55         struct timer_list startup_timer1;
56         struct timer_list startup_timer2;
57
58         /* Current progress in startup procedure */
59         int startup_progress;
60 };
61
62 #define VARIAX_OFFSET_ACTIVATE 7
63
64 /*
65         This message is sent by the device during initialization and identifies
66         the connected guitar version.
67 */
68 static const char variax_init_version[] = {
69         0xf0, 0x7e, 0x7f, 0x06, 0x02, 0x00, 0x01, 0x0c,
70         0x07, 0x00, 0x00, 0x00
71 };
72
73 /*
74         This message is the last one sent by the device during initialization.
75 */
76 static const char variax_init_done[] = {
77         0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6b
78 };
79
80 static const char variax_activate[] = {
81         0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x2a, 0x01,
82         0xf7
83 };
84
85 /* forward declarations: */
86 static void variax_startup2(unsigned long data);
87 static void variax_startup4(unsigned long data);
88 static void variax_startup5(unsigned long data);
89
90 static void variax_activate_async(struct usb_line6_variax *variax, int a)
91 {
92         variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = a;
93         line6_send_raw_message_async(&variax->line6, variax->buffer_activate,
94                                      sizeof(variax_activate));
95 }
96
97 /*
98         Variax startup procedure.
99         This is a sequence of functions with special requirements (e.g., must
100         not run immediately after initialization, must not run in interrupt
101         context). After the last one has finished, the device is ready to use.
102 */
103
104 static void variax_startup1(struct usb_line6_variax *variax)
105 {
106         CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_INIT);
107
108         /* delay startup procedure: */
109         line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
110                           variax_startup2, (unsigned long)variax);
111 }
112
113 static void variax_startup2(unsigned long data)
114 {
115         struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
116         struct usb_line6 *line6 = &variax->line6;
117
118         /* schedule another startup procedure until startup is complete: */
119         if (variax->startup_progress >= VARIAX_STARTUP_LAST)
120                 return;
121
122         variax->startup_progress = VARIAX_STARTUP_VERSIONREQ;
123         line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
124                           variax_startup2, (unsigned long)variax);
125
126         /* request firmware version: */
127         line6_version_request_async(line6);
128 }
129
130 static void variax_startup3(struct usb_line6_variax *variax)
131 {
132         CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_WAIT);
133
134         /* delay startup procedure: */
135         line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY3,
136                           variax_startup4, (unsigned long)variax);
137 }
138
139 static void variax_startup4(unsigned long data)
140 {
141         struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
142
143         CHECK_STARTUP_PROGRESS(variax->startup_progress,
144                                VARIAX_STARTUP_ACTIVATE);
145
146         /* activate device: */
147         variax_activate_async(variax, 1);
148         line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY4,
149                           variax_startup5, (unsigned long)variax);
150 }
151
152 static void variax_startup5(unsigned long data)
153 {
154         struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
155
156         CHECK_STARTUP_PROGRESS(variax->startup_progress,
157                                VARIAX_STARTUP_WORKQUEUE);
158
159         /* schedule work for global work queue: */
160         schedule_work(&variax->startup_work);
161 }
162
163 static void variax_startup6(struct work_struct *work)
164 {
165         struct usb_line6_variax *variax =
166             container_of(work, struct usb_line6_variax, startup_work);
167
168         CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_SETUP);
169
170         /* ALSA audio interface: */
171         snd_card_register(variax->line6.card);
172 }
173
174 /*
175         Process a completely received message.
176 */
177 static void line6_variax_process_message(struct usb_line6 *line6)
178 {
179         struct usb_line6_variax *variax = (struct usb_line6_variax *) line6;
180         const unsigned char *buf = variax->line6.buffer_message;
181
182         switch (buf[0]) {
183         case LINE6_RESET:
184                 dev_info(variax->line6.ifcdev, "VARIAX reset\n");
185                 break;
186
187         case LINE6_SYSEX_BEGIN:
188                 if (memcmp(buf + 1, variax_init_version + 1,
189                            sizeof(variax_init_version) - 1) == 0) {
190                         variax_startup3(variax);
191                 } else if (memcmp(buf + 1, variax_init_done + 1,
192                                   sizeof(variax_init_done) - 1) == 0) {
193                         /* notify of complete initialization: */
194                         variax_startup4((unsigned long)variax);
195                 }
196                 break;
197         }
198 }
199
200 /*
201         Variax destructor.
202 */
203 static void line6_variax_disconnect(struct usb_line6 *line6)
204 {
205         struct usb_line6_variax *variax = (struct usb_line6_variax *)line6;
206
207         del_timer(&variax->startup_timer1);
208         del_timer(&variax->startup_timer2);
209         cancel_work_sync(&variax->startup_work);
210
211         kfree(variax->buffer_activate);
212 }
213
214 /*
215          Try to init workbench device.
216 */
217 static int variax_init(struct usb_line6 *line6,
218                        const struct usb_device_id *id)
219 {
220         struct usb_line6_variax *variax = (struct usb_line6_variax *) line6;
221         int err;
222
223         line6->process_message = line6_variax_process_message;
224         line6->disconnect = line6_variax_disconnect;
225
226         init_timer(&variax->startup_timer1);
227         init_timer(&variax->startup_timer2);
228         INIT_WORK(&variax->startup_work, variax_startup6);
229
230         /* initialize USB buffers: */
231         variax->buffer_activate = kmemdup(variax_activate,
232                                           sizeof(variax_activate), GFP_KERNEL);
233
234         if (variax->buffer_activate == NULL)
235                 return -ENOMEM;
236
237         /* initialize MIDI subsystem: */
238         err = line6_init_midi(&variax->line6);
239         if (err < 0)
240                 return err;
241
242         /* initiate startup procedure: */
243         variax_startup1(variax);
244         return 0;
245 }
246
247 #define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
248 #define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
249
250 /* table of devices that work with this driver */
251 static const struct usb_device_id variax_id_table[] = {
252         { LINE6_IF_NUM(0x4650, 1), .driver_info = LINE6_PODXTLIVE_VARIAX },
253         { LINE6_DEVICE(0x534d),    .driver_info = LINE6_VARIAX },
254         {}
255 };
256
257 MODULE_DEVICE_TABLE(usb, variax_id_table);
258
259 static const struct line6_properties variax_properties_table[] = {
260         [LINE6_PODXTLIVE_VARIAX] = {
261                 .id = "PODxtLive",
262                 .name = "PODxt Live",
263                 .capabilities   = LINE6_CAP_CONTROL
264                                 | LINE6_CAP_PCM
265                                 | LINE6_CAP_HWMON,
266                 .altsetting = 1,
267                 .ep_ctrl_r = 0x86,
268                 .ep_ctrl_w = 0x05,
269                 .ep_audio_r = 0x82,
270                 .ep_audio_w = 0x01,
271         },
272         [LINE6_VARIAX] = {
273                 .id = "Variax",
274                 .name = "Variax Workbench",
275                 .capabilities   = LINE6_CAP_CONTROL,
276                 .altsetting = 1,
277                 .ep_ctrl_r = 0x82,
278                 .ep_ctrl_w = 0x01,
279                 /* no audio channel */
280         }
281 };
282
283 /*
284         Probe USB device.
285 */
286 static int variax_probe(struct usb_interface *interface,
287                         const struct usb_device_id *id)
288 {
289         return line6_probe(interface, id,
290                            &variax_properties_table[id->driver_info],
291                            variax_init, sizeof(struct usb_line6_variax));
292 }
293
294 static struct usb_driver variax_driver = {
295         .name = KBUILD_MODNAME,
296         .probe = variax_probe,
297         .disconnect = line6_disconnect,
298 #ifdef CONFIG_PM
299         .suspend = line6_suspend,
300         .resume = line6_resume,
301         .reset_resume = line6_resume,
302 #endif
303         .id_table = variax_id_table,
304 };
305
306 module_usb_driver(variax_driver);
307
308 MODULE_DESCRIPTION("Vairax Workbench USB driver");
309 MODULE_LICENSE("GPL");