pcm.c 14.7 KB
Newer Older
M
Markus Grabner 已提交
1
/*
2
 * Line 6 Linux USB driver
M
Markus Grabner 已提交
3
 *
4
 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
M
Markus Grabner 已提交
5 6 7 8 9 10 11
 *
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License as
 *	published by the Free Software Foundation, version 2.
 *
 */

12
#include <linux/slab.h>
T
Takashi Iwai 已提交
13
#include <linux/export.h>
M
Markus Grabner 已提交
14 15 16 17 18 19
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>

#include "capture.h"
20
#include "driver.h"
M
Markus Grabner 已提交
21 22
#include "playback.h"

23 24 25
/* impulse response volume controls */
static int snd_line6_impulse_volume_info(struct snd_kcontrol *kcontrol,
					 struct snd_ctl_elem_info *uinfo)
26
{
27 28 29 30 31
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = 1;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = 255;
	return 0;
32 33
}

34 35
static int snd_line6_impulse_volume_get(struct snd_kcontrol *kcontrol,
					struct snd_ctl_elem_value *ucontrol)
36
{
37 38 39 40
	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);

	ucontrol->value.integer.value[0] = line6pcm->impulse_volume;
	return 0;
41 42
}

43 44
static int snd_line6_impulse_volume_put(struct snd_kcontrol *kcontrol,
					struct snd_ctl_elem_value *ucontrol)
45
{
46 47
	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
	int value = ucontrol->value.integer.value[0];
48
	int err;
49

50 51
	if (line6pcm->impulse_volume == value)
		return 0;
52

53
	line6pcm->impulse_volume = value;
54 55 56 57 58 59 60
	if (value > 0) {
		err = line6_pcm_acquire(line6pcm, LINE6_STREAM_IMPULSE);
		if (err < 0) {
			line6pcm->impulse_volume = 0;
			return err;
		}
	} else {
61
		line6_pcm_release(line6pcm, LINE6_STREAM_IMPULSE);
62
	}
63 64
	return 1;
}
65

66 67 68 69 70 71 72 73 74
/* impulse response period controls */
static int snd_line6_impulse_period_info(struct snd_kcontrol *kcontrol,
					 struct snd_ctl_elem_info *uinfo)
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = 1;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = 2000;
	return 0;
75 76
}

77 78
static int snd_line6_impulse_period_get(struct snd_kcontrol *kcontrol,
					struct snd_ctl_elem_value *ucontrol)
79
{
80 81 82 83
	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);

	ucontrol->value.integer.value[0] = line6pcm->impulse_period;
	return 0;
84 85
}

86 87
static int snd_line6_impulse_period_put(struct snd_kcontrol *kcontrol,
					struct snd_ctl_elem_value *ucontrol)
88
{
89 90
	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
	int value = ucontrol->value.integer.value[0];
91

92 93
	if (line6pcm->impulse_period == value)
		return 0;
94

95 96
	line6pcm->impulse_period = value;
	return 1;
97 98
}

99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
/*
	Unlink all currently active URBs.
*/
static void line6_unlink_audio_urbs(struct snd_line6_pcm *line6pcm,
				    struct line6_pcm_stream *pcms)
{
	int i;

	for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
		if (test_bit(i, &pcms->active_urbs)) {
			if (!test_and_set_bit(i, &pcms->unlink_urbs))
				usb_unlink_urb(pcms->urbs[i]);
		}
	}
}

/*
	Wait until unlinking of all currently active URBs has been finished.
*/
static void line6_wait_clear_audio_urbs(struct snd_line6_pcm *line6pcm,
					struct line6_pcm_stream *pcms)
{
	int timeout = HZ;
	int i;
	int alive;

	do {
		alive = 0;
		for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
			if (test_bit(i, &pcms->active_urbs))
				alive++;
		}
		if (!alive)
			break;
		set_current_state(TASK_UNINTERRUPTIBLE);
		schedule_timeout(1);
	} while (--timeout > 0);
	if (alive)
T
Takashi Iwai 已提交
137 138
		dev_err(line6pcm->line6->ifcdev,
			"timeout: still %d active urbs..\n", alive);
139 140
}

