| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 3 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 4 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 5 | | - * (at your option) any later version. |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 8 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 9 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 10 | | - * GNU General Public License for more details. |
|---|
| 11 | | - * |
|---|
| 12 | | - * You should have received a copy of the GNU General Public License |
|---|
| 13 | | - * along with this program; if not, write to the Free Software |
|---|
| 14 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 15 | 3 | */ |
|---|
| 16 | 4 | |
|---|
| 17 | 5 | |
|---|
| .. | .. |
|---|
| 38 | 26 | #include "clock.h" |
|---|
| 39 | 27 | #include "stream.h" |
|---|
| 40 | 28 | #include "power.h" |
|---|
| 29 | +#include "media.h" |
|---|
| 30 | + |
|---|
| 31 | +static void audioformat_free(struct audioformat *fp) |
|---|
| 32 | +{ |
|---|
| 33 | + list_del(&fp->list); /* unlink for avoiding double-free */ |
|---|
| 34 | + kfree(fp->rate_table); |
|---|
| 35 | + kfree(fp->chmap); |
|---|
| 36 | + kfree(fp); |
|---|
| 37 | +} |
|---|
| 41 | 38 | |
|---|
| 42 | 39 | /* |
|---|
| 43 | 40 | * free a substream |
|---|
| .. | .. |
|---|
| 48 | 45 | |
|---|
| 49 | 46 | if (!subs->num_formats) |
|---|
| 50 | 47 | return; /* not initialized */ |
|---|
| 51 | | - list_for_each_entry_safe(fp, n, &subs->fmt_list, list) { |
|---|
| 52 | | - kfree(fp->rate_table); |
|---|
| 53 | | - kfree(fp->chmap); |
|---|
| 54 | | - kfree(fp); |
|---|
| 55 | | - } |
|---|
| 48 | + list_for_each_entry_safe(fp, n, &subs->fmt_list, list) |
|---|
| 49 | + audioformat_free(fp); |
|---|
| 56 | 50 | kfree(subs->rate_list.list); |
|---|
| 57 | 51 | kfree(subs->str_pd); |
|---|
| 52 | + snd_media_stream_delete(subs); |
|---|
| 58 | 53 | } |
|---|
| 59 | 54 | |
|---|
| 60 | 55 | |
|---|
| .. | .. |
|---|
| 73 | 68 | { |
|---|
| 74 | 69 | struct snd_usb_stream *stream = pcm->private_data; |
|---|
| 75 | 70 | struct snd_usb_audio *chip; |
|---|
| 76 | | - |
|---|
| 77 | 71 | if (stream) { |
|---|
| 78 | 72 | mutex_lock(&stream->chip->dev_lock); |
|---|
| 79 | 73 | chip = stream->chip; |
|---|
| .. | .. |
|---|
| 104 | 98 | subs->tx_length_quirk = as->chip->tx_length_quirk; |
|---|
| 105 | 99 | subs->speed = snd_usb_get_speed(subs->dev); |
|---|
| 106 | 100 | subs->pkt_offset_adj = 0; |
|---|
| 101 | + subs->stream_offset_adj = 0; |
|---|
| 107 | 102 | |
|---|
| 108 | 103 | snd_usb_set_pcm_ops(as->pcm, stream); |
|---|
| 109 | 104 | |
|---|
| .. | .. |
|---|
| 505 | 500 | return 0; |
|---|
| 506 | 501 | } |
|---|
| 507 | 502 | } |
|---|
| 503 | + |
|---|
| 504 | + if (chip->card->registered) |
|---|
| 505 | + chip->need_delayed_register = true; |
|---|
| 506 | + |
|---|
| 508 | 507 | /* look for an empty stream */ |
|---|
| 509 | 508 | list_for_each_entry(as, &chip->pcm_list, list) { |
|---|
| 510 | 509 | if (as->fmt_type != fp->fmt_type) |
|---|
| .. | .. |
|---|
| 847 | 846 | /* ok, let's parse further... */ |
|---|
| 848 | 847 | if (snd_usb_parse_audio_format(chip, fp, format, |
|---|
| 849 | 848 | fmt, stream) < 0) { |
|---|
| 850 | | - kfree(fp->rate_table); |
|---|
| 851 | | - kfree(fp); |
|---|
| 849 | + audioformat_free(fp); |
|---|
| 852 | 850 | return NULL; |
|---|
| 853 | 851 | } |
|---|
| 854 | 852 | |
|---|
| .. | .. |
|---|
| 1059 | 1057 | |
|---|
| 1060 | 1058 | pd = kzalloc(sizeof(*pd), GFP_KERNEL); |
|---|
| 1061 | 1059 | if (!pd) { |
|---|
| 1062 | | - kfree(fp->chmap); |
|---|
| 1063 | | - kfree(fp->rate_table); |
|---|
| 1064 | | - kfree(fp); |
|---|
| 1060 | + audioformat_free(fp); |
|---|
| 1065 | 1061 | return NULL; |
|---|
| 1066 | 1062 | } |
|---|
| 1067 | 1063 | pd->pd_id = (stream == SNDRV_PCM_STREAM_PLAYBACK) ? |
|---|
| .. | .. |
|---|
| 1080 | 1076 | /* ok, let's parse further... */ |
|---|
| 1081 | 1077 | if (snd_usb_parse_audio_format_v3(chip, fp, as, stream) < 0) { |
|---|
| 1082 | 1078 | kfree(pd); |
|---|
| 1083 | | - kfree(fp->chmap); |
|---|
| 1084 | | - kfree(fp->rate_table); |
|---|
| 1085 | | - kfree(fp); |
|---|
| 1079 | + audioformat_free(fp); |
|---|
| 1086 | 1080 | return NULL; |
|---|
| 1087 | 1081 | } |
|---|
| 1088 | 1082 | } |
|---|
| .. | .. |
|---|
| 1093 | 1087 | return fp; |
|---|
| 1094 | 1088 | } |
|---|
| 1095 | 1089 | |
|---|
| 1096 | | -int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) |
|---|
| 1090 | +static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip, |
|---|
| 1091 | + int iface_no, |
|---|
| 1092 | + bool *has_non_pcm, bool non_pcm) |
|---|
| 1097 | 1093 | { |
|---|
| 1098 | 1094 | struct usb_device *dev; |
|---|
| 1099 | 1095 | struct usb_interface *iface; |
|---|
| .. | .. |
|---|
| 1115 | 1111 | * Dallas DS4201 workaround: It presents 5 altsettings, but the last |
|---|
| 1116 | 1112 | * one misses syncpipe, and does not produce any sound. |
|---|
| 1117 | 1113 | */ |
|---|
| 1118 | | - if (chip->usb_id == USB_ID(0x04fa, 0x4201)) |
|---|
| 1114 | + if (chip->usb_id == USB_ID(0x04fa, 0x4201) && num >= 4) |
|---|
| 1119 | 1115 | num = 4; |
|---|
| 1120 | 1116 | |
|---|
| 1121 | 1117 | for (i = 0; i < num; i++) { |
|---|
| .. | .. |
|---|
| 1156 | 1152 | dev_dbg(&dev->dev, "%u:%d: unknown interface protocol %#02x, assuming v1\n", |
|---|
| 1157 | 1153 | iface_no, altno, protocol); |
|---|
| 1158 | 1154 | protocol = UAC_VERSION_1; |
|---|
| 1159 | | - /* fall through */ |
|---|
| 1155 | + fallthrough; |
|---|
| 1160 | 1156 | case UAC_VERSION_1: |
|---|
| 1161 | | - /* fall through */ |
|---|
| 1162 | 1157 | case UAC_VERSION_2: { |
|---|
| 1163 | 1158 | int bm_quirk = 0; |
|---|
| 1164 | 1159 | |
|---|
| .. | .. |
|---|
| 1194 | 1189 | else if (IS_ERR(fp)) |
|---|
| 1195 | 1190 | return PTR_ERR(fp); |
|---|
| 1196 | 1191 | |
|---|
| 1192 | + if (fp->fmt_type != UAC_FORMAT_TYPE_I) |
|---|
| 1193 | + *has_non_pcm = true; |
|---|
| 1194 | + if ((fp->fmt_type == UAC_FORMAT_TYPE_I) == non_pcm) { |
|---|
| 1195 | + audioformat_free(fp); |
|---|
| 1196 | + kfree(pd); |
|---|
| 1197 | + fp = NULL; |
|---|
| 1198 | + pd = NULL; |
|---|
| 1199 | + continue; |
|---|
| 1200 | + } |
|---|
| 1201 | + |
|---|
| 1197 | 1202 | dev_dbg(&dev->dev, "%u:%d: add audio endpoint %#x\n", iface_no, altno, fp->endpoint); |
|---|
| 1198 | 1203 | if (protocol == UAC_VERSION_3) |
|---|
| 1199 | 1204 | err = snd_usb_add_audio_stream_v3(chip, stream, fp, pd); |
|---|
| .. | .. |
|---|
| 1201 | 1206 | err = snd_usb_add_audio_stream(chip, stream, fp); |
|---|
| 1202 | 1207 | |
|---|
| 1203 | 1208 | if (err < 0) { |
|---|
| 1204 | | - list_del(&fp->list); /* unlink for avoiding double-free */ |
|---|
| 1209 | + audioformat_free(fp); |
|---|
| 1205 | 1210 | kfree(pd); |
|---|
| 1206 | | - kfree(fp->rate_table); |
|---|
| 1207 | | - kfree(fp->chmap); |
|---|
| 1208 | | - kfree(fp); |
|---|
| 1209 | 1211 | return err; |
|---|
| 1210 | 1212 | } |
|---|
| 1211 | 1213 | /* try to set the interface... */ |
|---|
| .. | .. |
|---|
| 1216 | 1218 | return 0; |
|---|
| 1217 | 1219 | } |
|---|
| 1218 | 1220 | |
|---|
| 1221 | +int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) |
|---|
| 1222 | +{ |
|---|
| 1223 | + int err; |
|---|
| 1224 | + bool has_non_pcm = false; |
|---|
| 1225 | + |
|---|
| 1226 | + /* parse PCM formats */ |
|---|
| 1227 | + err = __snd_usb_parse_audio_interface(chip, iface_no, &has_non_pcm, false); |
|---|
| 1228 | + if (err < 0) |
|---|
| 1229 | + return err; |
|---|
| 1230 | + |
|---|
| 1231 | + if (has_non_pcm) { |
|---|
| 1232 | + /* parse non-PCM formats */ |
|---|
| 1233 | + err = __snd_usb_parse_audio_interface(chip, iface_no, &has_non_pcm, true); |
|---|
| 1234 | + if (err < 0) |
|---|
| 1235 | + return err; |
|---|
| 1236 | + } |
|---|
| 1237 | + |
|---|
| 1238 | + return 0; |
|---|
| 1239 | +} |
|---|
| 1240 | + |
|---|