[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <aestmu2rblcrcz77tuqgkimaj4stg24skyp2avdstahwr3aa3i@cfv5ov2qjcf6>
Date: Mon, 21 Apr 2025 22:16:43 +0300
From: Dmitry Baryshkov <dmitry.baryshkov@....qualcomm.com>
To: AngeloGioacchino Del Regno <angelogioacchino.delregno@...labora.com>
Cc: chunkuang.hu@...nel.org, p.zabel@...gutronix.de, airlied@...il.com,
simona@...ll.ch, maarten.lankhorst@...ux.intel.com, mripard@...nel.org,
tzimmermann@...e.de, robh@...nel.org, krzk+dt@...nel.org,
conor+dt@...nel.org, matthias.bgg@...il.com, ck.hu@...iatek.com,
jitao.shi@...iatek.com, jie.qiu@...iatek.com, junzhi.zhao@...iatek.com,
dri-devel@...ts.freedesktop.org, linux-mediatek@...ts.infradead.org,
devicetree@...r.kernel.org, linux-kernel@...r.kernel.org,
linux-arm-kernel@...ts.infradead.org, kernel@...labora.com,
dmitry.baryshkov@...aro.org, lewis.liao@...iatek.com,
ives.chenjh@...iatek.com, tommyyl.chen@...iatek.com,
jason-jh.lin@...iatek.com
Subject: Re: [PATCH v9 22/23] drm/mediatek: Introduce HDMI/DDC v2 for
MT8195/MT8188
On Tue, Apr 15, 2025 at 12:43:20PM +0200, AngeloGioacchino Del Regno wrote:
> Add support for the newer HDMI-TX (Encoder) v2 and DDC v2 IPs
> found in MediaTek's MT8195, MT8188 SoC and their variants, and
> including support for display modes up to 4k60 and for HDMI
> Audio, as per the HDMI 2.0 spec.
>
> HDCP and CEC functionalities are also supported by this hardware,
> but are not included in this commit and that also poses a slight
> difference between the V2 and V1 controllers in how they handle
> Hotplug Detection (HPD).
>
> While the v1 controller was using the CEC controller to check
> HDMI cable connection and disconnection, in this driver the v2
> one does not.
>
> This is due to the fact that on parts with v2 designs, like the
> MT8195 SoC, there is one CEC controller shared between the HDMI
> Transmitter (HDMI-TX) and Receiver (HDMI-RX): before eventually
> adding support to use the CEC HW to wake up the HDMI controllers
> it is necessary to have support for one TX, one RX *and* for both
> at the same time.
>
> Reviewed-by: CK Hu <ck.hu@...iatek.com>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@...labora.com>
> ---
> drivers/gpu/drm/mediatek/Kconfig | 7 +
> drivers/gpu/drm/mediatek/Makefile | 2 +
> drivers/gpu/drm/mediatek/mtk_hdmi_common.c | 4 +
> drivers/gpu/drm/mediatek/mtk_hdmi_common.h | 9 +
> drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c | 385 +++++
> drivers/gpu/drm/mediatek/mtk_hdmi_regs_v2.h | 263 ++++
> drivers/gpu/drm/mediatek/mtk_hdmi_v2.c | 1396 +++++++++++++++++++
> 7 files changed, 2066 insertions(+)
> create mode 100644 drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c
> create mode 100644 drivers/gpu/drm/mediatek/mtk_hdmi_regs_v2.h
> create mode 100644 drivers/gpu/drm/mediatek/mtk_hdmi_v2.c
>
> +
> +static int mtk_hdmi_v2_setup_audio_infoframe(struct mtk_hdmi *hdmi)
> +{
> + struct hdmi_codec_params *params = &hdmi->aud_param.codec_params;
> + struct hdmi_audio_infoframe frame;
> + u8 buffer[14];
> + ssize_t ret;
> +
> + memcpy(&frame, ¶ms->cea, sizeof(frame));
> +
> + ret = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
> + if (ret < 0)
> + return ret;
This should really be done via
drm_atomic_helper_connector_hdmi_update_audio_infoframe() or
drm_atomic_helper_connector_hdmi_clear_audio_infoframe().
Ideally this should come from the .hw_params() / .prepare() calls so
that you don't need to store the params in the driver data.
> +
> + mtk_hdmi_v2_hw_write_audio_infoframe(hdmi, buffer);
> +
> + return 0;
> +}
> +
> +static inline void mtk_hdmi_v2_hw_gcp_avmute(struct mtk_hdmi *hdmi, bool mute)
> +{
> + u32 val;
> +
> + regmap_read(hdmi->regs, TOP_CFG01, &val);
> + val &= ~(CP_CLR_MUTE_EN | CP_SET_MUTE_EN);
> +
> + if (mute) {
> + val |= CP_SET_MUTE_EN;
> + val &= ~CP_CLR_MUTE_EN;
> + } else {
> + val |= CP_CLR_MUTE_EN;
> + val &= ~CP_SET_MUTE_EN;
> + }
> + regmap_write(hdmi->regs, TOP_CFG01, val);
> +
> + regmap_set_bits(hdmi->regs, TOP_INFO_RPT, CP_RPT_EN);
> + regmap_set_bits(hdmi->regs, TOP_INFO_EN, CP_EN | CP_EN_WR);
> +}
> +
> +static void mtk_hdmi_v2_hw_ncts_enable(struct mtk_hdmi *hdmi, bool enable)
> +{
> + if (enable)
> + regmap_set_bits(hdmi->regs, AIP_CTRL, CTS_SW_SEL);
> + else
> + regmap_clear_bits(hdmi->regs, AIP_CTRL, CTS_SW_SEL);
> +}
> +
> +static void mtk_hdmi_v2_hw_aud_set_channel_status(struct mtk_hdmi *hdmi)
> +{
> + u8 *ch_status = hdmi->aud_param.codec_params.iec.status;
> +
> + /* Only the first 5 to 7 bytes of Channel Status contain useful information */
> + regmap_write(hdmi->regs, AIP_I2S_CHST0, mtk_hdmi_v2_format_hw_packet(&ch_status[0], 4));
> + regmap_write(hdmi->regs, AIP_I2S_CHST1, mtk_hdmi_v2_format_hw_packet(&ch_status[4], 3));
> +}
> +
> +static void mtk_hdmi_v2_hw_aud_set_ncts(struct mtk_hdmi *hdmi,
> + unsigned int sample_rate,
> + unsigned int clock)
> +{
> + unsigned int n, cts;
> +
> + mtk_hdmi_get_ncts(sample_rate, clock, &n, &cts);
drm_hdmi_acr_get_n_cts() ?
> +
> + regmap_write(hdmi->regs, AIP_N_VAL, n);
> + regmap_write(hdmi->regs, AIP_CTS_SVAL, cts);
> +}
> +
[...]
> +
> +static int mtk_hdmi_v2_audio_hw_params(struct device *dev, void *data,
> + struct hdmi_codec_daifmt *daifmt,
> + struct hdmi_codec_params *params)
> +{
> + struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
> +
> + if (hdmi->audio_enable) {
> + mtk_hdmi_audio_params(hdmi, daifmt, params);
> + mtk_hdmi_v2_aud_output_config(hdmi, &hdmi->mode);
> + }
> + return 0;
> +}
> +
> +static int mtk_hdmi_v2_audio_startup(struct device *dev, void *data)
> +{
> + struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
> +
> + mtk_hdmi_v2_hw_aud_enable(hdmi, true);
> + hdmi->audio_enable = true;
> +
> + return 0;
> +}
> +
> +static void mtk_hdmi_v2_audio_shutdown(struct device *dev, void *data)
> +{
> + struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
> +
> + hdmi->audio_enable = false;
> + mtk_hdmi_v2_hw_aud_enable(hdmi, false);
Most likely you need to stop sending the AUDIO packet too. Or is it dome
by the hardware?
> +}
> +
> +static int mtk_hdmi_v2_audio_mute(struct device *dev, void *data, bool enable, int dir)
> +{
> + struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
> +
> + mtk_hdmi_v2_hw_aud_mute(hdmi, enable);
> +
> + return 0;
> +}
> +
> +static const struct hdmi_codec_ops mtk_hdmi_v2_audio_codec_ops = {
> + .hw_params = mtk_hdmi_v2_audio_hw_params,
> + .audio_startup = mtk_hdmi_v2_audio_startup,
> + .audio_shutdown = mtk_hdmi_v2_audio_shutdown,
> + .mute_stream = mtk_hdmi_v2_audio_mute,
> + .get_eld = mtk_hdmi_audio_get_eld,
> + .hook_plugged_cb = mtk_hdmi_v2_audio_hook_plugged_cb,
> +};
Do you plan to switch to the OP_HDMI_AUDIO? I'd really like to see
bridges use the framework instead of implementing everthing on their
own.
> +
> +static __maybe_unused int mtk_hdmi_v2_suspend(struct device *dev)
> +{
> + struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
> +
> + mtk_hdmi_v2_disable(hdmi);
> +
> + return 0;
> +}
> +
--
With best wishes
Dmitry
Powered by blists - more mailing lists