]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/line6/pod.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid...
[karo-tx-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
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
201         return sprintf(buf, "%d\n", pod->serial_number);
202 }
203
204 /*
205         "read" request on "firmware_version" special file.
206 */
207 static ssize_t firmware_version_show(struct device *dev,
208                                      struct device_attribute *attr, char *buf)
209 {
210         struct usb_interface *interface = to_usb_interface(dev);
211         struct usb_line6_pod *pod = usb_get_intfdata(interface);
212
213         return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
214                        pod->firmware_version % 100);
215 }
216
217 /*
218         "read" request on "device_id" special file.
219 */
220 static ssize_t device_id_show(struct device *dev,
221                               struct device_attribute *attr, char *buf)
222 {
223         struct usb_interface *interface = to_usb_interface(dev);
224         struct usb_line6_pod *pod = usb_get_intfdata(interface);
225
226         return sprintf(buf, "%d\n", pod->device_id);
227 }
228
229 /*
230         POD startup procedure.
231         This is a sequence of functions with special requirements (e.g., must
232         not run immediately after initialization, must not run in interrupt
233         context). After the last one has finished, the device is ready to use.
234 */
235
236 static void pod_startup1(struct usb_line6_pod *pod)
237 {
238         CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
239
240         /* delay startup procedure: */
241         line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
242                           (unsigned long)pod);
243 }
244
245 static void pod_startup2(unsigned long data)
246 {
247         struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
248         struct usb_line6 *line6 = &pod->line6;
249
250         CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
251
252         /* request firmware version: */
253         line6_version_request_async(line6);
254 }
255
256 static void pod_startup3(struct usb_line6_pod *pod)
257 {
258         CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
259
260         /* schedule work for global work queue: */
261         schedule_work(&pod->startup_work);
262 }
263
264 static void pod_startup4(struct work_struct *work)
265 {
266         struct usb_line6_pod *pod =
267             container_of(work, struct usb_line6_pod, startup_work);
268         struct usb_line6 *line6 = &pod->line6;
269
270         CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
271
272         /* serial number: */
273         line6_read_serial_number(&pod->line6, &pod->serial_number);
274
275         /* ALSA audio interface: */
276         line6_register_audio(line6);
277 }
278
279 /* POD special files: */
280 static DEVICE_ATTR_RO(device_id);
281 static DEVICE_ATTR_RO(firmware_version);
282 static DEVICE_ATTR_RO(serial_number);
283
284 /* control info callback */
285 static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
286                                         struct snd_ctl_elem_info *uinfo)
287 {
288         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
289         uinfo->count = 1;
290         uinfo->value.integer.min = 0;
291         uinfo->value.integer.max = 65535;
292         return 0;
293 }
294
295 /* control get callback */
296 static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
297                                        struct snd_ctl_elem_value *ucontrol)
298 {
299         struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
300         struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
301
302         ucontrol->value.integer.value[0] = pod->monitor_level;
303         return 0;
304 }
305
306 /* control put callback */
307 static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
308                                        struct snd_ctl_elem_value *ucontrol)
309 {
310         struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
311         struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
312
313         if (ucontrol->value.integer.value[0] == pod->monitor_level)
314                 return 0;
315
316         pod->monitor_level = ucontrol->value.integer.value[0];
317         pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
318                                  POD_MONITOR_LEVEL);
319         return 1;
320 }
321
322 /* control definition */
323 static struct snd_kcontrol_new pod_control_monitor = {
324         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
325         .name = "Monitor Playback Volume",
326         .index = 0,
327         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
328         .info = snd_pod_control_monitor_info,
329         .get = snd_pod_control_monitor_get,
330         .put = snd_pod_control_monitor_put
331 };
332
333 /*
334         POD destructor.
335 */
336 static void pod_destruct(struct usb_interface *interface)
337 {
338         struct usb_line6_pod *pod = usb_get_intfdata(interface);
339
340         if (pod == NULL)
341                 return;
342         line6_cleanup_audio(&pod->line6);
343
344         del_timer(&pod->startup_timer);
345         cancel_work_sync(&pod->startup_work);
346 }
347
348 /*
349         Create sysfs entries.
350 */
351 static int pod_create_files2(struct device *dev)
352 {
353         int err;
354
355         CHECK_RETURN(device_create_file(dev, &dev_attr_device_id));
356         CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version));
357         CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number));
358         return 0;
359 }
360
361 /*
362          Try to init POD device.
363 */
364 static int pod_try_init(struct usb_interface *interface,
365                         struct usb_line6_pod *pod)
366 {
367         int err;
368         struct usb_line6 *line6 = &pod->line6;
369
370         init_timer(&pod->startup_timer);
371         INIT_WORK(&pod->startup_work, pod_startup4);
372
373         if ((interface == NULL) || (pod == NULL))
374                 return -ENODEV;
375
376         /* create sysfs entries: */
377         err = pod_create_files2(&interface->dev);
378         if (err < 0)
379                 return err;
380
381         /* initialize audio system: */
382         err = line6_init_audio(line6);
383         if (err < 0)
384                 return err;
385
386         /* initialize MIDI subsystem: */
387         err = line6_init_midi(line6);
388         if (err < 0)
389                 return err;
390
391         /* initialize PCM subsystem: */
392         err = line6_init_pcm(line6, &pod_pcm_properties);
393         if (err < 0)
394                 return err;
395
396         /* register monitor control: */
397         err = snd_ctl_add(line6->card,
398                           snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
399         if (err < 0)
400                 return err;
401
402         /*
403            When the sound card is registered at this point, the PODxt Live
404            displays "Invalid Code Error 07", so we do it later in the event
405            handler.
406          */
407
408         if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) {
409                 pod->monitor_level = POD_SYSTEM_INVALID;
410
411                 /* initiate startup procedure: */
412                 pod_startup1(pod);
413         }
414
415         return 0;
416 }
417
418 /*
419          Init POD device (and clean up in case of failure).
420 */
421 int line6_pod_init(struct usb_interface *interface, struct usb_line6_pod *pod)
422 {
423         int err = pod_try_init(interface, pod);
424
425         if (err < 0)
426                 pod_destruct(interface);
427
428         return err;
429 }
430
431 /*
432         POD device disconnected.
433 */
434 void line6_pod_disconnect(struct usb_interface *interface)
435 {
436         struct usb_line6_pod *pod;
437
438         if (interface == NULL)
439                 return;
440         pod = usb_get_intfdata(interface);
441
442         if (pod != NULL) {
443                 struct snd_line6_pcm *line6pcm = pod->line6.line6pcm;
444                 struct device *dev = &interface->dev;
445
446                 if (line6pcm != NULL)
447                         line6_pcm_disconnect(line6pcm);
448
449                 if (dev != NULL) {
450                         /* remove sysfs entries: */
451                         device_remove_file(dev, &dev_attr_device_id);
452                         device_remove_file(dev, &dev_attr_firmware_version);
453                         device_remove_file(dev, &dev_attr_serial_number);
454                 }
455         }
456
457         pod_destruct(interface);
458 }