Hi
>-----Original Message-----
>From: Dmitry Baryshkov <[email protected]>
>Sent: Saturday, March 14, 2026 10:09 AM
>To: Hermes Wu (吳佳宏) <[email protected]>
>Cc: Andrzej Hajda <[email protected]>; Neil Armstrong
><[email protected]>; Robert Foss <[email protected]>; Laurent Pinchart
><[email protected]>; Jonas Karlman <[email protected]>; Jernej
>Skrabec <[email protected]>; David Airlie <[email protected]>; Simona
>Vetter <[email protected]>; Maarten Lankhorst
><[email protected]>; Maxime Ripard <[email protected]>;
>Thomas Zimmermann <[email protected]>; Rob Herring <[email protected]>;
>Krzysztof Kozlowski <[email protected]>; Conor Dooley <[email protected]>;
>Pet Weng (翁玉芬) <[email protected]>; Kenneth Hung (洪家倫)
><[email protected]>; [email protected];
>[email protected]; [email protected]
>Subject: Re: [PATCH v3 2/2] drm/bridge: Add ITE IT6162 MIPI DSI to HDMI bridge
>driver
>
>On Fri, Mar 13, 2026 at 02:16:01PM +0800, Hermes Wu via B4 Relay wrote:
>> From: Hermes Wu <[email protected]>
>>
>> Add support for the ITE IT6162 MIPI DSI to HDMI 2.0 bridge chip.
>> The IT6162 is an I2C-controlled bridge that supports the following
>> configurations:
>>
>> - Single MIPI DSI input: up to 4K @ 30Hz
>> - Dual MIPI DSI input (combined): up to 4K @ 60Hz
>>
>> The driver implements the DRM bridge and connector frameworks,
>> including mode setting, EDID retrieval, and HPD support.
>>
>> Also add a MAINTAINERS entry for the newly introduced ITE IT6162 MIPI
>> DSI to HDMI bridge driver, covering the driver source file and the
>> device tree binding document.
>>
>> Signed-off-by: Hermes Wu <[email protected]>
>> ---
>> Changes in v3:
>> * Fix OFFSET_VERSION_H register offset from 0x03 to 0x05
>> * Add MIPI_PORT_EN_MASK macro combining MIPI_PORT1_EN_MASK and
>> MIPI_PORT0_EN_MASK
>> * Rename HDCP enums: NO_HDCP -> HDCP_DISABLE, NO_HDCP_STATE ->
>> HDCP_STATE_IDLE,
>> AUTH_DONE -> HDCP_STATE_AUTH_DONE, AUTH_FAIL -> HDCP_STATE_AUTH_FAIL
>> * Rename it6162_infoblock_complete() to it6162_wait_command_complete()
>> * Rename it6162_infoblock_host_set() to it6162_infoblock_trigger()
>> * Remove it6162_infoblock_mipi_config() and it6162_infoblock_write_msg()
>> wrappers, inline into it6162_reset_init() and
>> it6162_mipi_set_video_timing() respectively
>> * Remove it6162_set_default_config() wrapper, inline into
>> it6162_reset_init()
>> * Fix typo: hdcp_encyption -> hdcp_encryption
>> * Fix typo: it6162_hdcp_read_infomation -> it6162_hdcp_read_information
>> * Remove dev_err_probe() usage outside of probe path
>> * Remove verbose success-path dev_info/dev_dbg logging throughout
>> * Replace __func__ usage in error messages with descriptive strings
>> * Fix double error printing in probe for it6162_init_pdata failure path
>> * Fix uninitialized variable warning: initialize cp_status to
>> DRM_MODE_CONTENT_PROTECTION_DESIRED at declaration; move
>> drm_hdcp_update_content_protection() inside the state-change block
>> * Fix audio sample width mapping: case 20 now maps to WORD_LENGTH_20BIT,
>> case 24 to WORD_LENGTH_24BIT
>> * Remove stray drm_dbg("it6162_bridge_atomic_disable") call
>> * Remove drm_dbg() calls from it6162_display_mode_to_settings()
>> * Drop unused struct it6162 * parameter from it6162_avi_to_video_setting()
>> and it6162_display_mode_to_settings()
>> * Fold it6162_set_default_config() body directly into it6162_reset_init(),
>> removing the wrapper
>> * Fix it6162_infoblock_request_data(): split command complete polling and
>> buffer status check into two steps; use wait_event_timeout() for
>> data_buf_sts since it is updated asynchronously by the interrupt
>> handler; add wait_queue_head_t data_buf_wait to struct it6162 and
>> wake_up() in interrupt handler
>> ---
>> MAINTAINERS | 7 +
>> drivers/gpu/drm/bridge/Kconfig | 17 +
>> drivers/gpu/drm/bridge/Makefile | 1 +
>> drivers/gpu/drm/bridge/ite-it6162.c | 1631
>> +++++++++++++++++++++++++++++++++++
>> 4 files changed, 1656 insertions(+)
>>
>> +
>> +static int it6162_bridge_hdmi_audio_prepare(struct drm_bridge *bridge,
>> + struct drm_connector *connector,
>> + struct hdmi_codec_daifmt *fmt,
>> + struct hdmi_codec_params *params) {
>> + struct it6162 *it6162 = bridge_to_it6162(bridge);
>> + struct it6162_audio config;
>> +
>> + it6162_audio_update_hw_params(it6162, &config, fmt, params);
>> + it6162_enable_audio(it6162, &config);
>
>You write the intermediate structure, use it and then forget it immediately.
>Can it be removed completely?
yes. it will remove in next patch
>> + return
>> drm_atomic_helper_connector_hdmi_update_audio_infoframe(connector,
>> +
>> ¶ms->cea);
>> +}
>> +
>> +static int it6162_bridge_hdmi_audio_startup(struct drm_bridge *bridge,
>> + struct drm_connector *connector) {
>> + return 0;
>> +}
>
>This is not necessary and can be dropped.
>
>> +
>> +static void it6162_bridge_hdmi_audio_shutdown(struct drm_bridge *bridge,
>> + struct drm_connector *connector) {
>> + struct it6162 *it6162 = bridge_to_it6162(bridge);
>
>drm_atomic_helper_connector_hdmi_clear_audio_infoframe() here.
>
>> +
>> + it6162_disable_audio(it6162);
>> +}
>> +
>> +static enum drm_mode_status
>> +it6162_hdmi_tmds_char_rate_valid(const struct drm_bridge *bridge,
>> + const struct drm_display_mode *mode,
>> + unsigned long long tmds_rate)
>> +{
>> + /*IT6162 hdmi supports HDMI2.0 600Mhz*/
>> + if (tmds_rate > 600000000)
>> + return MODE_CLOCK_HIGH;
>> +
>> + return MODE_OK;
>> +}
>> +
>> +static inline int
>> +it6162_write_infoframe(struct it6162 *it6162, const u8 *buffer,
>> +size_t len) {
>> + if (len > DATA_BUFFER_DEPTH)
>> + return -EINVAL;
>> +
>> + regmap_bulk_write(it6162->regmap, OFFSET_DATA_BUFFER, buffer, len);
>> + regmap_write(it6162->regmap, OFFSET_DATA_TYPE_IDX, len);
>> + it6162_infoblock_trigger(it6162, HOST_SET_CEA_INFOFRAME);
>
>Does the hardware automatically identify, which infoframe is it?
>
FW will check infoframe type in Header.
>> + return 0;
>> +}
>> +
>> +static inline int it6162_clear_infoframe(struct it6162 *it6162, u8
>> +type) {
>> + regmap_write(it6162->regmap, OFFSET_DATA_TYPE_IDX, 3);
>> + regmap_write(it6162->regmap, OFFSET_DATA_BUFFER, type);
>> + regmap_write(it6162->regmap, OFFSET_DATA_BUFFER + 1, 0x00);
>> + regmap_write(it6162->regmap, OFFSET_DATA_BUFFER + 2, 0x00);
>> + it6162_infoblock_trigger(it6162, HOST_SET_CEA_INFOFRAME);
>> + return 0;
>> +}
>> +
>> +static int
>> +it6162_bridge_hdmi_write_avi_infoframe(struct drm_bridge *bridge,
>> + const u8 *buffer, size_t len) {
>> + struct it6162 *it6162 = bridge_to_it6162(bridge);
>> +
>> + return it6162_write_infoframe(it6162, buffer, len); }
>> +
>> +static int
>> +it6162_bridge_hdmi_clear_avi_infoframe(struct drm_bridge *bridge) {
>> + struct it6162 *it6162 = bridge_to_it6162(bridge);
>> +
>> + return it6162_clear_infoframe(it6162, HDMI_INFOFRAME_TYPE_AVI); }
>> +
>> +static int
>> +it6162_bridge_hdmi_write_audio_infoframe(struct drm_bridge *bridge,
>> + const u8 *buffer, size_t len)
>> +{
>> + struct it6162 *it6162 = bridge_to_it6162(bridge);
>> +
>> + return it6162_write_infoframe(it6162, buffer, len); }
>> +
>> +static int
>> +it6162_bridge_hdmi_clear_audio_infoframe(struct drm_bridge *bridge) {
>> + struct it6162 *it6162 = bridge_to_it6162(bridge);
>> +
>> + return it6162_clear_infoframe(it6162, HDMI_INFOFRAME_TYPE_AUDIO); }
>> +
>> +static int
>> +it6162_bridge_hdmi_write_spd_infoframe(struct drm_bridge *bridge,
>> + const u8 *buffer, size_t len) {
>> + struct it6162 *it6162 = bridge_to_it6162(bridge);
>> +
>> + return it6162_write_infoframe(it6162, buffer, len); }
>> +
>> +static int
>> +it6162_bridge_hdmi_clear_spd_infoframe(struct drm_bridge *bridge) {
>> + struct it6162 *it6162 = bridge_to_it6162(bridge);
>> +
>> + return it6162_clear_infoframe(it6162, HDMI_INFOFRAME_TYPE_SPD); }
>> +
>> +static const struct drm_bridge_funcs it6162_bridge_funcs = {
>> + .attach = it6162_bridge_attach,
>> + .mode_valid = it6162_bridge_mode_valid,
>> + .detect = it6162_bridge_detect,
>> +
>> + .atomic_enable = it6162_bridge_atomic_enable,
>> + .atomic_disable = it6162_bridge_atomic_disable,
>> + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
>> + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
>> + .atomic_reset = drm_atomic_helper_bridge_reset,
>> + .atomic_check = it6162_bridge_atomic_check,
>> +
>> + .edid_read = it6162_bridge_read_edid,
>> +
>> + .hdmi_clear_avi_infoframe = it6162_bridge_hdmi_clear_avi_infoframe,
>> + .hdmi_write_avi_infoframe = it6162_bridge_hdmi_write_avi_infoframe,
>> + .hdmi_clear_spd_infoframe = it6162_bridge_hdmi_clear_spd_infoframe,
>> + .hdmi_write_spd_infoframe = it6162_bridge_hdmi_write_spd_infoframe,
>> + .hdmi_clear_audio_infoframe = it6162_bridge_hdmi_clear_audio_infoframe,
>> + .hdmi_write_audio_infoframe =
>> +it6162_bridge_hdmi_write_audio_infoframe,
>
>No HDMI Infoframes support? That's really sad.
Is HDMI Infoframe means HDMI-VSIF and HDMI-HF-VSIF?
>
>> +
>> + .hdmi_tmds_char_rate_valid = it6162_hdmi_tmds_char_rate_valid,
>> + .hdmi_audio_prepare = it6162_bridge_hdmi_audio_prepare,
>> + .hdmi_audio_startup = it6162_bridge_hdmi_audio_startup,
>> + .hdmi_audio_shutdown = it6162_bridge_hdmi_audio_shutdown,
>> +};
>> +
>> +static int it6162_probe(struct i2c_client *client) {
>> + struct device *dev = &client->dev;
>> + struct device_node *np = dev->of_node;
>> + struct it6162 *it6162;
>> + int ret;
>> +
>> + it6162 = devm_drm_bridge_alloc(dev, struct it6162, bridge,
>> + &it6162_bridge_funcs);
>> + if (IS_ERR(it6162))
>> + return PTR_ERR(it6162);
>> +
>> + it6162->dev = dev;
>> +
>> + ret = it6162_of_get_dsi_host(it6162);
>> + if (ret < 0)
>> + return ret;
>> +
>> + ret = it6162_i2c_regmap_init(client, it6162);
>> + if (ret != 0)
>> + return ret;
>> +
>> + ret = it6162_init_pdata(it6162);
>> + if (ret)
>> + return ret;
>> +
>> + it6162_config_default(it6162);
>> + it6162_parse_dt(it6162);
>> +
>> + if (it6162_detect_devices(it6162) < 0)
>> + return -ENODEV;
>> +
>> + if (!client->irq) {
>> + dev_err(dev, "Failed to get INTP IRQ");
>> + return -ENODEV;
>> + }
>> +
>> + ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
>> + it6162_int_threaded_handler,
>> + IRQF_TRIGGER_LOW | IRQF_ONESHOT |
>> + IRQF_NO_AUTOEN,
>> + "it6162-intp", it6162);
>> + if (ret)
>> + return ret;
>> +
>> + INIT_DELAYED_WORK(&it6162->hdcp_work, it6162_hdcp_work);
>> + init_waitqueue_head(&it6162->data_buf_wait);
>> +
>> + mutex_init(&it6162->lock);
>> +
>> + it6162->bridge.of_node = np;
>> + it6162->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID |
>> + DRM_BRIDGE_OP_MODES;
>> +
>> + it6162->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
>> +
>> + it6162->bridge.vendor = "ITE";
>> + it6162->bridge.product = "IT6162";
>
>You missed to specify DRM_BRIDGE_OP_HDMI, so all HDMI callbacks will be
>ignored.
>
>> +
>> + if (it6162_of_get_audio(it6162)) {
>> + it6162->bridge.ops |= DRM_BRIDGE_OP_HDMI_AUDIO;
>> + it6162->bridge.hdmi_audio_dev = dev;
>> + it6162->bridge.hdmi_audio_max_i2s_playback_channels = 8;
>> + it6162->bridge.hdmi_audio_dai_port = 2;
>> + }
>> +
>> + devm_drm_bridge_add(dev, &it6162->bridge);
>> +
>> + return it6162_attach_dsi(it6162);
>> +}
>> +
>> +static void it6162_remove(struct i2c_client *client) {
>> + struct it6162 *it6162 = i2c_get_clientdata(client);
>> +
>> + disable_irq(client->irq);
>> + cancel_delayed_work_sync(&it6162->hdcp_work);
>> + mutex_destroy(&it6162->lock);
>> +}
>> +
>> +static const struct it6162_chip_info it6162_chip_info = {
>> + .chip_id = 0x616200,
>> + .version = 0x006500,
>> +};
>> +
>> +static const struct of_device_id it6162_dt_ids[] = {
>> + { .compatible = "ite,it6162", .data = &it6162_chip_info},
>> + { }
>> +};
>> +MODULE_DEVICE_TABLE(of, it6162_dt_ids);
>> +
>> +static const struct i2c_device_id it6162_i2c_ids[] = {
>> + { "it6162", 0 },
>> + { },
>> +};
>> +MODULE_DEVICE_TABLE(i2c, it6162_i2c_ids);
>> +
>> +static struct i2c_driver it6162_driver = {
>> + .driver = {
>> + .name = "it6162",
>> + .of_match_table = it6162_dt_ids,
>> + },
>> + .probe = it6162_probe,
>> + .remove = it6162_remove,
>> + .id_table = it6162_i2c_ids,
>> +};
>> +module_i2c_driver(it6162_driver);
>> +
>> +MODULE_AUTHOR("Pet Weng <[email protected]>");
>> +MODULE_AUTHOR("Hermes Wu <[email protected]>");
>> +MODULE_DESCRIPTION("it6162 MIPI to HDMI driver");
>> +MODULE_LICENSE("GPL");
>>
>> --
>> 2.34.1
>>
>>
>
>--
>With best wishes
>Dmitry
>
BR,
Hermes