diff options
Diffstat (limited to 'sound/usb/usbaudio.c')
-rw-r--r-- | sound/usb/usbaudio.c | 45 |
1 files changed, 26 insertions, 19 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 56e42b88addf..8fd37596e3a1 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c | |||
@@ -186,6 +186,7 @@ struct snd_usb_substream { | |||
186 | u64 formats; /* format bitmasks (all or'ed) */ | 186 | u64 formats; /* format bitmasks (all or'ed) */ |
187 | unsigned int num_formats; /* number of supported audio formats (list) */ | 187 | unsigned int num_formats; /* number of supported audio formats (list) */ |
188 | struct list_head fmt_list; /* format list */ | 188 | struct list_head fmt_list; /* format list */ |
189 | struct snd_pcm_hw_constraint_list rate_list; /* limited rates */ | ||
189 | spinlock_t lock; | 190 | spinlock_t lock; |
190 | 191 | ||
191 | struct snd_urb_ops ops; /* callbacks (must be filled at init) */ | 192 | 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) | |||
1818 | static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime, | 1819 | static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime, |
1819 | struct snd_usb_substream *subs) | 1820 | struct snd_usb_substream *subs) |
1820 | { | 1821 | { |
1821 | struct list_head *p; | 1822 | struct audioformat *fp; |
1822 | struct snd_pcm_hw_constraint_list constraints_rates; | 1823 | int count = 0, needs_knot = 0; |
1823 | int err; | 1824 | int err; |
1824 | 1825 | ||
1825 | list_for_each(p, &subs->fmt_list) { | 1826 | list_for_each_entry(fp, &subs->fmt_list, list) { |
1826 | struct audioformat *fp; | 1827 | if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) |
1827 | fp = list_entry(p, struct audioformat, list); | 1828 | return 0; |
1828 | 1829 | count += fp->nr_rates; | |
1829 | if (!fp->needs_knot) | 1830 | if (fp->needs_knot) |
1830 | continue; | 1831 | needs_knot = 1; |
1831 | |||
1832 | constraints_rates.count = fp->nr_rates; | ||
1833 | constraints_rates.list = fp->rate_table; | ||
1834 | constraints_rates.mask = 0; | ||
1835 | |||
1836 | err = snd_pcm_hw_constraint_list(runtime, 0, | ||
1837 | SNDRV_PCM_HW_PARAM_RATE, | ||
1838 | &constraints_rates); | ||
1839 | |||
1840 | if (err < 0) | ||
1841 | return err; | ||
1842 | } | 1832 | } |
1833 | if (!needs_knot) | ||
1834 | return 0; | ||
1835 | |||
1836 | subs->rate_list.count = count; | ||
1837 | subs->rate_list.list = kmalloc(sizeof(int) * count, GFP_KERNEL); | ||
1838 | subs->rate_list.mask = 0; | ||
1839 | count = 0; | ||
1840 | list_for_each_entry(fp, &subs->fmt_list, list) { | ||
1841 | int i; | ||
1842 | for (i = 0; i < fp->nr_rates; i++) | ||
1843 | subs->rate_list.list[count++] = fp->rate_table[i]; | ||
1844 | } | ||
1845 | err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | ||
1846 | &subs->rate_list); | ||
1847 | if (err < 0) | ||
1848 | return err; | ||
1843 | 1849 | ||
1844 | return 0; | 1850 | return 0; |
1845 | } | 1851 | } |
@@ -2238,6 +2244,7 @@ static void free_substream(struct snd_usb_substream *subs) | |||
2238 | kfree(fp->rate_table); | 2244 | kfree(fp->rate_table); |
2239 | kfree(fp); | 2245 | kfree(fp); |
2240 | } | 2246 | } |
2247 | kfree(subs->rate_list.list); | ||
2241 | } | 2248 | } |
2242 | 2249 | ||
2243 | 2250 | ||