141 142
static inline struct line6_pcm_stream *
get_stream(struct snd_line6_pcm *line6pcm, int direction)
143
{
144 145
	return (direction == SNDRV_PCM_STREAM_PLAYBACK) ?
		&line6pcm->out : &line6pcm->in;
146 147
}

148 149 150 151 152
/* allocate a buffer if not opened yet;
 * call this in line6pcm.state_change mutex
 */
static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm,
				struct line6_pcm_stream *pstr, int type)
153
{
154 155 156 157 158 159 160 161
	/* Invoked multiple times in a row so allocate once only */
	if (!test_and_set_bit(type, &pstr->opened) && !pstr->buffer) {
		pstr->buffer = kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
				       line6pcm->max_packet_size, GFP_KERNEL);
		if (!pstr->buffer)
			return -ENOMEM;
	}
	return 0;
162 163
}

164 165 166 167 168
/* free a buffer if all streams are closed;
 * call this in line6pcm.state_change mutex
 */
static void line6_buffer_release(struct snd_line6_pcm *line6pcm,
				 struct line6_pcm_stream *pstr, int type)
169
{
170 171 172 173 174 175 176

	clear_bit(type, &pstr->opened);
	if (!pstr->opened) {
		line6_wait_clear_audio_urbs(line6pcm, pstr);
		kfree(pstr->buffer);
		pstr->buffer = NULL;
	}
177 178
}

179 180 181
/* start a PCM stream */
static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction,
			      int type)
182
{
183 184 185 186 187
	unsigned long flags;
	struct line6_pcm_stream *pstr = get_stream(line6pcm, direction);
	int ret = 0;

	spin_lock_irqsave(&pstr->lock, flags);
188 189
	if (!test_and_set_bit(type, &pstr->running) &&
	    !(pstr->active_urbs || pstr->unlink_urbs)) {
190 191 192 193 194 195
		pstr->count = 0;
		/* Submit all currently available URBs */
		if (direction == SNDRV_PCM_STREAM_PLAYBACK)
			ret = line6_submit_audio_out_all_urbs(line6pcm);
		else
			ret = line6_submit_audio_in_all_urbs(line6pcm);
196
	}
197 198 199 200 201
	if (ret < 0)
		clear_bit(type, &pstr->running);
	spin_unlock_irqrestore(&pstr->lock, flags);
	return ret;
}
202

203 204 205 206 207 208 209 210 211 212
/* stop a PCM stream; this doesn't sync with the unlinked URBs */
static void line6_stream_stop(struct snd_line6_pcm *line6pcm, int direction,
			  int type)
{
	unsigned long flags;
	struct line6_pcm_stream *pstr = get_stream(line6pcm, direction);

	spin_lock_irqsave(&pstr->lock, flags);
	clear_bit(type, &pstr->running);
	if (!pstr->running) {
213
		spin_unlock_irqrestore(&pstr->lock, flags);
214
		line6_unlink_audio_urbs(line6pcm, pstr);
215
		spin_lock_irqsave(&pstr->lock, flags);
216 217 218
		if (direction == SNDRV_PCM_STREAM_CAPTURE) {
			line6pcm->prev_fbuf = NULL;
			line6pcm->prev_fsize = 0;
219
		}
220 221 222
	}
	spin_unlock_irqrestore(&pstr->lock, flags);
}
223

224 225 226 227 228 229
/* common PCM trigger callback */
int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
{
	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
	struct snd_pcm_substream *s;
	int err;
230

231
	clear_bit(LINE6_FLAG_PREPARED, &line6pcm->flags);
232

233 234 235
	snd_pcm_group_for_each_entry(s, substream) {
		if (s->pcm->card != substream->pcm->card)
			continue;
236

237 238 239 240 241 242 243 244
		switch (cmd) {
		case SNDRV_PCM_TRIGGER_START:
		case SNDRV_PCM_TRIGGER_RESUME:
			err = line6_stream_start(line6pcm, s->stream,
						 LINE6_STREAM_PCM);
			if (err < 0)
				return err;
			break;
245

246 247 248 249 250
		case SNDRV_PCM_TRIGGER_STOP:
		case SNDRV_PCM_TRIGGER_SUSPEND:
			line6_stream_stop(line6pcm, s->stream,
					  LINE6_STREAM_PCM);
			break;
251

252 253 254 255 256
		case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
			if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
				return -EINVAL;
			set_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags);
			break;
257

258 259 260 261 262
		case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
			if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
				return -EINVAL;
			clear_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags);
			break;
263

264 265 266
		default:
			return -EINVAL;
		}
