From: Richard Fitzgerald <rf@opensource.cirrus.com>
To: broonie@kernel.org
Cc: yung-chuan.liao@linux.intel.com, linux-sound@vger.kernel.org,
linux-kernel@vger.kernel.org, patches@opensource.cirrus.com
Subject: [PATCH] ASoC: cs35l56: Support clock stop mode 1 if enabled in ACPI
Date: Wed, 11 Mar 2026 14:21:53 +0000 [thread overview]
Message-ID: <20260311142153.2201761-1-rf@opensource.cirrus.com> (raw)
Report the ability to support SoundWire clock-stop mode 1 if this is
enabled in ACPI. Mode 1 allows the device to lose state, so it can
reduce power consumption in clock-stop. Also add the necessary
handling to wait for re-enumeration on resume.
This does not use sdw_slave_read_prop(), because that also fills in
other properties from ACPI that were not previously set by the driver
and this has been observed to break some systems. Instead, the
"mipi-sdw-clock-stop-mode1-supported" property is checked directly.
When a SoundWire peripheral has been put into clock-stop mode 1 it
must be re-enumerated after the clock is restarted. A new flag
sdw_in_clock_stop_1 is set to true in cs35l56_sdw_clk_stop() if the
SoundWire core notifies that it is entering clock-stop 1.
cs35l56_sdw_handle_unattach() will wait for re-enumeration if
sdw_in_clock_stop_1 is true.
sdw_in_clock_stop_1 will be reset to false when an ATTACH notification
is received in cs35l56_sdw_update_status().
Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
---
sound/soc/codecs/cs35l56-sdw.c | 34 +++++++++++++++++++++++++++++-----
sound/soc/codecs/cs35l56.h | 1 +
2 files changed, 30 insertions(+), 5 deletions(-)
diff --git a/sound/soc/codecs/cs35l56-sdw.c b/sound/soc/codecs/cs35l56-sdw.c
index 30b3192d6ce9..9dc47fec1ea0 100644
--- a/sound/soc/codecs/cs35l56-sdw.c
+++ b/sound/soc/codecs/cs35l56-sdw.c
@@ -14,6 +14,7 @@
#include <linux/soundwire/sdw.h>
#include <linux/soundwire/sdw_registers.h>
#include <linux/soundwire/sdw_type.h>
+#include <linux/string_choices.h>
#include <linux/swab.h>
#include <linux/types.h>
#include <linux/workqueue.h>
@@ -340,6 +341,14 @@ static int cs35l56_sdw_read_prop(struct sdw_slave *peripheral)
struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev);
struct sdw_slave_prop *prop = &peripheral->prop;
struct sdw_dpn_prop *ports;
+ u8 clock_stop_1 = false;
+ int ret;
+
+ ret = fwnode_property_read_u8(dev_fwnode(cs35l56->base.dev),
+ "mipi-sdw-clock-stop-mode1-supported",
+ &clock_stop_1);
+ if (ret == 0)
+ prop->clk_stop_mode1 = !!clock_stop_1;
ports = devm_kcalloc(cs35l56->base.dev, 2, sizeof(*ports), GFP_KERNEL);
if (!ports)
@@ -363,6 +372,9 @@ static int cs35l56_sdw_read_prop(struct sdw_slave *peripheral)
ports[1].ch_prep_timeout = 10;
prop->src_dpn_prop = &ports[1];
+ dev_dbg(&peripheral->dev, "clock stop mode 1 supported: %s\n",
+ str_yes_no(prop->clk_stop_mode1));
+
return 0;
}
@@ -374,6 +386,7 @@ static int cs35l56_sdw_update_status(struct sdw_slave *peripheral,
switch (status) {
case SDW_SLAVE_ATTACHED:
dev_dbg(cs35l56->base.dev, "%s: ATTACHED\n", __func__);
+ cs35l56->sdw_in_clock_stop_1 = false;
if (cs35l56->sdw_attached)
break;
@@ -399,25 +412,35 @@ static int __maybe_unused cs35l56_sdw_clk_stop(struct sdw_slave *peripheral,
{
struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev);
- dev_dbg(cs35l56->base.dev, "%s: mode:%d type:%d\n", __func__, mode, type);
+ dev_dbg(cs35l56->base.dev, "%s: clock_stop_mode%d stage:%d\n", __func__, mode, type);
- return 0;
+ switch (type) {
+ case SDW_CLK_POST_PREPARE:
+ if (mode == SDW_CLK_STOP_MODE1)
+ cs35l56->sdw_in_clock_stop_1 = true;
+ else
+ cs35l56->sdw_in_clock_stop_1 = false;
+ return 0;
+ default:
+ return 0;
+ }
}
static const struct sdw_slave_ops cs35l56_sdw_ops = {
.read_prop = cs35l56_sdw_read_prop,
.interrupt_callback = cs35l56_sdw_interrupt,
.update_status = cs35l56_sdw_update_status,
-#ifdef DEBUG
.clk_stop = cs35l56_sdw_clk_stop,
-#endif
};
static int __maybe_unused cs35l56_sdw_handle_unattach(struct cs35l56_private *cs35l56)
{
struct sdw_slave *peripheral = cs35l56->sdw_peripheral;
- if (peripheral->unattach_request) {
+ dev_dbg(cs35l56->base.dev, "attached:%u unattach_request:%u in_clock_stop_1:%u\n",
+ cs35l56->sdw_attached, peripheral->unattach_request, cs35l56->sdw_in_clock_stop_1);
+
+ if (cs35l56->sdw_in_clock_stop_1 || peripheral->unattach_request) {
/* Cannot access registers until bus is re-initialized. */
dev_dbg(cs35l56->base.dev, "Wait for initialization_complete\n");
if (!wait_for_completion_timeout(&peripheral->initialization_complete,
@@ -427,6 +450,7 @@ static int __maybe_unused cs35l56_sdw_handle_unattach(struct cs35l56_private *cs
}
peripheral->unattach_request = 0;
+ cs35l56->sdw_in_clock_stop_1 = false;
/*
* Don't call regcache_mark_dirty(), we can't be sure that the
diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h
index 747529be3e2e..36d239d571cd 100644
--- a/sound/soc/codecs/cs35l56.h
+++ b/sound/soc/codecs/cs35l56.h
@@ -42,6 +42,7 @@ struct cs35l56_private {
bool sdw_irq_no_unmask;
bool soft_resetting;
bool sdw_attached;
+ bool sdw_in_clock_stop_1;
struct completion init_completion;
int speaker_id;
--
2.47.3
next reply other threads:[~2026-03-11 14:22 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-11 14:21 Richard Fitzgerald [this message]
2026-03-11 15:03 ` [PATCH] ASoC: cs35l56: Support clock stop mode 1 if enabled in ACPI Mark Brown
2026-03-11 15:17 ` Richard Fitzgerald
2026-03-11 15:30 ` Mark Brown
2026-03-11 15:34 ` Richard Fitzgerald
2026-03-11 15:50 ` Mark Brown
2026-03-11 15:58 ` Richard Fitzgerald
2026-03-11 16:09 ` Mark Brown
2026-03-11 18:56 ` Mark Brown
2026-03-14 21:58 ` Mark Brown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260311142153.2201761-1-rf@opensource.cirrus.com \
--to=rf@opensource.cirrus.com \
--cc=broonie@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
--cc=patches@opensource.cirrus.com \
--cc=yung-chuan.liao@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox