staging: line6: drop finish sysfs attr
[deliverable/linux.git] / drivers / staging / line6 / pod.c
CommitLineData
705ececd 1/*
e1a164d7 2 * Line6 Linux USB driver - 0.9.1beta
705ececd 3 *
1027f476 4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
705ececd
MG
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
5a0e3ad6 12#include <linux/slab.h>
1027f476
MG
13#include <linux/wait.h>
14#include <sound/control.h>
5a0e3ad6 15
705ececd
MG
16#include "audio.h"
17#include "capture.h"
18#include "control.h"
1027f476 19#include "driver.h"
705ececd
MG
20#include "playback.h"
21#include "pod.h"
22
705ececd 23#define POD_SYSEX_CODE 3
e1a164d7 24#define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */
705ececd 25
e1a164d7 26/* *INDENT-OFF* */
705ececd
MG
27
28enum {
705ececd
MG
29 POD_SYSEX_SAVE = 0x24,
30 POD_SYSEX_SYSTEM = 0x56,
31 POD_SYSEX_SYSTEMREQ = 0x57,
32 /* POD_SYSEX_UPDATE = 0x6c, */ /* software update! */
33 POD_SYSEX_STORE = 0x71,
34 POD_SYSEX_FINISH = 0x72,
35 POD_SYSEX_DUMPMEM = 0x73,
36 POD_SYSEX_DUMP = 0x74,
37 POD_SYSEX_DUMPREQ = 0x75
38 /* POD_SYSEX_DUMPMEM2 = 0x76 */ /* dumps entire internal memory of PODxt Pro */
39};
40
41enum {
42 POD_monitor_level = 0x04,
705ececd
MG
43 POD_tuner_mute = 0x13,
44 POD_tuner_freq = 0x15,
45 POD_tuner_note = 0x16,
46 POD_tuner_pitch = 0x17,
1027f476 47 POD_system_invalid = 0x10000
705ececd
MG
48};
49
e1a164d7
MG
50/* *INDENT-ON* */
51
705ececd
MG
52enum {
53 POD_DUMP_MEMORY = 2
54};
55
56enum {
57 POD_BUSY_READ,
58 POD_BUSY_WRITE,
59 POD_CHANNEL_DIRTY,
60 POD_SAVE_PRESSED,
61 POD_BUSY_MIDISEND
62};
63
705ececd
MG
64static struct snd_ratden pod_ratden = {
65 .num_min = 78125,
66 .num_max = 78125,
67 .num_step = 1,
68 .den = 2
69};
70
71static struct line6_pcm_properties pod_pcm_properties = {
1027f476 72 .snd_line6_playback_hw = {
e1a164d7
MG
73 .info = (SNDRV_PCM_INFO_MMAP |
74 SNDRV_PCM_INFO_INTERLEAVED |
75 SNDRV_PCM_INFO_BLOCK_TRANSFER |
76 SNDRV_PCM_INFO_MMAP_VALID |
77 SNDRV_PCM_INFO_PAUSE |
1027f476 78#ifdef CONFIG_PM
e1a164d7 79 SNDRV_PCM_INFO_RESUME |
1027f476 80#endif
e1a164d7
MG
81 SNDRV_PCM_INFO_SYNC_START),
82 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
83 .rates = SNDRV_PCM_RATE_KNOT,
84 .rate_min = 39062,
85 .rate_max = 39063,
86 .channels_min = 2,
87 .channels_max = 2,
88 .buffer_bytes_max = 60000,
89 .period_bytes_min = 64,
90 .period_bytes_max = 8192,
91 .periods_min = 1,
92 .periods_max = 1024},
1027f476 93 .snd_line6_capture_hw = {
e1a164d7
MG
94 .info = (SNDRV_PCM_INFO_MMAP |
95 SNDRV_PCM_INFO_INTERLEAVED |
96 SNDRV_PCM_INFO_BLOCK_TRANSFER |
97 SNDRV_PCM_INFO_MMAP_VALID |
1027f476 98#ifdef CONFIG_PM
e1a164d7 99 SNDRV_PCM_INFO_RESUME |
1027f476 100#endif
e1a164d7
MG
101 SNDRV_PCM_INFO_SYNC_START),
102 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
103 .rates = SNDRV_PCM_RATE_KNOT,
104 .rate_min = 39062,
105 .rate_max = 39063,
106 .channels_min = 2,
107 .channels_max = 2,
108 .buffer_bytes_max = 60000,
109 .period_bytes_min = 64,
110 .period_bytes_max = 8192,
111 .periods_min = 1,
112 .periods_max = 1024},
705ececd 113 .snd_line6_rates = {
e1a164d7
MG
114 .nrats = 1,
115 .rats = &pod_ratden},
705ececd
MG
116 .bytes_per_frame = POD_BYTES_PER_FRAME
117};
118
1027f476
MG
119static const char pod_request_channel[] = {
120 0xf0, 0x00, 0x01, 0x0c, 0x03, 0x75, 0xf7
121};
122
e1a164d7 123static const char pod_version_header[] = {
1027f476
MG
124 0xf2, 0x7e, 0x7f, 0x06, 0x02
125};
126
1027f476
MG
127/* forward declarations: */
128static void pod_startup2(unsigned long data);
129static void pod_startup3(struct usb_line6_pod *pod);
130static void pod_startup4(struct usb_line6_pod *pod);
705ececd 131
e1a164d7
MG
132static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
133 int size)
705ececd 134{
e1a164d7
MG
135 return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code,
136 size);
705ececd
MG
137}
138
705ececd 139/*
b772fe9e 140 Store parameter value in driver memory.
705ececd
MG
141*/
142static void pod_store_parameter(struct usb_line6_pod *pod, int param, int value)
143{
144 pod->prog_data.control[param] = value;
705ececd
MG
145}
146
147/*
1027f476 148 Handle SAVE button.
705ececd 149*/
e1a164d7
MG
150static void pod_save_button_pressed(struct usb_line6_pod *pod, int type,
151 int index)
705ececd 152{
705ececd
MG
153 set_bit(POD_SAVE_PRESSED, &pod->atomic_flags);
154}
155
156/*
157 Process a completely received message.
158*/
1027f476 159void line6_pod_process_message(struct usb_line6_pod *pod)
705ececd
MG
160{
161 const unsigned char *buf = pod->line6.buffer_message;
162
163 /* filter messages by type */
0fdef36a 164 switch (buf[0] & 0xf0) {
705ececd
MG
165 case LINE6_PARAM_CHANGE:
166 case LINE6_PROGRAM_CHANGE:
167 case LINE6_SYSEX_BEGIN:
e1a164d7 168 break; /* handle these further down */
705ececd
MG
169
170 default:
e1a164d7 171 return; /* ignore all others */
705ececd
MG
172 }
173
174 /* process all remaining messages */
0fdef36a 175 switch (buf[0]) {
705ececd
MG
176 case LINE6_PARAM_CHANGE | LINE6_CHANNEL_DEVICE:
177 pod_store_parameter(pod, buf[1], buf[2]);
178 /* intentionally no break here! */
179
180 case LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST:
0fdef36a
GKH
181 if ((buf[1] == POD_amp_model_setup) ||
182 (buf[1] == POD_effect_setup))
183 /* these also affect other settings */
e1a164d7
MG
184 line6_dump_request_async(&pod->dumpreq, &pod->line6, 0,
185 LINE6_DUMP_CURRENT);
705ececd
MG
186
187 break;
188
189 case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_DEVICE:
190 case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST:
705ececd 191 set_bit(POD_CHANNEL_DIRTY, &pod->atomic_flags);
e1a164d7
MG
192 line6_dump_request_async(&pod->dumpreq, &pod->line6, 0,
193 LINE6_DUMP_CURRENT);
705ececd
MG
194 break;
195
196 case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE:
197 case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN:
0fdef36a
GKH
198 if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) == 0) {
199 switch (buf[5]) {
705ececd 200 case POD_SYSEX_DUMP:
e1a164d7
MG
201 if (pod->line6.message_length ==
202 sizeof(pod->prog_data) + 7) {
0fdef36a 203 switch (pod->dumpreq.in_progress) {
705ececd 204 case LINE6_DUMP_CURRENT:
e1a164d7
MG
205 memcpy(&pod->prog_data, buf + 7,
206 sizeof(pod->prog_data));
705ececd
MG
207 break;
208
209 case POD_DUMP_MEMORY:
e1a164d7
MG
210 memcpy(&pod->prog_data_buf,
211 buf + 7,
212 sizeof
213 (pod->prog_data_buf));
705ececd
MG
214 break;
215
216 default:
e00d33cb
SH
217 dev_dbg(pod->line6.ifcdev,
218 "unknown dump code %02X\n",
219 pod->dumpreq.in_progress);
705ececd
MG
220 }
221
222 line6_dump_finished(&pod->dumpreq);
1027f476 223 pod_startup3(pod);
0fdef36a 224 } else
e00d33cb
SH
225 dev_dbg(pod->line6.ifcdev,
226 "wrong size of channel dump message (%d instead of %d)\n",
227 pod->line6.message_length,
228 (int)sizeof(pod->prog_data) +
229 7);
705ececd
MG
230
231 break;
232
e1a164d7
MG
233 case POD_SYSEX_SYSTEM:{
234 short value =
235 ((int)buf[7] << 12) | ((int)buf[8]
236 << 8) |
237 ((int)buf[9] << 4) | (int)buf[10];
705ececd 238
99c54e98 239 if (buf[6] == POD_monitor_level)
2c35dc21 240 pod->monitor_level = value;
e1a164d7
MG
241 break;
242 }
705ececd
MG
243
244 case POD_SYSEX_FINISH:
245 /* do we need to respond to this? */
246 break;
247
248 case POD_SYSEX_SAVE:
249 pod_save_button_pressed(pod, buf[6], buf[7]);
250 break;
251
705ececd 252 case POD_SYSEX_STORE:
e00d33cb
SH
253 dev_dbg(pod->line6.ifcdev,
254 "message %02X not yet implemented\n",
255 buf[5]);
705ececd
MG
256 break;
257
258 default:
e00d33cb
SH
259 dev_dbg(pod->line6.ifcdev,
260 "unknown sysex message %02X\n",
261 buf[5]);
705ececd 262 }
e1a164d7
MG
263 } else
264 if (memcmp
265 (buf, pod_version_header,
266 sizeof(pod_version_header)) == 0) {
267 pod->firmware_version =
268 buf[13] * 100 + buf[14] * 10 + buf[15];
269 pod->device_id =
270 ((int)buf[8] << 16) | ((int)buf[9] << 8) | (int)
271 buf[10];
1027f476 272 pod_startup4(pod);
0fdef36a 273 } else
e00d33cb 274 dev_dbg(pod->line6.ifcdev, "unknown sysex header\n");
705ececd
MG
275
276 break;
277
278 case LINE6_SYSEX_END:
279 break;
280
281 default:
e00d33cb
SH
282 dev_dbg(pod->line6.ifcdev, "POD: unknown message %02X\n",
283 buf[0]);
705ececd
MG
284 }
285}
286
287/*
288 Detect some cases that require a channel dump after sending a command to the
289 device. Important notes:
290 *) The actual dump request can not be sent here since we are not allowed to
291 wait for the completion of the first message in this context, and sending
292 the dump request before completion of the previous message leaves the POD
293 in an undefined state. The dump request will be sent when the echoed
294 commands are received.
295 *) This method fails if a param change message is "chopped" after the first
296 byte.
297*/
e1a164d7
MG
298void line6_pod_midi_postprocess(struct usb_line6_pod *pod, unsigned char *data,
299 int length)
705ececd
MG
300{
301 int i;
302
0fdef36a 303 if (!pod->midi_postprocess)
705ececd
MG
304 return;
305
0fdef36a
GKH
306 for (i = 0; i < length; ++i) {
307 if (data[i] == (LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST)) {
705ececd
MG
308 line6_invalidate_current(&pod->dumpreq);
309 break;
e1a164d7
MG
310 } else
311 if ((data[i] == (LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST))
312 && (i < length - 1))
313 if ((data[i + 1] == POD_amp_model_setup)
314 || (data[i + 1] == POD_effect_setup)) {
705ececd
MG
315 line6_invalidate_current(&pod->dumpreq);
316 break;
317 }
318 }
319}
320
705ececd
MG
321/*
322 Transmit PODxt Pro control parameter.
323*/
e1a164d7 324void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param,
5b9bd2ad 325 u8 value)
705ececd 326{
0fdef36a 327 if (line6_transmit_parameter(&pod->line6, param, value) == 0)
705ececd
MG
328 pod_store_parameter(pod, param, value);
329
e1a164d7 330 if ((param == POD_amp_model_setup) || (param == POD_effect_setup)) /* these also affect other settings */
705ececd
MG
331 line6_invalidate_current(&pod->dumpreq);
332}
333
705ececd 334/*
1027f476
MG
335 Identify system parameters related to the tuner.
336*/
337static bool pod_is_tuner(int code)
338{
339 return
e1a164d7
MG
340 (code == POD_tuner_mute) ||
341 (code == POD_tuner_freq) ||
342 (code == POD_tuner_note) || (code == POD_tuner_pitch);
1027f476
MG
343}
344
705ececd 345/*
1027f476 346 Send system parameter (from integer).
705ececd
MG
347 @param tuner non-zero, if code refers to a tuner parameter
348*/
e1a164d7
MG
349static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
350 int code)
705ececd
MG
351{
352 char *sysex;
353 static const int size = 5;
705ececd 354
e1a164d7
MG
355 if (((pod->prog_data.control[POD_tuner] & 0x40) == 0)
356 && pod_is_tuner(code))
705ececd
MG
357 return -EINVAL;
358
359 /* send value to tuner: */
360 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
0fdef36a 361 if (!sysex)
1027f476 362 return -ENOMEM;
705ececd
MG
363 sysex[SYSEX_DATA_OFS] = code;
364 sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
e1a164d7
MG
365 sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;
366 sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f;
367 sysex[SYSEX_DATA_OFS + 4] = (value) & 0x0f;
705ececd
MG
368 line6_send_sysex_message(&pod->line6, sysex, size);
369 kfree(sysex);
1027f476
MG
370 return 0;
371}
372
705ececd
MG
373/*
374 "read" request on "midi_postprocess" special file.
375*/
77491e52
GKH
376static ssize_t pod_get_midi_postprocess(struct device *dev,
377 struct device_attribute *attr,
378 char *buf)
705ececd
MG
379{
380 struct usb_interface *interface = to_usb_interface(dev);
381 struct usb_line6_pod *pod = usb_get_intfdata(interface);
382 return sprintf(buf, "%d\n", pod->midi_postprocess);
383}
384
385/*
386 "write" request on "midi_postprocess" special file.
387*/
77491e52
GKH
388static ssize_t pod_set_midi_postprocess(struct device *dev,
389 struct device_attribute *attr,
390 const char *buf, size_t count)
705ececd
MG
391{
392 struct usb_interface *interface = to_usb_interface(dev);
393 struct usb_line6_pod *pod = usb_get_intfdata(interface);
06501787 394 u8 value;
7e4d5c13
SB
395 int ret;
396
06501787 397 ret = kstrtou8(buf, 10, &value);
7e4d5c13
SB
398 if (ret)
399 return ret;
400
705ececd
MG
401 pod->midi_postprocess = value ? 1 : 0;
402 return count;
403}
404
405/*
406 "read" request on "serial_number" special file.
407*/
77491e52
GKH
408static ssize_t pod_get_serial_number(struct device *dev,
409 struct device_attribute *attr, char *buf)
705ececd
MG
410{
411 struct usb_interface *interface = to_usb_interface(dev);
412 struct usb_line6_pod *pod = usb_get_intfdata(interface);
413 return sprintf(buf, "%d\n", pod->serial_number);
414}
415
416/*
417 "read" request on "firmware_version" special file.
418*/
77491e52
GKH
419static ssize_t pod_get_firmware_version(struct device *dev,
420 struct device_attribute *attr,
421 char *buf)
705ececd
MG
422{
423 struct usb_interface *interface = to_usb_interface(dev);
424 struct usb_line6_pod *pod = usb_get_intfdata(interface);
0fdef36a
GKH
425 return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
426 pod->firmware_version % 100);
705ececd
MG
427}
428
429/*
430 "read" request on "device_id" special file.
431*/
77491e52
GKH
432static ssize_t pod_get_device_id(struct device *dev,
433 struct device_attribute *attr, char *buf)
705ececd
MG
434{
435 struct usb_interface *interface = to_usb_interface(dev);
436 struct usb_line6_pod *pod = usb_get_intfdata(interface);
437 return sprintf(buf, "%d\n", pod->device_id);
438}
439
1027f476
MG
440/*
441 POD startup procedure.
442 This is a sequence of functions with special requirements (e.g., must
443 not run immediately after initialization, must not run in interrupt
444 context). After the last one has finished, the device is ready to use.
445*/
446
447static void pod_startup1(struct usb_line6_pod *pod)
448{
e1a164d7 449 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
1027f476
MG
450
451 /* delay startup procedure: */
e1a164d7
MG
452 line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
453 (unsigned long)pod);
1027f476
MG
454}
455
456static void pod_startup2(unsigned long data)
457{
458 struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
e1a164d7
MG
459
460 /* schedule another startup procedure until startup is complete: */
461 if (pod->startup_progress >= POD_STARTUP_LAST)
462 return;
463
464 pod->startup_progress = POD_STARTUP_DUMPREQ;
465 line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
466 (unsigned long)pod);
1027f476
MG
467
468 /* current channel dump: */
e1a164d7
MG
469 line6_dump_request_async(&pod->dumpreq, &pod->line6, 0,
470 LINE6_DUMP_CURRENT);
1027f476
MG
471}
472
473static void pod_startup3(struct usb_line6_pod *pod)
474{
475 struct usb_line6 *line6 = &pod->line6;
e1a164d7 476 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
1027f476
MG
477
478 /* request firmware version: */
479 line6_version_request_async(line6);
705ececd
MG
480}
481
1027f476
MG
482static void pod_startup4(struct usb_line6_pod *pod)
483{
e1a164d7 484 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
1027f476
MG
485
486 /* schedule work for global work queue: */
487 schedule_work(&pod->startup_work);
488}
489
490static void pod_startup5(struct work_struct *work)
491{
e1a164d7
MG
492 struct usb_line6_pod *pod =
493 container_of(work, struct usb_line6_pod, startup_work);
1027f476
MG
494 struct usb_line6 *line6 = &pod->line6;
495
e1a164d7 496 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
1027f476
MG
497
498 /* serial number: */
499 line6_read_serial_number(&pod->line6, &pod->serial_number);
500
501 /* ALSA audio interface: */
502 line6_register_audio(line6);
503
504 /* device files: */
e1a164d7
MG
505 line6_pod_create_files(pod->firmware_version,
506 line6->properties->device_bit, line6->ifcdev);
1027f476
MG
507}
508
705ececd 509/* POD special files: */
705ececd 510static DEVICE_ATTR(device_id, S_IRUGO, pod_get_device_id, line6_nop_write);
e1a164d7
MG
511static DEVICE_ATTR(firmware_version, S_IRUGO, pod_get_firmware_version,
512 line6_nop_write);
a3a972a0 513static DEVICE_ATTR(midi_postprocess, S_IWUSR | S_IRUGO,
e1a164d7 514 pod_get_midi_postprocess, pod_set_midi_postprocess);
e1a164d7
MG
515static DEVICE_ATTR(serial_number, S_IRUGO, pod_get_serial_number,
516 line6_nop_write);
705ececd 517
1027f476 518#ifdef CONFIG_LINE6_USB_RAW
a3a972a0 519static DEVICE_ATTR(raw, S_IWUSR, line6_nop_read, line6_set_raw);
705ececd
MG
520#endif
521
1027f476
MG
522/* control info callback */
523static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
524 struct snd_ctl_elem_info *uinfo)
525{
526 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
527 uinfo->count = 1;
528 uinfo->value.integer.min = 0;
529 uinfo->value.integer.max = 65535;
530 return 0;
531}
532
533/* control get callback */
534static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
535 struct snd_ctl_elem_value *ucontrol)
536{
537 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
538 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
2c35dc21 539 ucontrol->value.integer.value[0] = pod->monitor_level;
1027f476
MG
540 return 0;
541}
542
543/* control put callback */
544static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
545 struct snd_ctl_elem_value *ucontrol)
546{
547 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
548 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
549
2c35dc21 550 if (ucontrol->value.integer.value[0] == pod->monitor_level)
1027f476
MG
551 return 0;
552
2c35dc21 553 pod->monitor_level = ucontrol->value.integer.value[0];
e1a164d7
MG
554 pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
555 POD_monitor_level);
1027f476
MG
556 return 1;
557}
558
559/* control definition */
560static struct snd_kcontrol_new pod_control_monitor = {
561 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
562 .name = "Monitor Playback Volume",
563 .index = 0,
564 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
565 .info = snd_pod_control_monitor_info,
566 .get = snd_pod_control_monitor_get,
567 .put = snd_pod_control_monitor_put
568};
569
705ececd
MG
570/*
571 POD destructor.
572*/
573static void pod_destruct(struct usb_interface *interface)
574{
575 struct usb_line6_pod *pod = usb_get_intfdata(interface);
705ececd 576
0fdef36a
GKH
577 if (pod == NULL)
578 return;
188e6645 579 line6_cleanup_audio(&pod->line6);
705ececd 580
e1a164d7
MG
581 del_timer(&pod->startup_timer);
582 cancel_work_sync(&pod->startup_work);
583
705ececd
MG
584 /* free dump request data: */
585 line6_dumpreq_destruct(&pod->dumpreq);
705ececd
MG
586}
587
588/*
589 Create sysfs entries.
590*/
b702ed25 591static int pod_create_files2(struct device *dev)
705ececd
MG
592{
593 int err;
594
705ececd 595 CHECK_RETURN(device_create_file(dev, &dev_attr_device_id));
705ececd
MG
596 CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version));
597 CHECK_RETURN(device_create_file(dev, &dev_attr_midi_postprocess));
705ececd 598 CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number));
705ececd 599
1027f476 600#ifdef CONFIG_LINE6_USB_RAW
705ececd
MG
601 CHECK_RETURN(device_create_file(dev, &dev_attr_raw));
602#endif
603
604 return 0;
605}
606
607/*
1027f476 608 Try to init POD device.
705ececd 609*/
e1a164d7
MG
610static int pod_try_init(struct usb_interface *interface,
611 struct usb_line6_pod *pod)
705ececd
MG
612{
613 int err;
614 struct usb_line6 *line6 = &pod->line6;
615
e1a164d7
MG
616 init_timer(&pod->startup_timer);
617 INIT_WORK(&pod->startup_work, pod_startup5);
618
0fdef36a
GKH
619 if ((interface == NULL) || (pod == NULL))
620 return -ENODEV;
705ececd 621
705ececd 622 /* initialize USB buffers: */
0fdef36a
GKH
623 err = line6_dumpreq_init(&pod->dumpreq, pod_request_channel,
624 sizeof(pod_request_channel));
625 if (err < 0) {
705ececd 626 dev_err(&interface->dev, "Out of memory\n");
705ececd
MG
627 return -ENOMEM;
628 }
629
705ececd 630 /* create sysfs entries: */
0fdef36a 631 err = pod_create_files2(&interface->dev);
027360c5 632 if (err < 0)
705ececd 633 return err;
705ececd
MG
634
635 /* initialize audio system: */
0fdef36a 636 err = line6_init_audio(line6);
027360c5 637 if (err < 0)
705ececd 638 return err;
705ececd
MG
639
640 /* initialize MIDI subsystem: */
0fdef36a 641 err = line6_init_midi(line6);
027360c5 642 if (err < 0)
705ececd 643 return err;
705ececd
MG
644
645 /* initialize PCM subsystem: */
0fdef36a 646 err = line6_init_pcm(line6, &pod_pcm_properties);
027360c5 647 if (err < 0)
705ececd 648 return err;
705ececd 649
1027f476 650 /* register monitor control: */
027360c5
GKH
651 err = snd_ctl_add(line6->card,
652 snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
653 if (err < 0)
705ececd 654 return err;
705ececd 655
1027f476 656 /*
e1a164d7
MG
657 When the sound card is registered at this point, the PODxt Live
658 displays "Invalid Code Error 07", so we do it later in the event
659 handler.
660 */
1027f476 661
0fdef36a 662 if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) {
2c35dc21 663 pod->monitor_level = POD_system_invalid;
1027f476
MG
664
665 /* initiate startup procedure: */
666 pod_startup1(pod);
705ececd
MG
667 }
668
669 return 0;
670}
671
1027f476
MG
672/*
673 Init POD device (and clean up in case of failure).
674*/
675int line6_pod_init(struct usb_interface *interface, struct usb_line6_pod *pod)
676{
677 int err = pod_try_init(interface, pod);
678
027360c5 679 if (err < 0)
1027f476 680 pod_destruct(interface);
1027f476
MG
681
682 return err;
683}
684
705ececd
MG
685/*
686 POD device disconnected.
687*/
1027f476 688void line6_pod_disconnect(struct usb_interface *interface)
705ececd
MG
689{
690 struct usb_line6_pod *pod;
691
0fdef36a
GKH
692 if (interface == NULL)
693 return;
705ececd
MG
694 pod = usb_get_intfdata(interface);
695
0fdef36a 696 if (pod != NULL) {
705ececd
MG
697 struct snd_line6_pcm *line6pcm = pod->line6.line6pcm;
698 struct device *dev = &interface->dev;
699
027360c5 700 if (line6pcm != NULL)
1027f476 701 line6_pcm_disconnect(line6pcm);
705ececd 702
0fdef36a 703 if (dev != NULL) {
705ececd 704 /* remove sysfs entries: */
e1a164d7
MG
705 line6_pod_remove_files(pod->firmware_version,
706 pod->line6.
707 properties->device_bit, dev);
705ececd 708
705ececd 709 device_remove_file(dev, &dev_attr_device_id);
705ececd
MG
710 device_remove_file(dev, &dev_attr_firmware_version);
711 device_remove_file(dev, &dev_attr_midi_postprocess);
705ececd 712 device_remove_file(dev, &dev_attr_serial_number);
705ececd 713
1027f476 714#ifdef CONFIG_LINE6_USB_RAW
705ececd
MG
715 device_remove_file(dev, &dev_attr_raw);
716#endif
717 }
718 }
719
720 pod_destruct(interface);
721}
This page took 0.384149 seconds and 5 git commands to generate.