summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2018-10-04 14:58:24 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2018-10-04 14:58:24 -0700
commit5be60e5316af6797dcd31cf08bf11b7e12d8ca08 (patch)
tree15c1d5bad848bdffdc45e8f3cf250176db312809 /drivers
parent6202b64fd2ed5f13c32ac2f54fb6824f1f2f95a5 (diff)
parentde9c641ccfabdd3675513e8b3be59588227d3b8c (diff)
Merge "drm/msm: add checksum for HDR infoframe"
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c15
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.c90
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h1
3 files changed, 105 insertions, 1 deletions
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
index 716c91563cc1..48bddbf0e871 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
@@ -2009,6 +2009,7 @@ struct drm_msm_ext_panel_hdr_metadata *hdr_meta)
u32 const version = 0x01;
u32 const length = 0x1a;
u32 const descriptor_id = 0x00;
+ u8 checksum;
struct hdmi *hdmi;
struct drm_connector *connector;
@@ -2039,7 +2040,19 @@ struct drm_msm_ext_panel_hdr_metadata *hdr_meta)
packet_header = type_code | (version << 8) | (length << 16);
hdmi_write(hdmi, HDMI_GENERIC0_HDR, packet_header);
- packet_payload = (hdr_meta->eotf << 8);
+ /**
+ * Checksum is not a mandatory field for
+ * the HDR infoframe as per CEA-861-3 specification.
+ * However some HDMI sinks still expect a
+ * valid checksum to be included as part of
+ * the infoframe. Hence compute and add
+ * the checksum to improve sink interoperability
+ * for our HDR solution on HDMI.
+ */
+ checksum = sde_hdmi_hdr_set_chksum(hdr_meta);
+
+ packet_payload = (hdr_meta->eotf << 8) | checksum;
+
if (connector->hdr_metadata_type_one) {
packet_payload |= (descriptor_id << 16)
| (HDMI_GET_LSB(hdr_meta->display_primaries_x[0])
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.c
index 5c3b3ec45e76..5600f24bd438 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.c
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.c
@@ -78,6 +78,96 @@ static const char *sde_hdmi_hdr_sname(enum sde_hdmi_hdr_state hdr_state)
}
}
+static u8 sde_hdmi_infoframe_checksum(u8 *ptr, size_t size)
+{
+ u8 csum = 0;
+ size_t i;
+
+ /* compute checksum */
+ for (i = 0; i < size; i++)
+ csum += ptr[i];
+
+ return 256 - csum;
+}
+
+u8 sde_hdmi_hdr_set_chksum(struct drm_msm_ext_panel_hdr_metadata *hdr_meta)
+{
+ u8 *buff;
+ u8 *ptr;
+ u32 length;
+ u32 size;
+ u32 chksum = 0;
+ u32 const type_code = 0x87;
+ u32 const version = 0x01;
+ u32 const descriptor_id = 0x00;
+
+ /* length of metadata is 26 bytes */
+ length = 0x1a;
+ /* add 4 bytes for the header */
+ size = length + HDMI_INFOFRAME_HEADER_SIZE;
+
+ buff = kzalloc(size, GFP_KERNEL);
+
+ if (!buff) {
+ SDE_ERROR("invalid buff\n");
+ goto err_alloc;
+ }
+
+ ptr = buff;
+
+ buff[0] = type_code;
+ buff[1] = version;
+ buff[2] = length;
+ buff[3] = 0;
+ /* start infoframe payload */
+ buff += HDMI_INFOFRAME_HEADER_SIZE;
+
+ buff[0] = hdr_meta->eotf;
+ buff[1] = descriptor_id;
+
+ buff[2] = hdr_meta->display_primaries_x[0] & 0xff;
+ buff[3] = hdr_meta->display_primaries_x[0] >> 8;
+
+ buff[4] = hdr_meta->display_primaries_x[1] & 0xff;
+ buff[5] = hdr_meta->display_primaries_x[1] >> 8;
+
+ buff[6] = hdr_meta->display_primaries_x[2] & 0xff;
+ buff[7] = hdr_meta->display_primaries_x[2] >> 8;
+
+ buff[8] = hdr_meta->display_primaries_y[0] & 0xff;
+ buff[9] = hdr_meta->display_primaries_y[0] >> 8;
+
+ buff[10] = hdr_meta->display_primaries_y[1] & 0xff;
+ buff[11] = hdr_meta->display_primaries_y[1] >> 8;
+
+ buff[12] = hdr_meta->display_primaries_y[2] & 0xff;
+ buff[13] = hdr_meta->display_primaries_y[2] >> 8;
+
+ buff[14] = hdr_meta->white_point_x & 0xff;
+ buff[15] = hdr_meta->white_point_x >> 8;
+ buff[16] = hdr_meta->white_point_y & 0xff;
+ buff[17] = hdr_meta->white_point_y >> 8;
+
+ buff[18] = hdr_meta->max_luminance & 0xff;
+ buff[19] = hdr_meta->max_luminance >> 8;
+
+ buff[20] = hdr_meta->min_luminance & 0xff;
+ buff[21] = hdr_meta->min_luminance >> 8;
+
+ buff[22] = hdr_meta->max_content_light_level & 0xff;
+ buff[23] = hdr_meta->max_content_light_level >> 8;
+
+ buff[24] = hdr_meta->max_average_light_level & 0xff;
+ buff[25] = hdr_meta->max_average_light_level >> 8;
+
+ chksum = sde_hdmi_infoframe_checksum(ptr, size);
+
+ kfree(ptr);
+
+err_alloc:
+ return chksum;
+}
+
/**
* sde_hdmi_dump_regs - utility to dump HDMI regs
* @hdmi_display: Pointer to private display handle
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h
index 8a79c361b718..985d8c3e605c 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h
@@ -201,5 +201,6 @@ u8 sde_hdmi_hdr_get_ops(u8 curr_state,
u8 new_state);
void sde_hdmi_ctrl_reset(struct hdmi *hdmi);
void sde_hdmi_ctrl_cfg(struct hdmi *hdmi, bool power_on);
+u8 sde_hdmi_hdr_set_chksum(struct drm_msm_ext_panel_hdr_metadata *hdr_meta);
#endif /* _SDE_HDMI_UTIL_H_ */