Skip to content

Commit fe1544d

Browse files
committed
Merge tag 'asoc-fix-v6.14-rc4' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Fixes for v6.14 More driver specific fixes, the firmware change is part of fixing the race conditions in the Cirrus driver.
2 parents c6557cc + 9da0ed4 commit fe1544d

File tree

11 files changed

+142
-51
lines changed

11 files changed

+142
-51
lines changed

drivers/firmware/cirrus/cs_dsp.c

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1609,8 +1609,8 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
16091609
goto out_fw;
16101610
}
16111611

1612-
ret = regmap_raw_write_async(regmap, reg, buf->buf,
1613-
le32_to_cpu(region->len));
1612+
ret = regmap_raw_write(regmap, reg, buf->buf,
1613+
le32_to_cpu(region->len));
16141614
if (ret != 0) {
16151615
cs_dsp_err(dsp,
16161616
"%s.%d: Failed to write %d bytes at %d in %s: %d\n",
@@ -1625,20 +1625,13 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
16251625
regions++;
16261626
}
16271627

1628-
ret = regmap_async_complete(regmap);
1629-
if (ret != 0) {
1630-
cs_dsp_err(dsp, "Failed to complete async write: %d\n", ret);
1631-
goto out_fw;
1632-
}
1633-
16341628
if (pos > firmware->size)
16351629
cs_dsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
16361630
file, regions, pos - firmware->size);
16371631

16381632
cs_dsp_debugfs_save_wmfwname(dsp, file);
16391633

16401634
out_fw:
1641-
regmap_async_complete(regmap);
16421635
cs_dsp_buf_free(&buf_list);
16431636

16441637
if (ret == -EOVERFLOW)
@@ -2326,8 +2319,8 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
23262319
cs_dsp_dbg(dsp, "%s.%d: Writing %d bytes at %x\n",
23272320
file, blocks, le32_to_cpu(blk->len),
23282321
reg);
2329-
ret = regmap_raw_write_async(regmap, reg, buf->buf,
2330-
le32_to_cpu(blk->len));
2322+
ret = regmap_raw_write(regmap, reg, buf->buf,
2323+
le32_to_cpu(blk->len));
23312324
if (ret != 0) {
23322325
cs_dsp_err(dsp,
23332326
"%s.%d: Failed to write to %x in %s: %d\n",
@@ -2339,18 +2332,13 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
23392332
blocks++;
23402333
}
23412334

2342-
ret = regmap_async_complete(regmap);
2343-
if (ret != 0)
2344-
cs_dsp_err(dsp, "Failed to complete async write: %d\n", ret);
2345-
23462335
if (pos > firmware->size)
23472336
cs_dsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
23482337
file, blocks, pos - firmware->size);
23492338

23502339
cs_dsp_debugfs_save_binname(dsp, file);
23512340

23522341
out_fw:
2353-
regmap_async_complete(regmap);
23542342
cs_dsp_buf_free(&buf_list);
23552343

23562344
if (ret == -EOVERFLOW)
@@ -2561,8 +2549,8 @@ static int cs_dsp_adsp2_enable_core(struct cs_dsp *dsp)
25612549
{
25622550
int ret;
25632551

2564-
ret = regmap_update_bits_async(dsp->regmap, dsp->base + ADSP2_CONTROL,
2565-
ADSP2_SYS_ENA, ADSP2_SYS_ENA);
2552+
ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2553+
ADSP2_SYS_ENA, ADSP2_SYS_ENA);
25662554
if (ret != 0)
25672555
return ret;
25682556

include/sound/cs35l56.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/firmware/cirrus/cs_dsp.h>
1313
#include <linux/regulator/consumer.h>
1414
#include <linux/regmap.h>
15+
#include <linux/spi/spi.h>
1516
#include <sound/cs-amp-lib.h>
1617

