staging: line6: avoid CamelCase POD_* enums in pod.c
[platform/adaptation/renesas_rcar/renesas_kernel.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         /* filter messages by type */
139         switch (buf[0] & 0xf0) {
140         case LINE6_PARAM_CHANGE:
141         case LINE6_PROGRAM_CHANGE:
142         case LINE6_SYSEX_BEGIN:
143                 break;          /* handle these further down */
144
145         default:
146                 return;         /* ignore all others */
147         }
148
149         /* process all remaining messages */
150         switch (buf[0]) {
151         case LINE6_PARAM_CHANGE | LINE6_CHANNEL_DEVICE:
152         case LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST:
153                 break;
154
155         case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_DEVICE:
156         case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST:
157                 break;
158
159         case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE:
160         case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN:
161                 if (memcmp(buf + 1, line6_midi_id,
162                            sizeof(line6_midi_id)) == 0) {
163                         switch (buf[5]) {
164                         case POD_SYSEX_DUMP:
165                                 break;
166
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];
172
173                                         if (buf[6] == POD_MONITOR_LEVEL)
174                                                 pod->monitor_level = value;
175                                         break;
176                                 }
177
178                         case POD_SYSEX_FINISH:
179                                 /* do we need to respond to this? */
180                                 break;
181
182                         case POD_SYSEX_SAVE:
183                                 break;
184
185                         case POD_SYSEX_STORE:
186                                 dev_dbg(pod->line6.ifcdev,
187                                         "message %02X not yet implemented\n",
188                                         buf[5]);
189                                 break;
190
191                         default:
192                                 dev_dbg(pod->line6.ifcdev,
193                                         "unknown sysex message %02X\n",
194                                         buf[5]);
195                         }
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];
205                         pod_startup3(pod);
206                 } else
207                         dev_dbg(pod->line6.ifcdev, "unknown sysex header\n");
208
209                 break;
210
211         case LINE6_SYSEX_END:
212                 break;
213
214         default:
215                 dev_dbg(pod->line6.ifcdev, "POD: unknown message %02X\n",
216                         buf[0]);
217         }
218 }
219
220 /*
221         Transmit PODxt Pro control parameter.
222 */
223 void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param,
224                                   u8 value)
225 {
226         line6_transmit_parameter(&pod->line6, param, value);
227 }
228
229 /*
230         Send system parameter (from integer).
231 */
232 static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
233                                     int code)
234 {
235         char *sysex;
236         static const int size = 5;
237
238         sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
239         if (!sysex)
240                 return -ENOMEM;
241         sysex[SYSEX_DATA_OFS] = code;
242         sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
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;
246         line6_send_sysex_message(&pod->line6, sysex, size);
247         kfree(sysex);
248         return 0;
249 }
250
251 /*
252         "read" request on "serial_number" special file.
253 */
254 static ssize_t pod_get_serial_number(struct device *dev,
255                                      struct device_attribute *attr, char *buf)
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 */
265 static ssize_t pod_get_firmware_version(struct device *dev,
266                                         struct device_attribute *attr,
267                                         char *buf)
268 {
269         struct usb_interface *interface = to_usb_interface(dev);
270         struct usb_line6_pod *pod = usb_get_intfdata(interface);
271         return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
272                        pod->firmware_version % 100);
273 }
274
275 /*
276         "read" request on "device_id" special file.
277 */
278 static ssize_t pod_get_device_id(struct device *dev,
279                                  struct device_attribute *attr, char *buf)
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
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
293 static void pod_startup1(struct usb_line6_pod *pod)
294 {
295         CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
296
297         /* delay startup procedure: */
298         line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
299                           (unsigned long)pod);
300 }
301
302 static void pod_startup2(unsigned long data)
303 {
304         struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
305         struct usb_line6 *line6 = &pod->line6;
306         CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
307
308         /* request firmware version: */
309         line6_version_request_async(line6);
310 }
311
312 static void pod_startup3(struct usb_line6_pod *pod)
313 {
314         CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
315
316         /* schedule work for global work queue: */
317         schedule_work(&pod->startup_work);
318 }
319
320 static void pod_startup4(struct work_struct *work)
321 {
322         struct usb_line6_pod *pod =
323             container_of(work, struct usb_line6_pod, startup_work);
324         struct usb_line6 *line6 = &pod->line6;
325
326         CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
327
328         /* serial number: */
329         line6_read_serial_number(&pod->line6, &pod->serial_number);
330
331         /* ALSA audio interface: */
332         line6_register_audio(line6);
333 }
334
335 /* POD special files: */
336 static DEVICE_ATTR(device_id, S_IRUGO, pod_get_device_id, line6_nop_write);
337 static DEVICE_ATTR(firmware_version, S_IRUGO, pod_get_firmware_version,
338                    line6_nop_write);
339 static DEVICE_ATTR(serial_number, S_IRUGO, pod_get_serial_number,
340                    line6_nop_write);
341
342 /* control info callback */
343 static 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 */
354 static 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;
359         ucontrol->value.integer.value[0] = pod->monitor_level;
360         return 0;
361 }
362
363 /* control put callback */
364 static 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
370         if (ucontrol->value.integer.value[0] == pod->monitor_level)
371                 return 0;
372
373         pod->monitor_level = ucontrol->value.integer.value[0];
374         pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
375                                  POD_MONITOR_LEVEL);
376         return 1;
377 }
378
379 /* control definition */
380 static 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
390 /*
391         POD destructor.
392 */
393 static void pod_destruct(struct usb_interface *interface)
394 {
395         struct usb_line6_pod *pod = usb_get_intfdata(interface);
396
397         if (pod == NULL)
398                 return;
399         line6_cleanup_audio(&pod->line6);
400
401         del_timer(&pod->startup_timer);
402         cancel_work_sync(&pod->startup_work);
403 }
404
405 /*
406         Create sysfs entries.
407 */
408 static int pod_create_files2(struct device *dev)
409 {
410         int err;
411
412         CHECK_RETURN(device_create_file(dev, &dev_attr_device_id));
413         CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version));
414         CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number));
415         return 0;
416 }
417
418 /*
419          Try to init POD device.
420 */
421 static int pod_try_init(struct usb_interface *interface,
422                         struct usb_line6_pod *pod)
423 {
424         int err;
425         struct usb_line6 *line6 = &pod->line6;
426
427         init_timer(&pod->startup_timer);
428         INIT_WORK(&pod->startup_work, pod_startup4);
429
430         if ((interface == NULL) || (pod == NULL))
431                 return -ENODEV;
432
433         /* create sysfs entries: */
434         err = pod_create_files2(&interface->dev);
435         if (err < 0)
436                 return err;
437
438         /* initialize audio system: */
439         err = line6_init_audio(line6);
440         if (err < 0)
441                 return err;
442
443         /* initialize MIDI subsystem: */
444         err = line6_init_midi(line6);
445         if (err < 0)
446                 return err;
447
448         /* initialize PCM subsystem: */
449         err = line6_init_pcm(line6, &pod_pcm_properties);
450         if (err < 0)
451                 return err;
452
453         /* register monitor control: */
454         err = snd_ctl_add(line6->card,
455                           snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
456         if (err < 0)
457                 return err;
458
459         /*
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          */
464
465         if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) {
466                 pod->monitor_level = POD_SYSTEM_INVALID;
467
468                 /* initiate startup procedure: */
469                 pod_startup1(pod);
470         }
471
472         return 0;
473 }
474
475 /*
476          Init POD device (and clean up in case of failure).
477 */
478 int line6_pod_init(struct usb_interface *interface, struct usb_line6_pod *pod)
479 {
480         int err = pod_try_init(interface, pod);
481
482         if (err < 0)
483                 pod_destruct(interface);
484
485         return err;
486 }
487
488 /*
489         POD device disconnected.
490 */
491 void line6_pod_disconnect(struct usb_interface *interface)
492 {
493         struct usb_line6_pod *pod;
494
495         if (interface == NULL)
496                 return;
497         pod = usb_get_intfdata(interface);
498
499         if (pod != NULL) {
500                 struct snd_line6_pcm *line6pcm = pod->line6.line6pcm;
501                 struct device *dev = &interface->dev;
502
503                 if (line6pcm != NULL)
504                         line6_pcm_disconnect(line6pcm);
505
506                 if (dev != NULL) {
507                         /* remove sysfs entries: */
508                         device_remove_file(dev, &dev_attr_device_id);
509                         device_remove_file(dev, &dev_attr_firmware_version);
510                         device_remove_file(dev, &dev_attr_serial_number);
511                 }
512         }
513
514         pod_destruct(interface);
515 }