On 7/28/26 7:29 AM, Julien Stephan wrote:
> Add a UCLASS_VIDEO driver for the HDMI TX v2 IP found on the MT8188.
> 
> On probe, the driver waits for a plugged and powered display, reads
> its EDID through the DDC bus to select the preferred mode, configures
> the HDMI controller and PHY accordingly, and then programs all the
> components of the vdosys1 pipeline (MDP RDMA, padding, VPP merge,
> ETHDR mixer, mutex, DPI1) to scan out the framebuffer. The
> framebuffer lives in a dedicated reserved-memory region referenced by
> the "memory-region" property of the hdmi node.
> 
> Signed-off-by: Pavlo Yadvychuk <[email protected]>
> Signed-off-by: Julien Stephan <[email protected]>
> ---
>  drivers/video/Kconfig                         |   1 +
>  drivers/video/Makefile                        |   1 +
>  drivers/video/mediatek/Kconfig                |  21 +
>  drivers/video/mediatek/Makefile               |  16 +
>  drivers/video/mediatek/mtk_hdmi.c             | 919 
> ++++++++++++++++++++++++++
>  drivers/video/mediatek/mtk_mt8188_hdmi_regs.h | 103 +++
>  6 files changed, 1061 insertions(+)
> 
> diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> index 15000e21840..cb3ba6a6f63 100644
> --- a/drivers/video/Kconfig
> +++ b/drivers/video/Kconfig
> @@ -770,6 +770,7 @@ config VIDEO_LCD_SPI_MISO
>         option takes a string in the format understood by 'sunxi_name_to_gpio'
>         function, e.g. PH1 for pin 1 of port H.
>  
> +source "drivers/video/mediatek/Kconfig"
>  source "drivers/video/meson/Kconfig"
>  
>  config VIDEO_MVEBU
> diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> index 082b8967982..a20011b9b17 100644
> --- a/drivers/video/Makefile
> +++ b/drivers/video/Makefile
> @@ -92,5 +92,6 @@ obj-$(CONFIG_VIDEO_SEPS525) += seps525.o
>  obj-$(CONFIG_VIDEO_ZYNQMP_DPSUB) += zynqmp/
>  
>  obj-y += bridge/
> +obj-y += mediatek/
>  obj-y += sunxi/
>  obj-y += tegra/
> diff --git a/drivers/video/mediatek/Kconfig b/drivers/video/mediatek/Kconfig
> new file mode 100644
> index 00000000000..427d7e36b90
> --- /dev/null
> +++ b/drivers/video/mediatek/Kconfig
> @@ -0,0 +1,21 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +#
> +# Copyright (C) 2022 BayLibre, SAS
> +#
> +# Author: Julien Stephan <[email protected]>
> +
> +config VIDEO_MEDIATEK_HDMI
> +     bool "Video HDMI Support for Mediatek SoCs"
> +     depends on VIDEO && ARCH_MEDIATEK
> +     depends on DM_I2C && PHY && POWER_DOMAIN
> +     select I2C_EDID
> +     select MISC
> +     select PHY_MTK_HDMI
> +     select MTK_POWER_DOMAIN
> +     select SYS_I2C_DDC_MTK
> +     help
> +       Enable support for the HDMI TX output found on recent MediaTek
> +       SoCs such as the MT8188. The driver reads the EDID of the
> +       connected display, selects its preferred mode and drives the
> +       vdosys1 display pipeline (MDP RDMA, padding, merge, ETHDR
> +       mixer, DPI) to scan out the U-Boot framebuffer over HDMI.
> diff --git a/drivers/video/mediatek/Makefile b/drivers/video/mediatek/Makefile
> new file mode 100644
> index 00000000000..af54450a836
> --- /dev/null
> +++ b/drivers/video/mediatek/Makefile
> @@ -0,0 +1,16 @@
> +# SPDX-License-Identifier: GPL-2.0
> +#
> +# Copyright (c) 2023 MediaTek Inc.
> +#
> +# Author: Julien Stephan <[email protected]>
> +
> +obj-$(CONFIG_VIDEO_MEDIATEK_HDMI) += \

Similar to other comment, if this is for just mt8188, then the
config option should also be CONFIG_VIDEO_MEDIATEK_HDMI_MT8188.
Othweriwse, _mt8188 should be removed from all of the file names.

> +     mtk_hdmi.o \
> +     mtk_disp_comp.o \
> +     mtk_dpi_mt8188.o \
> +     mtk_mdp_rdma_mt8188.o \
> +     mtk_disp_merge_mt8188.o \
> +     mtk_disp_mixer_mt8188.o \
> +     mtk_disp_mutex_mt8188.o \
> +     mtk_disp_padding_mt8188.o \
> +     mtk_vdosys1_mt8188.o
> diff --git a/drivers/video/mediatek/mtk_hdmi.c 
> b/drivers/video/mediatek/mtk_hdmi.c
> new file mode 100644
> index 00000000000..e174585fcbb
> --- /dev/null
> +++ b/drivers/video/mediatek/mtk_hdmi.c
> @@ -0,0 +1,919 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2025 BayLibre, SAS
> + * Author: Julien Stephan <[email protected]>
> + */
> +
> +#include <asm/io.h>
> +#include <asm/system.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <dm/device_compat.h>
> +#include <edid.h>
> +#include <errno.h>
> +#include <generic-phy.h>
> +#include <i2c.h>
> +#include <linux/delay.h>
> +#include <video.h>
> +
> +#include "mtk_disp_comp.h"
> +#include "mtk_disp_merge_mt8188.h"
> +#include "mtk_disp_mixer_mt8188.h"
> +#include "mtk_disp_mutex_mt8188.h"
> +#include "mtk_disp_padding_mt8188.h"
> +#include "mtk_dpi_mt8188.h"
> +#include "mtk_mdp_rdma_mt8188.h"
> +#include "mtk_mt8188_hdmi_regs.h"
> +#include "mtk_vdosys1_mt8188.h"
> +
> +#define MTK_HDMI_MAX_WIDTH                   3840
> +#define MTK_HDMI_MAX_HEIGHT                  2160
> +
> +#define MTK_HDMI_HPD_TIMEOUT_MS                      100
> +
> +/* 4 byte header + 13 byte payload */
> +#define HDMI_AVI_INFOFRAME_SIZE                      17
> +/* 4 byte header + 25 byte payload */
> +#define HDMI_SPD_INFOFRAME_SIZE                      29
> +
> +#define RGB444_8bit                          BIT(0)
> +#define RGB444_10bit                         BIT(1)
> +#define RGB444_12bit                         BIT(2)
> +#define RGB444_16bit                         BIT(3)
> +#define YCBCR444_8bit                                BIT(4)
> +#define YCBCR444_10bit                               BIT(5)
> +#define YCBCR444_12bit                               BIT(6)
> +#define YCBCR444_16bit                               BIT(7)
> +
> +#define YCBCR422_8bit_NO_SUPPORT             BIT(8)
> +#define YCBCR422_10bit_NO_SUPPORT            BIT(9)
> +#define YCBCR422_12bit                               BIT(10)
> +#define YCBCR422_16bit_NO_SUPPORT            BIT(11)
> +
> +#define YCBCR420_8bit                                BIT(12)
> +#define YCBCR420_10bit                               BIT(13)
> +#define YCBCR420_12bit                               BIT(14)
> +#define YCBCR420_16bit                               BIT(15)
> +
> +#define BYTES_TO_UINT32(msb, b1, b2, lsb)    \
> +     ((((msb) & 0xff) << 24) + (((b1) & 0xff) << 16) + (((b2) & 0xff) << 8) 
> + \
> +      (((lsb) & 0xff)))

