[go: nahoru, domu]

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/pcm.h>
15#include <sound/pcm_params.h>
16
17#include "audio.h"
18#include "capture.h"
19#include "driver.h"
20#include "pcm.h"
21#include "pod.h"
22#include "playback.h"
23
24/*
25	Software stereo volume control.
26*/
27static void change_volume(struct urb *urb_out, int volume[],
28			  int bytes_per_frame)
29{
30	int chn = 0;
31
32	if (volume[0] == 256 && volume[1] == 256)
33		return;		/* maximum volume - no change */
34
35	if (bytes_per_frame == 4) {
36		short *p, *buf_end;
37
38		p = (short *)urb_out->transfer_buffer;
39		buf_end = p + urb_out->transfer_buffer_length / sizeof(*p);
40
41		for (; p < buf_end; ++p) {
42			*p = (*p * volume[chn & 1]) >> 8;
43			++chn;
44		}
45	} else if (bytes_per_frame == 6) {
46		unsigned char *p, *buf_end;
47
48		p = (unsigned char *)urb_out->transfer_buffer;
49		buf_end = p + urb_out->transfer_buffer_length;
50
51		for (; p < buf_end; p += 3) {
52			int val;
53
54			val = p[0] + (p[1] << 8) + ((signed char)p[2] << 16);
55			val = (val * volume[chn & 1]) >> 8;
56			p[0] = val;
57			p[1] = val >> 8;
58			p[2] = val >> 16;
59			++chn;
60		}
61	}
62}
63
64#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
65
66/*
67	Create signal for impulse response test.
68*/
69static void create_impulse_test_signal(struct snd_line6_pcm *line6pcm,
70				       struct urb *urb_out, int bytes_per_frame)
71{
72	int frames = urb_out->transfer_buffer_length / bytes_per_frame;
73
74	if (bytes_per_frame == 4) {
75		int i;
76		short *pi = (short *)line6pcm->prev_fbuf;
77		short *po = (short *)urb_out->transfer_buffer;
78
79		for (i = 0; i < frames; ++i) {
80			po[0] = pi[0];
81			po[1] = 0;
82			pi += 2;
83			po += 2;
84		}
85	} else if (bytes_per_frame == 6) {
86		int i, j;
87		unsigned char *pi = line6pcm->prev_fbuf;
88		unsigned char *po = urb_out->transfer_buffer;
89
90		for (i = 0; i < frames; ++i) {
91			for (j = 0; j < bytes_per_frame / 2; ++j)
92				po[j] = pi[j];
93
94			for (; j < bytes_per_frame; ++j)
95				po[j] = 0;
96
97			pi += bytes_per_frame;
98			po += bytes_per_frame;
99		}
100	}
101	if (--line6pcm->impulse_count <= 0) {
102		((unsigned char *)(urb_out->transfer_buffer))[bytes_per_frame -
103							      1] =
104		    line6pcm->impulse_volume;
105		line6pcm->impulse_count = line6pcm->impulse_period;
106	}
107}
108
109#endif
110
111/*
112	Add signal to buffer for software monitoring.
113*/
114static void add_monitor_signal(struct urb *urb_out, unsigned char *signal,
115			       int volume, int bytes_per_frame)
116{
117	if (volume == 0)
118		return;		/* zero volume - no change */
119
120	if (bytes_per_frame == 4) {
121		short *pi, *po, *buf_end;
122
123		pi = (short *)signal;
124		po = (short *)urb_out->transfer_buffer;
125		buf_end = po + urb_out->transfer_buffer_length / sizeof(*po);
126
127		for (; po < buf_end; ++pi, ++po)
128			*po += (*pi * volume) >> 8;
129	}
130
131	/*
132	   We don't need to handle devices with 6 bytes per frame here
133	   since they all support hardware monitoring.
134	 */
135}
136
137/*
138	Find a free URB, prepare audio data, and submit URB.
139*/
140static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
141{
142	int index;
143	unsigned long flags;
144	int i, urb_size, urb_frames;
145	int ret;
146	const int bytes_per_frame = line6pcm->properties->bytes_per_frame;
147	const int frame_increment =
148	    line6pcm->properties->snd_line6_rates.rats[0].num_min;
149	const int frame_factor =
150	    line6pcm->properties->snd_line6_rates.rats[0].den *
151	    (USB_INTERVALS_PER_SECOND / LINE6_ISO_INTERVAL);
152	struct urb *urb_out;
153
154	spin_lock_irqsave(&line6pcm->lock_audio_out, flags);
155	index =
156	    find_first_zero_bit(&line6pcm->active_urb_out, LINE6_ISO_BUFFERS);
157
158	if (index < 0 || index >= LINE6_ISO_BUFFERS) {
159		spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags);
160		dev_err(line6pcm->line6->ifcdev, "no free URB found\n");
161		return -EINVAL;
162	}
163
164	urb_out = line6pcm->urb_audio_out[index];
165	urb_size = 0;
166
167	for (i = 0; i < LINE6_ISO_PACKETS; ++i) {
168		/* compute frame size for given sampling rate */
169		int fsize = 0;
170		struct usb_iso_packet_descriptor *fout =
171		    &urb_out->iso_frame_desc[i];
172
173		if (line6pcm->flags & LINE6_BITS_CAPTURE_STREAM)
174			fsize = line6pcm->prev_fsize;
175
176		if (fsize == 0) {
177			int n;
178
179			line6pcm->count_out += frame_increment;
180			n = line6pcm->count_out / frame_factor;
181			line6pcm->count_out -= n * frame_factor;
182			fsize = n * bytes_per_frame;
183		}
184
185		fout->offset = urb_size;
186		fout->length = fsize;
187		urb_size += fsize;
188	}
189
190	if (urb_size == 0) {
191		/* can't determine URB size */
192		spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags);
193		dev_err(line6pcm->line6->ifcdev, "driver bug: urb_size = 0\n");
194		return -EINVAL;
195	}
196
197	urb_frames = urb_size / bytes_per_frame;
198	urb_out->transfer_buffer =
199	    line6pcm->buffer_out +
200	    index * LINE6_ISO_PACKETS * line6pcm->max_packet_size;
201	urb_out->transfer_buffer_length = urb_size;
202	urb_out->context = line6pcm;
203
204	if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, &line6pcm->flags) &&
205	    !test_bit(LINE6_INDEX_PAUSE_PLAYBACK, &line6pcm->flags)) {
206		struct snd_pcm_runtime *runtime =
207		    get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK)->runtime;
208
209		if (line6pcm->pos_out + urb_frames > runtime->buffer_size) {
210			/*
211			   The transferred area goes over buffer boundary,
212			   copy the data to the temp buffer.
213			 */
214			int len;
215
216			len = runtime->buffer_size - line6pcm->pos_out;
217
218			if (len > 0) {
219				memcpy(urb_out->transfer_buffer,
220				       runtime->dma_area +
221				       line6pcm->pos_out * bytes_per_frame,
222				       len * bytes_per_frame);
223				memcpy(urb_out->transfer_buffer +
224				       len * bytes_per_frame, runtime->dma_area,
225				       (urb_frames - len) * bytes_per_frame);
226			} else
227				dev_err(line6pcm->line6->ifcdev, "driver bug: len = %d\n",
228					len);
229		} else {
230			memcpy(urb_out->transfer_buffer,
231			       runtime->dma_area +
232			       line6pcm->pos_out * bytes_per_frame,
233			       urb_out->transfer_buffer_length);
234		}
235
236		line6pcm->pos_out += urb_frames;
237		if (line6pcm->pos_out >= runtime->buffer_size)
238			line6pcm->pos_out -= runtime->buffer_size;
239	} else {
240		memset(urb_out->transfer_buffer, 0,
241		       urb_out->transfer_buffer_length);
242	}
243
244	change_volume(urb_out, line6pcm->volume_playback, bytes_per_frame);
245
246	if (line6pcm->prev_fbuf != NULL) {
247#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
248		if (line6pcm->flags & LINE6_BITS_PCM_IMPULSE) {
249			create_impulse_test_signal(line6pcm, urb_out,
250						   bytes_per_frame);
251			if (line6pcm->flags &
252			    LINE6_BIT_PCM_ALSA_CAPTURE_STREAM) {
253				line6_capture_copy(line6pcm,
254						   urb_out->transfer_buffer,
255						   urb_out->
256						   transfer_buffer_length);
257				line6_capture_check_period(line6pcm,
258					urb_out->transfer_buffer_length);
259			}
260		} else {
261#endif
262			if (!
263			    (line6pcm->line6->
264			     properties->capabilities & LINE6_BIT_HWMON)
265			    && (line6pcm->flags & LINE6_BITS_PLAYBACK_STREAM)
266			    && (line6pcm->flags & LINE6_BITS_CAPTURE_STREAM))
267				add_monitor_signal(urb_out, line6pcm->prev_fbuf,
268						   line6pcm->volume_monitor,
269						   bytes_per_frame);
270#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
271		}
272#endif
273	}
274
275	ret = usb_submit_urb(urb_out, GFP_ATOMIC);
276
277	if (ret == 0)
278		set_bit(index, &line6pcm->active_urb_out);
279	else
280		dev_err(line6pcm->line6->ifcdev,
281			"URB out #%d submission failed (%d)\n", index, ret);
282
283	spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags);
284	return 0;
285}
286
287/*
288	Submit all currently available playback URBs.
289*/
290int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm)
291{
292	int ret, i;
293
294	for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
295		ret = submit_audio_out_urb(line6pcm);
296		if (ret < 0)
297			return ret;
298	}
299
300	return 0;
301}
302
303/*
304	Unlink all currently active playback URBs.
305*/
306void line6_unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm)
307{
308	unsigned int i;
309
310	for (i = LINE6_ISO_BUFFERS; i--;) {
311		if (test_bit(i, &line6pcm->active_urb_out)) {
312			if (!test_and_set_bit(i, &line6pcm->unlink_urb_out)) {
313				struct urb *u = line6pcm->urb_audio_out[i];
314
315				usb_unlink_urb(u);
316			}
317		}
318	}
319}
320
321/*
322	Wait until unlinking of all currently active playback URBs has been
323	finished.
324*/
325void line6_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm)
326{
327	int timeout = HZ;
328	unsigned int i;
329	int alive;
330
331	do {
332		alive = 0;
333		for (i = LINE6_ISO_BUFFERS; i--;) {
334			if (test_bit(i, &line6pcm->active_urb_out))
335				alive++;
336		}
337		if (!alive)
338			break;
339		set_current_state(TASK_UNINTERRUPTIBLE);
340		schedule_timeout(1);
341	} while (--timeout > 0);
342	if (alive)
343		snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive);
344}
345
346/*
347	Unlink all currently active playback URBs, and wait for finishing.
348*/
349void line6_unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm)
350{
351	line6_unlink_audio_out_urbs(line6pcm);
352	line6_wait_clear_audio_out_urbs(line6pcm);
353}
354
355void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm)
356{
357	kfree(line6pcm->buffer_out);
358	line6pcm->buffer_out = NULL;
359}
360
361/*
362	Callback for completed playback URB.
363*/
364static void audio_out_callback(struct urb *urb)
365{
366	int i, index, length = 0, shutdown = 0;
367	unsigned long flags;
368	struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context;
369	struct snd_pcm_substream *substream =
370	    get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK);
371
372#if USE_CLEAR_BUFFER_WORKAROUND
373	memset(urb->transfer_buffer, 0, urb->transfer_buffer_length);
374#endif
375
376	line6pcm->last_frame_out = urb->start_frame;
377
378	/* find index of URB */
379	for (index = LINE6_ISO_BUFFERS; index--;)
380		if (urb == line6pcm->urb_audio_out[index])
381			break;
382
383	if (index < 0)
384		return;		/* URB has been unlinked asynchronously */
385
386	for (i = LINE6_ISO_PACKETS; i--;)
387		length += urb->iso_frame_desc[i].length;
388
389	spin_lock_irqsave(&line6pcm->lock_audio_out, flags);
390
391	if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, &line6pcm->flags)) {
392		struct snd_pcm_runtime *runtime = substream->runtime;
393
394		line6pcm->pos_out_done +=
395		    length / line6pcm->properties->bytes_per_frame;
396
397		if (line6pcm->pos_out_done >= runtime->buffer_size)
398			line6pcm->pos_out_done -= runtime->buffer_size;
399	}
400
401	clear_bit(index, &line6pcm->active_urb_out);
402
403	for (i = LINE6_ISO_PACKETS; i--;)
404		if (urb->iso_frame_desc[i].status == -EXDEV) {
405			shutdown = 1;
406			break;
407		}
408
409	if (test_and_clear_bit(index, &line6pcm->unlink_urb_out))
410		shutdown = 1;
411
412	spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags);
413
414	if (!shutdown) {
415		submit_audio_out_urb(line6pcm);
416
417		if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM,
418			     &line6pcm->flags)) {
419			line6pcm->bytes_out += length;
420			if (line6pcm->bytes_out >= line6pcm->period_out) {
421				line6pcm->bytes_out %= line6pcm->period_out;
422				snd_pcm_period_elapsed(substream);
423			}
424		}
425	}
426}
427
428/* open playback callback */
429static int snd_line6_playback_open(struct snd_pcm_substream *substream)
430{
431	int err;
432	struct snd_pcm_runtime *runtime = substream->runtime;
433	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
434
435	err = snd_pcm_hw_constraint_ratdens(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
436					    (&line6pcm->
437					     properties->snd_line6_rates));
438	if (err < 0)
439		return err;
440
441	runtime->hw = line6pcm->properties->snd_line6_playback_hw;
442	return 0;
443}
444
445/* close playback callback */
446static int snd_line6_playback_close(struct snd_pcm_substream *substream)
447{
448	return 0;
449}
450
451/* hw_params playback callback */
452static int snd_line6_playback_hw_params(struct snd_pcm_substream *substream,
453					struct snd_pcm_hw_params *hw_params)
454{
455	int ret;
456	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
457
458	/* -- Florian Demski [FD] */
459	/* don't ask me why, but this fixes the bug on my machine */
460	if (line6pcm == NULL) {
461		if (substream->pcm == NULL)
462			return -ENOMEM;
463		if (substream->pcm->private_data == NULL)
464			return -ENOMEM;
465		substream->private_data = substream->pcm->private_data;
466		line6pcm = snd_pcm_substream_chip(substream);
467	}
468	/* -- [FD] end */
469
470	ret = line6_pcm_acquire(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER);
471
472	if (ret < 0)
473		return ret;
474
475	ret = snd_pcm_lib_malloc_pages(substream,
476				       params_buffer_bytes(hw_params));
477	if (ret < 0) {
478		line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER);
479		return ret;
480	}
481
482	line6pcm->period_out = params_period_bytes(hw_params);
483	return 0;
484}
485
486/* hw_free playback callback */
487static int snd_line6_playback_hw_free(struct snd_pcm_substream *substream)
488{
489	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
490
491	line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER);
492	return snd_pcm_lib_free_pages(substream);
493}
494
495/* trigger playback callback */
496int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd)
497{
498	int err;
499
500	switch (cmd) {
501	case SNDRV_PCM_TRIGGER_START:
502#ifdef CONFIG_PM
503	case SNDRV_PCM_TRIGGER_RESUME:
504#endif
505		err = line6_pcm_acquire(line6pcm,
506					LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM);
507
508		if (err < 0)
509			return err;
510
511		break;
512
513	case SNDRV_PCM_TRIGGER_STOP:
514#ifdef CONFIG_PM
515	case SNDRV_PCM_TRIGGER_SUSPEND:
516#endif
517		err = line6_pcm_release(line6pcm,
518					LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM);
519
520		if (err < 0)
521			return err;
522
523		break;
524
525	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
526		set_bit(LINE6_INDEX_PAUSE_PLAYBACK, &line6pcm->flags);
527		break;
528
529	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
530		clear_bit(LINE6_INDEX_PAUSE_PLAYBACK, &line6pcm->flags);
531		break;
532
533	default:
534		return -EINVAL;
535	}
536
537	return 0;
538}
539
540/* playback pointer callback */
541static snd_pcm_uframes_t
542snd_line6_playback_pointer(struct snd_pcm_substream *substream)
543{
544	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
545
546	return line6pcm->pos_out_done;
547}
548
549/* playback operators */
550struct snd_pcm_ops snd_line6_playback_ops = {
551	.open = snd_line6_playback_open,
552	.close = snd_line6_playback_close,
553	.ioctl = snd_pcm_lib_ioctl,
554	.hw_params = snd_line6_playback_hw_params,
555	.hw_free = snd_line6_playback_hw_free,
556	.prepare = snd_line6_prepare,
557	.trigger = snd_line6_trigger,
558	.pointer = snd_line6_playback_pointer,
559};
560
561int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm)
562{
563	int i;
564
565	/* create audio URBs and fill in constant values: */
566	for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
567		struct urb *urb;
568
569		/* URB for audio out: */
570		urb = line6pcm->urb_audio_out[i] =
571		    usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL);
572
573		if (urb == NULL) {
574			dev_err(line6pcm->line6->ifcdev, "Out of memory\n");
575			return -ENOMEM;
576		}
577
578		urb->dev = line6pcm->line6->usbdev;
579		urb->pipe =
580		    usb_sndisocpipe(line6pcm->line6->usbdev,
581				    line6pcm->ep_audio_write &
582				    USB_ENDPOINT_NUMBER_MASK);
583		urb->transfer_flags = URB_ISO_ASAP;
584		urb->start_frame = -1;
585		urb->number_of_packets = LINE6_ISO_PACKETS;
586		urb->interval = LINE6_ISO_INTERVAL;
587		urb->error_count = 0;
588		urb->complete = audio_out_callback;
589	}
590
591	return 0;
592}
593