]> Pileus Git - ~andy/linux/blob - drivers/staging/line6/pod.c
Merge tag 'arc-v3.13-rc1-part2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[~andy/linux] / 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
38         /* dumps entire internal memory of PODxt Pro */
39         /* POD_SYSEX_DUMPMEM2  = 0x76 */
40 };
41
42 enum {
43         POD_MONITOR_LEVEL  = 0x04,
44         POD_SYSTEM_INVALID = 0x10000
45 };
46
47 /* *INDENT-ON* */
48
49 enum {
50         POD_DUMP_MEMORY = 2
51 };
52
53 enum {
54         POD_BUSY_READ,
55         POD_BUSY_WRITE,
56         POD_CHANNEL_DIRTY,
57         POD_SAVE_PRESSED,
58         POD_BUSY_MIDISEND
59 };
60
61 static struct snd_ratden pod_ratden = {
62         .num_min = 78125,
63         .num_max = 78125,
64         .num_step = 1,
65         .den = 2
66 };
67
68 static struct line6_pcm_properties pod_pcm_properties = {
69         .snd_line6_playback_hw = {
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 |
75 #ifdef CONFIG_PM
76                                            SNDRV_PCM_INFO_RESUME |
77 #endif
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},
90         .snd_line6_capture_hw = {
91                                  .info = (SNDRV_PCM_INFO_MMAP |
92                                           SNDRV_PCM_INFO_INTERLEAVED |
93                                           SNDRV_PCM_INFO_BLOCK_TRANSFER |
94                                           SNDRV_PCM_INFO_MMAP_VALID |
95 #ifdef CONFIG_PM
96                                           SNDRV_PCM_INFO_RESUME |
97 #endif
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},
110         .snd_line6_rates = {
111                             .nrats = 1,
112                             .rats = &pod_ratden},
113         .bytes_per_frame = POD_BYTES_PER_FRAME
114 };
115
116 static const char pod_version_header[] = {
117         0xf2, 0x7e, 0x7f, 0x06, 0x02
118 };
119
120 /* forward declarations: */
121 static void pod_startup2(unsigned long data);
122 static void pod_startup3(struct usb_line6_pod *pod);
123
124 static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
125                                     int size)
126 {
127         return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code,
128                                         size);
129 }
130
131 /*
132         Process a completely received message.
133 */
134 void line6_pod_process_message(struct usb_line6_pod *pod)
135 {
136         const unsigned char *buf = pod->line6.buffer_message;
137
138         if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) {
139                 pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15];
140                 pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) |
141                                  (int) buf[10];
142                 pod_startup3(pod);
143                 return;
144         }
145
146         /* Only look for sysex messages from this device */
147         if (buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE) &&
148             buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN)) {
149                 return;
150         }
151         if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) != 0)
152                 return;
153
154         if (buf[5] == POD_SYSEX_SYSTEM && buf[6] == POD_MONITOR_LEVEL) {
155                 short value = ((int)buf[7] << 12) | ((int)buf[8] << 8) |
156                               ((int)buf[9] << 4) | (int)buf[10];
157                 pod->monitor_level = value;
158         }
159 }
160
161 /*
162         Transmit PODxt Pro control parameter.
163 */
164 void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param,
165                                   u8 value)
166 {
167         line6_transmit_parameter(&pod->line6, param, value);
168 }
169
170 /*
171         Send system parameter (from integer).
172 */
173 static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
174                                     int code)
175 {
176         char *sysex;
177         static const int size = 5;
178
179         sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
180         if (!sysex)
181                 return -ENOMEM;
182         sysex[SYSEX_DATA_OFS] = code;
183         sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
184         sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;
185         sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f;
186         sysex[SYSEX_DATA_OFS + 4] = (value) & 0x0f;
187         line6_send_sysex_message(&pod->line6, sysex, size);
188         kfree(sysex);
189         return 0;
190 }
191
192 /*
193         "read" request on "serial_number" special file.
194 */
195 static ssize_t serial_number_show(struct device *dev,
196                                   struct device_attribute *attr, char *buf)
197 {
198         struct usb_interface *interface = to_usb_interface(dev);
199         struct usb_line6_pod *pod = usb_get_intfdata(interface);
200         return sprintf(buf, "%d\n", pod->serial_number);
201 }
202
203 /*
204         "read" request on "firmware_version" special file.
205 */
206 static ssize_t firmware_version_show(struct device *dev,
207                                      struct device_attribute *attr, char *buf)
208 {
209         struct usb_interface *interface = to_usb_interface(dev);
210         struct usb_line6_pod *pod = usb_get_intfdata(interface);
211         return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
212                        pod->firmware_version % 100);
213 }
214
215 /*
216         "read" request on "device_id" special file.
217 */
218 static ssize_t device_id_show(struct device *dev,
219                               struct device_attribute *attr, char *buf)
220 {
221         struct usb_interface *interface = to_usb_interface(dev);
222         struct usb_line6_pod *pod = usb_get_intfdata(interface);
223         return sprintf(buf, "%d\n", pod->device_id);
224 }
225
226 /*
227         POD startup procedure.
228         This is a sequence of functions with special requirements (e.g., must
229         not run immediately after initialization, must not run in interrupt
230         context). After the last one has finished, the device is ready to use.
231 */
232
233 static void pod_startup1(struct usb_line6_pod *pod)
234 {
235         CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
236
237         /* delay startup procedure: */
238         line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
239                           (unsigned long)pod);
240 }
241
242 static void pod_startup2(unsigned long data)
243 {
244         struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
245         struct usb_line6 *line6 = &pod->line6;
246         CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
247
248         /* request firmware version: */
249         line6_version_request_async(line6);
250 }
251
252 static void pod_startup3(struct usb_line6_pod *pod)
253 {
254         CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
255
256         /* schedule work for global work queue: */
257         schedule_work(&pod->startup_work);
258 }
259
260 static void pod_startup4(struct work_struct *work)
261 {
262         struct usb_line6_pod *pod =
263             container_of(work, struct usb_line6_pod, startup_work);
264         struct usb_line6 *line6 = &pod->line6;
265
266         CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
267
268         /* serial number: */
269         line6_read_serial_number(&pod->line6, &pod->serial_number);
270
271         /* ALSA audio interface: */
272         line6_register_audio(line6);
273 }
274
275 /* POD special files: */
276 static DEVICE_ATTR_RO(device_id);
277 static DEVICE_ATTR_RO(firmware_version);
278 static DEVICE_ATTR_RO(serial_number);
279
280 /* control info callback */
281 static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
282                                         struct snd_ctl_elem_info *uinfo)
283 {
284         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
285         uinfo->count = 1;
286         uinfo->value.integer.min = 0;
287         uinfo->value.integer.max = 65535;
288         return 0;
289 }
290
291 /* control get callback */
292 static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
293                                        struct snd_ctl_elem_value *ucontrol)
294 {
295         struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
296         struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
297         ucontrol->value.integer.value[0] = pod->monitor_level;
298         return 0;
299 }
300
301 /* control put callback */
302 static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
303                                        struct snd_ctl_elem_value *ucontrol)
304 {
305         struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
306         struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
307
308         if (ucontrol->value.integer.value[0] == pod->monitor_level)
309                 return 0;
310
311         pod->monitor_level = ucontrol->value.integer.value[0];
312         pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
313                                  POD_MONITOR_LEVEL);
314         return 1;
315 }
316
317 /* control definition */
318 static struct snd_kcontrol_new pod_control_monitor = {
319         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
320         .name = "Monitor Playback Volume",
321         .index = 0,
322         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
323         .info = snd_pod_control_monitor_info,
324         .get = snd_pod_control_monitor_get,
325         .put = snd_pod_control_monitor_put
326 };
327
328 /*
329         POD destructor.
330 */
331 static void pod_destruct(struct usb_interface *interface)
332 {
333         struct usb_line6_pod *pod = usb_get_intfdata(interface);
334
335         if (pod == NULL)
336                 return;
337         line6_cleanup_audio(&pod->line6);
338
339         del_timer(&pod->startup_timer);
340         cancel_work_sync(&pod->startup_work);
341 }
342
343 /*
344         Create sysfs entries.
345 */
346 static int pod_create_files2(struct device *dev)
347 {
348         int err;
349
350         CHECK_RETURN(device_create_file(dev, &dev_attr_device_id));
351         CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version));
352         CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number));
353         return 0;
354 }
355
356 /*
357          Try to init POD device.
358 */
359 static int pod_try_init(struct usb_interface *interface,
360                         struct usb_line6_pod *pod)
361 {
362         int err;
363         struct usb_line6 *line6 = &pod->line6;
364
365         init_timer(&pod->startup_timer);
366         INIT_WORK(&pod->startup_work, pod_startup4);
367
368         if ((interface == NULL) || (pod == NULL))
369                 return -ENODEV;
370
371         /* create sysfs entries: */
372         err = pod_create_files2(&interface->dev);
373         if (err < 0)
374                 return err;
375
376         /* initialize audio system: */
377         err = line6_init_audio(line6);
378         if (err < 0)
379                 return err;
380
381         /* initialize MIDI subsystem: */
382         err = line6_init_midi(line6);
383         if (err < 0)
384                 return err;
385
386         /* initialize PCM subsystem: */
387         err = line6_init_pcm(line6, &pod_pcm_properties);
388         if (err < 0)
389                 return err;
390
391         /* register monitor control: */
392         err = snd_ctl_add(line6->card,
393                           snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
394         if (err < 0)
395                 return err;
396
397         /*
398            When the sound card is registered at this point, the PODxt Live
399            displays "Invalid Code Error 07", so we do it later in the event
400            handler.
401          */
402
403         if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) {
404                 pod->monitor_level = POD_SYSTEM_INVALID;
405
406                 /* initiate startup procedure: */
407                 pod_startup1(pod);
408         }
409
410         return 0;
411 }
412
413 /*
414          Init POD device (and clean up in case of failure).
415 */
416 int line6_pod_init(struct usb_interface *interface, struct usb_line6_pod *pod)
417 {
418         int err = pod_try_init(interface, pod);
419
420         if (err < 0)
421                 pod_destruct(interface);
422
423         return err;
424 }
425
426 /*
427         POD device disconnected.
428 */
429 void line6_pod_disconnect(struct usb_interface *interface)
430 {
431         struct usb_line6_pod *pod;
432
433         if (interface == NULL)
434                 return;
435         pod = usb_get_intfdata(interface);
436
437         if (pod != NULL) {
438                 struct snd_line6_pcm *line6pcm = pod->line6.line6pcm;
439                 struct device *dev = &interface->dev;
440
441                 if (line6pcm != NULL)
442                         line6_pcm_disconnect(line6pcm);
443
444                 if (dev != NULL) {
445                         /* remove sysfs entries: */
446                         device_remove_file(dev, &dev_attr_device_id);
447                         device_remove_file(dev, &dev_attr_firmware_version);
448                         device_remove_file(dev, &dev_attr_serial_number);
449                 }
450         }
451
452         pod_destruct(interface);
453 }