|
@@ -186,6 +186,7 @@ struct snd_usb_substream {
|
|
|
u64 formats; /* format bitmasks (all or'ed) */
|
|
|
unsigned int num_formats; /* number of supported audio formats (list) */
|
|
|
struct list_head fmt_list; /* format list */
|
|
|
+ struct snd_pcm_hw_constraint_list rate_list; /* limited rates */
|
|
|
spinlock_t lock;
|
|
|
|
|
|
struct snd_urb_ops ops; /* callbacks (must be filled at init) */
|
|
@@ -1818,28 +1819,33 @@ static int check_hw_params_convention(struct snd_usb_substream *subs)
|
|
|
static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
|
|
|
struct snd_usb_substream *subs)
|
|
|
{
|
|
|
- struct list_head *p;
|
|
|
- struct snd_pcm_hw_constraint_list constraints_rates;
|
|
|
+ struct audioformat *fp;
|
|
|
+ int count = 0, needs_knot = 0;
|
|
|
int err;
|
|
|
|
|
|
- list_for_each(p, &subs->fmt_list) {
|
|
|
- struct audioformat *fp;
|
|
|
- fp = list_entry(p, struct audioformat, list);
|
|
|
-
|
|
|
- if (!fp->needs_knot)
|
|
|
- continue;
|
|
|
-
|
|
|
- constraints_rates.count = fp->nr_rates;
|
|
|
- constraints_rates.list = fp->rate_table;
|
|
|
- constraints_rates.mask = 0;
|
|
|
-
|
|
|
- err = snd_pcm_hw_constraint_list(runtime, 0,
|
|
|
- SNDRV_PCM_HW_PARAM_RATE,
|
|
|
- &constraints_rates);
|
|
|
-
|
|
|
- if (err < 0)
|
|
|
- return err;
|
|
|
+ list_for_each_entry(fp, &subs->fmt_list, list) {
|
|
|
+ if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)
|
|
|
+ return 0;
|
|
|
+ count += fp->nr_rates;
|
|
|
+ if (fp->needs_knot)
|
|
|
+ needs_knot = 1;
|
|
|
}
|
|
|
+ if (!needs_knot)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ subs->rate_list.count = count;
|
|
|
+ subs->rate_list.list = kmalloc(sizeof(int) * count, GFP_KERNEL);
|
|
|
+ subs->rate_list.mask = 0;
|
|
|
+ count = 0;
|
|
|
+ list_for_each_entry(fp, &subs->fmt_list, list) {
|
|
|
+ int i;
|
|
|
+ for (i = 0; i < fp->nr_rates; i++)
|
|
|
+ subs->rate_list.list[count++] = fp->rate_table[i];
|
|
|
+ }
|
|
|
+ err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
|
|
|
+ &subs->rate_list);
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -2238,6 +2244,7 @@ static void free_substream(struct snd_usb_substream *subs)
|
|
|
kfree(fp->rate_table);
|
|
|
kfree(fp);
|
|
|
}
|
|
|
+ kfree(subs->rate_list.list);
|
|
|
}
|
|
|
|
|
|
|