From 67840cbfb1cd91c63673e8c08ac35f8ec88ae0f4 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 29 Feb 2024 16:40:54 +0800 Subject: [PATCH 1/3] soundwire: intel_auxdevice: use pm_resume_resume to resume child We need to wait for each child to fully resume. Use pm_resume_resume to ensure it. Signed-off-by: Bard Liao --- drivers/soundwire/intel_auxdevice.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soundwire/intel_auxdevice.c b/drivers/soundwire/intel_auxdevice.c index 93698532deac40..48f6677b054ad1 100644 --- a/drivers/soundwire/intel_auxdevice.c +++ b/drivers/soundwire/intel_auxdevice.c @@ -454,9 +454,9 @@ static int intel_resume_child_device(struct device *dev, void *data) return 0; } - ret = pm_request_resume(dev); + ret = pm_runtime_resume(dev); if (ret < 0) { - dev_err(dev, "%s: pm_request_resume failed: %d\n", __func__, ret); + dev_err(dev, "%s: pm_runtime_resume failed: %d\n", __func__, ret); return ret; } From 5c9eaf2ad1b4f8d5b0dbea24f1f295b9fa7afa86 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 29 Feb 2024 16:56:43 +0800 Subject: [PATCH 2/3] soundwire: intel: export intel_resume_child_device We will resume each child in the next patch, and intel_resume_child_device() will be used. Signed-off-by: Bard Liao --- drivers/soundwire/intel_auxdevice.c | 2 +- drivers/soundwire/intel_auxdevice.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/soundwire/intel_auxdevice.c b/drivers/soundwire/intel_auxdevice.c index 48f6677b054ad1..84c291ac51db66 100644 --- a/drivers/soundwire/intel_auxdevice.c +++ b/drivers/soundwire/intel_auxdevice.c @@ -440,7 +440,7 @@ int intel_link_process_wakeen_event(struct auxiliary_device *auxdev) * PM calls */ -static int intel_resume_child_device(struct device *dev, void *data) +int intel_resume_child_device(struct device *dev, void *data) { int ret; struct sdw_slave *slave = dev_to_sdw_dev(dev); diff --git a/drivers/soundwire/intel_auxdevice.h b/drivers/soundwire/intel_auxdevice.h index a00ecde9556333..acaae0bd6592b8 100644 --- a/drivers/soundwire/intel_auxdevice.h +++ b/drivers/soundwire/intel_auxdevice.h @@ -6,6 +6,7 @@ int intel_link_startup(struct auxiliary_device *auxdev); int intel_link_process_wakeen_event(struct auxiliary_device *auxdev); +int intel_resume_child_device(struct device *dev, void *data); struct sdw_intel_link_dev { struct auxiliary_device auxdev; From fb32f60f442614aee4952b4ac52027db211a3fc0 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Fri, 23 Feb 2024 21:39:30 +0800 Subject: [PATCH 3/3] ASoC/soundwire: Intel: add sdw_intel_pre_exit helper We will disable SDW interrupt in hda_sdw_exit() before sdw_intel_exit() and peripherals will on longer access SDW registers. However, when the manager became pm_runtime active in the remove procedure, peripherals will become attached, and do the initialization process. The commit suggests a sdw_intel_pre_exit() function and use pm_runtime_resume() to wait for the peripherals being fully resumed. This will ensure there are no SoundWire registers accessed after the bus is powered-down. Signed-off-by: Bard Liao --- drivers/soundwire/intel_init.c | 17 +++++++++++++++++ include/linux/soundwire/sdw_intel.h | 1 + sound/soc/sof/intel/hda.c | 3 +++ 3 files changed, 21 insertions(+) diff --git a/drivers/soundwire/intel_init.c b/drivers/soundwire/intel_init.c index 534c8795e7e85d..f128670b2a6f4f 100644 --- a/drivers/soundwire/intel_init.c +++ b/drivers/soundwire/intel_init.c @@ -16,6 +16,7 @@ #include #include #include "cadence_master.h" +#include "bus.h" #include "intel.h" #include "intel_auxdevice.h" @@ -363,6 +364,22 @@ void sdw_intel_exit(struct sdw_intel_ctx *ctx) } EXPORT_SYMBOL_NS(sdw_intel_exit, SOUNDWIRE_INTEL_INIT); +void sdw_intel_pre_exit(struct sdw_intel_ctx *ctx) +{ + struct sdw_intel_link_res *link; + + list_for_each_entry(link, &ctx->link_list, list) { + struct sdw_bus *bus = &link->cdns->bus; + int ret; + + ret = device_for_each_child(bus->dev, NULL, intel_resume_child_device); + if (ret < 0) + dev_err(bus->dev, "%s: intel_resume_child_device failed: %d\n", + __func__, ret); + } +} +EXPORT_SYMBOL_NS(sdw_intel_pre_exit, SOUNDWIRE_INTEL_INIT); + void sdw_intel_process_wakeen_event(struct sdw_intel_ctx *ctx) { struct sdw_intel_link_dev *ldev; diff --git a/include/linux/soundwire/sdw_intel.h b/include/linux/soundwire/sdw_intel.h index 8e78417156e3c6..1b3562815b1425 100644 --- a/include/linux/soundwire/sdw_intel.h +++ b/include/linux/soundwire/sdw_intel.h @@ -373,6 +373,7 @@ sdw_intel_probe(struct sdw_intel_res *res); int sdw_intel_startup(struct sdw_intel_ctx *ctx); void sdw_intel_exit(struct sdw_intel_ctx *ctx); +void sdw_intel_pre_exit(struct sdw_intel_ctx *ctx); irqreturn_t sdw_intel_thread(int irq, void *dev_id); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 66126fb31d52db..c7710606b8df4c 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -220,6 +220,9 @@ static int hda_sdw_exit(struct snd_sof_dev *sdev) hdev = sdev->pdata->hw_pdata; + if (hdev->sdw) + sdw_intel_pre_exit(hdev->sdw); + hda_sdw_int_enable(sdev, false); if (hdev->sdw)