Skip to content

Commit 2aa0a36

Browse files
committed
Merge tag 'sound-7.1-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound fixes from Takashi Iwai: "A bunch of small fixes. One minor fix is found in the core side for data race in PCM OSS layer, while remaining changes are various device-specific fixes and quirks. - Core: PCM OSS data race fix - HD-audio: Fixes for TAS2781, CS35L56, and Realtek/Conexant quirks; avoidance of a WARN_ON for HDMI channel mapping - USB-audio: Improvements in UAC3 parsing robustness (leaks, size checks) and fixes for potential endless loops - ASoC: Driver-specific fixes for CS35L56, Intel bytcr_wm5102, Spacemit, AW88395, and others, plus a new quirk for Steam Deck OLED - Misc: A UAF fix in aloop driver, division by zero fix in ua101 driver and leak fixes in caiaq driver" * tag 'sound-7.1-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (32 commits) ALSA: hda/tas2781: Fix incorrect bit update for non-book-zero or book 0 pages >1 ALSA: hda: cs35l56: Fix uninitialized value in cs35l56_hda_read_acpi() ALSA: hda/conexant: Fix missing error check for jack detection ALSA: hda: Avoid WARN_ON() for HDMI chmap slot checks ALSA: usb-audio: Fix quirk entry placement for PreSonus AudioBox USB ASoC: spacemit: adjust FIFO trigger threshold to half FIFO size ASoC: spacemit: move hw constraints from hw_params to startup ASoC: codecs: ab8500: Fix casting of private data ASoC: cs35l56: Fix illegal writes to OTP_MEM registers ASoC: Intel: bytcr_wm5102: Fix MCLK leak on platform_clock_control error ALSA: usb-audio: Avoid potential endless loop in convert_chmap_v3() ALSA: usb-audio: Fix potential leak of pd at parsing UAC3 streams ALSA: caiaq: Don't abort when no input device is available ALSA: caiaq: Fix potentially leftover ep1_in_urb at error path ASoC: aw88395: Fix kernel panic caused by invalid GPIO error pointer ALSA: caiaq: fix usb_dev refcount leak on probe failure sound: ua101: fix division by zero at probe ALSA: usb-audio: apply quirk for Playstation PDP Riffmaster ALSA: hda: Remove duplicate cmedia entries in codecs Makefile ALSA: hda/realtek: Add micmute LED quirk for Acer Aspire A315-44P ...
2 parents e75a43c + e052a1f commit 2aa0a36

32 files changed

Lines changed: 266 additions & 122 deletions

sound/core/oss/pcm_oss.c

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2155,10 +2155,16 @@ static int snd_pcm_oss_get_trigger(struct snd_pcm_oss_file *pcm_oss_file)
21552155

21562156
psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
21572157
csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
2158-
if (psubstream && psubstream->runtime && psubstream->runtime->oss.trigger)
2159-
result |= PCM_ENABLE_OUTPUT;
2160-
if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger)
2161-
result |= PCM_ENABLE_INPUT;
2158+
if (psubstream && psubstream->runtime) {
2159+
guard(mutex)(&psubstream->runtime->oss.params_lock);
2160+
if (psubstream->runtime->oss.trigger)
2161+
result |= PCM_ENABLE_OUTPUT;
2162+
}
2163+
if (csubstream && csubstream->runtime) {
2164+
guard(mutex)(&csubstream->runtime->oss.params_lock);
2165+
if (csubstream->runtime->oss.trigger)
2166+
result |= PCM_ENABLE_INPUT;
2167+
}
21622168
return result;
21632169
}
21642170

@@ -2832,6 +2838,17 @@ static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream)
28322838
runtime->oss.period_frames;
28332839
}
28342840

2841+
static bool need_input_retrigger(struct snd_pcm_runtime *runtime)
2842+
{
2843+
bool ret;
2844+
2845+
guard(mutex)(&runtime->oss.params_lock);
2846+
ret = runtime->oss.trigger;
2847+
if (ret)
2848+
runtime->oss.trigger = 0;
2849+
return ret;
2850+
}
2851+
28352852
static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
28362853
{
28372854
struct snd_pcm_oss_file *pcm_oss_file;
@@ -2864,11 +2881,11 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
28642881
snd_pcm_oss_capture_ready(csubstream))
28652882
mask |= EPOLLIN | EPOLLRDNORM;
28662883
}
2867-
if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) {
2884+
if (ostate != SNDRV_PCM_STATE_RUNNING &&
2885+
need_input_retrigger(runtime)) {
28682886
struct snd_pcm_oss_file ofile;
28692887
memset(&ofile, 0, sizeof(ofile));
28702888
ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
2871-
runtime->oss.trigger = 0;
28722889
snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT);
28732890
}
28742891
}

