From: Richard Fitzgerald Date: Fri, 29 May 2026 14:03:50 +0000 (+0100) Subject: ASoC: cs35l56: Share common SoundWire interrupt enable/disable code X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cab82caa2d37124659637ffc1eed2d1c4f231fbc;p=thirdparty%2Flinux.git ASoC: cs35l56: Share common SoundWire interrupt enable/disable code Move the duplicated SoundWire interrupt enable/disable code into shared functions. These new functions are in cs35l56.c to prevent circular dependency between cs35l56.c and cs35l56-sdw.c Signed-off-by: Richard Fitzgerald Link: https://patch.msgid.link/20260529140350.408557-1-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- diff --git a/sound/soc/codecs/cs35l56-sdw.c b/sound/soc/codecs/cs35l56-sdw.c index c21568f57c63..847e88f3b204 100644 --- a/sound/soc/codecs/cs35l56-sdw.c +++ b/sound/soc/codecs/cs35l56-sdw.c @@ -230,11 +230,8 @@ static void cs35l56_sdw_init(struct sdw_slave *peripheral) * cs35l56_init can return with !init_done if it triggered * a soft reset. */ - if (cs35l56->base.init_done) { - /* Enable SoundWire interrupts */ - sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, - CS35L56_SDW_INT_MASK_CODEC_IRQ); - } + if (cs35l56->base.init_done) + cs35l56_unmask_soundwire_interrupts(cs35l56->sdw_peripheral); out: pm_runtime_put_autosuspend(cs35l56->base.dev); @@ -259,15 +256,11 @@ static int cs35l56_sdw_interrupt(struct sdw_slave *peripheral, pm_runtime_get_noresume(cs35l56->base.dev); /* - * Mask and clear until it has been handled. The read of GEN_INT_STAT_1 - * is required as per the SoundWire spec for interrupt status bits - * to clear. GEN_INT_MASK_1 masks the _inputs_ to GEN_INT_STAT1. + * Mask and clear until it has been handled. * None of the interrupts are time-critical so use the * power-efficient queue. */ - sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); - sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1); - sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); + cs35l56_mask_soundwire_interrupts(peripheral); queue_work(system_power_efficient_wq, &cs35l56->sdw_irq_work); return 0; @@ -283,8 +276,7 @@ static void cs35l56_sdw_irq_work(struct work_struct *work) /* unmask interrupts */ if (!cs35l56->sdw_irq_no_unmask) - sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, - CS35L56_SDW_INT_MASK_CODEC_IRQ); + cs35l56_unmask_soundwire_interrupts(cs35l56->sdw_peripheral); pm_runtime_put_autosuspend(cs35l56->base.dev); } @@ -441,9 +433,7 @@ static int __maybe_unused cs35l56_sdw_runtime_resume(struct device *dev) if (ret) return ret; - /* Re-enable SoundWire interrupts */ - sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, - CS35L56_SDW_INT_MASK_CODEC_IRQ); + cs35l56_unmask_soundwire_interrupts(cs35l56->sdw_peripheral); return 0; } @@ -455,18 +445,7 @@ static int __maybe_unused cs35l56_sdw_system_suspend(struct device *dev) if (!cs35l56->base.init_done) return 0; - /* - * Disable SoundWire interrupts. - * Flush - don't cancel because that could leave an unbalanced pm_runtime_get. - */ - cs35l56->sdw_irq_no_unmask = true; - flush_work(&cs35l56->sdw_irq_work); - - /* Mask interrupts and flush in case sdw_irq_work was queued again */ - sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); - sdw_read_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1); - sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); - flush_work(&cs35l56->sdw_irq_work); + cs35l56_disable_sdw_interrupts(cs35l56); return cs35l56_system_suspend(dev); } @@ -542,13 +521,7 @@ static void cs35l56_sdw_remove(struct sdw_slave *peripheral) { struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); - /* Disable SoundWire interrupts */ - cs35l56->sdw_irq_no_unmask = true; - flush_work(&cs35l56->sdw_irq_work); - sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); - sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1); - sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); - flush_work(&cs35l56->sdw_irq_work); + cs35l56_disable_sdw_interrupts(cs35l56); cs35l56_remove(cs35l56); } diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 80158913a60e..b4b126753c10 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -37,6 +37,49 @@ #include "wm_adsp.h" #include "cs35l56.h" +void cs35l56_mask_soundwire_interrupts(struct sdw_slave *peripheral) +{ + /* + * The read of GEN_INT_STAT_1 is required as per the SoundWire spec + * for interrupt status bits to clear. + * GEN_INT_MASK_1 masks the _inputs_ to GEN_INT_STAT1. + */ + sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); + sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1); + sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); +} +EXPORT_SYMBOL_NS_GPL(cs35l56_mask_soundwire_interrupts, "SND_SOC_CS35L56_CORE"); + +void cs35l56_unmask_soundwire_interrupts(struct sdw_slave *peripheral) +{ + sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, CS35L56_SDW_INT_MASK_CODEC_IRQ); +} +EXPORT_SYMBOL_NS_GPL(cs35l56_unmask_soundwire_interrupts, "SND_SOC_CS35L56_CORE"); + +void cs35l56_disable_sdw_interrupts(struct cs35l56_private *cs35l56) +{ + if (!cs35l56->sdw_peripheral) + return; + + cs35l56->sdw_irq_no_unmask = true; + flush_work(&cs35l56->sdw_irq_work); + + /* Mask interrupts and flush in case sdw_irq_work was queued again */ + cs35l56_mask_soundwire_interrupts(cs35l56->sdw_peripheral); + flush_work(&cs35l56->sdw_irq_work); +} +EXPORT_SYMBOL_NS_GPL(cs35l56_disable_sdw_interrupts, "SND_SOC_CS35L56_CORE"); + +void cs35l56_enable_sdw_interrupts(struct cs35l56_private *cs35l56) +{ + if (!cs35l56->sdw_peripheral) + return; + + cs35l56->sdw_irq_no_unmask = false; + cs35l56_unmask_soundwire_interrupts(cs35l56->sdw_peripheral); +} +EXPORT_SYMBOL_NS_GPL(cs35l56_enable_sdw_interrupts, "SND_SOC_CS35L56_CORE"); + static int cs35l56_dsp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); @@ -790,14 +833,7 @@ static void cs35l56_patch(struct cs35l56_private *cs35l56, bool firmware_missing * Setting sdw_irq_no_unmask prevents the handler re-enabling * the SoundWire interrupt. */ - if (cs35l56->sdw_peripheral) { - cs35l56->sdw_irq_no_unmask = true; - flush_work(&cs35l56->sdw_irq_work); - sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); - sdw_read_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1); - sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); - flush_work(&cs35l56->sdw_irq_work); - } + cs35l56_disable_sdw_interrupts(cs35l56); ret = cs35l56_firmware_shutdown(&cs35l56->base); if (ret) @@ -849,12 +885,7 @@ static void cs35l56_patch(struct cs35l56_private *cs35l56, bool firmware_missing err_unlock: mutex_unlock(&cs35l56->base.irq_lock); err: - /* Re-enable SoundWire interrupts */ - if (cs35l56->sdw_peripheral) { - cs35l56->sdw_irq_no_unmask = false; - sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, - CS35L56_SDW_INT_MASK_CODEC_IRQ); - } + cs35l56_enable_sdw_interrupts(cs35l56); } static void cs35l56_dsp_work(struct work_struct *work) diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h index d029fa3f8656..6a27ef2b7569 100644 --- a/sound/soc/codecs/cs35l56.h +++ b/sound/soc/codecs/cs35l56.h @@ -66,6 +66,11 @@ static inline struct cs35l56_private *cs35l56_private_from_base(struct cs35l56_b extern const struct dev_pm_ops cs35l56_pm_ops_i2c_spi; +void cs35l56_mask_soundwire_interrupts(struct sdw_slave *peripheral); +void cs35l56_unmask_soundwire_interrupts(struct sdw_slave *peripheral); +void cs35l56_disable_sdw_interrupts(struct cs35l56_private *cs35l56); +void cs35l56_enable_sdw_interrupts(struct cs35l56_private *cs35l56); + int cs35l56_system_suspend(struct device *dev); int cs35l56_system_suspend_late(struct device *dev); int cs35l56_system_suspend_no_irq(struct device *dev);