Looks like we could replace this with get_unaligned_le32() and 
get_unaligned_le24().
The latter would need to be ported from Linux.

> +
> +enum hdmi_color_depth {
> +     HDMI_8_BIT,
> +     HDMI_10_BIT,
> +     HDMI_12_BIT,
> +     HDMI_16_BIT,
> +};
> +
> +enum hdmi_colorspace {
> +     HDMI_COLORSPACE_RGB,
> +     HDMI_COLORSPACE_YUV422,
> +     HDMI_COLORSPACE_YUV444,
> +     HDMI_COLORSPACE_YUV420,
> +     HDMI_COLORSPACE_RESERVED4,
> +     HDMI_COLORSPACE_RESERVED5,
> +     HDMI_COLORSPACE_RESERVED6,
> +     HDMI_COLORSPACE_IDO_DEFINED,
> +};
> +
> +enum hdmi_colorimetry {
> +     HDMI_COLORIMETRY_NONE,
> +     HDMI_COLORIMETRY_ITU_601,
> +     HDMI_COLORIMETRY_ITU_709,
> +     HDMI_COLORIMETRY_EXTENDED,
> +};

Should some of these be moved to a generic header? I assume they
are the same everywhere (e.g. as seen in linux/hdmi.h).

> +
> +struct mtk_hdmi {
> +     struct udevice *dev;
> +     struct udevice *ddc_bus;
> +     struct udevice *dpi1;
> +     struct udevice *vdosys1;
> +     struct udevice *merge3;
> +     struct udevice *merge5;
> +     struct udevice *mixer;
> +     struct udevice *mutex;
> +     struct udevice *padding4;
> +     struct udevice *padding5;
> +     struct udevice *rdma4;
> +     struct udevice *rdma5;
> +     struct phy phy;
> +     fdt_addr_t regs;
> +     struct clk_bulk clk_bulk;
> +     u64 support_csp_depth;
> +     u64 set_csp_depth;
> +     enum hdmi_colorspace csp;
> +     enum hdmi_color_depth color_depth;
> +     enum hdmi_colorimetry colorimetry;
> +     struct display_timing mode;
> +};
> +
> +enum hdmi_hpd_state {
> +     HDMI_PLUG_OUT = 0,
> +     HDMI_PLUG_IN_AND_SINK_POWER_ON,
> +     HDMI_PLUG_IN_ONLY,
> +};
> +
> +static u32 mtk_hdmi_read(struct mtk_hdmi *hdmi, u32 offset)
> +{
> +     return readl(hdmi->regs + offset);
> +}
> +
> +static void mtk_hdmi_write(struct mtk_hdmi *hdmi, u32 offset, u32 val)
> +{
> +     writel(val, hdmi->regs + offset);
> +}
> +
> +static void mtk_hdmi_mask(struct mtk_hdmi *hdmi, u32 offset, u32 val, u32 
> mask)

mtk_hdmi_update() is better name?

> +{
> +     fdt_addr_t reg = hdmi->regs + offset;
> +     u32 tmp;
> +
> +     tmp = readl(reg);
> +     tmp = (tmp & ~mask) | (val & mask);
> +     writel(tmp, reg);
> +}
> +
> +static void mtk_hdmi_enable_hdmi_mode(struct mtk_hdmi *hdmi, bool enable)
> +{
> +     if (enable)
> +             mtk_hdmi_mask(hdmi, TOP_CFG00, HDMI_MODE_HDMI, HDMI_MODE_HDMI);
> +     else
> +             mtk_hdmi_mask(hdmi, TOP_CFG00, HDMI_MODE_DVI, HDMI_MODE_HDMI);

Would be a bit easier to see what is different like:

        u32 value = enable : HDMI_MODE_HDMI : HDMI_MODE_DVI;

        mtk_hdmi_mask(hdmi, TOP_CFG00, value, HDMI_MODE_HDMI);

Same applies below.

> +}
> +
> +static void mtk_hdmi_hw_vid_black(struct mtk_hdmi *hdmi, bool black)
> +{
> +     if (black)
> +             mtk_hdmi_mask(hdmi, TOP_VMUTE_CFG1, REG_VMUTE_EN, REG_VMUTE_EN);
> +     else
> +             mtk_hdmi_mask(hdmi, TOP_VMUTE_CFG1, 0, REG_VMUTE_EN);
> +}
> +
> +static void mtk_hdmi_hw_reset(struct mtk_hdmi *hdmi)
> +{
> +     mtk_hdmi_mask(hdmi, HDMI_CONFIG, 0x0 << HDMITX_SW_RSTB_SHIFT,

So just 0 to make it shorter?

> +                   HDMITX_SW_RSTB);
> +     udelay(5);
> +     mtk_hdmi_mask(hdmi, HDMI_CONFIG, 0x1 << HDMITX_SW_RSTB_SHIFT,

We already have HDMITX_SW_RSTB macro.

> +                   HDMITX_SW_RSTB);
> +}
> +
> +static inline void mtk_hdmi_set_sw_hpd(struct mtk_hdmi *hdmi, bool high)
> +{
> +     if (high)
> +             mtk_hdmi_mask(hdmi, HDMI_CONFIG, 0x1 << HDMITX_SW_HPD_SHIFT,

HDMITX_SW_HPD

> +                           HDMITX_SW_HPD);
> +     else
> +             mtk_hdmi_mask(hdmi, HDMI_CONFIG, 0x0 << HDMITX_SW_HPD_SHIFT,
> +                           HDMITX_SW_HPD);
> +}
> +
> +static void mtk_hdmi_set_deep_color(struct mtk_hdmi *hdmi, bool is_hdmi_sink)
> +{
> +     unsigned int deep_color = 0;

I assume 0 is DEEPCOLOR_MODE_8BIT? Would make more sense to put this
in the default case if it is meant as a fallback.

> +
> +     /* ycbcr422 12bit no deep color */
> +     if (hdmi->csp == HDMI_COLORSPACE_YUV422) {
> +             deep_color = DEEPCOLOR_MODE_8BIT;
> +     } else {
> +             switch (hdmi->color_depth) {
> +             case HDMI_8_BIT:
> +                     deep_color = DEEPCOLOR_MODE_8BIT;
> +                     break;
> +             case HDMI_10_BIT:
> +                     deep_color = DEEPCOLOR_MODE_10BIT;
> +                     break;
> +             case HDMI_12_BIT:
> +                     deep_color = DEEPCOLOR_MODE_12BIT;
> +                     break;
> +             case HDMI_16_BIT:
> +                     deep_color = DEEPCOLOR_MODE_16BIT;
> +                     break;
> +             default:
> +                     dev_warn(hdmi->dev, "Unsupported color depth %d\n",
> +                              hdmi->color_depth);

Missing break. Or should it return?

> +             }
> +     }
> +
> +     mtk_hdmi_mask(hdmi, TOP_CFG00, deep_color, DEEPCOLOR_MODE_MASKBIT);
> +
> +     /* GCP */
> +     mtk_hdmi_mask(hdmi, TOP_CFG00, 0, DEEPCOLOR_PAT_EN);
> +     if (is_hdmi_sink && deep_color != DEEPCOLOR_MODE_8BIT)
> +             mtk_hdmi_mask(hdmi, TOP_MISC_CTLR, DEEP_COLOR_ADD,
> +                           DEEP_COLOR_ADD);
> +     else
> +             mtk_hdmi_mask(hdmi, TOP_MISC_CTLR, 0, DEEP_COLOR_ADD);
> +}
> +
> +static void mtk_hdmi_yuv420_downsample(struct mtk_hdmi *hdmi, bool enable)

This could just be 2 different functions since nothing is shared between
the two branches.

> +{
> +     if (enable) {
> +             mtk_hdmi_mask(hdmi, HDMI_CONFIG,
> +                           HDMI_YUV420_MODE | HDMITX_SW_HPD,
> +                           HDMI_YUV420_MODE | HDMITX_SW_HPD);
> +             mtk_hdmi_mask(hdmi, VID_DOWNSAMPLE_CONFIG,
> +                           C444_C422_CONFIG_ENABLE, C444_C422_CONFIG_ENABLE);
> +             mtk_hdmi_mask(hdmi, VID_DOWNSAMPLE_CONFIG,
> +                           C422_C420_CONFIG_ENABLE, C422_C420_CONFIG_ENABLE);
> +             mtk_hdmi_mask(hdmi, VID_DOWNSAMPLE_CONFIG, 0,
> +                           C422_C420_CONFIG_BYPASS);
> +             mtk_hdmi_mask(hdmi, VID_DOWNSAMPLE_CONFIG,
> +                           C422_C420_CONFIG_OUT_CB_OR_CR,
> +                           C422_C420_CONFIG_OUT_CB_OR_CR);
> +             mtk_hdmi_mask(hdmi, VID_OUT_FORMAT,
> +                           OUTPUT_FORMAT_DEMUX_420_ENABLE,
> +                           OUTPUT_FORMAT_DEMUX_420_ENABLE);
> +     } else {
> +             mtk_hdmi_mask(hdmi, HDMI_CONFIG, 0 | HDMITX_SW_HPD,
> +                           HDMI_YUV420_MODE | HDMITX_SW_HPD);
> +             mtk_hdmi_mask(hdmi, VID_DOWNSAMPLE_CONFIG, 0,
> +                           C444_C422_CONFIG_ENABLE);
> +             mtk_hdmi_mask(hdmi, VID_DOWNSAMPLE_CONFIG, 0,
> +                           C422_C420_CONFIG_ENABLE);
> +             mtk_hdmi_mask(hdmi, VID_DOWNSAMPLE_CONFIG,
> +                           C422_C420_CONFIG_BYPASS, C422_C420_CONFIG_BYPASS);
> +             mtk_hdmi_mask(hdmi, VID_DOWNSAMPLE_CONFIG, 0,
> +                           C422_C420_CONFIG_OUT_CB_OR_CR);
> +             mtk_hdmi_mask(hdmi, VID_OUT_FORMAT, 0,
> +                           OUTPUT_FORMAT_DEMUX_420_ENABLE);
> +     }
> +}
> +
> +static bool mtk_hdmi_tmds_over_340M(struct mtk_hdmi *hdmi)
> +{
> +     unsigned long pixel_clk, tmds_clk;
> +
> +     pixel_clk = hdmi->mode.pixelclock.typ;
> +
> +     switch (hdmi->color_depth) {
> +     case HDMI_8_BIT:
> +             tmds_clk = pixel_clk;
> +             break;
> +     case HDMI_10_BIT:
> +             tmds_clk = pixel_clk * 5 / 4;
> +             break;
> +     case HDMI_12_BIT:
> +             tmds_clk = pixel_clk * 3 / 2;
> +             break;
> +     case HDMI_16_BIT:
> +             tmds_clk = pixel_clk * 2;
> +             break;
> +     default:
> +             dev_warn(hdmi->dev, "Unsupported color depth %d\n",
> +                      hdmi->color_depth);
> +             return false;
> +     }
> +
> +     return tmds_clk >= 340000000 && hdmi->csp != HDMI_COLORSPACE_YUV420;

Can we get a macro for 340000000 to explain what it is?

> +}
> +
> +static inline void mtk_hdmi_enable_scrambling(struct mtk_hdmi *hdmi,
> +                                           bool enable)
> +{
> +     udelay(150);
> +
> +     if (enable)
> +             mtk_hdmi_mask(hdmi, TOP_CFG00, SCR_ON | HDMI2_ON,
> +                           SCR_ON | HDMI2_ON);
> +     else
> +             mtk_hdmi_mask(hdmi, TOP_CFG00, SCR_OFF | HDMI2_OFF,
> +                           SCR_ON | HDMI2_ON);
> +}
> +
> +static void mtk_hdmi_disable_abist(struct mtk_hdmi *hdmi)
> +{
> +     mtk_hdmi_mask(hdmi, TOP_CFG00, 0, ABIST_ENABLE);
> +}
> +
> +static void mtk_hdmi_change_video_resolution(struct mtk_hdmi *hdmi)
> +{
> +     bool is_over_340M = false;

Initializing this is dead code.

> +     bool is_hdmi_sink = true;

Making this const would make it a bit more obivous how this
is being used.

> +
> +     mtk_hdmi_hw_reset(hdmi);
> +     mtk_hdmi_set_sw_hpd(hdmi, true);
> +     udelay(5);
> +
> +     mtk_hdmi_write(hdmi, HDCP_TOP_CTRL, 0x0);
> +
> +     mtk_hdmi_set_deep_color(hdmi, is_hdmi_sink);
> +     mtk_hdmi_enable_hdmi_mode(hdmi, is_hdmi_sink);
> +
> +     udelay(10);
> +     mtk_hdmi_hw_vid_black(hdmi, true);
> +
> +     mtk_hdmi_mask(hdmi, TOP_CFG01, NULL_PKT_VSYNC_HIGH_EN,
> +                   NULL_PKT_VSYNC_HIGH_EN | NULL_PKT_EN);
> +
> +     is_over_340M = mtk_hdmi_tmds_over_340M(hdmi);
> +     dev_dbg(hdmi->dev, "is_over_340M: %d\n", is_over_340M);
> +
> +     mtk_hdmi_enable_scrambling(hdmi, is_over_340M);
> +
> +     if (hdmi->csp == HDMI_COLORSPACE_YUV420)
> +             mtk_hdmi_yuv420_downsample(hdmi, true);
> +     else
> +             mtk_hdmi_yuv420_downsample(hdmi, false);
> +}
> +
> +static void mtk_hdmi_output_set_display_mode(struct mtk_hdmi *hdmi,
> +                                          struct display_timing *mode)
> +{
> +     unsigned long link_rate = mode->pixelclock.typ;
> +     int ret;
> +
> +     ret = generic_phy_configure(&hdmi->phy, &link_rate);
> +     if (ret)
> +             dev_err(hdmi->dev, "Setting clock=%u failed: %d\n",
> +                     mode->pixelclock.typ, ret);
> +
> +     mtk_hdmi_change_video_resolution(hdmi);
> +}
> +
> +static void mtk_hdmi_convert_colorspace_depth(struct mtk_hdmi *hdmi)
> +{
> +     switch (hdmi->set_csp_depth) {
> +     case RGB444_8bit:
> +             hdmi->csp = HDMI_COLORSPACE_RGB;
> +             hdmi->color_depth = HDMI_8_BIT;
> +             break;
> +     case RGB444_10bit:
> +             hdmi->csp = HDMI_COLORSPACE_RGB;
> +             hdmi->color_depth = HDMI_10_BIT;
> +             break;
> +     case RGB444_12bit:
> +             hdmi->csp = HDMI_COLORSPACE_RGB;
> +             hdmi->color_depth = HDMI_12_BIT;
> +             break;
> +     case RGB444_16bit:
> +             hdmi->csp = HDMI_COLORSPACE_RGB;
> +             hdmi->color_depth = HDMI_16_BIT;
> +             break;
> +     case YCBCR444_8bit:
> +             hdmi->csp = HDMI_COLORSPACE_YUV444;
> +             hdmi->color_depth = HDMI_8_BIT;
> +             break;
> +     case YCBCR444_10bit:
> +             hdmi->csp = HDMI_COLORSPACE_YUV444;
> +             hdmi->color_depth = HDMI_10_BIT;
> +             break;
> +     case YCBCR444_12bit:
> +             hdmi->csp = HDMI_COLORSPACE_YUV444;
> +             hdmi->color_depth = HDMI_12_BIT;
> +             break;
> +     case YCBCR444_16bit:
> +             hdmi->csp = HDMI_COLORSPACE_YUV444;
> +             hdmi->color_depth = HDMI_16_BIT;
> +             break;
> +     case YCBCR422_12bit:
> +             hdmi->csp = HDMI_COLORSPACE_YUV422;
> +             hdmi->color_depth = HDMI_12_BIT;
> +             break;
> +     case YCBCR420_8bit:
> +             hdmi->csp = HDMI_COLORSPACE_YUV420;
> +             hdmi->color_depth = HDMI_8_BIT;
> +             break;
> +     case YCBCR420_10bit:
> +             hdmi->csp = HDMI_COLORSPACE_YUV420;
> +             hdmi->color_depth = HDMI_10_BIT;
> +             break;
> +     case YCBCR420_12bit:
> +             hdmi->csp = HDMI_COLORSPACE_YUV420;
> +             hdmi->color_depth = HDMI_12_BIT;
> +             break;
> +     case YCBCR420_16bit:
> +             hdmi->csp = HDMI_COLORSPACE_YUV420;
> +             hdmi->color_depth = HDMI_16_BIT;
> +             break;
> +     default:
> +             hdmi->csp = HDMI_COLORSPACE_RGB;
> +             hdmi->color_depth = HDMI_8_BIT;
> +     }
> +
> +     dev_dbg(hdmi->dev, "color space: %d, color depth: %d\n",
> +             hdmi->csp, hdmi->color_depth);
> +}
> +
> +static int mtk_hdmi_setup_spd_infoframe(struct mtk_hdmi *hdmi, u8 *buffer,
> +                                     size_t bufsz, const char *vendor,
> +                                     const char *product)
> +{
> +     u8 checksum = 0;
> +     int i;
> +
> +     if (bufsz < HDMI_SPD_INFOFRAME_SIZE)
> +             return -EINVAL;
> +
> +     memset(buffer, 0, HDMI_SPD_INFOFRAME_SIZE);
> +
> +     /* SPD InfoFrame header */
> +     buffer[0] = 0x83;  /* SPD InfoFrame type */
> +     buffer[1] = 0x01;  /* Version */
> +     buffer[2] = 0x19;  /* Length (25 bytes) */
> +
> +     /* Vendor name (8 bytes, padded with spaces) */
> +     strlcpy((char *)&buffer[4], vendor, 8);

Why is vendor limited to 8 if we pad with spaced up to 12?

And this only copies up to 7 chars because of strlcpy() ensuring
zero terminator, so comment is misleading.

> +     for (i = 4; i < 12; i++) {
> +             if (buffer[i] == '\0')
> +                     buffer[i] = ' ';
> +     }
> +
> +     /* Product description (16 bytes, padded with spaces) */
> +     strlcpy((char *)&buffer[12], product, 16);

Similar.

> +     for (i = 12; i < 28; i++) {
> +             if (buffer[i] == '\0')
> +                     buffer[i] = ' ';
> +     }
> +
> +     /* checksum over the full frame, so that the total sums to zero */
> +     for (i = 0; i < HDMI_SPD_INFOFRAME_SIZE; i++)
> +             checksum += buffer[i];
> +     buffer[3] = 0x100 - checksum;
> +
> +     return 0;
> +}
> +
> +static int mtk_hdmi_setup_avi_infoframe(struct mtk_hdmi *hdmi, u8 *buffer,
> +                                     size_t bufsz,
> +                                     struct display_timing *mode)
> +{
> +     u8 checksum = 0;
> +     int i;
> +
> +     if (bufsz < HDMI_AVI_INFOFRAME_SIZE)
> +             return -EINVAL;
> +
> +     memset(buffer, 0, HDMI_AVI_INFOFRAME_SIZE);
> +
> +     /* AVI InfoFrame header */
> +     buffer[0] = 0x82;  /* AVI InfoFrame type */
> +     buffer[1] = 0x02;  /* Version */
> +     buffer[2] = 0x0D;  /* Length (13 bytes) */
> +
> +     /* Data byte 1: Scan info, bar info, active format info, RGB/YCC */
> +     buffer[4] = 0x00; /* RGB by default */
> +     if (hdmi->csp == HDMI_COLORSPACE_YUV422)
> +             buffer[4] |= 0x20;  /* YCC422 */
> +     else if (hdmi->csp == HDMI_COLORSPACE_YUV444)
> +             buffer[4] |= 0x40;  /* YCC444 */
> +     else if (hdmi->csp == HDMI_COLORSPACE_YUV420)
> +             buffer[4] |= 0x60;  /* YCC420 */

Would make this a switch statemnt. Then we don't need the comments about
default or YCCxxx.

Or make an else case at the end and change all |= to =.

> +
> +     /* Data byte 4: Video Identification Code (VIC) */
> +     if (mode->hactive.typ == 1920 && mode->vactive.typ == 1080)
> +             buffer[7] = 16;  /* 1920x1080@60Hz */
> +     else if (mode->hactive.typ == 1280 && mode->vactive.typ == 720)
> +             buffer[7] = 4;   /* 1280x720@60Hz */
> +     else if (mode->hactive.typ == 720 && mode->vactive.typ == 480)
> +             buffer[7] = 2;   /* 720x480@60Hz */
> +     else
> +             buffer[7] = 0;   /* Unknown/unsupported timing */
> +
> +     /*
> +      * Data byte 2: picture aspect ratio, active portion same as
> +      * picture. VIC 2 is a 4:3 mode, the others are 16:9.
> +      */
> +     buffer[5] = buffer[7] == 2 ? 0x18 : 0x28;
> +
> +     /* Data byte 3: Colorimetry, picture scaling */
> +     buffer[6] = 0x00;  /* No specific colorimetry */
> +     if (hdmi->colorimetry == HDMI_COLORIMETRY_ITU_709)
> +             buffer[6] |= 0x80;
> +     else if (hdmi->colorimetry == HDMI_COLORIMETRY_ITU_601)
> +             buffer[6] |= 0x40;

Similar.

> +
> +     /* Data byte 5: Pixel repetition */
> +     buffer[8] = 0x00;  /* No pixel repetition */
> +
> +     /* checksum over the full frame, so that the total sums to zero */
> +     for (i = 0; i < HDMI_AVI_INFOFRAME_SIZE; i++)

checksum is intialized far away. Could do it here insted.

        for (checksum = 0, i = 0; i < HDMI_AVI_INFOFRAME_SIZE; i++)

> +             checksum += buffer[i];
> +     buffer[3] = 0x100 - checksum;
> +
> +     return 0;
> +}
> +
> +static void mtk_hdmi_hw_avi_infoframe(struct mtk_hdmi *hdmi, u8 *buf, u8 len)
> +{
> +     /* Disable AVI InfoFrame first */
> +     mtk_hdmi_mask(hdmi, TOP_INFO_EN, AVI_DIS_WR | AVI_DIS,
> +                   AVI_EN_WR | AVI_EN);
> +     mtk_hdmi_mask(hdmi, TOP_INFO_RPT, AVI_RPT_DIS, AVI_RPT_EN);
> +
> +     /* Write AVI InfoFrame header */
> +     mtk_hdmi_write(hdmi, TOP_AVI_HEADER,
> +                    BYTES_TO_UINT32(0, buf[2], buf[1], buf[0]));
> +
> +     /* Write AVI InfoFrame data packets */
> +     mtk_hdmi_write(hdmi, TOP_AVI_PKT00,
> +                    BYTES_TO_UINT32(buf[6], buf[5], buf[4], buf[3]));
> +
> +     mtk_hdmi_write(hdmi, TOP_AVI_PKT01,
> +                    BYTES_TO_UINT32(0, buf[9], buf[8], buf[7]));
> +
> +     mtk_hdmi_write(hdmi, TOP_AVI_PKT02,
> +                    BYTES_TO_UINT32(buf[13], buf[12], buf[11], buf[10]));
> +
> +     mtk_hdmi_write(hdmi, TOP_AVI_PKT03,
> +                    BYTES_TO_UINT32(0, buf[16], buf[15], buf[14]));
> +
> +     /* Clear remaining packets */
> +     mtk_hdmi_write(hdmi, TOP_AVI_PKT04, 0);
> +     mtk_hdmi_write(hdmi, TOP_AVI_PKT05, 0);
> +
> +     /* Enable AVI InfoFrame */
> +     mtk_hdmi_mask(hdmi, TOP_INFO_RPT, AVI_RPT_EN, AVI_RPT_EN);
> +     mtk_hdmi_mask(hdmi, TOP_INFO_EN, AVI_EN_WR | AVI_EN,
> +                   AVI_EN_WR | AVI_EN);
> +}
> +
> +static void mtk_hdmi_hw_spd_infoframe(struct mtk_hdmi *hdmi, u8 *buf, u8 len)
> +{
> +     /* Disable SPD InfoFrame first */
> +     mtk_hdmi_mask(hdmi, TOP_INFO_EN, SPD_DIS_WR | SPD_DIS,
> +                   SPD_EN_WR | SPD_EN);
> +     mtk_hdmi_mask(hdmi, TOP_INFO_RPT, SPD_RPT_DIS, SPD_RPT_EN);
> +
> +     /* Write SPD InfoFrame header */
> +     mtk_hdmi_write(hdmi, TOP_SPDIF_HEADER,
> +                    BYTES_TO_UINT32(0, buf[2], buf[1], buf[0]));
> +
> +     /* Write SPD InfoFrame data packets */
> +     mtk_hdmi_write(hdmi, TOP_SPDIF_PKT00,
> +                    BYTES_TO_UINT32(buf[6], buf[5], buf[4], buf[3]));
> +
> +     mtk_hdmi_write(hdmi, TOP_SPDIF_PKT01,
> +                    BYTES_TO_UINT32(0, buf[9], buf[8], buf[7]));
> +
> +     mtk_hdmi_write(hdmi, TOP_SPDIF_PKT02,
> +                    BYTES_TO_UINT32(buf[13], buf[12], buf[11], buf[10]));
> +
> +     mtk_hdmi_write(hdmi, TOP_SPDIF_PKT03,
> +                    BYTES_TO_UINT32(0, buf[16], buf[15], buf[14]));
> +
> +     mtk_hdmi_write(hdmi, TOP_SPDIF_PKT04,
> +                    BYTES_TO_UINT32(buf[20], buf[19], buf[18], buf[17]));
> +
> +     mtk_hdmi_write(hdmi, TOP_SPDIF_PKT05,
> +                    BYTES_TO_UINT32(0, buf[23], buf[22], buf[21]));
> +
> +     mtk_hdmi_write(hdmi, TOP_SPDIF_PKT06,
> +                    BYTES_TO_UINT32(buf[27], buf[26], buf[25], buf[24]));
> +
> +     mtk_hdmi_write(hdmi, TOP_SPDIF_PKT07, buf[28]);
> +
> +     /* Enable SPD InfoFrame */
> +     mtk_hdmi_mask(hdmi, TOP_INFO_RPT, SPD_RPT_EN, SPD_RPT_EN);
> +     mtk_hdmi_mask(hdmi, TOP_INFO_EN, SPD_EN_WR | SPD_EN,
> +                   SPD_EN_WR | SPD_EN);
> +}
> +
> +static void mtk_hdmi_setup_infoframes(struct mtk_hdmi *hdmi,
> +                                   struct display_timing *mode)
> +{
> +     u8 buffer_spd[HDMI_SPD_INFOFRAME_SIZE];
> +     u8 buffer_avi[HDMI_AVI_INFOFRAME_SIZE];
> +     int ret;
> +
> +     ret = mtk_hdmi_setup_avi_infoframe(hdmi, buffer_avi,
> +                                        sizeof(buffer_avi), mode);
> +     if (ret) {
> +             dev_warn(hdmi->dev, "Failed to setup AVI infoframe: %d\n", ret);

Why warn instead of err?

> +             return;
> +     }
> +
> +     ret = mtk_hdmi_setup_spd_infoframe(hdmi, buffer_spd,
> +                                        sizeof(buffer_spd),
> +                                        "MediaTek", "On-chip HDMI");
> +     if (ret) {
> +             dev_warn(hdmi->dev, "Failed to setup SPD infoframe: %d\n", ret);
> +             return;
> +     }
> +
> +     /* Send the infoframes to hardware */
> +     mtk_hdmi_hw_avi_infoframe(hdmi, buffer_avi, sizeof(buffer_avi));
> +     mtk_hdmi_hw_spd_infoframe(hdmi, buffer_spd, sizeof(buffer_spd));
> +}
> +
> +static void mtk_hdmi_controller_pre_enable(struct mtk_hdmi *hdmi,
> +                                        struct display_timing *mode)
> +{
> +     mtk_hdmi_convert_colorspace_depth(hdmi);
> +     mtk_hdmi_output_set_display_mode(hdmi, mode);
> +     mtk_hdmi_setup_infoframes(hdmi, mode);
> +}
> +
> +static void mtk_hdmi_controller_enable(struct mtk_hdmi *hdmi)
> +{
> +     generic_phy_power_on(&hdmi->phy);
> +     mtk_hdmi_hw_vid_black(hdmi, false);
> +}
> +
> +static inline void mtk_hdmi_disable_all_int(struct mtk_hdmi *hdmi)
> +{
> +     /* disable all tx irq */
> +     mtk_hdmi_write(hdmi, TOP_INT_MASK00, 0x00000000);
> +     mtk_hdmi_write(hdmi, TOP_INT_MASK01, 0x00000000);

Just 0 is fine.

> +}
> +
> +static int mtk_hdmi_read_edid(struct mtk_hdmi *hdmi, u8 *buf, int buf_size)
> +{
> +     struct udevice *chip;
> +     int ret;
> +
> +     if (!hdmi->ddc_bus || buf_size < EDID_SIZE)
> +             return -EINVAL;
> +
> +     ret = i2c_get_chip(hdmi->ddc_bus, EDID_ADDR, 1, &chip);
> +     if (ret)
> +             return ret;
> +
> +     ret = dm_i2c_read(chip, 0, buf, EDID_SIZE);
> +     if (ret) {
> +             dev_err(hdmi->dev, "failed to read EDID: %d\n", ret);
> +             return ret;
> +     }
> +
> +     /* read the extension block, if any */
> +     if (buf[0x7e] != 0 && buf_size >= EDID_EXT_SIZE) {
> +             ret = dm_i2c_read(chip, EDID_SIZE, buf + EDID_SIZE,
> +                               buf_size - EDID_SIZE);
> +             if (ret)
> +                     dev_warn(hdmi->dev,
> +                              "error reading extended EDID block\n");
> +     }
> +
> +     return 0;
> +}
> +
> +static enum hdmi_hpd_state mtk_hdmi_hpd_pord_status(struct mtk_hdmi *hdmi)
> +{
> +     unsigned int hpd_status;
> +
> +     hpd_status = mtk_hdmi_read(hdmi, HPD_DDC_STATUS);
> +     if ((hpd_status & (HPD_PIN_STA | PORD_PIN_STA)) ==
> +         (HPD_PIN_STA | PORD_PIN_STA))
> +             return HDMI_PLUG_IN_AND_SINK_POWER_ON;
> +     else if ((hpd_status & (HPD_PIN_STA | PORD_PIN_STA)) == HPD_PIN_STA)
> +             return HDMI_PLUG_IN_ONLY;
> +     else
> +             return HDMI_PLUG_OUT;
> +}
> +
> +static int mtk_hdmi_wait_for_hpd(struct mtk_hdmi *hdmi)
> +{
> +     ulong start = get_timer(0);
> +
> +     do {
> +             if (mtk_hdmi_hpd_pord_status(hdmi) ==
> +                 HDMI_PLUG_IN_AND_SINK_POWER_ON)
> +                     return 0;

nit: add blank line here

> +             udelay(100);
> +     } while (get_timer(start) < MTK_HDMI_HPD_TIMEOUT_MS);
> +
> +     return -ETIMEDOUT;
> +}
> +
> +static bool mtk_hdmi_mode_valid(void *priv, const struct display_timing 
> *timing)
> +{
> +     return timing->hactive.typ < MTK_HDMI_MAX_WIDTH &&
> +            timing->vactive.typ < MTK_HDMI_MAX_HEIGHT;
> +}
> +
> +static int mtk_hdmi_get_display_timing(struct mtk_hdmi *hdmi,
> +                                    struct display_timing *timing)
> +{
> +     u8 edid[EDID_EXT_SIZE];
> +     int panel_bits_per_colour;
> +     int ret;
> +
> +     ret = mtk_hdmi_read_edid(hdmi, edid, EDID_EXT_SIZE);
> +     if (ret)
> +             return ret;
> +
> +     ret = edid_get_timing_validate(edid, sizeof(struct edid1_info),
> +                                    timing, &panel_bits_per_colour,
> +                                    mtk_hdmi_mode_valid, NULL);
> +     if (ret)
> +             return ret;
> +
> +     debug("Display timing:\n clock %u Hz\n", timing->pixelclock.typ);
> +     debug(" hactive: %d,\thfront_p: %d,\thback_p: %d hsync:\t%d\n",
> +           timing->hactive.typ, timing->hfront_porch.typ,
> +           timing->hback_porch.typ, timing->hsync_len.typ);
> +     debug(" vactive: %d,\tvfront_p: %d,\tvback_p: %d vsync:\t%d\n",
> +           timing->vactive.typ, timing->vfront_porch.typ,
> +           timing->vback_porch.typ, timing->vsync_len.typ);
> +     debug(" flags: 0x%x\n", timing->flags);
> +
> +     return 0;
> +}
> +
> +static void mtk_hdmi_controller_initialize(struct mtk_hdmi *hdmi,
> +                                        struct display_timing *mode)
> +{
> +     mtk_hdmi_disable_all_int(hdmi);
> +
> +     mtk_hdmi_disable_abist(hdmi);
> +
> +     mtk_hdmi_controller_pre_enable(hdmi, mode);
> +
> +     /* let the new configuration settle before unmuting the output */
> +     mdelay(50);
> +
> +     mtk_hdmi_controller_enable(hdmi);
> +}
> +
> +static void mtk_hdmi_reset_colorspace_setting(struct mtk_hdmi *hdmi)
> +{
> +     hdmi->set_csp_depth = RGB444_8bit;
> +     hdmi->csp = HDMI_COLORSPACE_RGB;
> +     hdmi->color_depth = HDMI_8_BIT;
> +     hdmi->colorimetry = HDMI_COLORIMETRY_NONE;
> +}
> +
> +static int mtk_hdmi_get_component(struct udevice *dev, const char *name,
> +                               struct udevice **compp)
> +{
> +     int ret;
> +
> +     ret = uclass_get_device_by_phandle(UCLASS_MISC, dev, name, compp);
> +     if (ret) {
> +             dev_err(dev, "cannot get %s: %d\n", name, ret);
> +             return ret;
> +     }
> +
> +     return mtk_disp_comp_enable(*compp);
> +}
> +
> +static int mtk_hdmi_probe(struct udevice *dev)
> +{
> +     struct mtk_hdmi *hdmi = dev_get_priv(dev);
> +     struct video_priv *priv = dev_get_uclass_priv(dev);
> +     struct video_uc_plat *plat = dev_get_uclass_plat(dev);
> +     struct ofnode_phandle_args args;
> +     struct display_timing timing;
> +     fdt_size_t fb_region_size;
> +     int ret;
> +
> +     hdmi->dev = dev;
> +
> +     hdmi->regs = dev_read_addr(dev);
> +     if (hdmi->regs == FDT_ADDR_T_NONE)
> +             return -EINVAL;
> +
> +     ret = clk_get_bulk(dev, &hdmi->clk_bulk);
> +     if (ret) {
> +             dev_err(dev, "failed to get clocks: %d\n", ret);
> +             return ret;
> +     }
> +
> +     ret = clk_enable_bulk(&hdmi->clk_bulk);
> +     if (ret) {
> +             dev_err(dev, "failed to enable clocks: %d\n", ret);
> +             return ret;
> +     }
> +
> +     ret = generic_phy_get_by_name(dev, "hdmi", &hdmi->phy);
> +     if (ret) {
> +             dev_err(dev, "failed to get HDMI PHY: %d\n", ret);
> +             return ret;
> +     }
> +
> +     ret = uclass_get_device_by_ofnode(UCLASS_I2C,
> +                                       dev_read_subnode(dev, "i2c"),
> +                                       &hdmi->ddc_bus);
> +     if (ret) {
> +             dev_err(dev, "failed to get DDC I2C bus: %d\n", ret);
> +             return ret;
> +     }
> +
> +     mtk_hdmi_reset_colorspace_setting(hdmi);
> +
> +     ret = mtk_hdmi_wait_for_hpd(hdmi);
> +     if (ret) {
> +             dev_err(dev, "display is not connected\n");
> +             return ret;
> +     }
> +
> +     ret = mtk_hdmi_get_display_timing(hdmi, &timing);
> +     if (ret) {
> +             dev_err(dev, "failed to get display timing from EDID: %d\n",
> +                     ret);
> +             return ret;
> +     }
> +
> +     hdmi->mode = timing;
> +     /* CEA-861: SD modes use ITU-601 colorimetry, HD modes ITU-709 */
> +     hdmi->colorimetry = timing.vactive.typ >= 720 ?
> +                         HDMI_COLORIMETRY_ITU_709 : HDMI_COLORIMETRY_ITU_601;
> +
> +     mtk_hdmi_controller_initialize(hdmi, &timing);
> +
> +     /* Set up video private data based on the selected display timing */
> +     priv->bpix = VIDEO_BPP32;
> +     priv->xsize = timing.hactive.typ;
> +     priv->ysize = timing.vactive.typ;
> +     priv->line_length = priv->xsize * VNBYTES(VIDEO_BPP32);
> +
> +     plat->size = priv->ysize * priv->line_length;
> +
> +     /* the framebuffer lives in a dedicated reserved-memory region */
> +     ret = dev_read_phandle_with_args(dev, "memory-region", NULL, 0, 0,
> +                                      &args);
> +     if (ret) {
> +             dev_err(dev, "no framebuffer memory-region: %d\n", ret);
> +             return ret;
> +     }
> +
> +     plat->base = ofnode_get_addr_size(args.node, "reg", &fb_region_size);
> +     if (plat->base == FDT_ADDR_T_NONE) {
> +             dev_err(dev, "failed to decode framebuffer region\n");
> +             return -EINVAL;
> +     }
> +
> +     if (fb_region_size < plat->size) {
> +             dev_err(dev, "framebuffer region too small: %llu < %u\n",
> +                     (unsigned long long)fb_region_size, plat->size);
> +             return -EINVAL;
> +     }
> +
> +     ret = mtk_hdmi_get_component(dev, "mediatek,dpi1", &hdmi->dpi1);
> +     if (ret)
> +             return ret;

nit: add blank line after all of these return statements.

> +     mtk_dpi_hw_enable(hdmi->dpi1);
> +     mtk_dpi_config(hdmi->dpi1, &timing,
> +                    hdmi->csp == HDMI_COLORSPACE_RGB);
> +
> +     ret = mtk_hdmi_get_component(dev, "mediatek,rdma4", &hdmi->rdma4);
> +     if (ret)
> +             return ret;
> +     mtk_mdp_rdma_config(hdmi->rdma4, plat, &timing, false);
> +
> +     ret = mtk_hdmi_get_component(dev, "mediatek,rdma5", &hdmi->rdma5);
> +     if (ret)
> +             return ret;
> +     mtk_mdp_rdma_config(hdmi->rdma5, plat, &timing, true);
> +
> +     ret = mtk_hdmi_get_component(dev, "mediatek,vdosys1", &hdmi->vdosys1);
> +     if (ret)
> +             return ret;
> +     mtk_vdosys1_configure_hdmi(hdmi->vdosys1);
> +
> +     ret = mtk_hdmi_get_component(dev, "mediatek,merge3", &hdmi->merge3);
> +     if (ret)
> +             return ret;
> +     mtk_disp_merge_config(hdmi->merge3, priv->xsize / 2, priv->ysize,
> +                           priv->xsize / 2, priv->ysize,
> +                           priv->xsize, priv->ysize);
> +
> +     ret = mtk_hdmi_get_component(dev, "mediatek,merge5", &hdmi->merge5);
> +     if (ret)
> +             return ret;
> +     mtk_disp_merge_config(hdmi->merge5, priv->xsize, priv->ysize, 0, 0,
> +                           priv->xsize, priv->ysize);
> +
> +     ret = mtk_hdmi_get_component(dev, "mediatek,mixer", &hdmi->mixer);
> +     if (ret)
> +             return ret;
> +     mtk_disp_mixer_config(hdmi->mixer, priv->xsize, priv->ysize);
> +
> +     ret = mtk_hdmi_get_component(dev, "mediatek,mutex1", &hdmi->mutex);
> +     if (ret)
> +             return ret;
> +     mtk_disp_mutex_config(hdmi->mutex);
> +
> +     ret = mtk_hdmi_get_component(dev, "mediatek,padding4",
> +                                  &hdmi->padding4);
> +     if (ret)
> +             return ret;
> +     mtk_disp_padding_config(hdmi->padding4);
> +
> +     ret = mtk_hdmi_get_component(dev, "mediatek,padding5",
> +                                  &hdmi->padding5);
> +     if (ret)
> +             return ret;
> +     mtk_disp_padding_config(hdmi->padding5);
> +
> +     video_set_flush_dcache(dev, true);
> +
> +     return 0;
> +}
> +
> +static const struct udevice_id mtk_hdmi_ids[] = {
> +     {
> +             .compatible = "mediatek,mt8188-hdmi-tx",
> +     },
> +     { }
> +};
> +
> +U_BOOT_DRIVER(mtk_hdmi) = {
> +     .name           = "mtk_hdmi",
> +     .id             = UCLASS_VIDEO,
> +     .of_match       = mtk_hdmi_ids,
> +     .probe          = mtk_hdmi_probe,
> +     .bind           = dm_scan_fdt_dev,
> +     .priv_auto      = sizeof(struct mtk_hdmi),
> +};
> diff --git a/drivers/video/mediatek/mtk_mt8188_hdmi_regs.h 
> b/drivers/video/mediatek/mtk_mt8188_hdmi_regs.h
> new file mode 100644
> index 00000000000..bcee2d1985d
> --- /dev/null
> +++ b/drivers/video/mediatek/mtk_mt8188_hdmi_regs.h

