1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Line 6 Linux USB driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <linux/slab.h>
9*4882a593Smuzhiyun #include <linux/export.h>
10*4882a593Smuzhiyun #include <sound/core.h>
11*4882a593Smuzhiyun #include <sound/control.h>
12*4882a593Smuzhiyun #include <sound/pcm.h>
13*4882a593Smuzhiyun #include <sound/pcm_params.h>
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #include "capture.h"
16*4882a593Smuzhiyun #include "driver.h"
17*4882a593Smuzhiyun #include "playback.h"
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun /* impulse response volume controls */
snd_line6_impulse_volume_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)20*4882a593Smuzhiyun static int snd_line6_impulse_volume_info(struct snd_kcontrol *kcontrol,
21*4882a593Smuzhiyun struct snd_ctl_elem_info *uinfo)
22*4882a593Smuzhiyun {
23*4882a593Smuzhiyun uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
24*4882a593Smuzhiyun uinfo->count = 1;
25*4882a593Smuzhiyun uinfo->value.integer.min = 0;
26*4882a593Smuzhiyun uinfo->value.integer.max = 255;
27*4882a593Smuzhiyun return 0;
28*4882a593Smuzhiyun }
29*4882a593Smuzhiyun
snd_line6_impulse_volume_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)30*4882a593Smuzhiyun static int snd_line6_impulse_volume_get(struct snd_kcontrol *kcontrol,
31*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun ucontrol->value.integer.value[0] = line6pcm->impulse_volume;
36*4882a593Smuzhiyun return 0;
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun
snd_line6_impulse_volume_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)39*4882a593Smuzhiyun static int snd_line6_impulse_volume_put(struct snd_kcontrol *kcontrol,
40*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
43*4882a593Smuzhiyun int value = ucontrol->value.integer.value[0];
44*4882a593Smuzhiyun int err;
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun if (line6pcm->impulse_volume == value)
47*4882a593Smuzhiyun return 0;
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun line6pcm->impulse_volume = value;
50*4882a593Smuzhiyun if (value > 0) {
51*4882a593Smuzhiyun err = line6_pcm_acquire(line6pcm, LINE6_STREAM_IMPULSE, true);
52*4882a593Smuzhiyun if (err < 0) {
53*4882a593Smuzhiyun line6pcm->impulse_volume = 0;
54*4882a593Smuzhiyun return err;
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun } else {
57*4882a593Smuzhiyun line6_pcm_release(line6pcm, LINE6_STREAM_IMPULSE);
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun return 1;
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun /* impulse response period controls */
snd_line6_impulse_period_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)63*4882a593Smuzhiyun static int snd_line6_impulse_period_info(struct snd_kcontrol *kcontrol,
64*4882a593Smuzhiyun struct snd_ctl_elem_info *uinfo)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
67*4882a593Smuzhiyun uinfo->count = 1;
68*4882a593Smuzhiyun uinfo->value.integer.min = 0;
69*4882a593Smuzhiyun uinfo->value.integer.max = 2000;
70*4882a593Smuzhiyun return 0;
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun
snd_line6_impulse_period_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)73*4882a593Smuzhiyun static int snd_line6_impulse_period_get(struct snd_kcontrol *kcontrol,
74*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun ucontrol->value.integer.value[0] = line6pcm->impulse_period;
79*4882a593Smuzhiyun return 0;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun
snd_line6_impulse_period_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)82*4882a593Smuzhiyun static int snd_line6_impulse_period_put(struct snd_kcontrol *kcontrol,
83*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
86*4882a593Smuzhiyun int value = ucontrol->value.integer.value[0];
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun if (line6pcm->impulse_period == value)
89*4882a593Smuzhiyun return 0;
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun line6pcm->impulse_period = value;
92*4882a593Smuzhiyun return 1;
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun /*
96*4882a593Smuzhiyun Unlink all currently active URBs.
97*4882a593Smuzhiyun */
line6_unlink_audio_urbs(struct snd_line6_pcm * line6pcm,struct line6_pcm_stream * pcms)98*4882a593Smuzhiyun static void line6_unlink_audio_urbs(struct snd_line6_pcm *line6pcm,
99*4882a593Smuzhiyun struct line6_pcm_stream *pcms)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun int i;
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun for (i = 0; i < line6pcm->line6->iso_buffers; i++) {
104*4882a593Smuzhiyun if (test_bit(i, &pcms->active_urbs)) {
105*4882a593Smuzhiyun if (!test_and_set_bit(i, &pcms->unlink_urbs))
106*4882a593Smuzhiyun usb_unlink_urb(pcms->urbs[i]);
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun /*
112*4882a593Smuzhiyun Wait until unlinking of all currently active URBs has been finished.
113*4882a593Smuzhiyun */
line6_wait_clear_audio_urbs(struct snd_line6_pcm * line6pcm,struct line6_pcm_stream * pcms)114*4882a593Smuzhiyun static void line6_wait_clear_audio_urbs(struct snd_line6_pcm *line6pcm,
115*4882a593Smuzhiyun struct line6_pcm_stream *pcms)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun int timeout = HZ;
118*4882a593Smuzhiyun int i;
119*4882a593Smuzhiyun int alive;
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun do {
122*4882a593Smuzhiyun alive = 0;
123*4882a593Smuzhiyun for (i = 0; i < line6pcm->line6->iso_buffers; i++) {
124*4882a593Smuzhiyun if (test_bit(i, &pcms->active_urbs))
125*4882a593Smuzhiyun alive++;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun if (!alive)
128*4882a593Smuzhiyun break;
129*4882a593Smuzhiyun set_current_state(TASK_UNINTERRUPTIBLE);
130*4882a593Smuzhiyun schedule_timeout(1);
131*4882a593Smuzhiyun } while (--timeout > 0);
132*4882a593Smuzhiyun if (alive)
133*4882a593Smuzhiyun dev_err(line6pcm->line6->ifcdev,
134*4882a593Smuzhiyun "timeout: still %d active urbs..\n", alive);
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun static inline struct line6_pcm_stream *
get_stream(struct snd_line6_pcm * line6pcm,int direction)138*4882a593Smuzhiyun get_stream(struct snd_line6_pcm *line6pcm, int direction)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun return (direction == SNDRV_PCM_STREAM_PLAYBACK) ?
141*4882a593Smuzhiyun &line6pcm->out : &line6pcm->in;
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun /* allocate a buffer if not opened yet;
145*4882a593Smuzhiyun * call this in line6pcm.state_mutex
146*4882a593Smuzhiyun */
line6_buffer_acquire(struct snd_line6_pcm * line6pcm,struct line6_pcm_stream * pstr,int direction,int type)147*4882a593Smuzhiyun static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm,
148*4882a593Smuzhiyun struct line6_pcm_stream *pstr, int direction, int type)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun const int pkt_size =
151*4882a593Smuzhiyun (direction == SNDRV_PCM_STREAM_PLAYBACK) ?
152*4882a593Smuzhiyun line6pcm->max_packet_size_out :
153*4882a593Smuzhiyun line6pcm->max_packet_size_in;
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun /* Invoked multiple times in a row so allocate once only */
156*4882a593Smuzhiyun if (!test_and_set_bit(type, &pstr->opened) && !pstr->buffer) {
157*4882a593Smuzhiyun pstr->buffer =
158*4882a593Smuzhiyun kmalloc(array3_size(line6pcm->line6->iso_buffers,
159*4882a593Smuzhiyun LINE6_ISO_PACKETS, pkt_size),
160*4882a593Smuzhiyun GFP_KERNEL);
161*4882a593Smuzhiyun if (!pstr->buffer)
162*4882a593Smuzhiyun return -ENOMEM;
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun return 0;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun /* free a buffer if all streams are closed;
168*4882a593Smuzhiyun * call this in line6pcm.state_mutex
169*4882a593Smuzhiyun */
line6_buffer_release(struct snd_line6_pcm * line6pcm,struct line6_pcm_stream * pstr,int type)170*4882a593Smuzhiyun static void line6_buffer_release(struct snd_line6_pcm *line6pcm,
171*4882a593Smuzhiyun struct line6_pcm_stream *pstr, int type)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun clear_bit(type, &pstr->opened);
174*4882a593Smuzhiyun if (!pstr->opened) {
175*4882a593Smuzhiyun line6_wait_clear_audio_urbs(line6pcm, pstr);
176*4882a593Smuzhiyun kfree(pstr->buffer);
177*4882a593Smuzhiyun pstr->buffer = NULL;
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun /* start a PCM stream */
line6_stream_start(struct snd_line6_pcm * line6pcm,int direction,int type)182*4882a593Smuzhiyun static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction,
183*4882a593Smuzhiyun int type)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun unsigned long flags;
186*4882a593Smuzhiyun struct line6_pcm_stream *pstr = get_stream(line6pcm, direction);
187*4882a593Smuzhiyun int ret = 0;
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun spin_lock_irqsave(&pstr->lock, flags);
190*4882a593Smuzhiyun if (!test_and_set_bit(type, &pstr->running) &&
191*4882a593Smuzhiyun !(pstr->active_urbs || pstr->unlink_urbs)) {
192*4882a593Smuzhiyun pstr->count = 0;
193*4882a593Smuzhiyun /* Submit all currently available URBs */
194*4882a593Smuzhiyun if (direction == SNDRV_PCM_STREAM_PLAYBACK)
195*4882a593Smuzhiyun ret = line6_submit_audio_out_all_urbs(line6pcm);
196*4882a593Smuzhiyun else
197*4882a593Smuzhiyun ret = line6_submit_audio_in_all_urbs(line6pcm);
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun if (ret < 0)
201*4882a593Smuzhiyun clear_bit(type, &pstr->running);
202*4882a593Smuzhiyun spin_unlock_irqrestore(&pstr->lock, flags);
203*4882a593Smuzhiyun return ret;
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun /* stop a PCM stream; this doesn't sync with the unlinked URBs */
line6_stream_stop(struct snd_line6_pcm * line6pcm,int direction,int type)207*4882a593Smuzhiyun static void line6_stream_stop(struct snd_line6_pcm *line6pcm, int direction,
208*4882a593Smuzhiyun int type)
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun unsigned long flags;
211*4882a593Smuzhiyun struct line6_pcm_stream *pstr = get_stream(line6pcm, direction);
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun spin_lock_irqsave(&pstr->lock, flags);
214*4882a593Smuzhiyun clear_bit(type, &pstr->running);
215*4882a593Smuzhiyun if (!pstr->running) {
216*4882a593Smuzhiyun spin_unlock_irqrestore(&pstr->lock, flags);
217*4882a593Smuzhiyun line6_unlink_audio_urbs(line6pcm, pstr);
218*4882a593Smuzhiyun spin_lock_irqsave(&pstr->lock, flags);
219*4882a593Smuzhiyun if (direction == SNDRV_PCM_STREAM_CAPTURE) {
220*4882a593Smuzhiyun line6pcm->prev_fbuf = NULL;
221*4882a593Smuzhiyun line6pcm->prev_fsize = 0;
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun spin_unlock_irqrestore(&pstr->lock, flags);
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun /* common PCM trigger callback */
snd_line6_trigger(struct snd_pcm_substream * substream,int cmd)228*4882a593Smuzhiyun int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
231*4882a593Smuzhiyun struct snd_pcm_substream *s;
232*4882a593Smuzhiyun int err;
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun clear_bit(LINE6_FLAG_PREPARED, &line6pcm->flags);
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun snd_pcm_group_for_each_entry(s, substream) {
237*4882a593Smuzhiyun if (s->pcm->card != substream->pcm->card)
238*4882a593Smuzhiyun continue;
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun switch (cmd) {
241*4882a593Smuzhiyun case SNDRV_PCM_TRIGGER_START:
242*4882a593Smuzhiyun case SNDRV_PCM_TRIGGER_RESUME:
243*4882a593Smuzhiyun if (s->stream == SNDRV_PCM_STREAM_CAPTURE &&
244*4882a593Smuzhiyun (line6pcm->line6->properties->capabilities &
245*4882a593Smuzhiyun LINE6_CAP_IN_NEEDS_OUT)) {
246*4882a593Smuzhiyun err = line6_stream_start(line6pcm, SNDRV_PCM_STREAM_PLAYBACK,
247*4882a593Smuzhiyun LINE6_STREAM_CAPTURE_HELPER);
248*4882a593Smuzhiyun if (err < 0)
249*4882a593Smuzhiyun return err;
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun err = line6_stream_start(line6pcm, s->stream,
252*4882a593Smuzhiyun LINE6_STREAM_PCM);
253*4882a593Smuzhiyun if (err < 0)
254*4882a593Smuzhiyun return err;
255*4882a593Smuzhiyun break;
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun case SNDRV_PCM_TRIGGER_STOP:
258*4882a593Smuzhiyun case SNDRV_PCM_TRIGGER_SUSPEND:
259*4882a593Smuzhiyun if (s->stream == SNDRV_PCM_STREAM_CAPTURE &&
260*4882a593Smuzhiyun (line6pcm->line6->properties->capabilities &
261*4882a593Smuzhiyun LINE6_CAP_IN_NEEDS_OUT)) {
262*4882a593Smuzhiyun line6_stream_stop(line6pcm, SNDRV_PCM_STREAM_PLAYBACK,
263*4882a593Smuzhiyun LINE6_STREAM_CAPTURE_HELPER);
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun line6_stream_stop(line6pcm, s->stream,
266*4882a593Smuzhiyun LINE6_STREAM_PCM);
267*4882a593Smuzhiyun break;
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
270*4882a593Smuzhiyun if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
271*4882a593Smuzhiyun return -EINVAL;
272*4882a593Smuzhiyun set_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags);
273*4882a593Smuzhiyun break;
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
276*4882a593Smuzhiyun if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
277*4882a593Smuzhiyun return -EINVAL;
278*4882a593Smuzhiyun clear_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags);
279*4882a593Smuzhiyun break;
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun default:
282*4882a593Smuzhiyun return -EINVAL;
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun return 0;
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun /* common PCM pointer callback */
snd_line6_pointer(struct snd_pcm_substream * substream)290*4882a593Smuzhiyun snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream)
291*4882a593Smuzhiyun {
292*4882a593Smuzhiyun struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
293*4882a593Smuzhiyun struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun return pstr->pos_done;
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun /* Acquire and optionally start duplex streams:
299*4882a593Smuzhiyun * type is either LINE6_STREAM_IMPULSE or LINE6_STREAM_MONITOR
300*4882a593Smuzhiyun */
line6_pcm_acquire(struct snd_line6_pcm * line6pcm,int type,bool start)301*4882a593Smuzhiyun int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type, bool start)
302*4882a593Smuzhiyun {
303*4882a593Smuzhiyun struct line6_pcm_stream *pstr;
304*4882a593Smuzhiyun int ret = 0, dir;
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun /* TODO: We should assert SNDRV_PCM_STREAM_PLAYBACK/CAPTURE == 0/1 */
307*4882a593Smuzhiyun mutex_lock(&line6pcm->state_mutex);
308*4882a593Smuzhiyun for (dir = 0; dir < 2; dir++) {
309*4882a593Smuzhiyun pstr = get_stream(line6pcm, dir);
310*4882a593Smuzhiyun ret = line6_buffer_acquire(line6pcm, pstr, dir, type);
311*4882a593Smuzhiyun if (ret < 0)
312*4882a593Smuzhiyun goto error;
313*4882a593Smuzhiyun if (!pstr->running)
314*4882a593Smuzhiyun line6_wait_clear_audio_urbs(line6pcm, pstr);
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun if (start) {
317*4882a593Smuzhiyun for (dir = 0; dir < 2; dir++) {
318*4882a593Smuzhiyun ret = line6_stream_start(line6pcm, dir, type);
319*4882a593Smuzhiyun if (ret < 0)
320*4882a593Smuzhiyun goto error;
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun error:
324*4882a593Smuzhiyun mutex_unlock(&line6pcm->state_mutex);
325*4882a593Smuzhiyun if (ret < 0)
326*4882a593Smuzhiyun line6_pcm_release(line6pcm, type);
327*4882a593Smuzhiyun return ret;
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(line6_pcm_acquire);
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun /* Stop and release duplex streams */
line6_pcm_release(struct snd_line6_pcm * line6pcm,int type)332*4882a593Smuzhiyun void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type)
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun struct line6_pcm_stream *pstr;
335*4882a593Smuzhiyun int dir;
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun mutex_lock(&line6pcm->state_mutex);
338*4882a593Smuzhiyun for (dir = 0; dir < 2; dir++)
339*4882a593Smuzhiyun line6_stream_stop(line6pcm, dir, type);
340*4882a593Smuzhiyun for (dir = 0; dir < 2; dir++) {
341*4882a593Smuzhiyun pstr = get_stream(line6pcm, dir);
342*4882a593Smuzhiyun line6_buffer_release(line6pcm, pstr, type);
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun mutex_unlock(&line6pcm->state_mutex);
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(line6_pcm_release);
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun /* common PCM hw_params callback */
snd_line6_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * hw_params)349*4882a593Smuzhiyun int snd_line6_hw_params(struct snd_pcm_substream *substream,
350*4882a593Smuzhiyun struct snd_pcm_hw_params *hw_params)
351*4882a593Smuzhiyun {
352*4882a593Smuzhiyun int ret;
353*4882a593Smuzhiyun struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
354*4882a593Smuzhiyun struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun mutex_lock(&line6pcm->state_mutex);
357*4882a593Smuzhiyun ret = line6_buffer_acquire(line6pcm, pstr, substream->stream,
358*4882a593Smuzhiyun LINE6_STREAM_PCM);
359*4882a593Smuzhiyun if (ret < 0)
360*4882a593Smuzhiyun goto error;
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun pstr->period = params_period_bytes(hw_params);
363*4882a593Smuzhiyun error:
364*4882a593Smuzhiyun mutex_unlock(&line6pcm->state_mutex);
365*4882a593Smuzhiyun return ret;
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun /* common PCM hw_free callback */
snd_line6_hw_free(struct snd_pcm_substream * substream)369*4882a593Smuzhiyun int snd_line6_hw_free(struct snd_pcm_substream *substream)
370*4882a593Smuzhiyun {
371*4882a593Smuzhiyun struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
372*4882a593Smuzhiyun struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun mutex_lock(&line6pcm->state_mutex);
375*4882a593Smuzhiyun line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM);
376*4882a593Smuzhiyun mutex_unlock(&line6pcm->state_mutex);
377*4882a593Smuzhiyun return 0;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun /* control info callback */
snd_line6_control_playback_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)382*4882a593Smuzhiyun static int snd_line6_control_playback_info(struct snd_kcontrol *kcontrol,
383*4882a593Smuzhiyun struct snd_ctl_elem_info *uinfo)
384*4882a593Smuzhiyun {
385*4882a593Smuzhiyun uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
386*4882a593Smuzhiyun uinfo->count = 2;
387*4882a593Smuzhiyun uinfo->value.integer.min = 0;
388*4882a593Smuzhiyun uinfo->value.integer.max = 256;
389*4882a593Smuzhiyun return 0;
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun /* control get callback */
snd_line6_control_playback_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)393*4882a593Smuzhiyun static int snd_line6_control_playback_get(struct snd_kcontrol *kcontrol,
394*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
395*4882a593Smuzhiyun {
396*4882a593Smuzhiyun int i;
397*4882a593Smuzhiyun struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun for (i = 0; i < 2; i++)
400*4882a593Smuzhiyun ucontrol->value.integer.value[i] = line6pcm->volume_playback[i];
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun return 0;
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun /* control put callback */
snd_line6_control_playback_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)406*4882a593Smuzhiyun static int snd_line6_control_playback_put(struct snd_kcontrol *kcontrol,
407*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
408*4882a593Smuzhiyun {
409*4882a593Smuzhiyun int i, changed = 0;
410*4882a593Smuzhiyun struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun for (i = 0; i < 2; i++)
413*4882a593Smuzhiyun if (line6pcm->volume_playback[i] !=
414*4882a593Smuzhiyun ucontrol->value.integer.value[i]) {
415*4882a593Smuzhiyun line6pcm->volume_playback[i] =
416*4882a593Smuzhiyun ucontrol->value.integer.value[i];
417*4882a593Smuzhiyun changed = 1;
418*4882a593Smuzhiyun }
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun return changed;
421*4882a593Smuzhiyun }
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun /* control definition */
424*4882a593Smuzhiyun static const struct snd_kcontrol_new line6_controls[] = {
425*4882a593Smuzhiyun {
426*4882a593Smuzhiyun .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
427*4882a593Smuzhiyun .name = "PCM Playback Volume",
428*4882a593Smuzhiyun .info = snd_line6_control_playback_info,
429*4882a593Smuzhiyun .get = snd_line6_control_playback_get,
430*4882a593Smuzhiyun .put = snd_line6_control_playback_put
431*4882a593Smuzhiyun },
432*4882a593Smuzhiyun {
433*4882a593Smuzhiyun .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
434*4882a593Smuzhiyun .name = "Impulse Response Volume",
435*4882a593Smuzhiyun .info = snd_line6_impulse_volume_info,
436*4882a593Smuzhiyun .get = snd_line6_impulse_volume_get,
437*4882a593Smuzhiyun .put = snd_line6_impulse_volume_put
438*4882a593Smuzhiyun },
439*4882a593Smuzhiyun {
440*4882a593Smuzhiyun .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
441*4882a593Smuzhiyun .name = "Impulse Response Period",
442*4882a593Smuzhiyun .info = snd_line6_impulse_period_info,
443*4882a593Smuzhiyun .get = snd_line6_impulse_period_get,
444*4882a593Smuzhiyun .put = snd_line6_impulse_period_put
445*4882a593Smuzhiyun },
446*4882a593Smuzhiyun };
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun /*
449*4882a593Smuzhiyun Cleanup the PCM device.
450*4882a593Smuzhiyun */
cleanup_urbs(struct line6_pcm_stream * pcms,int iso_buffers)451*4882a593Smuzhiyun static void cleanup_urbs(struct line6_pcm_stream *pcms, int iso_buffers)
452*4882a593Smuzhiyun {
453*4882a593Smuzhiyun int i;
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun /* Most likely impossible in current code... */
456*4882a593Smuzhiyun if (pcms->urbs == NULL)
457*4882a593Smuzhiyun return;
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun for (i = 0; i < iso_buffers; i++) {
460*4882a593Smuzhiyun if (pcms->urbs[i]) {
461*4882a593Smuzhiyun usb_kill_urb(pcms->urbs[i]);
462*4882a593Smuzhiyun usb_free_urb(pcms->urbs[i]);
463*4882a593Smuzhiyun }
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun kfree(pcms->urbs);
466*4882a593Smuzhiyun pcms->urbs = NULL;
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun
line6_cleanup_pcm(struct snd_pcm * pcm)469*4882a593Smuzhiyun static void line6_cleanup_pcm(struct snd_pcm *pcm)
470*4882a593Smuzhiyun {
471*4882a593Smuzhiyun struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm);
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun cleanup_urbs(&line6pcm->out, line6pcm->line6->iso_buffers);
474*4882a593Smuzhiyun cleanup_urbs(&line6pcm->in, line6pcm->line6->iso_buffers);
475*4882a593Smuzhiyun kfree(line6pcm);
476*4882a593Smuzhiyun }
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun /* create a PCM device */
snd_line6_new_pcm(struct usb_line6 * line6,struct snd_pcm ** pcm_ret)479*4882a593Smuzhiyun static int snd_line6_new_pcm(struct usb_line6 *line6, struct snd_pcm **pcm_ret)
480*4882a593Smuzhiyun {
481*4882a593Smuzhiyun struct snd_pcm *pcm;
482*4882a593Smuzhiyun int err;
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun err = snd_pcm_new(line6->card, (char *)line6->properties->name,
485*4882a593Smuzhiyun 0, 1, 1, pcm_ret);
486*4882a593Smuzhiyun if (err < 0)
487*4882a593Smuzhiyun return err;
488*4882a593Smuzhiyun pcm = *pcm_ret;
489*4882a593Smuzhiyun strcpy(pcm->name, line6->properties->name);
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun /* set operators */
492*4882a593Smuzhiyun snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
493*4882a593Smuzhiyun &snd_line6_playback_ops);
494*4882a593Smuzhiyun snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_line6_capture_ops);
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun /* pre-allocation of buffers */
497*4882a593Smuzhiyun snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
498*4882a593Smuzhiyun NULL, 64 * 1024, 128 * 1024);
499*4882a593Smuzhiyun return 0;
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun /*
503*4882a593Smuzhiyun Sync with PCM stream stops.
504*4882a593Smuzhiyun */
line6_pcm_disconnect(struct snd_line6_pcm * line6pcm)505*4882a593Smuzhiyun void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm)
506*4882a593Smuzhiyun {
507*4882a593Smuzhiyun line6_unlink_audio_urbs(line6pcm, &line6pcm->out);
508*4882a593Smuzhiyun line6_unlink_audio_urbs(line6pcm, &line6pcm->in);
509*4882a593Smuzhiyun line6_wait_clear_audio_urbs(line6pcm, &line6pcm->out);
510*4882a593Smuzhiyun line6_wait_clear_audio_urbs(line6pcm, &line6pcm->in);
511*4882a593Smuzhiyun }
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun /*
514*4882a593Smuzhiyun Create and register the PCM device and mixer entries.
515*4882a593Smuzhiyun Create URBs for playback and capture.
516*4882a593Smuzhiyun */
line6_init_pcm(struct usb_line6 * line6,struct line6_pcm_properties * properties)517*4882a593Smuzhiyun int line6_init_pcm(struct usb_line6 *line6,
518*4882a593Smuzhiyun struct line6_pcm_properties *properties)
519*4882a593Smuzhiyun {
520*4882a593Smuzhiyun int i, err;
521*4882a593Smuzhiyun unsigned ep_read = line6->properties->ep_audio_r;
522*4882a593Smuzhiyun unsigned ep_write = line6->properties->ep_audio_w;
523*4882a593Smuzhiyun struct snd_pcm *pcm;
524*4882a593Smuzhiyun struct snd_line6_pcm *line6pcm;
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun if (!(line6->properties->capabilities & LINE6_CAP_PCM))
527*4882a593Smuzhiyun return 0; /* skip PCM initialization and report success */
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun err = snd_line6_new_pcm(line6, &pcm);
530*4882a593Smuzhiyun if (err < 0)
531*4882a593Smuzhiyun return err;
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun line6pcm = kzalloc(sizeof(*line6pcm), GFP_KERNEL);
534*4882a593Smuzhiyun if (!line6pcm)
535*4882a593Smuzhiyun return -ENOMEM;
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun mutex_init(&line6pcm->state_mutex);
538*4882a593Smuzhiyun line6pcm->pcm = pcm;
539*4882a593Smuzhiyun line6pcm->properties = properties;
540*4882a593Smuzhiyun line6pcm->volume_playback[0] = line6pcm->volume_playback[1] = 255;
541*4882a593Smuzhiyun line6pcm->volume_monitor = 255;
542*4882a593Smuzhiyun line6pcm->line6 = line6;
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun spin_lock_init(&line6pcm->out.lock);
545*4882a593Smuzhiyun spin_lock_init(&line6pcm->in.lock);
546*4882a593Smuzhiyun line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD;
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun line6->line6pcm = line6pcm;
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun pcm->private_data = line6pcm;
551*4882a593Smuzhiyun pcm->private_free = line6_cleanup_pcm;
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun line6pcm->max_packet_size_in =
554*4882a593Smuzhiyun usb_maxpacket(line6->usbdev,
555*4882a593Smuzhiyun usb_rcvisocpipe(line6->usbdev, ep_read), 0);
556*4882a593Smuzhiyun line6pcm->max_packet_size_out =
557*4882a593Smuzhiyun usb_maxpacket(line6->usbdev,
558*4882a593Smuzhiyun usb_sndisocpipe(line6->usbdev, ep_write), 1);
559*4882a593Smuzhiyun if (!line6pcm->max_packet_size_in || !line6pcm->max_packet_size_out) {
560*4882a593Smuzhiyun dev_err(line6pcm->line6->ifcdev,
561*4882a593Smuzhiyun "cannot get proper max packet size\n");
562*4882a593Smuzhiyun return -EINVAL;
563*4882a593Smuzhiyun }
564*4882a593Smuzhiyun
565*4882a593Smuzhiyun err = line6_create_audio_out_urbs(line6pcm);
566*4882a593Smuzhiyun if (err < 0)
567*4882a593Smuzhiyun return err;
568*4882a593Smuzhiyun
569*4882a593Smuzhiyun err = line6_create_audio_in_urbs(line6pcm);
570*4882a593Smuzhiyun if (err < 0)
571*4882a593Smuzhiyun return err;
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun /* mixer: */
574*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(line6_controls); i++) {
575*4882a593Smuzhiyun err = snd_ctl_add(line6->card,
576*4882a593Smuzhiyun snd_ctl_new1(&line6_controls[i], line6pcm));
577*4882a593Smuzhiyun if (err < 0)
578*4882a593Smuzhiyun return err;
579*4882a593Smuzhiyun }
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun return 0;
582*4882a593Smuzhiyun }
583*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(line6_init_pcm);
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun /* prepare pcm callback */
snd_line6_prepare(struct snd_pcm_substream * substream)586*4882a593Smuzhiyun int snd_line6_prepare(struct snd_pcm_substream *substream)
587*4882a593Smuzhiyun {
588*4882a593Smuzhiyun struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
589*4882a593Smuzhiyun struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun mutex_lock(&line6pcm->state_mutex);
592*4882a593Smuzhiyun if (!pstr->running)
593*4882a593Smuzhiyun line6_wait_clear_audio_urbs(line6pcm, pstr);
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun if (!test_and_set_bit(LINE6_FLAG_PREPARED, &line6pcm->flags)) {
596*4882a593Smuzhiyun line6pcm->out.count = 0;
597*4882a593Smuzhiyun line6pcm->out.pos = 0;
598*4882a593Smuzhiyun line6pcm->out.pos_done = 0;
599*4882a593Smuzhiyun line6pcm->out.bytes = 0;
600*4882a593Smuzhiyun line6pcm->in.count = 0;
601*4882a593Smuzhiyun line6pcm->in.pos_done = 0;
602*4882a593Smuzhiyun line6pcm->in.bytes = 0;
603*4882a593Smuzhiyun }
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun mutex_unlock(&line6pcm->state_mutex);
606*4882a593Smuzhiyun return 0;
607*4882a593Smuzhiyun }
608