blob: 24aa7397910eb726197912472b019e776b3a5a5a [file] [log] [blame]
/******************************************************************************
*
* 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;
}