blob: 6b0edb61c07d56dae7324bcf2f91a52baeb90a33 [file] [log] [blame]
/* vim: set et fde fdm=syntax ft=c.doxygen ts=4 sts=4 sw=4 : */
/*
* Copyright © 2011 Saleem Abdulrasool <compnerd@compnerd.org>.
* All rights reserved.
*
* 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. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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 AUTHOR 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.
*/
#include "string.h"
#include "stdlib.h"
#include "stddef.h"
#include "xil_types.h"
#include "xstatus.h"
#include "xil_exception.h"
#include "xvidc_edid_ext.h"
#if XVIDC_EDID_VERBOSITY > 1
#include "math.h"
#define CM_2_MM(cm) ((cm) * 10)
#define CM_2_IN(cm) ((cm) * 0.3937)
#endif
#if XVIDC_EDID_VERBOSITY > 0
#define HZ_2_MHZ(hz) ((hz) / 1000000)
#endif
#if XVIDC_EDID_VERBOSITY > 1
static void
xvidc_disp_cea861_audio_data(
const struct xvidc_cea861_audio_data_block * const adb,
XV_VidC_EdidCntrlParam *EdidCtrlParam,
XV_VidC_Verbose VerboseEn);
static void
xvidc_disp_cea861_speaker_allocation_data(
const struct xvidc_cea861_speaker_allocation_data_block * const sadb,
XV_VidC_EdidCntrlParam *EdidCtrlParam,
XV_VidC_Verbose VerboseEn);
static void
xvidc_disp_cea861_video_data(
const struct xvidc_cea861_video_data_block * const vdb,
XV_VidC_EdidCntrlParam *EdidCtrlParam,
XV_VidC_Verbose VerboseEn);
#endif
static void
xvidc_disp_cea861_extended_data(
const struct xvidc_cea861_extended_data_block * const edb,
XV_VidC_EdidCntrlParam *EdidCtrlParam,
XV_VidC_Verbose VerboseEn);
static void
xvidc_disp_cea861_vendor_data(
const struct xvidc_cea861_vendor_specific_data_block * vsdb,
XV_VidC_EdidCntrlParam *EdidCtrlParam,
XV_VidC_Verbose VerboseEn);
static void
xvidc_disp_cea861(const struct xvidc_edid_extension * const ext,
XV_VidC_EdidCntrlParam *EdidCtrlParam,
XV_VidC_Verbose VerboseEn);
static void
xvidc_disp_edid1(const struct edid * const edid,
XV_VidC_EdidCntrlParam *EdidCtrlParam,
XV_VidC_Verbose VerboseEn);
/*****************************************************************************/
/**
*
* This function parse EDID on General Data & VESA Data
*
* @param data is a pointer to the EDID array.
* @param EdidCtrlParam is a pointer the EDID Control parameter
* @param VerboseEn is a pointer to the XV_HdmiTxSs core instance.
*
* @return None
*
* @note API Define below here are CEA861 routines
*
******************************************************************************/
static void
xvidc_disp_edid1(const struct edid * const edid,
XV_VidC_EdidCntrlParam *EdidCtrlParam,
XV_VidC_Verbose VerboseEn)
{
const struct xvidc_edid_monitor_range_limits *monitor_range_limits = NULL;
xvidc_edid_monitor_descriptor_string monitor_serial_number = {0};
xvidc_edid_monitor_descriptor_string monitor_model_name = {0};
bool has_ascii_string = false;
char manufacturer[4] = {0};
#if XVIDC_EDID_VERBOSITY > 1
XV_VidC_DoubleRep min_doubleval;
XV_VidC_DoubleRep max_doubleval;
#endif
u8 i;
#if XVIDC_EDID_VERBOSITY > 0
//add by mmo
XV_VidC_TimingParam timing_params;
#endif
#if XVIDC_EDID_VERBOSITY > 1
struct xvidc_edid_color_characteristics_data characteristics;
const u8 vlen = edid->maximum_vertical_image_size;
const u8 hlen = edid->maximum_horizontal_image_size;
static const char * const display_type[] = {
[XVIDC_EDID_DISPLAY_TYPE_MONOCHROME] = "Monochrome or greyscale",
[XVIDC_EDID_DISPLAY_TYPE_RGB] = "sRGB colour",
[XVIDC_EDID_DISPLAY_TYPE_NON_RGB] = "Non-sRGB colour",
[XVIDC_EDID_DISPLAY_TYPE_UNDEFINED] = "Undefined",
};
#endif
xvidc_edid_manufacturer(edid, manufacturer);
for (i = 0; i < ARRAY_SIZE(edid->detailed_timings); i++) {
const struct xvidc_edid_monitor_descriptor * const mon =
&edid->detailed_timings[i].monitor;
if (!xvidc_edid_detailed_timing_is_monitor_descriptor(edid, i))
continue;
switch (mon->tag) {
case XVIDC_EDID_MONTIOR_DESCRIPTOR_MANUFACTURER_DEFINED:
/* This is arbitrary data, just silently ignore it. */
break;
case XVIDC_EDID_MONITOR_DESCRIPTOR_ASCII_STRING:
has_ascii_string = true;
break;
case XVIDC_EDID_MONITOR_DESCRIPTOR_MONITOR_NAME:
strncpy(monitor_model_name, (char *) mon->data,
sizeof(monitor_model_name) - 1);
break;
case XVIDC_EDID_MONITOR_DESCRIPTOR_MONITOR_RANGE_LIMITS:
monitor_range_limits =
(struct xvidc_edid_monitor_range_limits *) &mon->data;
break;
case XVIDC_EDID_MONITOR_DESCRIPTOR_MONITOR_SERIAL_NUMBER:
strncpy(monitor_serial_number, (char *) mon->data,
sizeof(monitor_serial_number) - 1);
break;
default:
if (VerboseEn) {
xil_printf("unknown monitor descriptor type 0x%02x\n",
mon->tag);
}
break;
}
}
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf("Sink Information\r\n");
xil_printf(" Model name............... %s\r\n",
*monitor_model_name ? monitor_model_name : "n/a");
#if XVIDC_EDID_VERBOSITY > 1
xil_printf(" Manufacturer............. %s\r\n",
manufacturer);
xil_printf(" Product code............. %u\r\n",
(u16) edid->product_u16);
if (*(u32 *) edid->serial_number_u32)
xil_printf(" Module serial number..... %u\r\n",
(u32) edid->serial_number_u32);
#endif
#if defined(DISPLAY_UNKNOWN)
xil_printf(" Plug and Play ID......... %s\r\n", NULL);
#endif
#if XVIDC_EDID_VERBOSITY > 1
xil_printf(" Serial number............ %s\r\n",
*monitor_serial_number ? monitor_serial_number : "n/a");
xil_printf(" Manufacture date......... %u",
edid->manufacture_year + 1990);
if (edid->manufacture_week <= 52)
xil_printf(", ISO week %u", edid->manufacture_week);
xil_printf("\r\n");
#endif
xil_printf(" EDID revision............ %u.%u\r\n",
edid->version, edid->revision);
#if XVIDC_EDID_VERBOSITY > 1
xil_printf(" Input signal type........ %s\r\n",
edid->video_input_definition.digital.digital ? "Digital" : "Analog");
if (edid->video_input_definition.digital.digital) {
xil_printf(" VESA DFP 1.x supported... %s\r\n",
edid->video_input_definition.digital.dfp_1x ? "Yes" : "No");
} else {
/* Missing Piece: To print analog flags */
}
#endif
#if defined(DISPLAY_UNKNOWN)
xil_printf(" Color bit depth.......... %s\r\n", NULL);
#endif
#if XVIDC_EDID_VERBOSITY > 1
xil_printf(" Display type............. %s\r\n",
display_type[edid->feature_support.display_type]);
xil_printf(" Screen size.............. %u mm x %u mm (%.1f in)\r\n",
CM_2_MM(hlen), CM_2_MM(vlen),
CM_2_IN(sqrt(hlen * hlen + vlen * vlen)));
xil_printf(" Power management......... %s%s%s%s\r\n",
edid->feature_support.active_off ? "Active off, " : "",
edid->feature_support.suspend ? "Suspend, " : "",
edid->feature_support.standby ? "Standby, " : "",
(edid->feature_support.active_off ||
edid->feature_support.suspend ||
edid->feature_support.standby) ? "\b\b " : "n/a");
#endif
xil_printf(" Extension blocks......... %u\r\n",
edid->extensions);
#if defined(DISPLAY_UNKNOWN)
xil_printf(" DDC/CI................... %s\r\n", NULL);
#endif
xil_printf("\r\n");
}
#endif
if (has_ascii_string) {
if (VerboseEn) {
#if XVIDC_EDID_VERBOSITY > 1
xil_printf("General purpose ASCII string\r\n");
#endif
}
for (i = 0; i < ARRAY_SIZE(edid->detailed_timings); i++) {
if (!xvidc_edid_detailed_timing_is_monitor_descriptor(edid, i))
continue;
}
if (VerboseEn) {
#if XVIDC_EDID_VERBOSITY > 1
xil_printf("\r\n");
#endif
}
}
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf("Color characteristics\r\n");
xil_printf(" Default color space...... %ssRGB\r\n",
edid->feature_support.standard_default_color_space ? "":"Non-");
#if XVIDC_EDID_VERBOSITY > 1
min_doubleval =
Double2Int(xvidc_edid_gamma(edid));
xil_printf(" Display gamma............ %d.%03d\r\n",
min_doubleval.Integer, min_doubleval.Decimal);
characteristics = xvidc_edid_color_characteristics(edid);
min_doubleval =
Double2Int(xvidc_edid_decode_fixed_point(characteristics.red.x));
max_doubleval =
Double2Int(xvidc_edid_decode_fixed_point(characteristics.red.y));
xil_printf(" Red chromaticity......... Rx %d.%03d - Ry %d.%03d\r\n",
min_doubleval.Integer, min_doubleval.Decimal,
max_doubleval.Integer, max_doubleval.Decimal);
min_doubleval =
Double2Int(xvidc_edid_decode_fixed_point(characteristics.green.x));
max_doubleval =
Double2Int(xvidc_edid_decode_fixed_point(characteristics.green.y));
xil_printf(" Green chromaticity....... Gx %d.%03d - Gy %d.%03d\r\n",
min_doubleval.Integer, min_doubleval.Decimal,
max_doubleval.Integer, max_doubleval.Decimal);
min_doubleval =
Double2Int(xvidc_edid_decode_fixed_point(characteristics.blue.x));
max_doubleval =
Double2Int(xvidc_edid_decode_fixed_point(characteristics.blue.y));
xil_printf(" Blue chromaticity........ Bx %d.%03d - By %d.%03d\r\n",
min_doubleval.Integer, min_doubleval.Decimal,
max_doubleval.Integer, max_doubleval.Decimal);
min_doubleval =
Double2Int(xvidc_edid_decode_fixed_point(characteristics.white.x));
max_doubleval =
Double2Int(xvidc_edid_decode_fixed_point(characteristics.white.y));
xil_printf(" White point (default).... Wx %d.%03d - Wy %d.%03d\r\n",
min_doubleval.Integer, min_doubleval.Decimal,
max_doubleval.Integer, max_doubleval.Decimal);
#endif
#if defined(DISPLAY_UNKNOWN)
xil_printf(" Additional descriptors... %s\r\n", NULL);
#endif
xil_printf("\r\n");
xil_printf("VESA Timing characteristics\r\n");
}
#endif
if (monitor_range_limits) {
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf(" Horizontal scan range.... %u - %u kHz\r\n",
monitor_range_limits->minimum_horizontal_rate,
monitor_range_limits->maximum_horizontal_rate);
xil_printf(" Vertical scan range...... %u - %u Hz\r\n",
monitor_range_limits->minimum_vertical_rate,
monitor_range_limits->maximum_vertical_rate);
xil_printf(" Video bandwidth.......... %u MHz\r\n",
monitor_range_limits->maximum_supported_pixel_clock * 10);
}
#endif
EdidCtrlParam->MaxFrameRateSupp =
monitor_range_limits->maximum_vertical_rate;
EdidCtrlParam->MaxTmdsMhz =
(monitor_range_limits->maximum_supported_pixel_clock * 10);
}
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
#if defined(DISPLAY_UNKNOWN)
xil_printf(" CVT standard............. %s\r\n", NULL);
#endif
#if XVIDC_EDID_VERBOSITY > 1
xil_printf(" GTF standard............. %sSupported\r\n",
edid->feature_support.default_gtf ? "" : "Not ");
#endif
#if defined(DISPLAY_UNKNOWN)
xil_printf(" Additional descriptors... %s\r\n", NULL);
#endif
#if XVIDC_EDID_VERBOSITY > 0
xil_printf(" Preferred timing......... %s\r\n",
edid->feature_support.preferred_timing_mode ? "Yes" : "No");
#endif
for (i = 0; i < ARRAY_SIZE(edid->detailed_timings); i++) {
if (xvidc_edid_detailed_timing_is_monitor_descriptor(edid, i))
continue;
timing_params = XV_VidC_timing(&edid->detailed_timings[i].timing);
EdidCtrlParam->PreferedTiming[i] =
XV_VidC_timing(&edid->detailed_timings[i].timing);
#if XVIDC_EDID_VERBOSITY > 0
if (edid->feature_support.preferred_timing_mode) {
xil_printf(" Native/preferred timing.. %ux%u%c at %uHz"
" (%u:%u)\r\n",
timing_params.hres,
timing_params.vres,
timing_params.vidfrmt ? 'i' : 'p',
timing_params.vfreq,
timing_params.aspect_ratio.width,
timing_params.aspect_ratio.height);
xil_printf(" Modeline............... \"%ux%u\" %u %u %u %u"
" %u %u %u %u %u %chsync %cvsync\r\n",
timing_params.hres,
timing_params.vres,
HZ_2_MHZ (timing_params.pixclk),
(timing_params.hres),
(timing_params.hres + timing_params.hfp),
(timing_params.hres + timing_params.hfp +
timing_params.hsync_width),
(timing_params.htotal),
(timing_params.vres),
(timing_params.vres + timing_params.vfp),
(timing_params.vres + timing_params.vfp +
timing_params.vsync_width),
(timing_params.vtotal),
timing_params.hsync_polarity ? '+' : '-',
timing_params.vsync_polarity ? '+' : '-');
} else {
xil_printf(" Native/preferred timing.. n/a\r\n");
}
#endif
}
#if XVIDC_EDID_VERBOSITY > 0
xil_printf("\r\n");
#endif
#if XVIDC_EDID_VERBOSITY > 1
xil_printf("Established Timings supported\r\n");
if (edid->established_timings.timing_720x400_70)
xil_printf(" 720 x 400p @ 70Hz - IBM VGA\r\n");
if (edid->established_timings.timing_720x400_88)
xil_printf(" 720 x 400p @ 88Hz - IBM XGA2\r\n");
if (edid->established_timings.timing_640x480_60)
xil_printf(" 640 x 480p @ 60Hz - IBM VGA\r\n");
if (edid->established_timings.timing_640x480_67)
xil_printf(" 640 x 480p @ 67Hz - Apple Mac II\r\n");
if (edid->established_timings.timing_640x480_72)
xil_printf(" 640 x 480p @ 72Hz - VESA\r\n");
if (edid->established_timings.timing_640x480_75)
xil_printf(" 640 x 480p @ 75Hz - VESA\r\n");
if (edid->established_timings.timing_800x600_56)
xil_printf(" 800 x 600p @ 56Hz - VESA\r\n");
if (edid->established_timings.timing_800x600_60)
xil_printf(" 800 x 600p @ 60Hz - VESA\r\n");
if (edid->established_timings.timing_800x600_72)
xil_printf(" 800 x 600p @ 72Hz - VESA\r\n");
if (edid->established_timings.timing_800x600_75)
xil_printf(" 800 x 600p @ 75Hz - VESA\r\n");
if (edid->established_timings.timing_832x624_75)
xil_printf(" 832 x 624p @ 75Hz - Apple Mac II\r\n");
if (edid->established_timings.timing_1024x768_87)
xil_printf(" 1024 x 768i @ 87Hz - VESA\r\n");
if (edid->established_timings.timing_1024x768_60)
xil_printf(" 1024 x 768p @ 60Hz - VESA\r\n");
if (edid->established_timings.timing_1024x768_70)
xil_printf(" 1024 x 768p @ 70Hz - VESA\r\n");
if (edid->established_timings.timing_1024x768_75)
xil_printf(" 1024 x 768p @ 75Hz - VESA\r\n");
if (edid->established_timings.timing_1280x1024_75)
xil_printf(" 1280 x 1024p @ 75Hz - VESA\r\n");
#endif
}
#endif
#if XVIDC_EDID_VERBOSITY > 1
if (VerboseEn) {
xil_printf("Standard Timings supported\r\n");
for (i = 0; i < ARRAY_SIZE(edid->standard_timing_id); i++) {
const struct xvidc_edid_standard_timing_descriptor * const desc =
&edid->standard_timing_id[i];
if (!memcmp(desc, XVIDC_EDID_STANDARD_TIMING_DESCRIPTOR_INVALID,
sizeof(*desc)))
{
continue;
} else {
if (((desc->horizontal_active_pixels + 31)* 8) >= 1000) {
xil_printf(" %u x",(desc->horizontal_active_pixels + 31)* 8);
} else {
xil_printf(" %u x",(desc->horizontal_active_pixels + 31)* 8);
}
switch (desc->image_aspect_ratio) {
case 0: //Aspect Ratio = 16:10
xil_printf(" %up ",
(((desc->horizontal_active_pixels + 31)* 8) * 10) / 16);
break;
case 1: //Aspect Ratio = 4:3
xil_printf(" %up ",
(((desc->horizontal_active_pixels + 31)* 8) * 3) / 4);
break;
case 2: //Aspect Ratio = 5:4
xil_printf(" %up ",
(((desc->horizontal_active_pixels + 31)* 8) * 4) / 5);
break;
case 3: //Aspect Ratio = 16:9
xil_printf(" %up ",
(((desc->horizontal_active_pixels + 31)* 8) * 9) / 16);
break;
default: //Aspect Ratio = 16:10
xil_printf(" %up ",
(((desc->horizontal_active_pixels + 31)* 8) * 10) / 16);
break;
}
xil_printf("@ %uHz\r\n",(desc->refresh_rate + 60));
}
}
}
#endif
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf("\r\n");
}
#endif
}
/*****************************************************************************/
/**
*
* This function parse EDID on CEA 861 Audio Data
*
* @param data is a pointer to the EDID array.
* @param EdidCtrlParam is a pointer the EDID Control parameter
* @param VerboseEn is a pointer to the XV_HdmiTxSs core instance.
*
* @return None
*
* @note API Define below here are CEA861 routines
*
******************************************************************************/
#if XVIDC_EDID_VERBOSITY > 1
static void
xvidc_disp_cea861_audio_data(
const struct xvidc_cea861_audio_data_block * const adb,
XV_VidC_EdidCntrlParam *EdidCtrlParam,
XV_VidC_Verbose VerboseEn) {
/* For Future Usage */
EdidCtrlParam = EdidCtrlParam;
const u8 descriptors = adb->header.length / sizeof(*adb->sad);
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf("CE audio data (formats supported)\r\n");
}
#endif
for (u8 i = 0; i < descriptors; i++) {
const struct xvidc_cea861_short_audio_descriptor * const sad =
(struct xvidc_cea861_short_audio_descriptor *) &adb->sad[i];
switch (sad->audio_format) {
case XVIDC_CEA861_AUDIO_FORMAT_LPCM:
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf(" LPCM %u-channel, %s%s%s\b%s",
sad->channels + 1,
sad->flags.lpcm.bitrate_16_bit ? "16/" : "",
sad->flags.lpcm.bitrate_20_bit ? "20/" : "",
sad->flags.lpcm.bitrate_24_bit ? "24/" : "",
((sad->flags.lpcm.bitrate_16_bit +
sad->flags.lpcm.bitrate_20_bit +
sad->flags.lpcm.bitrate_24_bit) > 1) ?
" bit depths" : "-bit");
}
#endif
break;
case XVIDC_CEA861_AUDIO_FORMAT_AC_3:
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf(" AC-3 %u-channel, %4uk max. bit rate",
sad->channels + 1,
(sad->flags.maximum_bit_rate << 3));
}
#endif
break;
default:
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf("Unknown audio format 0x%02x\r\n",
sad->audio_format);
}
#endif
continue;
}
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf(" at %s%s%s%s%s%s%s\b kHz\r\n",
sad->sample_rate_32_kHz ? "32/" : "",
sad->sample_rate_44_1_kHz ? "44.1/" : "",
sad->sample_rate_48_kHz ? "48/" : "",
sad->sample_rate_88_2_kHz ? "88.2/" : "",
sad->sample_rate_96_kHz ? "96/" : "",
sad->sample_rate_176_4_kHz ? "176.4/" : "",
sad->sample_rate_192_kHz ? "192/" : "");
}
#endif
}
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf("\r\n");
}
#endif
}
#endif
/*****************************************************************************/
/**
*
* This function parse EDID on CEA 861 Extended Data
*
* @param data is a pointer to the EDID array.
* @param EdidCtrlParam is a pointer the EDID Control parameter
* @param VerboseEn is a pointer to the XV_HdmiTxSs core instance.
*
* @return None
*
* @note None.
*
******************************************************************************/
static void
xvidc_disp_cea861_extended_data(
const struct xvidc_cea861_extended_data_block * const edb,
XV_VidC_EdidCntrlParam *EdidCtrlParam,
XV_VidC_Verbose VerboseEn) {
/* During Verbosity 0, VerboseEn won't be used */
/* To avoid compilation warnings */
VerboseEn = VerboseEn;
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf("CEA Extended Tags\r\n");
}
#endif
switch(edb->xvidc_cea861_extended_tag_codes) {
#if XVIDC_EDID_VERBOSITY > 1
case XVIDC_CEA861_EXT_TAG_TYPE_VIDEO_CAPABILITY:
if (VerboseEn) {
xil_printf(" Video capability data block\r\n");
}
break;
case XVIDC_CEA861_EXT_TAG_TYPE_VENDOR_SPECIFIC:
if (VerboseEn) {
xil_printf(" Vendor-specific video data block\r\n");
}
break;
case XVIDC_CEA861_EXT_TAG_TYPE_VESA_DISPLAY_DEVICE:
if (VerboseEn) {
xil_printf(" VESA video display device data block\r\n");
}
break;
case XVIDC_CEA861_EXT_TAG_TYPE_VESA_VIDEO_TIMING_BLOCK_EXT:
if (VerboseEn) {
xil_printf("VESA video timing block extension\r\n");
}
break;
case XVIDC_CEA861_EXT_TAG_TYPE_RESERVED_FOR_HDMI_VIDEO_DATA_BLOCK:
if (VerboseEn) {
xil_printf("Reserved for HDMI video data block\r\n");
}
break;
case XVIDC_CEA861_EXT_TAG_TYPE_COLORIMETRY:
if (VerboseEn) {
xil_printf(" Colorimetry data block\r\n");
}
break;
case XVIDC_CEA861_EXT_TAG_TYPE_HDR_STATIC_METADATA:
if (VerboseEn) {
xil_printf("HDR static metadata data block\r\n");
}
break;
case XVIDC_CEA861_EXT_TAG_TYPE_HDR_DYNAMIC_METADATA:
if (VerboseEn) {
xil_printf(" HDR dynamic metadata data block\r\n");
}
break;
case XVIDC_CEA861_EXT_TAG_TYPE_VIDEO_FRMT_PREFERENCE:
if (VerboseEn) {
xil_printf(" Video format preference data block\r\n");
}
break;
case XVIDC_CEA861_EXT_TAG_TYPE_CEA_MISC_AUDIO_FIELDS:
if (VerboseEn) {
xil_printf("Reserved for CEA miscellaneous audio fields\r\n");
}
break;
case XVIDC_CEA861_EXT_TAG_TYPE_VENDOR_SPECIFC_AUDIO:
if (VerboseEn) {
xil_printf(" Vendor-specific audio data block\r\n\r\n");
}
break;
case XVIDC_CEA861_EXT_TAG_TYPE_HDMI_AUDIO:
if (VerboseEn) {
xil_printf(" HDMI audio data block\r\n");
}
break;
case XVIDC_CEA861_EXT_TAG_TYPE_ROOM_CONFIGURATION:
if (VerboseEn) {
xil_printf(" Room configuration data block\r\n");
}
break;
case XVIDC_CEA861_EXT_TAG_TYPE_SPEAKER_LOCATION:
if (VerboseEn) {
xil_printf(" Speaker location data block\r\n");
}
break;
case XVIDC_CEA861_EXT_TAG_TYPE_INFOFRAME:
if (VerboseEn) {
xil_printf(" Video capability data block\r\n");
}
break;
#endif
case XVIDC_CEA861_EXT_TAG_TYPE_YCBCR420_VIDEO:
#if XVIDC_EDID_VERBOSITY > 1
if (VerboseEn) {
xil_printf(" YCbCr 4:2:0 video data block\r\n");
xil_printf(" YCbCr 4:2:0.............. Supported\r\n");
}
#endif
EdidCtrlParam->IsYCbCr420Supp = XVIDC_SUPPORTED;
#if XVIDC_EDID_VERBOSITY > 1
if (VerboseEn) {
xil_printf(" CE video identifiers (VICs) - "
" timing/formats supported\r\n");
}
for (u8 i = 0; i < edb->header.length - 1; i++) {
u8 vic;
u8 native=0;
if ((edb->data[i] & 0x7F) == 0) {
continue;
} else if (((edb->data[i]) >= 1) && ((edb->data[i]) <= 64)){
vic = (edb->data[i]) & 0x7F;
} else if (((edb->data[i]) >= 65) && ((edb->data[i]) <= 127)){
vic = (edb->data[i]);
} else if (((edb->data[i]) >= 129) && ((edb->data[i]) <= 192)){
vic = (edb->data[i]) & 0x7F;
native = 1;
} else if (((edb->data[i]) >= 193) && ((edb->data[i]) <= 253)){
vic = (edb->data[i]);
} else {
continue;
}
const struct xvidc_cea861_timing * const timing =
&xvidc_cea861_timings[vic];
if (VerboseEn) {
xil_printf(" %s CEA Mode %02u: %4u x %4u%c @ %dHz\r\n",
native ? "*" : " ",
vic,
timing->hactive, timing->vactive,
(timing->mode == INTERLACED) ? 'i' : 'p',
(u32)(timing->vfreq));
}
}
if (VerboseEn) {
xil_printf("\r\n");
}
#endif
break;
case XVIDC_CEA861_EXT_TAG_TYPE_YCBCR420_CAPABILITY_MAP:
#if XVIDC_EDID_VERBOSITY > 1
if (VerboseEn) {
xil_printf(" YCbCr 4:2:0 capability map data block\r\n");
xil_printf(" YCbCr 4:2:0.............. Supported\r\n");
}
#endif
EdidCtrlParam->IsYCbCr420Supp = XVIDC_SUPPORTED;
#if XVIDC_EDID_VERBOSITY > 1
for (u8 i = 0; i < edb->header.length - 1; i++) {
u8 v = edb->data[i];
for (u8 j = 0; j < 8; j++) {
if (v & (1 << j)) {
if (VerboseEn) {
const struct xvidc_cea861_timing * const timing =
&xvidc_cea861_timings[EdidCtrlParam->SuppCeaVIC[(i * 8) + j]];
xil_printf(" CEA Mode %02u: %4u x %4u%c"
"@ %dHz\r\n",
EdidCtrlParam->SuppCeaVIC[(i * 8) + j],
timing->hactive, timing->vactive,
(timing->mode == INTERLACED) ? 'i' : 'p',
(u32)(timing->vfreq));
}
}
}
}
#endif
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf("\r\n");
}
#endif
break;
default :
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
#if XVIDC_EDID_VERBOSITY > 1
xil_printf(" Not Supported: Ext Tag: %03x\r\n",
edb->xvidc_cea861_extended_tag_codes);
#endif
xil_printf("\r\n");
}
#endif
break;
}
}
#if XVIDC_EDID_VERBOSITY > 1
static void
xvidc_disp_cea861_video_data(
const struct xvidc_cea861_video_data_block * const vdb,
XV_VidC_EdidCntrlParam *EdidCtrlParam,
XV_VidC_Verbose VerboseEn) {
/* For Future Usage */
EdidCtrlParam = EdidCtrlParam;
if (VerboseEn) {
xil_printf("CE video identifiers (VICs) - timing/formats"
" supported\r\n");
}
for (u8 i = 0; i < vdb->header.length; i++) {
const struct xvidc_cea861_timing * const timing =
&xvidc_cea861_timings[vdb->svd[i].video_identification_code];
EdidCtrlParam->SuppCeaVIC[i] = vdb->svd[i].video_identification_code;
if (VerboseEn) {
xil_printf(" %s CEA Mode %02u: %4u x %4u%c @ %dHz\r\n",
vdb->svd[i].native ? "*" : " ",
vdb->svd[i].video_identification_code,
timing->hactive, timing->vactive,
(timing->mode == INTERLACED) ? 'i' : 'p',
(u32)(timing->vfreq));
}
}
if (VerboseEn) {
xil_printf("\r\n");
}
}
#endif
/*****************************************************************************/
/**
*
* This function parse EDID on CEA 861 Vendor Specific Data
*
* @param data is a pointer to the EDID array.
* @param EdidCtrlParam is a pointer the EDID Control parameter
* @param VerboseEn is a pointer to the XV_HdmiTxSs core instance.
*
* @return None
*
* @note None.
*
******************************************************************************/
static void
xvidc_disp_cea861_vendor_data(
const struct xvidc_cea861_vendor_specific_data_block * vsdb,
XV_VidC_EdidCntrlParam *EdidCtrlParam,
XV_VidC_Verbose VerboseEn) {
/* During Verbosity 0, VerboseEn won't be used */
/* To avoid compilation warnings */
VerboseEn = VerboseEn;
const u8 oui[] = { vsdb->ieee_registration[2],
vsdb->ieee_registration[1],
vsdb->ieee_registration[0] };
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf("CEA vendor specific data (VSDB)\r\n");
xil_printf(" IEEE registration number. 0x");
for (u8 i = 0; i < ARRAY_SIZE(oui); i++)
xil_printf("%02X", oui[i]);
xil_printf("\r\n");
}
#endif
if (!memcmp(oui, HDMI_OUI, sizeof(oui))) {
const struct xvidc_cea861_hdmi_vendor_specific_data_block * const hdmi =
(struct xvidc_cea861_hdmi_vendor_specific_data_block *) vsdb;
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf(" CEC physical address..... %u.%u.%u.%u\r\n",
hdmi->port_configuration_a,
hdmi->port_configuration_b,
hdmi->port_configuration_c,
hdmi->port_configuration_d);
}
#endif
if (hdmi->header.length >= HDMI_VSDB_EXTENSION_FLAGS_OFFSET) {
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
#if XVIDC_EDID_VERBOSITY > 1
xil_printf(" Supports AI (ACP, ISRC).. %s\r\n",
hdmi->audio_info_frame ? "Yes" : "No");
#endif
xil_printf(" Supports 48bpp........... %s\r\n",
hdmi->colour_depth_48_bit ? "Yes" : "No");
xil_printf(" Supports 36bpp........... %s\r\n",
hdmi->colour_depth_36_bit ? "Yes" : "No");
xil_printf(" Supports 30bpp........... %s\r\n",
hdmi->colour_depth_30_bit ? "Yes" : "No");
xil_printf(" Supp. YUV444 Deep Color.. %s\r\n",
hdmi->yuv_444_supported ? "Yes" : "No");
#if XVIDC_EDID_VERBOSITY > 1
xil_printf(" Supports dual-link DVI... %s\r\n",
hdmi->dvi_dual_link ? "Yes" : "No");
#endif
}
#endif
EdidCtrlParam->Is30bppSupp = hdmi->colour_depth_30_bit;
EdidCtrlParam->Is36bppSupp = hdmi->colour_depth_36_bit;
EdidCtrlParam->Is48bppSupp = hdmi->colour_depth_48_bit;
EdidCtrlParam->IsYCbCr444DeepColSupp = hdmi->yuv_444_supported;
}
if (hdmi->header.length >= HDMI_VSDB_MAX_TMDS_OFFSET) {
if (hdmi->max_tmds_clock) {
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf(" Maximum TMDS clock....... %uMHz\r\n",
hdmi->max_tmds_clock * 5);
}
#endif
EdidCtrlParam->MaxTmdsMhz = (hdmi->max_tmds_clock * 5);
} else {
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf(" Maximum TMDS clock....... n/a\r\n");
}
#endif
}
}
if (hdmi->header.length >= HDMI_VSDB_LATENCY_FIELDS_OFFSET) {
if (hdmi->latency_fields) {
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf(" Video latency %s........ %ums\r\n",
hdmi->interlaced_latency_fields ? "(p)" : "...",
(hdmi->video_latency - 1) << 1);
xil_printf(" Audio latency %s........ %ums\r\n",
hdmi->interlaced_latency_fields ? "(p)" : "...",
(hdmi->audio_latency - 1) << 1);
}
#endif
}
if (hdmi->interlaced_latency_fields) {
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf(" Video latency (i)........ %ums\r\n",
hdmi->interlaced_video_latency);
xil_printf(" Audio latency (i)........ %ums\r\n",
hdmi->interlaced_audio_latency);
}
#endif
}
}
} else if (!memcmp(oui, HDMI_OUI_HF, sizeof(oui))) {
const struct xvidc_cea861_hdmi_hf_vendor_specific_data_block * const hdmi =
(struct xvidc_cea861_hdmi_hf_vendor_specific_data_block *) vsdb;
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf(" Version.................. %d\r\n",hdmi->version);
}
#endif
if (hdmi->max_tmds_char_rate) {
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf(" Maximum TMDS clock....... %uMHz\r\n",
hdmi->max_tmds_char_rate * 5);
}
#endif
EdidCtrlParam->MaxTmdsMhz = (hdmi->max_tmds_char_rate * 5);
} else {
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf(" Max. Supp. TMDS clock (<=340MHz)\r\n");
}
#endif
}
if (hdmi->header.length >= HDMI_VSDB_EXTENSION_FLAGS_OFFSET) {
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
#if XVIDC_EDID_VERBOSITY > 1
xil_printf(" RRC Capable Support...... %s\r\n",
hdmi->rr_capable ? "Yes" : "No");
xil_printf(" SCDC Present............. %s\r\n",
hdmi->scdc_present ? "Yes" : "No");
xil_printf(" HDMI1.4 Scramble Support. %s\r\n",
hdmi->lte_340mcsc_scramble ? "Yes" : "No");
#endif
xil_printf(" YUV 420 Deep.C. Support..\r\n");
xil_printf(" Supports 48bpp......... %s\r\n",
hdmi->dc_48bit_yuv420 ? "Yes" : "No");
xil_printf(" Supports 36bpp......... %s\r\n",
hdmi->dc_36bit_yuv420 ? "Yes" : "No");
xil_printf(" Supports 30bpp......... %s\r\n",
hdmi->dc_30bit_yuv420 ? "Yes" : "No");
}
#endif
EdidCtrlParam->IsYCbCr420dc30bppSupp = hdmi->dc_30bit_yuv420;
EdidCtrlParam->IsYCbCr420dc36bppSupp = hdmi->dc_36bit_yuv420;
EdidCtrlParam->IsYCbCr420dc48bppSupp = hdmi->dc_48bit_yuv420;
EdidCtrlParam->IsSCDCReadRequestReady = hdmi->rr_capable;
EdidCtrlParam->IsSCDCPresent = hdmi->scdc_present;
}
}
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf("\r\n");
}
#endif
}
#if XVIDC_EDID_VERBOSITY > 1
/*****************************************************************************/
/**
*
* This function parse EDID on CEA 861 Speaker Allocation
*
* @param data is a pointer to the EDID array.
* @param EdidCtrlParam is a pointer the EDID Control parameter
* @param VerboseEn is a pointer to the XV_HdmiTxSs core instance.
*
* @return None
*
* @note None.
*
******************************************************************************/
static void
xvidc_disp_cea861_speaker_allocation_data(
const struct xvidc_cea861_speaker_allocation_data_block * const sadb,
XV_VidC_EdidCntrlParam *EdidCtrlParam,
XV_VidC_Verbose VerboseEn) {
/* For Future Usage */
EdidCtrlParam = EdidCtrlParam;
const struct xvidc_cea861_speaker_allocation * const sa = &sadb->payload;
const u8 * const channel_configuration = (u8 *) sa;
if (VerboseEn) {
xil_printf("CEA speaker allocation data\r\n");
xil_printf(" Channel configuration.... %u.%u\r\n",
(__builtin_popcountll(channel_configuration[0] & 0xe9) << 1) +
(__builtin_popcountll(channel_configuration[0] & 0x14) << 0) +
(__builtin_popcountll(channel_configuration[1] & 0x01) << 1) +
(__builtin_popcountll(channel_configuration[1] & 0x06) << 0),
(channel_configuration[0] & 0x02));
xil_printf(" Front left/right......... %s\r\n",
sa->front_left_right ? "Yes" : "No");
xil_printf(" Front LFE................ %s\r\n",
sa->front_lfe ? "Yes" : "No");
xil_printf(" Front center............. %s\r\n",
sa->front_center ? "Yes" : "No");
xil_printf(" Rear left/right.......... %s\r\n",
sa->rear_left_right ? "Yes" : "No");
xil_printf(" Rear center.............. %s\r\n",
sa->rear_center ? "Yes" : "No");
xil_printf(" Front left/right center.. %s\r\n",
sa->front_left_right_center ? "Yes" : "No");
xil_printf(" Rear left/right center... %s\r\n",
sa->rear_left_right_center ? "Yes" : "No");
xil_printf(" Front left/right wide.... %s\r\n",
sa->front_left_right_wide ? "Yes" : "No");
xil_printf(" Front left/right high.... %s\r\n",
sa->front_left_right_high ? "Yes" : "No");
xil_printf(" Top center............... %s\r\n",
sa->top_center ? "Yes" : "No");
xil_printf(" Front center high........ %s\r\n",
sa->front_center_high ? "Yes" : "No");
xil_printf("\r\n");
}
}
#endif
/*****************************************************************************/
/**
*
* This function Parse and Display the CEA-861
*
* @param data is a pointer to the EDID array.
* @param EdidCtrlParam is a pointer the EDID Control parameter
* @param VerboseEn is a pointer to the XV_HdmiTxSs core instance.
*
* @return None
*
* @note None.
*
******************************************************************************/
static void
xvidc_disp_cea861(const struct xvidc_edid_extension * const ext,
XV_VidC_EdidCntrlParam *EdidCtrlParam,
XV_VidC_Verbose VerboseEn) {
const struct xvidc_cea861_timing_block * const ctb =
(struct xvidc_cea861_timing_block *) ext;
const u8 offset = offsetof(struct xvidc_cea861_timing_block, data);
u8 index = 0;
#if XVIDC_EDID_VERBOSITY > 1
const struct xvidc_edid_detailed_timing_descriptor *dtd = NULL;
u8 i;
XV_VidC_TimingParam timing_params;
#endif
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf("CEA-861 Information\r\n");
xil_printf(" Revision number.......... %u\r\n",
ctb->revision);
}
#endif
if (ctb->revision >= 2) {
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
#if XVIDC_EDID_VERBOSITY > 1
xil_printf(" IT underscan............. %supported\r\n",
ctb->underscan_supported ? "S" : "Not s");
#endif
xil_printf(" Basic audio.............. %supported\r\n",
ctb->basic_audio_supported ? "S" : "Not s");
xil_printf(" YCbCr 4:4:4.............. %supported\r\n",
ctb->yuv_444_supported ? "S" : "Not s");
xil_printf(" YCbCr 4:2:2.............. %supported\r\n",
ctb->yuv_422_supported ? "S" : "Not s");
#if XVIDC_EDID_VERBOSITY > 1
xil_printf(" Native formats........... %u\r\n",
ctb->native_dtds);
#endif
}
#endif
EdidCtrlParam->IsYCbCr444Supp = ctb->yuv_444_supported;
EdidCtrlParam->IsYCbCr422Supp = ctb->yuv_422_supported;
}
#if XVIDC_EDID_VERBOSITY > 1
dtd = (struct xvidc_edid_detailed_timing_descriptor *)
((u8 *) ctb + ctb->dtd_offset);
for (i = 0; dtd->pixel_clock; i++, dtd++) {
timing_params = XV_VidC_timing(dtd);
if (VerboseEn) {
xil_printf(" Detailed timing #%u....... %ux%u%c at %uHz "
"(%u:%u)\r\n",
i + 1,
timing_params.hres,
timing_params.vres,
timing_params.vidfrmt ? 'i' : 'p',
timing_params.vfreq,
timing_params.aspect_ratio.width,
timing_params.aspect_ratio.height);
xil_printf(
" Modeline............... \"%ux%u\" %u %u %u %u %u %u %u %u %u"
" %chsync %cvsync\r\n",
timing_params.hres,
timing_params.vres,
HZ_2_MHZ (timing_params.pixclk),
(timing_params.hres),
(timing_params.hres + timing_params.hfp),
(timing_params.hres + timing_params.hfp +
timing_params.hsync_width),
(timing_params.htotal),
(timing_params.vres),
(timing_params.vres + timing_params.vfp),
(timing_params.vres + timing_params.vfp +
timing_params.vsync_width),
(timing_params.vtotal),
timing_params.hsync_polarity ? '+' : '-',
timing_params.vsync_polarity ? '+' : '-');
}
}
#endif
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf("\r\n");
}
#endif
if (ctb->revision >= 3) {
do {
const struct xvidc_cea861_data_block_header * const header =
(struct xvidc_cea861_data_block_header *) &ctb->data[index];
switch (header->tag) {
case XVIDC_CEA861_DATA_BLOCK_TYPE_AUDIO:
{
#if XVIDC_EDID_VERBOSITY > 1
const struct xvidc_cea861_audio_data_block * const db =
(struct xvidc_cea861_audio_data_block *) header;
xvidc_disp_cea861_audio_data(db,EdidCtrlParam,VerboseEn);
#endif
}
break;
case XVIDC_CEA861_DATA_BLOCK_TYPE_VIDEO:
{
#if XVIDC_EDID_VERBOSITY > 1
const struct xvidc_cea861_video_data_block * const db =
(struct xvidc_cea861_video_data_block *) header;
xvidc_disp_cea861_video_data(db,EdidCtrlParam,VerboseEn);
#endif
}
break;
case XVIDC_CEA861_DATA_BLOCK_TYPE_VENDOR_SPECIFIC:
{
const struct
xvidc_cea861_vendor_specific_data_block * const db =
(struct xvidc_cea861_vendor_specific_data_block *) header;
xvidc_disp_cea861_vendor_data(db,EdidCtrlParam,VerboseEn);
}
break;
case XVIDC_CEA861_DATA_BLOCK_TYPE_SPEAKER_ALLOCATION:
{
#if XVIDC_EDID_VERBOSITY > 1
const struct
xvidc_cea861_speaker_allocation_data_block * const db =
(struct xvidc_cea861_speaker_allocation_data_block *) header;
xvidc_disp_cea861_speaker_allocation_data(db,
EdidCtrlParam,VerboseEn);
#endif
}
break;
case XVIDC_CEA861_DATA_BLOCK_TYPE_EXTENDED:
{
const struct xvidc_cea861_extended_data_block * const db =
(struct xvidc_cea861_extended_data_block *) header;
xvidc_disp_cea861_extended_data(db,EdidCtrlParam,VerboseEn);
}
break;
default:
#if XVIDC_EDID_VERBOSITY > 1
if (VerboseEn) {
xil_printf("Unknown CEA-861 data block type 0x%02x\r\n",
header->tag);
}
#endif
break;
}
index = index + header->length + sizeof(*header);
} while (index < ctb->dtd_offset - offset);
}
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf("\r\n");
}
#endif
}
/*****************************************************************************/
/**
*
* This structure parse parse EDID routines
*
*
* @note None.
*
******************************************************************************/
static const struct xvidc_edid_extension_handler {
void (* const inf_disp)(const struct xvidc_edid_extension * const,
XV_VidC_EdidCntrlParam *EdidCtrlParam, XV_VidC_Verbose VerboseEn);
} xvidc_edid_extension_handlers[] = {
[XVIDC_EDID_EXTENSION_CEA] = { xvidc_disp_cea861 },
};
/*****************************************************************************/
/**
*
* This function parse and print the EDID of the Sink
*
* @param data is a pointer to the EDID array.
* @param EdidCtrlParam is a pointer the EDID Control parameter
* @param VerboseEn is a pointer to the XV_HdmiTxSs core instance.
*
* @return None
*
* @note None.
*
******************************************************************************/
void
XV_VidC_parse_edid(const u8 * const data,
XV_VidC_EdidCntrlParam *EdidCtrlParam,
XV_VidC_Verbose VerboseEn) {
const struct edid * const edid = (struct edid *) data;
const struct xvidc_edid_extension * const extensions =
(struct xvidc_edid_extension *) (data + sizeof(*edid));
XV_VidC_EdidCtrlParamInit(EdidCtrlParam);
xvidc_disp_edid1(edid,EdidCtrlParam,VerboseEn);
for (u8 i = 0; i < edid->extensions; i++) {
const struct xvidc_edid_extension * const extension = &extensions[i];
const struct xvidc_edid_extension_handler * const handler =
&xvidc_edid_extension_handlers[extension->tag];
if (!handler) {
#if XVIDC_EDID_VERBOSITY > 0
if (VerboseEn) {
xil_printf("WARNING: block %u contains unknown extension "
" (%#04x)\r\n", i, extensions[i].tag);
}
#endif
continue;
}
if (handler->inf_disp) {
(*handler->inf_disp)(extension,EdidCtrlParam,VerboseEn);
}
}
}