aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/i2c/adv7511.c35
1 files changed, 24 insertions, 11 deletions
diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c
index f20450c8156f..ee618942cb8e 100644
--- a/drivers/media/i2c/adv7511.c
+++ b/drivers/media/i2c/adv7511.c
@@ -965,26 +965,38 @@ static void adv7511_check_monitor_present_status(struct v4l2_subdev *sd)
965 965
966static bool edid_block_verify_crc(uint8_t *edid_block) 966static bool edid_block_verify_crc(uint8_t *edid_block)
967{ 967{
968 int i;
969 uint8_t sum = 0; 968 uint8_t sum = 0;
969 int i;
970 970
971 for (i = 0; i < 128; i++) 971 for (i = 0; i < 128; i++)
972 sum += *(edid_block + i); 972 sum += edid_block[i];
973 return (sum == 0); 973 return sum == 0;
974} 974}
975 975
976static bool edid_segment_verify_crc(struct v4l2_subdev *sd, u32 segment) 976static bool edid_verify_crc(struct v4l2_subdev *sd, u32 segment)
977{ 977{
978 struct adv7511_state *state = get_adv7511_state(sd); 978 struct adv7511_state *state = get_adv7511_state(sd);
979 u32 blocks = state->edid.blocks; 979 u32 blocks = state->edid.blocks;
980 uint8_t *data = state->edid.data; 980 uint8_t *data = state->edid.data;
981 981
982 if (edid_block_verify_crc(&data[segment * 256])) { 982 if (!edid_block_verify_crc(&data[segment * 256]))
983 if ((segment + 1) * 2 <= blocks) 983 return false;
984 return edid_block_verify_crc(&data[segment * 256 + 128]); 984 if ((segment + 1) * 2 <= blocks)
985 return edid_block_verify_crc(&data[segment * 256 + 128]);
986 return true;
987}
988
989static bool edid_verify_header(struct v4l2_subdev *sd, u32 segment)
990{
991 static const u8 hdmi_header[] = {
992 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
993 };
994 struct adv7511_state *state = get_adv7511_state(sd);
995 u8 *data = state->edid.data;
996
997 if (segment != 0)
985 return true; 998 return true;
986 } 999 return !memcmp(data, hdmi_header, sizeof(hdmi_header));
987 return false;
988} 1000}
989 1001
990static bool adv7511_check_edid_status(struct v4l2_subdev *sd) 1002static bool adv7511_check_edid_status(struct v4l2_subdev *sd)
@@ -1013,9 +1025,10 @@ static bool adv7511_check_edid_status(struct v4l2_subdev *sd)
1013 state->edid.blocks = state->edid.data[0x7e] + 1; 1025 state->edid.blocks = state->edid.data[0x7e] + 1;
1014 v4l2_dbg(1, debug, sd, "%s: %d blocks in total\n", __func__, state->edid.blocks); 1026 v4l2_dbg(1, debug, sd, "%s: %d blocks in total\n", __func__, state->edid.blocks);
1015 } 1027 }
1016 if (!edid_segment_verify_crc(sd, segment)) { 1028 if (!edid_verify_crc(sd, segment) ||
1029 !edid_verify_header(sd, segment)) {
1017 /* edid crc error, force reread of edid segment */ 1030 /* edid crc error, force reread of edid segment */
1018 v4l2_dbg(1, debug, sd, "%s: edid crc error\n", __func__); 1031 v4l2_err(sd, "%s: edid crc or header error\n", __func__);
1019 state->have_monitor = false; 1032 state->have_monitor = false;
1020 adv7511_s_power(sd, false); 1033 adv7511_s_power(sd, false);
1021 adv7511_s_power(sd, true); 1034 adv7511_s_power(sd, true);