diff options
| -rw-r--r-- | sound/usb/line6/capture.c | 5 | ||||
| -rw-r--r-- | sound/usb/line6/driver.h | 4 | ||||
| -rw-r--r-- | sound/usb/line6/pcm.c | 31 | ||||
| -rw-r--r-- | sound/usb/line6/pcm.h | 4 | ||||
| -rw-r--r-- | sound/usb/line6/toneport.c | 4 |
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 */ |
| 240 | static int snd_line6_capture_close(struct snd_pcm_substream *substream) | 242 | static 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 | */ |
| 289 | int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type) | 303 | int 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, | |||
| 191 | extern int snd_line6_hw_free(struct snd_pcm_substream *substream); | 192 | extern int snd_line6_hw_free(struct snd_pcm_substream *substream); |
| 192 | extern snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream); | 193 | extern snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream); |
| 193 | extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm); | 194 | extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm); |
| 194 | extern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type); | 195 | extern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type, |
| 196 | bool start); | ||
| 195 | extern void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type); | 197 | extern 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 */ |