267
	}
268

269 270 271
	return 0;
}

272 273 274 275 276 277 278 279 280
/* common PCM pointer callback */
snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream)
{
	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
	struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);

	return pstr->pos_done;
}

281 282 283 284
/* Acquire and start duplex streams:
 * type is either LINE6_STREAM_IMPULSE or LINE6_STREAM_MONITOR
 */
int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type)
285
{
286 287 288 289 290 291 292 293 294 295 296
	struct line6_pcm_stream *pstr;
	int ret = 0, dir;

	mutex_lock(&line6pcm->state_mutex);
	for (dir = 0; dir < 2; dir++) {
		pstr = get_stream(line6pcm, dir);
		ret = line6_buffer_acquire(line6pcm, pstr, type);
		if (ret < 0)
			goto error;
		if (!pstr->running)
			line6_wait_clear_audio_urbs(line6pcm, pstr);
297
	}
298 299 300 301
	for (dir = 0; dir < 2; dir++) {
		ret = line6_stream_start(line6pcm, dir, type);
		if (ret < 0)
			goto error;
302
	}
303 304 305 306 307 308 309
 error:
	mutex_unlock(&line6pcm->state_mutex);
	if (ret < 0)
		line6_pcm_release(line6pcm, type);
	return ret;
}
EXPORT_SYMBOL_GPL(line6_pcm_acquire);
310

311 312 313 314 315 316 317 318 319 320 321 322
/* Stop and release duplex streams */
void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type)
{
	struct line6_pcm_stream *pstr;
	int dir;

	mutex_lock(&line6pcm->state_mutex);
	for (dir = 0; dir < 2; dir++)
		line6_stream_stop(line6pcm, dir, type);
	for (dir = 0; dir < 2; dir++) {
		pstr = get_stream(line6pcm, dir);
		line6_buffer_release(line6pcm, pstr, type);
323
	}
324
	mutex_unlock(&line6pcm->state_mutex);
325
}
T
Takashi Iwai 已提交
326
EXPORT_SYMBOL_GPL(line6_pcm_release);
327

328 329 330
/* common PCM hw_params callback */
int snd_line6_hw_params(struct snd_pcm_substream *substream,
			struct snd_pcm_hw_params *hw_params)
M
Markus Grabner 已提交
331
{
332
	int ret;
M
Markus Grabner 已提交
333
	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
334 335 336 337 338 339 340 341 342 343 344 345 346
	struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);

	mutex_lock(&line6pcm->state_mutex);
	ret = line6_buffer_acquire(line6pcm, pstr, LINE6_STREAM_PCM);
	if (ret < 0)
		goto error;

	ret = snd_pcm_lib_malloc_pages(substream,
				       params_buffer_bytes(hw_params));
	if (ret < 0) {
		line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM);
		goto error;
	}
M
Markus Grabner 已提交
347

348 349 350 351 352
	pstr->period = params_period_bytes(hw_params);
 error:
	mutex_unlock(&line6pcm->state_mutex);
	return ret;
}
M
Markus Grabner 已提交
353

354 355 356 357 358
/* common PCM hw_free callback */
int snd_line6_hw_free(struct snd_pcm_substream *substream)
{
	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
	struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
M
Markus Grabner 已提交
359

360 361 362 363
	mutex_lock(&line6pcm->state_mutex);
	line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM);
	mutex_unlock(&line6pcm->state_mutex);
	return snd_pcm_lib_free_pages(substream);
M
Markus Grabner 已提交
364 365
}

366

M
Markus Grabner 已提交
367
/* control info callback */
368 369
static int snd_line6_control_playback_info(struct snd_kcontrol *kcontrol,
					   struct snd_ctl_elem_info *uinfo)