1718
#define CS35L56_DEVID 0x0000000
@@ -61,6 +62,7 @@
6162
#define CS35L56_IRQ1_MASK_8 0x000E0AC
6263
#define CS35L56_IRQ1_MASK_18 0x000E0D4
6364
#define CS35L56_IRQ1_MASK_20 0x000E0DC
65+
#define CS35L56_DSP_MBOX_1_RAW 0x0011000
6466
#define CS35L56_DSP_VIRTUAL1_MBOX_1 0x0011020
6567
#define CS35L56_DSP_VIRTUAL1_MBOX_2 0x0011024
6668
#define CS35L56_DSP_VIRTUAL1_MBOX_3 0x0011028
@@ -224,6 +226,7 @@
224226
#define CS35L56_HALO_STATE_SHUTDOWN 1
225227
#define CS35L56_HALO_STATE_BOOT_DONE 2
226228

229+
#define CS35L56_MBOX_CMD_PING 0x0A000000
227230
#define CS35L56_MBOX_CMD_AUDIO_PLAY 0x0B000001
228231
#define CS35L56_MBOX_CMD_AUDIO_PAUSE 0x0B000002
229232
#define CS35L56_MBOX_CMD_AUDIO_REINIT 0x0B000003
@@ -254,6 +257,16 @@
254257
#define CS35L56_NUM_BULK_SUPPLIES 3
255258
#define CS35L56_NUM_DSP_REGIONS 5
256259

260+
/* Additional margin for SYSTEM_RESET to control port ready on SPI */
261+
#define CS35L56_SPI_RESET_TO_PORT_READY_US (CS35L56_CONTROL_PORT_READY_US + 2500)
262+
263+
struct cs35l56_spi_payload {
264+
__be32 addr;
265+
__be16 pad;
266+
__be32 value;
267+
} __packed;
268+
static_assert(sizeof(struct cs35l56_spi_payload) == 10);
269+
257270
struct cs35l56_base {
258271
struct device *dev;
259272
struct regmap *regmap;
@@ -269,13 +282,31 @@ struct cs35l56_base {
269282
s8 cal_index;
270283
struct cirrus_amp_cal_data cal_data;
271284
struct gpio_desc *reset_gpio;
285+
struct cs35l56_spi_payload *spi_payload_buf;
272286
};
273287

274288
static inline bool cs35l56_is_otp_register(unsigned int reg)
275289
{
276290
return (reg >> 16) == 3;
277291
}
278292

293+
static inline int cs35l56_init_config_for_spi(struct cs35l56_base *cs35l56,
294+
struct spi_device *spi)
295+
{
296+
cs35l56->spi_payload_buf = devm_kzalloc(&spi->dev,
297+
sizeof(*cs35l56->spi_payload_buf),
298+
GFP_KERNEL | GFP_DMA);
299+
if (!cs35l56->spi_payload_buf)
300+
return -ENOMEM;
301+
302+
return 0;
303+
}
304+
305+
static inline bool cs35l56_is_spi(struct cs35l56_base *cs35l56)
306+
{
307+
return IS_ENABLED(CONFIG_SPI_MASTER) && !!cs35l56->spi_payload_buf;
308+
}
309+
279310
extern const struct regmap_config cs35l56_regmap_i2c;
280311
extern const struct regmap_config cs35l56_regmap_spi;
281312
extern const struct regmap_config cs35l56_regmap_sdw;

sound/pci/hda/cs35l56_hda_spi.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ static int cs35l56_hda_spi_probe(struct spi_device *spi)
2222
return -ENOMEM;
2323

2424
cs35l56->base.dev = &spi->dev;
25+
ret = cs35l56_init_config_for_spi(&cs35l56->base, spi);
26+
if (ret)
27+
return ret;
2528

2629
#ifdef CS35L56_WAKE_HOLD_TIME_US
2730
cs35l56->base.can_hibernate = true;

sound/soc/codecs/cs35l56-shared.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/gpio/consumer.h>
1111
#include <linux/regmap.h>
1212
#include <linux/regulator/consumer.h>
13+
#include <linux/spi/spi.h>
1314
#include <linux/types.h>
1415
#include <sound/cs-amp-lib.h>
1516

@@ -303,6 +304,79 @@ void cs35l56_wait_min_reset_pulse(void)
303304
}
304305
EXPORT_SYMBOL_NS_GPL(cs35l56_wait_min_reset_pulse, "SND_SOC_CS35L56_SHARED");
305306

