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 10bf94586d3856d2ff22364c076da7c34e406a15..b6b77ca7c8794af96ee37de00bdbfebce745a78c 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 acd831a25b9b9ebe94a70c682a1dcc352754ffe7..10149d9e26172de7110b727b406d6ee8f0968d10 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 23840c8724741cceceea444ec00cb68577caec4e..d8d8aad6407e57b6df194466b5db6f2882f01d36 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 9da1407386d063ef9f5c05f10d0021c6e01adf07..d93694d803348958e8af66c9d2efb231f7b963fe 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 2eedd2d489b97304761e33bffbe2c92f5c5d86f0..ef90bf46cb9700b45fadc31021915e062d04d1c6 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 7c188e887b5021cda4d6e82a1d0d06201ebf2674..0c90f8d1d6ff6f0c10c10653e207bdd307e182d9 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);