aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/usb/card.h1
-rw-r--r--sound/usb/endpoint.c21
-rw-r--r--sound/usb/endpoint.h1
-rw-r--r--sound/usb/pcm.c9
4 files changed, 32 insertions, 0 deletions
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 5b19901f305a..3329ce710cb9 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -136,6 +136,7 @@ struct snd_usb_endpoint {
unsigned int cur_period_frames;
unsigned int cur_period_bytes;
unsigned int cur_buffer_periods;
+ unsigned char cur_clock;
spinlock_t lock;
struct list_head list;
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 533919a28856..29c4865966f5 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -722,6 +722,7 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
ep->cur_period_frames = params_period_size(params);
ep->cur_period_bytes = ep->cur_period_frames * ep->cur_frame_bytes;
ep->cur_buffer_periods = params_periods(params);
+ ep->cur_clock = fp->clock;
if (ep->type == SND_USB_ENDPOINT_TYPE_SYNC)
endpoint_set_syncinterval(chip, ep);
@@ -833,6 +834,7 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip,
ep->altsetting = 0;
ep->cur_audiofmt = NULL;
ep->cur_rate = 0;
+ ep->cur_clock = 0;
ep->iface_ref = NULL;
usb_audio_dbg(chip, "EP 0x%x closed\n", ep->ep_num);
}
@@ -1340,6 +1342,25 @@ unlock:
return err;
}
+/* get the current rate set to the given clock by any endpoint */
+int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock)
+{
+ struct snd_usb_endpoint *ep;
+ int rate = 0;
+
+ if (!clock)
+ return 0;
+ mutex_lock(&chip->mutex);
+ list_for_each_entry(ep, &chip->ep_list, list) {
+ if (ep->cur_clock == clock && ep->cur_rate) {
+ rate = ep->cur_rate;
+ break;
+ }
+ }
+ mutex_unlock(&chip->mutex);
+ return rate;
+}
+
/**
* snd_usb_endpoint_start: start an snd_usb_endpoint
*
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index a668f675b52b..a1099ec37e1c 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -19,6 +19,7 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep);
int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep);
+int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock);
bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep,
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 5dc9266180e3..19392117de9e 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -734,6 +734,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{
struct snd_usb_substream *subs = rule->private;
+ struct snd_usb_audio *chip = subs->stream->chip;
const struct audioformat *fp;
struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
unsigned int rmin, rmax, r;
@@ -745,6 +746,14 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
list_for_each_entry(fp, &subs->fmt_list, list) {
if (!hw_check_valid_format(subs, params, fp))
continue;
+ r = snd_usb_endpoint_get_clock_rate(chip, fp->clock);
+ if (r > 0) {
+ if (!snd_interval_test(it, r))
+ continue;
+ rmin = min(rmin, r);
+ rmax = max(rmax, r);
+ continue;
+ }
if (fp->rate_table && fp->nr_rates) {
for (i = 0; i < fp->nr_rates; i++) {
r = fp->rate_table[i];