307+
static const struct {
308+
u32 addr;
309+
u32 value;
310+
} cs35l56_spi_system_reset_stages[] = {
311+
{ .addr = CS35L56_DSP_VIRTUAL1_MBOX_1, .value = CS35L56_MBOX_CMD_SYSTEM_RESET },
312+
/* The next write is necessary to delimit the soft reset */
313+
{ .addr = CS35L56_DSP_MBOX_1_RAW, .value = CS35L56_MBOX_CMD_PING },
314+
};
315+
316+
static void cs35l56_spi_issue_bus_locked_reset(struct cs35l56_base *cs35l56_base,
317+
struct spi_device *spi)
318+
{
319+
struct cs35l56_spi_payload *buf = cs35l56_base->spi_payload_buf;
320+
struct spi_transfer t = {
321+
.tx_buf = buf,
322+
.len = sizeof(*buf),
323+
};
324+
struct spi_message m;
325+
int i, ret;
326+
327+
for (i = 0; i < ARRAY_SIZE(cs35l56_spi_system_reset_stages); i++) {
328+
buf->addr = cpu_to_be32(cs35l56_spi_system_reset_stages[i].addr);
329+
buf->value = cpu_to_be32(cs35l56_spi_system_reset_stages[i].value);
330+
spi_message_init_with_transfers(&m, &t, 1);
331+
ret = spi_sync_locked(spi, &m);
332+
if (ret)
333+
dev_warn(cs35l56_base->dev, "spi_sync failed: %d\n", ret);
334+
335+
usleep_range(CS35L56_SPI_RESET_TO_PORT_READY_US,
336+
2 * CS35L56_SPI_RESET_TO_PORT_READY_US);
337+
}
338+
}
339+
340+
static void cs35l56_spi_system_reset(struct cs35l56_base *cs35l56_base)
341+
{
342+
struct spi_device *spi = to_spi_device(cs35l56_base->dev);
343+
unsigned int val;
344+
int read_ret, ret;
345+
346+
/*
347+
* There must not be any other SPI bus activity while the amp is
348+
* soft-resetting.
349+
*/
350+
ret = spi_bus_lock(spi->controller);
351+
if (ret) {
352+
dev_warn(cs35l56_base->dev, "spi_bus_lock failed: %d\n", ret);
353+
return;
354+
}
355+
356+
cs35l56_spi_issue_bus_locked_reset(cs35l56_base, spi);
357+
spi_bus_unlock(spi->controller);
358+
359+
/*
360+
* Check firmware boot by testing for a response in MBOX_2.
361+
* HALO_STATE cannot be trusted yet because the reset sequence
362+
* can leave it with stale state. But MBOX is reset.
363+
* The regmap must remain in cache-only until the chip has
364+
* booted, so use a bypassed read.
365+
*/
366+
ret = read_poll_timeout(regmap_read_bypassed, read_ret,
367+
(val > 0) && (val < 0xffffffff),
368+
CS35L56_HALO_STATE_POLL_US,
369+
CS35L56_HALO_STATE_TIMEOUT_US,
370+
false,
371+
cs35l56_base->regmap,
372+
CS35L56_DSP_VIRTUAL1_MBOX_2,
373+
&val);
374+
if (ret) {
375+
dev_err(cs35l56_base->dev, "SPI reboot timed out(%d): MBOX2=%#x\n",
376+
read_ret, val);
377+
}
378+
}
379+
306380
static const struct reg_sequence cs35l56_system_reset_seq[] = {
307381
REG_SEQ0(CS35L56_DSP1_HALO_STATE, 0),
308382
REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET),
@@ -315,6 +389,12 @@ void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire)
315389
* accesses other than the controlled system reset sequence below.
316390
*/
317391
regcache_cache_only(cs35l56_base->regmap, true);
392+
393+
if (cs35l56_is_spi(cs35l56_base)) {
394+
cs35l56_spi_system_reset(cs35l56_base);
395+
return;
396+
}
397+
318398
regmap_multi_reg_write_bypassed(cs35l56_base->regmap,
319399
cs35l56_system_reset_seq,
320400
ARRAY_SIZE(cs35l56_system_reset_seq));