sound/drivers/aloop.c

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ struct loopback_ops {
9999
struct loopback_cable {
100100
spinlock_t lock;
101101
struct loopback_pcm *streams[2];
102+
/* in-flight peer stops running outside cable->lock */
103+
atomic_t stop_count;
104+
wait_queue_head_t stop_wait;
102105
struct snd_pcm_hardware hw;
103106
/* flags */
104107
unsigned int valid;
@@ -366,8 +369,11 @@ static int loopback_check_format(struct loopback_cable *cable, int stream)
366369
return 0;
367370
if (stream == SNDRV_PCM_STREAM_CAPTURE)
368371
return -EIO;
369-
else if (cruntime->state == SNDRV_PCM_STATE_RUNNING)
372+
else if (cruntime->state == SNDRV_PCM_STATE_RUNNING) {
373+
/* close must not free the peer runtime below */
374+
atomic_inc(&cable->stop_count);
370375
stop_capture = true;
376+
}
371377
}
372378

373379
setup = get_setup(dpcm_play);
@@ -396,8 +402,11 @@ static int loopback_check_format(struct loopback_cable *cable, int stream)
396402
}
397403
}
398404

399-
if (stop_capture)
405+
if (stop_capture) {
400406
snd_pcm_stop(dpcm_capt->substream, SNDRV_PCM_STATE_DRAINING);
407+
if (atomic_dec_and_test(&cable->stop_count))
408+
wake_up(&cable->stop_wait);
409+
}
401410

402411
return 0;
403412
}
@@ -1049,23 +1058,29 @@ static void free_cable(struct snd_pcm_substream *substream)
10491058
struct loopback *loopback = substream->private_data;
10501059
int dev = get_cable_index(substream);
10511060
struct loopback_cable *cable;
1061+
struct loopback_pcm *dpcm;
1062+
bool other_alive;
10521063

10531064
cable = loopback->cables[substream->number][dev];
10541065
if (!cable)
10551066
return;
1056-
if (cable->streams[!substream->stream]) {
1057-
/* other stream is still alive */
1058-
guard(spinlock_irq)(&cable->lock);
1059-
cable->streams[substream->stream] = NULL;
1060-
} else {
1061-
struct loopback_pcm *dpcm = substream->runtime->private_data;
10621067

1063-
if (cable->ops && cable->ops->close_cable && dpcm)
1064-
cable->ops->close_cable(dpcm);
1065-
/* free the cable */
1066-
loopback->cables[substream->number][dev] = NULL;
1067-
kfree(cable);
1068+
scoped_guard(spinlock_irq, &cable->lock) {
1069+
cable->streams[substream->stream] = NULL;
1070+
other_alive = cable->streams[!substream->stream];
10681071
}
1072+
1073+
/* Pair with the stop_count increment in loopback_check_format(). */
1074+
wait_event(cable->stop_wait, !atomic_read(&cable->stop_count));
1075+
if (other_alive)
1076+
return;
1077+
1078+
dpcm = substream->runtime->private_data;
1079+
if (cable->ops && cable->ops->close_cable && dpcm)
1080+
cable->ops->close_cable(dpcm);
1081+
/* free the cable */
1082+
loopback->cables[substream->number][dev] = NULL;
1083+
kfree(cable);
10691084
}
10701085

10711086
static int loopback_jiffies_timer_open(struct loopback_pcm *dpcm)
@@ -1260,6 +1275,8 @@ static int loopback_open(struct snd_pcm_substream *substream)
12601275
goto unlock;
12611276
}
12621277
spin_lock_init(&cable->lock);
1278+
atomic_set(&cable->stop_count, 0);
1279+
init_waitqueue_head(&cable->stop_wait);
12631280
cable->hw = loopback_pcm_hardware;
12641281
if (loopback->timer_source)
12651282
cable->ops = &loopback_snd_timer_ops;

