summaryrefslogtreecommitdiff
path: root/sound/usb/pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb/pcm.c')
-rw-r--r--sound/usb/pcm.c70
1 files changed, 64 insertions, 6 deletions
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 24df26df81db..a56eb871784b 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -228,7 +228,7 @@ static int start_endpoints(struct snd_usb_substream *subs)
if (!test_and_set_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) {
struct snd_usb_endpoint *ep = subs->data_endpoint;
- dev_dbg(&subs->dev->dev, "Starting data EP @%p\n", ep);
+ dev_dbg(&subs->dev->dev, "Starting data EP @%pK\n", ep);
ep->data_subs = subs;
err = snd_usb_endpoint_start(ep);
@@ -257,7 +257,7 @@ static int start_endpoints(struct snd_usb_substream *subs)
}
}
- dev_dbg(&subs->dev->dev, "Starting sync EP @%p\n", ep);
+ dev_dbg(&subs->dev->dev, "Starting sync EP @%pK\n", ep);
ep->sync_slave = subs->data_endpoint;
err = snd_usb_endpoint_start(ep);
@@ -566,6 +566,64 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
return 0;
}
+int snd_usb_enable_audio_stream(struct snd_usb_substream *subs,
+ bool enable)
+{
+ struct audioformat *fmt;
+ struct usb_host_interface *alts;
+ struct usb_interface *iface;
+ int ret;
+
+ if (!enable) {
+ if (subs->interface >= 0) {
+ usb_set_interface(subs->dev, subs->interface, 0);
+ subs->altset_idx = 0;
+ subs->interface = -1;
+ subs->cur_audiofmt = NULL;
+ }
+
+ snd_usb_autosuspend(subs->stream->chip);
+ return 0;
+ }
+
+ snd_usb_autoresume(subs->stream->chip);
+ fmt = find_format(subs);
+ if (!fmt) {
+ dev_err(&subs->dev->dev,
+ "cannot set format: format = %#x, rate = %d, channels = %d\n",
+ subs->pcm_format, subs->cur_rate, subs->channels);
+ return -EINVAL;
+ }
+
+ subs->altset_idx = 0;
+ subs->interface = -1;
+ if (atomic_read(&subs->stream->chip->shutdown)) {
+ ret = -ENODEV;
+ } else {
+ ret = set_format(subs, fmt);
+ if (ret < 0)
+ return ret;
+
+ iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface);
+ alts = &iface->altsetting[subs->cur_audiofmt->altset_idx];
+ ret = snd_usb_init_sample_rate(subs->stream->chip,
+ subs->cur_audiofmt->iface,
+ alts,
+ subs->cur_audiofmt,
+ subs->cur_rate);
+ if (ret < 0) {
+ dev_err(&subs->dev->dev, "failed to set rate %d\n",
+ subs->cur_rate);
+ return ret;
+ }
+ }
+
+ subs->interface = fmt->iface;
+ subs->altset_idx = fmt->altset_idx;
+
+ return 0;
+}
+
/*
* Return the score of matching two audioformats.
* Veto the audioformat if:
@@ -583,13 +641,13 @@ static int match_endpoint_audioformats(struct snd_usb_substream *subs,
if (fp->channels < 1) {
dev_dbg(&subs->dev->dev,
- "%s: (fmt @%p) no channels\n", __func__, fp);
+ "%s: (fmt @%pK) no channels\n", __func__, fp);
return 0;
}
if (!(fp->formats & pcm_format_to_bits(pcm_format))) {
dev_dbg(&subs->dev->dev,
- "%s: (fmt @%p) no match for format %d\n", __func__,
+ "%s: (fmt @%pK) no match for format %d\n", __func__,
fp, pcm_format);
return 0;
}
@@ -602,7 +660,7 @@ static int match_endpoint_audioformats(struct snd_usb_substream *subs,
}
if (!score) {
dev_dbg(&subs->dev->dev,
- "%s: (fmt @%p) no match for rate %d\n", __func__,
+ "%s: (fmt @%pK) no match for rate %d\n", __func__,
fp, rate);
return 0;
}
@@ -611,7 +669,7 @@ static int match_endpoint_audioformats(struct snd_usb_substream *subs,
score++;
dev_dbg(&subs->dev->dev,
- "%s: (fmt @%p) score %d\n", __func__, fp, score);
+ "%s: (fmt @%pK) score %d\n", __func__, fp, score);
return score;
}