Does this really need to be a header file if it is only included in
one file? Everything could just be in the .c file directly.

> @@ -0,0 +1,103 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2025 MediaTek Inc.
> + * Copyright (c) 2025 BayLibre, SAS
> + */
> +
> +#ifndef _MTK_MT8188_HDMI_REGS_H
> +#define _MTK_MT8188_HDMI_REGS_H
> +
> +#define AVI_DIS                                      (0)
> +#define AVI_DIS_WR                           (0)
> +#define AVI_EN                                       (0x1)
> +#define AVI_EN_WR                            BIT(16)
> +#define AVI_RPT_DIS                          (0x0)
> +#define AVI_RPT_EN                           (0x1)
> +
> +#define C422_C420_CONFIG_BYPASS                      BIT(5)
> +#define C422_C420_CONFIG_ENABLE                      BIT(4)
> +#define C422_C420_CONFIG_OUT_CB_OR_CR                BIT(6)
> +#define C444_C422_CONFIG_ENABLE                      (0x1)
> +
> +#define DEEPCOLOR_MODE_10BIT                 BIT(8)
> +#define DEEPCOLOR_MODE_12BIT                 GENMASK(9, 8)
> +#define DEEPCOLOR_MODE_16BIT                 GENMASK(10, 8)
> +#define DEEPCOLOR_MODE_8BIT                  (0)
> +#define DEEPCOLOR_MODE_MASKBIT                       GENMASK(10, 8)
> +#define DEEPCOLOR_PAT_EN                     BIT(12)
> +#define DEEP_COLOR_ADD                               BIT(4)
> +
> +#define HDMI2_OFF                            (0)
> +#define HDMI2_ON                             BIT(2)
> +
> +#define HDMITX_SW_HPD                                BIT(29)
> +#define HDMITX_SW_HPD_SHIFT                  (29)
> +#define HDMITX_SW_RSTB                               BIT(31)
> +#define HDMITX_SW_RSTB_SHIFT                 (31)
> +
> +#define HDMI_MODE_DVI                                (0)
> +#define HDMI_MODE_HDMI                               BIT(3)
> +
> +#define HDMI_YUV420_MODE                     BIT(10)
> +#define HDMI_YUV420_MODE_SHIFT                       (10)
> +
> +#define HPD_DDC_STATUS                               0xC60
> +#define PORD_PIN_STA                         BIT(5)
> +#define HPD_PIN_STA                          BIT(4)
> +
> +#define NULL_PKT_EN                          BIT(2)
> +#define NULL_PKT_VSYNC_HIGH_EN                       BIT(3)
> +
> +#define OUTPUT_FORMAT_DEMUX_420_ENABLE               BIT(10)
> +
> +#define REG_VMUTE_EN                         BIT(16)
> +
> +#define SCR_OFF                                      0
> +#define SCR_ON                                       BIT(4)
> +
> +#define SPD_DIS                                      0
> +#define SPD_DIS_WR                           0
> +#define SPD_EN                                       BIT(1)
> +#define SPD_EN_WR                            BIT(17)
> +#define SPD_RPT_DIS                          0
> +#define SPD_RPT_EN                           BIT(1)
> +
> +#define TOP_CFG00                            0x000
> +#define TOP_CFG01                            0x004
> +#define TOP_INFO_EN                          0x01C
> +#define TOP_INFO_RPT                         0x020
> +#define TOP_AVI_HEADER                               0x024
> +#define TOP_AVI_PKT00                                0x028
> +#define TOP_AVI_PKT01                                0x02C
> +#define TOP_AVI_PKT02                                0x030
> +#define TOP_AVI_PKT03                                0x034
> +#define TOP_AVI_PKT04                                0x038
> +#define TOP_AVI_PKT05                                0x03C
> +#define TOP_INT_MASK00                               0x1B0
> +#define TOP_INT_MASK01                               0x1B4
> +#define TOP_MISC_CTLR                                0x1A4
> +#define TOP_SPDIF_HEADER                     0x054
> +#define TOP_SPDIF_PKT00                              0x058
> +#define TOP_SPDIF_PKT01                              0x05C
> +#define TOP_SPDIF_PKT02                              0x060
> +#define TOP_SPDIF_PKT03                              0x064
> +#define TOP_SPDIF_PKT04                              0x068
> +#define TOP_SPDIF_PKT05                              0x06C
> +#define TOP_SPDIF_PKT06                              0x070
> +#define TOP_SPDIF_PKT07                              0x074
> +#define TOP_VMUTE_CFG1                               0x1C8
> +
> +#define VID_DOWNSAMPLE_CONFIG                        0x8F0
> +#define VID_OUT_FORMAT                               0x8FC
> +
> +#define ABIST_ENABLE                         BIT(31)
> +#define ABIST_VIDEO_FORMAT_MASKBIT           (0x3F << 16)

Should this be GENMASK()?

> +#define ABIST_VIDEO_FORMAT_720x480P          (0x2 << 16)
> +#define ABIST_VIDEO_FORMAT_720P50            (0xC << 16)
> +#define ABIST_VIDEO_FORMAT_1080P60           (0xA << 16)
> +#define ABIST_VIDEO_FORMAT_3840x2160P30              (0x19 << 16)

And then use FIELD_PREP/FIELD_GET for these.

> +
> +#define HDCP_TOP_CTRL                                0xC00
> +#define HDMI_CONFIG                          0xEA0
> +
> +#endif /* _MTK_MT8188_HDMI_REGS_H */
> 

Reply via email to