370
{
M
Markus Grabner 已提交
371 372 373 374 375 376 377 378
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = 2;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = 256;
	return 0;
}

/* control get callback */
379 380
static int snd_line6_control_playback_get(struct snd_kcontrol *kcontrol,
					  struct snd_ctl_elem_value *ucontrol)
381
{
M
Markus Grabner 已提交
382 383 384
	int i;
	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);

T
Takashi Iwai 已提交
385
	for (i = 0; i < 2; i++)
386
		ucontrol->value.integer.value[i] = line6pcm->volume_playback[i];
M
Markus Grabner 已提交
387 388 389 390 391

	return 0;
}

/* control put callback */
392 393
static int snd_line6_control_playback_put(struct snd_kcontrol *kcontrol,
					  struct snd_ctl_elem_value *ucontrol)
394
{
M
Markus Grabner 已提交
395 396 397
	int i, changed = 0;
	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);

T
Takashi Iwai 已提交
398
	for (i = 0; i < 2; i++)
399 400 401 402
		if (line6pcm->volume_playback[i] !=
		    ucontrol->value.integer.value[i]) {
			line6pcm->volume_playback[i] =
			    ucontrol->value.integer.value[i];
M
Markus Grabner 已提交
403 404 405 406 407 408 409
			changed = 1;
		}

	return changed;
}

/* control definition */
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
static struct snd_kcontrol_new line6_controls[] = {
	{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "PCM Playback Volume",
		.info = snd_line6_control_playback_info,
		.get = snd_line6_control_playback_get,
		.put = snd_line6_control_playback_put
	},
	{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "Impulse Response Volume",
		.info = snd_line6_impulse_volume_info,
		.get = snd_line6_impulse_volume_get,
		.put = snd_line6_impulse_volume_put
	},
	{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "Impulse Response Period",
		.info = snd_line6_impulse_period_info,
		.get = snd_line6_impulse_period_get,
		.put = snd_line6_impulse_period_put
	},
M
Markus Grabner 已提交
432 433 434 435 436
};

/*
	Cleanup the PCM device.
*/
437
static void cleanup_urbs(struct line6_pcm_stream *pcms)
M
Markus Grabner 已提交
438 439 440
{
	int i;

T
Takashi Iwai 已提交
441
	for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
442 443 444
		if (pcms->urbs[i]) {
			usb_kill_urb(pcms->urbs[i]);
			usb_free_urb(pcms->urbs[i]);
M
Markus Grabner 已提交
445 446
		}
	}
447 448 449 450 451 452 453 454
}

static void line6_cleanup_pcm(struct snd_pcm *pcm)
{
	struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm);

	cleanup_urbs(&line6pcm->out);
	cleanup_urbs(&line6pcm->in);
455
	kfree(line6pcm);
M
Markus Grabner 已提交
456 457 458
}

/* create a PCM device */
459
static int snd_line6_new_pcm(struct usb_line6 *line6, struct snd_pcm **pcm_ret)
M
Markus Grabner 已提交
460 461 462 463
{
	struct snd_pcm *pcm;
	int err;

464 465
	err = snd_pcm_new(line6->card, (char *)line6->properties->name,
			  0, 1, 1, pcm_ret);
466
	if (err < 0)
M
Markus Grabner 已提交
467
		return err;
468 469
	pcm = *pcm_ret;
	strcpy(pcm->name, line6->properties->name);
M
Markus Grabner 已提交
470 471

	/* set operators */
472 473
	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
			&snd_line6_playback_ops);
474
	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_line6_capture_ops);
M
Markus Grabner 已提交
475 476

	/* pre-allocation of buffers */
477
	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
478 479 480
					      snd_dma_continuous_data
					      (GFP_KERNEL), 64 * 1024,
					      128 * 1024);
M
Markus Grabner 已提交
481 482 483
	return 0;
}

484
/*
485
	Sync with PCM stream stops.
486 487 488
*/
void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm)
{
489 490 491 492
	line6_unlink_audio_urbs(line6pcm, &line6pcm->out);
	line6_unlink_audio_urbs(line6pcm, &line6pcm->in);
	line6_wait_clear_audio_urbs(line6pcm, &line6pcm->out);
	line6_wait_clear_audio_urbs(line6pcm, &line6pcm->in);
493 494
}

