diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2018-10-04 14:58:24 -0700 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2018-10-04 14:58:24 -0700 |
commit | 5be60e5316af6797dcd31cf08bf11b7e12d8ca08 (patch) | |
tree | 15c1d5bad848bdffdc45e8f3cf250176db312809 /drivers | |
parent | 6202b64fd2ed5f13c32ac2f54fb6824f1f2f95a5 (diff) | |
parent | de9c641ccfabdd3675513e8b3be59588227d3b8c (diff) |
Merge "drm/msm: add checksum for HDR infoframe"
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.c | 90 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h | 1 |
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_ */ |