From: Sen Wang <sen@ti.com>
To: <andrzej.hajda@intel.com>, <neil.armstrong@linaro.org>,
<rfoss@kernel.org>, <airlied@gmail.com>,
<maarten.lankhorst@linux.intel.com>, <mripard@kernel.org>,
<tzimmermann@suse.de>, <dri-devel@lists.freedesktop.org>,
<jani.nikula@intel.com>, <simona@ffwll.ch>,
<linux-kernel@vger.kernel.org>
Cc: <tomi.valkeinen@ideasonboard.com>, <devarsht@ti.com>,
<r-donadkar@ti.com>, <s-jain1@ti.com>, Sen Wang <sen@ti.com>
Subject: [PATCH] drm/bridge: sii902x: Add audio context to suspend/resume routine
Date: Wed, 11 Feb 2026 15:10:18 -0600 [thread overview]
Message-ID: <20260211211018.149916-1-sen@ti.com> (raw)
The sii902x driver has existing suspend/resume handlers that save and
restore video-related register context (TPI mode and interrupts), but
these handlers were not saving/restoring audio configuration registers.
This caused HDMI audio to stop working after system suspend/resume cycles.
Therefore add audio-related register context to the existing
suspend/resume handlers when audio context needs to be saved/restored. As
well as mclk for the sake of power saving, in the case of sii902x being
the frame producer.
The audio context is only saved/restored when audio.active is true,
avoiding unnecessary register access when audio is not in use.
Tested on TI SK-AM62P-LP board with HDMI audio playback across multiple
suspend/resume cycles.
Signed-off-by: Sen Wang <sen@ti.com>
---
drivers/gpu/drm/bridge/sii902x.c | 91 +++++++++++++++++++++++++++++++-
1 file changed, 90 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
index 134657041799..fd38a6ae86b2 100644
--- a/drivers/gpu/drm/bridge/sii902x.c
+++ b/drivers/gpu/drm/bridge/sii902x.c
@@ -192,6 +192,13 @@ struct sii902x {
struct platform_device *pdev;
struct clk *mclk;
u32 i2s_fifo_sequence[4];
+ bool active;
+ /* Audio register context for save/resume */
+ unsigned int ctx_i2s_input_config;
+ unsigned int ctx_audio_config_byte2;
+ unsigned int ctx_audio_config_byte3;
+ u8 ctx_i2s_stream_header[SII902X_TPI_I2S_STRM_HDR_SIZE];
+ u8 ctx_audio_infoframe[SII902X_TPI_MISC_INFOFRAME_SIZE];
} audio;
};
@@ -764,6 +771,8 @@ static int sii902x_audio_hw_params(struct device *dev, void *data,
if (ret)
goto out;
+ sii902x->audio.active = true;
+
dev_dbg(dev, "%s: hdmi audio enabled\n", __func__);
out:
mutex_unlock(&sii902x->mutex);
@@ -786,6 +795,8 @@ static void sii902x_audio_shutdown(struct device *dev, void *data)
regmap_write(sii902x->regmap, SII902X_TPI_AUDIO_CONFIG_BYTE2_REG,
SII902X_TPI_AUDIO_INTERFACE_DISABLE);
+ sii902x->audio.active = false;
+
mutex_unlock(&sii902x->mutex);
clk_disable_unprepare(sii902x->audio.mclk);
@@ -1081,7 +1092,7 @@ static int __maybe_unused sii902x_resume(struct device *dev)
{
struct sii902x *sii902x = dev_get_drvdata(dev);
unsigned int tpi_reg, status;
- int ret;
+ int ret, i;
ret = regmap_read(sii902x->regmap, SII902X_REG_TPI_RQB, &tpi_reg);
if (ret)
@@ -1109,7 +1120,62 @@ static int __maybe_unused sii902x_resume(struct device *dev)
regmap_read(sii902x->regmap, SII902X_INT_STATUS, &status);
regmap_write(sii902x->regmap, SII902X_INT_STATUS, status);
+ /*
+ * Restore audio context if audio was active before suspend,
+ * in the matching order of sii902x_audio_hw_params()
+ * initialization
+ */
+ if (sii902x->audio.active) {
+ /* Re-enable mclk */
+ ret = clk_prepare_enable(sii902x->audio.mclk);
+ if (ret) {
+ dev_err(dev, "Failed to re-enable mclk: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_write(sii902x->regmap, SII902X_TPI_AUDIO_CONFIG_BYTE2_REG,
+ sii902x->audio.ctx_audio_config_byte2);
+ if (ret)
+ goto err_audio_resume;
+
+ ret = regmap_write(sii902x->regmap, SII902X_TPI_I2S_INPUT_CONFIG_REG,
+ sii902x->audio.ctx_i2s_input_config);
+ if (ret)
+ goto err_audio_resume;
+
+ for (i = 0; i < ARRAY_SIZE(sii902x->audio.i2s_fifo_sequence) &&
+ sii902x->audio.i2s_fifo_sequence[i]; i++) {
+ ret = regmap_write(sii902x->regmap,
+ SII902X_TPI_I2S_ENABLE_MAPPING_REG,
+ sii902x->audio.i2s_fifo_sequence[i]);
+ if (ret)
+ goto err_audio_resume;
+ }
+
+ ret = regmap_write(sii902x->regmap, SII902X_TPI_AUDIO_CONFIG_BYTE3_REG,
+ sii902x->audio.ctx_audio_config_byte3);
+ if (ret)
+ goto err_audio_resume;
+
+ ret = regmap_bulk_write(sii902x->regmap, SII902X_TPI_I2S_STRM_HDR_BASE,
+ sii902x->audio.ctx_i2s_stream_header,
+ SII902X_TPI_I2S_STRM_HDR_SIZE);
+ if (ret)
+ goto err_audio_resume;
+
+ ret = regmap_bulk_write(sii902x->regmap, SII902X_TPI_MISC_INFOFRAME_BASE,
+ sii902x->audio.ctx_audio_infoframe,
+ SII902X_TPI_MISC_INFOFRAME_SIZE);
+ if (ret)
+ goto err_audio_resume;
+ }
+
return 0;
+
+err_audio_resume:
+ clk_disable_unprepare(sii902x->audio.mclk);
+ dev_err(dev, "Failed to restore audio registers: %d\n", ret);
+ return ret;
}
static int __maybe_unused sii902x_suspend(struct device *dev)
@@ -1122,6 +1188,29 @@ static int __maybe_unused sii902x_suspend(struct device *dev)
regmap_read(sii902x->regmap, SII902X_INT_ENABLE,
&sii902x->ctx_interrupt);
+ /*
+ * Save audio context if audio is active, and
+ * in the matching order of sii902x_audio_hw_params()
+ * initialization
+ */
+ if (sii902x->audio.active) {
+ regmap_read(sii902x->regmap, SII902X_TPI_AUDIO_CONFIG_BYTE2_REG,
+ &sii902x->audio.ctx_audio_config_byte2);
+ regmap_read(sii902x->regmap, SII902X_TPI_I2S_INPUT_CONFIG_REG,
+ &sii902x->audio.ctx_i2s_input_config);
+ regmap_read(sii902x->regmap, SII902X_TPI_AUDIO_CONFIG_BYTE3_REG,
+ &sii902x->audio.ctx_audio_config_byte3);
+ regmap_bulk_read(sii902x->regmap, SII902X_TPI_I2S_STRM_HDR_BASE,
+ sii902x->audio.ctx_i2s_stream_header,
+ SII902X_TPI_I2S_STRM_HDR_SIZE);
+ regmap_bulk_read(sii902x->regmap, SII902X_TPI_MISC_INFOFRAME_BASE,
+ sii902x->audio.ctx_audio_infoframe,
+ SII902X_TPI_MISC_INFOFRAME_SIZE);
+
+ /* Disable mclk during suspend */
+ clk_disable_unprepare(sii902x->audio.mclk);
+ }
+
return 0;
}
--
2.43.0
next reply other threads:[~2026-02-11 21:10 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-11 21:10 Sen Wang [this message]
2026-03-18 13:39 ` [PATCH] drm/bridge: sii902x: Add audio context to suspend/resume routine Devarsh Thakkar
2026-03-18 19:35 ` Wang, Sen
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=20260211211018.149916-1-sen@ti.com \
--to=sen@ti.com \
--cc=airlied@gmail.com \
--cc=andrzej.hajda@intel.com \
--cc=devarsht@ti.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=jani.nikula@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mripard@kernel.org \
--cc=neil.armstrong@linaro.org \
--cc=r-donadkar@ti.com \
--cc=rfoss@kernel.org \
--cc=s-jain1@ti.com \
--cc=simona@ffwll.ch \
--cc=tomi.valkeinen@ideasonboard.com \
--cc=tzimmermann@suse.de \
/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