mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 02:21:52 +09:00
drm/bridge: synopsys: dw-hdmi-qp: Support DOVI HDR
Change-Id: I72279ebf4d55b1aa53ca12bb8995881af3f0defd Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user