sound/hda/codecs/Makefile

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ snd-hda-codec-cm9825-y := cm9825.o
77
snd-hda-codec-analog-y := analog.o
88
snd-hda-codec-ca0110-y := ca0110.o
99
snd-hda-codec-ca0132-y := ca0132.o
10-
snd-hda-codec-cmedia-y := cmedia.o
1110
snd-hda-codec-conexant-y := conexant.o
1211
snd-hda-codec-idt-y := sigmatel.o
1312
snd-hda-codec-senarytech-y := senarytech.o
@@ -26,7 +25,6 @@ obj-$(CONFIG_SND_HDA_CODEC_CM9825) += snd-hda-codec-cm9825.o
2625
obj-$(CONFIG_SND_HDA_CODEC_ANALOG) += snd-hda-codec-analog.o
2726
obj-$(CONFIG_SND_HDA_CODEC_CA0110) += snd-hda-codec-ca0110.o
2827
obj-$(CONFIG_SND_HDA_CODEC_CA0132) += snd-hda-codec-ca0132.o
29-
obj-$(CONFIG_SND_HDA_CODEC_CMEDIA) += snd-hda-codec-cmedia.o
3028
obj-$(CONFIG_SND_HDA_CODEC_CONEXANT) += snd-hda-codec-conexant.o
3129
obj-$(CONFIG_SND_HDA_CODEC_SIGMATEL) += snd-hda-codec-idt.o
3230
obj-$(CONFIG_SND_HDA_CODEC_SENARYTECH) += snd-hda-codec-senarytech.o

sound/hda/codecs/conexant.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1175,6 +1175,7 @@ static void add_cx5051_fake_mutes(struct hda_codec *codec)
11751175
static int cx_probe(struct hda_codec *codec, const struct hda_device_id *id)
11761176
{
11771177
struct conexant_spec *spec;
1178+
struct hda_jack_callback *callback;
11781179
int err;
11791180

11801181
codec_info(codec, "%s: BIOS auto-probing.\n", codec->core.chip_name);
@@ -1190,7 +1191,12 @@ static int cx_probe(struct hda_codec *codec, const struct hda_device_id *id)
11901191
case 0x14f11f86:
11911192
case 0x14f11f87:
11921193
spec->is_cx11880_sn6140 = true;
1193-
snd_hda_jack_detect_enable_callback(codec, 0x19, cx_update_headset_mic_vref);
1194+
callback = snd_hda_jack_detect_enable_callback(codec, 0x19,
1195+
cx_update_headset_mic_vref);
1196+
if (IS_ERR(callback)) {
1197+
err = PTR_ERR(callback);
1198+
goto error;
1199+
}
11941200
break;
11951201
}
11961202

sound/hda/codecs/realtek/alc269.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3694,6 +3694,17 @@ static void alc287_fixup_lenovo_thinkpad_with_alc1318(struct hda_codec *codec,
36943694
spec->power_hook = alc287_s4_power_gpio3_default;
36953695
spec->gen.pcm_playback_hook = alc287_alc1318_playback_pcm_hook;
36963696
}
3697+
3698+
static void alc287_fixup_tb_vmaster_led(struct hda_codec *codec,
3699+
const struct hda_fixup *fix, int action)
3700+
{
3701+
struct alc_spec *spec = codec->spec;
3702+
3703+
if (action == HDA_FIXUP_ACT_PRE_PROBE)
3704+
spec->gen.vmaster_mute_led = 1;
3705+
3706+
alc287_fixup_bind_dacs(codec, fix, action);
3707+
}
36973708
/* GPIO2: mute led GPIO3: micmute led */
36983709
static void alc245_tas2781_spi_hp_fixup_muteled(struct hda_codec *codec,
36993710
const struct hda_fixup *fix, int action)
@@ -6448,7 +6459,7 @@ static const struct hda_fixup alc269_fixups[] = {
64486459
},
64496460
[ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD] = {
64506461
.type = HDA_FIXUP_FUNC,
6451-
.v.func = alc287_fixup_bind_dacs,
6462+
.v.func = alc287_fixup_tb_vmaster_led,
64526463
.chained = true,
64536464
.chain_id = ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI,
64546465
},
@@ -6717,6 +6728,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
67176728
SND_PCI_QUIRK(0x1025, 0x159c, "Acer Nitro 5 AN515-58", ALC2XX_FIXUP_HEADSET_MIC),
67186729
SND_PCI_QUIRK(0x1025, 0x1597, "Acer Nitro 5 AN517-55", ALC2XX_FIXUP_HEADSET_MIC),
67196730
SND_PCI_QUIRK(0x1025, 0x160e, "Acer PT316-51S", ALC2XX_FIXUP_HEADSET_MIC),
6731+
SND_PCI_QUIRK(0x1025, 0x1640, "Acer Aspire A315-44P", ALC256_FIXUP_ACER_SFG16_MICMUTE_LED),
67206732
SND_PCI_QUIRK(0x1025, 0x1679, "Acer Nitro 16 AN16-41", ALC2XX_FIXUP_HEADSET_MIC),
67216733
SND_PCI_QUIRK(0x1025, 0x169a, "Acer Swift SFG16", ALC256_FIXUP_ACER_SFG16_MICMUTE_LED),
67226734
SND_PCI_QUIRK(0x1025, 0x171e, "Acer Nitro ANV15-51", ALC245_FIXUP_ACER_MICMUTE_LED),

