blob: 470fc1049d54e36180a302188c6d71f6b87bea33 [file] [log] [blame]
Markus Grabner705ecec2009-02-27 19:43:04 -08001/*
Chris Rorvickc078a4a2015-01-20 02:20:50 -06002 * Line 6 Linux USB driver
Markus Grabner705ecec2009-02-27 19:43:04 -08003 *
Markus Grabner1027f4762010-08-12 01:35:30 +02004 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
Markus Grabner705ecec2009-02-27 19:43:04 -08005 *
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
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090012#include <linux/slab.h>
Takashi Iwaiccddbe42015-01-15 08:22:31 +010013#include <linux/export.h>
Markus Grabner705ecec2009-02-27 19:43:04 -080014#include <sound/core.h>
15#include <sound/control.h>
16#include <sound/pcm.h>
17#include <sound/pcm_params.h>
18
Markus Grabner705ecec2009-02-27 19:43:04 -080019#include "capture.h"
Markus Grabner1027f4762010-08-12 01:35:30 +020020#include "driver.h"
Markus Grabner705ecec2009-02-27 19:43:04 -080021#include "playback.h"
Markus Grabner705ecec2009-02-27 19:43:04 -080022
Takashi Iwai075587b2015-01-19 14:28:25 +010023/* impulse response volume controls */
24static int snd_line6_impulse_volume_info(struct snd_kcontrol *kcontrol,
25 struct snd_ctl_elem_info *uinfo)
Markus Grabner1027f4762010-08-12 01:35:30 +020026{
Takashi Iwai075587b2015-01-19 14:28:25 +010027 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
28 uinfo->count = 1;
29 uinfo->value.integer.min = 0;
30 uinfo->value.integer.max = 255;
31 return 0;
Markus Grabner1027f4762010-08-12 01:35:30 +020032}
33
Takashi Iwai075587b2015-01-19 14:28:25 +010034static int snd_line6_impulse_volume_get(struct snd_kcontrol *kcontrol,
35 struct snd_ctl_elem_value *ucontrol)
Markus Grabner1027f4762010-08-12 01:35:30 +020036{
Takashi Iwai075587b2015-01-19 14:28:25 +010037 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
38
39 ucontrol->value.integer.value[0] = line6pcm->impulse_volume;
40 return 0;
Markus Grabner1027f4762010-08-12 01:35:30 +020041}
42
Takashi Iwai075587b2015-01-19 14:28:25 +010043static int snd_line6_impulse_volume_put(struct snd_kcontrol *kcontrol,
44 struct snd_ctl_elem_value *ucontrol)
Markus Grabner1027f4762010-08-12 01:35:30 +020045{
Takashi Iwai075587b2015-01-19 14:28:25 +010046 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
47 int value = ucontrol->value.integer.value[0];
Johannes Thumshirncdf5e552012-08-06 14:08:50 +020048
Takashi Iwai075587b2015-01-19 14:28:25 +010049 if (line6pcm->impulse_volume == value)
50 return 0;
Johannes Thumshirncdf5e552012-08-06 14:08:50 +020051
Markus Grabner1027f4762010-08-12 01:35:30 +020052 line6pcm->impulse_volume = value;
Markus Grabnere1a164d2010-08-23 01:08:25 +020053 if (value > 0)
Takashi Iwai63e20df2015-01-27 15:24:09 +010054 line6_pcm_acquire(line6pcm, LINE6_STREAM_IMPULSE);
Markus Grabner1027f4762010-08-12 01:35:30 +020055 else
Takashi Iwai63e20df2015-01-27 15:24:09 +010056 line6_pcm_release(line6pcm, LINE6_STREAM_IMPULSE);
Takashi Iwai075587b2015-01-19 14:28:25 +010057 return 1;
Markus Grabner1027f4762010-08-12 01:35:30 +020058}
59
Takashi Iwai075587b2015-01-19 14:28:25 +010060/* impulse response period controls */
61static int snd_line6_impulse_period_info(struct snd_kcontrol *kcontrol,
62 struct snd_ctl_elem_info *uinfo)
Markus Grabner1027f4762010-08-12 01:35:30 +020063{
Takashi Iwai075587b2015-01-19 14:28:25 +010064 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
65 uinfo->count = 1;
66 uinfo->value.integer.min = 0;
67 uinfo->value.integer.max = 2000;
68 return 0;
Markus Grabner1027f4762010-08-12 01:35:30 +020069}
70
Takashi Iwai075587b2015-01-19 14:28:25 +010071static int snd_line6_impulse_period_get(struct snd_kcontrol *kcontrol,
72 struct snd_ctl_elem_value *ucontrol)
Markus Grabner1027f4762010-08-12 01:35:30 +020073{
Takashi Iwai075587b2015-01-19 14:28:25 +010074 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
Laurent Naveta3762902012-11-30 11:57:32 +010075
Takashi Iwai075587b2015-01-19 14:28:25 +010076 ucontrol->value.integer.value[0] = line6pcm->impulse_period;
77 return 0;
Markus Grabner1027f4762010-08-12 01:35:30 +020078}
Markus Grabner1027f4762010-08-12 01:35:30 +020079
Takashi Iwai075587b2015-01-19 14:28:25 +010080static int snd_line6_impulse_period_put(struct snd_kcontrol *kcontrol,
81 struct snd_ctl_elem_value *ucontrol)
82{
83 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
84 int value = ucontrol->value.integer.value[0];
85
86 if (line6pcm->impulse_period == value)
87 return 0;
88
89 line6pcm->impulse_period = value;
90 return 1;
91}
Markus Grabner1027f4762010-08-12 01:35:30 +020092
Takashi Iwaid8131e62015-01-23 16:18:42 +010093/*
94 Unlink all currently active URBs.
95*/
96static void line6_unlink_audio_urbs(struct snd_line6_pcm *line6pcm,
97 struct line6_pcm_stream *pcms)
98{
99 int i;
100
101 for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
102 if (test_bit(i, &pcms->active_urbs)) {
103 if (!test_and_set_bit(i, &pcms->unlink_urbs))
104 usb_unlink_urb(pcms->urbs[i]);
105 }
106 }
107}
108
109/*
110 Wait until unlinking of all currently active URBs has been finished.
111*/
112static void line6_wait_clear_audio_urbs(struct snd_line6_pcm *line6pcm,
113 struct line6_pcm_stream *pcms)
114{
115 int timeout = HZ;
116 int i;
117 int alive;
118
119 do {
120 alive = 0;
121 for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
122 if (test_bit(i, &pcms->active_urbs))
123 alive++;
124 }
125 if (!alive)
126 break;
127 set_current_state(TASK_UNINTERRUPTIBLE);
128 schedule_timeout(1);
129 } while (--timeout > 0);
130 if (alive)
Takashi Iwaiccaac9e2015-01-23 16:20:50 +0100131 dev_err(line6pcm->line6->ifcdev,
132 "timeout: still %d active urbs..\n", alive);
Takashi Iwaid8131e62015-01-23 16:18:42 +0100133}
134
Takashi Iwai63e20df2015-01-27 15:24:09 +0100135static inline struct line6_pcm_stream *
136get_stream(struct snd_line6_pcm *line6pcm, int direction)
137{
138 return (direction == SNDRV_PCM_STREAM_PLAYBACK) ?
139 &line6pcm->out : &line6pcm->in;
140}
141
142/* allocate a buffer if not opened yet;
143 * call this in line6pcm.state_change mutex
144 */
145static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm,
146 struct line6_pcm_stream *pstr, int type)
Takashi Iwaie90576c2015-01-23 16:25:03 +0100147{
148 /* Invoked multiple times in a row so allocate once only */
Takashi Iwai63e20df2015-01-27 15:24:09 +0100149 if (!test_and_set_bit(type, &pstr->opened) && !pstr->buffer) {
150 pstr->buffer = kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
151 line6pcm->max_packet_size, GFP_KERNEL);
152 if (!pstr->buffer)
153 return -ENOMEM;
154 }
Takashi Iwaie90576c2015-01-23 16:25:03 +0100155 return 0;
156}
157
Takashi Iwai63e20df2015-01-27 15:24:09 +0100158/* free a buffer if all streams are closed;
159 * call this in line6pcm.state_change mutex
160 */
161static void line6_buffer_release(struct snd_line6_pcm *line6pcm,
162 struct line6_pcm_stream *pstr, int type)
Takashi Iwaie90576c2015-01-23 16:25:03 +0100163{
Takashi Iwaie90576c2015-01-23 16:25:03 +0100164
Takashi Iwai63e20df2015-01-27 15:24:09 +0100165 clear_bit(type, &pstr->opened);
166 if (!pstr->opened) {
167 line6_wait_clear_audio_urbs(line6pcm, pstr);
168 kfree(pstr->buffer);
169 pstr->buffer = NULL;
Markus Grabner0ca54882012-01-20 00:09:09 +0100170 }
Takashi Iwai63e20df2015-01-27 15:24:09 +0100171}
Markus Grabner0ca54882012-01-20 00:09:09 +0100172
Takashi Iwai63e20df2015-01-27 15:24:09 +0100173/* start a PCM stream */
174static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction,
175 int type)
176{
177 unsigned long flags;
178 struct line6_pcm_stream *pstr = get_stream(line6pcm, direction);
179 int ret = 0;
180
181 spin_lock_irqsave(&pstr->lock, flags);
182 if (!test_and_set_bit(type, &pstr->running)) {
183 if (pstr->active_urbs || pstr->unlink_urbs) {
184 ret = -EBUSY;
185 goto error;
Markus Grabner6b02a17e2011-12-10 02:12:32 +0100186 }
187
Takashi Iwai63e20df2015-01-27 15:24:09 +0100188 pstr->count = 0;
189 /* Submit all currently available URBs */
190 if (direction == SNDRV_PCM_STREAM_PLAYBACK)
191 ret = line6_submit_audio_out_all_urbs(line6pcm);
192 else
193 ret = line6_submit_audio_in_all_urbs(line6pcm);
Markus Grabner1027f4762010-08-12 01:35:30 +0200194 }
Takashi Iwai63e20df2015-01-27 15:24:09 +0100195 error:
196 if (ret < 0)
197 clear_bit(type, &pstr->running);
198 spin_unlock_irqrestore(&pstr->lock, flags);
199 return ret;
Markus Grabner1027f4762010-08-12 01:35:30 +0200200}
201
Takashi Iwai63e20df2015-01-27 15:24:09 +0100202/* stop a PCM stream; this doesn't sync with the unlinked URBs */
203static void line6_stream_stop(struct snd_line6_pcm *line6pcm, int direction,
204 int type)
Markus Grabner1027f4762010-08-12 01:35:30 +0200205{
Takashi Iwai63e20df2015-01-27 15:24:09 +0100206 unsigned long flags;
207 struct line6_pcm_stream *pstr = get_stream(line6pcm, direction);
Arnd Bergmann9f613602013-06-21 21:55:35 +0200208
Takashi Iwai63e20df2015-01-27 15:24:09 +0100209 spin_lock_irqsave(&pstr->lock, flags);
210 clear_bit(type, &pstr->running);
211 if (!pstr->running) {
212 line6_unlink_audio_urbs(line6pcm, pstr);
213 if (direction == SNDRV_PCM_STREAM_CAPTURE) {
214 line6pcm->prev_fbuf = NULL;
215 line6pcm->prev_fsize = 0;
216 }
Takashi Iwaif2bb6142015-01-27 16:17:26 +0100217 }
Takashi Iwai63e20df2015-01-27 15:24:09 +0100218 spin_unlock_irqrestore(&pstr->lock, flags);
Markus Grabner1027f4762010-08-12 01:35:30 +0200219}
220
Takashi Iwai63e20df2015-01-27 15:24:09 +0100221/* common PCM trigger callback */
Markus Grabner705ecec2009-02-27 19:43:04 -0800222int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
223{
224 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
Markus Grabner705ecec2009-02-27 19:43:04 -0800225 struct snd_pcm_substream *s;
Takashi Iwai63e20df2015-01-27 15:24:09 +0100226 int err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800227
Takashi Iwai63e20df2015-01-27 15:24:09 +0100228 clear_bit(LINE6_FLAG_PREPARED, &line6pcm->flags);
Markus Grabner705ecec2009-02-27 19:43:04 -0800229
Markus Grabner705ecec2009-02-27 19:43:04 -0800230 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai7d70c812015-01-19 15:11:17 +0100231 if (s->pcm->card != substream->pcm->card)
232 continue;
Takashi Iwai63e20df2015-01-27 15:24:09 +0100233
234 switch (cmd) {
235 case SNDRV_PCM_TRIGGER_START:
236 case SNDRV_PCM_TRIGGER_RESUME:
237 err = line6_stream_start(line6pcm, s->stream,
238 LINE6_STREAM_PCM);
239 if (err < 0)
240 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800241 break;
242
Takashi Iwai63e20df2015-01-27 15:24:09 +0100243 case SNDRV_PCM_TRIGGER_STOP:
244 case SNDRV_PCM_TRIGGER_SUSPEND:
245 line6_stream_stop(line6pcm, s->stream,
246 LINE6_STREAM_PCM);
247 break;
248
249 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
250 if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
251 return -EINVAL;
252 set_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags);
253 break;
254
255 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
256 if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
257 return -EINVAL;
258 clear_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags);
Markus Grabner705ecec2009-02-27 19:43:04 -0800259 break;
260
261 default:
Takashi Iwai63e20df2015-01-27 15:24:09 +0100262 return -EINVAL;
Markus Grabner705ecec2009-02-27 19:43:04 -0800263 }
264 }
265
Takashi Iwai63e20df2015-01-27 15:24:09 +0100266 return 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800267}
268
Takashi Iwai63e20df2015-01-27 15:24:09 +0100269/* Acquire and start duplex streams:
270 * type is either LINE6_STREAM_IMPULSE or LINE6_STREAM_MONITOR
271 */
272int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type)
273{
274 struct line6_pcm_stream *pstr;
275 int ret = 0, dir;
276
277 mutex_lock(&line6pcm->state_mutex);
278 for (dir = 0; dir < 2; dir++) {
279 pstr = get_stream(line6pcm, dir);
280 ret = line6_buffer_acquire(line6pcm, pstr, type);
281 if (ret < 0)
282 goto error;
283 if (!pstr->running)
284 line6_wait_clear_audio_urbs(line6pcm, pstr);
285 }
286 for (dir = 0; dir < 2; dir++) {
287 ret = line6_stream_start(line6pcm, dir, type);
288 if (ret < 0)
289 goto error;
290 }
291 error:
292 mutex_unlock(&line6pcm->state_mutex);
293 if (ret < 0)
294 line6_pcm_release(line6pcm, type);
295 return ret;
296}
297EXPORT_SYMBOL_GPL(line6_pcm_acquire);
298
299/* Stop and release duplex streams */
300void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type)
301{
302 struct line6_pcm_stream *pstr;
303 int dir;
304
305 mutex_lock(&line6pcm->state_mutex);
306 for (dir = 0; dir < 2; dir++)
307 line6_stream_stop(line6pcm, dir, type);
308 for (dir = 0; dir < 2; dir++) {
309 pstr = get_stream(line6pcm, dir);
310 line6_buffer_release(line6pcm, pstr, type);
311 }
312 mutex_unlock(&line6pcm->state_mutex);
313}
314EXPORT_SYMBOL_GPL(line6_pcm_release);
315
316/* common PCM hw_params callback */
317int snd_line6_hw_params(struct snd_pcm_substream *substream,
318 struct snd_pcm_hw_params *hw_params)
319{
320 int ret;
321 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
322 struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
323
324 mutex_lock(&line6pcm->state_mutex);
325 ret = line6_buffer_acquire(line6pcm, pstr, LINE6_STREAM_PCM);
326 if (ret < 0)
327 goto error;
328
329 ret = snd_pcm_lib_malloc_pages(substream,
330 params_buffer_bytes(hw_params));
331 if (ret < 0) {
332 line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM);
333 goto error;
334 }
335
336 pstr->period = params_period_bytes(hw_params);
337 error:
338 mutex_unlock(&line6pcm->state_mutex);
339 return ret;
340}
341
342/* common PCM hw_free callback */
343int snd_line6_hw_free(struct snd_pcm_substream *substream)
344{
345 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
346 struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
347
348 mutex_lock(&line6pcm->state_mutex);
349 line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM);
350 mutex_unlock(&line6pcm->state_mutex);
351 return snd_pcm_lib_free_pages(substream);
352}
353
354
Markus Grabner705ecec2009-02-27 19:43:04 -0800355/* control info callback */
Markus Grabner1027f4762010-08-12 01:35:30 +0200356static int snd_line6_control_playback_info(struct snd_kcontrol *kcontrol,
357 struct snd_ctl_elem_info *uinfo)
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800358{
Markus Grabner705ecec2009-02-27 19:43:04 -0800359 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
360 uinfo->count = 2;
361 uinfo->value.integer.min = 0;
362 uinfo->value.integer.max = 256;
363 return 0;
364}
365
366/* control get callback */
Markus Grabner1027f4762010-08-12 01:35:30 +0200367static int snd_line6_control_playback_get(struct snd_kcontrol *kcontrol,
368 struct snd_ctl_elem_value *ucontrol)
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800369{
Markus Grabner705ecec2009-02-27 19:43:04 -0800370 int i;
371 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
372
Takashi Iwai9fb754b2015-01-23 15:08:40 +0100373 for (i = 0; i < 2; i++)
Markus Grabner1027f4762010-08-12 01:35:30 +0200374 ucontrol->value.integer.value[i] = line6pcm->volume_playback[i];
Markus Grabner705ecec2009-02-27 19:43:04 -0800375
376 return 0;
377}
378
379/* control put callback */
Markus Grabner1027f4762010-08-12 01:35:30 +0200380static int snd_line6_control_playback_put(struct snd_kcontrol *kcontrol,
381 struct snd_ctl_elem_value *ucontrol)
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800382{
Markus Grabner705ecec2009-02-27 19:43:04 -0800383 int i, changed = 0;
384 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
385
Takashi Iwai9fb754b2015-01-23 15:08:40 +0100386 for (i = 0; i < 2; i++)
Markus Grabnere1a164d2010-08-23 01:08:25 +0200387 if (line6pcm->volume_playback[i] !=
388 ucontrol->value.integer.value[i]) {
389 line6pcm->volume_playback[i] =
390 ucontrol->value.integer.value[i];
Markus Grabner705ecec2009-02-27 19:43:04 -0800391 changed = 1;
392 }
393
394 return changed;
395}
396
397/* control definition */
Takashi Iwai075587b2015-01-19 14:28:25 +0100398static struct snd_kcontrol_new line6_controls[] = {
399 {
400 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
401 .name = "PCM Playback Volume",
402 .info = snd_line6_control_playback_info,
403 .get = snd_line6_control_playback_get,
404 .put = snd_line6_control_playback_put
405 },
406 {
407 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
408 .name = "Impulse Response Volume",
409 .info = snd_line6_impulse_volume_info,
410 .get = snd_line6_impulse_volume_get,
411 .put = snd_line6_impulse_volume_put
412 },
413 {
414 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
415 .name = "Impulse Response Period",
416 .info = snd_line6_impulse_period_info,
417 .get = snd_line6_impulse_period_get,
418 .put = snd_line6_impulse_period_put
419 },
Markus Grabner705ecec2009-02-27 19:43:04 -0800420};
421
422/*
423 Cleanup the PCM device.
424*/
Takashi Iwaid8131e62015-01-23 16:18:42 +0100425static void cleanup_urbs(struct line6_pcm_stream *pcms)
Markus Grabner705ecec2009-02-27 19:43:04 -0800426{
427 int i;
Markus Grabner705ecec2009-02-27 19:43:04 -0800428
Takashi Iwai9fb754b2015-01-23 15:08:40 +0100429 for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
Takashi Iwaid8131e62015-01-23 16:18:42 +0100430 if (pcms->urbs[i]) {
431 usb_kill_urb(pcms->urbs[i]);
432 usb_free_urb(pcms->urbs[i]);
Markus Grabner705ecec2009-02-27 19:43:04 -0800433 }
434 }
Takashi Iwaid8131e62015-01-23 16:18:42 +0100435}
436
437static void line6_cleanup_pcm(struct snd_pcm *pcm)
438{
439 struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm);
440
441 cleanup_urbs(&line6pcm->out);
442 cleanup_urbs(&line6pcm->in);
Takashi Iwaib45a7c52015-01-19 14:41:57 +0100443 kfree(line6pcm);
Markus Grabner705ecec2009-02-27 19:43:04 -0800444}
445
446/* create a PCM device */
Takashi Iwaib45a7c52015-01-19 14:41:57 +0100447static int snd_line6_new_pcm(struct usb_line6 *line6, struct snd_pcm **pcm_ret)
Markus Grabner705ecec2009-02-27 19:43:04 -0800448{
449 struct snd_pcm *pcm;
450 int err;
451
Takashi Iwaib45a7c52015-01-19 14:41:57 +0100452 err = snd_pcm_new(line6->card, (char *)line6->properties->name,
453 0, 1, 1, pcm_ret);
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800454 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800455 return err;
Takashi Iwaib45a7c52015-01-19 14:41:57 +0100456 pcm = *pcm_ret;
457 strcpy(pcm->name, line6->properties->name);
Markus Grabner705ecec2009-02-27 19:43:04 -0800458
459 /* set operators */
Shawn Bohrerafb90912009-11-15 22:17:57 -0600460 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
461 &snd_line6_playback_ops);
Markus Grabnere1a164d2010-08-23 01:08:25 +0200462 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_line6_capture_ops);
Markus Grabner705ecec2009-02-27 19:43:04 -0800463
464 /* pre-allocation of buffers */
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800465 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
Markus Grabnere1a164d2010-08-23 01:08:25 +0200466 snd_dma_continuous_data
467 (GFP_KERNEL), 64 * 1024,
468 128 * 1024);
Markus Grabner705ecec2009-02-27 19:43:04 -0800469 return 0;
470}
471
472/*
Takashi Iwai5a475312015-01-19 16:15:54 +0100473 Sync with PCM stream stops.
Markus Grabner1027f4762010-08-12 01:35:30 +0200474*/
475void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm)
476{
Takashi Iwaid8131e62015-01-23 16:18:42 +0100477 line6_unlink_audio_urbs(line6pcm, &line6pcm->out);
478 line6_unlink_audio_urbs(line6pcm, &line6pcm->in);
479 line6_wait_clear_audio_urbs(line6pcm, &line6pcm->out);
480 line6_wait_clear_audio_urbs(line6pcm, &line6pcm->in);
Markus Grabner1027f4762010-08-12 01:35:30 +0200481}
482
483/*
Markus Grabner705ecec2009-02-27 19:43:04 -0800484 Create and register the PCM device and mixer entries.
485 Create URBs for playback and capture.
486*/
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800487int line6_init_pcm(struct usb_line6 *line6,
488 struct line6_pcm_properties *properties)
Markus Grabner705ecec2009-02-27 19:43:04 -0800489{
Takashi Iwai075587b2015-01-19 14:28:25 +0100490 int i, err;
Chris Rorvick16d603d2015-01-12 12:42:55 -0800491 unsigned ep_read = line6->properties->ep_audio_r;
492 unsigned ep_write = line6->properties->ep_audio_w;
Takashi Iwaib45a7c52015-01-19 14:41:57 +0100493 struct snd_pcm *pcm;
Markus Grabner705ecec2009-02-27 19:43:04 -0800494 struct snd_line6_pcm *line6pcm;
495
Chris Rorvick4cb1a4a2015-01-12 12:42:45 -0800496 if (!(line6->properties->capabilities & LINE6_CAP_PCM))
Markus Grabnere1a164d2010-08-23 01:08:25 +0200497 return 0; /* skip PCM initialization and report success */
Markus Grabner705ecec2009-02-27 19:43:04 -0800498
Takashi Iwaib45a7c52015-01-19 14:41:57 +0100499 err = snd_line6_new_pcm(line6, &pcm);
500 if (err < 0)
501 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800502
Takashi Iwaib45a7c52015-01-19 14:41:57 +0100503 line6pcm = kzalloc(sizeof(*line6pcm), GFP_KERNEL);
504 if (!line6pcm)
Markus Grabner705ecec2009-02-27 19:43:04 -0800505 return -ENOMEM;
506
Takashi Iwai63e20df2015-01-27 15:24:09 +0100507 mutex_init(&line6pcm->state_mutex);
Takashi Iwaib45a7c52015-01-19 14:41:57 +0100508 line6pcm->pcm = pcm;
509 line6pcm->properties = properties;
Markus Grabner1027f4762010-08-12 01:35:30 +0200510 line6pcm->volume_playback[0] = line6pcm->volume_playback[1] = 255;
511 line6pcm->volume_monitor = 255;
Markus Grabner705ecec2009-02-27 19:43:04 -0800512 line6pcm->line6 = line6;
Stefan Hajnoczi3b08db32011-11-23 08:20:44 +0000513
514 /* Read and write buffers are sized identically, so choose minimum */
515 line6pcm->max_packet_size = min(
516 usb_maxpacket(line6->usbdev,
517 usb_rcvisocpipe(line6->usbdev, ep_read), 0),
518 usb_maxpacket(line6->usbdev,
519 usb_sndisocpipe(line6->usbdev, ep_write), 1));
520
Takashi Iwaiad0119a2015-01-23 16:10:57 +0100521 spin_lock_init(&line6pcm->out.lock);
522 spin_lock_init(&line6pcm->in.lock);
Takashi Iwai075587b2015-01-19 14:28:25 +0100523 line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD;
Markus Grabner705ecec2009-02-27 19:43:04 -0800524
Takashi Iwaib45a7c52015-01-19 14:41:57 +0100525 line6->line6pcm = line6pcm;
526
527 pcm->private_data = line6pcm;
528 pcm->private_free = line6_cleanup_pcm;
529
Markus Grabner1027f4762010-08-12 01:35:30 +0200530 err = line6_create_audio_out_urbs(line6pcm);
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800531 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800532 return err;
533
Markus Grabner1027f4762010-08-12 01:35:30 +0200534 err = line6_create_audio_in_urbs(line6pcm);
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800535 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800536 return err;
537
538 /* mixer: */
Takashi Iwai075587b2015-01-19 14:28:25 +0100539 for (i = 0; i < ARRAY_SIZE(line6_controls); i++) {
540 err = snd_ctl_add(line6->card,
541 snd_ctl_new1(&line6_controls[i], line6pcm));
542 if (err < 0)
543 return err;
544 }
Markus Grabner1027f4762010-08-12 01:35:30 +0200545
Markus Grabner705ecec2009-02-27 19:43:04 -0800546 return 0;
547}
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100548EXPORT_SYMBOL_GPL(line6_init_pcm);
Markus Grabner705ecec2009-02-27 19:43:04 -0800549
550/* prepare pcm callback */
551int snd_line6_prepare(struct snd_pcm_substream *substream)
552{
553 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
Takashi Iwai63e20df2015-01-27 15:24:09 +0100554 struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
Markus Grabner705ecec2009-02-27 19:43:04 -0800555
Takashi Iwai63e20df2015-01-27 15:24:09 +0100556 mutex_lock(&line6pcm->state_mutex);
557 if (!pstr->running)
558 line6_wait_clear_audio_urbs(line6pcm, pstr);
Stefan Hajnoczi665f3f52011-12-10 02:12:31 +0100559
Takashi Iwai63e20df2015-01-27 15:24:09 +0100560 if (!test_and_set_bit(LINE6_FLAG_PREPARED, &line6pcm->flags)) {
Takashi Iwaiad0119a2015-01-23 16:10:57 +0100561 line6pcm->out.count = 0;
562 line6pcm->out.pos = 0;
563 line6pcm->out.pos_done = 0;
564 line6pcm->out.bytes = 0;
565 line6pcm->in.count = 0;
566 line6pcm->in.pos_done = 0;
567 line6pcm->in.bytes = 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800568 }
569
Takashi Iwai63e20df2015-01-27 15:24:09 +0100570 mutex_unlock(&line6pcm->state_mutex);
Markus Grabner705ecec2009-02-27 19:43:04 -0800571 return 0;
572}