diff options
Diffstat (limited to 'sound/usb/stream.c')
-rw-r--r-- | sound/usb/stream.c | 83 |
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; |