From 2fe08216fda33bbc1f80133b8fd560ffd094b987 Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Thu, 2 Jun 2022 15:57:57 +0200 Subject: ASoC: SOF: Fix potential NULL pointer dereference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cleanup path for sof_prepare_widgets_in_path() should check if unprepare callback exists before calling it, instead it checks if it does not exist. Fix the check. Signed-off-by: Amadeusz Sławiński Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20220602135757.3335351-1-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-audio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 8d740635a4bb..28976098a89e 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -318,7 +318,7 @@ sink_prepare: p->walking = false; if (ret < 0) { /* unprepare the source widget */ - if (!widget_ops[widget->id].ipc_unprepare && swidget->prepared) { + if (widget_ops[widget->id].ipc_unprepare && swidget->prepared) { widget_ops[widget->id].ipc_unprepare(swidget); swidget->prepared = false; } -- cgit v1.2.3 From 9688073ee98cb2894d5434fe91dd256383727089 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Tue, 31 May 2022 11:02:03 +0800 Subject: ASoC: fsl_sai: Add support for i.MX8MN The SAI module on i.MX8MN is almost same as i.MX8MP, So reuse same soc data as i.MX8MP. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1653966123-28217-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index fa950dde5310..e765da9a19e7 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -1293,6 +1293,7 @@ static const struct of_device_id fsl_sai_ids[] = { { .compatible = "fsl,imx8mm-sai", .data = &fsl_sai_imx8mm_data }, { .compatible = "fsl,imx8mp-sai", .data = &fsl_sai_imx8mp_data }, { .compatible = "fsl,imx8ulp-sai", .data = &fsl_sai_imx8ulp_data }, + { .compatible = "fsl,imx8mn-sai", .data = &fsl_sai_imx8mp_data }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, fsl_sai_ids); -- cgit v1.2.3 From d9a251a029f23e79c1ac394bc551ed5d536bc740 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 2 Jun 2022 12:08:25 +0300 Subject: ASoC: SOF: ipc-msg-injector: Propagate write errors correctly This code is supposed to propagate errors from simple_write_to_buffer() or return -EFAULT if "size != count". However "size" needs to be signed for the code to work correctly and the case where "size == 0" is not handled correctly. Fixes: 066c67624d8c ("ASoC: SOF: ipc-msg-injector: Add support for IPC4 messages") Fixes: 2f0b1b013bbc ("ASoC: SOF: debug: Add support for IPC message injection") Signed-off-by: Dan Carpenter Acked-by: Peter Ujfalusi Link: https://lore.kernel.org/r/Yph+Cd+JrfOH0i7z@kili Signed-off-by: Mark Brown --- sound/soc/sof/sof-client-ipc-msg-injector.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/sof-client-ipc-msg-injector.c b/sound/soc/sof/sof-client-ipc-msg-injector.c index 03490a4d4ae7..030cb97d7713 100644 --- a/sound/soc/sof/sof-client-ipc-msg-injector.c +++ b/sound/soc/sof/sof-client-ipc-msg-injector.c @@ -150,7 +150,7 @@ static ssize_t sof_msg_inject_dfs_write(struct file *file, const char __user *bu { struct sof_client_dev *cdev = file->private_data; struct sof_msg_inject_priv *priv = cdev->data; - size_t size; + ssize_t size; int ret; if (*ppos) @@ -158,8 +158,10 @@ static ssize_t sof_msg_inject_dfs_write(struct file *file, const char __user *bu size = simple_write_to_buffer(priv->tx_buffer, priv->max_msg_size, ppos, buffer, count); + if (size < 0) + return size; if (size != count) - return size > 0 ? -EFAULT : size; + return -EFAULT; memset(priv->rx_buffer, 0, priv->max_msg_size); @@ -179,7 +181,7 @@ static ssize_t sof_msg_inject_ipc4_dfs_write(struct file *file, struct sof_client_dev *cdev = file->private_data; struct sof_msg_inject_priv *priv = cdev->data; struct sof_ipc4_msg *ipc4_msg = priv->tx_buffer; - size_t size; + ssize_t size; int ret; if (*ppos) @@ -192,8 +194,10 @@ static ssize_t sof_msg_inject_ipc4_dfs_write(struct file *file, size = simple_write_to_buffer(&ipc4_msg->header_u64, sizeof(ipc4_msg->header_u64), ppos, buffer, count); + if (size < 0) + return size; if (size != sizeof(ipc4_msg->header_u64)) - return size > 0 ? -EFAULT : size; + return -EFAULT; count -= size; if (!count) { @@ -201,8 +205,10 @@ static ssize_t sof_msg_inject_ipc4_dfs_write(struct file *file, size = simple_write_to_buffer(ipc4_msg->data_ptr, priv->max_msg_size, ppos, buffer, count); + if (size < 0) + return size; if (size != count) - return size > 0 ? -EFAULT : size; + return -EFAULT; } ipc4_msg->data_size = count; -- cgit v1.2.3 From bedc357217e6e09623f6209c891fa8d57a737ac1 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 2 Jun 2022 12:09:35 +0300 Subject: ASoC: SOF: ipc-msg-injector: Fix reversed if statement This if statement is reversed. In fact, the condition can just be deleted because writing zero bytes is a no-op. Fixes: 066c67624d8c ("ASoC: SOF: ipc-msg-injector: Add support for IPC4 messages") Signed-off-by: Dan Carpenter Acked-by: Peter Ujfalusi Link: https://lore.kernel.org/r/Yph+T3PpGCdPsEDj@kili Signed-off-by: Mark Brown --- sound/soc/sof/sof-client-ipc-msg-injector.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/sof-client-ipc-msg-injector.c b/sound/soc/sof/sof-client-ipc-msg-injector.c index 030cb97d7713..6bdfa527b7f7 100644 --- a/sound/soc/sof/sof-client-ipc-msg-injector.c +++ b/sound/soc/sof/sof-client-ipc-msg-injector.c @@ -200,16 +200,14 @@ static ssize_t sof_msg_inject_ipc4_dfs_write(struct file *file, return -EFAULT; count -= size; - if (!count) { - /* Copy the payload */ - size = simple_write_to_buffer(ipc4_msg->data_ptr, - priv->max_msg_size, ppos, buffer, - count); - if (size < 0) - return size; - if (size != count) - return -EFAULT; - } + /* Copy the payload */ + size = simple_write_to_buffer(ipc4_msg->data_ptr, + priv->max_msg_size, ppos, buffer, + count); + if (size < 0) + return size; + if (size != count) + return -EFAULT; ipc4_msg->data_size = count; -- cgit v1.2.3 From d1f5272c0f7d2e53c6f2480f46725442776f5f78 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Thu, 26 May 2022 13:21:28 -0500 Subject: ASoC: wm8962: Fix suspend while playing music If the audio CODEC is playing sound when the system is suspended, it can be left in a state which throws the following error: wm8962 3-001a: ASoC: error at soc_component_read_no_lock on wm8962.3-001a: -16 Once this error has occurred, the audio will not work again until rebooted. Fix this by configuring SET_SYSTEM_SLEEP_PM_OPS. Signed-off-by: Adam Ford Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20220526182129.538472-1-aford173@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8962.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 34cd5a2a997c..5cca89364280 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3868,6 +3868,7 @@ static int wm8962_runtime_suspend(struct device *dev) #endif static const struct dev_pm_ops wm8962_pm = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) SET_RUNTIME_PM_OPS(wm8962_runtime_suspend, wm8962_runtime_resume, NULL) }; -- cgit v1.2.3 From 8259610c2ec01c5cbfb61882ae176aabacac9c19 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 3 Jun 2022 14:39:37 +0200 Subject: ASoC: es8328: Fix event generation for deemphasis control Currently the put() method for the deemphasis control returns 0 when a new value is written to the control even if the value changed, meaning events are not generated. Fix this, skip the work of updating the value when it is unchanged and then return 1 after having done so. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220603123937.4013603-1-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/es8328.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c index 3f00ead97006..dd53dfd87b04 100644 --- a/sound/soc/codecs/es8328.c +++ b/sound/soc/codecs/es8328.c @@ -161,13 +161,16 @@ static int es8328_put_deemph(struct snd_kcontrol *kcontrol, if (deemph > 1) return -EINVAL; + if (es8328->deemph == deemph) + return 0; + ret = es8328_set_deemph(component); if (ret < 0) return ret; es8328->deemph = deemph; - return 0; + return 1; } -- cgit v1.2.3 From 2abdf9f80019e8244d3806ed0e1c9f725e50b452 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 3 Jun 2022 13:50:03 +0200 Subject: ASoC: wm_adsp: Fix event generation for wm_adsp_fw_put() Currently wm_adsp_fw_put() returns 0 rather than 1 when updating the value of the control, meaning that no event is generated to userspace. Fix this by setting the default return value to 1, the code already exits early with a return value of 0 if the value is unchanged. Signed-off-by: Mark Brown Reviewed-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20220603115003.3865834-1-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index e32c8ded181d..9cfd4f18493f 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -333,7 +333,7 @@ int wm_adsp_fw_put(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; struct wm_adsp *dsp = snd_soc_component_get_drvdata(component); - int ret = 0; + int ret = 1; if (ucontrol->value.enumerated.item[0] == dsp[e->shift_l].fw) return 0; -- cgit v1.2.3 From f9e9bdd5bb180325256e3bdfeb9c4c6526133478 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 6 Jun 2022 15:37:46 -0500 Subject: ASoC: Realtek/Maxim SoundWire codecs: disable pm_runtime on remove When binding/unbinding codec drivers, the following warnings are thrown: [ 107.266879] rt715-sdca sdw:3:025d:0714:01: Unbalanced pm_runtime_enable! [ 306.879700] rt711-sdca sdw:0:025d:0711:01: Unbalanced pm_runtime_enable! Add a remove callback for all Realtek/Maxim SoundWire codecs and remove this warning. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20220606203752.144159-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/max98373-sdw.c | 12 +++++++++++- sound/soc/codecs/rt1308-sdw.c | 11 +++++++++++ sound/soc/codecs/rt1316-sdw.c | 11 +++++++++++ sound/soc/codecs/rt5682-sdw.c | 5 ++++- sound/soc/codecs/rt700-sdw.c | 6 +++++- sound/soc/codecs/rt711-sdca-sdw.c | 6 +++++- sound/soc/codecs/rt711-sdw.c | 6 +++++- sound/soc/codecs/rt715-sdca-sdw.c | 12 ++++++++++++ sound/soc/codecs/rt715-sdw.c | 12 ++++++++++++ 9 files changed, 76 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c index f47e956d4f55..97b64477dde6 100644 --- a/sound/soc/codecs/max98373-sdw.c +++ b/sound/soc/codecs/max98373-sdw.c @@ -862,6 +862,16 @@ static int max98373_sdw_probe(struct sdw_slave *slave, return max98373_init(slave, regmap); } +static int max98373_sdw_remove(struct sdw_slave *slave) +{ + struct max98373_priv *max98373 = dev_get_drvdata(&slave->dev); + + if (max98373->first_hw_init) + pm_runtime_disable(&slave->dev); + + return 0; +} + #if defined(CONFIG_OF) static const struct of_device_id max98373_of_match[] = { { .compatible = "maxim,max98373", }, @@ -893,7 +903,7 @@ static struct sdw_driver max98373_sdw_driver = { .pm = &max98373_pm, }, .probe = max98373_sdw_probe, - .remove = NULL, + .remove = max98373_sdw_remove, .ops = &max98373_slave_ops, .id_table = max98373_id, }; diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c index 1c11b42dd76e..72f673f278ee 100644 --- a/sound/soc/codecs/rt1308-sdw.c +++ b/sound/soc/codecs/rt1308-sdw.c @@ -691,6 +691,16 @@ static int rt1308_sdw_probe(struct sdw_slave *slave, return 0; } +static int rt1308_sdw_remove(struct sdw_slave *slave) +{ + struct rt1308_sdw_priv *rt1308 = dev_get_drvdata(&slave->dev); + + if (rt1308->first_hw_init) + pm_runtime_disable(&slave->dev); + + return 0; +} + static const struct sdw_device_id rt1308_id[] = { SDW_SLAVE_ENTRY_EXT(0x025d, 0x1308, 0x2, 0, 0), {}, @@ -750,6 +760,7 @@ static struct sdw_driver rt1308_sdw_driver = { .pm = &rt1308_pm, }, .probe = rt1308_sdw_probe, + .remove = rt1308_sdw_remove, .ops = &rt1308_slave_ops, .id_table = rt1308_id, }; diff --git a/sound/soc/codecs/rt1316-sdw.c b/sound/soc/codecs/rt1316-sdw.c index 60baa9ff1907..2d6b5f9d4d77 100644 --- a/sound/soc/codecs/rt1316-sdw.c +++ b/sound/soc/codecs/rt1316-sdw.c @@ -676,6 +676,16 @@ static int rt1316_sdw_probe(struct sdw_slave *slave, return rt1316_sdw_init(&slave->dev, regmap, slave); } +static int rt1316_sdw_remove(struct sdw_slave *slave) +{ + struct rt1316_sdw_priv *rt1316 = dev_get_drvdata(&slave->dev); + + if (rt1316->first_hw_init) + pm_runtime_disable(&slave->dev); + + return 0; +} + static const struct sdw_device_id rt1316_id[] = { SDW_SLAVE_ENTRY_EXT(0x025d, 0x1316, 0x3, 0x1, 0), {}, @@ -735,6 +745,7 @@ static struct sdw_driver rt1316_sdw_driver = { .pm = &rt1316_pm, }, .probe = rt1316_sdw_probe, + .remove = rt1316_sdw_remove, .ops = &rt1316_slave_ops, .id_table = rt1316_id, }; diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index 248257a2e4e0..f04e18c32489 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -719,9 +719,12 @@ static int rt5682_sdw_remove(struct sdw_slave *slave) { struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev); - if (rt5682 && rt5682->hw_init) + if (rt5682->hw_init) cancel_delayed_work_sync(&rt5682->jack_detect_work); + if (rt5682->first_hw_init) + pm_runtime_disable(&slave->dev); + return 0; } diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c index bda594899664..f7439e40ca8b 100644 --- a/sound/soc/codecs/rt700-sdw.c +++ b/sound/soc/codecs/rt700-sdw.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include "rt700.h" @@ -463,11 +464,14 @@ static int rt700_sdw_remove(struct sdw_slave *slave) { struct rt700_priv *rt700 = dev_get_drvdata(&slave->dev); - if (rt700 && rt700->hw_init) { + if (rt700->hw_init) { cancel_delayed_work_sync(&rt700->jack_detect_work); cancel_delayed_work_sync(&rt700->jack_btn_check_work); } + if (rt700->first_hw_init) + pm_runtime_disable(&slave->dev); + return 0; } diff --git a/sound/soc/codecs/rt711-sdca-sdw.c b/sound/soc/codecs/rt711-sdca-sdw.c index aaf5af153d3f..c722a2b0041f 100644 --- a/sound/soc/codecs/rt711-sdca-sdw.c +++ b/sound/soc/codecs/rt711-sdca-sdw.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "rt711-sdca.h" #include "rt711-sdca-sdw.h" @@ -364,11 +365,14 @@ static int rt711_sdca_sdw_remove(struct sdw_slave *slave) { struct rt711_sdca_priv *rt711 = dev_get_drvdata(&slave->dev); - if (rt711 && rt711->hw_init) { + if (rt711->hw_init) { cancel_delayed_work_sync(&rt711->jack_detect_work); cancel_delayed_work_sync(&rt711->jack_btn_check_work); } + if (rt711->first_hw_init) + pm_runtime_disable(&slave->dev); + return 0; } diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c index bda2cc9439c9..f49c94baa37c 100644 --- a/sound/soc/codecs/rt711-sdw.c +++ b/sound/soc/codecs/rt711-sdw.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include "rt711.h" @@ -464,12 +465,15 @@ static int rt711_sdw_remove(struct sdw_slave *slave) { struct rt711_priv *rt711 = dev_get_drvdata(&slave->dev); - if (rt711 && rt711->hw_init) { + if (rt711->hw_init) { cancel_delayed_work_sync(&rt711->jack_detect_work); cancel_delayed_work_sync(&rt711->jack_btn_check_work); cancel_work_sync(&rt711->calibration_work); } + if (rt711->first_hw_init) + pm_runtime_disable(&slave->dev); + return 0; } diff --git a/sound/soc/codecs/rt715-sdca-sdw.c b/sound/soc/codecs/rt715-sdca-sdw.c index 0ecd2948f7aa..13e731d16675 100644 --- a/sound/soc/codecs/rt715-sdca-sdw.c +++ b/sound/soc/codecs/rt715-sdca-sdw.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include "rt715-sdca.h" @@ -193,6 +194,16 @@ static int rt715_sdca_sdw_probe(struct sdw_slave *slave, return rt715_sdca_init(&slave->dev, mbq_regmap, regmap, slave); } +static int rt715_sdca_sdw_remove(struct sdw_slave *slave) +{ + struct rt715_sdca_priv *rt715 = dev_get_drvdata(&slave->dev); + + if (rt715->first_hw_init) + pm_runtime_disable(&slave->dev); + + return 0; +} + static const struct sdw_device_id rt715_sdca_id[] = { SDW_SLAVE_ENTRY_EXT(0x025d, 0x715, 0x3, 0x1, 0), SDW_SLAVE_ENTRY_EXT(0x025d, 0x714, 0x3, 0x1, 0), @@ -267,6 +278,7 @@ static struct sdw_driver rt715_sdw_driver = { .pm = &rt715_pm, }, .probe = rt715_sdca_sdw_probe, + .remove = rt715_sdca_sdw_remove, .ops = &rt715_sdca_slave_ops, .id_table = rt715_sdca_id, }; diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c index a7b21b03c08b..b047bf87a100 100644 --- a/sound/soc/codecs/rt715-sdw.c +++ b/sound/soc/codecs/rt715-sdw.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -514,6 +515,16 @@ static int rt715_sdw_probe(struct sdw_slave *slave, return 0; } +static int rt715_sdw_remove(struct sdw_slave *slave) +{ + struct rt715_priv *rt715 = dev_get_drvdata(&slave->dev); + + if (rt715->first_hw_init) + pm_runtime_disable(&slave->dev); + + return 0; +} + static const struct sdw_device_id rt715_id[] = { SDW_SLAVE_ENTRY_EXT(0x025d, 0x714, 0x2, 0, 0), SDW_SLAVE_ENTRY_EXT(0x025d, 0x715, 0x2, 0, 0), @@ -575,6 +586,7 @@ static struct sdw_driver rt715_sdw_driver = { .pm = &rt715_pm, }, .probe = rt715_sdw_probe, + .remove = rt715_sdw_remove, .ops = &rt715_slave_ops, .id_table = rt715_id, }; -- cgit v1.2.3 From 716c2e7e1608a89423ec84398b99ff2fa855d161 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 6 Jun 2022 15:37:47 -0500 Subject: ASoC: rt711-sdca-sdw: fix calibrate mutex initialization In codec driver bind/unbind test, the following warning is thrown: DEBUG_LOCKS_WARN_ON(lock->magic != lock) ... [ 699.182495] rt711_sdca_jack_init+0x1b/0x1d0 [snd_soc_rt711_sdca] [ 699.182498] rt711_sdca_set_jack_detect+0x3b/0x90 [snd_soc_rt711_sdca] [ 699.182500] snd_soc_component_set_jack+0x24/0x50 [snd_soc_core] A quick check in the code shows that the 'calibrate_mutex' used by this driver are not initialized at probe time. Moving the initialization to the probe removes the issue. BugLink: https://github.com/thesofproject/linux/issues/3644 Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20220606203752.144159-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt711-sdca-sdw.c | 3 +++ sound/soc/codecs/rt711-sdca.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt711-sdca-sdw.c b/sound/soc/codecs/rt711-sdca-sdw.c index c722a2b0041f..a085b2f530aa 100644 --- a/sound/soc/codecs/rt711-sdca-sdw.c +++ b/sound/soc/codecs/rt711-sdca-sdw.c @@ -373,6 +373,9 @@ static int rt711_sdca_sdw_remove(struct sdw_slave *slave) if (rt711->first_hw_init) pm_runtime_disable(&slave->dev); + mutex_destroy(&rt711->calibrate_mutex); + mutex_destroy(&rt711->disable_irq_lock); + return 0; } diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c index 57629c18db38..af73bcb4560a 100644 --- a/sound/soc/codecs/rt711-sdca.c +++ b/sound/soc/codecs/rt711-sdca.c @@ -1412,6 +1412,7 @@ int rt711_sdca_init(struct device *dev, struct regmap *regmap, rt711->regmap = regmap; rt711->mbq_regmap = mbq_regmap; + mutex_init(&rt711->calibrate_mutex); mutex_init(&rt711->disable_irq_lock); /* @@ -1550,7 +1551,6 @@ int rt711_sdca_io_init(struct device *dev, struct sdw_slave *slave) rt711_sdca_jack_detect_handler); INIT_DELAYED_WORK(&rt711->jack_btn_check_work, rt711_sdca_btn_check_handler); - mutex_init(&rt711->calibrate_mutex); } /* calibration */ -- cgit v1.2.3 From 768ad6d80db2dbbb1bfbb5e616d701a0b560f12a Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 6 Jun 2022 15:37:48 -0500 Subject: ASoC: Intel: sof_sdw: handle errors on card registration If the card registration fails, typically because of deferred probes, the device properties added for headset codecs are not removed, which leads to kernel oopses in driver bind/unbind tests. We already clean-up the device properties when the card is removed, this code can be moved as a helper and called upon card registration errors. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20220606203752.144159-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 51 +++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 22 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 1f00679b4240..ad826ad82d51 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1398,6 +1398,33 @@ static struct snd_soc_card card_sof_sdw = { .late_probe = sof_sdw_card_late_probe, }; +static void mc_dailink_exit_loop(struct snd_soc_card *card) +{ + struct snd_soc_dai_link *link; + int ret; + int i, j; + + for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { + if (!codec_info_list[i].exit) + continue; + /* + * We don't need to call .exit function if there is no matched + * dai link found. + */ + for_each_card_prelinks(card, j, link) { + if (!strcmp(link->codecs[0].dai_name, + codec_info_list[i].dai_name)) { + ret = codec_info_list[i].exit(card, link); + if (ret) + dev_warn(card->dev, + "codec exit failed %d\n", + ret); + break; + } + } + } +} + static int mc_probe(struct platform_device *pdev) { struct snd_soc_card *card = &card_sof_sdw; @@ -1462,6 +1489,7 @@ static int mc_probe(struct platform_device *pdev) ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) { dev_err(card->dev, "snd_soc_register_card failed %d\n", ret); + mc_dailink_exit_loop(card); return ret; } @@ -1473,29 +1501,8 @@ static int mc_probe(struct platform_device *pdev) static int mc_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); - struct snd_soc_dai_link *link; - int ret; - int i, j; - for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { - if (!codec_info_list[i].exit) - continue; - /* - * We don't need to call .exit function if there is no matched - * dai link found. - */ - for_each_card_prelinks(card, j, link) { - if (!strcmp(link->codecs[0].dai_name, - codec_info_list[i].dai_name)) { - ret = codec_info_list[i].exit(card, link); - if (ret) - dev_warn(&pdev->dev, - "codec exit failed %d\n", - ret); - break; - } - } - } + mc_dailink_exit_loop(card); return 0; } -- cgit v1.2.3 From 74d40901ebad7c466a95b1ae3c6891f1ba09786f Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 6 Jun 2022 15:37:49 -0500 Subject: ASoC: rt711: fix calibrate mutex initialization Follow the same flow as rt711-sdca and initialize all mutexes at probe time. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20220606203752.144159-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt711-sdw.c | 3 +++ sound/soc/codecs/rt711.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c index f49c94baa37c..4fe68bcf2a7c 100644 --- a/sound/soc/codecs/rt711-sdw.c +++ b/sound/soc/codecs/rt711-sdw.c @@ -474,6 +474,9 @@ static int rt711_sdw_remove(struct sdw_slave *slave) if (rt711->first_hw_init) pm_runtime_disable(&slave->dev); + mutex_destroy(&rt711->calibrate_mutex); + mutex_destroy(&rt711->disable_irq_lock); + return 0; } diff --git a/sound/soc/codecs/rt711.c b/sound/soc/codecs/rt711.c index 9838fb4d5b9c..1e35ba433a7e 100644 --- a/sound/soc/codecs/rt711.c +++ b/sound/soc/codecs/rt711.c @@ -1204,6 +1204,7 @@ int rt711_init(struct device *dev, struct regmap *sdw_regmap, rt711->sdw_regmap = sdw_regmap; rt711->regmap = regmap; + mutex_init(&rt711->calibrate_mutex); mutex_init(&rt711->disable_irq_lock); /* @@ -1318,7 +1319,6 @@ int rt711_io_init(struct device *dev, struct sdw_slave *slave) rt711_jack_detect_handler); INIT_DELAYED_WORK(&rt711->jack_btn_check_work, rt711_btn_check_handler); - mutex_init(&rt711->calibrate_mutex); INIT_WORK(&rt711->calibration_work, rt711_calibration_work); schedule_work(&rt711->calibration_work); } -- cgit v1.2.3 From 05ba4c00fa9cb077a0dd91f5e6056951a787f63c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 6 Jun 2022 15:37:50 -0500 Subject: ASoC: rt7*-sdw: harden jack_detect_handler Realtek headset codec drivers typically check if the card is instantiated before proceeding with the jack detection. The rt700, rt711 and rt711-sdca are however missing a check on the card pointer, which can lead to NULL dereferences encountered in driver bind/unbind tests. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20220606203752.144159-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt700.c | 2 +- sound/soc/codecs/rt711-sdca.c | 2 +- sound/soc/codecs/rt711.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt700.c b/sound/soc/codecs/rt700.c index af32295fa9b9..4a99d5f4706f 100644 --- a/sound/soc/codecs/rt700.c +++ b/sound/soc/codecs/rt700.c @@ -162,7 +162,7 @@ static void rt700_jack_detect_handler(struct work_struct *work) if (!rt700->hs_jack) return; - if (!rt700->component->card->instantiated) + if (!rt700->component->card || !rt700->component->card->instantiated) return; reg = RT700_VERB_GET_PIN_SENSE | RT700_HP_OUT; diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c index af73bcb4560a..93b36f05cb56 100644 --- a/sound/soc/codecs/rt711-sdca.c +++ b/sound/soc/codecs/rt711-sdca.c @@ -294,7 +294,7 @@ static void rt711_sdca_jack_detect_handler(struct work_struct *work) if (!rt711->hs_jack) return; - if (!rt711->component->card->instantiated) + if (!rt711->component->card || !rt711->component->card->instantiated) return; /* SDW_SCP_SDCA_INT_SDCA_0 is used for jack detection */ diff --git a/sound/soc/codecs/rt711.c b/sound/soc/codecs/rt711.c index 1e35ba433a7e..2f445b27305a 100644 --- a/sound/soc/codecs/rt711.c +++ b/sound/soc/codecs/rt711.c @@ -242,7 +242,7 @@ static void rt711_jack_detect_handler(struct work_struct *work) if (!rt711->hs_jack) return; - if (!rt711->component->card->instantiated) + if (!rt711->component->card || !rt711->component->card->instantiated) return; if (pm_runtime_status_suspended(rt711->slave->dev.parent)) { -- cgit v1.2.3 From a49267a3bd102e3991514e884aac89cc0d0b5f35 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 6 Jun 2022 15:37:51 -0500 Subject: ASoC: codecs: rt700/rt711/rt711-sdca: initialize workqueues in probe The workqueues are initialized in the io_init functions, which isn't quite right. In some tests, this leads to warnings throw from __queue_delayed_work() WARN_ON_FUNCTION_MISMATCH(timer->function, delayed_work_timer_fn); Move all the initializations to the probe functions. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20220606203752.144159-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt700.c | 12 +++++------- sound/soc/codecs/rt711-sdca.c | 10 +++------- sound/soc/codecs/rt711.c | 12 +++++------- 3 files changed, 13 insertions(+), 21 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt700.c b/sound/soc/codecs/rt700.c index 4a99d5f4706f..7a6cf3434591 100644 --- a/sound/soc/codecs/rt700.c +++ b/sound/soc/codecs/rt700.c @@ -1115,6 +1115,11 @@ int rt700_init(struct device *dev, struct regmap *sdw_regmap, mutex_init(&rt700->disable_irq_lock); + INIT_DELAYED_WORK(&rt700->jack_detect_work, + rt700_jack_detect_handler); + INIT_DELAYED_WORK(&rt700->jack_btn_check_work, + rt700_btn_check_handler); + /* * Mark hw_init to false * HW init will be performed when device reports present @@ -1209,13 +1214,6 @@ int rt700_io_init(struct device *dev, struct sdw_slave *slave) /* Finish Initial Settings, set power to D3 */ regmap_write(rt700->regmap, RT700_SET_AUDIO_POWER_STATE, AC_PWRST_D3); - if (!rt700->first_hw_init) { - INIT_DELAYED_WORK(&rt700->jack_detect_work, - rt700_jack_detect_handler); - INIT_DELAYED_WORK(&rt700->jack_btn_check_work, - rt700_btn_check_handler); - } - /* * if set_jack callback occurred early than io_init, * we set up the jack detection function now diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c index 93b36f05cb56..2b3b77577d1f 100644 --- a/sound/soc/codecs/rt711-sdca.c +++ b/sound/soc/codecs/rt711-sdca.c @@ -1415,6 +1415,9 @@ int rt711_sdca_init(struct device *dev, struct regmap *regmap, mutex_init(&rt711->calibrate_mutex); mutex_init(&rt711->disable_irq_lock); + INIT_DELAYED_WORK(&rt711->jack_detect_work, rt711_sdca_jack_detect_handler); + INIT_DELAYED_WORK(&rt711->jack_btn_check_work, rt711_sdca_btn_check_handler); + /* * Mark hw_init to false * HW init will be performed when device reports present @@ -1546,13 +1549,6 @@ int rt711_sdca_io_init(struct device *dev, struct sdw_slave *slave) rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, RT711_PUSH_BTN_INT_CTL0, 0x20, 0x00); - if (!rt711->first_hw_init) { - INIT_DELAYED_WORK(&rt711->jack_detect_work, - rt711_sdca_jack_detect_handler); - INIT_DELAYED_WORK(&rt711->jack_btn_check_work, - rt711_sdca_btn_check_handler); - } - /* calibration */ ret = rt711_sdca_calibration(rt711); if (ret < 0) diff --git a/sound/soc/codecs/rt711.c b/sound/soc/codecs/rt711.c index 2f445b27305a..5709a6bbe8fc 100644 --- a/sound/soc/codecs/rt711.c +++ b/sound/soc/codecs/rt711.c @@ -1207,6 +1207,10 @@ int rt711_init(struct device *dev, struct regmap *sdw_regmap, mutex_init(&rt711->calibrate_mutex); mutex_init(&rt711->disable_irq_lock); + INIT_DELAYED_WORK(&rt711->jack_detect_work, rt711_jack_detect_handler); + INIT_DELAYED_WORK(&rt711->jack_btn_check_work, rt711_btn_check_handler); + INIT_WORK(&rt711->calibration_work, rt711_calibration_work); + /* * Mark hw_init to false * HW init will be performed when device reports present @@ -1314,14 +1318,8 @@ int rt711_io_init(struct device *dev, struct sdw_slave *slave) if (rt711->first_hw_init) rt711_calibration(rt711); - else { - INIT_DELAYED_WORK(&rt711->jack_detect_work, - rt711_jack_detect_handler); - INIT_DELAYED_WORK(&rt711->jack_btn_check_work, - rt711_btn_check_handler); - INIT_WORK(&rt711->calibration_work, rt711_calibration_work); + else schedule_work(&rt711->calibration_work); - } /* * if set_jack callback occurred early than io_init, -- cgit v1.2.3 From e02b99e9b79ff272e8c299a3ee53bdb194ca885e Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 6 Jun 2022 15:37:52 -0500 Subject: ASoC: codecs: rt700/rt711/rt711-sdca: resume bus/codec in .set_jack_detect The .set_jack_detect() codec component callback is invoked during card registration, which happens when the machine driver is probed. The issue is that this callback can race with the bus suspend/resume, and IO timeouts can happen. This can be reproduced very easily if the machine driver is 'blacklisted' and manually probed after the bus suspends. The bus and codec need to be re-initialized using pm_runtime helpers. Previous contributions tried to make sure accesses to the bus during the .set_jack_detect() component callback only happen when the bus is active. This was done by changing the regcache status on a component remove. This is however a layering violation, the regcache status should only be modified on device probe, suspend and resume. The component probe/remove should not modify how the device regcache is handled. This solution also didn't handle all the possible race conditions, and the RT700 headset codec was not handled. This patch tries to resume the codec device before handling the jack initializations. In case the codec has not yet been initialized, pm_runtime may not be enabled yet, so we don't squelch the -EACCES error code and only stop the jack information. When the codec reports as attached, the jack initialization will proceed as usual. BugLink: https://github.com/thesofproject/linux/issues/3643 Fixes: 7ad4d237e7c4a ('ASoC: rt711-sdca: Add RT711 SDCA vendor-specific driver') Fixes: 899b12542b089 ('ASoC: rt711: add snd_soc_component remove callback') Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20220606203752.144159-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt700.c | 16 +++++++++++++--- sound/soc/codecs/rt711-sdca.c | 26 ++++++++++++++------------ sound/soc/codecs/rt711.c | 24 +++++++++++++----------- 3 files changed, 40 insertions(+), 26 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt700.c b/sound/soc/codecs/rt700.c index 7a6cf3434591..9bceeeb830b1 100644 --- a/sound/soc/codecs/rt700.c +++ b/sound/soc/codecs/rt700.c @@ -315,17 +315,27 @@ static int rt700_set_jack_detect(struct snd_soc_component *component, struct snd_soc_jack *hs_jack, void *data) { struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component); + int ret; rt700->hs_jack = hs_jack; - if (!rt700->hw_init) { - dev_dbg(&rt700->slave->dev, - "%s hw_init not ready yet\n", __func__); + ret = pm_runtime_resume_and_get(component->dev); + if (ret < 0) { + if (ret != -EACCES) { + dev_err(component->dev, "%s: failed to resume %d\n", __func__, ret); + return ret; + } + + /* pm_runtime not enabled yet */ + dev_dbg(component->dev, "%s: skipping jack init for now\n", __func__); return 0; } rt700_jack_init(rt700); + pm_runtime_mark_last_busy(component->dev); + pm_runtime_put_autosuspend(component->dev); + return 0; } diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c index 2b3b77577d1f..dfe3c9299ebd 100644 --- a/sound/soc/codecs/rt711-sdca.c +++ b/sound/soc/codecs/rt711-sdca.c @@ -487,16 +487,27 @@ static int rt711_sdca_set_jack_detect(struct snd_soc_component *component, struct snd_soc_jack *hs_jack, void *data) { struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + int ret; rt711->hs_jack = hs_jack; - if (!rt711->hw_init) { - dev_dbg(&rt711->slave->dev, - "%s hw_init not ready yet\n", __func__); + ret = pm_runtime_resume_and_get(component->dev); + if (ret < 0) { + if (ret != -EACCES) { + dev_err(component->dev, "%s: failed to resume %d\n", __func__, ret); + return ret; + } + + /* pm_runtime not enabled yet */ + dev_dbg(component->dev, "%s: skipping jack init for now\n", __func__); return 0; } rt711_sdca_jack_init(rt711); + + pm_runtime_mark_last_busy(component->dev); + pm_runtime_put_autosuspend(component->dev); + return 0; } @@ -1190,14 +1201,6 @@ static int rt711_sdca_probe(struct snd_soc_component *component) return 0; } -static void rt711_sdca_remove(struct snd_soc_component *component) -{ - struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); - - regcache_cache_only(rt711->regmap, true); - regcache_cache_only(rt711->mbq_regmap, true); -} - static const struct snd_soc_component_driver soc_sdca_dev_rt711 = { .probe = rt711_sdca_probe, .controls = rt711_sdca_snd_controls, @@ -1207,7 +1210,6 @@ static const struct snd_soc_component_driver soc_sdca_dev_rt711 = { .dapm_routes = rt711_sdca_audio_map, .num_dapm_routes = ARRAY_SIZE(rt711_sdca_audio_map), .set_jack = rt711_sdca_set_jack_detect, - .remove = rt711_sdca_remove, .endianness = 1, }; diff --git a/sound/soc/codecs/rt711.c b/sound/soc/codecs/rt711.c index 5709a6bbe8fc..9df800abfc2d 100644 --- a/sound/soc/codecs/rt711.c +++ b/sound/soc/codecs/rt711.c @@ -457,17 +457,27 @@ static int rt711_set_jack_detect(struct snd_soc_component *component, struct snd_soc_jack *hs_jack, void *data) { struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component); + int ret; rt711->hs_jack = hs_jack; - if (!rt711->hw_init) { - dev_dbg(&rt711->slave->dev, - "%s hw_init not ready yet\n", __func__); + ret = pm_runtime_resume_and_get(component->dev); + if (ret < 0) { + if (ret != -EACCES) { + dev_err(component->dev, "%s: failed to resume %d\n", __func__, ret); + return ret; + } + + /* pm_runtime not enabled yet */ + dev_dbg(component->dev, "%s: skipping jack init for now\n", __func__); return 0; } rt711_jack_init(rt711); + pm_runtime_mark_last_busy(component->dev); + pm_runtime_put_autosuspend(component->dev); + return 0; } @@ -932,13 +942,6 @@ static int rt711_probe(struct snd_soc_component *component) return 0; } -static void rt711_remove(struct snd_soc_component *component) -{ - struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component); - - regcache_cache_only(rt711->regmap, true); -} - static const struct snd_soc_component_driver soc_codec_dev_rt711 = { .probe = rt711_probe, .set_bias_level = rt711_set_bias_level, @@ -949,7 +952,6 @@ static const struct snd_soc_component_driver soc_codec_dev_rt711 = { .dapm_routes = rt711_audio_map, .num_dapm_routes = ARRAY_SIZE(rt711_audio_map), .set_jack = rt711_set_jack_detect, - .remove = rt711_remove, .endianness = 1, }; -- cgit v1.2.3 From 5871321fb4558c55bf9567052b618ff0be6b975e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 4 Jun 2022 11:52:46 +0100 Subject: ASoC: ops: Fix off by one in range control validation We currently report that range controls accept a range of 0..(max-min) but accept writes in the range 0..(max-min+1). Remove that extra +1. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220604105246.4055214-1-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/soc-ops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index e693070f51fe..d867f449d82d 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -526,7 +526,7 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, return -EINVAL; if (mc->platform_max && tmp > mc->platform_max) return -EINVAL; - if (tmp > mc->max - mc->min + 1) + if (tmp > mc->max - mc->min) return -EINVAL; if (invert) @@ -547,7 +547,7 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, return -EINVAL; if (mc->platform_max && tmp > mc->platform_max) return -EINVAL; - if (tmp > mc->max - mc->min + 1) + if (tmp > mc->max - mc->min) return -EINVAL; if (invert) -- cgit v1.2.3 From ec3ad554b956d5dbefa1962c419f164ba223e6b3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 8 Jun 2022 02:09:16 +0000 Subject: ASoC: ak4613: cares Simple-Audio-Card case for TDM Renesas is the only user of ak4613 on upstream for now, and commit f28dbaa958fbd8 ("ASoC: ak4613: add TDM256 support") added TDM256 support. Renesas tested part of it, because of board connection. It was assuming ak4613 is probed via Audio-Graph-Card, but it might be probed via Simple-Audio-Card either. It will indicates WARNING in such case. This patch fixup it. Reported-by: Geert Uytterhoeven Signed-off-by: Kuninori Morimoto Tested-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/87h74v29f7.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/ak4613.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c index 55e773f92122..93606e5afd8f 100644 --- a/sound/soc/codecs/ak4613.c +++ b/sound/soc/codecs/ak4613.c @@ -868,10 +868,12 @@ static void ak4613_parse_of(struct ak4613_priv *priv, /* * connected STDI + * TDM support is assuming it is probed via Audio-Graph-Card style here. + * Default is SDTIx1 if it was probed via Simple-Audio-Card for now. */ sdti_num = of_graph_get_endpoint_count(np); - if (WARN_ON((sdti_num > 3) || (sdti_num < 1))) - return; + if ((sdti_num >= SDTx_MAX) || (sdti_num < 1)) + sdti_num = 1; AK4613_CONFIG_SDTI_set(priv, sdti_num); } -- cgit v1.2.3 From 537b4a0c8b9490d762e70c0ecec38144c83d0c37 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 9 Jun 2022 11:59:47 +0300 Subject: ASoC: SOF: Intel: hda-dsp: Expose hda_dsp_core_power_up() The hda_dsp_core_power_up() needs to be exposed so that it can be used in hda-loader.c to correct the boot flow. The first step must not unstall the core, it should only power up the core(s). Add sanity check for the core_mask while exposing it to be safe. Complements: 2a68ff846164 ("ASoC: SOF: Intel: hda: Revisit IMR boot sequence") Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20220609085949.29062-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 10 +++++++++- sound/soc/sof/intel/hda.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 000ea906670c..e24eea725acb 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -181,12 +181,20 @@ int hda_dsp_core_run(struct snd_sof_dev *sdev, unsigned int core_mask) * Power Management. */ -static int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask) +int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask) { + struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; + const struct sof_intel_dsp_desc *chip = hda->desc; unsigned int cpa; u32 adspcs; int ret; + /* restrict core_mask to host managed cores mask */ + core_mask &= chip->host_managed_cores_mask; + /* return if core_mask is not valid */ + if (!core_mask) + return 0; + /* update bits */ snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPCS, HDA_DSP_ADSPCS_SPA_MASK(core_mask), diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 3e0f7b0c586a..0f57ef5d9b8e 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -497,6 +497,7 @@ struct sof_intel_hda_stream { */ int hda_dsp_probe(struct snd_sof_dev *sdev); int hda_dsp_remove(struct snd_sof_dev *sdev); +int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask); int hda_dsp_core_run(struct snd_sof_dev *sdev, unsigned int core_mask); int hda_dsp_enable_core(struct snd_sof_dev *sdev, unsigned int core_mask); int hda_dsp_core_reset_power_down(struct snd_sof_dev *sdev, -- cgit v1.2.3 From fcb3c775f7073410965ce9414ddb2a1f339c502b Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 9 Jun 2022 11:59:48 +0300 Subject: ASoC: SOF: Intel: hda-loader: Make sure that the fw load sequence is followed The hda_dsp_enable_core() is powering up _and_ unstall the core in one call while the first step of the firmware loading must not unstall the core. The core can be unstalled only after the set cpb_cfp and the configuration of the IPC register for the ROM_CONTROL message. Complements: 2a68ff846164 ("ASoC: SOF: Intel: hda: Revisit IMR boot sequence") Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20220609085949.29062-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-loader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 64290125d7cd..103e62bcfa82 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -110,7 +110,7 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) int ret; /* step 1: power up corex */ - ret = hda_dsp_enable_core(sdev, chip->host_managed_cores_mask); + ret = hda_dsp_core_power_up(sdev, chip->host_managed_cores_mask); if (ret < 0) { if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) dev_err(sdev->dev, "error: dsp core 0/1 power up failed\n"); -- cgit v1.2.3 From 4643e10a17e549467420aaeeb35c9b3480716618 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 9 Jun 2022 11:59:49 +0300 Subject: ASoC: SOF: Intel: hda-loader: Clarify the cl_dsp_init() flow Update the comment for the cl_dsp_init() to clarify what is done by the function and use the chip->init_core_mask instead of BIT(0) when unstalling/running the init core. Complements: 2a68ff846164 ("ASoC: SOF: Intel: hda: Revisit IMR boot sequence") Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20220609085949.29062-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-loader.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 103e62bcfa82..d3ec5996a9a3 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -95,9 +95,9 @@ out_put: } /* - * first boot sequence has some extra steps. core 0 waits for power - * status on core 1, so power up core 1 also momentarily, keep it in - * reset/stall and then turn it off + * first boot sequence has some extra steps. + * power on all host managed cores and only unstall/run the boot core to boot the + * DSP then turn off all non boot cores (if any) is powered on. */ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) { @@ -127,7 +127,7 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) snd_sof_dsp_write(sdev, HDA_DSP_BAR, chip->ipc_req, ipc_hdr); /* step 3: unset core 0 reset state & unstall/run core 0 */ - ret = hda_dsp_core_run(sdev, BIT(0)); + ret = hda_dsp_core_run(sdev, chip->init_core_mask); if (ret < 0) { if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) dev_err(sdev->dev, -- cgit v1.2.3 From 5702b838dd9a8be634f9c6bdfd769422c26e9162 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 10 Jun 2022 11:47:35 +0300 Subject: ASoC: SOF: ipc3-topology: Move and correct size checks in sof_ipc3_control_load_bytes() Move the size checks prior to allocating memory as these checks do not need the data to be allocated and in case of an error we would not need to free the allocation. The max size must not be less than the size of struct sof_ipc_ctrl_data + struct sof_abi_hdr as the ABI header needs to be present under all circumstances. The check was incorrectly used or between the two size checks. Fixes: b5cee8feb1d4 ("ASoC: SOF: topology: Make control parsing IPC agnostic") Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20220610084735.19397-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc3-topology.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c index 043554d7cb4a..10740c55294d 100644 --- a/sound/soc/sof/ipc3-topology.c +++ b/sound/soc/sof/ipc3-topology.c @@ -1577,24 +1577,23 @@ static int sof_ipc3_control_load_bytes(struct snd_sof_dev *sdev, struct snd_sof_ struct sof_ipc_ctrl_data *cdata; int ret; - scontrol->ipc_control_data = kzalloc(scontrol->max_size, GFP_KERNEL); - if (!scontrol->ipc_control_data) - return -ENOMEM; - - if (scontrol->max_size < sizeof(*cdata) || - scontrol->max_size < sizeof(struct sof_abi_hdr)) { - ret = -EINVAL; - goto err; + if (scontrol->max_size < (sizeof(*cdata) + sizeof(struct sof_abi_hdr))) { + dev_err(sdev->dev, "%s: insufficient size for a bytes control: %zu.\n", + __func__, scontrol->max_size); + return -EINVAL; } - /* init the get/put bytes data */ if (scontrol->priv_size > scontrol->max_size - sizeof(*cdata)) { - dev_err(sdev->dev, "err: bytes data size %zu exceeds max %zu.\n", + dev_err(sdev->dev, + "%s: bytes data size %zu exceeds max %zu.\n", __func__, scontrol->priv_size, scontrol->max_size - sizeof(*cdata)); - ret = -EINVAL; - goto err; + return -EINVAL; } + scontrol->ipc_control_data = kzalloc(scontrol->max_size, GFP_KERNEL); + if (!scontrol->ipc_control_data) + return -ENOMEM; + scontrol->size = sizeof(struct sof_ipc_ctrl_data) + scontrol->priv_size; cdata = scontrol->ipc_control_data; -- cgit v1.2.3 From 46c80e72c16adff20f61240f887c4842e80cb6ec Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Fri, 10 Jun 2022 14:42:57 +0200 Subject: ASoC: Intel: avs: Fix parsing UUIDs in topology MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use correct type for parsing UUIDs, this eliminates warning present, when compiling with W=1. Fixes: 34ae2cd53673 ("ASoC: Intel: avs: Add topology parsing infrastructure") Reported-by: Pierre-Louis Bossart Signed-off-by: Amadeusz Sławiński Reviewed-by: Cezary Rojewski Link: https://lore.kernel.org/r/20220610124257.4160658-1-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/topology.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/avs/topology.c b/sound/soc/intel/avs/topology.c index 0d11cc8aab0b..6a06fe387d13 100644 --- a/sound/soc/intel/avs/topology.c +++ b/sound/soc/intel/avs/topology.c @@ -128,10 +128,10 @@ struct avs_tplg_token_parser { static int avs_parse_uuid_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset) { - struct snd_soc_tplg_vendor_value_elem *tuple = elem; + struct snd_soc_tplg_vendor_uuid_elem *tuple = elem; guid_t *val = (guid_t *)((u8 *)object + offset); - guid_copy((guid_t *)val, (const guid_t *)&tuple->value); + guid_copy((guid_t *)val, (const guid_t *)&tuple->uuid); return 0; } -- cgit v1.2.3 From 6548c884a595391fab172faeae39e2b329b848f3 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 10 Jun 2022 15:48:18 +0100 Subject: ASoC: qdsp6: q6apm-dai: unprepare stream if its already prepared prepare callback can be called multiple times, so unprepare the stream if its already prepared. Without this DSP is not happy to setting the params on a already prepared graph. Fixes: 9b4fe0f1cd79 ("ASoC: qdsp6: audioreach: add q6apm-dai support") Reported-by: Srinivasa Rao Mandadapu Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20220610144818.511797-1-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6apm-dai.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sound') diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index 19c4a90ec1ea..ee59ef36b85a 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -147,6 +147,12 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, cfg.num_channels = runtime->channels; cfg.bit_width = prtd->bits_per_sample; + if (prtd->state) { + /* clear the previous setup if any */ + q6apm_graph_stop(prtd->graph); + q6apm_unmap_memory_regions(prtd->graph, substream->stream); + } + prtd->pcm_count = snd_pcm_lib_period_bytes(substream); prtd->pos = 0; /* rate and channels are sent to audio driver */ -- cgit v1.2.3 From 7263fc6c71c3a88c17a1ce3565b7b6f378d13878 Mon Sep 17 00:00:00 2001 From: Yassine Oudjana Date: Mon, 6 Jun 2022 19:22:26 +0400 Subject: ASoC: wcd9335: Remove RX channel from old list before adding it to a new one Currently in slim_rx_mux_put, an RX channel gets added to a new list even if it is already in one. This can mess up links and make either it, the new list head, or both, get linked to the wrong entries. This can cause an entry to link to itself which in turn ends up making list_for_each_entry in other functions loop infinitely. To avoid issues, always remove the RX channel from any list it's in before adding it to a new list. Signed-off-by: Yassine Oudjana Link: https://lore.kernel.org/r/20220606152226.149164-1-y.oudjana@protonmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/wcd9335.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 617a36a89dfe..597420679505 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -1289,9 +1289,12 @@ static int slim_rx_mux_put(struct snd_kcontrol *kc, wcd->rx_port_value[port_id] = ucontrol->value.enumerated.item[0]; + /* Remove channel from any list it's in before adding it to a new one */ + list_del_init(&wcd->rx_chs[port_id].list); + switch (wcd->rx_port_value[port_id]) { case 0: - list_del_init(&wcd->rx_chs[port_id].list); + /* Channel already removed from lists. Nothing to do here */ break; case 1: list_add_tail(&wcd->rx_chs[port_id].list, -- cgit v1.2.3 From 6bda28a2f7113b1c49eb05155ace02b75bccae7b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 3 Jun 2022 14:46:09 +0200 Subject: ASoC: wcd9335: Fix spurious event generation The slimbus mux put operation unconditionally reports a change in value which means that spurious events are generated. Fix this by exiting early in that case. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220603124609.4024666-1-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/wcd9335.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sound') diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 597420679505..d9f135200688 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -1287,6 +1287,9 @@ static int slim_rx_mux_put(struct snd_kcontrol *kc, struct snd_soc_dapm_update *update = NULL; u32 port_id = w->shift; + if (wcd->rx_port_value[port_id] == ucontrol->value.enumerated.item[0]) + return 0; + wcd->rx_port_value[port_id] = ucontrol->value.enumerated.item[0]; /* Remove channel from any list it's in before adding it to a new one */ -- cgit v1.2.3 From 65c1c99d96f160e3fead8c6ec67b669cbe62320f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 3 Jun 2022 14:25:26 +0200 Subject: ASoC: wcd938x: Fix event generation for some controls Currently wcd938x_*_put() unconditionally report that the value of the control changed, resulting in spurious events being generated. Return 0 in that case instead as we should. There is still an issue in the compander control which is a bit more complex. Signed-off-by: Mark Brown Reported-by: kernel test robot Link: https://lore.kernel.org/r/20220603122526.3914942-1-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/wcd938x.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'sound') diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c index c1b61b997f69..781ae569be29 100644 --- a/sound/soc/codecs/wcd938x.c +++ b/sound/soc/codecs/wcd938x.c @@ -2519,6 +2519,9 @@ static int wcd938x_tx_mode_put(struct snd_kcontrol *kcontrol, struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; int path = e->shift_l; + if (wcd938x->tx_mode[path] == ucontrol->value.enumerated.item[0]) + return 0; + wcd938x->tx_mode[path] = ucontrol->value.enumerated.item[0]; return 1; @@ -2541,6 +2544,9 @@ static int wcd938x_rx_hph_mode_put(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + if (wcd938x->hph_mode == ucontrol->value.enumerated.item[0]) + return 0; + wcd938x->hph_mode = ucontrol->value.enumerated.item[0]; return 1; @@ -2632,6 +2638,9 @@ static int wcd938x_ldoh_put(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + if (wcd938x->ldoh == ucontrol->value.integer.value[0]) + return 0; + wcd938x->ldoh = ucontrol->value.integer.value[0]; return 1; @@ -2654,6 +2663,9 @@ static int wcd938x_bcs_put(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + if (wcd938x->bcs_dis == ucontrol->value.integer.value[0]) + return 0; + wcd938x->bcs_dis = ucontrol->value.integer.value[0]; return 1; -- cgit v1.2.3 From da440af07fc3dd2b5a5138671eba51991dd1fac8 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 12 Jun 2022 17:56:52 +0200 Subject: ASoC: Intel: bytcr_wm5102: Fix GPIO related probe-ordering problem The "wlf,spkvdd-ena" GPIO needed by the bytcr_wm5102 driver is made available through a gpio-lookup table. This gpio-lookup table is registered by drivers/mfd/arizona-spi.c, which may get probed after the bytcr_wm5102 driver. If the gpio-lookup table has not registered yet then the gpiod_get() will return -ENOENT. Treat -ENOENT as -EPROBE_DEFER to still keep things working in this case. Signed-off-by: Hans de Goede Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20220612155652.107310-1-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_wm5102.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/bytcr_wm5102.c b/sound/soc/intel/boards/bytcr_wm5102.c index 00384c6fbcaa..330c0ace1638 100644 --- a/sound/soc/intel/boards/bytcr_wm5102.c +++ b/sound/soc/intel/boards/bytcr_wm5102.c @@ -421,8 +421,17 @@ static int snd_byt_wm5102_mc_probe(struct platform_device *pdev) priv->spkvdd_en_gpio = gpiod_get(codec_dev, "wlf,spkvdd-ena", GPIOD_OUT_LOW); put_device(codec_dev); - if (IS_ERR(priv->spkvdd_en_gpio)) - return dev_err_probe(dev, PTR_ERR(priv->spkvdd_en_gpio), "getting spkvdd-GPIO\n"); + if (IS_ERR(priv->spkvdd_en_gpio)) { + ret = PTR_ERR(priv->spkvdd_en_gpio); + /* + * The spkvdd gpio-lookup is registered by: drivers/mfd/arizona-spi.c, + * so -ENOENT means that arizona-spi hasn't probed yet. + */ + if (ret == -ENOENT) + ret = -EPROBE_DEFER; + + return dev_err_probe(dev, ret, "getting spkvdd-GPIO\n"); + } /* override platform name, if required */ byt_wm5102_card.dev = dev; -- cgit v1.2.3