[PATCH v4] ASoC: codecs: wsa881x: add runtime pm support
WSA SoundWire Controller does not support Clock stop and performs a soft reset on suspend resume path. Its recommended that WSA881x codecs connected to this are also reset using a hard reset during suspend resume.
So this codec driver performs a hard reset during suspend resume cycle.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org ---
Changes since v3: - added missing sign off. - no code changes
sound/soc/codecs/wsa881x.c | 53 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+)
diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c index 0222370ff95d..616b26c70c3b 100644 --- a/sound/soc/codecs/wsa881x.c +++ b/sound/soc/codecs/wsa881x.c @@ -11,6 +11,7 @@ #include <linux/of_gpio.h> #include <linux/regmap.h> #include <linux/slab.h> +#include <linux/pm_runtime.h> #include <linux/soundwire/sdw.h> #include <linux/soundwire/sdw_registers.h> #include <linux/soundwire/sdw_type.h> @@ -198,6 +199,7 @@ #define WSA881X_OCP_CTL_TIMER_SEC 2 #define WSA881X_OCP_CTL_TEMP_CELSIUS 25 #define WSA881X_OCP_CTL_POLL_TIMER_SEC 60 +#define WSA881X_PROBE_TIMEOUT 1000
#define WSA881X_PA_GAIN_TLV(xname, reg, shift, max, invert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ @@ -747,6 +749,12 @@ static int wsa881x_put_pa_gain(struct snd_kcontrol *kc, unsigned int mask = (1 << fls(max)) - 1; int val, ret, min_gain, max_gain;
+ ret = pm_runtime_get_sync(comp->dev); + if (ret < 0 && ret != -EACCES) { + pm_runtime_put_noidle(comp->dev); + return ret; + } + max_gain = (max - ucontrol->value.integer.value[0]) & mask; /* * Gain has to set incrementally in 4 steps @@ -773,6 +781,9 @@ static int wsa881x_put_pa_gain(struct snd_kcontrol *kc, usleep_range(1000, 1010); }
+ pm_runtime_mark_last_busy(comp->dev); + pm_runtime_put_autosuspend(comp->dev); + return 1; }
@@ -1101,6 +1112,7 @@ static int wsa881x_probe(struct sdw_slave *pdev, const struct sdw_device_id *id) { struct wsa881x_priv *wsa881x; + struct device *dev = &pdev->dev;
wsa881x = devm_kzalloc(&pdev->dev, sizeof(*wsa881x), GFP_KERNEL); if (!wsa881x) @@ -1132,12 +1144,52 @@ static int wsa881x_probe(struct sdw_slave *pdev, return PTR_ERR(wsa881x->regmap); }
+ pm_runtime_set_autosuspend_delay(dev, 3000); + pm_runtime_use_autosuspend(dev); + pm_runtime_mark_last_busy(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + return devm_snd_soc_register_component(&pdev->dev, &wsa881x_component_drv, wsa881x_dais, ARRAY_SIZE(wsa881x_dais)); }
+static int __maybe_unused wsa881x_runtime_suspend(struct device *dev) +{ + struct regmap *regmap = dev_get_regmap(dev, NULL); + struct wsa881x_priv *wsa881x = dev_get_drvdata(dev); + + gpiod_direction_output(wsa881x->sd_n, 0); + + regcache_cache_only(regmap, true); + regcache_mark_dirty(regmap); + + return 0; +} + +static int __maybe_unused wsa881x_runtime_resume(struct device *dev) +{ + struct sdw_slave *slave = dev_to_sdw_dev(dev); + struct regmap *regmap = dev_get_regmap(dev, NULL); + struct wsa881x_priv *wsa881x = dev_get_drvdata(dev); + + gpiod_direction_output(wsa881x->sd_n, 1); + + wait_for_completion_timeout(&slave->initialization_complete, + msecs_to_jiffies(WSA881X_PROBE_TIMEOUT)); + + regcache_cache_only(regmap, false); + regcache_sync(regmap); + + return 0; +} + +static const struct dev_pm_ops wsa881x_pm_ops = { + SET_RUNTIME_PM_OPS(wsa881x_runtime_suspend, wsa881x_runtime_resume, NULL) +}; + static const struct sdw_device_id wsa881x_slave_id[] = { SDW_SLAVE_ENTRY(0x0217, 0x2010, 0), SDW_SLAVE_ENTRY(0x0217, 0x2110, 0), @@ -1151,6 +1203,7 @@ static struct sdw_driver wsa881x_codec_driver = { .id_table = wsa881x_slave_id, .driver = { .name = "wsa881x-codec", + .pm = &wsa881x_pm_ops, } }; module_sdw_driver(wsa881x_codec_driver);
On Mon, 28 Feb 2022 14:42:35 +0000, Srinivas Kandagatla wrote:
WSA SoundWire Controller does not support Clock stop and performs a soft reset on suspend resume path. Its recommended that WSA881x codecs connected to this are also reset using a hard reset during suspend resume.
So this codec driver performs a hard reset during suspend resume cycle.
[...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[1/1] ASoC: codecs: wsa881x: add runtime pm support commit: 8dd55245836119ee3636543b6c2597efd78e643d
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
Hi Srini,
+static int __maybe_unused wsa881x_runtime_resume(struct device *dev) +{
- struct sdw_slave *slave = dev_to_sdw_dev(dev);
- struct regmap *regmap = dev_get_regmap(dev, NULL);
- struct wsa881x_priv *wsa881x = dev_get_drvdata(dev);
- gpiod_direction_output(wsa881x->sd_n, 1);
- wait_for_completion_timeout(&slave->initialization_complete,
msecs_to_jiffies(WSA881X_PROBE_TIMEOUT));
while I was revisiting pm_runtime support, I also saw that this codec driver is the only one that doesn't check for errors
max98373-sdw.c: time = wait_for_completion_timeout(&slave->initialization_complete,
rt1308-sdw.c: time = wait_for_completion_timeout(&slave->initialization_complete,
rt1316-sdw.c: time = wait_for_completion_timeout(&slave->initialization_complete,
rt5682-sdw.c: time = wait_for_completion_timeout(&slave->initialization_complete,
rt5682.c: &slave->initialization_complete,
rt700-sdw.c: time = wait_for_completion_timeout(&slave->initialization_complete,
rt711-sdca-sdw.c: time = wait_for_completion_timeout(&slave->initialization_complete,
rt711-sdw.c: time = wait_for_completion_timeout(&slave->initialization_complete,
rt715-sdw.c: time = wait_for_completion_timeout(&slave->initialization_complete,
wsa881x.c: wait_for_completion_timeout(&slave->initialization_complete,
If the attachment fails for some reason, you probably want to avoid starting regmap syncs that will fail by construction, no?
- regcache_cache_only(regmap, false);
- regcache_sync(regmap);
- return 0;
+}
On 20/04/2022 18:59, Pierre-Louis Bossart wrote:
Hi Srini,
+static int __maybe_unused wsa881x_runtime_resume(struct device *dev) +{
- struct sdw_slave *slave = dev_to_sdw_dev(dev);
- struct regmap *regmap = dev_get_regmap(dev, NULL);
- struct wsa881x_priv *wsa881x = dev_get_drvdata(dev);
- gpiod_direction_output(wsa881x->sd_n, 1);
- wait_for_completion_timeout(&slave->initialization_complete,
msecs_to_jiffies(WSA881X_PROBE_TIMEOUT));
while I was revisiting pm_runtime support, I also saw that this codec driver is the only one that doesn't check for errors
max98373-sdw.c: time = wait_for_completion_timeout(&slave->initialization_complete,
rt1308-sdw.c: time = wait_for_completion_timeout(&slave->initialization_complete,
rt1316-sdw.c: time = wait_for_completion_timeout(&slave->initialization_complete,
rt5682-sdw.c: time = wait_for_completion_timeout(&slave->initialization_complete,
rt5682.c: &slave->initialization_complete,
rt700-sdw.c: time = wait_for_completion_timeout(&slave->initialization_complete,
rt711-sdca-sdw.c: time = wait_for_completion_timeout(&slave->initialization_complete,
rt711-sdw.c: time = wait_for_completion_timeout(&slave->initialization_complete,
rt715-sdw.c: time = wait_for_completion_timeout(&slave->initialization_complete,
wsa881x.c: wait_for_completion_timeout(&slave->initialization_complete,
If the attachment fails for some reason, you probably want to avoid starting regmap syncs that will fail by construction, no?
Thanks Pierre for auditing the calls.
Yes syncs would fail on reg writes if initialization timeout. Do you already have fix patch to this or do you want me to send one?
Am also trying to understand what is the expected behavior in the resume failure cases, should pm attempt to resume the codec after some time, if so returning -ETIMEOUT is the right error code?
--srini
- regcache_cache_only(regmap, false);
- regcache_sync(regmap);
- return 0;
+}
participants (3)
-
Mark Brown
-
Pierre-Louis Bossart
-
Srinivas Kandagatla