diff options
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/usbaudio.c | 54 | ||||
-rw-r--r-- | sound/usb/usbmixer.c | 27 | ||||
-rw-r--r-- | sound/usb/usbmixer_maps.c | 24 | ||||
-rw-r--r-- | sound/usb/usbquirks.h | 5 |
4 files changed, 106 insertions, 4 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 1b7f499c549d..49248fa7aef4 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c | |||
@@ -68,7 +68,7 @@ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | |||
68 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ | 68 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ |
69 | static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Vendor ID for this card */ | 69 | static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Vendor ID for this card */ |
70 | static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Product ID for this card */ | 70 | static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Product ID for this card */ |
71 | static int nrpacks = 4; /* max. number of packets per urb */ | 71 | static int nrpacks = 8; /* max. number of packets per urb */ |
72 | static int async_unlink = 1; | 72 | static int async_unlink = 1; |
73 | static int device_setup[SNDRV_CARDS]; /* device parameter for this card*/ | 73 | static int device_setup[SNDRV_CARDS]; /* device parameter for this card*/ |
74 | 74 | ||
@@ -100,7 +100,7 @@ MODULE_PARM_DESC(device_setup, "Specific device setup (if needed)."); | |||
100 | * | 100 | * |
101 | */ | 101 | */ |
102 | 102 | ||
103 | #define MAX_PACKS 10 | 103 | #define MAX_PACKS 20 |
104 | #define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */ | 104 | #define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */ |
105 | #define MAX_URBS 8 | 105 | #define MAX_URBS 8 |
106 | #define SYNC_URBS 4 /* always four urbs for sync */ | 106 | #define SYNC_URBS 4 /* always four urbs for sync */ |
@@ -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 | ||
128 | struct snd_usb_substream; | 129 | struct 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 | */ | ||
1809 | static 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 | } |
@@ -2049,7 +2087,7 @@ static struct usb_driver usb_audio_driver = { | |||
2049 | }; | 2087 | }; |
2050 | 2088 | ||
2051 | 2089 | ||
2052 | #if defined(CONFIG_PROCFS) && defined(CONFIG_SND_VERBOSE_PROCFS) | 2090 | #if defined(CONFIG_PROC_FS) && defined(CONFIG_SND_VERBOSE_PROCFS) |
2053 | 2091 | ||
2054 | /* | 2092 | /* |
2055 | * proc interface for list the supported pcm formats | 2093 | * proc interface for list the supported pcm formats |
@@ -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; |
@@ -3499,7 +3545,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr) | |||
3499 | } | 3545 | } |
3500 | usb_chip[chip->index] = NULL; | 3546 | usb_chip[chip->index] = NULL; |
3501 | mutex_unlock(®ister_mutex); | 3547 | mutex_unlock(®ister_mutex); |
3502 | snd_card_free(card); | 3548 | snd_card_free_when_closed(card); |
3503 | } else { | 3549 | } else { |
3504 | mutex_unlock(®ister_mutex); | 3550 | mutex_unlock(®ister_mutex); |
3505 | } | 3551 | } |
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index 491e975a0c87..e516d6adbb22 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <sound/control.h> | 37 | #include <sound/control.h> |
38 | #include <sound/hwdep.h> | 38 | #include <sound/hwdep.h> |
39 | #include <sound/info.h> | 39 | #include <sound/info.h> |
40 | #include <sound/tlv.h> | ||
40 | 41 | ||
41 | #include "usbaudio.h" | 42 | #include "usbaudio.h" |
42 | 43 | ||
@@ -416,6 +417,26 @@ static inline int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channe | |||
416 | return set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value); | 417 | return set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value); |
417 | } | 418 | } |
418 | 419 | ||
420 | /* | ||
421 | * TLV callback for mixer volume controls | ||
422 | */ | ||
423 | static int mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
424 | unsigned int size, unsigned int __user *_tlv) | ||
425 | { | ||
426 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | ||
427 | DECLARE_TLV_DB_SCALE(scale, 0, 0, 0); | ||
428 | |||
429 | if (size < sizeof(scale)) | ||
430 | return -ENOMEM; | ||
431 | /* USB descriptions contain the dB scale in 1/256 dB unit | ||
432 | * while ALSA TLV contains in 1/100 dB unit | ||
433 | */ | ||
434 | scale[2] = (convert_signed_value(cval, cval->min) * 100) / 256; | ||
435 | scale[3] = (convert_signed_value(cval, cval->res) * 100) / 256; | ||
436 | if (copy_to_user(_tlv, scale, sizeof(scale))) | ||
437 | return -EFAULT; | ||
438 | return 0; | ||
439 | } | ||
419 | 440 | ||
420 | /* | 441 | /* |
421 | * parser routines begin here... | 442 | * parser routines begin here... |
@@ -933,6 +954,12 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc, | |||
933 | } | 954 | } |
934 | strlcat(kctl->id.name + len, control == USB_FEATURE_MUTE ? " Switch" : " Volume", | 955 | strlcat(kctl->id.name + len, control == USB_FEATURE_MUTE ? " Switch" : " Volume", |
935 | sizeof(kctl->id.name)); | 956 | sizeof(kctl->id.name)); |
957 | if (control == USB_FEATURE_VOLUME) { | ||
958 | kctl->tlv.c = mixer_vol_tlv; | ||
959 | kctl->vd[0].access |= | ||
960 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | ||
961 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; | ||
962 | } | ||
936 | break; | 963 | break; |
937 | 964 | ||
938 | default: | 965 | default: |
diff --git a/sound/usb/usbmixer_maps.c b/sound/usb/usbmixer_maps.c index 37accb68652d..7c4dcb3f436a 100644 --- a/sound/usb/usbmixer_maps.c +++ b/sound/usb/usbmixer_maps.c | |||
@@ -234,6 +234,26 @@ static struct usbmix_name_map justlink_map[] = { | |||
234 | { 0 } /* terminator */ | 234 | { 0 } /* terminator */ |
235 | }; | 235 | }; |
236 | 236 | ||
237 | /* TerraTec Aureon 5.1 MkII USB */ | ||
238 | static struct usbmix_name_map aureon_51_2_map[] = { | ||
239 | /* 1: IT USB */ | ||
240 | /* 2: IT Mic */ | ||
241 | /* 3: IT Line */ | ||
242 | /* 4: IT SPDIF */ | ||
243 | /* 5: OT SPDIF */ | ||
244 | /* 6: OT Speaker */ | ||
245 | /* 7: OT USB */ | ||
246 | { 8, "Capture Source" }, /* SU */ | ||
247 | { 9, "Master Playback" }, /* FU */ | ||
248 | { 10, "Mic Capture" }, /* FU */ | ||
249 | { 11, "Line Capture" }, /* FU */ | ||
250 | { 12, "IEC958 In Capture" }, /* FU */ | ||
251 | { 13, "Mic Playback" }, /* FU */ | ||
252 | { 14, "Line Playback" }, /* FU */ | ||
253 | /* 15: MU */ | ||
254 | {} /* terminator */ | ||
255 | }; | ||
256 | |||
237 | /* | 257 | /* |
238 | * Control map entries | 258 | * Control map entries |
239 | */ | 259 | */ |
@@ -276,6 +296,10 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { | |||
276 | .id = USB_ID(0x0c45, 0x1158), | 296 | .id = USB_ID(0x0c45, 0x1158), |
277 | .map = justlink_map, | 297 | .map = justlink_map, |
278 | }, | 298 | }, |
299 | { | ||
300 | .id = USB_ID(0x0ccd, 0x0028), | ||
301 | .map = aureon_51_2_map, | ||
302 | }, | ||
279 | { 0 } /* terminator */ | 303 | { 0 } /* terminator */ |
280 | }; | 304 | }; |
281 | 305 | ||
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index 9351846d7a9d..a7e9563a01df 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h | |||
@@ -123,6 +123,10 @@ YAMAHA_DEVICE(0x103e, NULL), | |||
123 | YAMAHA_DEVICE(0x103f, NULL), | 123 | YAMAHA_DEVICE(0x103f, NULL), |
124 | YAMAHA_DEVICE(0x1040, NULL), | 124 | YAMAHA_DEVICE(0x1040, NULL), |
125 | YAMAHA_DEVICE(0x1041, NULL), | 125 | YAMAHA_DEVICE(0x1041, NULL), |
126 | YAMAHA_DEVICE(0x1042, NULL), | ||
127 | YAMAHA_DEVICE(0x1043, NULL), | ||
128 | YAMAHA_DEVICE(0x1044, NULL), | ||
129 | YAMAHA_DEVICE(0x1045, NULL), | ||
126 | YAMAHA_DEVICE(0x2000, "DGP-7"), | 130 | YAMAHA_DEVICE(0x2000, "DGP-7"), |
127 | YAMAHA_DEVICE(0x2001, "DGP-5"), | 131 | YAMAHA_DEVICE(0x2001, "DGP-5"), |
128 | YAMAHA_DEVICE(0x2002, NULL), | 132 | YAMAHA_DEVICE(0x2002, NULL), |
@@ -141,6 +145,7 @@ YAMAHA_DEVICE(0x500b, "DME64N"), | |||
141 | YAMAHA_DEVICE(0x500c, "DME24N"), | 145 | YAMAHA_DEVICE(0x500c, "DME24N"), |
142 | YAMAHA_DEVICE(0x500d, NULL), | 146 | YAMAHA_DEVICE(0x500d, NULL), |
143 | YAMAHA_DEVICE(0x500e, NULL), | 147 | YAMAHA_DEVICE(0x500e, NULL), |
148 | YAMAHA_DEVICE(0x500f, NULL), | ||
144 | YAMAHA_DEVICE(0x7000, "DTX"), | 149 | YAMAHA_DEVICE(0x7000, "DTX"), |
145 | YAMAHA_DEVICE(0x7010, "UB99"), | 150 | YAMAHA_DEVICE(0x7010, "UB99"), |
146 | #undef YAMAHA_DEVICE | 151 | #undef YAMAHA_DEVICE |