.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Line 6 Linux USB driver |
---|
3 | 4 | * |
---|
4 | 5 | * 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 | 6 | */ |
---|
11 | 7 | |
---|
12 | 8 | #include <linux/slab.h> |
---|
.. | .. |
---|
39 | 35 | Stages of POD startup procedure |
---|
40 | 36 | */ |
---|
41 | 37 | enum { |
---|
42 | | - POD_STARTUP_INIT = 1, |
---|
43 | 38 | POD_STARTUP_VERSIONREQ, |
---|
44 | | - POD_STARTUP_WORKQUEUE, |
---|
45 | 39 | POD_STARTUP_SETUP, |
---|
46 | | - POD_STARTUP_LAST = POD_STARTUP_SETUP - 1 |
---|
| 40 | + POD_STARTUP_DONE, |
---|
47 | 41 | }; |
---|
48 | 42 | |
---|
49 | 43 | enum { |
---|
.. | .. |
---|
63 | 57 | /* Instrument monitor level */ |
---|
64 | 58 | int monitor_level; |
---|
65 | 59 | |
---|
66 | | - /* Timer for device initialization */ |
---|
67 | | - struct timer_list startup_timer; |
---|
68 | | - |
---|
69 | | - /* Work handler for device initialization */ |
---|
70 | | - struct work_struct startup_work; |
---|
71 | | - |
---|
72 | 60 | /* Current progress in startup procedure */ |
---|
73 | 61 | int startup_progress; |
---|
74 | 62 | |
---|
.. | .. |
---|
81 | 69 | /* Device ID */ |
---|
82 | 70 | int device_id; |
---|
83 | 71 | }; |
---|
| 72 | + |
---|
| 73 | +#define line6_to_pod(x) container_of(x, struct usb_line6_pod, line6) |
---|
84 | 74 | |
---|
85 | 75 | #define POD_SYSEX_CODE 3 |
---|
86 | 76 | |
---|
.. | .. |
---|
120 | 110 | POD_BUSY_MIDISEND |
---|
121 | 111 | }; |
---|
122 | 112 | |
---|
123 | | -static struct snd_ratden pod_ratden = { |
---|
| 113 | +static const struct snd_ratden pod_ratden = { |
---|
124 | 114 | .num_min = 78125, |
---|
125 | 115 | .num_max = 78125, |
---|
126 | 116 | .num_step = 1, |
---|
.. | .. |
---|
169 | 159 | .bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */ |
---|
170 | 160 | }; |
---|
171 | 161 | |
---|
172 | | -static const char pod_version_header[] = { |
---|
173 | | - 0xf2, 0x7e, 0x7f, 0x06, 0x02 |
---|
174 | | -}; |
---|
175 | 162 | |
---|
176 | | -/* forward declarations: */ |
---|
177 | | -static void pod_startup2(struct timer_list *t); |
---|
178 | | -static void pod_startup3(struct usb_line6_pod *pod); |
---|
| 163 | +static const char pod_version_header[] = { |
---|
| 164 | + 0xf0, 0x7e, 0x7f, 0x06, 0x02 |
---|
| 165 | +}; |
---|
179 | 166 | |
---|
180 | 167 | static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code, |
---|
181 | 168 | int size) |
---|
.. | .. |
---|
189 | 176 | */ |
---|
190 | 177 | static void line6_pod_process_message(struct usb_line6 *line6) |
---|
191 | 178 | { |
---|
192 | | - struct usb_line6_pod *pod = (struct usb_line6_pod *) line6; |
---|
| 179 | + struct usb_line6_pod *pod = line6_to_pod(line6); |
---|
193 | 180 | const unsigned char *buf = pod->line6.buffer_message; |
---|
194 | 181 | |
---|
195 | 182 | if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) { |
---|
196 | 183 | pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15]; |
---|
197 | 184 | pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) | |
---|
198 | 185 | (int) buf[10]; |
---|
199 | | - pod_startup3(pod); |
---|
| 186 | + if (pod->startup_progress == POD_STARTUP_VERSIONREQ) { |
---|
| 187 | + pod->startup_progress = POD_STARTUP_SETUP; |
---|
| 188 | + schedule_delayed_work(&line6->startup_work, 0); |
---|
| 189 | + } |
---|
200 | 190 | return; |
---|
201 | 191 | } |
---|
202 | 192 | |
---|
.. | .. |
---|
281 | 271 | context). After the last one has finished, the device is ready to use. |
---|
282 | 272 | */ |
---|
283 | 273 | |
---|
284 | | -static void pod_startup1(struct usb_line6_pod *pod) |
---|
| 274 | +static void pod_startup(struct usb_line6 *line6) |
---|
285 | 275 | { |
---|
286 | | - CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT); |
---|
| 276 | + struct usb_line6_pod *pod = line6_to_pod(line6); |
---|
287 | 277 | |
---|
288 | | - /* delay startup procedure: */ |
---|
289 | | - line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2); |
---|
290 | | -} |
---|
| 278 | + switch (pod->startup_progress) { |
---|
| 279 | + case POD_STARTUP_VERSIONREQ: |
---|
| 280 | + /* request firmware version: */ |
---|
| 281 | + line6_version_request_async(line6); |
---|
| 282 | + break; |
---|
| 283 | + case POD_STARTUP_SETUP: |
---|
| 284 | + /* serial number: */ |
---|
| 285 | + line6_read_serial_number(&pod->line6, &pod->serial_number); |
---|
291 | 286 | |
---|
292 | | -static void pod_startup2(struct timer_list *t) |
---|
293 | | -{ |
---|
294 | | - struct usb_line6_pod *pod = from_timer(pod, t, startup_timer); |
---|
295 | | - struct usb_line6 *line6 = &pod->line6; |
---|
296 | | - |
---|
297 | | - CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ); |
---|
298 | | - |
---|
299 | | - /* request firmware version: */ |
---|
300 | | - line6_version_request_async(line6); |
---|
301 | | -} |
---|
302 | | - |
---|
303 | | -static void pod_startup3(struct usb_line6_pod *pod) |
---|
304 | | -{ |
---|
305 | | - CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE); |
---|
306 | | - |
---|
307 | | - /* schedule work for global work queue: */ |
---|
308 | | - schedule_work(&pod->startup_work); |
---|
309 | | -} |
---|
310 | | - |
---|
311 | | -static void pod_startup4(struct work_struct *work) |
---|
312 | | -{ |
---|
313 | | - struct usb_line6_pod *pod = |
---|
314 | | - container_of(work, struct usb_line6_pod, startup_work); |
---|
315 | | - struct usb_line6 *line6 = &pod->line6; |
---|
316 | | - |
---|
317 | | - CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP); |
---|
318 | | - |
---|
319 | | - /* serial number: */ |
---|
320 | | - line6_read_serial_number(&pod->line6, &pod->serial_number); |
---|
321 | | - |
---|
322 | | - /* ALSA audio interface: */ |
---|
323 | | - snd_card_register(line6->card); |
---|
| 287 | + /* ALSA audio interface: */ |
---|
| 288 | + if (snd_card_register(line6->card)) |
---|
| 289 | + dev_err(line6->ifcdev, "Failed to register POD card.\n"); |
---|
| 290 | + pod->startup_progress = POD_STARTUP_DONE; |
---|
| 291 | + break; |
---|
| 292 | + default: |
---|
| 293 | + break; |
---|
| 294 | + } |
---|
324 | 295 | } |
---|
325 | 296 | |
---|
326 | 297 | /* POD special files: */ |
---|
.. | .. |
---|
356 | 327 | struct snd_ctl_elem_value *ucontrol) |
---|
357 | 328 | { |
---|
358 | 329 | struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); |
---|
359 | | - struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6; |
---|
| 330 | + struct usb_line6_pod *pod = line6_to_pod(line6pcm->line6); |
---|
360 | 331 | |
---|
361 | 332 | ucontrol->value.integer.value[0] = pod->monitor_level; |
---|
362 | 333 | return 0; |
---|
.. | .. |
---|
367 | 338 | struct snd_ctl_elem_value *ucontrol) |
---|
368 | 339 | { |
---|
369 | 340 | struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); |
---|
370 | | - struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6; |
---|
| 341 | + struct usb_line6_pod *pod = line6_to_pod(line6pcm->line6); |
---|
371 | 342 | |
---|
372 | 343 | if (ucontrol->value.integer.value[0] == pod->monitor_level) |
---|
373 | 344 | return 0; |
---|
.. | .. |
---|
390 | 361 | }; |
---|
391 | 362 | |
---|
392 | 363 | /* |
---|
393 | | - POD device disconnected. |
---|
394 | | -*/ |
---|
395 | | -static void line6_pod_disconnect(struct usb_line6 *line6) |
---|
396 | | -{ |
---|
397 | | - struct usb_line6_pod *pod = (struct usb_line6_pod *)line6; |
---|
398 | | - |
---|
399 | | - del_timer_sync(&pod->startup_timer); |
---|
400 | | - cancel_work_sync(&pod->startup_work); |
---|
401 | | -} |
---|
402 | | - |
---|
403 | | -/* |
---|
404 | 364 | Try to init POD device. |
---|
405 | 365 | */ |
---|
406 | 366 | static int pod_init(struct usb_line6 *line6, |
---|
407 | 367 | const struct usb_device_id *id) |
---|
408 | 368 | { |
---|
409 | 369 | int err; |
---|
410 | | - struct usb_line6_pod *pod = (struct usb_line6_pod *) line6; |
---|
| 370 | + struct usb_line6_pod *pod = line6_to_pod(line6); |
---|
411 | 371 | |
---|
412 | 372 | line6->process_message = line6_pod_process_message; |
---|
413 | | - line6->disconnect = line6_pod_disconnect; |
---|
414 | | - |
---|
415 | | - timer_setup(&pod->startup_timer, NULL, 0); |
---|
416 | | - INIT_WORK(&pod->startup_work, pod_startup4); |
---|
| 373 | + line6->startup = pod_startup; |
---|
417 | 374 | |
---|
418 | 375 | /* create sysfs entries: */ |
---|
419 | 376 | err = snd_card_add_dev_attr(line6->card, &pod_dev_attr_group); |
---|
.. | .. |
---|
441 | 398 | pod->monitor_level = POD_SYSTEM_INVALID; |
---|
442 | 399 | |
---|
443 | 400 | /* initiate startup procedure: */ |
---|
444 | | - pod_startup1(pod); |
---|
| 401 | + schedule_delayed_work(&line6->startup_work, |
---|
| 402 | + msecs_to_jiffies(POD_STARTUP_DELAY)); |
---|
445 | 403 | } |
---|
446 | 404 | |
---|
447 | 405 | return 0; |
---|