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