From 0cb3359e28e136f76db7a6c2f131d489127e7db2 Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Mon, 23 Dec 2024 15:19:11 +0800 Subject: [PATCH] drm/bridge: synopsys: dw-hdmi-qp: Support DOVI HDR Change-Id: I72279ebf4d55b1aa53ca12bb8995881af3f0defd Signed-off-by: Algea Cao --- drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 42 ++++- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 144 +++++++++++++--- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 169 ++----------------- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 4 +- include/drm/bridge/dw_hdmi.h | 9 + 5 files changed, 187 insertions(+), 181 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c index a98aa4fb6cb2..36ba988e288a 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c @@ -276,6 +276,7 @@ struct dw_hdmi_qp { u8 edid[HDMI_EDID_LEN]; u8 vendor_info[VENDOR_INFO_LEN]; + u32 dovi_vsif[DOVI_VSIF_LEN]; struct { const struct dw_hdmi_qp_phy_ops *ops; @@ -1583,10 +1584,18 @@ static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi_qp *hdmi, struct dw_hdmi_link_config *link_cfg = NULL; void *data = hdmi->plat_data->phy_data; + hdmi_modb(hdmi, 0, PKTSCHED_VSI_TX_EN, PKTSCHED_PKT_EN); + + if (hdmi->dovi_vsif[0]) { + for (i = 0; i < 8; i++) + hdmi_writel(hdmi, hdmi->dovi_vsif[i], PKT_VSI_CONTENTS0 + i * 4); + + goto out; + } + if (hdmi->plat_data->get_link_cfg) link_cfg = hdmi->plat_data->get_link_cfg(data); - hdmi_modb(hdmi, 0, PKTSCHED_VSI_TX_EN, PKTSCHED_PKT_EN); for (i = 0; i <= 7; i++) hdmi_writel(hdmi, 0, PKT_VSI_CONTENTS0 + i * 4); @@ -1652,6 +1661,7 @@ static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi_qp *hdmi, hdmi_writel(hdmi, 0, PKT_VSI_CONTENTS7); +out: hdmi_modb(hdmi, 0, PKTSCHED_VSI_FIELDRATE, PKTSCHED_PKT_CONFIG1); hdmi_modb(hdmi, PKTSCHED_VSI_TX_EN, PKTSCHED_VSI_TX_EN, PKTSCHED_PKT_EN); @@ -2754,6 +2764,8 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector) hdmi->plat_data->get_edid_dsc_info(data, edid); memcpy(hdmi->vendor_info, &raw_edid[8], VENDOR_INFO_LEN); ret = drm_edid_connector_update(connector, drm_edid); + if (hdmi->plat_data->get_dovi_data) + hdmi->plat_data->get_dovi_data(data, edid, connector); if (hdmi->plat_data->get_colorimetry) hdmi->plat_data->get_colorimetry(data, edid); if (hdmi->plat_data->get_yuv422_format) @@ -3089,6 +3101,27 @@ static void set_dw_hdmi_hdcp_enable(struct dw_hdmi_qp *hdmi, } } +static bool dovi_vsif_equal(struct dw_hdmi_qp *hdmi) +{ + void *data = hdmi->plat_data->phy_data; + int ret; + u32 vsif[DOVI_VSIF_LEN] = {0}; + + if (!hdmi->plat_data->get_dovi_vsif) + return true; + + hdmi->plat_data->get_dovi_vsif(data, vsif); + + ret = memcmp(hdmi->dovi_vsif, vsif, DOVI_VSIF_LEN * 4); + + if (ret) { + memcpy(hdmi->dovi_vsif, vsif, DOVI_VSIF_LEN * 4); + return false; + } else { + return true; + } +} + static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, struct drm_atomic_state *state) { @@ -3251,8 +3284,12 @@ static void dw_hdmi_connector_atomic_commit(struct drm_connector *connector, hdmi->update = false; } - if (!hdmi->disabled) + if (!hdmi->disabled) { set_dw_hdmi_hdcp_enable(hdmi, connector, state); + if (!dovi_vsif_equal(hdmi)) + hdmi_config_vendor_specific_infoframe(hdmi, hdmi->curr_conn, + &hdmi->previous_mode); + } } void dw_hdmi_qp_set_quant_range(struct dw_hdmi_qp *hdmi) @@ -3483,6 +3520,7 @@ static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge, } hdmi->curr_conn = NULL; + hdmi->update = false; mutex_unlock(&hdmi->mutex); cancel_work_sync(&hdmi->flt_work); diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index a3c76f8d28f1..410606328d3e 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -251,7 +251,7 @@ enum mode_color_caps_mask { struct mode_color_caps { struct drm_mode_modeinfo umode; - u8 color_caps; + u64 color_caps; }; struct rockchip_hdmi { @@ -305,17 +305,19 @@ struct rockchip_hdmi { struct drm_property *outputmode_capacity; struct drm_property *quant_range; struct drm_property *hdr_panel_metadata_property; - struct drm_property *next_hdr_sink_data_property; struct drm_property *output_hdmi_dvi; struct drm_property *output_type_capacity; struct drm_property *allm_capacity; struct drm_property *allm_enable; struct drm_property *hdcp_state_property; struct drm_property *mode_color_capacity; + struct drm_property *hdr_panel_dovi_vsdb; + struct drm_property *vsif_data; - struct drm_property_blob *hdr_panel_blob_ptr; - struct drm_property_blob *next_hdr_data_ptr; struct drm_property_blob *mode_color_caps_ptr; + struct drm_property_blob *hdr_panel_blob_ptr; + struct drm_property_blob *hdr_panel_dovi_vsdb_ptr; + struct drm_property_blob *vsif_data_ptr; unsigned int colordepth; unsigned int colorimetry; @@ -331,8 +333,8 @@ struct rockchip_hdmi { u8 add_func; u8 edid_colorimetry; u8 hdcp_status; + u8 dovi_vsdb[DOVI_VSDB_LEN]; struct rockchip_drm_dsc_cap dsc_cap; - struct next_hdr_sink_data next_hdr_data; struct dw_hdmi_link_config link_cfg; struct gpio_desc *enable_gpio; @@ -1011,7 +1013,7 @@ static void hdmi_select_link_config(struct rockchip_hdmi *hdmi, hdmi->link_cfg.add_func = hdmi->add_func; if (!max_frl_rate || (tmdsclk < HDMI20_MAX_RATE && mode.clock < HDMI20_MAX_RATE)) { - dev_info(hdmi->dev, "use tmds mode\n"); + dev_dbg(hdmi->dev, "use tmds mode\n"); hdmi->link_cfg.frl_mode = false; return; } @@ -2866,26 +2868,25 @@ dw_hdmi_rockchip_get_edid_dsc_info(void *data, const struct edid *edid) } static int -dw_hdmi_rockchip_get_next_hdr_data(void *data, struct edid *edid, - struct drm_connector *connector) +dw_hdmi_rockchip_get_dovi_data(void *data, const struct edid *edid, + struct drm_connector *connector) { int ret; struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; - struct next_hdr_sink_data *sink_data = &hdmi->next_hdr_data; - size_t size = sizeof(*sink_data); - struct drm_property *property = hdmi->next_hdr_sink_data_property; - struct drm_property_blob *blob = hdmi->hdr_panel_blob_ptr; + u8 *sink_data = hdmi->dovi_vsdb; + struct drm_property *property = hdmi->hdr_panel_dovi_vsdb; - if (!edid) - return -EINVAL; + if (!edid || !connector) + return -ENOMEM; - rockchip_drm_parse_next_hdr(sink_data, edid); + rockchip_drm_parse_dovi(sink_data, edid); - ret = drm_property_replace_global_blob(connector->dev, &blob, size, sink_data, - &connector->base, property); + ret = drm_property_replace_global_blob(connector->dev, &hdmi->hdr_panel_dovi_vsdb_ptr, + DOVI_VSDB_LEN, sink_data, &connector->base, + property); return ret; -}; +} static int dw_hdmi_rockchip_get_colorimetry(void *data, const struct edid *edid) { @@ -2894,6 +2895,29 @@ static int dw_hdmi_rockchip_get_colorimetry(void *data, const struct edid *edid) return rockchip_drm_parse_colorimetry_data_block(&hdmi->edid_colorimetry, edid); } +static void dw_hdmi_rockchip_get_vsif_data(void *data, u32 *buf) +{ + struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; + struct dovi_vsif_data *vsif; + u8 vsif_db[32] = {0}; + int i; + + if (!buf) + return; + + if (!hdmi->vsif_data_ptr) + return; + + vsif = (struct dovi_vsif_data *)hdmi->vsif_data_ptr->data; + + for (i = 0; i < 3; i++) + vsif_db[i] = vsif->header[i]; + for (i = 0; i < 28; i++) + vsif_db[i + 4] = vsif->pb[i]; + + memcpy(buf, vsif_db, DOVI_VSIF_LEN * 4); +} + static struct dw_hdmi_link_config *dw_hdmi_rockchip_get_link_cfg(void *data) { @@ -3085,7 +3109,7 @@ static void dw_hdmi_rockchip_force_frl_rate(void *data, u8 rate) static u8 mode_color_caps_init(struct drm_connector *connector, struct drm_display_mode *mode, struct drm_display_info *info) { - u8 color_caps_mask = RGB_8BIT; + u8 color_caps_mask = BIT(RGB_8BIT); if (info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30) color_caps_mask |= BIT(RGB_10BIT); @@ -3214,6 +3238,40 @@ static const struct drm_prop_enum_list allm_enable_list[] = { { 1, "enable" }, }; +static int +hdmi_atomic_replace_property_blob_from_id(struct drm_device *dev, + struct drm_property_blob **blob, + uint64_t blob_id, + ssize_t expected_size, + ssize_t expected_elem_size, + bool *replaced) +{ + struct drm_property_blob *new_blob = NULL; + + if (blob_id != 0) { + new_blob = drm_property_lookup_blob(dev, blob_id); + if (!new_blob) + goto out; + + if (expected_size > 0 && + new_blob->length != expected_size) { + drm_property_blob_put(new_blob); + return -EINVAL; + } + if (expected_elem_size > 0 && + new_blob->length % expected_elem_size != 0) { + drm_property_blob_put(new_blob); + return -EINVAL; + } + } + +out: + *replaced |= drm_property_replace_blob(blob, new_blob); + drm_property_blob_put(new_blob); + + return 0; +} + static void dw_hdmi_rockchip_attach_properties(struct drm_connector *connector, unsigned int color, int version, @@ -3297,9 +3355,9 @@ dw_hdmi_rockchip_attach_properties(struct drm_connector *connector, prop = drm_property_create(connector->dev, DRM_MODE_PROP_BLOB | DRM_MODE_PROP_IMMUTABLE, - "NEXT_HDR_SINK_DATA", 0); + "HDR_PANEL_DOVI_VSDB", 0); if (prop) { - hdmi->next_hdr_sink_data_property = prop; + hdmi->hdr_panel_dovi_vsdb = prop; drm_object_attach_property(&connector->base, prop, 0); } @@ -3331,6 +3389,12 @@ dw_hdmi_rockchip_attach_properties(struct drm_connector *connector, drm_object_attach_property(&connector->base, prop, 0); } + prop = drm_property_create(connector->dev, DRM_MODE_PROP_BLOB, "VSIF_DATA", 0); + if (prop) { + hdmi->vsif_data = prop; + drm_object_attach_property(&connector->base, hdmi->vsif_data, 0); + } + prop = drm_property_create_enum(connector->dev, 0, "output_type_capacity", output_type_cap_list, @@ -3423,10 +3487,10 @@ dw_hdmi_rockchip_destroy_properties(struct drm_connector *connector, hdmi->hdr_panel_metadata_property = NULL; } - if (hdmi->next_hdr_sink_data_property) { + if (hdmi->hdr_panel_dovi_vsdb) { drm_property_destroy(connector->dev, - hdmi->next_hdr_sink_data_property); - hdmi->next_hdr_sink_data_property = NULL; + hdmi->hdr_panel_dovi_vsdb); + hdmi->hdr_panel_dovi_vsdb = NULL; } if (hdmi->output_hdmi_dvi) { @@ -3458,6 +3522,16 @@ dw_hdmi_rockchip_destroy_properties(struct drm_connector *connector, drm_property_destroy(connector->dev, hdmi->mode_color_capacity); hdmi->mode_color_capacity = NULL; } + + if (hdmi->hdr_panel_dovi_vsdb) { + drm_property_destroy(connector->dev, hdmi->hdr_panel_dovi_vsdb); + hdmi->hdr_panel_dovi_vsdb = NULL; + } + + if (hdmi->vsif_data) { + drm_property_destroy(connector->dev, hdmi->vsif_data); + hdmi->vsif_data = NULL; + } } static int @@ -3528,6 +3602,16 @@ dw_hdmi_rockchip_set_property(struct drm_connector *connector, return 0; } else if (property == hdmi->mode_color_capacity) { return 0; + } else if (property == hdmi->hdr_panel_dovi_vsdb) { + return 0; + } else if (property == hdmi->vsif_data) { + int ret; + bool replaced = false; + + ret = hdmi_atomic_replace_property_blob_from_id(connector->dev, + &hdmi->vsif_data_ptr, + val, -1, -1, &replaced); + return ret; } DRM_ERROR("Unknown property [PROP:%d:%s]\n", @@ -3614,6 +3698,12 @@ dw_hdmi_rockchip_get_property(struct drm_connector *connector, } else if (property == hdmi->mode_color_capacity) { *val = hdmi->mode_color_caps_ptr ? hdmi->mode_color_caps_ptr->base.id : 0; return 0; + } else if (property == hdmi->hdr_panel_dovi_vsdb) { + *val = (hdmi->hdr_panel_dovi_vsdb_ptr) ? hdmi->hdr_panel_dovi_vsdb_ptr->base.id : 0; + return 0; + } else if (property == hdmi->vsif_data) { + *val = (hdmi->vsif_data_ptr) ? hdmi->vsif_data_ptr->base.id : 0; + return 0; } DRM_ERROR("Unknown property [PROP:%d:%s]\n", @@ -4307,10 +4397,12 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, dw_hdmi_rockchip_get_yuv422_format; plat_data->get_edid_dsc_info = dw_hdmi_rockchip_get_edid_dsc_info; - plat_data->get_next_hdr_data = - dw_hdmi_rockchip_get_next_hdr_data; + plat_data->get_dovi_data = + dw_hdmi_rockchip_get_dovi_data; plat_data->get_colorimetry = dw_hdmi_rockchip_get_colorimetry; + plat_data->get_dovi_vsif = + dw_hdmi_rockchip_get_vsif_data; plat_data->get_link_cfg = dw_hdmi_rockchip_get_link_cfg; plat_data->set_hdcp2_enable = rockchip_set_hdcp2_enable; plat_data->set_hdcp_status = rockchip_set_hdcp_status; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 8bd9319f44d5..5a46e47e3877 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -580,9 +580,9 @@ cea_db_payload_len(const u8 *db) (i) < (end) && (i) + cea_db_payload_len(&(cea)[(i)]) < (end); \ (i) += cea_db_payload_len(&(cea)[(i)]) + 1) -#define HDMI_NEXT_HDR_VSDB_OUI 0xd04601 +#define HDMI_DOVI_VSDB_OUI 0xd04601 -static bool cea_db_is_hdmi_next_hdr_block(const u8 *db) +static bool cea_db_is_hdmi_dovi_block(const u8 *db) { unsigned int oui; @@ -593,8 +593,7 @@ static bool cea_db_is_hdmi_next_hdr_block(const u8 *db) return false; oui = db[3] << 16 | db[2] << 8 | db[1]; - - return oui == HDMI_NEXT_HDR_VSDB_OUI; + return oui == HDMI_DOVI_VSDB_OUI; } static bool cea_db_is_hdmi_forum_vsdb(const u8 *db) @@ -1009,150 +1008,16 @@ static void parse_hdmi_forum_scds(struct rockchip_drm_dsc_cap *dsc_cap, } } -enum { - VER_26_BYTE_V0, - VER_15_BYTE_V1, - VER_12_BYTE_V1, - VER_12_BYTE_V2, -}; - -static int check_next_hdr_version(const u8 *next_hdr_db) -{ - u16 ver; - - ver = (next_hdr_db[5] & 0xf0) << 8 | next_hdr_db[0]; - - switch (ver) { - case 0x00f9: - return VER_26_BYTE_V0; - case 0x20ee: - return VER_15_BYTE_V1; - case 0x20eb: - return VER_12_BYTE_V1; - case 0x40eb: - return VER_12_BYTE_V2; - default: - return -ENOENT; - } -} - -static void parse_ver_26_v0_data(struct ver_26_v0 *hdr, const u8 *data) -{ - hdr->yuv422_12bit = data[5] & BIT(0); - hdr->support_2160p_60 = (data[5] & BIT(1)) >> 1; - hdr->global_dimming = (data[5] & BIT(2)) >> 2; - - hdr->dm_major_ver = (data[21] & 0xf0) >> 4; - hdr->dm_minor_ver = data[21] & 0xf; - - hdr->t_min_pq = (data[19] << 4) | ((data[18] & 0xf0) >> 4); - hdr->t_max_pq = (data[20] << 4) | (data[18] & 0xf); - - hdr->rx = (data[7] << 4) | ((data[6] & 0xf0) >> 4); - hdr->ry = (data[8] << 4) | (data[6] & 0xf); - hdr->gx = (data[10] << 4) | ((data[9] & 0xf0) >> 4); - hdr->gy = (data[11] << 4) | (data[9] & 0xf); - hdr->bx = (data[13] << 4) | ((data[12] & 0xf0) >> 4); - hdr->by = (data[14] << 4) | (data[12] & 0xf); - hdr->wx = (data[16] << 4) | ((data[15] & 0xf0) >> 4); - hdr->wy = (data[17] << 4) | (data[15] & 0xf); -} - -static void parse_ver_15_v1_data(struct ver_15_v1 *hdr, const u8 *data) -{ - hdr->yuv422_12bit = data[5] & BIT(0); - hdr->support_2160p_60 = (data[5] & BIT(1)) >> 1; - hdr->global_dimming = data[6] & BIT(0); - - hdr->dm_version = (data[5] & 0x1c) >> 2; - - hdr->colorimetry = data[7] & BIT(0); - - hdr->t_max_lum = (data[6] & 0xfe) >> 1; - hdr->t_min_lum = (data[7] & 0xfe) >> 1; - - hdr->rx = data[9]; - hdr->ry = data[10]; - hdr->gx = data[11]; - hdr->gy = data[12]; - hdr->bx = data[13]; - hdr->by = data[14]; -} - -static void parse_ver_12_v1_data(struct ver_12_v1 *hdr, const u8 *data) -{ - hdr->yuv422_12bit = data[5] & BIT(0); - hdr->support_2160p_60 = (data[5] & BIT(1)) >> 1; - hdr->global_dimming = data[6] & BIT(0); - - hdr->dm_version = (data[5] & 0x1c) >> 2; - - hdr->colorimetry = data[7] & BIT(0); - - hdr->t_max_lum = (data[6] & 0xfe) >> 1; - hdr->t_min_lum = (data[7] & 0xfe) >> 1; - - hdr->low_latency = data[8] & 0x3; - - hdr->unique_rx = (data[11] & 0xf8) >> 3; - hdr->unique_ry = (data[11] & 0x7) << 2 | (data[10] & BIT(0)) << 1 | - (data[9] & BIT(0)); - hdr->unique_gx = (data[9] & 0xfe) >> 1; - hdr->unique_gy = (data[10] & 0xfe) >> 1; - hdr->unique_bx = (data[8] & 0xe0) >> 5; - hdr->unique_by = (data[8] & 0x1c) >> 2; -} - -static void parse_ver_12_v2_data(struct ver_12_v2 *hdr, const u8 *data) -{ - hdr->yuv422_12bit = data[5] & BIT(0); - hdr->backlt_ctrl = (data[5] & BIT(1)) >> 1; - hdr->global_dimming = (data[6] & BIT(2)) >> 2; - - hdr->dm_version = (data[5] & 0x1c) >> 2; - hdr->backlt_min_luma = data[6] & 0x3; - hdr->interface = data[7] & 0x3; - hdr->yuv444_10b_12b = (data[8] & BIT(0)) << 1 | (data[9] & BIT(0)); - - hdr->t_min_pq_v2 = (data[6] & 0xf8) >> 3; - hdr->t_max_pq_v2 = (data[7] & 0xf8) >> 3; - - hdr->unique_rx = (data[10] & 0xf8) >> 3; - hdr->unique_ry = (data[11] & 0xf8) >> 3; - hdr->unique_gx = (data[8] & 0xfe) >> 1; - hdr->unique_gy = (data[9] & 0xfe) >> 1; - hdr->unique_bx = data[10] & 0x7; - hdr->unique_by = data[11] & 0x7; -} - static -void parse_next_hdr_block(struct next_hdr_sink_data *sink_data, - const u8 *next_hdr_db) +int parse_dovi_block(u8 *sink_data, const u8 *dovi_db) { - int version; + u8 length = (dovi_db[0] & 0x1f) + 1; - version = check_next_hdr_version(next_hdr_db); - if (version < 0) - return; + if (length > DOVI_VSDB_LEN) + return -EINVAL; - sink_data->version = version; - - switch (version) { - case VER_26_BYTE_V0: - parse_ver_26_v0_data(&sink_data->ver_26_v0, next_hdr_db); - break; - case VER_15_BYTE_V1: - parse_ver_15_v1_data(&sink_data->ver_15_v1, next_hdr_db); - break; - case VER_12_BYTE_V1: - parse_ver_12_v1_data(&sink_data->ver_12_v1, next_hdr_db); - break; - case VER_12_BYTE_V2: - parse_ver_12_v2_data(&sink_data->ver_12_v2, next_hdr_db); - break; - default: - break; - } + memcpy(sink_data, dovi_db, length); + return 0; } int rockchip_drm_parse_cea_ext(struct rockchip_drm_dsc_cap *dsc_cap, @@ -1187,16 +1052,15 @@ int rockchip_drm_parse_cea_ext(struct rockchip_drm_dsc_cap *dsc_cap, } EXPORT_SYMBOL(rockchip_drm_parse_cea_ext); -int rockchip_drm_parse_next_hdr(struct next_hdr_sink_data *sink_data, - const struct edid *edid) +int rockchip_drm_parse_dovi(u8 *sink_data, const struct edid *edid) { const u8 *edid_ext; - int i, start, end; + int i, start, end, ret; if (!sink_data || !edid) return -EINVAL; - memset(sink_data, 0, sizeof(struct next_hdr_sink_data)); + memset(sink_data, 0, DOVI_VSDB_LEN); edid_ext = find_cea_extension(edid); if (!edid_ext) @@ -1208,13 +1072,16 @@ int rockchip_drm_parse_next_hdr(struct next_hdr_sink_data *sink_data, for_each_cea_db(edid_ext, i, start, end) { const u8 *db = &edid_ext[i]; - if (cea_db_is_hdmi_next_hdr_block(db)) - parse_next_hdr_block(sink_data, db); + if (cea_db_is_hdmi_dovi_block(db)) { + ret = parse_dovi_block(sink_data, db); + if (ret) + return ret; + } } return 0; } -EXPORT_SYMBOL(rockchip_drm_parse_next_hdr); +EXPORT_SYMBOL(rockchip_drm_parse_dovi); #define COLORIMETRY_DATA_BLOCK 0x5 #define USE_EXTENDED_TAG 0x07 diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 9eef4e6b4ca8..c28e84f7a2b1 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -74,6 +74,7 @@ struct iommu_domain; #define HDMI_EOTF_HDR10PLUS 0x10 #define HDMI_EOTF_HDRVIVID 0x11 #define HDMI_EOTF_DOVI 0x12 +#define DOVI_VSDB_LEN 26 enum rockchip_drm_debug_category { VOP_DEBUG_PLANE = BIT(0), @@ -661,8 +662,7 @@ int rockchip_drm_get_yuv422_format(struct drm_connector *connector, int rockchip_drm_parse_cea_ext(struct rockchip_drm_dsc_cap *dsc_cap, u8 *max_frl_rate_per_lane, u8 *max_lanes, u8 *add_func, const struct edid *edid); -int rockchip_drm_parse_next_hdr(struct next_hdr_sink_data *sink_data, - const struct edid *edid); +int rockchip_drm_parse_dovi(u8 *sink_data, const struct edid *edid); int rockchip_drm_parse_colorimetry_data_block(u8 *colorimetry, const struct edid *edid); struct dma_buf *rockchip_drm_gem_prime_export(struct drm_gem_object *obj, int flags); long rockchip_drm_dclk_round_rate(u32 version, struct clk *dclk, unsigned long rate); diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index 1a4a93ded628..d02952ceafeb 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -80,6 +80,7 @@ struct platform_device; */ #define SUPPORT_HDMI_ALLM BIT(1) +#define DOVI_VSIF_LEN 8 enum { DW_HDMI_RES_8, @@ -142,6 +143,11 @@ struct dw_hdmi_link_config { u8 pps_payload[128]; }; +struct dovi_vsif_data { + u8 header[3]; + u8 pb[28]; +}; + struct dw_hdmi_phy_ops { int (*init)(struct dw_hdmi *hdmi, void *data, const struct drm_display_info *display, @@ -254,6 +260,9 @@ struct dw_hdmi_plat_data { int (*get_edid_dsc_info)(void *data, const struct edid *edid); int (*get_next_hdr_data)(void *data, struct edid *edid, struct drm_connector *connector); + int (*get_dovi_data)(void *data, const struct edid *edid, + struct drm_connector *connector); + void (*get_dovi_vsif)(void *data, u32 *buf); struct dw_hdmi_link_config *(*get_link_cfg)(void *data); void (*set_hdcp_status)(void *data, u8 status); void (*set_hdcp2_enable)(void *data, bool enable);