drm/rockchip: dw_hdmi: Support get hdr10 plus vsdb

Add drm property HDR10_PLUS_VSDB that hdr10 plus data
in edid:

struct hdr10_plus_vsdb {
	u8 application_version;
	u8 full_frame_peak_luminance_index;
	u8 peak_luminance_index;
};

Change-Id: I464cb67e0d9784df905bf34fd8472f80a6b98296
Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
This commit is contained in:
Algea Cao
2024-11-20 14:35:30 +08:00
committed by Tao Huang
parent 734aea1cce
commit ff7af21e33
5 changed files with 104 additions and 0 deletions

View File

@@ -2770,6 +2770,8 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
hdmi->plat_data->get_colorimetry(data, edid);
if (hdmi->plat_data->get_yuv422_format)
hdmi->plat_data->get_yuv422_format(connector, edid);
if (hdmi->plat_data->get_hdr10_plus_vsdb)
hdmi->plat_data->get_hdr10_plus_vsdb(data, edid, connector);
dw_hdmi_update_hdr_property(connector);
if (ret > 0 && hdmi->plat_data->split_mode) {
struct dw_hdmi_qp *secondary = NULL;

View File

@@ -314,11 +314,13 @@ struct rockchip_hdmi {
struct drm_property *mode_color_capacity;
struct drm_property *hdr_panel_dovi_vsdb;
struct drm_property *vsif_data;
struct drm_property *hdr10_plus_vsdb;
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;
struct drm_property_blob *hdr10_plus_vsdb_ptr;
unsigned int colordepth;
unsigned int colorimetry;
@@ -335,6 +337,7 @@ struct rockchip_hdmi {
u8 edid_colorimetry;
u8 hdcp_status;
u8 dovi_vsdb[DOVI_VSDB_LEN];
struct hdr10_plus_vsdb hdr10_plus_data;
struct rockchip_drm_dsc_cap dsc_cap;
struct dw_hdmi_link_config link_cfg;
struct gpio_desc *enable_gpio;
@@ -2867,6 +2870,31 @@ dw_hdmi_rockchip_get_edid_dsc_info(void *data, const struct edid *edid)
&hdmi->max_lanes, &hdmi->add_func, edid);
}
static int
dw_hdmi_rockchip_get_hdr10_plus_vsdb(void *data, const struct edid *edid,
struct drm_connector *connector)
{
int ret;
struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
struct drm_property *property = hdmi->hdr10_plus_vsdb;
u8 hdr10_plus;
if (!edid || !connector)
return -ENOMEM;
hdr10_plus = rockchip_drm_parse_hdr10_plus_vsdb(edid);
hdmi->hdr10_plus_data.application_version = hdr10_plus & 0x3;
hdmi->hdr10_plus_data.full_frame_peak_luminance_index = hdr10_plus & 0xc;
hdmi->hdr10_plus_data.peak_luminance_index = hdr10_plus & 0xf0;
ret = drm_property_replace_global_blob(connector->dev, &hdmi->hdr10_plus_vsdb_ptr,
3, &hdmi->hdr10_plus_data, &connector->base,
property);
return ret;
}
static int
dw_hdmi_rockchip_get_dovi_data(void *data, const struct edid *edid,
struct drm_connector *connector)
@@ -3418,6 +3446,15 @@ dw_hdmi_rockchip_attach_properties(struct drm_connector *connector,
drm_object_attach_property(&connector->base, prop, 0);
}
hdmi->enable_allm = allm_en;
prop = drm_property_create(connector->dev,
DRM_MODE_PROP_BLOB |
DRM_MODE_PROP_IMMUTABLE,
"HDR10_PLUS_VSDB", 0);
if (prop) {
hdmi->hdr10_plus_vsdb = prop;
drm_object_attach_property(&connector->base, prop, 0);
}
}
prop = drm_property_create_enum(connector->dev, 0,
@@ -3572,6 +3609,11 @@ dw_hdmi_rockchip_destroy_properties(struct drm_connector *connector,
drm_property_destroy(connector->dev, hdmi->vsif_data);
hdmi->vsif_data = NULL;
}
if (hdmi->hdr10_plus_vsdb) {
drm_property_destroy(connector->dev, hdmi->hdr10_plus_vsdb);
hdmi->hdr10_plus_vsdb = NULL;
}
}
static int
@@ -3652,6 +3694,8 @@ dw_hdmi_rockchip_set_property(struct drm_connector *connector,
&hdmi->vsif_data_ptr,
val, -1, -1, &replaced);
return ret;
} else if (property == hdmi->hdr10_plus_vsdb) {
return 0;
}
DRM_ERROR("Unknown property [PROP:%d:%s]\n",
@@ -3744,6 +3788,9 @@ dw_hdmi_rockchip_get_property(struct drm_connector *connector,
} else if (property == hdmi->vsif_data) {
*val = (hdmi->vsif_data_ptr) ? hdmi->vsif_data_ptr->base.id : 0;
return 0;
} else if (property == hdmi->hdr10_plus_vsdb) {
*val = (hdmi->hdr10_plus_vsdb_ptr) ? hdmi->hdr10_plus_vsdb_ptr->base.id : 0;
return 0;
}
DRM_ERROR("Unknown property [PROP:%d:%s]\n",
@@ -4445,6 +4492,8 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
dw_hdmi_rockchip_get_colorimetry;
plat_data->get_dovi_vsif =
dw_hdmi_rockchip_get_vsif_data;
plat_data->get_hdr10_plus_vsdb =
dw_hdmi_rockchip_get_hdr10_plus_vsdb;
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;

View File

@@ -1179,6 +1179,50 @@ rockchip_drm_parse_colorimetry_data_block(u8 *colorimetry, const struct edid *ed
}
EXPORT_SYMBOL(rockchip_drm_parse_colorimetry_data_block);
#define HDR10_PLUS_OUI 0x90848b
static bool cea_db_is_hdr10_plus_block(const u8 *db)
{
unsigned int oui;
if (cea_db_tag(db) != CTA_DB_EXTENDED_TAG)
return false;
if (cea_db_payload_len(db) < 5)
return false;
oui = db[4] << 16 | db[3] << 8 | db[2];
return oui == HDR10_PLUS_OUI;
}
u8 rockchip_drm_parse_hdr10_plus_vsdb(const struct edid *edid)
{
const u8 *edid_ext;
int i, start, end;
u8 hdr10_plus = 0;
if (!edid)
return 0;
edid_ext = find_cea_extension(edid);
if (!edid_ext)
return 0;
if (cea_db_offsets(edid_ext, &start, &end))
return 0;
for_each_cea_db(edid_ext, i, start, end) {
const u8 *db = &edid_ext[i];
if (cea_db_is_hdr10_plus_block(db))
/* As per CEA 861-G spec */
hdr10_plus = db[5];
}
return hdr10_plus;
}
EXPORT_SYMBOL(rockchip_drm_parse_hdr10_plus_vsdb);
/*
* Attach a (component) device to the shared drm dma mapping from master drm
* device. This is used by the VOPs to map GEM buffers to a common DMA

View File

@@ -669,6 +669,7 @@ int rockchip_drm_parse_cea_ext(struct rockchip_drm_dsc_cap *dsc_cap,
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);
u8 rockchip_drm_parse_hdr10_plus_vsdb(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);
int rockchip_drm_dclk_set_rate(u32 version, struct clk *dclk, unsigned long rate);

View File

@@ -148,6 +148,12 @@ struct dovi_vsif_data {
u8 pb[28];
};
struct hdr10_plus_vsdb {
u8 application_version;
u8 full_frame_peak_luminance_index;
u8 peak_luminance_index;
};
struct dw_hdmi_phy_ops {
int (*init)(struct dw_hdmi *hdmi, void *data,
const struct drm_display_info *display,
@@ -286,6 +292,8 @@ struct dw_hdmi_plat_data {
void *data);
void (*crtc_pre_disable)(void *data, struct drm_crtc *crtc);
void (*crtc_post_enable)(void *data, struct drm_crtc *crtc);
int (*get_hdr10_plus_vsdb)(void *data, const struct edid *edid,
struct drm_connector *connector);
/* Vendor Property support */
const struct dw_hdmi_property_ops *property_ops;