From 8d01c3c73cefbb5bacffe804427daed3e6051435 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 10 May 2019 11:38:03 -0500 Subject: ASoC: SOF: nocodec: fix undefined reference The nocodec option can be selected individually, leading to the following issue: sound/soc/sof/core.o: In function `snd_sof_device_probe': core.c:(.text+0x4af): undefined reference to `sof_nocodec_setup' Fix by selecting the SND_SOF_NOCODEC option as needed. Reported-by: Hulk Robot Reported-by: YueHaibing Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/Kconfig | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index b204c65698f9..a9a1d502daae 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -44,7 +44,10 @@ config SND_SOC_SOF_OPTIONS if SND_SOC_SOF_OPTIONS config SND_SOC_SOF_NOCODEC - tristate "SOF nocodec mode Support" + tristate + +config SND_SOC_SOF_NOCODEC_SUPPORT + bool "SOF nocodec mode support" help This adds support for a dummy/nocodec machine driver fallback option if no known codec is detected. This is typically only @@ -80,7 +83,7 @@ if SND_SOC_SOF_DEBUG config SND_SOC_SOF_FORCE_NOCODEC_MODE bool "SOF force nocodec Mode" - depends on SND_SOC_SOF_NOCODEC + depends on SND_SOC_SOF_NOCODEC_SUPPORT help This forces SOF to use dummy/nocodec as machine driver, even though there is a codec detected on the real platform. This is @@ -135,6 +138,7 @@ endif ## SND_SOC_SOF_OPTIONS config SND_SOC_SOF tristate select SND_SOC_TOPOLOGY + select SND_SOC_SOF_NOCODEC if SND_SOC_SOF_NOCODEC_SUPPORT help This option is not user-selectable but automagically handled by 'select' statements at a higher level -- cgit From a69270d8bfeb35fc89d047ea6db803cd75a74f12 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 9 May 2019 15:10:23 -0500 Subject: ASoC: SOF: fix race in FW boot timeout handling A race condition exists in handling firmware boot timeout. If FW sends FW_READY just after boot timeout has expired in driver, a kernel exception will result as FW_READY handler will be run while the state is still being cleaned up in snd_sof_run_firmware(). Avoid the race by setting boot_complete also in the error case. Signed-off-by: Kai Vehmanen Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/loader.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 81c7452aae17..628fae552442 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -372,6 +372,8 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev) msecs_to_jiffies(sdev->boot_timeout)); if (ret == 0) { dev_err(sdev->dev, "error: firmware boot failure\n"); + /* after this point FW_READY msg should be ignored */ + sdev->boot_complete = true; snd_sof_dsp_dbg_dump(sdev, SOF_DBG_REGS | SOF_DBG_MBOX | SOF_DBG_TEXT | SOF_DBG_PCI); return -EIO; -- cgit From 8199a12037892f01e2cf5bedf5fbf08dff11b282 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Thu, 9 May 2019 15:10:25 -0500 Subject: ASoC: SOF: fix error in verbose ipc command parsing Remove the erroneous addition of "SET_VALUE" to the GLB IPC command string. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index f0b9d3c53f6f..894e68cbd69d 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -115,7 +115,7 @@ static void ipc_log_header(struct device *dev, u8 *text, u32 cmd) } break; case SOF_IPC_GLB_COMP_MSG: - str = "GLB_COMP_MSG: SET_VALUE"; + str = "GLB_COMP_MSG"; switch (type) { case SOF_IPC_COMP_SET_VALUE: str2 = "SET_VALUE"; break; -- cgit From f3df05c805983427319eddc2411a2105ee1757cf Mon Sep 17 00:00:00 2001 From: Matt Flax Date: Wed, 8 May 2019 16:33:13 +1000 Subject: ASoC : cs4265 : readable register too low The cs4265_readable_register function stopped short of the maximum register. An example bug is taken from : https://github.com/Audio-Injector/Ultra/issues/25 Where alsactl store fails with : Cannot read control '2,0,0,C Data Buffer,0': Input/output error This patch fixes the bug by setting the cs4265 to have readable registers up to the maximum hardware register CS4265_MAX_REGISTER. Signed-off-by: Matt Flax Reviewed-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/cs4265.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c index ab27d2b94d02..c0190ec59e74 100644 --- a/sound/soc/codecs/cs4265.c +++ b/sound/soc/codecs/cs4265.c @@ -60,7 +60,7 @@ static const struct reg_default cs4265_reg_defaults[] = { static bool cs4265_readable_register(struct device *dev, unsigned int reg) { switch (reg) { - case CS4265_CHIP_ID ... CS4265_SPDIF_CTL2: + case CS4265_CHIP_ID ... CS4265_MAX_REGISTER: return true; default: return false; -- cgit From a8dee20d792432740509237943700fbcfc230bad Mon Sep 17 00:00:00 2001 From: Viorel Suman Date: Thu, 9 May 2019 13:30:36 +0000 Subject: ASoC: ak4458: add return value for ak4458_probe AK4458 is probed successfully even if AK4458 is not present - this is caused by probe function returning no error on i2c access failure. Return an error on probe if i2c access has failed. Signed-off-by: Shengjiu Wang Signed-off-by: Viorel Suman Signed-off-by: Mark Brown --- sound/soc/codecs/ak4458.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/ak4458.c b/sound/soc/codecs/ak4458.c index eab7c76cfcd9..4c5c3ec92609 100644 --- a/sound/soc/codecs/ak4458.c +++ b/sound/soc/codecs/ak4458.c @@ -536,9 +536,10 @@ static void ak4458_power_on(struct ak4458_priv *ak4458) } } -static void ak4458_init(struct snd_soc_component *component) +static int ak4458_init(struct snd_soc_component *component) { struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component); + int ret; /* External Mute ON */ if (ak4458->mute_gpiod) @@ -546,21 +547,21 @@ static void ak4458_init(struct snd_soc_component *component) ak4458_power_on(ak4458); - snd_soc_component_update_bits(component, AK4458_00_CONTROL1, + ret = snd_soc_component_update_bits(component, AK4458_00_CONTROL1, 0x80, 0x80); /* ACKS bit = 1; 10000000 */ + if (ret < 0) + return ret; - ak4458_rstn_control(component, 1); + return ak4458_rstn_control(component, 1); } static int ak4458_probe(struct snd_soc_component *component) { struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component); - ak4458_init(component); - ak4458->fs = 48000; - return 0; + return ak4458_init(component); } static void ak4458_remove(struct snd_soc_component *component) -- cgit From 5087a8f17df868601cd7568299e91c28086d2b45 Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Wed, 8 May 2019 10:32:41 +0800 Subject: ASoC: soc-pcm: BE dai needs prepare when pause release after resume If playback/capture is paused and system enters S3, after system returns from suspend, BE dai needs to call prepare() callback when playback/capture is released from pause if RESUME_INFO flag is not set. Currently, the dpcm_be_dai_prepare() function will block calling prepare() if the pcm is in SND_SOC_DPCM_STATE_PAUSED state. This will cause the following test case fail if the pcm uses BE: playback -> pause -> S3 suspend -> S3 resume -> pause release The playback may exit abnormally when pause is released because the BE dai prepare() is not called. This patch allows dpcm_be_dai_prepare() to call dai prepare() callback in SND_SOC_DPCM_STATE_PAUSED state. Signed-off-by: Libin Yang Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 74695355c1f8..7347e6f99248 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2471,7 +2471,8 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream) if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) && (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) && - (be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND)) + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND) && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED)) continue; dev_dbg(be->dev, "ASoC: prepare BE %s\n", -- cgit From 176a11834b65ec35e3b7a953f87fb9cc41309497 Mon Sep 17 00:00:00 2001 From: Viorel Suman Date: Mon, 13 May 2019 10:02:42 +0000 Subject: ASoC: ak4458: rstn_control - return a non-zero on error only snd_soc_component_update_bits() may return 1 if operation was successful and the value of the register changed. Return a non-zero in ak4458_rstn_control for an error only. Signed-off-by: Shengjiu Wang Signed-off-by: Viorel Suman Reviewed-by: Daniel Baluta Signed-off-by: Mark Brown --- sound/soc/codecs/ak4458.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/ak4458.c b/sound/soc/codecs/ak4458.c index 4c5c3ec92609..71562154c0b1 100644 --- a/sound/soc/codecs/ak4458.c +++ b/sound/soc/codecs/ak4458.c @@ -304,7 +304,10 @@ static int ak4458_rstn_control(struct snd_soc_component *component, int bit) AK4458_00_CONTROL1, AK4458_RSTN_MASK, 0x0); - return ret; + if (ret < 0) + return ret; + + return 0; } static int ak4458_hw_params(struct snd_pcm_substream *substream, -- cgit From b06c58c2a1eed571ea2a6640fdb85b7b00196b1e Mon Sep 17 00:00:00 2001 From: "S.j. Wang" Date: Wed, 15 May 2019 06:42:18 +0000 Subject: ASoC: fsl_asrc: Fix the issue about unsupported rate When the output sample rate is [8kHz, 30kHz], the limitation of the supported ratio range is [1/24, 8]. In the driver we use (8kHz, 30kHz) instead of [8kHz, 30kHz]. So this patch is to fix this issue and the potential rounding issue with divider. Fixes: fff6e03c7b65 ("ASoC: fsl_asrc: add support for 8-30kHz output sample rate") Cc: Signed-off-by: Shengjiu Wang Acked-by: Nicolin Chen Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_asrc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index 0b937924d2e4..ea035c12a325 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -282,8 +282,8 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair) return -EINVAL; } - if ((outrate > 8000 && outrate < 30000) && - (outrate/inrate > 24 || inrate/outrate > 8)) { + if ((outrate >= 8000 && outrate <= 30000) && + (outrate > 24 * inrate || inrate > 8 * outrate)) { pair_err("exceed supported ratio range [1/24, 8] for \ inrate/outrate: %d/%d\n", inrate, outrate); return -EINVAL; -- cgit From ad6eecbfc01c987e0253371f274c3872042e4350 Mon Sep 17 00:00:00 2001 From: "S.j. Wang" Date: Thu, 16 May 2019 06:04:29 +0000 Subject: ASoC: cs42xx8: Add regcache mask dirty Add regcache_mark_dirty before regcache_sync for power of codec may be lost at suspend, then all the register need to be reconfigured. Fixes: 0c516b4ff85c ("ASoC: cs42xx8: Add codec driver support for CS42448/CS42888") Cc: Signed-off-by: Shengjiu Wang Signed-off-by: Mark Brown --- sound/soc/codecs/cs42xx8.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c index ebb9e0cf8364..28a4ac36c4f8 100644 --- a/sound/soc/codecs/cs42xx8.c +++ b/sound/soc/codecs/cs42xx8.c @@ -558,6 +558,7 @@ static int cs42xx8_runtime_resume(struct device *dev) msleep(5); regcache_cache_only(cs42xx8->regmap, false); + regcache_mark_dirty(cs42xx8->regmap); ret = regcache_sync(cs42xx8->regmap); if (ret) { -- cgit From f7c4842abfa1a219554a3ffd8c317e8fdd979bec Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 17 May 2019 10:21:12 +0900 Subject: ASoC: soc-dpm: fixup DAI active unbalance snd_soc_dai_link_event() is updating snd_soc_dai :: active, but it is unbalance. It counts up if it has startup callback. case SND_SOC_DAPM_PRE_PMU: ... snd_soc_dapm_widget_for_each_source_path(w, path) { ... if (source->driver->ops->startup) { ... => source->active++; } ... } ... But, always counts down case SND_SOC_DAPM_PRE_PMD: ... snd_soc_dapm_widget_for_each_source_path(w, path) { ... => source->active--; ... } This patch always counts up when SND_SOC_DAPM_PRE_PMD. Signed-off-by: Kuninori Morimoto Reviewed-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 65ee0bb5dd0b..62e27defce56 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3828,8 +3828,8 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, ret); goto out; } - source->active++; } + source->active++; ret = soc_dai_hw_params(&substream, params, source); if (ret < 0) goto out; @@ -3850,8 +3850,8 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, ret); goto out; } - sink->active++; } + sink->active++; ret = soc_dai_hw_params(&substream, params, sink); if (ret < 0) goto out; -- cgit From 7b8164c1a29ce8ef91672c50ceac5c14475f5601 Mon Sep 17 00:00:00 2001 From: Curtis Malainey Date: Thu, 16 May 2019 18:43:40 -0700 Subject: ASoC: rt5677-spi: Handle over reading when flipping bytes There is a case when a we want to read a large number of bytes that require a burst but is not a multiple of the word size (8). When this happens rt5677_spi_reverse will run off the end of the buffer. The solution is to tell spi_reverse the actual size of the destination and stop if we reach it even if we have data left that we read. Cc: Ben Zhang Signed-off-by: Curtis Malainey Signed-off-by: Mark Brown --- sound/soc/codecs/rt5677-spi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt5677-spi.c b/sound/soc/codecs/rt5677-spi.c index 84b6bd8b50e1..a4dfa0345c6e 100644 --- a/sound/soc/codecs/rt5677-spi.c +++ b/sound/soc/codecs/rt5677-spi.c @@ -101,7 +101,7 @@ static void rt5677_spi_reverse(u8 *dst, u32 dstlen, const u8 *src, u32 srclen) u32 word_size = min_t(u32, dstlen, 8); for (w = 0; w < dstlen; w += word_size) { - for (i = 0; i < word_size; i++) { + for (i = 0; i < word_size && i + w < dstlen; i++) { si = w + word_size - i - 1; dst[w + i] = si < srclen ? src[si] : 0; } @@ -152,8 +152,9 @@ int rt5677_spi_read(u32 addr, void *rxbuf, size_t len) status |= spi_sync(g_spi, &m); mutex_unlock(&spi_mutex); + /* Copy data back to caller buffer */ - rt5677_spi_reverse(cb + offset, t[1].len, body, t[1].len); + rt5677_spi_reverse(cb + offset, len - offset, body, t[1].len); } return status; } -- cgit From 30d9d4ff53532087bc13ed29d7715df868794b5e Mon Sep 17 00:00:00 2001 From: Sathya Prakash M R Date: Sat, 18 May 2019 13:30:08 -0500 Subject: ASoC: Intel: soc-acpi: Fix machine selection order The selection order of m/c in match table is corrected to use common codec as last in the list. Signed-off-by: Sathya Prakash M R Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-cnl-match.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c index df7c52cad5c3..c36c0aa4f683 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c @@ -29,17 +29,17 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_machines[] = { .sof_tplg_filename = "sof-cnl-rt274.tplg", }, { - .id = "10EC5682", + .id = "MX98357A", .drv_name = "sof_rt5682", + .quirk_data = &cml_codecs, .sof_fw_filename = "sof-cnl.ri", - .sof_tplg_filename = "sof-cml-rt5682.tplg", + .sof_tplg_filename = "sof-cml-rt5682-max98357a.tplg", }, { - .id = "MX98357A", + .id = "10EC5682", .drv_name = "sof_rt5682", - .quirk_data = &cml_codecs, .sof_fw_filename = "sof-cnl.ri", - .sof_tplg_filename = "sof-cml-rt5682-max98357a.tplg", + .sof_tplg_filename = "sof-cml-rt5682.tplg", }, {}, -- cgit From 069d037aea98ffa64c26d4b1dc958fb8f39f5c2b Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Thu, 16 May 2019 18:51:26 +0100 Subject: ASoC: simple-card: Fix configuration of DAI format When configuring a codec to be both bit-clock and frame-master, it was found that the codec was always configured as bit-clock and frame-slave. Looking at the simple_dai_link_of() function there appears to be two problems with the configuration of the DAI format, which are ... 1. The function asoc_simple_parse_daifmt() is called before the function asoc_simple_parse_codec() and this means that the device-tree node for the codec has not been parsed yet, which is needed by the function asoc_simple_parse_daifmt() to determine who is the codec. 2. The phandle passed to asoc_simple_parse_daifmt() is the phandle to the 'codec' node and not the phandle of the actual codec defined by the 'sound-dai' property under the 'codec' node. Fix the above by moving the call to asoc_simple_parse_daifmt() after the the call to asoc_simple_parse_codec() and pass the phandle for the codec to asoc_simple_parse_daifmt(). Signed-off-by: Jon Hunter Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 9b568f578bcd..c2c8dcbcf795 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -283,11 +283,6 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, codec_dai = dai_props->codec_dai = &priv->dais[li->dais++]; - ret = asoc_simple_parse_daifmt(dev, node, codec, - prefix, &dai_link->dai_fmt); - if (ret < 0) - goto dai_link_of_err; - simple_parse_mclk_fs(top, cpu, codec, dai_props, prefix); ret = asoc_simple_parse_cpu(cpu, dai_link, &single_cpu); @@ -298,6 +293,11 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, if (ret < 0) goto dai_link_of_err; + ret = asoc_simple_parse_daifmt(dev, node, dai_link->codecs->of_node, + prefix, &dai_link->dai_fmt); + if (ret < 0) + goto dai_link_of_err; + ret = asoc_simple_parse_platform(plat, dai_link); if (ret < 0) goto dai_link_of_err; -- cgit From d5952f34ade5e6034e5eca3617fb77d4395bf492 Mon Sep 17 00:00:00 2001 From: Sathya Prakash M R Date: Mon, 20 May 2019 14:46:41 -0500 Subject: ASoC: Intel: sof-rt5682: fix for codec button mapping The RT5682 codec button mapping, initially copied from the DA7219 one, needs to be corrected. Signed-off-by: Sathya Prakash M R Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index f28fb98cc306..39ddefec4991 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -144,9 +144,9 @@ static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) jack = &ctx->sof_headset; snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); - snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP); - snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); - snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); + snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); + snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); + snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); ret = snd_soc_component_set_jack(component, jack, NULL); if (ret) { -- cgit From df9366131a452296d040a7a496d93108f1fc240c Mon Sep 17 00:00:00 2001 From: Sathya Prakash M R Date: Mon, 20 May 2019 14:46:42 -0500 Subject: ASoC: Intel: sof-rt5682: fix AMP quirk support The use of BIT/GENMASK was incorrect, fix. Signed-off-by: Sathya Prakash M R Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 39ddefec4991..3343dbcd506f 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -29,9 +29,10 @@ #define SOF_RT5682_MCLK_EN BIT(3) #define SOF_RT5682_MCLK_24MHZ BIT(4) #define SOF_SPEAKER_AMP_PRESENT BIT(5) -#define SOF_RT5682_SSP_AMP(quirk) ((quirk) & GENMASK(8, 6)) -#define SOF_RT5682_SSP_AMP_MASK (GENMASK(8, 6)) #define SOF_RT5682_SSP_AMP_SHIFT 6 +#define SOF_RT5682_SSP_AMP_MASK (GENMASK(8, 6)) +#define SOF_RT5682_SSP_AMP(quirk) \ + (((quirk) << SOF_RT5682_SSP_AMP_SHIFT) & SOF_RT5682_SSP_AMP_MASK) /* Default: MCLK on, MCLK 19.2M, SSP0 */ static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN | -- cgit From 4819d06292c9b57eabdd6d1603e49a27baf183be Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 24 May 2019 09:54:04 +0100 Subject: ASoC: simple-card: Restore original configuration of DAI format Revert commit 069d037aea98 ("ASoC: simple-card: Fix configuration of DAI format"). During further review, it turns out that the actual issue was caused by an incorrectly formatted device-tree node describing the soundcard. The following is incorrect because the simple-audio-card 'bitclock-master' and 'frame-master' properties should not reference the actual codec phandle ... sound { compatible = "simple-audio-card"; ... => simple-audio-card,bitclock-master = <&codec>; => simple-audio-card,frame-master = <&codec>; ... simple-audio-card,cpu { sound-dai = <&xxx>; }; simple-audio-card,codec { => sound-dai = <&codec>; }; }; Rather, these properties should reference the phandle to the 'simple-audio-card,codec' property as shown below ... sound { compatible = "simple-audio-card"; ... => simple-audio-card,bitclock-master = <&codec>; => simple-audio-card,frame-master = <&codec>; ... simple-audio-card,cpu { sound-dai = <&xxx>; }; => codec: simple-audio-card,codec { /* simple-card wants here */ sound-dai = <&xxx>; /* not here */ }; }; Signed-off-by: Jon Hunter Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index c2c8dcbcf795..9b568f578bcd 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -283,6 +283,11 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, codec_dai = dai_props->codec_dai = &priv->dais[li->dais++]; + ret = asoc_simple_parse_daifmt(dev, node, codec, + prefix, &dai_link->dai_fmt); + if (ret < 0) + goto dai_link_of_err; + simple_parse_mclk_fs(top, cpu, codec, dai_props, prefix); ret = asoc_simple_parse_cpu(cpu, dai_link, &single_cpu); @@ -293,11 +298,6 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, if (ret < 0) goto dai_link_of_err; - ret = asoc_simple_parse_daifmt(dev, node, dai_link->codecs->of_node, - prefix, &dai_link->dai_fmt); - if (ret < 0) - goto dai_link_of_err; - ret = asoc_simple_parse_platform(plat, dai_link); if (ret < 0) goto dai_link_of_err; -- cgit From 34ac3c3eb8f0c07252ceddf0a22dd240e5c91ccb Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Thu, 23 May 2019 10:12:01 -0700 Subject: ASoC: core: lock client_mutex while removing link components Removing link components results in topology unloading. So, acquire the client_mutex before removing components in soc_remove_link_components. This will prevent the lockdep warning seen when dai links are removed during topology removal. Signed-off-by: Ranjani Sridharan Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 2403bec2fccf..7c9415987ac7 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1005,12 +1005,14 @@ static void soc_remove_link_components(struct snd_soc_card *card, struct snd_soc_component *component; struct snd_soc_rtdcom_list *rtdcom; + mutex_lock(&client_mutex); for_each_rtdcom(rtd, rtdcom) { component = rtdcom->component; if (component->driver->remove_order == order) soc_remove_component(component); } + mutex_unlock(&client_mutex); } static void soc_remove_dai_links(struct snd_soc_card *card) -- cgit From 29040d1ac569606fece70966179de272cfc0d4db Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 27 May 2019 16:51:34 +0900 Subject: ASoC: soc-core: fixup references at soc_cleanup_card_resources() commit 53e947a0e1f7 ("ASoC: soc-core: merge card resources cleanup method") merged cleanup method of snd_soc_instantiate_card() and soc_cleanup_card_resources(). But, after this commit, if user uses unbind/bind to Component factor drivers, Kernel might indicates refcount error at soc_cleanup_card_resources(). The 1st reason is card->snd_card is still exist even though snd_card_free() was called, but it is already cleaned. We need to set NULL to it. 2nd is card->dapm and card create debugfs, but its dentry is still exist even though it was removed. We need to set NULL to it. Fixes: 53e947a0e1f7 ("ASoC: soc-core: merge card resources cleanup method") Cc: stable@vger.kernel.org # for v5.1 Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 7 ++++++- sound/soc/soc-dapm.c | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 7c9415987ac7..46042d41b79b 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -228,7 +228,10 @@ static void soc_init_card_debugfs(struct snd_soc_card *card) static void soc_cleanup_card_debugfs(struct snd_soc_card *card) { + if (!card->debugfs_card_root) + return; debugfs_remove_recursive(card->debugfs_card_root); + card->debugfs_card_root = NULL; } static void snd_soc_debugfs_init(void) @@ -2039,8 +2042,10 @@ match: static int soc_cleanup_card_resources(struct snd_soc_card *card) { /* free the ALSA card at first; this syncs with pending operations */ - if (card->snd_card) + if (card->snd_card) { snd_card_free(card->snd_card); + card->snd_card = NULL; + } /* remove and free each DAI */ soc_remove_dai_links(card); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 62e27defce56..5fc57af9cb6f 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2192,7 +2192,10 @@ static void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w) static void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm) { + if (!dapm->debugfs_dapm) + return; debugfs_remove_recursive(dapm->debugfs_dapm); + dapm->debugfs_dapm = NULL; } #else -- cgit From b85459aafae63f250606bd406d4f7537fda33b51 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Fri, 24 May 2019 14:09:17 -0500 Subject: ASoC: SOF: core: remove DSP after unregistering machine driver snd_sof_remove() disables the DSP and unmaps the DSP BAR. Removing topology after disabling the DSP results in a kernel panic while unloading the pipeline widget. This is because pipeline widget unload attempts to power down the core it is scheduled on by accessing the DSP registers. So, the suggested fix here is to unregister the machine driver first to remove the topology and then disable the DSP to avoid the situation described above. Note that the kernel panic only happens in cases where the HDaudio link is not managed by the hdac library, e.g. no codec or when HDMI is not supported. When the hdac library is used, snd_sof_remove() calls snd_hdac_ext_bus_device_remove() to remove the codec which unregisters the component driver thereby also removing the topology before the DSP is disabled. Fixes: c16211d6226 ("ASoC: SOF: Add Sound Open Firmware driver core") Reviewed-by: Takashi Iwai Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 32105e0fabe8..0bc4a8472c10 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -484,7 +484,6 @@ int snd_sof_device_remove(struct device *dev) snd_sof_ipc_free(sdev); snd_sof_free_debug(sdev); snd_sof_free_trace(sdev); - snd_sof_remove(sdev); /* * Unregister machine driver. This will unbind the snd_card which @@ -494,6 +493,14 @@ int snd_sof_device_remove(struct device *dev) if (!IS_ERR_OR_NULL(pdata->pdev_mach)) platform_device_unregister(pdata->pdev_mach); + /* + * Unregistering the machine driver results in unloading the topology. + * Some widgets, ex: scheduler, attempt to power down the core they are + * scheduled on, when they are unloaded. Therefore, the DSP must be + * removed only after the topology has been unloaded. + */ + snd_sof_remove(sdev); + /* release firmware */ release_firmware(pdata->fw); pdata->fw = NULL; -- cgit From 13931ae31b67a8a26a4cd417088fc43e3d4a8591 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Fri, 24 May 2019 14:09:18 -0500 Subject: ASoC: SOF: core: remove snd_soc_unregister_component in case of error No need to call snd_soc_unregister_component in case of error because the component device is resource-managed. Fixes: c16211d6226 ("ASoC: SOF: Add Sound Open Firmware driver core") Reviewed-by: Takashi Iwai Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 0bc4a8472c10..693ad83bffc9 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -382,7 +382,7 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) if (IS_ERR(plat_data->pdev_mach)) { ret = PTR_ERR(plat_data->pdev_mach); - goto comp_err; + goto fw_run_err; } dev_dbg(sdev->dev, "created machine %s\n", @@ -393,8 +393,6 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) return 0; -comp_err: - snd_soc_unregister_component(sdev->dev); fw_run_err: snd_sof_fw_unload(sdev); fw_load_err: -- cgit From 0bce512e784d137700275f7839c4547eddbd4b6a Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 May 2019 14:09:19 -0500 Subject: ASoC: SOF: core: fix error handling with the probe workqueue In some configurations, it's a requirement to split the probe in two, with a second part handled in a workqueue (e.g. for HDMI support which depends on the DRM modules). SOF already handles these configurations but the error flow is incorrect. When an error occurs in the workqueue, the probe has technically already completed. If we release the resources on errors, this generates kernel oops/use-after-free when the resources are released a second time on module removal. GitHub issue: https://github.com/thesofproject/linux/issues/945 Fixes: c16211d6226 ("ASoC: SOF: Add Sound Open Firmware driver core") Reviewed-by: Takashi Iwai Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 693ad83bffc9..5beda47cdf9f 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -393,6 +393,7 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) return 0; +#if !IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) fw_run_err: snd_sof_fw_unload(sdev); fw_load_err: @@ -401,6 +402,21 @@ ipc_err: snd_sof_free_debug(sdev); dbg_err: snd_sof_remove(sdev); +#else + + /* + * when the probe_continue is handled in a work queue, the + * probe does not fail so we don't release resources here. + * They will be released with an explicit call to + * snd_sof_device_remove() when the PCI/ACPI device is removed + */ + +fw_run_err: +fw_load_err: +ipc_err: +dbg_err: + +#endif return ret; } -- cgit From 04ea642ff62a2b2da3d5844283991a41328f49b1 Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Fri, 24 May 2019 14:09:20 -0500 Subject: ASoC: SOF: pcm: clear hw_params_upon_resume flag correctly sof_pcm_hw_params() can only be called once to setup the FW hw_params. So after calling sof_pcm_hw_params(), hw_params_upon_resume flag must be cleared to avoid multiple invoking sof_pcm_hw_params() by prepare. For example, after resume, there is an xrun happened, prepare() will be called. As the hw_params_upon_resume flag is not cleared, sof_pcm_hw_params() will be called and this will cause IPC timeout. This patch fixes such issues. Fixes: 868bd00f495 ("ASoC: SOF: Add PCM operations support") Reviewed-by: Takashi Iwai Signed-off-by: Libin Yang Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 649968841dad..d6dc9a7df0f4 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -214,6 +214,9 @@ static int sof_pcm_hw_params(struct snd_pcm_substream *substream, INIT_WORK(&spcm->stream[substream->stream].period_elapsed_work, sof_pcm_period_elapsed_work); + /* clear hw_params_upon_resume flag */ + spcm->hw_params_upon_resume[substream->stream] = 0; + return ret; } @@ -429,9 +432,6 @@ static int sof_pcm_open(struct snd_pcm_substream *substream) dev_dbg(sdev->dev, "pcm: open stream %d dir %d\n", spcm->pcm.pcm_id, substream->stream); - /* clear hw_params_upon_resume flag */ - spcm->hw_params_upon_resume[substream->stream] = 0; - caps = &spcm->pcm.caps[substream->stream]; ret = pm_runtime_get_sync(sdev->dev); -- cgit From fab4edf42d2d68d0aa67822650174dcd0ee25ffa Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 May 2019 14:09:21 -0500 Subject: ASoC: SOF: pcm: remove warning - initialize workqueue on open If the SOF hw_params() fail, typically with an IPC error thrown by the firmware, the period_elapsed workqueue is not initialized, but we still cancel it in hw_free(), which results in a kernel warning. Move the initialization to the .open callback. Tested on Broadwell (Samus) and IceLake. Fixes: e2803e610ae ("ASoC: SOF: PCM: add period_elapsed work to fix race condition in interrupt context") GitHub issue: https://github.com/thesofproject/linux/issues/932 Reviewed-by: Takashi Iwai Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index d6dc9a7df0f4..dace6c4cd91e 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -211,9 +211,6 @@ static int sof_pcm_hw_params(struct snd_pcm_substream *substream, /* save pcm hw_params */ memcpy(&spcm->params[substream->stream], params, sizeof(*params)); - INIT_WORK(&spcm->stream[substream->stream].period_elapsed_work, - sof_pcm_period_elapsed_work); - /* clear hw_params_upon_resume flag */ spcm->hw_params_upon_resume[substream->stream] = 0; @@ -432,6 +429,9 @@ static int sof_pcm_open(struct snd_pcm_substream *substream) dev_dbg(sdev->dev, "pcm: open stream %d dir %d\n", spcm->pcm.pcm_id, substream->stream); + INIT_WORK(&spcm->stream[substream->stream].period_elapsed_work, + sof_pcm_period_elapsed_work); + caps = &spcm->pcm.caps[substream->stream]; ret = pm_runtime_get_sync(sdev->dev); -- cgit From 5661ad9490ee4abdb27295880e524acc656c89e7 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 24 May 2019 14:09:22 -0500 Subject: ASoC: SOF: control: correct the copy size for bytes kcontrol put The size for the bytes kcontrol should include the abi header, that is, data->size + sizeof(*data), it is also aligned with get method after this change. Fixes: c3078f53970 ("ASoC: SOF: Add Sound Open Firmware KControl support") Reviewed-by: Takashi Iwai Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/control.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c index 11762c4580f1..84e2cbfbbcbb 100644 --- a/sound/soc/sof/control.c +++ b/sound/soc/sof/control.c @@ -349,6 +349,7 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol, struct snd_sof_dev *sdev = scontrol->sdev; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; struct sof_abi_hdr *data = cdata->data; + size_t size = data->size + sizeof(*data); int ret, err; if (be->max > sizeof(ucontrol->value.bytes.data)) { @@ -358,10 +359,10 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol, return -EINVAL; } - if (data->size > be->max) { + if (size > be->max) { dev_err_ratelimited(sdev->dev, - "error: size too big %d bytes max is %d\n", - data->size, be->max); + "error: size too big %zu bytes max is %d\n", + size, be->max); return -EINVAL; } @@ -375,7 +376,7 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol, } /* copy from kcontrol */ - memcpy(data, ucontrol->value.bytes.data, data->size); + memcpy(data, ucontrol->value.bytes.data, size); /* notify DSP of byte control updates */ snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, -- cgit From 1183e9a634db06825da7faba566bce50afde4357 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 24 May 2019 14:09:23 -0500 Subject: ASoC: SOF: ipc: fix a race, leading to IPC timeouts Currently on all supported platforms the IPC IRQ thread first signals the sender when an IPC response is received from the DSP, then unmasks the IPC interrupt. Those actions are performed without holding any locks, so the thread can be interrupted between them. IPC timeouts have been observed in such scenarios: if the sender is woken up and it proceeds with sending the next message without unmasking the IPC interrupt, it can miss the next response. This patch takes a spin-lock to prevent the IRQ thread from being preempted at that point. It also makes sure, that the next IPC transmission by the host cannot take place before the IRQ thread has finished updating all the required IPC registers. Fixes: 53e0c72d98b ("ASoC: SOF: Add support for IPC IO between DSP and Host") Reviewed-by: Takashi Iwai Signed-off-by: Guennadi Liakhovetski Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/bdw.c | 9 ++++----- sound/soc/sof/intel/byt.c | 10 +++++----- sound/soc/sof/intel/cnl.c | 4 ++++ sound/soc/sof/intel/hda-ipc.c | 17 ++++++++++++++--- sound/soc/sof/ipc.c | 13 ------------- 5 files changed, 27 insertions(+), 26 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index 065cb868bdfa..8ff3ee520aea 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -283,6 +283,8 @@ static irqreturn_t bdw_irq_thread(int irq, void *context) SHIM_IMRX, SHIM_IMRX_DONE, SHIM_IMRX_DONE); + spin_lock_irq(&sdev->ipc_lock); + /* * handle immediate reply from DSP core. If the msg is * found, set done bit in cmd_done which is called at the @@ -294,6 +296,8 @@ static irqreturn_t bdw_irq_thread(int irq, void *context) snd_sof_ipc_reply(sdev, ipcx); bdw_dsp_done(sdev); + + spin_unlock_irq(&sdev->ipc_lock); } ipcd = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCD); @@ -485,7 +489,6 @@ static void bdw_get_reply(struct snd_sof_dev *sdev) { struct snd_sof_ipc_msg *msg = sdev->msg; struct sof_ipc_reply reply; - unsigned long flags; int ret = 0; /* @@ -501,8 +504,6 @@ static void bdw_get_reply(struct snd_sof_dev *sdev) /* get reply */ sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply)); - spin_lock_irqsave(&sdev->ipc_lock, flags); - if (reply.error < 0) { memcpy(msg->reply_data, &reply, sizeof(reply)); ret = reply.error; @@ -521,8 +522,6 @@ static void bdw_get_reply(struct snd_sof_dev *sdev) } msg->reply_error = ret; - - spin_unlock_irqrestore(&sdev->ipc_lock, flags); } static void bdw_host_done(struct snd_sof_dev *sdev) diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 7bf9143d3106..9e4c07eb889b 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -329,6 +329,9 @@ static irqreturn_t byt_irq_thread(int irq, void *context) SHIM_IMRX, SHIM_IMRX_DONE, SHIM_IMRX_DONE); + + spin_lock_irq(&sdev->ipc_lock); + /* * handle immediate reply from DSP core. If the msg is * found, set done bit in cmd_done which is called at the @@ -340,6 +343,8 @@ static irqreturn_t byt_irq_thread(int irq, void *context) snd_sof_ipc_reply(sdev, ipcx); byt_dsp_done(sdev); + + spin_unlock_irq(&sdev->ipc_lock); } /* new message from DSP */ @@ -383,7 +388,6 @@ static void byt_get_reply(struct snd_sof_dev *sdev) { struct snd_sof_ipc_msg *msg = sdev->msg; struct sof_ipc_reply reply; - unsigned long flags; int ret = 0; /* @@ -399,8 +403,6 @@ static void byt_get_reply(struct snd_sof_dev *sdev) /* get reply */ sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply)); - spin_lock_irqsave(&sdev->ipc_lock, flags); - if (reply.error < 0) { memcpy(msg->reply_data, &reply, sizeof(reply)); ret = reply.error; @@ -419,8 +421,6 @@ static void byt_get_reply(struct snd_sof_dev *sdev) } msg->reply_error = ret; - - spin_unlock_irqrestore(&sdev->ipc_lock, flags); } static void byt_host_done(struct snd_sof_dev *sdev) diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 08a1a3d3c08d..b2eba7adcad8 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -64,6 +64,8 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) CNL_DSP_REG_HIPCCTL, CNL_DSP_REG_HIPCCTL_DONE, 0); + spin_lock_irq(&sdev->ipc_lock); + /* handle immediate reply from DSP core */ hda_dsp_ipc_get_reply(sdev); snd_sof_ipc_reply(sdev, msg); @@ -75,6 +77,8 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) cnl_ipc_dsp_done(sdev); + spin_unlock_irq(&sdev->ipc_lock); + ret = IRQ_HANDLED; } diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index 73ead7070cde..51b285103394 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -72,7 +72,6 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev) struct snd_sof_ipc_msg *msg = sdev->msg; struct sof_ipc_reply reply; struct sof_ipc_cmd_hdr *hdr; - unsigned long flags; int ret = 0; /* @@ -84,7 +83,6 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev) dev_warn(sdev->dev, "unexpected ipc interrupt raised!\n"); return; } - spin_lock_irqsave(&sdev->ipc_lock, flags); hdr = msg->msg_data; if (hdr->cmd == (SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_CTX_SAVE)) { @@ -123,7 +121,6 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev) out: msg->reply_error = ret; - spin_unlock_irqrestore(&sdev->ipc_lock, flags); } static bool hda_dsp_ipc_is_sof(uint32_t msg) @@ -172,6 +169,18 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) HDA_DSP_REG_HIPCCTL, HDA_DSP_REG_HIPCCTL_DONE, 0); + /* + * Make sure the interrupt thread cannot be preempted between + * waking up the sender and re-enabling the interrupt. Also + * protect against a theoretical race with sof_ipc_tx_message(): + * if the DSP is fast enough to receive an IPC message, reply to + * it, and the host interrupt processing calls this function on + * a different core from the one, where the sending is taking + * place, the message might not yet be marked as expecting a + * reply. + */ + spin_lock_irq(&sdev->ipc_lock); + /* handle immediate reply from DSP core - ignore ROM messages */ if (hda_dsp_ipc_is_sof(msg)) { hda_dsp_ipc_get_reply(sdev); @@ -187,6 +196,8 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) /* set the done bit */ hda_dsp_ipc_dsp_done(sdev); + spin_unlock_irq(&sdev->ipc_lock); + ret = IRQ_HANDLED; } diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index 894e68cbd69d..10304a90cf25 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -308,19 +308,8 @@ EXPORT_SYMBOL(sof_ipc_tx_message); int snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id) { struct snd_sof_ipc_msg *msg = &sdev->ipc->msg; - unsigned long flags; - - /* - * Protect against a theoretical race with sof_ipc_tx_message(): if the - * DSP is fast enough to receive an IPC message, reply to it, and the - * host interrupt processing calls this function on a different core - * from the one, where the sending is taking place, the message might - * not yet be marked as expecting a reply. - */ - spin_lock_irqsave(&sdev->ipc_lock, flags); if (msg->ipc_complete) { - spin_unlock_irqrestore(&sdev->ipc_lock, flags); dev_err(sdev->dev, "error: no reply expected, received 0x%x", msg_id); return -EINVAL; @@ -330,8 +319,6 @@ int snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id) msg->ipc_complete = true; wake_up(&msg->waitq); - spin_unlock_irqrestore(&sdev->ipc_lock, flags); - return 0; } EXPORT_SYMBOL(snd_sof_ipc_reply); -- cgit From be1b577d01787c67acc6dd1257588183386a08f4 Mon Sep 17 00:00:00 2001 From: Zhu Yingjiang Date: Fri, 24 May 2019 14:09:24 -0500 Subject: ASoC: SOF: Intel: hda: fix the hda init chip re-write hda_init_caps and remove the HDA reset, clean HDA streams and clear interrupt steps in hda_dsp_probe so the HDA init steps will not be called twice if the CONFIG_SND_SOC_SOF_HDA is true. Fixes: 8a300c8fb17 ("ASoC: SOF: Intel: Add HDA controller for Intel DSP") Reviewed-by: Takashi Iwai Signed-off-by: Zhu Yingjiang Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-ctrl.c | 102 +++++++++++++++++++++++++++++++++++++---- sound/soc/sof/intel/hda.c | 99 ++++++++------------------------------- 2 files changed, 112 insertions(+), 89 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index 2c3645736e1f..07bc123112c9 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -161,21 +161,105 @@ int hda_dsp_ctrl_clock_power_gating(struct snd_sof_dev *sdev, bool enable) return 0; } -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) -/* - * While performing reset, controller may not come back properly and causing - * issues, so recommendation is to set CGCTL.MISCBDCGE to 0 then do reset - * (init chip) and then again set CGCTL.MISCBDCGE to 1 - */ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset) { struct hdac_bus *bus = sof_to_bus(sdev); - int ret; + struct hdac_stream *stream; + int sd_offset, ret = 0; + + if (bus->chip_init) + return 0; hda_dsp_ctrl_misc_clock_gating(sdev, false); - ret = snd_hdac_bus_init_chip(bus, full_reset); + + if (full_reset) { + /* clear WAKESTS */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS, + SOF_HDA_WAKESTS_INT_MASK, + SOF_HDA_WAKESTS_INT_MASK); + + /* reset HDA controller */ + ret = hda_dsp_ctrl_link_reset(sdev, true); + if (ret < 0) { + dev_err(sdev->dev, "error: failed to reset HDA controller\n"); + return ret; + } + + usleep_range(500, 1000); + + /* exit HDA controller reset */ + ret = hda_dsp_ctrl_link_reset(sdev, false); + if (ret < 0) { + dev_err(sdev->dev, "error: failed to exit HDA controller reset\n"); + return ret; + } + + usleep_range(1000, 1200); + } + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + /* check to see if controller is ready */ + if (!snd_hdac_chip_readb(bus, GCTL)) { + dev_dbg(bus->dev, "controller not ready!\n"); + return -EBUSY; + } + + /* Accept unsolicited responses */ + snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, AZX_GCTL_UNSOL); + + /* detect codecs */ + if (!bus->codec_mask) { + bus->codec_mask = snd_hdac_chip_readw(bus, STATESTS); + dev_dbg(bus->dev, "codec_mask = 0x%lx\n", bus->codec_mask); + } +#endif + + /* clear stream status */ + list_for_each_entry(stream, &bus->stream_list, list) { + sd_offset = SOF_STREAM_SD_OFFSET(stream); + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, + sd_offset + + SOF_HDA_ADSP_REG_CL_SD_STS, + SOF_HDA_CL_DMA_SD_INT_MASK, + SOF_HDA_CL_DMA_SD_INT_MASK); + } + + /* clear WAKESTS */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS, + SOF_HDA_WAKESTS_INT_MASK, + SOF_HDA_WAKESTS_INT_MASK); + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + /* clear rirb status */ + snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK); +#endif + + /* clear interrupt status register */ + snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS, + SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_ALL_STREAM); + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + /* initialize the codec command I/O */ + snd_hdac_bus_init_cmd_io(bus); +#endif + + /* enable CIE and GIE interrupts */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, + SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, + SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN); + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + /* program the position buffer */ + if (bus->use_posbuf && bus->posbuf.addr) { + snd_hdac_chip_writel(bus, DPLBASE, (u32)bus->posbuf.addr); + snd_hdac_chip_writel(bus, DPUBASE, + upper_32_bits(bus->posbuf.addr)); + } +#endif + + bus->chip_init = true; + hda_dsp_ctrl_misc_clock_gating(sdev, true); return ret; } -#endif diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 7e3980a2f7ba..e47f03dc62f0 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -264,9 +264,12 @@ static const char *fixup_tplg_name(struct snd_sof_dev *sdev, return tplg_filename; } +#endif + static int hda_init_caps(struct snd_sof_dev *sdev) { struct hdac_bus *bus = sof_to_bus(sdev); +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) struct hdac_ext_link *hlink; struct snd_soc_acpi_mach_params *mach_params; struct snd_soc_acpi_mach *hda_mach; @@ -274,8 +277,9 @@ static int hda_init_caps(struct snd_sof_dev *sdev) struct snd_soc_acpi_mach *mach; const char *tplg_filename; int codec_num = 0; - int ret = 0; int i; +#endif + int ret = 0; device_disable_async_suspend(bus->dev); @@ -283,6 +287,14 @@ static int hda_init_caps(struct snd_sof_dev *sdev) if (bus->ppcap) dev_dbg(sdev->dev, "PP capability, will probe DSP later.\n"); + ret = hda_dsp_ctrl_init_chip(sdev, true); + if (ret < 0) { + dev_err(bus->dev, "error: init chip failed with ret: %d\n", + ret); + return ret; + } + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) if (bus->mlcap) snd_hdac_ext_bus_get_ml_capabilities(bus); @@ -293,12 +305,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev) return ret; } - ret = hda_dsp_ctrl_init_chip(sdev, true); - if (ret < 0) { - dev_err(bus->dev, "error: init chip failed with ret: %d\n", ret); - goto out; - } - /* codec detection */ if (!bus->codec_mask) { dev_info(bus->dev, "no hda codecs found!\n"); @@ -339,8 +345,10 @@ static int hda_init_caps(struct snd_sof_dev *sdev) /* use local variable for readability */ tplg_filename = pdata->tplg_filename; tplg_filename = fixup_tplg_name(sdev, tplg_filename); - if (!tplg_filename) - goto out; + if (!tplg_filename) { + hda_codec_i915_exit(sdev); + return ret; + } pdata->tplg_filename = tplg_filename; } } @@ -364,35 +372,10 @@ static int hda_init_caps(struct snd_sof_dev *sdev) */ list_for_each_entry(hlink, &bus->hlink_list, list) snd_hdac_ext_bus_link_put(bus, hlink); - - return 0; - -out: - hda_codec_i915_exit(sdev); - return ret; -} - -#else - -static int hda_init_caps(struct snd_sof_dev *sdev) -{ - /* - * set CGCTL.MISCBDCGE to 0 during reset and set back to 1 - * when reset finished. - * TODO: maybe no need for init_caps? - */ - hda_dsp_ctrl_misc_clock_gating(sdev, 0); - - /* clear WAKESTS */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS, - SOF_HDA_WAKESTS_INT_MASK, - SOF_HDA_WAKESTS_INT_MASK); - +#endif return 0; } -#endif - static const struct sof_intel_dsp_desc *get_chip_info(struct snd_sof_pdata *pdata) { @@ -409,9 +392,8 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) struct pci_dev *pci = to_pci_dev(sdev->dev); struct sof_intel_hda_dev *hdev; struct hdac_bus *bus; - struct hdac_stream *stream; const struct sof_intel_dsp_desc *chip; - int sd_offset, ret = 0; + int ret = 0; /* * detect DSP by checking class/subclass/prog-id information @@ -558,49 +540,6 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) if (ret < 0) goto free_ipc_irq; - /* reset HDA controller */ - ret = hda_dsp_ctrl_link_reset(sdev, true); - if (ret < 0) { - dev_err(sdev->dev, "error: failed to reset HDA controller\n"); - goto free_ipc_irq; - } - - /* exit HDA controller reset */ - ret = hda_dsp_ctrl_link_reset(sdev, false); - if (ret < 0) { - dev_err(sdev->dev, "error: failed to exit HDA controller reset\n"); - goto free_ipc_irq; - } - - /* clear stream status */ - list_for_each_entry(stream, &bus->stream_list, list) { - sd_offset = SOF_STREAM_SD_OFFSET(stream); - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, - sd_offset + - SOF_HDA_ADSP_REG_CL_SD_STS, - SOF_HDA_CL_DMA_SD_INT_MASK, - SOF_HDA_CL_DMA_SD_INT_MASK); - } - - /* clear WAKESTS */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS, - SOF_HDA_WAKESTS_INT_MASK, - SOF_HDA_WAKESTS_INT_MASK); - - /* clear interrupt status register */ - snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS, - SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_ALL_STREAM); - - /* enable CIE and GIE interrupts */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, - SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, - SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN); - - /* re-enable CGCTL.MISCBDCGE after reset */ - hda_dsp_ctrl_misc_clock_gating(sdev, true); - - device_disable_async_suspend(&pci->dev); - /* enable DSP features */ snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, SOF_HDA_PPCTL_GPROCEN, SOF_HDA_PPCTL_GPROCEN); -- cgit From 1f2675f6655838aaf910f911fd0abc821e3ff3df Mon Sep 17 00:00:00 2001 From: Georgii Staroselskii Date: Tue, 28 May 2019 13:47:39 +0300 Subject: ASoC: sun4i-codec: fix first delay on Speaker Allwinner DAC seems to have a delay in the Speaker audio routing. When playing a sound for the first time, the sound gets chopped. On a second play the sound is played correctly. After some time (~5s) the issue gets back. This commit seems to be fixing the same issue as bf14da7 but for another codepath. This is the DTS that was used to debug the problem. &codec { allwinner,pa-gpios = <&r_pio 0 11 GPIO_ACTIVE_HIGH>; /* PL11 */ allwinner,audio-routing = "Speaker", "LINEOUT"; status = "okay"; } Signed-off-by: Georgii Staroselskii Reviewed-by: Chen-Yu Tsai Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-codec.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'sound') diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 15d08e343b47..28d2f7713f8d 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -1329,6 +1329,15 @@ static int sun4i_codec_spk_event(struct snd_soc_dapm_widget *w, gpiod_set_value_cansleep(scodec->gpio_pa, !!SND_SOC_DAPM_EVENT_ON(event)); + if (SND_SOC_DAPM_EVENT_ON(event)) { + /* + * Need a delay to wait for DAC to push the data. 700ms seems + * to be the best compromise not to feel this delay while + * playing a sound. + */ + msleep(700); + } + return 0; } -- cgit From 3e951e7914408aee196db77a5cb377801c85692a Mon Sep 17 00:00:00 2001 From: Kovács Tamás Date: Fri, 31 May 2019 19:22:26 +0200 Subject: ASoC: Intel: Baytrail: add quirk for Aegex 10 (RU2) tablet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This tablet has an incorrect acpi identifier just like Thinkpad10 tablet, which is why it is trying to load the RT5640 driver instead of the RT5762 driver. The RT5640 driver, on the other hand, checks the hardware ID, so no driver are loaded during boot. This fix resolves to load the RT5672 driver on this tablet during boot. It also provides the correct IO configuration, like the jack detect mode 3, for 1.8V pullup. I would like to thank Pierre-Louis Bossart for helping with this patch. Signed-off-by: Kovács Tamás Signed-off-by: Mark Brown --- sound/soc/codecs/rt5670.c | 12 ++++++++++++ sound/soc/intel/common/soc-acpi-intel-byt-match.c | 17 +++++++++++++++++ 2 files changed, 29 insertions(+) (limited to 'sound') diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 9a037108b1ae..a746e11ccfe3 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -2882,6 +2882,18 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { RT5670_DEV_GPIO | RT5670_JD_MODE3), }, + { + .callback = rt5670_quirk_cb, + .ident = "Aegex 10 tablet (RU2)", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "AEGEX"), + DMI_MATCH(DMI_PRODUCT_VERSION, "RU2"), + }, + .driver_data = (unsigned long *)(RT5670_DMIC_EN | + RT5670_DMIC2_INR | + RT5670_DEV_GPIO | + RT5670_JD_MODE3), + }, {} }; diff --git a/sound/soc/intel/common/soc-acpi-intel-byt-match.c b/sound/soc/intel/common/soc-acpi-intel-byt-match.c index 0cfab247876a..9fb58f1f095f 100644 --- a/sound/soc/intel/common/soc-acpi-intel-byt-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-byt-match.c @@ -22,6 +22,7 @@ static unsigned long byt_machine_id; #define BYT_THINKPAD_10 1 #define BYT_POV_P1006W 2 +#define BYT_AEGEX_10 3 static int byt_thinkpad10_quirk_cb(const struct dmi_system_id *id) { @@ -35,6 +36,12 @@ static int byt_pov_p1006w_quirk_cb(const struct dmi_system_id *id) return 1; } +static int byt_aegex10_quirk_cb(const struct dmi_system_id *id) +{ + byt_machine_id = BYT_AEGEX_10; + return 1; +} + static const struct dmi_system_id byt_table[] = { { .callback = byt_thinkpad10_quirk_cb, @@ -75,9 +82,18 @@ static const struct dmi_system_id byt_table[] = { DMI_EXACT_MATCH(DMI_BOARD_NAME, "0E57"), }, }, + { + /* Aegex 10 tablet (RU2) */ + .callback = byt_aegex10_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "AEGEX"), + DMI_MATCH(DMI_PRODUCT_VERSION, "RU2"), + }, + }, { } }; +/* The Thinkapd 10 and Aegex 10 tablets have the same ID problem */ static struct snd_soc_acpi_mach byt_thinkpad_10 = { .id = "10EC5640", .drv_name = "cht-bsw-rt5672", @@ -104,6 +120,7 @@ static struct snd_soc_acpi_mach *byt_quirk(void *arg) switch (byt_machine_id) { case BYT_THINKPAD_10: + case BYT_AEGEX_10: return &byt_thinkpad_10; case BYT_POV_P1006W: return &byt_pov_p1006w; -- cgit From 347d1c4b0779cbeabaebb9b8e9967afe28db22f1 Mon Sep 17 00:00:00 2001 From: Slawomir Blauciak Date: Mon, 3 Jun 2019 11:20:32 -0500 Subject: ASoC: SOF: ipc: replace fw ready bitfield with explicit bit ordering Previously the structure used bitfields, which do not guarantee bit ordering. This change makes sure the order is clearly defined. It also renames and repurposes the field for general use. Signed-off-by: Slawomir Blauciak Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/ipc.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index 10304a90cf25..2414640a32d1 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -763,16 +763,19 @@ int snd_sof_ipc_valid(struct snd_sof_dev *sdev) } } - if (ready->debug.bits.build) { + if (ready->flags & SOF_IPC_INFO_BUILD) { dev_info(sdev->dev, "Firmware debug build %d on %s-%s - options:\n" " GDB: %s\n" " lock debug: %s\n" " lock vdebug: %s\n", v->build, v->date, v->time, - ready->debug.bits.gdb ? "enabled" : "disabled", - ready->debug.bits.locks ? "enabled" : "disabled", - ready->debug.bits.locks_verbose ? "enabled" : "disabled"); + ready->flags & SOF_IPC_INFO_GDB ? + "enabled" : "disabled", + ready->flags & SOF_IPC_INFO_LOCKS ? + "enabled" : "disabled", + ready->flags & SOF_IPC_INFO_LOCKSV ? + "enabled" : "disabled"); } /* copy the fw_version into debugfs at first boot */ -- cgit From d6947bb234dcc86e878d502516d0fb9d635aa2ae Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Fri, 31 May 2019 09:01:37 -0700 Subject: ASoC: hda: fix unbalanced codec dev refcount for HDA_DEV_ASOC HDA_DEV_ASOC type codec device refcounts are managed differently from HDA_DEV_LEGACY devices. The refcount is released explicitly in snd_hdac_ext_bus_device_remove() for ASOC type devices. So, remove the put_device() call in snd_hda_codec_dev_free() for such devices to make the refcount balanced. This will prevent the NULL pointer exception when the codec driver is released after the card is freed. Signed-off-by: Ranjani Sridharan Reviewed-by: Takashi Iwai Signed-off-by: Mark Brown --- sound/pci/hda/hda_codec.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index ec0b8595eb4d..6cdec64dc68a 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -834,7 +834,14 @@ static int snd_hda_codec_dev_free(struct snd_device *device) codec->in_freeing = 1; snd_hdac_device_unregister(&codec->core); codec_display_power(codec, false); - put_device(hda_codec_dev(codec)); + + /* + * In the case of ASoC HD-audio bus, the device refcount is released in + * snd_hdac_ext_bus_device_remove() explicitly. + */ + if (codec->core.type == HDA_DEV_LEGACY) + put_device(hda_codec_dev(codec)); + return 0; } -- cgit From 14104eb6a351a5bad21fdd2cf05ca46ad5e5beab Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Mon, 3 Jun 2019 11:18:15 -0500 Subject: ASoC: SOF: fix DSP oops definitions in FW ABI The definitions for DSP oops structures were not aligned correctly to current FW ABI version 3.6.0, leading to invalid data being printed out to debug logs. Fix the structs and update related platform code accordingly. Signed-off-by: Kai Vehmanen Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/bdw.c | 17 ++++++++++------- sound/soc/sof/intel/byt.c | 15 +++++++++------ sound/soc/sof/intel/hda.c | 16 ++++++++++------ sound/soc/sof/xtensa/core.c | 2 +- 4 files changed, 30 insertions(+), 20 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index 8ff3ee520aea..70d524ef9bc0 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -220,17 +220,20 @@ static void bdw_get_registers(struct snd_sof_dev *sdev, struct sof_ipc_panic_info *panic_info, u32 *stack, size_t stack_words) { - /* first read regsisters */ - sof_mailbox_read(sdev, sdev->dsp_oops_offset, xoops, sizeof(*xoops)); + u32 offset = sdev->dsp_oops_offset; + + /* first read registers */ + sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops)); + + /* note: variable AR register array is not read */ /* then get panic info */ - sof_mailbox_read(sdev, sdev->dsp_oops_offset + sizeof(*xoops), - panic_info, sizeof(*panic_info)); + offset += xoops->arch_hdr.totalsize; + sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info)); /* then get the stack */ - sof_mailbox_read(sdev, sdev->dsp_oops_offset + sizeof(*xoops) + - sizeof(*panic_info), stack, - stack_words * sizeof(u32)); + offset += sizeof(*panic_info); + sof_mailbox_read(sdev, offset, stack, stack_words * sizeof(u32)); } static void bdw_dump(struct snd_sof_dev *sdev, u32 flags) diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 9e4c07eb889b..39d1ae01c45d 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -265,17 +265,20 @@ static void byt_get_registers(struct snd_sof_dev *sdev, struct sof_ipc_panic_info *panic_info, u32 *stack, size_t stack_words) { + u32 offset = sdev->dsp_oops_offset; + /* first read regsisters */ - sof_mailbox_read(sdev, sdev->dsp_oops_offset, xoops, sizeof(*xoops)); + sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops)); + + /* note: variable AR register array is not read */ /* then get panic info */ - sof_mailbox_read(sdev, sdev->dsp_oops_offset + sizeof(*xoops), - panic_info, sizeof(*panic_info)); + offset += xoops->arch_hdr.totalsize; + sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info)); /* then get the stack */ - sof_mailbox_read(sdev, sdev->dsp_oops_offset + sizeof(*xoops) + - sizeof(*panic_info), stack, - stack_words * sizeof(u32)); + offset += sizeof(*panic_info); + sof_mailbox_read(sdev, offset, stack, stack_words * sizeof(u32)); } static void byt_dump(struct snd_sof_dev *sdev, u32 flags) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index e47f03dc62f0..8f5c68861bbc 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -108,17 +108,21 @@ static void hda_dsp_get_registers(struct snd_sof_dev *sdev, struct sof_ipc_panic_info *panic_info, u32 *stack, size_t stack_words) { + u32 offset = sdev->dsp_oops_offset; + /* first read registers */ - sof_block_read(sdev, sdev->mmio_bar, sdev->dsp_oops_offset, xoops, - sizeof(*xoops)); + sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops)); + + /* note: variable AR register array is not read */ /* then get panic info */ - sof_block_read(sdev, sdev->mmio_bar, sdev->dsp_oops_offset + - sizeof(*xoops), panic_info, sizeof(*panic_info)); + offset += xoops->arch_hdr.totalsize; + sof_block_read(sdev, sdev->mmio_bar, offset, + panic_info, sizeof(*panic_info)); /* then get the stack */ - sof_block_read(sdev, sdev->mmio_bar, sdev->dsp_oops_offset + - sizeof(*xoops) + sizeof(*panic_info), stack, + offset += sizeof(*panic_info); + sof_block_read(sdev, sdev->mmio_bar, offset, stack, stack_words * sizeof(u32)); } diff --git a/sound/soc/sof/xtensa/core.c b/sound/soc/sof/xtensa/core.c index c3ad23a85b99..46a4905a9dce 100644 --- a/sound/soc/sof/xtensa/core.c +++ b/sound/soc/sof/xtensa/core.c @@ -110,7 +110,7 @@ static void xtensa_stack(struct snd_sof_dev *sdev, void *oops, u32 *stack, u32 stack_words) { struct sof_ipc_dsp_oops_xtensa *xoops = oops; - u32 stack_ptr = xoops->stack; + u32 stack_ptr = xoops->plat_hdr.stackptr; /* 4 * 8chars + 3 ws + 1 terminating NUL */ unsigned char buf[4 * 8 + 3 + 1]; int i; -- cgit From ad169f9f0dbb531cd68db921b351ccafcf684ae4 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 31 May 2019 22:25:26 +0800 Subject: ASoC: SOF: Intel: hda: Fix COMPILE_TEST build error while building without PCI: sound/soc/sof/intel/hda.o: In function `hda_dsp_probe': hda.c:(.text+0x79c): undefined reference to `pci_ioremap_bar' hda.c:(.text+0x79c): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `pci_ioremap_bar' hda.c:(.text+0x7c4): undefined reference to `pci_ioremap_bar' hda.c:(.text+0x7c4): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `pci_ioremap_bar' Reported-by: Hulk Robot Fixes: e13ef82a9ab8 ("ASoC: SOF: add COMPILE_TEST for PCI options") Signed-off-by: YueHaibing Acked-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 8f5c68861bbc..9e2e0f21524e 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -227,7 +227,9 @@ static int hda_init(struct snd_sof_dev *sdev) /* initialise hdac bus */ bus->addr = pci_resource_start(pci, 0); +#if IS_ENABLED(CONFIG_PCI) bus->remap_addr = pci_ioremap_bar(pci, 0); +#endif if (!bus->remap_addr) { dev_err(bus->dev, "error: ioremap error\n"); return -ENXIO; @@ -454,7 +456,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) goto hdac_bus_unmap; /* DSP base */ +#if IS_ENABLED(CONFIG_PCI) sdev->bar[HDA_DSP_BAR] = pci_ioremap_bar(pci, HDA_DSP_BAR); +#endif if (!sdev->bar[HDA_DSP_BAR]) { dev_err(sdev->dev, "error: ioremap error\n"); ret = -ENXIO; -- cgit From cbc0fa7b6e8c6180c18fd951d28197281a526330 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 1 Jun 2019 16:51:44 +0800 Subject: ASoC: da7219: Fix build error without CONFIG_I2C Fix gcc build error while CONFIG_I2C is not set sound/soc/codecs/da7219.c:2640:1: warning: data definition has no type or storage class module_i2c_driver(da7219_i2c_driver); ^~~~~~~~~~~~~~~~~ sound/soc/codecs/da7219.c:2640:1: error: type defaults to int in declaration of module_i2c_driver [-Werror=implicit-int] sound/soc/codecs/da7219.c:2640:1: warning: parameter names (without types) in function declaration sound/soc/codecs/da7219.c:2629:26: warning: da7219_i2c_driver defined but not used [-Wunused-variable] Reported-by: Hulk Robot Fixes: 6d817c0e9fd7 ("ASoC: codecs: Add da7219 codec driver") Signed-off-by: YueHaibing Signed-off-by: Mark Brown --- sound/soc/mediatek/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig index f70b7109f2b6..59980df5add6 100644 --- a/sound/soc/mediatek/Kconfig +++ b/sound/soc/mediatek/Kconfig @@ -132,7 +132,7 @@ config SND_SOC_MT8183_MT6358_TS3A227E_MAX98357A config SND_SOC_MT8183_DA7219_MAX98357A tristate "ASoC Audio driver for MT8183 with DA7219 MAX98357A codec" - depends on SND_SOC_MT8183 + depends on SND_SOC_MT8183 && I2C select SND_SOC_MT6358 select SND_SOC_MAX98357A select SND_SOC_DA7219 -- cgit From 5628c8979642a076f91ee86c3bae5ad251639af0 Mon Sep 17 00:00:00 2001 From: Yu-Hsuan Hsu Date: Tue, 4 Jun 2019 18:49:09 +0800 Subject: ASoC: max98090: remove 24-bit format support if RJ is 0 The supported formats are S16_LE and S24_LE now. However, by datasheet of max98090, S24_LE is only supported when it is in the right justified mode. We should remove 24-bit format if it is not in that mode to avoid triggering error. Signed-off-by: Yu-Hsuan Hsu Signed-off-by: Mark Brown --- sound/soc/codecs/max98090.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'sound') diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 7619ea31ab50..ada8c25e643d 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -1909,6 +1909,21 @@ static int max98090_configure_dmic(struct max98090_priv *max98090, return 0; } +static int max98090_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component); + unsigned int fmt = max98090->dai_fmt; + + /* Remove 24-bit format support if it is not in right justified mode. */ + if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_RIGHT_J) { + substream->runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; + snd_pcm_hw_constraint_msbits(substream->runtime, 0, 16, 16); + } + return 0; +} + static int max98090_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) @@ -2316,6 +2331,7 @@ EXPORT_SYMBOL_GPL(max98090_mic_detect); #define MAX98090_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) static const struct snd_soc_dai_ops max98090_dai_ops = { + .startup = max98090_dai_startup, .set_sysclk = max98090_dai_set_sysclk, .set_fmt = max98090_dai_set_fmt, .set_tdm_slot = max98090_set_tdm_slot, -- cgit From 7e46169a5f35762f335898a75d1b8a242f2ae0f5 Mon Sep 17 00:00:00 2001 From: Marcus Cooper Date: Mon, 3 Jun 2019 19:47:27 +0200 Subject: ASoC: sun4i-i2s: Fix sun8i tx channel offset mask Although not causing any noticeable issues, the mask for the channel offset is covering too many bits. Signed-off-by: Marcus Cooper Acked-by: Maxime Ripard Acked-by: Chen-Yu Tsai Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-i2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index d5ec1a20499d..8162e107e50b 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -110,7 +110,7 @@ #define SUN8I_I2S_TX_CHAN_MAP_REG 0x44 #define SUN8I_I2S_TX_CHAN_SEL_REG 0x34 -#define SUN8I_I2S_TX_CHAN_OFFSET_MASK GENMASK(13, 11) +#define SUN8I_I2S_TX_CHAN_OFFSET_MASK GENMASK(13, 12) #define SUN8I_I2S_TX_CHAN_OFFSET(offset) (offset << 12) #define SUN8I_I2S_TX_CHAN_EN_MASK GENMASK(11, 4) #define SUN8I_I2S_TX_CHAN_EN(num_chan) (((1 << num_chan) - 1) << 4) -- cgit From f9927000cb35f250051f0f1878db12ee2626eea1 Mon Sep 17 00:00:00 2001 From: Marcus Cooper Date: Mon, 3 Jun 2019 19:47:28 +0200 Subject: ASoC: sun4i-i2s: Add offset to RX channel select Whilst testing the capture functionality of the i2s on the newer SoCs it was noticed that the recording was somewhat distorted. This was due to the offset not being set correctly on the receiver side. Signed-off-by: Marcus Cooper Acked-by: Maxime Ripard Acked-by: Chen-Yu Tsai Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-i2s.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sound') diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 8162e107e50b..bc128e2a6096 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -460,6 +460,10 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, SUN8I_I2S_TX_CHAN_OFFSET_MASK, SUN8I_I2S_TX_CHAN_OFFSET(offset)); + + regmap_update_bits(i2s->regmap, SUN8I_I2S_RX_CHAN_SEL_REG, + SUN8I_I2S_TX_CHAN_OFFSET_MASK, + SUN8I_I2S_TX_CHAN_OFFSET(offset)); } regmap_field_write(i2s->field_fmt_mode, val); -- cgit From fb54555134b9b17835545e4d096b5550c27eed64 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Jun 2019 15:08:55 -0500 Subject: ASoC: Intel: cht_bsw_max98090: fix kernel oops with platform_name override The platform override code uses devm_ functions to allocate memory for the new name but the card device is not initialized. Fix by moving the init earlier. Fixes: 7e7e24d7c7ff0 ("ASoC: Intel: cht_bsw_max98090_ti: platform name fixup support") Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/cht_bsw_max98090_ti.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c index c0e0844f75b9..572e336ae0f9 100644 --- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c @@ -454,6 +454,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) } /* override plaform name, if required */ + snd_soc_card_cht.dev = &pdev->dev; mach = (&pdev->dev)->platform_data; platform_name = mach->mach_params.platform; @@ -463,7 +464,6 @@ static int snd_cht_mc_probe(struct platform_device *pdev) return ret_val; /* register the soc card */ - snd_soc_card_cht.dev = &pdev->dev; snd_soc_card_set_drvdata(&snd_soc_card_cht, drv); if (drv->quirks & QUIRK_PMC_PLT_CLK_0) -- cgit From 79136a016add1acb690fe8d96be50dd22a143d26 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Jun 2019 15:08:56 -0500 Subject: ASoC: Intel: bytcht_es8316: fix kernel oops with platform_name override The platform override code uses devm_ functions to allocate memory for the new name but the card device is not initialized. Fix by moving the init earlier. Fixes: e4bc6b1195f64 ("ASoC: Intel: bytcht_es8316: platform name fixup support") Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcht_es8316.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index e8c585ffd04d..128b57932a92 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -495,6 +495,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) } /* override plaform name, if required */ + byt_cht_es8316_card.dev = dev; platform_name = mach->mach_params.platform; ret = snd_soc_fixup_dai_links_platform_name(&byt_cht_es8316_card, @@ -575,7 +576,6 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) (quirk & BYT_CHT_ES8316_MONO_SPEAKER) ? "mono" : "stereo", mic_name[BYT_CHT_ES8316_MAP(quirk)]); byt_cht_es8316_card.long_name = long_name; - byt_cht_es8316_card.dev = dev; snd_soc_card_set_drvdata(&byt_cht_es8316_card, priv); ret = devm_snd_soc_register_card(dev, &byt_cht_es8316_card); -- cgit From 096701e8131425044d2054a0c210d6ea24ee7386 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Jun 2019 15:08:57 -0500 Subject: ASoC: Intel: cht_bsw_nau8824: fix kernel oops with platform_name override The platform override code uses devm_ functions to allocate memory for the new name but the card device is not initialized. Fix by moving the init earlier. Fixes: 4506db8043341 ("ASoC: Intel: cht_bsw_nau8824: platform name fixup support") Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/cht_bsw_nau8824.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/cht_bsw_nau8824.c b/sound/soc/intel/boards/cht_bsw_nau8824.c index 02c2fa239331..20fae391c75a 100644 --- a/sound/soc/intel/boards/cht_bsw_nau8824.c +++ b/sound/soc/intel/boards/cht_bsw_nau8824.c @@ -257,6 +257,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) snd_soc_card_set_drvdata(&snd_soc_card_cht, drv); /* override plaform name, if required */ + snd_soc_card_cht.dev = &pdev->dev; mach = (&pdev->dev)->platform_data; platform_name = mach->mach_params.platform; @@ -266,7 +267,6 @@ static int snd_cht_mc_probe(struct platform_device *pdev) return ret_val; /* register the soc card */ - snd_soc_card_cht.dev = &pdev->dev; ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht); if (ret_val) { dev_err(&pdev->dev, -- cgit From 9bbc799318a34061703f2a980e2b6df7fc6760f0 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Jun 2019 15:08:58 -0500 Subject: ASoC: Intel: cht_bsw_rt5672: fix kernel oops with platform_name override The platform override code uses devm_ functions to allocate memory for the new name but the card device is not initialized. Fix by moving the init earlier. Fixes: f403906da05cd ("ASoC: Intel: cht_bsw_rt5672: platform name fixup support") Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/cht_bsw_rt5672.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index 0f7770822388..1455e19d3768 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c @@ -426,6 +426,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) } /* override plaform name, if required */ + snd_soc_card_cht.dev = &pdev->dev; platform_name = mach->mach_params.platform; ret_val = snd_soc_fixup_dai_links_platform_name(&snd_soc_card_cht, @@ -443,7 +444,6 @@ static int snd_cht_mc_probe(struct platform_device *pdev) snd_soc_card_set_drvdata(&snd_soc_card_cht, drv); /* register the soc card */ - snd_soc_card_cht.dev = &pdev->dev; ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht); if (ret_val) { dev_err(&pdev->dev, -- cgit From 70fc53734e71ce51f46dfcfd1a1c319e1cfe080c Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Tue, 4 Jun 2019 11:31:02 +0800 Subject: ASoC: core: move DAI pre-links initiation to snd_soc_instantiate_card Kernel crashes when an ASoC component rebinding. The dai_link->platforms has been reset to NULL by soc_cleanup_platform() in soc_cleanup_card_resources() when un-registering component. However, it has no chance to re-allocate the dai_link->platforms when registering the component again. Move the DAI pre-links initiation from snd_soc_register_card() to snd_soc_instantiate_card() to make sure all DAI pre-links get initiated when component rebinding. As an example, by using the following commands: - echo -n max98357a > /sys/bus/platform/drivers/max98357a/unbind - echo -n max98357a > /sys/bus/platform/drivers/max98357a/bind Got the error message: "Unable to handle kernel NULL pointer dereference at virtual address". The call trace: snd_soc_is_matching_component+0x30/0x6c soc_bind_dai_link+0x16c/0x240 snd_soc_bind_card+0x1e4/0xb10 snd_soc_add_component+0x270/0x300 snd_soc_register_component+0x54/0x6c Signed-off-by: Tzung-Bi Shih Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 46042d41b79b..3fecd957995e 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2072,6 +2072,16 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) int ret, i, order; mutex_lock(&client_mutex); + for_each_card_prelinks(card, i, dai_link) { + ret = soc_init_dai_link(card, dai_link); + if (ret) { + soc_cleanup_platform(card); + dev_err(card->dev, "ASoC: failed to init link %s: %d\n", + dai_link->name, ret); + mutex_unlock(&client_mutex); + return ret; + } + } mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT); card->dapm.bias_level = SND_SOC_BIAS_OFF; @@ -2796,26 +2806,9 @@ static int snd_soc_bind_card(struct snd_soc_card *card) */ int snd_soc_register_card(struct snd_soc_card *card) { - int i, ret; - struct snd_soc_dai_link *link; - if (!card->name || !card->dev) return -EINVAL; - mutex_lock(&client_mutex); - for_each_card_prelinks(card, i, link) { - - ret = soc_init_dai_link(card, link); - if (ret) { - soc_cleanup_platform(card); - dev_err(card->dev, "ASoC: failed to init link %s\n", - link->name); - mutex_unlock(&client_mutex); - return ret; - } - } - mutex_unlock(&client_mutex); - dev_set_drvdata(card->dev, card); snd_soc_initialize_card_lists(card); -- cgit From 1f5253b08e06bc798e5254ede22d4238e9a52af8 Mon Sep 17 00:00:00 2001 From: Zhu Yingjiang Date: Wed, 22 May 2019 11:21:40 -0500 Subject: ASoC: SOF: Intel: hda: use the defined ppcap functions There are already defined ppcap and ppcap interrupt functions, use the already defined functions for easy code read. Fixes: 8a300c8fb17 ("ASoC: SOF: Intel: Add HDA controller for Intel DSP") Reviewed-by: Takashi Iwai Signed-off-by: Zhu Yingjiang Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 9e2e0f21524e..faf1a8ada091 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -548,13 +548,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) if (ret < 0) goto free_ipc_irq; - /* enable DSP features */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, - SOF_HDA_PPCTL_GPROCEN, SOF_HDA_PPCTL_GPROCEN); - - /* enable DSP IRQ */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, - SOF_HDA_PPCTL_PIE, SOF_HDA_PPCTL_PIE); + /* enable ppcap interrupt */ + hda_dsp_ctrl_ppcap_enable(sdev, true); + hda_dsp_ctrl_ppcap_int_enable(sdev, true); /* initialize waitq for code loading */ init_waitqueue_head(&sdev->waitq); -- cgit From 6d647b736a6b1cbf2f8deab0e6a94c34a6ea9d60 Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Wed, 22 May 2019 11:21:41 -0500 Subject: ALSA: hdac: fix memory release for SST and SOF drivers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During the integration of HDaudio support, we changed the way in which we get hdev in snd_hdac_ext_bus_device_init() to use one preallocated with devm_kzalloc(), however it still left kfree(hdev) in snd_hdac_ext_bus_device_exit(). It leads to oopses when trying to rmmod and modprobe. Fix it, by just removing kfree call. SOF also uses some of the snd_hdac_ functions for HDAudio support but allocated the memory with kzalloc. A matching fix is provided separately to align all users of the snd_hdac_ library. Fixes: 6298542fa33b ("ALSA: hdac: remove memory allocation from snd_hdac_ext_bus_device_init") Reviewed-by: Takashi Iwai Signed-off-by: Amadeusz Sławiński Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/hda/ext/hdac_ext_bus.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound') diff --git a/sound/hda/ext/hdac_ext_bus.c b/sound/hda/ext/hdac_ext_bus.c index 9c37d9af3023..08cc0ce3b924 100644 --- a/sound/hda/ext/hdac_ext_bus.c +++ b/sound/hda/ext/hdac_ext_bus.c @@ -173,7 +173,6 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_init); void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev) { snd_hdac_device_exit(hdev); - kfree(hdev); } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_exit); -- cgit From 04268bf2757a125616b6c2140e6250f43b7b737a Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Wed, 5 Jun 2019 15:45:52 +0200 Subject: SoC: rt274: Fix internal jack assignment in set_jack callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we call snd_soc_component_set_jack(component, NULL, NULL) we should set rt274->jack to passed jack, so when interrupt is triggered it calls snd_soc_jack_report(rt274->jack, ...) with proper value. This fixes problem in machine where in register, we call snd_soc_register(component, &headset, NULL), which just calls rt274_mic_detect via callback. Now when machine driver is removed "headset" will be gone, so we need to tell codec driver that it's gone with: snd_soc_register(component, NULL, NULL), but we also need to be able to handle NULL jack argument here gracefully. If we don't set it to NULL, next time the rt274_irq runs it will call snd_soc_jack_report with first argument being invalid pointer and there will be Oops. Signed-off-by: Amadeusz Sławiński Signed-off-by: Mark Brown --- sound/soc/codecs/rt274.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt274.c b/sound/soc/codecs/rt274.c index adf59039a3b6..cdd312db3e78 100644 --- a/sound/soc/codecs/rt274.c +++ b/sound/soc/codecs/rt274.c @@ -405,6 +405,8 @@ static int rt274_mic_detect(struct snd_soc_component *component, { struct rt274_priv *rt274 = snd_soc_component_get_drvdata(component); + rt274->jack = jack; + if (jack == NULL) { /* Disable jack detection */ regmap_update_bits(rt274->regmap, RT274_EAPD_GPIO_IRQ_CTRL, @@ -412,7 +414,6 @@ static int rt274_mic_detect(struct snd_soc_component *component, return 0; } - rt274->jack = jack; regmap_update_bits(rt274->regmap, RT274_EAPD_GPIO_IRQ_CTRL, RT274_IRQ_EN, RT274_IRQ_EN); -- cgit From 495f926c68ddb905a7a0192963096138c6a934e1 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Fri, 7 Jun 2019 22:07:06 -0700 Subject: ASoC: core: Fix deadlock in snd_soc_instantiate_card() Move the client_mutex lock to snd_soc_unbind_card() before removing link components. This prevents the deadlock in the error path in snd_soc_instantiate_card(). Fixes: 34ac3c3eb8 (ASoC: core: lock client_mutex while removing link components) Reported-by: kernelci.org bot Signed-off-by: Ranjani Sridharan Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 3fecd957995e..41c0cfaf2db5 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1008,14 +1008,12 @@ static void soc_remove_link_components(struct snd_soc_card *card, struct snd_soc_component *component; struct snd_soc_rtdcom_list *rtdcom; - mutex_lock(&client_mutex); for_each_rtdcom(rtd, rtdcom) { component = rtdcom->component; if (component->driver->remove_order == order) soc_remove_component(component); } - mutex_unlock(&client_mutex); } static void soc_remove_dai_links(struct snd_soc_card *card) @@ -2839,12 +2837,14 @@ static void snd_soc_unbind_card(struct snd_soc_card *card, bool unregister) snd_soc_dapm_shutdown(card); snd_soc_flush_all_delayed_work(card); + mutex_lock(&client_mutex); /* remove all components used by DAI links on this card */ for_each_comp_order(order) { for_each_card_rtds(card, rtd) { soc_remove_link_components(card, rtd, order); } } + mutex_unlock(&client_mutex); soc_cleanup_card_resources(card); if (!unregister) -- cgit From 3da428ff2aa5a5191ba2f1630eea75f03242f3f2 Mon Sep 17 00:00:00 2001 From: Alex Levin Date: Fri, 7 Jun 2019 15:19:11 -0700 Subject: ASoC: Intel: sst: fix kmalloc call with wrong flags When calling kmalloc with GFP_KERNEL in case CONFIG_SLOB is unset, kmem_cache_alloc_trace is called. In case CONFIG_TRACING is set, kmem_cache_alloc_trace will ball slab_alloc, which will call slab_pre_alloc_hook which might_sleep_if. The context in which it is called in this case, the intel_sst_interrupt_mrfld, calling a sleeping kmalloc generates a BUG(): Fixes: 972b0d456e64 ("ASoC: Intel: remove GFP_ATOMIC, use GFP_KERNEL") [ 20.250671] BUG: sleeping function called from invalid context at mm/slab.h:422 [ 20.250683] in_atomic(): 1, irqs_disabled(): 1, pid: 1791, name: Chrome_IOThread [ 20.250690] CPU: 0 PID: 1791 Comm: Chrome_IOThread Tainted: G W 4.19.43 #61 [ 20.250693] Hardware name: GOOGLE Kefka, BIOS Google_Kefka.7287.337.0 03/02/2017 [ 20.250697] Call Trace: [ 20.250704] [ 20.250716] dump_stack+0x7e/0xc3 [ 20.250725] ___might_sleep+0x12a/0x140 [ 20.250731] kmem_cache_alloc_trace+0x53/0x1c5 [ 20.250736] ? update_cfs_rq_load_avg+0x17e/0x1aa [ 20.250740] ? cpu_load_update+0x6c/0xc2 [ 20.250746] sst_create_ipc_msg+0x2d/0x88 [ 20.250752] intel_sst_interrupt_mrfld+0x12a/0x22c [ 20.250758] __handle_irq_event_percpu+0x133/0x228 [ 20.250764] handle_irq_event_percpu+0x35/0x7a [ 20.250768] handle_irq_event+0x36/0x55 [ 20.250773] handle_fasteoi_irq+0xab/0x16c [ 20.250779] handle_irq+0xd9/0x11e [ 20.250785] do_IRQ+0x54/0xe0 [ 20.250791] common_interrupt+0xf/0xf [ 20.250795] [ 20.250800] RIP: 0010:__lru_cache_add+0x4e/0xad [ 20.250806] Code: 00 01 48 c7 c7 b8 df 01 00 65 48 03 3c 25 28 f1 00 00 48 8b 48 08 48 89 ca 48 ff ca f6 c1 01 48 0f 44 d0 f0 ff 42 34 0f b6 0f <89> ca fe c2 88 17 48 89 44 cf 08 80 fa 0f 74 0e 48 8b 08 66 85 c9 [ 20.250809] RSP: 0000:ffffa568810bfd98 EFLAGS: 00000202 ORIG_RAX: ffffffffffffffd6 [ 20.250814] RAX: ffffd3b904eb1940 RBX: ffffd3b904eb1940 RCX: 0000000000000004 [ 20.250817] RDX: ffffd3b904eb1940 RSI: ffffa10ee5c47450 RDI: ffffa10efba1dfb8 [ 20.250821] RBP: ffffa568810bfda8 R08: ffffa10ef9c741c1 R09: dead000000000100 [ 20.250824] R10: 0000000000000000 R11: 0000000000000000 R12: ffffa10ee8d52a40 [ 20.250827] R13: ffffa10ee8d52000 R14: ffffa10ee5c47450 R15: 800000013ac65067 [ 20.250835] lru_cache_add_active_or_unevictable+0x4e/0xb8 [ 20.250841] handle_mm_fault+0xd98/0x10c4 [ 20.250848] __do_page_fault+0x235/0x42d [ 20.250853] ? page_fault+0x8/0x30 [ 20.250858] do_page_fault+0x3d/0x17a [ 20.250862] ? page_fault+0x8/0x30 [ 20.250866] page_fault+0x1e/0x30 [ 20.250872] RIP: 0033:0x7962fdea9304 [ 20.250875] Code: 0f 11 4c 17 f0 c3 48 3b 15 f1 26 31 00 0f 83 e2 00 00 00 48 39 f7 72 0f 74 12 4c 8d 0c 16 4c 39 cf 0f 82 63 01 00 00 48 89 d1 a4 c3 80 fa 08 73 12 80 fa 04 73 1e 80 fa 01 77 26 72 05 0f b6 [ 20.250879] RSP: 002b:00007962f4db5468 EFLAGS: 00010206 [ 20.250883] RAX: 00003c8cc9d47008 RBX: 0000000000000000 RCX: 0000000000001b48 [ 20.250886] RDX: 0000000000002b40 RSI: 00003c8cc9551000 RDI: 00003c8cc9d48000 [ 20.250890] RBP: 00007962f4db5820 R08: 0000000000000000 R09: 00003c8cc9552b48 [ 20.250893] R10: 0000562dd1064d30 R11: 00003c8cc825b908 R12: 00003c8cc966d3c0 [ 20.250896] R13: 00003c8cc9e280c0 R14: 0000000000000000 R15: 0000000000000000 Signed-off-by: Alex Levin Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst/sst_pvt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/atom/sst/sst_pvt.c b/sound/soc/intel/atom/sst/sst_pvt.c index 00a37a09dc9b..dba0ca07ebf9 100644 --- a/sound/soc/intel/atom/sst/sst_pvt.c +++ b/sound/soc/intel/atom/sst/sst_pvt.c @@ -166,11 +166,11 @@ int sst_create_ipc_msg(struct ipc_post **arg, bool large) { struct ipc_post *msg; - msg = kzalloc(sizeof(*msg), GFP_KERNEL); + msg = kzalloc(sizeof(*msg), GFP_ATOMIC); if (!msg) return -ENOMEM; if (large) { - msg->mailbox_data = kzalloc(SST_MAILBOX_SIZE, GFP_KERNEL); + msg->mailbox_data = kzalloc(SST_MAILBOX_SIZE, GFP_ATOMIC); if (!msg->mailbox_data) { kfree(msg); return -ENOMEM; -- cgit