]> Pileus Git - ~andy/linux/blob - drivers/staging/line6/pcm.c
Merge branch 'omap1-part2' into omap1
[~andy/linux] / drivers / staging / line6 / pcm.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 <sound/core.h>
14 #include <sound/control.h>
15 #include <sound/pcm.h>
16 #include <sound/pcm_params.h>
17
18 #include "audio.h"
19 #include "capture.h"
20 #include "driver.h"
21 #include "playback.h"
22 #include "pod.h"
23
24 #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
25
26 static struct snd_line6_pcm *dev2pcm(struct device *dev)
27 {
28         struct usb_interface *interface = to_usb_interface(dev);
29         struct usb_line6 *line6 = usb_get_intfdata(interface);
30         struct snd_line6_pcm *line6pcm = line6->line6pcm;
31         return line6pcm;
32 }
33
34 /*
35         "read" request on "impulse_volume" special file.
36 */
37 static ssize_t pcm_get_impulse_volume(struct device *dev,
38                                       struct device_attribute *attr, char *buf)
39 {
40         return sprintf(buf, "%d\n", dev2pcm(dev)->impulse_volume);
41 }
42
43 /*
44         "write" request on "impulse_volume" special file.
45 */
46 static ssize_t pcm_set_impulse_volume(struct device *dev,
47                                       struct device_attribute *attr,
48                                       const char *buf, size_t count)
49 {
50         struct snd_line6_pcm *line6pcm = dev2pcm(dev);
51         int value = simple_strtoul(buf, NULL, 10);
52         line6pcm->impulse_volume = value;
53
54         if (value > 0)
55                 line6_pcm_start(line6pcm, MASK_PCM_IMPULSE);
56         else
57                 line6_pcm_stop(line6pcm, MASK_PCM_IMPULSE);
58
59         return count;
60 }
61
62 /*
63         "read" request on "impulse_period" special file.
64 */
65 static ssize_t pcm_get_impulse_period(struct device *dev,
66                                       struct device_attribute *attr, char *buf)
67 {
68         return sprintf(buf, "%d\n", dev2pcm(dev)->impulse_period);
69 }
70
71 /*
72         "write" request on "impulse_period" special file.
73 */
74 static ssize_t pcm_set_impulse_period(struct device *dev,
75                                       struct device_attribute *attr,
76                                       const char *buf, size_t count)
77 {
78         dev2pcm(dev)->impulse_period = simple_strtoul(buf, NULL, 10);
79         return count;
80 }
81
82 static DEVICE_ATTR(impulse_volume, S_IWUSR | S_IRUGO, pcm_get_impulse_volume,
83                    pcm_set_impulse_volume);
84 static DEVICE_ATTR(impulse_period, S_IWUSR | S_IRUGO, pcm_get_impulse_period,
85                    pcm_set_impulse_period);
86
87 #endif
88
89 static bool test_flags(unsigned long flags0, unsigned long flags1,
90                        unsigned long mask)
91 {
92         return ((flags0 & mask) == 0) && ((flags1 & mask) != 0);
93 }
94
95 int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels)
96 {
97         unsigned long flags_old =
98             __sync_fetch_and_or(&line6pcm->flags, channels);
99         unsigned long flags_new = flags_old | channels;
100         int err = 0;
101         
102         line6pcm->prev_fbuf = NULL;
103
104         if (test_flags(flags_old, flags_new, MASK_CAPTURE)) {
105                 /*
106                    Waiting for completion of active URBs in the stop handler is
107                    a bug, we therefore report an error if capturing is restarted
108                    too soon.
109                  */
110                 if (line6pcm->active_urb_in | line6pcm->unlink_urb_in)
111                         return -EBUSY;
112
113                 if (!(flags_new & MASK_PCM_ALSA_CAPTURE)) {
114                         err = line6_alloc_capture_buffer(line6pcm);
115
116                         if (err < 0)
117                                 goto pcm_start_error;
118                 }
119
120                 line6pcm->count_in = 0;
121                 line6pcm->prev_fsize = 0;
122                 err = line6_submit_audio_in_all_urbs(line6pcm);
123
124                 if (err < 0)
125                         goto pcm_start_error;
126         }
127
128         if (test_flags(flags_old, flags_new, MASK_PLAYBACK)) {
129                 /*
130                    See comment above regarding PCM restart.
131                  */
132                 if (line6pcm->active_urb_out | line6pcm->unlink_urb_out)
133                         return -EBUSY;
134
135                 if (!(flags_new & MASK_PCM_ALSA_PLAYBACK)) {
136                         err = line6_alloc_playback_buffer(line6pcm);
137
138                         if (err < 0)
139                                 goto pcm_start_error;
140                 }
141
142                 line6pcm->count_out = 0;
143                 err = line6_submit_audio_out_all_urbs(line6pcm);
144
145                 if (err < 0)
146                         goto pcm_start_error;
147         }
148
149         return 0;
150
151 pcm_start_error:
152         __sync_fetch_and_and(&line6pcm->flags, ~channels);
153         return err;
154 }
155
156 int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels)
157 {
158         unsigned long flags_old =
159             __sync_fetch_and_and(&line6pcm->flags, ~channels);
160         unsigned long flags_new = flags_old & ~channels;
161
162         if (test_flags(flags_new, flags_old, MASK_CAPTURE)) {
163                 line6_unlink_audio_in_urbs(line6pcm);
164
165                 if (!(flags_old & MASK_PCM_ALSA_CAPTURE))
166                         line6_free_capture_buffer(line6pcm);
167         }
168
169         if (test_flags(flags_new, flags_old, MASK_PLAYBACK)) {
170                 line6_unlink_audio_out_urbs(line6pcm);
171
172                 if (!(flags_old & MASK_PCM_ALSA_PLAYBACK))
173                         line6_free_playback_buffer(line6pcm);
174         }
175
176         return 0;
177 }
178
179 /* trigger callback */
180 int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
181 {
182         struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
183         struct snd_pcm_substream *s;
184         int err;
185         unsigned long flags;
186
187         spin_lock_irqsave(&line6pcm->lock_trigger, flags);
188         clear_bit(BIT_PREPARED, &line6pcm->flags);
189
190         snd_pcm_group_for_each_entry(s, substream) {
191                 switch (s->stream) {
192                 case SNDRV_PCM_STREAM_PLAYBACK:
193                         err = snd_line6_playback_trigger(line6pcm, cmd);
194
195                         if (err < 0) {
196                                 spin_unlock_irqrestore(&line6pcm->lock_trigger,
197                                                        flags);
198                                 return err;
199                         }
200
201                         break;
202
203                 case SNDRV_PCM_STREAM_CAPTURE:
204                         err = snd_line6_capture_trigger(line6pcm, cmd);
205
206                         if (err < 0) {
207                                 spin_unlock_irqrestore(&line6pcm->lock_trigger,
208                                                        flags);
209                                 return err;
210                         }
211
212                         break;
213
214                 default:
215                         dev_err(line6pcm->line6->ifcdev,
216                                 "Unknown stream direction %d\n", s->stream);
217                 }
218         }
219
220         spin_unlock_irqrestore(&line6pcm->lock_trigger, flags);
221         return 0;
222 }
223
224 /* control info callback */
225 static int snd_line6_control_playback_info(struct snd_kcontrol *kcontrol,
226                                            struct snd_ctl_elem_info *uinfo)
227 {
228         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
229         uinfo->count = 2;
230         uinfo->value.integer.min = 0;
231         uinfo->value.integer.max = 256;
232         return 0;
233 }
234
235 /* control get callback */
236 static int snd_line6_control_playback_get(struct snd_kcontrol *kcontrol,
237                                           struct snd_ctl_elem_value *ucontrol)
238 {
239         int i;
240         struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
241
242         for (i = 2; i--;)
243                 ucontrol->value.integer.value[i] = line6pcm->volume_playback[i];
244
245         return 0;
246 }
247
248 /* control put callback */
249 static int snd_line6_control_playback_put(struct snd_kcontrol *kcontrol,
250                                           struct snd_ctl_elem_value *ucontrol)
251 {
252         int i, changed = 0;
253         struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
254
255         for (i = 2; i--;)
256                 if (line6pcm->volume_playback[i] !=
257                     ucontrol->value.integer.value[i]) {
258                         line6pcm->volume_playback[i] =
259                             ucontrol->value.integer.value[i];
260                         changed = 1;
261                 }
262
263         return changed;
264 }
265
266 /* control definition */
267 static struct snd_kcontrol_new line6_control_playback = {
268         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
269         .name = "PCM Playback Volume",
270         .index = 0,
271         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
272         .info = snd_line6_control_playback_info,
273         .get = snd_line6_control_playback_get,
274         .put = snd_line6_control_playback_put
275 };
276
277 /*
278         Cleanup the PCM device.
279 */
280 static void line6_cleanup_pcm(struct snd_pcm *pcm)
281 {
282         int i;
283         struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm);
284
285 #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
286         device_remove_file(line6pcm->line6->ifcdev, &dev_attr_impulse_volume);
287         device_remove_file(line6pcm->line6->ifcdev, &dev_attr_impulse_period);
288 #endif
289
290         for (i = LINE6_ISO_BUFFERS; i--;) {
291                 if (line6pcm->urb_audio_out[i]) {
292                         usb_kill_urb(line6pcm->urb_audio_out[i]);
293                         usb_free_urb(line6pcm->urb_audio_out[i]);
294                 }
295                 if (line6pcm->urb_audio_in[i]) {
296                         usb_kill_urb(line6pcm->urb_audio_in[i]);
297                         usb_free_urb(line6pcm->urb_audio_in[i]);
298                 }
299         }
300 }
301
302 /* create a PCM device */
303 static int snd_line6_new_pcm(struct snd_line6_pcm *line6pcm)
304 {
305         struct snd_pcm *pcm;
306         int err;
307
308         err = snd_pcm_new(line6pcm->line6->card,
309                           (char *)line6pcm->line6->properties->name,
310                           0, 1, 1, &pcm);
311         if (err < 0)
312                 return err;
313
314         pcm->private_data = line6pcm;
315         pcm->private_free = line6_cleanup_pcm;
316         line6pcm->pcm = pcm;
317         strcpy(pcm->name, line6pcm->line6->properties->name);
318
319         /* set operators */
320         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
321                         &snd_line6_playback_ops);
322         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_line6_capture_ops);
323
324         /* pre-allocation of buffers */
325         snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
326                                               snd_dma_continuous_data
327                                               (GFP_KERNEL), 64 * 1024,
328                                               128 * 1024);
329
330         return 0;
331 }
332
333 /* PCM device destructor */
334 static int snd_line6_pcm_free(struct snd_device *device)
335 {
336         return 0;
337 }
338
339 /*
340         Stop substream if still running.
341 */
342 static void pcm_disconnect_substream(struct snd_pcm_substream *substream)
343 {
344         if (substream->runtime && snd_pcm_running(substream))
345                 snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
346 }
347
348 /*
349         Stop PCM stream.
350 */
351 void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm)
352 {
353         pcm_disconnect_substream(get_substream
354                                  (line6pcm, SNDRV_PCM_STREAM_CAPTURE));
355         pcm_disconnect_substream(get_substream
356                                  (line6pcm, SNDRV_PCM_STREAM_PLAYBACK));
357         line6_unlink_wait_clear_audio_out_urbs(line6pcm);
358         line6_unlink_wait_clear_audio_in_urbs(line6pcm);
359 }
360
361 /*
362         Create and register the PCM device and mixer entries.
363         Create URBs for playback and capture.
364 */
365 int line6_init_pcm(struct usb_line6 *line6,
366                    struct line6_pcm_properties *properties)
367 {
368         static struct snd_device_ops pcm_ops = {
369                 .dev_free = snd_line6_pcm_free,
370         };
371
372         int err;
373         int ep_read = 0, ep_write = 0;
374         struct snd_line6_pcm *line6pcm;
375
376         if (!(line6->properties->capabilities & LINE6_BIT_PCM))
377                 return 0;       /* skip PCM initialization and report success */
378
379         /* initialize PCM subsystem based on product id: */
380         switch (line6->product) {
381         case LINE6_DEVID_BASSPODXT:
382         case LINE6_DEVID_BASSPODXTLIVE:
383         case LINE6_DEVID_BASSPODXTPRO:
384         case LINE6_DEVID_PODXT:
385         case LINE6_DEVID_PODXTLIVE:
386         case LINE6_DEVID_PODXTPRO:
387         case LINE6_DEVID_PODHD300:
388                 ep_read = 0x82;
389                 ep_write = 0x01;
390                 break;
391
392         case LINE6_DEVID_PODHD500:
393         case LINE6_DEVID_PODX3:
394         case LINE6_DEVID_PODX3LIVE:
395                 ep_read = 0x86;
396                 ep_write = 0x02;
397                 break;
398
399         case LINE6_DEVID_POCKETPOD:
400                 ep_read = 0x82;
401                 ep_write = 0x02;
402                 break;
403
404         case LINE6_DEVID_GUITARPORT:
405         case LINE6_DEVID_PODSTUDIO_GX:
406         case LINE6_DEVID_PODSTUDIO_UX1:
407         case LINE6_DEVID_PODSTUDIO_UX2:
408         case LINE6_DEVID_TONEPORT_GX:
409         case LINE6_DEVID_TONEPORT_UX1:
410         case LINE6_DEVID_TONEPORT_UX2:
411                 ep_read = 0x82;
412                 ep_write = 0x01;
413                 break;
414
415                 /* this is for interface_number == 1:
416                    case LINE6_DEVID_TONEPORT_UX2:
417                    case LINE6_DEVID_PODSTUDIO_UX2:
418                    ep_read  = 0x87;
419                    ep_write = 0x00;
420                    break;
421                  */
422
423         default:
424                 MISSING_CASE;
425         }
426
427         line6pcm = kzalloc(sizeof(struct snd_line6_pcm), GFP_KERNEL);
428
429         if (line6pcm == NULL)
430                 return -ENOMEM;
431
432         line6pcm->volume_playback[0] = line6pcm->volume_playback[1] = 255;
433         line6pcm->volume_monitor = 255;
434         line6pcm->line6 = line6;
435         line6pcm->ep_audio_read = ep_read;
436         line6pcm->ep_audio_write = ep_write;
437
438         /* Read and write buffers are sized identically, so choose minimum */
439         line6pcm->max_packet_size = min(
440                         usb_maxpacket(line6->usbdev,
441                                 usb_rcvisocpipe(line6->usbdev, ep_read), 0),
442                         usb_maxpacket(line6->usbdev,
443                                 usb_sndisocpipe(line6->usbdev, ep_write), 1));
444
445         line6pcm->properties = properties;
446         line6->line6pcm = line6pcm;
447
448         /* PCM device: */
449         err = snd_device_new(line6->card, SNDRV_DEV_PCM, line6, &pcm_ops);
450         if (err < 0)
451                 return err;
452
453         snd_card_set_dev(line6->card, line6->ifcdev);
454
455         err = snd_line6_new_pcm(line6pcm);
456         if (err < 0)
457                 return err;
458
459         spin_lock_init(&line6pcm->lock_audio_out);
460         spin_lock_init(&line6pcm->lock_audio_in);
461         spin_lock_init(&line6pcm->lock_trigger);
462
463         err = line6_create_audio_out_urbs(line6pcm);
464         if (err < 0)
465                 return err;
466
467         err = line6_create_audio_in_urbs(line6pcm);
468         if (err < 0)
469                 return err;
470
471         /* mixer: */
472         err =
473             snd_ctl_add(line6->card,
474                         snd_ctl_new1(&line6_control_playback, line6pcm));
475         if (err < 0)
476                 return err;
477
478 #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
479         /* impulse response test: */
480         err = device_create_file(line6->ifcdev, &dev_attr_impulse_volume);
481         if (err < 0)
482                 return err;
483
484         err = device_create_file(line6->ifcdev, &dev_attr_impulse_period);
485         if (err < 0)
486                 return err;
487
488         line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD;
489 #endif
490
491         return 0;
492 }
493
494 /* prepare pcm callback */
495 int snd_line6_prepare(struct snd_pcm_substream *substream)
496 {
497         struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
498
499         switch (substream->stream) {
500         case SNDRV_PCM_STREAM_PLAYBACK:
501                 if ((line6pcm->flags & MASK_PLAYBACK) == 0)
502                         line6_unlink_wait_clear_audio_out_urbs(line6pcm);
503
504                 break;
505
506         case SNDRV_PCM_STREAM_CAPTURE:
507                 if ((line6pcm->flags & MASK_CAPTURE) == 0)
508                         line6_unlink_wait_clear_audio_in_urbs(line6pcm);
509
510                 break;
511
512         default:
513                 MISSING_CASE;
514         }
515
516         if (!test_and_set_bit(BIT_PREPARED, &line6pcm->flags)) {
517                 line6pcm->count_out = 0;
518                 line6pcm->pos_out = 0;
519                 line6pcm->pos_out_done = 0;
520                 line6pcm->bytes_out = 0;
521                 line6pcm->count_in = 0;
522                 line6pcm->pos_in_done = 0;
523                 line6pcm->bytes_in = 0;
524         }
525
526         return 0;
527 }