summaryrefslogtreecommitdiffstats
path: root/sound/usb/stream.c
diff options
context:
space:
mode:
authorRuslan Bilovol <ruslan.bilovol@gmail.com>2018-05-03 21:24:04 -0400
committerTakashi Iwai <tiwai@suse.de>2018-05-13 02:54:35 -0400
commit17156f23e93c0f59e06dd2aaffd06221341caaee (patch)
treef7eac9dcff74c160bc43f1a032b5d15647fbe1d8 /sound/usb/stream.c
parent10aa7cad37d330dbff6a285af56dc4a7153a8f00 (diff)
ALSA: usb: add UAC3 BADD profiles support
Recently released USB Audio Class 3.0 specification contains BADD (Basic Audio Device Definition) document which describes pre-defined UAC3 configurations. BADD support is mandatory for UAC3 devices, it should be implemented as a separate USB device configuration. As per BADD document, class-specific descriptors shall not be included in the Device’s Configuration descriptor ("inferred"), but host can guess them from BADD profile number, number of endpoints and their max packed sizes. This patch adds support of all BADD profiles from the spec Signed-off-by: Ruslan Bilovol <ruslan.bilovol@gmail.com> Tested-by: Jorge Sanjuan <jorge.sanjuan@codethink.co.uk> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb/stream.c')
-rw-r--r--sound/usb/stream.c83
1 files changed, 74 insertions, 9 deletions
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index 764be07474a8..de8bbb304199 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -817,15 +817,67 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
817 struct uac3_input_terminal_descriptor *input_term; 817 struct uac3_input_terminal_descriptor *input_term;
818 struct uac3_output_terminal_descriptor *output_term; 818 struct uac3_output_terminal_descriptor *output_term;
819 struct uac3_cluster_header_descriptor *cluster; 819 struct uac3_cluster_header_descriptor *cluster;
820 struct uac3_as_header_descriptor *as; 820 struct uac3_as_header_descriptor *as = NULL;
821 struct uac3_hc_descriptor_header hc_header; 821 struct uac3_hc_descriptor_header hc_header;
822 struct snd_pcm_chmap_elem *chmap; 822 struct snd_pcm_chmap_elem *chmap;
823 unsigned char badd_profile;
824 u64 badd_formats = 0;
823 unsigned int num_channels; 825 unsigned int num_channels;
824 struct audioformat *fp; 826 struct audioformat *fp;
825 u16 cluster_id, wLength; 827 u16 cluster_id, wLength;
826 int clock = 0; 828 int clock = 0;
827 int err; 829 int err;
828 830
831 badd_profile = chip->badd_profile;
832
833 if (badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
834 unsigned int maxpacksize =
835 le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
836
837 switch (maxpacksize) {
838 default:
839 dev_err(&dev->dev,
840 "%u:%d : incorrect wMaxPacketSize for BADD profile\n",
841 iface_no, altno);
842 return NULL;
843 case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_16:
844 case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_16:
845 badd_formats = SNDRV_PCM_FMTBIT_S16_LE;
846 num_channels = 1;
847 break;
848 case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_24:
849 case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_24:
850 badd_formats = SNDRV_PCM_FMTBIT_S24_3LE;
851 num_channels = 1;
852 break;
853 case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_16:
854 case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_16:
855 badd_formats = SNDRV_PCM_FMTBIT_S16_LE;
856 num_channels = 2;
857 break;
858 case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_24:
859 case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_24:
860 badd_formats = SNDRV_PCM_FMTBIT_S24_3LE;
861 num_channels = 2;
862 break;
863 }
864
865 chmap = kzalloc(sizeof(*chmap), GFP_KERNEL);
866 if (!chmap)
867 return ERR_PTR(-ENOMEM);
868
869 if (num_channels == 1) {
870 chmap->map[0] = SNDRV_CHMAP_MONO;
871 } else {
872 chmap->map[0] = SNDRV_CHMAP_FL;
873 chmap->map[1] = SNDRV_CHMAP_FR;
874 }
875
876 chmap->channels = num_channels;
877 clock = UAC3_BADD_CS_ID9;
878 goto found_clock;
879 }
880
829 as = snd_usb_find_csint_desc(alts->extra, alts->extralen, 881 as = snd_usb_find_csint_desc(alts->extra, alts->extralen,
830 NULL, UAC_AS_GENERAL); 882 NULL, UAC_AS_GENERAL);
831 if (!as) { 883 if (!as) {
@@ -931,16 +983,29 @@ found_clock:
931 if (!fp) 983 if (!fp)
932 return ERR_PTR(-ENOMEM); 984 return ERR_PTR(-ENOMEM);
933 985
934 fp->attributes = parse_uac_endpoint_attributes(chip, alts,
935 UAC_VERSION_3,
936 iface_no);
937 fp->chmap = chmap; 986 fp->chmap = chmap;
938 987
939 /* ok, let's parse further... */ 988 if (badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
940 if (snd_usb_parse_audio_format_v3(chip, fp, as, stream) < 0) { 989 fp->attributes = 0; /* No attributes */
941 kfree(fp->rate_table); 990
942 kfree(fp); 991 fp->fmt_type = UAC_FORMAT_TYPE_I;
943 return NULL; 992 fp->formats = badd_formats;
993
994 fp->nr_rates = 0; /* SNDRV_PCM_RATE_CONTINUOUS */
995 fp->rate_min = UAC3_BADD_SAMPLING_RATE;
996 fp->rate_max = UAC3_BADD_SAMPLING_RATE;
997 fp->rates = SNDRV_PCM_RATE_CONTINUOUS;
998
999 } else {
1000 fp->attributes = parse_uac_endpoint_attributes(chip, alts,
1001 UAC_VERSION_3,
1002 iface_no);
1003 /* ok, let's parse further... */
1004 if (snd_usb_parse_audio_format_v3(chip, fp, as, stream) < 0) {
1005 kfree(fp->rate_table);
1006 kfree(fp);
1007 return NULL;
1008 }
944 } 1009 }
945 1010
946 return fp; 1011 return fp;