diff options
| -rw-r--r-- | drivers/media/i2c/adv7511.c | 35 |
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 | ||
| 966 | static bool edid_block_verify_crc(uint8_t *edid_block) | 966 | static 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 | ||
| 976 | static bool edid_segment_verify_crc(struct v4l2_subdev *sd, u32 segment) | 976 | static 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 | |||
| 989 | static 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 | ||
| 990 | static bool adv7511_check_edid_status(struct v4l2_subdev *sd) | 1002 | static 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); |