sound/hda/codecs/side-codecs/cs35l56_hda.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -180,11 +180,15 @@ static int cs35l56_hda_mixer_get(struct snd_kcontrol *kcontrol,
180180
{
181181
struct cs35l56_hda *cs35l56 = snd_kcontrol_chip(kcontrol);
182182
unsigned int reg_val;
183-
int i;
183+
int i, ret;
184184

185185
cs35l56_hda_wait_dsp_ready(cs35l56);
186186

187-
regmap_read(cs35l56->base.regmap, kcontrol->private_value, &reg_val);
187+
ret = regmap_read(cs35l56->base.regmap, kcontrol->private_value,
188+
&reg_val);
189+
if (ret)
190+
return ret;
191+
188192
reg_val &= CS35L56_ASP_TXn_SRC_MASK;
189193

190194
for (i = 0; i < CS35L56_NUM_INPUT_SRC; ++i) {
@@ -203,15 +207,20 @@ static int cs35l56_hda_mixer_put(struct snd_kcontrol *kcontrol,
203207
struct cs35l56_hda *cs35l56 = snd_kcontrol_chip(kcontrol);
204208
unsigned int item = ucontrol->value.enumerated.item[0];
205209
bool changed;
210+
int ret;
206211

207212
if (item >= CS35L56_NUM_INPUT_SRC)
208213
return -EINVAL;
209214

210215
cs35l56_hda_wait_dsp_ready(cs35l56);
211216

212-
regmap_update_bits_check(cs35l56->base.regmap, kcontrol->private_value,
213-
CS35L56_INPUT_MASK, cs35l56_tx_input_values[item],
214-
&changed);
217+
ret = regmap_update_bits_check(cs35l56->base.regmap,
218+
kcontrol->private_value,
219+
CS35L56_INPUT_MASK,
220+
cs35l56_tx_input_values[item],
221+
&changed);
222+
if (ret)
223+
return ret;
215224

216225
return changed;
217226
}
@@ -967,6 +976,7 @@ static int cs35l56_hda_system_resume(struct device *dev)
967976
static int cs35l56_hda_fixup_yoga9(struct cs35l56_hda *cs35l56, int *bus_addr)
968977
{
969978
/* The cirrus,dev-index property has the wrong values */
979+
cs35l56->num_amps = 2;
970980
switch (*bus_addr) {
971981
case 0x30:
972982
cs35l56->index = 1;
@@ -1016,7 +1026,6 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id)
10161026
char hid_string[8];
10171027
struct acpi_device *adev;
10181028
const char *property, *sub;
1019-
size_t nval;
10201029
int i, ret;
10211030

10221031
/*
@@ -1052,13 +1061,14 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id)
10521061
ret = -EINVAL;
10531062
goto err;
10541063
}
1055-
nval = ret;
1064+
cs35l56->num_amps = ret;
10561065

1057-
ret = device_property_read_u32_array(cs35l56->base.dev, property, values, nval);
1066+
ret = device_property_read_u32_array(cs35l56->base.dev, property, values,
1067+
cs35l56->num_amps);
10581068
if (ret)
10591069
goto err;
10601070

1061-
for (i = 0; i < nval; i++) {
1071+
for (i = 0; i < cs35l56->num_amps; i++) {
10621072
if (values[i] == id) {
10631073
cs35l56->index = i;
10641074
break;
@@ -1081,7 +1091,8 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id)
10811091
"Read ACPI _SUB failed(%ld): fallback to generic firmware\n",
10821092
PTR_ERR(sub));
10831093
} else {
1084-
ret = cirrus_scodec_get_speaker_id(cs35l56->base.dev, cs35l56->index, nval, -1);
1094+
ret = cirrus_scodec_get_speaker_id(cs35l56->base.dev, cs35l56->index,
1095+
cs35l56->num_amps, -1);
10851096
if (ret == -ENOENT) {
10861097
cs35l56->system_name = sub;
10871098
} else if (ret >= 0) {

sound/hda/codecs/side-codecs/cs35l56_hda.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ struct cs35l56_hda {
2626
struct work_struct dsp_work;
2727

2828
int index;
29+
int num_amps;
2930
const char *system_name;
3031
const char *amp_name;
3132

sound/hda/codecs/side-codecs/tas2781_hda_spi.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,18 @@ static int tasdevice_spi_dev_update_bits(struct tasdevice_priv *tas_priv,
132132
int ret, val;
133133

134134
/*
135-
* In our TAS2781 SPI mode, read/write was masked in last bit of
136-
* address, it cause regmap_update_bits() not work as expected.
135+
* In TAS2781 SPI mode, when accessing non-book-zero or page numbers
136+
* greater than 1 in book 0, an additional byte must be read. The
137+
* first byte in such cases is a dummy byte and should be ignored.
137138
*/
138-
ret = tasdevice_dev_read(tas_priv, chn, reg, &val);
139+
if ((TASDEVICE_BOOK_ID(reg) > 0) || (TASDEVICE_PAGE_ID(reg) > 1)) {
140+
unsigned char buf[2];
141+
142+
ret = tasdevice_dev_bulk_read(tas_priv, chn, reg, buf, 2);
143+
val = buf[1];
144+
} else {
145+
ret = tasdevice_dev_read(tas_priv, chn, reg, &val);
146+
}
139147
if (ret < 0) {
140148
dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
141149
return ret;

sound/hda/core/hdmi_chmap.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -353,13 +353,16 @@ static void hdmi_std_setup_channel_mapping(struct hdac_chmap *chmap,
353353
if (hdmi_channel_mapping[ca][1] == 0) {
354354
int hdmi_slot = 0;
355355
/* fill actual channel mappings in ALSA channel (i) order */
356-
for (i = 0; i < ch_alloc->channels; i++) {
357-
while (!WARN_ON(hdmi_slot >= 8) &&
358-
!ch_alloc->speakers[7 - hdmi_slot])
359-
hdmi_slot++; /* skip zero slots */
356+
for (i = 0; i < ch_alloc->channels && hdmi_slot < 8; i++) {
357+
while (!ch_alloc->speakers[7 - hdmi_slot]) {
358+
/* skip zero slots */
359+
if (++hdmi_slot >= 8)
360+
goto out;
361+
}
360362

361363
hdmi_channel_mapping[ca][i] = (i << 4) | hdmi_slot++;
362364
}
365+
out:
363366
/* fill the rest of the slots with ALSA channel 0xf */
364367
for (hdmi_slot = 0; hdmi_slot < 8; hdmi_slot++)
365368
if (!ch_alloc->speakers[7 - hdmi_slot])

sound/soc/amd/acp/acp-legacy-mach.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ static int acp_asoc_probe(struct platform_device *pdev)
174174
acp_card_drvdata->acp_rev = mach->mach_params.subsystem_rev;
175175

176176
dmi_id = dmi_first_match(acp_quirk_table);
177-
if (dmi_id && dmi_id->driver_data)
177+
if (dmi_id && dmi_id->driver_data == (void *)QUIRK_TDM_MODE_ENABLE)
178178
acp_card_drvdata->tdm_mode = dmi_id->driver_data;
179179

180180
ret = acp_legacy_dai_links_create(card);

0 commit comments

Comments
 (0)