Loading drivers/video/msm/mdss/mdss_hdmi_edid.c +66 −20 Original line number Diff line number Diff line Loading @@ -16,6 +16,13 @@ #include "mdss_hdmi_edid.h" #define DBC_START_OFFSET 4 /* * As per CEA-861-E specification 7.5.2, there can be * upto 31 bytes following any tag (data block type). */ #define MAX_DATA_BLOCK_SIZE 31 #define HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd) \ (!((vsd)[8] & BIT(7)) ? 9 : (!((vsd)[8] & BIT(6)) ? 11 : 13)) Loading @@ -32,6 +39,17 @@ #define BUFF_SIZE_3D 128 enum data_block_types { RESERVED, AUDIO_DATA_BLOCK, VIDEO_DATA_BLOCK, VENDOR_SPECIFIC_DATA_BLOCK, SPEAKER_ALLOCATION_DATA_BLOCK, VESA_DTC_DATA_BLOCK, RESERVED2, USE_EXTENDED_TAG }; struct hdmi_edid_sink_data { u32 disp_mode_list[HDMI_VFRMT_MAX]; u32 disp_3d_mode_list[HDMI_VFRMT_MAX]; Loading Loading @@ -526,7 +544,8 @@ static void hdmi_edid_extract_extended_data_blocks( } /* A Tage code of 7 identifies extended data blocks */ etag = hdmi_edid_find_block(in_buf, start_offset, 7, &len); etag = hdmi_edid_find_block(in_buf, start_offset, USE_EXTENDED_TAG, &len); while (etag != NULL) { /* The extended data block should at least be 2 bytes long */ Loading Loading @@ -572,7 +591,8 @@ static void hdmi_edid_extract_extended_data_blocks( /* There could be more that one extended data block */ start_offset = etag - in_buf + len + 1; etag = hdmi_edid_find_block(in_buf, start_offset, 7, &len); etag = hdmi_edid_find_block(in_buf, start_offset, USE_EXTENDED_TAG, &len); } } /* hdmi_edid_extract_extended_data_blocks */ Loading @@ -587,11 +607,12 @@ static void hdmi_edid_extract_3d_present(struct hdmi_edid_ctrl *edid_ctrl, return; } vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3, &len); vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, VENDOR_SPECIFIC_DATA_BLOCK, &len); edid_ctrl->present_3d = 0; if (vsd == NULL || len < 9) { DEV_DBG("%s: blk-id 3 not found or not long enough\n", if (vsd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE) { DEV_DBG("%s: No/Invalid vendor Specific Data Block\n", __func__); return; } Loading @@ -618,9 +639,13 @@ static void hdmi_edid_extract_audio_data_blocks( return; } adb = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 1, &len); if ((adb == NULL) || (len > MAX_AUDIO_DATA_BLOCK_SIZE)) adb = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, AUDIO_DATA_BLOCK, &len); if ((adb == NULL) || (len > MAX_AUDIO_DATA_BLOCK_SIZE)) { DEV_DBG("%s: No/Invalid Audio Data Block\n", __func__); return; } memcpy(edid_ctrl->audio_data_block, adb + 1, len); edid_ctrl->adb_size = len; Loading @@ -646,9 +671,13 @@ static void hdmi_edid_extract_speaker_allocation_data( return; } sadb = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 4, &len); if ((sadb == NULL) || (len != MAX_SPKR_ALLOC_DATA_BLOCK_SIZE)) sadb = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, SPEAKER_ALLOCATION_DATA_BLOCK, &len); if ((sadb == NULL) || (len != MAX_SPKR_ALLOC_DATA_BLOCK_SIZE)) { DEV_DBG("%s: No/Invalid Speaker Allocation Data Block\n", __func__); return; } memcpy(edid_ctrl->spkr_alloc_data_block, sadb + 1, len); edid_ctrl->sadb_size = len; Loading @@ -675,9 +704,11 @@ static void hdmi_edid_extract_latency_fields(struct hdmi_edid_ctrl *edid_ctrl, return; } vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3, &len); vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, VENDOR_SPECIFIC_DATA_BLOCK, &len); if (vsd == NULL || len < 12 || !(vsd[8] & BIT(7))) { if (vsd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE || !(vsd[8] & BIT(7))) { edid_ctrl->video_latency = (u16)-1; edid_ctrl->audio_latency = (u16)-1; DEV_DBG("%s: EDID: No audio/video latency present\n", __func__); Loading @@ -701,9 +732,14 @@ static u32 hdmi_edid_extract_ieee_reg_id(struct hdmi_edid_ctrl *edid_ctrl, return 0; } vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3, &len); if (vsd == NULL || len < 8) vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, VENDOR_SPECIFIC_DATA_BLOCK, &len); if (vsd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE) { DEV_DBG("%s: No/Invalid Vendor Specific Data Block\n", __func__); return 0; } DEV_DBG("%s: EDID: VSD PhyAddr=%04x, MaxTMDS=%dMHz\n", __func__, ((u32)vsd[4] << 8) + (u32)vsd[5], (u32)vsd[7] * 5); Loading Loading @@ -900,11 +936,14 @@ static int hdmi_edid_get_display_vsd_3d_mode(const u8 *data_buf, u16 structure_all, structure_mask; const u8 *vsd = num_of_cea_blocks ? hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET, 3, &len) : NULL; VENDOR_SPECIFIC_DATA_BLOCK, &len) : NULL; int i; if (!vsd) if (vsd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE) { DEV_DBG("%s: No/Invalid Vendor Specific Data Block\n", __func__); return -ENXIO; } offset = HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd); if (offset >= len - 1) Loading Loading @@ -1046,10 +1085,11 @@ static void hdmi_edid_get_extended_video_formats( return; } vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3, &db_len); vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, VENDOR_SPECIFIC_DATA_BLOCK, &db_len); if (vsd == NULL || db_len < 9) { DEV_DBG("%s: blk-id 3 not found or not long enough\n", if (vsd == NULL || db_len == 0 || db_len > MAX_DATA_BLOCK_SIZE) { DEV_DBG("%s: No/Invalid Vendor Specific Data Block\n", __func__); return; } Loading Loading @@ -1099,8 +1139,14 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl, edid_blk0 = &data_buf[0x0]; edid_blk1 = &data_buf[0x80]; svd = num_of_cea_blocks ? hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET, 2, &len) : NULL; hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET, VIDEO_DATA_BLOCK, &len) : NULL; if (svd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE) { DEV_DBG("%s: No/Invalid Video Data Block\n", __func__); return; } sink_data = &edid_ctrl->sink_data; Loading Loading
drivers/video/msm/mdss/mdss_hdmi_edid.c +66 −20 Original line number Diff line number Diff line Loading @@ -16,6 +16,13 @@ #include "mdss_hdmi_edid.h" #define DBC_START_OFFSET 4 /* * As per CEA-861-E specification 7.5.2, there can be * upto 31 bytes following any tag (data block type). */ #define MAX_DATA_BLOCK_SIZE 31 #define HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd) \ (!((vsd)[8] & BIT(7)) ? 9 : (!((vsd)[8] & BIT(6)) ? 11 : 13)) Loading @@ -32,6 +39,17 @@ #define BUFF_SIZE_3D 128 enum data_block_types { RESERVED, AUDIO_DATA_BLOCK, VIDEO_DATA_BLOCK, VENDOR_SPECIFIC_DATA_BLOCK, SPEAKER_ALLOCATION_DATA_BLOCK, VESA_DTC_DATA_BLOCK, RESERVED2, USE_EXTENDED_TAG }; struct hdmi_edid_sink_data { u32 disp_mode_list[HDMI_VFRMT_MAX]; u32 disp_3d_mode_list[HDMI_VFRMT_MAX]; Loading Loading @@ -526,7 +544,8 @@ static void hdmi_edid_extract_extended_data_blocks( } /* A Tage code of 7 identifies extended data blocks */ etag = hdmi_edid_find_block(in_buf, start_offset, 7, &len); etag = hdmi_edid_find_block(in_buf, start_offset, USE_EXTENDED_TAG, &len); while (etag != NULL) { /* The extended data block should at least be 2 bytes long */ Loading Loading @@ -572,7 +591,8 @@ static void hdmi_edid_extract_extended_data_blocks( /* There could be more that one extended data block */ start_offset = etag - in_buf + len + 1; etag = hdmi_edid_find_block(in_buf, start_offset, 7, &len); etag = hdmi_edid_find_block(in_buf, start_offset, USE_EXTENDED_TAG, &len); } } /* hdmi_edid_extract_extended_data_blocks */ Loading @@ -587,11 +607,12 @@ static void hdmi_edid_extract_3d_present(struct hdmi_edid_ctrl *edid_ctrl, return; } vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3, &len); vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, VENDOR_SPECIFIC_DATA_BLOCK, &len); edid_ctrl->present_3d = 0; if (vsd == NULL || len < 9) { DEV_DBG("%s: blk-id 3 not found or not long enough\n", if (vsd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE) { DEV_DBG("%s: No/Invalid vendor Specific Data Block\n", __func__); return; } Loading @@ -618,9 +639,13 @@ static void hdmi_edid_extract_audio_data_blocks( return; } adb = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 1, &len); if ((adb == NULL) || (len > MAX_AUDIO_DATA_BLOCK_SIZE)) adb = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, AUDIO_DATA_BLOCK, &len); if ((adb == NULL) || (len > MAX_AUDIO_DATA_BLOCK_SIZE)) { DEV_DBG("%s: No/Invalid Audio Data Block\n", __func__); return; } memcpy(edid_ctrl->audio_data_block, adb + 1, len); edid_ctrl->adb_size = len; Loading @@ -646,9 +671,13 @@ static void hdmi_edid_extract_speaker_allocation_data( return; } sadb = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 4, &len); if ((sadb == NULL) || (len != MAX_SPKR_ALLOC_DATA_BLOCK_SIZE)) sadb = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, SPEAKER_ALLOCATION_DATA_BLOCK, &len); if ((sadb == NULL) || (len != MAX_SPKR_ALLOC_DATA_BLOCK_SIZE)) { DEV_DBG("%s: No/Invalid Speaker Allocation Data Block\n", __func__); return; } memcpy(edid_ctrl->spkr_alloc_data_block, sadb + 1, len); edid_ctrl->sadb_size = len; Loading @@ -675,9 +704,11 @@ static void hdmi_edid_extract_latency_fields(struct hdmi_edid_ctrl *edid_ctrl, return; } vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3, &len); vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, VENDOR_SPECIFIC_DATA_BLOCK, &len); if (vsd == NULL || len < 12 || !(vsd[8] & BIT(7))) { if (vsd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE || !(vsd[8] & BIT(7))) { edid_ctrl->video_latency = (u16)-1; edid_ctrl->audio_latency = (u16)-1; DEV_DBG("%s: EDID: No audio/video latency present\n", __func__); Loading @@ -701,9 +732,14 @@ static u32 hdmi_edid_extract_ieee_reg_id(struct hdmi_edid_ctrl *edid_ctrl, return 0; } vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3, &len); if (vsd == NULL || len < 8) vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, VENDOR_SPECIFIC_DATA_BLOCK, &len); if (vsd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE) { DEV_DBG("%s: No/Invalid Vendor Specific Data Block\n", __func__); return 0; } DEV_DBG("%s: EDID: VSD PhyAddr=%04x, MaxTMDS=%dMHz\n", __func__, ((u32)vsd[4] << 8) + (u32)vsd[5], (u32)vsd[7] * 5); Loading Loading @@ -900,11 +936,14 @@ static int hdmi_edid_get_display_vsd_3d_mode(const u8 *data_buf, u16 structure_all, structure_mask; const u8 *vsd = num_of_cea_blocks ? hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET, 3, &len) : NULL; VENDOR_SPECIFIC_DATA_BLOCK, &len) : NULL; int i; if (!vsd) if (vsd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE) { DEV_DBG("%s: No/Invalid Vendor Specific Data Block\n", __func__); return -ENXIO; } offset = HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd); if (offset >= len - 1) Loading Loading @@ -1046,10 +1085,11 @@ static void hdmi_edid_get_extended_video_formats( return; } vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3, &db_len); vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, VENDOR_SPECIFIC_DATA_BLOCK, &db_len); if (vsd == NULL || db_len < 9) { DEV_DBG("%s: blk-id 3 not found or not long enough\n", if (vsd == NULL || db_len == 0 || db_len > MAX_DATA_BLOCK_SIZE) { DEV_DBG("%s: No/Invalid Vendor Specific Data Block\n", __func__); return; } Loading Loading @@ -1099,8 +1139,14 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl, edid_blk0 = &data_buf[0x0]; edid_blk1 = &data_buf[0x80]; svd = num_of_cea_blocks ? hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET, 2, &len) : NULL; hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET, VIDEO_DATA_BLOCK, &len) : NULL; if (svd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE) { DEV_DBG("%s: No/Invalid Video Data Block\n", __func__); return; } sink_data = &edid_ctrl->sink_data; Loading