Linux Audio

Check our new training course

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