From 0c2c6c94303c37f148a90a974041b4524ba26e37 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Tue, 26 Sep 2023 10:00:18 +0800 Subject: [PATCH] drm/bridge: synopsys: Fix wrong FIFO reset on AUD_CONF0 Should use update_bits instead of write directly which will override the other configs on AUD_CONF0. Fixes: 19820cc6531a ("drm/bridge: synopsys: Recover sound for XRUN routine") Signed-off-by: Sugar Zhang Change-Id: Ie64cdce700a30f1b4a64fc9d437d34bd0496aa30 --- drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h | 1 + .../gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 14 ++++++++++++-- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h index f72d27208ebe..966d297ef41d 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h @@ -17,6 +17,7 @@ struct dw_hdmi_i2s_audio_data { void (*write)(struct dw_hdmi *hdmi, u8 val, int offset); u8 (*read)(struct dw_hdmi *hdmi, int offset); + void (*mod)(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned int reg); u8 *(*get_eld)(struct dw_hdmi *hdmi); }; diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c index 95b0caef8b4e..e621021dc50a 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c @@ -34,6 +34,14 @@ static inline u8 hdmi_read(struct dw_hdmi_i2s_audio_data *audio, int offset) return audio->read(hdmi, offset); } +static inline void hdmi_update_bits(struct dw_hdmi_i2s_audio_data *audio, + u8 data, u8 mask, unsigned int reg) +{ + struct dw_hdmi *hdmi = audio->hdmi; + + audio->mod(hdmi, data, mask, reg); +} + static int dw_hdmi_i2s_hw_params(struct device *dev, void *data, struct hdmi_codec_daifmt *fmt, struct hdmi_codec_params *hparms) @@ -52,7 +60,8 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void *data, } /* Reset the FIFOs before applying new params */ - hdmi_write(audio, HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0); + hdmi_update_bits(audio, HDMI_AUD_CONF0_SW_RESET, + HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0); hdmi_write(audio, (u8)~HDMI_MC_SWRSTZ_I2SSWRST_REQ, HDMI_MC_SWRSTZ); inputclkfs = HDMI_AUD_INPUTCLKFS_64FS; @@ -141,7 +150,8 @@ static int dw_hdmi_i2s_prepare(struct device *dev, void *data, dw_hdmi_audio_disable(hdmi); - hdmi_write(audio, HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0); + hdmi_update_bits(audio, HDMI_AUD_CONF0_SW_RESET, + HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0); hdmi_write(audio, (u8)~HDMI_MC_SWRSTZ_I2SSWRST_REQ, HDMI_MC_SWRSTZ); dw_hdmi_audio_enable(hdmi); diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index c36513ce718e..f462aacda62f 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -5008,6 +5008,7 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, audio.get_eld = hdmi_audio_get_eld; audio.write = hdmi_writeb; audio.read = hdmi_readb; + audio.mod = hdmi_modb; hdmi->enable_audio = dw_hdmi_i2s_audio_enable; hdmi->disable_audio = dw_hdmi_i2s_audio_disable;