aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/usb/usbaudio.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 087f9b64d8a0..664dd4c21e66 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -123,6 +123,7 @@ struct audioformat {
123 unsigned int rate_min, rate_max; /* min/max rates */ 123 unsigned int rate_min, rate_max; /* min/max rates */
124 unsigned int nr_rates; /* number of rate table entries */ 124 unsigned int nr_rates; /* number of rate table entries */
125 unsigned int *rate_table; /* rate table */ 125 unsigned int *rate_table; /* rate table */
126 unsigned int needs_knot; /* any unusual rates? */
126}; 127};
127 128
128struct snd_usb_substream; 129struct snd_usb_substream;
@@ -1759,6 +1760,9 @@ static int check_hw_params_convention(struct snd_usb_substream *subs)
1759 } 1760 }
1760 channels[f->format] |= (1 << f->channels); 1761 channels[f->format] |= (1 << f->channels);
1761 rates[f->format] |= f->rates; 1762 rates[f->format] |= f->rates;
1763 /* needs knot? */
1764 if (f->needs_knot)
1765 goto __out;
1762 } 1766 }
1763 /* check whether channels and rates match for all formats */ 1767 /* check whether channels and rates match for all formats */
1764 cmaster = rmaster = 0; 1768 cmaster = rmaster = 0;
@@ -1799,6 +1803,38 @@ static int check_hw_params_convention(struct snd_usb_substream *subs)
1799 return err; 1803 return err;
1800} 1804}
1801 1805
1806/*
1807 * If the device supports unusual bit rates, does the request meet these?
1808 */
1809static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
1810 struct snd_usb_substream *subs)
1811{
1812 struct list_head *p;
1813 struct snd_pcm_hw_constraint_list constraints_rates;
1814 int err;
1815
1816 list_for_each(p, &subs->fmt_list) {
1817 struct audioformat *fp;
1818 fp = list_entry(p, struct audioformat, list);
1819
1820 if (!fp->needs_knot)
1821 continue;
1822
1823 constraints_rates.count = fp->nr_rates;
1824 constraints_rates.list = fp->rate_table;
1825 constraints_rates.mask = 0;
1826
1827 err = snd_pcm_hw_constraint_list(runtime, 0,
1828 SNDRV_PCM_HW_PARAM_RATE,
1829 &constraints_rates);
1830
1831 if (err < 0)
1832 return err;
1833 }
1834
1835 return 0;
1836}
1837
1802 1838
1803/* 1839/*
1804 * set up the runtime hardware information. 1840 * set up the runtime hardware information.
@@ -1861,6 +1897,8 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
1861 SNDRV_PCM_HW_PARAM_CHANNELS, 1897 SNDRV_PCM_HW_PARAM_CHANNELS,
1862 -1)) < 0) 1898 -1)) < 0)
1863 return err; 1899 return err;
1900 if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0)
1901 return err;
1864 } 1902 }
1865 return 0; 1903 return 0;
1866} 1904}
@@ -2406,6 +2444,7 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform
2406 unsigned char *fmt, int offset) 2444 unsigned char *fmt, int offset)
2407{ 2445{
2408 int nr_rates = fmt[offset]; 2446 int nr_rates = fmt[offset];
2447 int found;
2409 if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) { 2448 if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) {
2410 snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n", 2449 snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n",
2411 chip->dev->devnum, fp->iface, fp->altsetting); 2450 chip->dev->devnum, fp->iface, fp->altsetting);
@@ -2428,6 +2467,7 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform
2428 return -1; 2467 return -1;
2429 } 2468 }
2430 2469
2470 fp->needs_knot = 0;
2431 fp->nr_rates = nr_rates; 2471 fp->nr_rates = nr_rates;
2432 fp->rate_min = fp->rate_max = combine_triple(&fmt[8]); 2472 fp->rate_min = fp->rate_max = combine_triple(&fmt[8]);
2433 for (r = 0, idx = offset + 1; r < nr_rates; r++, idx += 3) { 2473 for (r = 0, idx = offset + 1; r < nr_rates; r++, idx += 3) {
@@ -2436,13 +2476,19 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform
2436 fp->rate_min = rate; 2476 fp->rate_min = rate;
2437 else if (rate > fp->rate_max) 2477 else if (rate > fp->rate_max)
2438 fp->rate_max = rate; 2478 fp->rate_max = rate;
2479 found = 0;
2439 for (c = 0; c < (int)ARRAY_SIZE(conv_rates); c++) { 2480 for (c = 0; c < (int)ARRAY_SIZE(conv_rates); c++) {
2440 if (rate == conv_rates[c]) { 2481 if (rate == conv_rates[c]) {
2482 found = 1;
2441 fp->rates |= (1 << c); 2483 fp->rates |= (1 << c);
2442 break; 2484 break;
2443 } 2485 }
2444 } 2486 }
2487 if (!found)
2488 fp->needs_knot = 1;
2445 } 2489 }
2490 if (fp->needs_knot)
2491 fp->rates |= SNDRV_PCM_RATE_KNOT;
2446 } else { 2492 } else {
2447 /* continuous rates */ 2493 /* continuous rates */
2448 fp->rates = SNDRV_PCM_RATE_CONTINUOUS; 2494 fp->rates = SNDRV_PCM_RATE_CONTINUOUS;