M
Markus Grabner 已提交
495 496 497 498
/*
	Create and register the PCM device and mixer entries.
	Create URBs for playback and capture.
*/
499 500
int line6_init_pcm(struct usb_line6 *line6,
		   struct line6_pcm_properties *properties)
M
Markus Grabner 已提交
501
{
502
	int i, err;
503 504
	unsigned ep_read = line6->properties->ep_audio_r;
	unsigned ep_write = line6->properties->ep_audio_w;
505
	struct snd_pcm *pcm;
M
Markus Grabner 已提交
506 507
	struct snd_line6_pcm *line6pcm;

508
	if (!(line6->properties->capabilities & LINE6_CAP_PCM))
509
		return 0;	/* skip PCM initialization and report success */
M
Markus Grabner 已提交
510

511 512 513
	err = snd_line6_new_pcm(line6, &pcm);
	if (err < 0)
		return err;
M
Markus Grabner 已提交
514

515 516
	line6pcm = kzalloc(sizeof(*line6pcm), GFP_KERNEL);
	if (!line6pcm)
M
Markus Grabner 已提交
517 518
		return -ENOMEM;

519
	mutex_init(&line6pcm->state_mutex);
520 521
	line6pcm->pcm = pcm;
	line6pcm->properties = properties;
522 523
	line6pcm->volume_playback[0] = line6pcm->volume_playback[1] = 255;
	line6pcm->volume_monitor = 255;
M
Markus Grabner 已提交
524
	line6pcm->line6 = line6;
525 526 527 528 529 530 531 532

	/* Read and write buffers are sized identically, so choose minimum */
	line6pcm->max_packet_size = min(
			usb_maxpacket(line6->usbdev,
				usb_rcvisocpipe(line6->usbdev, ep_read), 0),
			usb_maxpacket(line6->usbdev,
				usb_sndisocpipe(line6->usbdev, ep_write), 1));

533 534
	spin_lock_init(&line6pcm->out.lock);
	spin_lock_init(&line6pcm->in.lock);
535
	line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD;
M
Markus Grabner 已提交
536

537 538 539 540 541
	line6->line6pcm = line6pcm;

	pcm->private_data = line6pcm;
	pcm->private_free = line6_cleanup_pcm;

542
	err = line6_create_audio_out_urbs(line6pcm);
543
	if (err < 0)
M
Markus Grabner 已提交
544 545
		return err;

546
	err = line6_create_audio_in_urbs(line6pcm);
547
	if (err < 0)
M
Markus Grabner 已提交
548 549 550
		return err;

	/* mixer: */
551 552 553 554 555 556
	for (i = 0; i < ARRAY_SIZE(line6_controls); i++) {
		err = snd_ctl_add(line6->card,
				  snd_ctl_new1(&line6_controls[i], line6pcm));
		if (err < 0)
			return err;
	}
557

M
Markus Grabner 已提交
558 559
	return 0;
}
T
Takashi Iwai 已提交
560
EXPORT_SYMBOL_GPL(line6_init_pcm);
M
Markus Grabner 已提交
561 562 563 564 565

/* prepare pcm callback */
int snd_line6_prepare(struct snd_pcm_substream *substream)
{
	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
566
	struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
M
Markus Grabner 已提交
567

568 569 570
	mutex_lock(&line6pcm->state_mutex);
	if (!pstr->running)
		line6_wait_clear_audio_urbs(line6pcm, pstr);
571

572
	if (!test_and_set_bit(LINE6_FLAG_PREPARED, &line6pcm->flags)) {
573 574 575 576 577 578 579
		line6pcm->out.count = 0;
		line6pcm->out.pos = 0;
		line6pcm->out.pos_done = 0;
		line6pcm->out.bytes = 0;
		line6pcm->in.count = 0;
		line6pcm->in.pos_done = 0;
		line6pcm->in.bytes = 0;
M
Markus Grabner 已提交
580 581
	}

582
	mutex_unlock(&line6pcm->state_mutex);
M
Markus Grabner 已提交
583 584
	return 0;
}