summaryrefslogtreecommitdiffstats
path: root/sound/usb/stream.c
diff options
context:
space:
mode:
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;