| /****************************************************************************** |
| * |
| * Copyright (C) 2015-2016 Cadence Design Systems, Inc. |
| * All rights reserved worldwide. |
| * |
| * Copyright 2017-2018 NXP |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * 3. Neither the name of the copyright holder nor the names of its contributors |
| * may be used to endorse or promote products derived from this software without |
| * specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
| * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", |
| * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED |
| * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE |
| * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
| * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE |
| * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| * |
| ****************************************************************************** |
| * |
| * edid_parser.c |
| * |
| ****************************************************************************** |
| */ |
| |
| #include "edid_parser.h" |
| |
| static EDID_PARSER_RESULT edid_parse_dtd(S_DTD_DATA *descriptor, |
| unsigned char *raw_data) |
| { |
| unsigned int raw_data_index = 0; |
| |
| descriptor->header.type = DESCRIPTOR_TYPE_DTD; |
| descriptor->header.tag = 0; |
| |
| descriptor->pixel_clock = raw_data[raw_data_index]; |
| descriptor->pixel_clock += |
| (unsigned short)raw_data[raw_data_index + 1] << 8; |
| |
| descriptor->horizontal_addressable_video = raw_data[raw_data_index + 2]; |
| descriptor->horizontal_addressable_video += |
| ((unsigned short)raw_data[raw_data_index + 4] & 0xF0) << 4; |
| descriptor->horizontal_blanking = raw_data[raw_data_index + 3]; |
| descriptor->horizontal_blanking += |
| ((unsigned short)raw_data[raw_data_index + 4] & 0x0F) << 8; |
| |
| descriptor->vertical_addressable_video = raw_data[raw_data_index + 5]; |
| descriptor->vertical_addressable_video += |
| ((unsigned short)raw_data[raw_data_index + 7] & 0xF0) << 4; |
| descriptor->vertical_blanking = raw_data[raw_data_index + 6]; |
| descriptor->vertical_blanking += |
| ((unsigned short)raw_data[raw_data_index + 7] & 0x0F) << 8; |
| |
| descriptor->horizontal_front_porch = raw_data[raw_data_index + 8]; |
| descriptor->horizontal_front_porch += |
| ((unsigned short)raw_data[raw_data_index + 11] & 0xC0) << 2; |
| descriptor->horizontal_sync_pulse_width = raw_data[raw_data_index + 9]; |
| descriptor->horizontal_sync_pulse_width += |
| ((unsigned short)raw_data[raw_data_index + 11] & 0x30) << 4; |
| |
| descriptor->vertical_front_porch = |
| (raw_data[raw_data_index + 10] & 0xF0) >> 4; |
| descriptor->vertical_front_porch += |
| (raw_data[raw_data_index + 11] & 0x0C) << 2; |
| descriptor->vertical_sync_pulse_width = |
| raw_data[raw_data_index + 10] & 0x0F; |
| descriptor->vertical_sync_pulse_width += |
| (raw_data[raw_data_index + 11] & 0x03) << 4; |
| |
| descriptor->horizontal_addressable_video_image_size = |
| raw_data[raw_data_index + 12]; |
| descriptor->horizontal_addressable_video_image_size += |
| ((unsigned short)raw_data[raw_data_index + 14] & 0xF0) << 4; |
| descriptor->vertical_addressable_video_image_size = |
| raw_data[raw_data_index + 13]; |
| descriptor->vertical_addressable_video_image_size += |
| ((unsigned short)raw_data[raw_data_index + 14] & 0x0F) << 8; |
| |
| descriptor->horizontal_border = raw_data[raw_data_index + 15]; |
| descriptor->vertical_border = raw_data[raw_data_index + 16]; |
| |
| descriptor->signal_features = raw_data[raw_data_index + 17]; |
| |
| return EDID_PARSER_SUCCESS; |
| } |
| |
| static EDID_PARSER_RESULT edid_parse_serial_number(S_SERIAL_NUMBER_DATA * |
| descriptor, |
| unsigned char *raw_data) |
| { |
| unsigned int raw_data_index = 0; |
| descriptor->header.type = DESCRIPTOR_TYPE_SERIAL_NUMBER; |
| descriptor->header.tag = 0xFF; |
| |
| int idx; |
| for (idx = 0; idx < 13; idx++) |
| descriptor->serial_number[idx] = |
| raw_data[raw_data_index + 5 + idx]; |
| |
| return EDID_PARSER_SUCCESS; |
| } |
| |
| static EDID_PARSER_RESULT edid_parse_data_string(S_DATA_STRING_DATA * |
| descriptor, |
| unsigned char *raw_data) |
| { |
| unsigned int raw_data_index = 0; |
| descriptor->header.type = DESCRIPTOR_TYPE_DATA_STRING; |
| descriptor->header.tag = 0xFE; |
| int idx; |
| for (idx = 0; idx < 13; idx++) |
| descriptor->data_string[idx] = |
| raw_data[raw_data_index + 5 + idx]; |
| |
| return EDID_PARSER_SUCCESS; |
| } |
| |
| static EDID_PARSER_RESULT edid_parse_range_limits(S_RANGE_LIMITS_DATA * |
| descriptor, |
| unsigned char *raw_data) |
| { |
| unsigned int raw_data_index = 0; |
| |
| descriptor->header.type = DESCRIPTOR_TYPE_RANGE_LIMITS; |
| descriptor->header.tag = 0xFD; |
| |
| descriptor->offset_flags = raw_data[raw_data_index + 4]; |
| descriptor->min_vertical_rate = raw_data[raw_data_index + 5]; |
| descriptor->max_vertical_rate = raw_data[raw_data_index + 6]; |
| descriptor->min_horizontal_rate = raw_data[raw_data_index + 7]; |
| descriptor->max_horizontal_rate = raw_data[raw_data_index + 8]; |
| descriptor->max_pixel_clock = raw_data[raw_data_index + 9]; |
| |
| switch (raw_data[raw_data_index + 10]) { |
| case 0x00: |
| descriptor->type = VIDEO_TIMING_DEFAULT_GTF; |
| break; |
| case 0x01: |
| descriptor->type = VIDEO_TIMING_RANGE_LIMITS_ONLY; |
| break; |
| case 0x02: |
| descriptor->type = VIDEO_TIMING_SECONDARY_GTF; |
| S_RANGE_LIMITS_VIDEO_TIMING_SECONDARY_GTF *timing_type_gtf = |
| (S_RANGE_LIMITS_VIDEO_TIMING_SECONDARY_GTF *) |
| descriptor->suport_flags; |
| timing_type_gtf->start_break_frequency = |
| raw_data[raw_data_index + 12]; |
| timing_type_gtf->c = raw_data[raw_data_index + 13]; |
| timing_type_gtf->m = raw_data[raw_data_index + 14]; |
| timing_type_gtf->m += |
| (unsigned short)raw_data[raw_data_index + 15] << 8; |
| timing_type_gtf->k = raw_data[raw_data_index + 16]; |
| timing_type_gtf->j = raw_data[raw_data_index + 17]; |
| break; |
| case 0x04: |
| descriptor->type = VIDEO_TIMING_CVT; |
| S_RANGE_LIMITS_VIDEO_TIMING_CVT *timing_type_cvt = |
| (S_RANGE_LIMITS_VIDEO_TIMING_CVT *)descriptor-> |
| suport_flags; |
| timing_type_cvt->cvt_version = raw_data[raw_data_index + 11]; |
| timing_type_cvt->additional_pixel_clock_precision = |
| raw_data[raw_data_index + 12] >> 2; |
| timing_type_cvt->max_active_pixels = |
| raw_data[raw_data_index + 13]; |
| timing_type_cvt->max_active_pixels += |
| (unsigned short)(raw_data[raw_data_index + 12] & 0x03) |
| << 8; |
| timing_type_cvt->supported_ar = |
| raw_data[raw_data_index + 14] >> 3; |
| timing_type_cvt->preferred_ar = |
| raw_data[raw_data_index + 15] >> 5; |
| timing_type_cvt->blanking_support = |
| (raw_data[raw_data_index + 15] & 0x18) >> 3; |
| timing_type_cvt->supported_scalling = |
| raw_data[raw_data_index + 16] >> 4; |
| timing_type_cvt->preferred_vertical_refresh_rate = |
| raw_data[raw_data_index + 17]; |
| break; |
| } |
| |
| return EDID_PARSER_SUCCESS; |
| } |
| |
| static EDID_PARSER_RESULT edid_parse_product_name(S_PRODUCT_NAME_DATA * |
| descriptor, |
| unsigned char *raw_data) |
| { |
| unsigned int raw_data_index = 0; |
| |
| descriptor->header.type = DESCRIPTOR_TYPE_PRODUCT_NAME; |
| descriptor->header.tag = 0xFC; |
| int idx; |
| for (idx = 0; idx < 13; idx++) |
| descriptor->product_name[idx] = |
| raw_data[raw_data_index + 5 + idx]; |
| |
| return EDID_PARSER_SUCCESS; |
| } |
| |
| static EDID_PARSER_RESULT edid_parse_color_point(S_COLOR_POINT_DATA * |
| descriptor, |
| unsigned char *raw_data) |
| { |
| unsigned int raw_data_index = 0; |
| |
| descriptor->header.type = DESCRIPTOR_TYPE_COLOR_POINT; |
| descriptor->header.tag = 0xFB; |
| descriptor->white_point_index_1 = raw_data[raw_data_index + 5]; |
| descriptor->white_x_1 = (raw_data[raw_data_index + 6] & 0x0C) >> 2; |
| descriptor->white_x_1 += |
| (unsigned short)raw_data[raw_data_index + 7] << 2; |
| descriptor->white_y_1 = raw_data[raw_data_index + 6] & 0x03; |
| descriptor->white_y_1 += |
| (unsigned short)raw_data[raw_data_index + 8] << 2; |
| descriptor->gamma_1 = raw_data[raw_data_index + 9]; |
| |
| descriptor->white_point_index_2 = raw_data[raw_data_index + 10]; |
| descriptor->white_x_2 = (raw_data[raw_data_index + 11] & 0x0C) >> 2; |
| descriptor->white_x_2 += |
| (unsigned short)raw_data[raw_data_index + 12] << 2; |
| descriptor->white_y_2 = raw_data[raw_data_index + 11] & 0x03; |
| descriptor->white_y_2 += |
| (unsigned short)raw_data[raw_data_index + 13] << 2; |
| descriptor->gamma_2 = raw_data[raw_data_index + 14]; |
| |
| return EDID_PARSER_SUCCESS; |
| } |
| |
| static EDID_PARSER_RESULT edid_parse_standard_timing(S_STANDARD_TIMING_DATA * |
| descriptor, |
| unsigned char *raw_data) |
| { |
| unsigned int raw_data_index = 0; |
| |
| descriptor->header.type = DESCRIPTOR_TYPE_STANDARD_TIMING; |
| descriptor->header.tag = 0xFA; |
| int idx; |
| for (idx = 0; idx < 6; idx++) { |
| descriptor->standard_timings[idx] = |
| raw_data[raw_data_index + 5 + 2 * idx]; |
| descriptor->standard_timings[idx] += |
| (unsigned short)raw_data[raw_data_index + 5 + 2 * idx + |
| 1]; |
| } |
| |
| return EDID_PARSER_SUCCESS; |
| } |
| |
| static EDID_PARSER_RESULT edid_parse_color_management(S_COLOR_MANAGEMENT_DATA * |
| descriptor, |
| unsigned char *raw_data) |
| { |
| unsigned int raw_data_index = 0; |
| |
| descriptor->header.type = DESCRIPTOR_TYPE_COLOR_MANAGEMENT; |
| descriptor->header.tag = 0xF9; |
| |
| descriptor->version = raw_data[raw_data_index + 5]; |
| |
| descriptor->red_a3 = raw_data[raw_data_index + 6]; |
| descriptor->red_a3 += (unsigned short)raw_data[raw_data_index + 7] << 8; |
| descriptor->red_a2 = raw_data[raw_data_index + 8]; |
| descriptor->red_a2 += (unsigned short)raw_data[raw_data_index + 9] << 8; |
| |
| descriptor->green_a3 = raw_data[raw_data_index + 10]; |
| descriptor->green_a3 += |
| (unsigned short)raw_data[raw_data_index + 11] << 8; |
| descriptor->green_a2 = raw_data[raw_data_index + 12]; |
| descriptor->green_a2 += |
| (unsigned short)raw_data[raw_data_index + 13] << 8; |
| |
| descriptor->blue_a3 = raw_data[raw_data_index + 14]; |
| descriptor->blue_a3 += |
| (unsigned short)raw_data[raw_data_index + 15] << 8; |
| descriptor->blue_a2 = raw_data[raw_data_index + 16]; |
| descriptor->blue_a2 += |
| (unsigned short)raw_data[raw_data_index + 17] << 8; |
| |
| return EDID_PARSER_SUCCESS; |
| } |
| |
| static EDID_PARSER_RESULT edid_parse_cvt_timing_codes(S_CVT_TIMING_CODES_DATA * |
| descriptor, |
| unsigned char *raw_data) |
| { |
| unsigned int raw_data_index = 0; |
| |
| descriptor->header.type = DESCRIPTOR_TYPE_CVT_TIMING_CODES; |
| descriptor->header.tag = 0xF8; |
| descriptor->version = raw_data[raw_data_index + 5]; |
| |
| int idx; |
| for (idx = 0; idx < 4; idx++) { |
| descriptor->addressable_lines[idx] = |
| raw_data[raw_data_index + 6 + idx * 3]; |
| descriptor->addressable_lines[idx] += |
| (unsigned short)(raw_data[raw_data_index + 7 + idx * 3] |
| & 0xF0) << 4; |
| descriptor->aspect_ratio[idx] = |
| (raw_data[raw_data_index + 7 + idx * 3] & 0x0C) >> 2; |
| descriptor->preferred_vertical_rate[idx] = |
| (raw_data[raw_data_index + 8 + idx * 3] & 0x60) >> 5; |
| descriptor->supported_vertical_rate_and_blanking[idx] = |
| raw_data[raw_data_index + 8 + idx * 3] & 0x1F; |
| } |
| |
| return EDID_PARSER_SUCCESS; |
| } |
| |
| static EDID_PARSER_RESULT |
| edid_parse_established_timings_3(S_ESTABLISHED_TIMINGS_3_DATA *descriptor, |
| unsigned char *raw_data) |
| { |
| unsigned int raw_data_index = 0; |
| |
| descriptor->header.type = DESCRIPTOR_TYPE_ESTABLISHED_TIMINGS_3; |
| descriptor->header.tag = 0xF7; |
| descriptor->version = raw_data[raw_data_index + 5]; |
| int idx; |
| for (idx = 0; idx < 6; idx++) { |
| descriptor->established_timings[idx] = |
| raw_data[raw_data_index + 6 + idx]; |
| } |
| |
| return EDID_PARSER_SUCCESS; |
| } |
| |
| static EDID_PARSER_RESULT edid_parse_dummy(S_DUMMY_DATA *descriptor, |
| unsigned char *raw_data) |
| { |
| descriptor->header.type = DESCRIPTOR_TYPE_DUMMY; |
| descriptor->header.tag = 0x10; |
| return EDID_PARSER_SUCCESS; |
| } |
| |
| static EDID_PARSER_RESULT |
| edid_parse_manufacturer_specific(S_MANUFACTURER_SPECIFIC_DATA *descriptor, |
| unsigned char *raw_data, unsigned char tag) |
| { |
| descriptor->header.type = DESCRIPTOR_TYPE_MANUFACTURER_SPECIFIC; |
| descriptor->header.tag = tag; |
| |
| return EDID_PARSER_SUCCESS; |
| } |
| |
| EDID_PARSER_RESULT edid_parse(S_EDID_DATA *edid, unsigned char *raw_data, |
| unsigned int len) |
| { |
| unsigned int raw_data_index = 0; |
| unsigned char sum = 0; |
| /*CHECK SUM OF BYTES IN BLOCK0 */ |
| for (raw_data_index = 0; raw_data_index < EDID_LENGTH; raw_data_index++) |
| sum += raw_data[raw_data_index]; |
| |
| if (sum != 0) |
| return EDID_PARSER_ERROR; |
| |
| /*READ HEADER */ |
| for (raw_data_index = 0; raw_data_index < EDID_HEADER_LENGTH; |
| raw_data_index++) |
| edid->header[raw_data_index] = raw_data[raw_data_index]; |
| |
| /*READ VENDOR & PRODUCT IDENTIFICATION */ |
| /*manufacturer name */ |
| edid->manufacturer_name[0] = ((raw_data[8] & 0x7C) >> 2) + 0x40; |
| edid->manufacturer_name[1] = |
| ((raw_data[8] & 0x03) << 3) + ((raw_data[9] & 0xE0) >> 5) + |
| 0x40; |
| edid->manufacturer_name[2] = ((raw_data[9] & 0x1F)) + 0x40; |
| edid->manufacturer_name[3] = 0; |
| |
| /*product code */ |
| edid->product_code = (raw_data[10]); |
| edid->product_code += ((unsigned short)raw_data[11]) << 8; |
| |
| /*serial number */ |
| edid->serial_number = raw_data[12]; |
| edid->serial_number += (unsigned int)raw_data[13] << 8; |
| edid->serial_number += (unsigned int)raw_data[14] << 16; |
| edid->serial_number += (unsigned int)raw_data[15] << 24; |
| |
| /*week of manufacture */ |
| edid->week = raw_data[16]; |
| |
| /*year of manufacture */ |
| edid->year = raw_data[17]; |
| |
| /*EDID STRUCTURE VERSION & REVISION */ |
| edid->edid_version = ((unsigned short)raw_data[18] << 8) + raw_data[19]; |
| |
| /*BASIC DISPLAY PARAMETERS AND FEATURES */ |
| /*video input definition */ |
| edid->video_input_definition = raw_data[20]; |
| |
| /*horizontal screen size */ |
| edid->horizontal_size = raw_data[21]; |
| |
| /*vertical screen size */ |
| edid->vertical_size = raw_data[22]; |
| |
| /*display transfer characteristic */ |
| edid->gamma = raw_data[23]; |
| |
| /*feature support */ |
| edid->feature_support = raw_data[24]; |
| |
| /*COLOR CHARACTERISTIC */ |
| /*red */ |
| edid->chromacity_coorditates_red_x = (raw_data[25] & 0xC0) >> 6; |
| edid->chromacity_coorditates_red_x += (unsigned short)raw_data[27] << 2; |
| edid->chromacity_coorditates_red_y = (raw_data[25] & 0x30) >> 4; |
| edid->chromacity_coorditates_red_y += (unsigned short)raw_data[28] << 2; |
| |
| /*green */ |
| edid->chromacity_coorditates_green_x = (raw_data[25] & 0x0C) >> 2; |
| edid->chromacity_coorditates_green_x += |
| (unsigned short)raw_data[29] << 2; |
| edid->chromacity_coorditates_green_y = (raw_data[25] & 0x03); |
| edid->chromacity_coorditates_green_y += |
| (unsigned short)raw_data[30] << 2; |
| |
| /*blue */ |
| edid->chromacity_coorditates_blue_x = (raw_data[26] & 0xC0) >> 6; |
| edid->chromacity_coorditates_blue_x += |
| (unsigned short)raw_data[31] << 2; |
| edid->chromacity_coorditates_blue_y = (raw_data[26] & 0x30) >> 4; |
| edid->chromacity_coorditates_blue_y += |
| (unsigned short)raw_data[32] << 2; |
| |
| /*blue */ |
| edid->chromacity_coorditates_white_x = (raw_data[26] & 0x0C) >> 2; |
| edid->chromacity_coorditates_white_x += |
| (unsigned short)raw_data[33] << 2; |
| edid->chromacity_coorditates_white_y = (raw_data[26] & 0x03); |
| edid->chromacity_coorditates_white_y += |
| (unsigned short)raw_data[34] << 2; |
| |
| /*ESTABLISHED TIMINGS */ |
| edid->established_timing_1 = raw_data[35]; |
| edid->established_timing_2 = raw_data[36]; |
| edid->manufacturer_timing = raw_data[37]; |
| |
| /*STANDARD TIMINGS */ |
| for (raw_data_index = 0; raw_data_index < 8; raw_data_index++) { |
| edid->standard_timings[raw_data_index] = |
| raw_data[38 + (2 * raw_data_index)]; |
| edid->standard_timings[raw_data_index] += |
| (unsigned short)raw_data[38 + (2 * raw_data_index + 1)]; |
| } |
| /*extensions */ |
| edid->extensions = raw_data[126]; |
| |
| /*DESCRIPTORS */ |
| unsigned int descriptor_index; |
| raw_data_index = 54; |
| for (descriptor_index = 0; descriptor_index < 4; descriptor_index++) { |
| if (raw_data[raw_data_index] == 0 && |
| raw_data[raw_data_index] == 0) { |
| /*display descriptor found */ |
| unsigned char tag = raw_data[raw_data_index + 3]; |
| if (tag == 0xFF) { |
| /*display product serial number */ |
| S_SERIAL_NUMBER_DATA *descriptor = |
| (S_SERIAL_NUMBER_DATA *)edid-> |
| descriptors[descriptor_index]; |
| if (edid_parse_serial_number |
| (descriptor, |
| raw_data + raw_data_index) != |
| EDID_PARSER_SUCCESS) |
| return EDID_PARSER_ERROR; |
| |
| } else if (tag == 0xFE) { |
| /*alphanumeric data string */ |
| S_DATA_STRING_DATA *descriptor = |
| (S_DATA_STRING_DATA *)edid-> |
| descriptors[descriptor_index]; |
| if (edid_parse_data_string |
| (descriptor, |
| raw_data + raw_data_index) != |
| EDID_PARSER_SUCCESS) |
| return EDID_PARSER_ERROR; |
| |
| } else if (tag == 0xFD) { |
| /*display range limits */ |
| S_RANGE_LIMITS_DATA *descriptor = |
| (S_RANGE_LIMITS_DATA *)edid-> |
| descriptors[descriptor_index]; |
| if (edid_parse_range_limits |
| (descriptor, |
| raw_data + raw_data_index) != |
| EDID_PARSER_SUCCESS) |
| return EDID_PARSER_ERROR; |
| |
| } else if (tag == 0xFC) { |
| /*display product name */ |
| S_PRODUCT_NAME_DATA *descriptor = |
| (S_PRODUCT_NAME_DATA *)edid-> |
| descriptors[descriptor_index]; |
| if (edid_parse_product_name |
| (descriptor, |
| raw_data + raw_data_index) != |
| EDID_PARSER_SUCCESS) |
| return EDID_PARSER_ERROR; |
| |
| } else if (tag == 0xFB) { |
| /*color point data */ |
| S_COLOR_POINT_DATA *descriptor = |
| (S_COLOR_POINT_DATA *)edid-> |
| descriptors[descriptor_index]; |
| if (edid_parse_color_point |
| (descriptor, |
| raw_data + raw_data_index) != |
| EDID_PARSER_SUCCESS) |
| return EDID_PARSER_ERROR; |
| |
| } else if (tag == 0xFA) { |
| /*standard timing identifications */ |
| S_STANDARD_TIMING_DATA *descriptor = |
| (S_STANDARD_TIMING_DATA *)edid-> |
| descriptors[descriptor_index]; |
| if (edid_parse_standard_timing |
| (descriptor, |
| raw_data + raw_data_index) != |
| EDID_PARSER_SUCCESS) |
| return EDID_PARSER_ERROR; |
| |
| } else if (tag == 0xF9) { |
| /*display color management (DCM) */ |
| S_COLOR_MANAGEMENT_DATA *descriptor = |
| (S_COLOR_MANAGEMENT_DATA *)edid-> |
| descriptors[descriptor_index]; |
| if (edid_parse_color_management |
| (descriptor, |
| raw_data + raw_data_index) != |
| EDID_PARSER_SUCCESS) |
| return EDID_PARSER_ERROR; |
| |
| } else if (tag == 0xF8) { |
| /*CVT 3 byte timing codes */ |
| S_CVT_TIMING_CODES_DATA *descriptor = |
| (S_CVT_TIMING_CODES_DATA *)edid-> |
| descriptors[descriptor_index]; |
| if (edid_parse_cvt_timing_codes |
| (descriptor, |
| raw_data + raw_data_index) != |
| EDID_PARSER_SUCCESS) |
| return EDID_PARSER_ERROR; |
| |
| } else if (tag == 0xF7) { |
| /*established timings III */ |
| S_ESTABLISHED_TIMINGS_3_DATA *descriptor = |
| (S_ESTABLISHED_TIMINGS_3_DATA *)edid-> |
| descriptors[descriptor_index]; |
| if (edid_parse_established_timings_3 |
| (descriptor, |
| raw_data + raw_data_index) != |
| EDID_PARSER_SUCCESS) |
| return EDID_PARSER_ERROR; |
| |
| } else if (tag == 0x10) { |
| /*dummy */ |
| S_DUMMY_DATA *descriptor = |
| (S_DUMMY_DATA *)edid-> |
| descriptors[descriptor_index]; |
| if (edid_parse_dummy |
| (descriptor, |
| raw_data + raw_data_index) != |
| EDID_PARSER_SUCCESS) |
| return EDID_PARSER_ERROR; |
| |
| } else if (tag <= 0x0F) { |
| /*manufacturer specific data */ |
| S_MANUFACTURER_SPECIFIC_DATA *descriptor = |
| (S_MANUFACTURER_SPECIFIC_DATA *)edid-> |
| descriptors[descriptor_index]; |
| if (edid_parse_manufacturer_specific |
| (descriptor, raw_data + raw_data_index, |
| tag) != EDID_PARSER_SUCCESS) |
| return EDID_PARSER_ERROR; |
| } |
| } else { |
| /*detailed timing definition */ |
| S_DTD_DATA *descriptor = |
| (S_DTD_DATA *)edid-> |
| descriptors[descriptor_index]; |
| if (edid_parse_dtd |
| (descriptor, |
| raw_data + raw_data_index) != |
| EDID_PARSER_SUCCESS) |
| return EDID_PARSER_ERROR; |
| } |
| raw_data_index += 18; |
| } |
| |
| return EDID_PARSER_SUCCESS; |
| } |