sound/soc/codecs/cs35l56-spi.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ static int cs35l56_spi_probe(struct spi_device *spi)
3333

3434
cs35l56->base.dev = &spi->dev;
3535
cs35l56->base.can_hibernate = true;
36+
ret = cs35l56_init_config_for_spi(&cs35l56->base, spi);
37+
if (ret)
38+
return ret;
3639

3740
ret = cs35l56_common_probe(cs35l56);
3841
if (ret != 0)

sound/soc/codecs/es8328.c

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,6 @@ static const struct snd_kcontrol_new es8328_right_line_controls =
233233

234234
/* Left Mixer */
235235
static const struct snd_kcontrol_new es8328_left_mixer_controls[] = {
236-
SOC_DAPM_SINGLE("Playback Switch", ES8328_DACCONTROL17, 7, 1, 0),
237236
SOC_DAPM_SINGLE("Left Bypass Switch", ES8328_DACCONTROL17, 6, 1, 0),
238237
SOC_DAPM_SINGLE("Right Playback Switch", ES8328_DACCONTROL18, 7, 1, 0),
239238
SOC_DAPM_SINGLE("Right Bypass Switch", ES8328_DACCONTROL18, 6, 1, 0),
@@ -243,7 +242,6 @@ static const struct snd_kcontrol_new es8328_left_mixer_controls[] = {
243242
static const struct snd_kcontrol_new es8328_right_mixer_controls[] = {
244243
SOC_DAPM_SINGLE("Left Playback Switch", ES8328_DACCONTROL19, 7, 1, 0),
245244
SOC_DAPM_SINGLE("Left Bypass Switch", ES8328_DACCONTROL19, 6, 1, 0),
246-
SOC_DAPM_SINGLE("Playback Switch", ES8328_DACCONTROL20, 7, 1, 0),
247245
SOC_DAPM_SINGLE("Right Bypass Switch", ES8328_DACCONTROL20, 6, 1, 0),
248246
};
249247

@@ -336,10 +334,10 @@ static const struct snd_soc_dapm_widget es8328_dapm_widgets[] = {
336334
SND_SOC_DAPM_DAC("Left DAC", "Left Playback", ES8328_DACPOWER,
337335
ES8328_DACPOWER_LDAC_OFF, 1),
338336

339-
SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0,
337+
SND_SOC_DAPM_MIXER("Left Mixer", ES8328_DACCONTROL17, 7, 0,
340338
&es8328_left_mixer_controls[0],
341339
ARRAY_SIZE(es8328_left_mixer_controls)),
342-
SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0,
340+
SND_SOC_DAPM_MIXER("Right Mixer", ES8328_DACCONTROL20, 7, 0,
343341
&es8328_right_mixer_controls[0],
344342
ARRAY_SIZE(es8328_right_mixer_controls)),
345343

@@ -418,19 +416,14 @@ static const struct snd_soc_dapm_route es8328_dapm_routes[] = {
418416
{ "Right Line Mux", "PGA", "Right PGA Mux" },
419417
{ "Right Line Mux", "Differential", "Differential Mux" },
420418

421-
{ "Left Out 1", NULL, "Left DAC" },
422-
{ "Right Out 1", NULL, "Right DAC" },
423-
{ "Left Out 2", NULL, "Left DAC" },
424-
{ "Right Out 2", NULL, "Right DAC" },
425-
426-
{ "Left Mixer", "Playback Switch", "Left DAC" },
419+
{ "Left Mixer", NULL, "Left DAC" },
427420
{ "Left Mixer", "Left Bypass Switch", "Left Line Mux" },
428421
{ "Left Mixer", "Right Playback Switch", "Right DAC" },
429422
{ "Left Mixer", "Right Bypass Switch", "Right Line Mux" },
430423

431424
{ "Right Mixer", "Left Playback Switch", "Left DAC" },
432425
{ "Right Mixer", "Left Bypass Switch", "Left Line Mux" },
433-
{ "Right Mixer", "Playback Switch", "Right DAC" },
426+
{ "Right Mixer", NULL, "Right DAC" },
434427
{ "Right Mixer", "Right Bypass Switch", "Right Line Mux" },
435428

436429
{ "DAC DIG", NULL, "DAC STM" },

sound/soc/fsl/fsl_sai.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -994,10 +994,10 @@ static struct snd_soc_dai_driver fsl_sai_dai_template[] = {
994994
{
995995
.name = "sai-tx",
996996
.playback = {
997-
.stream_name = "CPU-Playback",
997+
.stream_name = "SAI-Playback",
998998
.channels_min = 1,
999999
.channels_max = 32,
1000-
.rate_min = 8000,
1000+
.rate_min = 8000,
10011001
.rate_max = 2822400,
10021002
.rates = SNDRV_PCM_RATE_KNOT,
10031003
.formats = FSL_SAI_FORMATS,
@@ -1007,7 +1007,7 @@ static struct snd_soc_dai_driver fsl_sai_dai_template[] = {
10071007
{
10081008
.name = "sai-rx",
10091009
.capture = {
1010-
.stream_name = "CPU-Capture",
1010+
.stream_name = "SAI-Capture",
10111011
.channels_min = 1,
10121012
.channels_max = 32,
10131013
.rate_min = 8000,

sound/soc/fsl/imx-audmix.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ static const struct snd_soc_ops imx_audmix_be_ops = {
119119
static const char *name[][3] = {
120120
{"HiFi-AUDMIX-FE-0", "HiFi-AUDMIX-FE-1", "HiFi-AUDMIX-FE-2"},
121121
{"sai-tx", "sai-tx", "sai-rx"},
122-
{"AUDMIX-Playback-0", "AUDMIX-Playback-1", "CPU-Capture"},
123-
{"CPU-Playback", "CPU-Playback", "AUDMIX-Capture-0"},
122+
{"AUDMIX-Playback-0", "AUDMIX-Playback-1", "SAI-Capture"},
123+
{"SAI-Playback", "SAI-Playback", "AUDMIX-Capture-0"},
124124
};
125125

126126
static int imx_audmix_probe(struct platform_device *pdev)

sound/soc/intel/boards/sof_sdw.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,9 @@ static int create_sdw_dailink(struct snd_soc_card *card,
803803
int *be_id, struct snd_soc_codec_conf **codec_conf)
804804
{
805805
struct device *dev = card->dev;
806+
struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev);
806807
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
808+
struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
807809
struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private;
808810
struct asoc_sdw_endpoint *sof_end;
809811
int stream;
@@ -900,6 +902,11 @@ static int create_sdw_dailink(struct snd_soc_card *card,
900902

901903
codecs[j].name = sof_end->codec_name;
902904
codecs[j].dai_name = sof_end->dai_info->dai_name;
905+
if (sof_end->dai_info->dai_type == SOC_SDW_DAI_TYPE_MIC &&
906+
mach_params->dmic_num > 0) {
907+
dev_warn(dev,
908+
"Both SDW DMIC and PCH DMIC are present, if incorrect, please set kernel params snd_sof_intel_hda_generic dmic_num=0 to disable PCH DMIC\n");
909+
}
903910
j++;
904911
}
905912

sound/soc/sof/intel/hda.c

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,22 +1312,8 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
13121312
/* report to machine driver if any DMICs are found */
13131313
mach->mach_params.dmic_num = check_dmic_num(sdev);
13141314

1315-
if (sdw_mach_found) {
1316-
/*
1317-
* DMICs use up to 4 pins and are typically pin-muxed with SoundWire
1318-
* link 2 and 3, or link 1 and 2, thus we only try to enable dmics
1319-
* if all conditions are true:
1320-
* a) 2 or fewer links are used by SoundWire
1321-
* b) the NHLT table reports the presence of microphones
1322-
*/
1323-
if (hweight_long(mach->link_mask) <= 2)
1324-
dmic_fixup = true;
1325-
else
1326-
mach->mach_params.dmic_num = 0;
1327-
} else {
1328-
if (mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER)
1329-
dmic_fixup = true;
1330-
}
1315+
if (sdw_mach_found || mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER)
1316+
dmic_fixup = true;
13311317

13321318
if (tplg_fixup &&
13331319
dmic_fixup &&

0 commit comments

Comments
 (0)