Loading drivers/video/fbdev/msm/mdss_hdmi_edid.c +115 −0 Original line number Diff line number Diff line Loading @@ -67,6 +67,13 @@ enum edid_sink_mode { SINK_MODE_HDMI }; enum luminance_value { NO_LUMINANCE_DATA = 3, MAXIMUM_LUMINANCE = 4, FRAME_AVERAGE_LUMINANCE = 5, MINIMUM_LUMINANCE = 6 }; enum data_block_types { RESERVED, AUDIO_DATA_BLOCK, Loading @@ -82,6 +89,7 @@ enum extended_data_block_types { VIDEO_CAPABILITY_DATA_BLOCK = 0x0, VENDOR_SPECIFIC_VIDEO_DATA_BLOCK = 0x01, HDMI_VIDEO_DATA_BLOCK = 0x04, HDR_STATIC_METADATA_DATA_BLOCK = 0x06, Y420_VIDEO_DATA_BLOCK = 0x0E, VIDEO_FORMAT_PREFERENCE_DATA_BLOCK = 0x0D, Y420_CAPABILITY_MAP_DATA_BLOCK = 0x0F, Loading Loading @@ -143,11 +151,13 @@ struct hdmi_edid_ctrl { char vendor_id[EDID_VENDOR_ID_SIZE]; bool keep_resv_timings; bool edid_override; bool hdr_supported; struct hdmi_edid_sink_data sink_data; struct hdmi_edid_init_data init_data; struct hdmi_edid_sink_caps sink_caps; struct hdmi_edid_override_data override_data; struct hdmi_edid_hdr_data hdr_data; }; static bool hdmi_edid_is_mode_supported(struct hdmi_edid_ctrl *edid_ctrl, Loading Loading @@ -203,6 +213,14 @@ static int hdmi_edid_reset_parser(struct hdmi_edid_ctrl *edid_ctrl) if (!edid_ctrl->keep_resv_timings) hdmi_reset_resv_timing_info(); /* reset HDR related data */ edid_ctrl->hdr_supported = false; edid_ctrl->hdr_data.eotf = 0; edid_ctrl->hdr_data.descriptor = 0; edid_ctrl->hdr_data.max_luminance = 0; edid_ctrl->hdr_data.avg_luminance = 0; edid_ctrl->hdr_data.min_luminance = 0; return 0; } Loading Loading @@ -762,6 +780,30 @@ err: } static DEVICE_ATTR(add_res, S_IWUSR, NULL, hdmi_edid_sysfs_wta_add_resolution); static ssize_t hdmi_edid_sysfs_rda_hdr_data(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t ret; struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev); if (!edid_ctrl) { DEV_ERR("%s: invalid input\n", __func__); return -EINVAL; } ret = scnprintf(buf, PAGE_SIZE, "%d, %u, %u, %u, %u, %u\n", edid_ctrl->hdr_supported, edid_ctrl->hdr_data.eotf, edid_ctrl->hdr_data.descriptor, edid_ctrl->hdr_data.max_luminance, edid_ctrl->hdr_data.avg_luminance, edid_ctrl->hdr_data.min_luminance); DEV_DBG("%s: '%s'\n", __func__, buf); return ret; } static DEVICE_ATTR(hdr_data, S_IRUGO, hdmi_edid_sysfs_rda_hdr_data, NULL); static struct attribute *hdmi_edid_fs_attrs[] = { &dev_attr_edid_modes.attr, &dev_attr_pa.attr, Loading @@ -775,6 +817,7 @@ static struct attribute *hdmi_edid_fs_attrs[] = { &dev_attr_res_info.attr, &dev_attr_res_info_data.attr, &dev_attr_add_res.attr, &dev_attr_hdr_data.attr, NULL, }; Loading Loading @@ -899,6 +942,47 @@ static void hdmi_edid_parse_Y420VDB(struct hdmi_edid_ctrl *edid_ctrl, } } static bool hdmi_edid_is_luminance_value_present(u32 block_length, enum luminance_value value) { return block_length > NO_LUMINANCE_DATA && value <= block_length; } static void hdmi_edid_parse_hdrdb(struct hdmi_edid_ctrl *edid_ctrl, const u8 *data_block) { u8 len = 0; if (!edid_ctrl || !data_block) { pr_err("%s: invalid input\n", __func__); return; } /* Byte 1: Length of Data Block */ len = data_block[0] & 0x1F; /* Byte 3: Electro-Optical Transfer Functions */ edid_ctrl->hdr_data.eotf = data_block[2] & 0x3F; /* Byte 4: Static Metadata Descriptors */ edid_ctrl->hdr_data.descriptor = data_block[3] & 0x1; /* Byte 5: Desired Content Maximum Luminance */ if (hdmi_edid_is_luminance_value_present(len, MAXIMUM_LUMINANCE)) edid_ctrl->hdr_data.max_luminance = data_block[MAXIMUM_LUMINANCE]; /* Byte 6: Desired Content Max Frame-average Luminance */ if (hdmi_edid_is_luminance_value_present(len, FRAME_AVERAGE_LUMINANCE)) edid_ctrl->hdr_data.avg_luminance = data_block[FRAME_AVERAGE_LUMINANCE]; /* Byte 7: Desired Content Min Luminance */ if (hdmi_edid_is_luminance_value_present(len, MINIMUM_LUMINANCE)) edid_ctrl->hdr_data.min_luminance = data_block[MINIMUM_LUMINANCE]; } static void hdmi_edid_parse_Y420CMDB(struct hdmi_edid_ctrl *edid_ctrl, const u8 *in_buf) { Loading Loading @@ -1045,6 +1129,12 @@ static void hdmi_edid_extract_extended_data_blocks( __func__, etag[2]); hdmi_edid_parse_Y420VDB(edid_ctrl, etag); break; case HDR_STATIC_METADATA_DATA_BLOCK: DEV_DBG("%s found HDR Static Metadata. Byte 3 = 0x%x", __func__, etag[2]); hdmi_edid_parse_hdrdb(edid_ctrl, etag); edid_ctrl->hdr_supported = true; break; default: DEV_DBG("%s: Tag Code %d not supported\n", __func__, etag[1]); Loading Loading @@ -2355,6 +2445,31 @@ u8 hdmi_edid_get_deep_color(void *input) return edid_ctrl->deep_color; } /** * hdmi_edid_get_hdr_data() - get the HDR capabiliies of the sink * @input: edid parser data * * This API returns HDR info associated with the sink: * electro-optical transfer function, static metadata descriptor, * desired content max luminance data, desired content max * frame-average luminance data, and desired content min luminance * data. * * Return: HDR data. */ void hdmi_edid_get_hdr_data(void *input, struct hdmi_edid_hdr_data *hdr_data) { struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input; if (!edid_ctrl || !hdr_data) { DEV_ERR("%s: invalid input\n", __func__); return; } hdr_data = &edid_ctrl->hdr_data; } bool hdmi_edid_is_s3d_mode_supported(void *input, u32 video_mode, u32 s3d_mode) { int i; Loading drivers/video/fbdev/msm/mdss_hdmi_edid.h +18 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,22 @@ struct hdmi_edid_init_data { u32 buf_size; }; /* * struct hdmi_edid_hdr_data - HDR Static Metadata * @eotf: Electro-Optical Transfer Function * @descriptor: Static Metadata Descriptor * @max_luminance: Desired Content Maximum Luminance * @avg_luminance: Desired Content Frame-average Luminance * @min_luminance: Desired Content Minimum Luminance */ struct hdmi_edid_hdr_data { u32 eotf; u32 descriptor; u32 max_luminance; u32 avg_luminance; u32 min_luminance; }; int hdmi_edid_parser(void *edid_ctrl); u32 hdmi_edid_get_raw_data(void *edid_ctrl, u8 *buf, u32 size); u8 hdmi_edid_get_sink_scaninfo(void *edid_ctrl, u32 resolution); Loading @@ -44,5 +60,7 @@ void *hdmi_edid_init(struct hdmi_edid_init_data *init_data); bool hdmi_edid_is_s3d_mode_supported(void *input, u32 video_mode, u32 s3d_mode); u8 hdmi_edid_get_deep_color(void *edid_ctrl); void hdmi_edid_get_hdr_data(void *edid_ctrl, struct hdmi_edid_hdr_data *hdr_data); #endif /* __HDMI_EDID_H__ */ Loading
drivers/video/fbdev/msm/mdss_hdmi_edid.c +115 −0 Original line number Diff line number Diff line Loading @@ -67,6 +67,13 @@ enum edid_sink_mode { SINK_MODE_HDMI }; enum luminance_value { NO_LUMINANCE_DATA = 3, MAXIMUM_LUMINANCE = 4, FRAME_AVERAGE_LUMINANCE = 5, MINIMUM_LUMINANCE = 6 }; enum data_block_types { RESERVED, AUDIO_DATA_BLOCK, Loading @@ -82,6 +89,7 @@ enum extended_data_block_types { VIDEO_CAPABILITY_DATA_BLOCK = 0x0, VENDOR_SPECIFIC_VIDEO_DATA_BLOCK = 0x01, HDMI_VIDEO_DATA_BLOCK = 0x04, HDR_STATIC_METADATA_DATA_BLOCK = 0x06, Y420_VIDEO_DATA_BLOCK = 0x0E, VIDEO_FORMAT_PREFERENCE_DATA_BLOCK = 0x0D, Y420_CAPABILITY_MAP_DATA_BLOCK = 0x0F, Loading Loading @@ -143,11 +151,13 @@ struct hdmi_edid_ctrl { char vendor_id[EDID_VENDOR_ID_SIZE]; bool keep_resv_timings; bool edid_override; bool hdr_supported; struct hdmi_edid_sink_data sink_data; struct hdmi_edid_init_data init_data; struct hdmi_edid_sink_caps sink_caps; struct hdmi_edid_override_data override_data; struct hdmi_edid_hdr_data hdr_data; }; static bool hdmi_edid_is_mode_supported(struct hdmi_edid_ctrl *edid_ctrl, Loading Loading @@ -203,6 +213,14 @@ static int hdmi_edid_reset_parser(struct hdmi_edid_ctrl *edid_ctrl) if (!edid_ctrl->keep_resv_timings) hdmi_reset_resv_timing_info(); /* reset HDR related data */ edid_ctrl->hdr_supported = false; edid_ctrl->hdr_data.eotf = 0; edid_ctrl->hdr_data.descriptor = 0; edid_ctrl->hdr_data.max_luminance = 0; edid_ctrl->hdr_data.avg_luminance = 0; edid_ctrl->hdr_data.min_luminance = 0; return 0; } Loading Loading @@ -762,6 +780,30 @@ err: } static DEVICE_ATTR(add_res, S_IWUSR, NULL, hdmi_edid_sysfs_wta_add_resolution); static ssize_t hdmi_edid_sysfs_rda_hdr_data(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t ret; struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev); if (!edid_ctrl) { DEV_ERR("%s: invalid input\n", __func__); return -EINVAL; } ret = scnprintf(buf, PAGE_SIZE, "%d, %u, %u, %u, %u, %u\n", edid_ctrl->hdr_supported, edid_ctrl->hdr_data.eotf, edid_ctrl->hdr_data.descriptor, edid_ctrl->hdr_data.max_luminance, edid_ctrl->hdr_data.avg_luminance, edid_ctrl->hdr_data.min_luminance); DEV_DBG("%s: '%s'\n", __func__, buf); return ret; } static DEVICE_ATTR(hdr_data, S_IRUGO, hdmi_edid_sysfs_rda_hdr_data, NULL); static struct attribute *hdmi_edid_fs_attrs[] = { &dev_attr_edid_modes.attr, &dev_attr_pa.attr, Loading @@ -775,6 +817,7 @@ static struct attribute *hdmi_edid_fs_attrs[] = { &dev_attr_res_info.attr, &dev_attr_res_info_data.attr, &dev_attr_add_res.attr, &dev_attr_hdr_data.attr, NULL, }; Loading Loading @@ -899,6 +942,47 @@ static void hdmi_edid_parse_Y420VDB(struct hdmi_edid_ctrl *edid_ctrl, } } static bool hdmi_edid_is_luminance_value_present(u32 block_length, enum luminance_value value) { return block_length > NO_LUMINANCE_DATA && value <= block_length; } static void hdmi_edid_parse_hdrdb(struct hdmi_edid_ctrl *edid_ctrl, const u8 *data_block) { u8 len = 0; if (!edid_ctrl || !data_block) { pr_err("%s: invalid input\n", __func__); return; } /* Byte 1: Length of Data Block */ len = data_block[0] & 0x1F; /* Byte 3: Electro-Optical Transfer Functions */ edid_ctrl->hdr_data.eotf = data_block[2] & 0x3F; /* Byte 4: Static Metadata Descriptors */ edid_ctrl->hdr_data.descriptor = data_block[3] & 0x1; /* Byte 5: Desired Content Maximum Luminance */ if (hdmi_edid_is_luminance_value_present(len, MAXIMUM_LUMINANCE)) edid_ctrl->hdr_data.max_luminance = data_block[MAXIMUM_LUMINANCE]; /* Byte 6: Desired Content Max Frame-average Luminance */ if (hdmi_edid_is_luminance_value_present(len, FRAME_AVERAGE_LUMINANCE)) edid_ctrl->hdr_data.avg_luminance = data_block[FRAME_AVERAGE_LUMINANCE]; /* Byte 7: Desired Content Min Luminance */ if (hdmi_edid_is_luminance_value_present(len, MINIMUM_LUMINANCE)) edid_ctrl->hdr_data.min_luminance = data_block[MINIMUM_LUMINANCE]; } static void hdmi_edid_parse_Y420CMDB(struct hdmi_edid_ctrl *edid_ctrl, const u8 *in_buf) { Loading Loading @@ -1045,6 +1129,12 @@ static void hdmi_edid_extract_extended_data_blocks( __func__, etag[2]); hdmi_edid_parse_Y420VDB(edid_ctrl, etag); break; case HDR_STATIC_METADATA_DATA_BLOCK: DEV_DBG("%s found HDR Static Metadata. Byte 3 = 0x%x", __func__, etag[2]); hdmi_edid_parse_hdrdb(edid_ctrl, etag); edid_ctrl->hdr_supported = true; break; default: DEV_DBG("%s: Tag Code %d not supported\n", __func__, etag[1]); Loading Loading @@ -2355,6 +2445,31 @@ u8 hdmi_edid_get_deep_color(void *input) return edid_ctrl->deep_color; } /** * hdmi_edid_get_hdr_data() - get the HDR capabiliies of the sink * @input: edid parser data * * This API returns HDR info associated with the sink: * electro-optical transfer function, static metadata descriptor, * desired content max luminance data, desired content max * frame-average luminance data, and desired content min luminance * data. * * Return: HDR data. */ void hdmi_edid_get_hdr_data(void *input, struct hdmi_edid_hdr_data *hdr_data) { struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input; if (!edid_ctrl || !hdr_data) { DEV_ERR("%s: invalid input\n", __func__); return; } hdr_data = &edid_ctrl->hdr_data; } bool hdmi_edid_is_s3d_mode_supported(void *input, u32 video_mode, u32 s3d_mode) { int i; Loading
drivers/video/fbdev/msm/mdss_hdmi_edid.h +18 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,22 @@ struct hdmi_edid_init_data { u32 buf_size; }; /* * struct hdmi_edid_hdr_data - HDR Static Metadata * @eotf: Electro-Optical Transfer Function * @descriptor: Static Metadata Descriptor * @max_luminance: Desired Content Maximum Luminance * @avg_luminance: Desired Content Frame-average Luminance * @min_luminance: Desired Content Minimum Luminance */ struct hdmi_edid_hdr_data { u32 eotf; u32 descriptor; u32 max_luminance; u32 avg_luminance; u32 min_luminance; }; int hdmi_edid_parser(void *edid_ctrl); u32 hdmi_edid_get_raw_data(void *edid_ctrl, u8 *buf, u32 size); u8 hdmi_edid_get_sink_scaninfo(void *edid_ctrl, u32 resolution); Loading @@ -44,5 +60,7 @@ void *hdmi_edid_init(struct hdmi_edid_init_data *init_data); bool hdmi_edid_is_s3d_mode_supported(void *input, u32 video_mode, u32 s3d_mode); u8 hdmi_edid_get_deep_color(void *edid_ctrl); void hdmi_edid_get_hdr_data(void *edid_ctrl, struct hdmi_edid_hdr_data *hdr_data); #endif /* __HDMI_EDID_H__ */