mbox series

[0/3] ASOC: cs42l42: Add support for system suspend

Message ID 20220120175549.671831-1-rf@opensource.cirrus.com
Headers show
Series ASOC: cs42l42: Add support for system suspend | expand

Message

Richard Fitzgerald Jan. 20, 2022, 5:55 p.m. UTC
Add system suspend and resume handlers so that the cs42l42 is cleanly
put into power-off state during system suspend and the registers are
restored in resume.

The first two patches separate out two small changes that can stand
alone and are needed to enable the system suspend implementation:

1) Don't rely on there being a jack unplug IRQ before a plug IRQ.
There won't be if the unplug and plug happened while in system suspend.

2) Put a mutex around the entire IRQ handling so that the suspend can
ensure the last run of the IRQ handler has completed before it powers
down.

Richard Fitzgerald (3):
  ASoC: cs42l42: Report full jack status when plug is detected
  ASoC: cs42l42: Change jack_detect_mutex to a lock of all IRQ handling
  ASoC: cs42l42: Handle system suspend

 sound/soc/codecs/cs42l42.c | 164 ++++++++++++++++++++++++++++++++++++++++++---
 sound/soc/codecs/cs42l42.h |   7 +-
 2 files changed, 161 insertions(+), 10 deletions(-)

Comments

Richard Fitzgerald Jan. 21, 2022, 10:22 a.m. UTC | #1
On 20/01/2022 17:55, Richard Fitzgerald wrote:

> +static int __maybe_unused cs42l42_resume(struct device *dev)
> +{
> +	struct cs42l42_private *cs42l42 = dev_get_drvdata(dev);
> +	int ret;
> +
> +	/*
> +	 * If jack was unplugged and re-plugged during suspend it could
> +	 * have changed type but the tip-sense state hasn't changed.
> +	 * Force a plugged state to be re-evaluated.
> +	 */
> +	if (cs42l42->plug_state != CS42L42_TS_UNPLUG)
> +		cs42l42->plug_state = CS42L42_TS_TRANS;
> +
> +	ret = regulator_bulk_enable(ARRAY_SIZE(cs42l42->supplies), cs42l42->supplies);
> +	if (ret != 0) {
> +		dev_err(dev, "Failed to enable supplies: %d\n", ret);
> +		return ret;
> +	}
> +
> +	gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
> +	usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2);
> +
> +	regcache_cache_only(cs42l42->regmap, false);
> +	regcache_mark_dirty(cs42l42->regmap);
> +
> +	/* Sync LATCH_TO_VP first so the VP domain registers sync correctly */
> +	regcache_sync_region(cs42l42->regmap, CS42L42_MIC_DET_CTL1, CS42L42_MIC_DET_CTL1);
> +	regcache_sync(cs42l42->regmap);
> +
> +	cs42l42->suspended = false;

This should be taking the irq_mutex around the regcache_sync() so that
we don't get unhandled interrupts after the interrupts are unmasked
but before cs42l42->suspended is cleared.

Will push a V2 with this fix.