aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/usb/line6/capture.c5
-rw-r--r--sound/usb/line6/driver.h4
-rw-r--r--sound/usb/line6/pcm.c31
-rw-r--r--sound/usb/line6/pcm.h4
-rw-r--r--sound/usb/line6/toneport.c4
5 files changed, 37 insertions, 11 deletions
diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c
index 0228cb4bdfcf..7c812565f90d 100644
--- a/sound/usb/line6/capture.c
+++ b/sound/usb/line6/capture.c
@@ -232,6 +232,8 @@ static int snd_line6_capture_open(struct snd_pcm_substream *substream)
232 if (err < 0) 232 if (err < 0)
233 return err; 233 return err;
234 234
235 line6_pcm_acquire(line6pcm, LINE6_STREAM_CAPTURE_HELPER, false);
236
235 runtime->hw = line6pcm->properties->capture_hw; 237 runtime->hw = line6pcm->properties->capture_hw;
236 return 0; 238 return 0;
237} 239}
@@ -239,6 +241,9 @@ static int snd_line6_capture_open(struct snd_pcm_substream *substream)
239/* close capture callback */ 241/* close capture callback */
240static int snd_line6_capture_close(struct snd_pcm_substream *substream) 242static int snd_line6_capture_close(struct snd_pcm_substream *substream)
241{ 243{
244 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
245
246 line6_pcm_release(line6pcm, LINE6_STREAM_CAPTURE_HELPER);
242 return 0; 247 return 0;
243} 248}
244 249
diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h
index 2d3213912d4c..0bcab38ac10d 100644
--- a/sound/usb/line6/driver.h
+++ b/sound/usb/line6/driver.h
@@ -100,8 +100,10 @@ enum {
100 LINE6_CAP_CONTROL = 1 << 0, 100 LINE6_CAP_CONTROL = 1 << 0,
101 /* device supports PCM input/output via USB */ 101 /* device supports PCM input/output via USB */
102 LINE6_CAP_PCM = 1 << 1, 102 LINE6_CAP_PCM = 1 << 1,
103 /* device support hardware monitoring */ 103 /* device supports hardware monitoring */
104 LINE6_CAP_HWMON = 1 << 2, 104 LINE6_CAP_HWMON = 1 << 2,
105 /* device requires output data when input is read */
106 LINE6_CAP_IN_NEEDS_OUT = 1 << 3,
105}; 107};
106 108
107/* 109/*
diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c
index a5a44309bc9d..fab53f58d447 100644
--- a/sound/usb/line6/pcm.c
+++ b/sound/usb/line6/pcm.c
@@ -52,7 +52,7 @@ static int snd_line6_impulse_volume_put(struct snd_kcontrol *kcontrol,
52 52
53 line6pcm->impulse_volume = value; 53 line6pcm->impulse_volume = value;
54 if (value > 0) { 54 if (value > 0) {
55 err = line6_pcm_acquire(line6pcm, LINE6_STREAM_IMPULSE); 55 err = line6_pcm_acquire(line6pcm, LINE6_STREAM_IMPULSE, true);
56 if (err < 0) { 56 if (err < 0) {
57 line6pcm->impulse_volume = 0; 57 line6pcm->impulse_volume = 0;
58 return err; 58 return err;
@@ -242,6 +242,14 @@ int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
242 switch (cmd) { 242 switch (cmd) {
243 case SNDRV_PCM_TRIGGER_START: 243 case SNDRV_PCM_TRIGGER_START:
244 case SNDRV_PCM_TRIGGER_RESUME: 244 case SNDRV_PCM_TRIGGER_RESUME:
245 if (s->stream == SNDRV_PCM_STREAM_CAPTURE &&
246 (line6pcm->line6->properties->capabilities &
247 LINE6_CAP_IN_NEEDS_OUT)) {
248 err = line6_stream_start(line6pcm, SNDRV_PCM_STREAM_PLAYBACK,
249 LINE6_STREAM_CAPTURE_HELPER);
250 if (err < 0)
251 return err;
252 }
245 err = line6_stream_start(line6pcm, s->stream, 253 err = line6_stream_start(line6pcm, s->stream,
246 LINE6_STREAM_PCM); 254 LINE6_STREAM_PCM);
247 if (err < 0) 255 if (err < 0)
@@ -250,6 +258,12 @@ int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
250 258
251 case SNDRV_PCM_TRIGGER_STOP: 259 case SNDRV_PCM_TRIGGER_STOP:
252 case SNDRV_PCM_TRIGGER_SUSPEND: 260 case SNDRV_PCM_TRIGGER_SUSPEND:
261 if (s->stream == SNDRV_PCM_STREAM_CAPTURE &&
262 (line6pcm->line6->properties->capabilities &
263 LINE6_CAP_IN_NEEDS_OUT)) {
264 line6_stream_stop(line6pcm, SNDRV_PCM_STREAM_PLAYBACK,
265 LINE6_STREAM_CAPTURE_HELPER);
266 }
253 line6_stream_stop(line6pcm, s->stream, 267 line6_stream_stop(line6pcm, s->stream,
254 LINE6_STREAM_PCM); 268 LINE6_STREAM_PCM);
255 break; 269 break;
@@ -283,14 +297,15 @@ snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream)
283 return pstr->pos_done; 297 return pstr->pos_done;
284} 298}
285 299
286/* Acquire and start duplex streams: 300/* Acquire and optionally start duplex streams:
287 * type is either LINE6_STREAM_IMPULSE or LINE6_STREAM_MONITOR 301 * type is either LINE6_STREAM_IMPULSE or LINE6_STREAM_MONITOR
288 */ 302 */
289int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type) 303int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type, bool start)
290{ 304{
291 struct line6_pcm_stream *pstr; 305 struct line6_pcm_stream *pstr;
292 int ret = 0, dir; 306 int ret = 0, dir;
293 307
308 /* TODO: We should assert SNDRV_PCM_STREAM_PLAYBACK/CAPTURE == 0/1 */
294 mutex_lock(&line6pcm->state_mutex); 309 mutex_lock(&line6pcm->state_mutex);
295 for (dir = 0; dir < 2; dir++) { 310 for (dir = 0; dir < 2; dir++) {
296 pstr = get_stream(line6pcm, dir); 311 pstr = get_stream(line6pcm, dir);
@@ -300,10 +315,12 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type)
300 if (!pstr->running) 315 if (!pstr->running)
301 line6_wait_clear_audio_urbs(line6pcm, pstr); 316 line6_wait_clear_audio_urbs(line6pcm, pstr);
302 } 317 }
303 for (dir = 0; dir < 2; dir++) { 318 if (start) {
304 ret = line6_stream_start(line6pcm, dir, type); 319 for (dir = 0; dir < 2; dir++) {
305 if (ret < 0) 320 ret = line6_stream_start(line6pcm, dir, type);
306 goto error; 321 if (ret < 0)
322 goto error;
323 }
307 } 324 }
308 error: 325 error:
309 mutex_unlock(&line6pcm->state_mutex); 326 mutex_unlock(&line6pcm->state_mutex);
diff --git a/sound/usb/line6/pcm.h b/sound/usb/line6/pcm.h
index 67fda315aa89..bb0c9cbf2a78 100644
--- a/sound/usb/line6/pcm.h
+++ b/sound/usb/line6/pcm.h
@@ -73,6 +73,7 @@ enum {
73 LINE6_STREAM_PCM, 73 LINE6_STREAM_PCM,
74 LINE6_STREAM_MONITOR, 74 LINE6_STREAM_MONITOR,
75 LINE6_STREAM_IMPULSE, 75 LINE6_STREAM_IMPULSE,
76 LINE6_STREAM_CAPTURE_HELPER,
76}; 77};
77 78
78/* misc bit flags for PCM operation */ 79/* misc bit flags for PCM operation */
@@ -191,7 +192,8 @@ extern int snd_line6_hw_params(struct snd_pcm_substream *substream,
191extern int snd_line6_hw_free(struct snd_pcm_substream *substream); 192extern int snd_line6_hw_free(struct snd_pcm_substream *substream);
192extern snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream); 193extern snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream);
193extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm); 194extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm);
194extern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type); 195extern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type,
196 bool start);
195extern void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type); 197extern void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type);
196 198
197#endif 199#endif
diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c
index da76e030eefc..8e22f430d700 100644
--- a/sound/usb/line6/toneport.c
+++ b/sound/usb/line6/toneport.c
@@ -177,7 +177,7 @@ static int snd_toneport_monitor_put(struct snd_kcontrol *kcontrol,
177 line6pcm->volume_monitor = ucontrol->value.integer.value[0]; 177 line6pcm->volume_monitor = ucontrol->value.integer.value[0];
178 178
179 if (line6pcm->volume_monitor > 0) { 179 if (line6pcm->volume_monitor > 0) {
180 err = line6_pcm_acquire(line6pcm, LINE6_STREAM_MONITOR); 180 err = line6_pcm_acquire(line6pcm, LINE6_STREAM_MONITOR, true);
181 if (err < 0) { 181 if (err < 0) {
182 line6pcm->volume_monitor = 0; 182 line6pcm->volume_monitor = 0;
183 line6_pcm_release(line6pcm, LINE6_STREAM_MONITOR); 183 line6_pcm_release(line6pcm, LINE6_STREAM_MONITOR);
@@ -246,7 +246,7 @@ static void toneport_start_pcm(unsigned long arg)
246 struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)arg; 246 struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)arg;
247 struct usb_line6 *line6 = &toneport->line6; 247 struct usb_line6 *line6 = &toneport->line6;
248 248
249 line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR); 249 line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR, true);
250} 250}
251 251
252/* control definition */ 252/* control definition */