staging: line6: wrap lines to 80 chars in pod.c
[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"
1027f476 18#include "driver.h"
705ececd
MG
19#include "playback.h"
20#include "pod.h"
21
705ececd 22#define POD_SYSEX_CODE 3
e1a164d7 23#define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */
705ececd 24
e1a164d7 25/* *INDENT-OFF* */
705ececd
MG
26
27enum {
705ececd
MG
28 POD_SYSEX_SAVE = 0x24,
29 POD_SYSEX_SYSTEM = 0x56,
30 POD_SYSEX_SYSTEMREQ = 0x57,
31 /* POD_SYSEX_UPDATE = 0x6c, */ /* software update! */
32 POD_SYSEX_STORE = 0x71,
33 POD_SYSEX_FINISH = 0x72,
34 POD_SYSEX_DUMPMEM = 0x73,
35 POD_SYSEX_DUMP = 0x74,
36 POD_SYSEX_DUMPREQ = 0x75
0a1eb4e8
SH
37
38 /* dumps entire internal memory of PODxt Pro */
39 /* POD_SYSEX_DUMPMEM2 = 0x76 */
705ececd
MG
40};
41
42enum {
43 POD_monitor_level = 0x04,
1027f476 44 POD_system_invalid = 0x10000
705ececd
MG
45};
46
e1a164d7
MG
47/* *INDENT-ON* */
48
705ececd
MG
49enum {
50 POD_DUMP_MEMORY = 2
51};
52
53enum {
54 POD_BUSY_READ,
55 POD_BUSY_WRITE,
56 POD_CHANNEL_DIRTY,
57 POD_SAVE_PRESSED,
58 POD_BUSY_MIDISEND
59};
60
705ececd
MG
61static struct snd_ratden pod_ratden = {
62 .num_min = 78125,
63 .num_max = 78125,
64 .num_step = 1,
65 .den = 2
66};
67
68static struct line6_pcm_properties pod_pcm_properties = {
1027f476 69 .snd_line6_playback_hw = {
e1a164d7
MG
70 .info = (SNDRV_PCM_INFO_MMAP |
71 SNDRV_PCM_INFO_INTERLEAVED |
72 SNDRV_PCM_INFO_BLOCK_TRANSFER |
73 SNDRV_PCM_INFO_MMAP_VALID |
74 SNDRV_PCM_INFO_PAUSE |
1027f476 75#ifdef CONFIG_PM
e1a164d7 76 SNDRV_PCM_INFO_RESUME |
1027f476 77#endif
e1a164d7
MG
78 SNDRV_PCM_INFO_SYNC_START),
79 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
80 .rates = SNDRV_PCM_RATE_KNOT,
81 .rate_min = 39062,
82 .rate_max = 39063,
83 .channels_min = 2,
84 .channels_max = 2,
85 .buffer_bytes_max = 60000,
86 .period_bytes_min = 64,
87 .period_bytes_max = 8192,
88 .periods_min = 1,
89 .periods_max = 1024},
1027f476 90 .snd_line6_capture_hw = {
e1a164d7
MG
91 .info = (SNDRV_PCM_INFO_MMAP |
92 SNDRV_PCM_INFO_INTERLEAVED |
93 SNDRV_PCM_INFO_BLOCK_TRANSFER |
94 SNDRV_PCM_INFO_MMAP_VALID |
1027f476 95#ifdef CONFIG_PM
e1a164d7 96 SNDRV_PCM_INFO_RESUME |
1027f476 97#endif
e1a164d7
MG
98 SNDRV_PCM_INFO_SYNC_START),
99 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
100 .rates = SNDRV_PCM_RATE_KNOT,
101 .rate_min = 39062,
102 .rate_max = 39063,
103 .channels_min = 2,
104 .channels_max = 2,
105 .buffer_bytes_max = 60000,
106 .period_bytes_min = 64,
107 .period_bytes_max = 8192,
108 .periods_min = 1,
109 .periods_max = 1024},
705ececd 110 .snd_line6_rates = {
e1a164d7
MG
111 .nrats = 1,
112 .rats = &pod_ratden},
705ececd
MG
113 .bytes_per_frame = POD_BYTES_PER_FRAME
114};
115
e1a164d7 116static const char pod_version_header[] = {
1027f476
MG
117 0xf2, 0x7e, 0x7f, 0x06, 0x02
118};
119
1027f476
MG
120/* forward declarations: */
121static void pod_startup2(unsigned long data);
122static void pod_startup3(struct usb_line6_pod *pod);
705ececd 123
e1a164d7
MG
124static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
125 int size)
705ececd 126{
e1a164d7
MG
127 return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code,
128 size);
705ececd
MG
129}
130
705ececd
MG
131/*
132 Process a completely received message.
133*/
1027f476 134void line6_pod_process_message(struct usb_line6_pod *pod)
705ececd
MG
135{
136 const unsigned char *buf = pod->line6.buffer_message;
137
138 /* filter messages by type */
0fdef36a 139 switch (buf[0] & 0xf0) {
705ececd
MG
140 case LINE6_PARAM_CHANGE:
141 case LINE6_PROGRAM_CHANGE:
142 case LINE6_SYSEX_BEGIN:
e1a164d7 143 break; /* handle these further down */
705ececd
MG
144
145 default:
e1a164d7 146 return; /* ignore all others */
705ececd
MG
147 }
148
149 /* process all remaining messages */
0fdef36a 150 switch (buf[0]) {
705ececd 151 case LINE6_PARAM_CHANGE | LINE6_CHANNEL_DEVICE:
705ececd 152 case LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST:
705ececd
MG
153 break;
154
155 case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_DEVICE:
156 case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST:
705ececd
MG
157 break;
158
159 case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE:
160 case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN:
0a1eb4e8
SH
161 if (memcmp(buf + 1, line6_midi_id,
162 sizeof(line6_midi_id)) == 0) {
0fdef36a 163 switch (buf[5]) {
705ececd 164 case POD_SYSEX_DUMP:
705ececd
MG
165 break;
166
e1a164d7
MG
167 case POD_SYSEX_SYSTEM:{
168 short value =
169 ((int)buf[7] << 12) | ((int)buf[8]
170 << 8) |
171 ((int)buf[9] << 4) | (int)buf[10];
705ececd 172
99c54e98 173 if (buf[6] == POD_monitor_level)
2c35dc21 174 pod->monitor_level = value;
e1a164d7
MG
175 break;
176 }
705ececd
MG
177
178 case POD_SYSEX_FINISH:
179 /* do we need to respond to this? */
180 break;
181
182 case POD_SYSEX_SAVE:
705ececd
MG
183 break;
184
705ececd 185 case POD_SYSEX_STORE:
e00d33cb
SH
186 dev_dbg(pod->line6.ifcdev,
187 "message %02X not yet implemented\n",
188 buf[5]);
705ececd
MG
189 break;
190
191 default:
e00d33cb
SH
192 dev_dbg(pod->line6.ifcdev,
193 "unknown sysex message %02X\n",
194 buf[5]);
705ececd 195 }
e1a164d7
MG
196 } else
197 if (memcmp
198 (buf, pod_version_header,
199 sizeof(pod_version_header)) == 0) {
200 pod->firmware_version =
201 buf[13] * 100 + buf[14] * 10 + buf[15];
202 pod->device_id =
203 ((int)buf[8] << 16) | ((int)buf[9] << 8) | (int)
204 buf[10];
09fda10a 205 pod_startup3(pod);
0fdef36a 206 } else
e00d33cb 207 dev_dbg(pod->line6.ifcdev, "unknown sysex header\n");
705ececd
MG
208
209 break;
210
211 case LINE6_SYSEX_END:
212 break;
213
214 default:
e00d33cb
SH
215 dev_dbg(pod->line6.ifcdev, "POD: unknown message %02X\n",
216 buf[0]);
705ececd
MG
217 }
218}
219
705ececd
MG
220/*
221 Transmit PODxt Pro control parameter.
222*/
e1a164d7 223void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param,
5b9bd2ad 224 u8 value)
705ececd 225{
79038f61 226 line6_transmit_parameter(&pod->line6, param, value);
705ececd
MG
227}
228
705ececd 229/*
1027f476 230 Send system parameter (from integer).
705ececd 231*/
e1a164d7
MG
232static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
233 int code)
705ececd
MG
234{
235 char *sysex;
236 static const int size = 5;
705ececd 237
705ececd 238 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
0fdef36a 239 if (!sysex)
1027f476 240 return -ENOMEM;
705ececd
MG
241 sysex[SYSEX_DATA_OFS] = code;
242 sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
e1a164d7
MG
243 sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;
244 sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f;
245 sysex[SYSEX_DATA_OFS + 4] = (value) & 0x0f;
705ececd
MG
246 line6_send_sysex_message(&pod->line6, sysex, size);
247 kfree(sysex);
1027f476
MG
248 return 0;
249}
250
705ececd
MG
251/*
252 "read" request on "serial_number" special file.
253*/
77491e52
GKH
254static ssize_t pod_get_serial_number(struct device *dev,
255 struct device_attribute *attr, char *buf)
705ececd
MG
256{
257 struct usb_interface *interface = to_usb_interface(dev);
258 struct usb_line6_pod *pod = usb_get_intfdata(interface);
259 return sprintf(buf, "%d\n", pod->serial_number);
260}
261
262/*
263 "read" request on "firmware_version" special file.
264*/
77491e52
GKH
265static ssize_t pod_get_firmware_version(struct device *dev,
266 struct device_attribute *attr,
267 char *buf)
705ececd
MG
268{
269 struct usb_interface *interface = to_usb_interface(dev);
270 struct usb_line6_pod *pod = usb_get_intfdata(interface);
0fdef36a
GKH
271 return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
272 pod->firmware_version % 100);
705ececd
MG
273}
274
275/*
276 "read" request on "device_id" special file.
277*/
77491e52
GKH
278static ssize_t pod_get_device_id(struct device *dev,
279 struct device_attribute *attr, char *buf)
705ececd
MG
280{
281 struct usb_interface *interface = to_usb_interface(dev);
282 struct usb_line6_pod *pod = usb_get_intfdata(interface);
283 return sprintf(buf, "%d\n", pod->device_id);
284}
285
1027f476
MG
286/*
287 POD startup procedure.
288 This is a sequence of functions with special requirements (e.g., must
289 not run immediately after initialization, must not run in interrupt
290 context). After the last one has finished, the device is ready to use.
291*/
292
293static void pod_startup1(struct usb_line6_pod *pod)
294{
e1a164d7 295 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
1027f476
MG
296
297 /* delay startup procedure: */
e1a164d7
MG
298 line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
299 (unsigned long)pod);
1027f476
MG
300}
301
302static void pod_startup2(unsigned long data)
303{
304 struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
1027f476 305 struct usb_line6 *line6 = &pod->line6;
e1a164d7 306 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
1027f476
MG
307
308 /* request firmware version: */
309 line6_version_request_async(line6);
705ececd
MG
310}
311
09fda10a 312static void pod_startup3(struct usb_line6_pod *pod)
1027f476 313{
e1a164d7 314 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
1027f476
MG
315
316 /* schedule work for global work queue: */
317 schedule_work(&pod->startup_work);
318}
319
09fda10a 320static void pod_startup4(struct work_struct *work)
1027f476 321{
e1a164d7
MG
322 struct usb_line6_pod *pod =
323 container_of(work, struct usb_line6_pod, startup_work);
1027f476
MG
324 struct usb_line6 *line6 = &pod->line6;
325
e1a164d7 326 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
1027f476
MG
327
328 /* serial number: */
329 line6_read_serial_number(&pod->line6, &pod->serial_number);
330
331 /* ALSA audio interface: */
332 line6_register_audio(line6);
1027f476
MG
333}
334
705ececd 335/* POD special files: */
705ececd 336static DEVICE_ATTR(device_id, S_IRUGO, pod_get_device_id, line6_nop_write);
e1a164d7
MG
337static DEVICE_ATTR(firmware_version, S_IRUGO, pod_get_firmware_version,
338 line6_nop_write);
e1a164d7
MG
339static DEVICE_ATTR(serial_number, S_IRUGO, pod_get_serial_number,
340 line6_nop_write);
705ececd 341
1027f476
MG
342/* control info callback */
343static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
344 struct snd_ctl_elem_info *uinfo)
345{
346 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
347 uinfo->count = 1;
348 uinfo->value.integer.min = 0;
349 uinfo->value.integer.max = 65535;
350 return 0;
351}
352
353/* control get callback */
354static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
355 struct snd_ctl_elem_value *ucontrol)
356{
357 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
358 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
2c35dc21 359 ucontrol->value.integer.value[0] = pod->monitor_level;
1027f476
MG
360 return 0;
361}
362
363/* control put callback */
364static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
365 struct snd_ctl_elem_value *ucontrol)
366{
367 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
368 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
369
2c35dc21 370 if (ucontrol->value.integer.value[0] == pod->monitor_level)
1027f476
MG
371 return 0;
372
2c35dc21 373 pod->monitor_level = ucontrol->value.integer.value[0];
e1a164d7
MG
374 pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
375 POD_monitor_level);
1027f476
MG
376 return 1;
377}
378
379/* control definition */
380static struct snd_kcontrol_new pod_control_monitor = {
381 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
382 .name = "Monitor Playback Volume",
383 .index = 0,
384 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
385 .info = snd_pod_control_monitor_info,
386 .get = snd_pod_control_monitor_get,
387 .put = snd_pod_control_monitor_put
388};
389
705ececd
MG
390/*
391 POD destructor.
392*/
393static void pod_destruct(struct usb_interface *interface)
394{
395 struct usb_line6_pod *pod = usb_get_intfdata(interface);
705ececd 396
0fdef36a
GKH
397 if (pod == NULL)
398 return;
188e6645 399 line6_cleanup_audio(&pod->line6);
705ececd 400
e1a164d7
MG
401 del_timer(&pod->startup_timer);
402 cancel_work_sync(&pod->startup_work);
705ececd
MG
403}
404
405/*
406 Create sysfs entries.
407*/
b702ed25 408static int pod_create_files2(struct device *dev)
705ececd
MG
409{
410 int err;
411
705ececd 412 CHECK_RETURN(device_create_file(dev, &dev_attr_device_id));
705ececd 413 CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version));
705ececd 414 CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number));
705ececd
MG
415 return 0;
416}
417
418/*
1027f476 419 Try to init POD device.
705ececd 420*/
e1a164d7
MG
421static int pod_try_init(struct usb_interface *interface,
422 struct usb_line6_pod *pod)
705ececd
MG
423{
424 int err;
425 struct usb_line6 *line6 = &pod->line6;
426
e1a164d7 427 init_timer(&pod->startup_timer);
09fda10a 428 INIT_WORK(&pod->startup_work, pod_startup4);
e1a164d7 429
0fdef36a
GKH
430 if ((interface == NULL) || (pod == NULL))
431 return -ENODEV;
705ececd 432
705ececd 433 /* create sysfs entries: */
0fdef36a 434 err = pod_create_files2(&interface->dev);
027360c5 435 if (err < 0)
705ececd 436 return err;
705ececd
MG
437
438 /* initialize audio system: */
0fdef36a 439 err = line6_init_audio(line6);
027360c5 440 if (err < 0)
705ececd 441 return err;
705ececd
MG
442
443 /* initialize MIDI subsystem: */
0fdef36a 444 err = line6_init_midi(line6);
027360c5 445 if (err < 0)
705ececd 446 return err;
705ececd
MG
447
448 /* initialize PCM subsystem: */
0fdef36a 449 err = line6_init_pcm(line6, &pod_pcm_properties);
027360c5 450 if (err < 0)
705ececd 451 return err;
705ececd 452
1027f476 453 /* register monitor control: */
027360c5
GKH
454 err = snd_ctl_add(line6->card,
455 snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
456 if (err < 0)
705ececd 457 return err;
705ececd 458
1027f476 459 /*
e1a164d7
MG
460 When the sound card is registered at this point, the PODxt Live
461 displays "Invalid Code Error 07", so we do it later in the event
462 handler.
463 */
1027f476 464
0fdef36a 465 if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) {
2c35dc21 466 pod->monitor_level = POD_system_invalid;
1027f476
MG
467
468 /* initiate startup procedure: */
469 pod_startup1(pod);
705ececd
MG
470 }
471
472 return 0;
473}
474
1027f476
MG
475/*
476 Init POD device (and clean up in case of failure).
477*/
478int line6_pod_init(struct usb_interface *interface, struct usb_line6_pod *pod)
479{
480 int err = pod_try_init(interface, pod);
481
027360c5 482 if (err < 0)
1027f476 483 pod_destruct(interface);
1027f476
MG
484
485 return err;
486}
487
705ececd
MG
488/*
489 POD device disconnected.
490*/
1027f476 491void line6_pod_disconnect(struct usb_interface *interface)
705ececd
MG
492{
493 struct usb_line6_pod *pod;
494
0fdef36a
GKH
495 if (interface == NULL)
496 return;
705ececd
MG
497 pod = usb_get_intfdata(interface);
498
0fdef36a 499 if (pod != NULL) {
705ececd
MG
500 struct snd_line6_pcm *line6pcm = pod->line6.line6pcm;
501 struct device *dev = &interface->dev;
502
027360c5 503 if (line6pcm != NULL)
1027f476 504 line6_pcm_disconnect(line6pcm);
705ececd 505
0fdef36a 506 if (dev != NULL) {
705ececd 507 /* remove sysfs entries: */
705ececd 508 device_remove_file(dev, &dev_attr_device_id);
705ececd 509 device_remove_file(dev, &dev_attr_firmware_version);
705ececd 510 device_remove_file(dev, &dev_attr_serial_number);
705ececd
MG
511 }
512 }
513
514 pod_destruct(interface);
515}
This page took 0.390081 seconds and 5 git commands to generate.