From 9b639eb39bcba67ef2a9318c9f4579bfd0fb890c Mon Sep 17 00:00:00 2001 From: Shengjiu Wang <shengjiu.wang@nxp.com> Date: Fri, 23 Oct 2020 19:52:10 +0800 Subject: [PATCH] MLK-24916-3: drm: bridge: synopsys: Add HBR support for gp audio Only non_pcm, 32bit, 192kHz, 8channel streams be recognized as HBR streams. In order to support this feature, need to enhance the API in dw-hdmi driver. The test command is: $iecset -c 4 audio off $aplay -Dhw:4 -r 192000 -c 8 -f S32_LE out_put.spd.iec958 $iecset -c 4 audio on Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com> Reviewed-by: Viorel Suman <viorel.suman@nxp.com> --- .../drm/bridge/synopsys/dw-hdmi-gp-audio.c | 4 +++ drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 30 ++++++++++++++++++- drivers/gpu/drm/imx/dw_hdmi-imx.c | 5 ++-- drivers/gpu/drm/imx/imx8mp-hdmi-pavi.c | 12 ++++++-- drivers/gpu/drm/imx/imx8mp-hdmi-pavi.h | 2 +- include/drm/bridge/dw_hdmi.h | 5 +++- 6 files changed, 51 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-gp-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-gp-audio.c index 10bf94586d385..b6b77ca7c8794 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-gp-audio.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-gp-audio.c @@ -89,6 +89,10 @@ static int audio_hw_params(struct device *dev, void *data, dw_hdmi_set_channel_count(dw->data.hdmi, params->channels); dw_hdmi_set_channel_allocation(dw->data.hdmi, ca); + dw_hdmi_set_sample_non_pcm(dw->data.hdmi, + params->iec.status[0] & IEC958_AES0_NONAUDIO); + dw_hdmi_set_sample_width(dw->data.hdmi, params->sample_width); + return ret; } diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index acd831a25b9b9..10149d9e26172 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -191,6 +191,8 @@ struct dw_hdmi { spinlock_t audio_lock; struct mutex audio_mutex; + unsigned int sample_non_pcm; + unsigned int sample_width; unsigned int sample_rate; unsigned int channels; unsigned int audio_cts; @@ -709,6 +711,22 @@ static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi) mutex_unlock(&hdmi->audio_mutex); } +void dw_hdmi_set_sample_width(struct dw_hdmi *hdmi, unsigned int width) +{ + mutex_lock(&hdmi->audio_mutex); + hdmi->sample_width = width; + mutex_unlock(&hdmi->audio_mutex); +} +EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_width); + +void dw_hdmi_set_sample_non_pcm(struct dw_hdmi *hdmi, unsigned int non_pcm) +{ + mutex_lock(&hdmi->audio_mutex); + hdmi->sample_non_pcm = non_pcm; + mutex_unlock(&hdmi->audio_mutex); +} +EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_non_pcm); + void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate) { mutex_lock(&hdmi->audio_mutex); @@ -828,8 +846,18 @@ static void dw_hdmi_gp_audio_enable(struct dw_hdmi *hdmi) hdmi_modb(hdmi, 0x3, 0x3, HDMI_FC_DATAUTO3); + /* hbr */ + if (hdmi->sample_rate == 192000 && hdmi->channels == 8 && + hdmi->sample_width == 32 && hdmi->sample_non_pcm) { + hdmi_modb(hdmi, 0x01, 0x01, HDMI_GP_CONF2); + } + if (hdmi->phy.ops->enable_audio) - hdmi->phy.ops->enable_audio(hdmi, hdmi->phy.data, hdmi->channels); + hdmi->phy.ops->enable_audio(hdmi, hdmi->phy.data, + hdmi->channels, + hdmi->sample_width, + hdmi->sample_rate, + hdmi->sample_non_pcm); } static void dw_hdmi_gp_audio_disable(struct dw_hdmi *hdmi) diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c index 23840c8724741..d8d8aad6407e5 100644 --- a/drivers/gpu/drm/imx/dw_hdmi-imx.c +++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c @@ -318,9 +318,10 @@ static int imx8mp_hdmimix_setup(struct imx_hdmi *hdmi) return clk_bulk_prepare_enable(ARRAY_SIZE(imx8mp_clocks), imx8mp_clocks); } -void imx8mp_hdmi_enable_audio(struct dw_hdmi *dw_hdmi, void *data, int channel) +void imx8mp_hdmi_enable_audio(struct dw_hdmi *dw_hdmi, void *data, int channel, + int width, int rate, int non_pcm) { - imx8mp_hdmi_pai_enable(channel); + imx8mp_hdmi_pai_enable(channel, width, rate, non_pcm); } void imx8mp_hdmi_disable_audio(struct dw_hdmi *dw_hdmi, void *data) diff --git a/drivers/gpu/drm/imx/imx8mp-hdmi-pavi.c b/drivers/gpu/drm/imx/imx8mp-hdmi-pavi.c index 9da1407386d06..d93694d803348 100644 --- a/drivers/gpu/drm/imx/imx8mp-hdmi-pavi.c +++ b/drivers/gpu/drm/imx/imx8mp-hdmi-pavi.c @@ -42,12 +42,20 @@ static struct imx8mp_hdmi_pavi *gpavi; /* PAI APIs */ -void imx8mp_hdmi_pai_enable(int channel) +void imx8mp_hdmi_pai_enable(int channel, int width, int rate, int non_pcm) { /* PAI set */ writel((0x3030000 | ((channel-1) << 8)), gpavi->base + HTX_PAI_CTRL_EXT); - writel(0x1c0c675b, gpavi->base + HTX_PAI_FIELD_CTRL); + + /* hbr */ + if (non_pcm && width == 32 && channel == 8 && rate == 192000) + writel(0x004e77df, gpavi->base + HTX_PAI_FIELD_CTRL); + else if (width == 32) + writel(0x1c8c675b, gpavi->base + HTX_PAI_FIELD_CTRL); + else + writel(0x1c0c675b, gpavi->base + HTX_PAI_FIELD_CTRL); + /* PAI start running */ writel(HTX_PAI_CTRL_ENABLE, gpavi->base + HTX_PAI_CTRL); } diff --git a/drivers/gpu/drm/imx/imx8mp-hdmi-pavi.h b/drivers/gpu/drm/imx/imx8mp-hdmi-pavi.h index 2eedd2d489b97..ef90bf46cb970 100644 --- a/drivers/gpu/drm/imx/imx8mp-hdmi-pavi.h +++ b/drivers/gpu/drm/imx/imx8mp-hdmi-pavi.h @@ -24,7 +24,7 @@ struct imx8mp_hdmi_pavi { struct reset_control *reset_pvi; }; -void imx8mp_hdmi_pai_enable(int channel); +void imx8mp_hdmi_pai_enable(int channel, int width, int rate, int non_pcm); void imx8mp_hdmi_pai_disable(void); void imx8mp_hdmi_pvi_enable(const struct drm_display_mode *mode); diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index 7c188e887b502..0c90f8d1d6ff6 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -121,7 +121,8 @@ struct dw_hdmi_phy_ops { void (*update_hpd)(struct dw_hdmi *hdmi, void *data, bool force, bool disabled, bool rxsense); void (*setup_hpd)(struct dw_hdmi *hdmi, void *data); - void (*enable_audio)(struct dw_hdmi *hdmi, void *data, int channel); + void (*enable_audio)(struct dw_hdmi *hdmi, void *data, int channel, + int width, int rate, int non_pcm); void (*disable_audio)(struct dw_hdmi *hdmi, void *data); }; @@ -175,6 +176,8 @@ void dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense); int dw_hdmi_set_plugged_cb(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb fn, struct device *codec_dev); +void dw_hdmi_set_sample_non_pcm(struct dw_hdmi *hdmi, unsigned int non_pcm); +void dw_hdmi_set_sample_width(struct dw_hdmi *hdmi, unsigned int width); void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate); void dw_hdmi_set_channel_count(struct dw_hdmi *hdmi, unsigned int cnt); void dw_hdmi_set_channel_status(struct dw_hdmi *hdmi, u8 *channel_status); -- GitLab