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