diff options
Diffstat (limited to 'ANDROID_3.4.5/drivers/video/wmt/parse-edid.c')
-rwxr-xr-x | ANDROID_3.4.5/drivers/video/wmt/parse-edid.c | 1069 |
1 files changed, 0 insertions, 1069 deletions
diff --git a/ANDROID_3.4.5/drivers/video/wmt/parse-edid.c b/ANDROID_3.4.5/drivers/video/wmt/parse-edid.c deleted file mode 100755 index 8bf8da74..00000000 --- a/ANDROID_3.4.5/drivers/video/wmt/parse-edid.c +++ /dev/null @@ -1,1069 +0,0 @@ -/*++ - * linux/drivers/video/wmt/parse-edid.c - * WonderMedia video post processor (VPP) driver - * - * Copyright c 2014 WonderMedia Technologies, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * WonderMedia Technologies, Inc. - * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C ---*/ - -#define PARSE_EDID_C -#undef DEBUG -/* #define DEBUG */ -/* #define DEBUG_DETAIL */ - -#include "vpp.h" -#include "edid.h" -#include "hdmi.h" - -const char edid_v1_header[] = { - 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}; - -const char edid_v1_descriptor_flag[] = { 0x00, 0x00 }; - -#define COMBINE_HI_8LO(hi, lo) \ - ((((unsigned)hi) << 8) | (unsigned)lo) - -#define COMBINE_HI_4LO(hi, lo) \ - ((((unsigned)hi) << 4) | (unsigned)lo) - -#define UPPER_NIBBLE(x) \ - (((128|64|32|16) & (x)) >> 4) - -#define LOWER_NIBBLE(x) \ - ((1|2|4|8) & (x)) - -#define MONITOR_NAME 0xfc -#define MONITOR_LIMITS 0xfd -#define UNKNOWN_DESCRIPTOR -1 -#define DETAILED_TIMING_BLOCK -2 - -struct edid_timing_t edid_establish_timing[] = { - { 800, 600, 60 }, { 800, 600, 56 }, { 640, 480, 75 }, { 640, 480, 72 }, - { 640, 480, 67 }, { 640, 480, 60 }, { 720, 400, 88 }, { 720, 400, 70 }, - { 1280, 1024, 75 }, { 1024, 768, 75 }, { 1024, 768, 70 }, - { 1024, 768, 60 }, { 1024, 768, 87 }, { 832, 624, 75 }, - { 800, 600, 75 }, { 800, 600, 72 }, { 1152, 870, 75 } -}; -int edid_msg_enable; -int edid_disable; -struct edid_parsed_t edid_parsed; - -#undef DBGMSG -#define DBGMSG(fmt, args...) if (edid_msg_enable) \ - DPRINT(fmt, ## args) - -static int block_type(char *block) -{ - if (!memcmp(edid_v1_descriptor_flag, block, 2)) { - /* descriptor */ - if (block[2] != 0) - return UNKNOWN_DESCRIPTOR; - return block[3]; - } - /* detailed timing block */ - return DETAILED_TIMING_BLOCK; -} /* End of block_type() */ - -static char *get_vendor_sign(char *block, char *sign) -{ - unsigned short h; - - /* - 08h WORD big-endian manufacturer ID (see #00136) - bits 14-10: first letter (01h='A', 02h='B', etc.) - bits 9-5: second letter - bits 4-0: third letter - */ - h = COMBINE_HI_8LO(block[0], block[1]); - sign[0] = ((h >> 10) & 0x1f) + 'A' - 1; - sign[1] = ((h >> 5) & 0x1f) + 'A' - 1; - sign[2] = (h & 0x1f) + 'A' - 1; - sign[3] = 0; - return sign; -} /* End of get_vendor_sign() */ - -static char *get_monitor_name(char *block, char *name) -{ -#define DESCRIPTOR_DATA 5 - - char *ptr = block + DESCRIPTOR_DATA; - unsigned i; - - for (i = 0; i < 13; i++, ptr++) { - if (*ptr == 0xa) { - name[i] = 0; - return name; - } - name[i] = *ptr; - } - return name; -} /* End of get_monitor_name() */ - -static int parse_timing_description(char *dtd, struct edid_info_t *info) -{ -#define PIXEL_CLOCK_LO ((unsigned)dtd[0]) -#define PIXEL_CLOCK_HI ((unsigned)dtd[1]) -#define PIXEL_CLOCK (COMBINE_HI_8LO(PIXEL_CLOCK_HI, PIXEL_CLOCK_LO) * 10000) -#define H_ACTIVE_LO ((unsigned)dtd[2]) -#define H_BLANKING_LO ((unsigned)dtd[3]) -#define H_ACTIVE_HI UPPER_NIBBLE((unsigned)dtd[4]) -#define H_ACTIVE COMBINE_HI_8LO(H_ACTIVE_HI, H_ACTIVE_LO) -#define H_BLANKING_HI LOWER_NIBBLE((unsigned)dtd[4]) -#define H_BLANKING COMBINE_HI_8LO(H_BLANKING_HI, H_BLANKING_LO) -#define V_ACTIVE_LO ((unsigned)dtd[5]) -#define V_BLANKING_LO ((unsigned)dtd[6]) -#define V_ACTIVE_HI UPPER_NIBBLE((unsigned)dtd[7]) -#define V_ACTIVE COMBINE_HI_8LO(V_ACTIVE_HI, V_ACTIVE_LO) -#define V_BLANKING_HI LOWER_NIBBLE((unsigned)dtd[7]) -#define V_BLANKING COMBINE_HI_8LO(V_BLANKING_HI, V_BLANKING_LO) -#define H_SYNC_OFFSET_LO ((unsigned)dtd[8]) -#define H_SYNC_WIDTH_LO ((unsigned)dtd[9]) -#define V_SYNC_OFFSET_LO UPPER_NIBBLE((unsigned)dtd[10]) -#define V_SYNC_WIDTH_LO LOWER_NIBBLE((unsigned)dtd[10]) -#define V_SYNC_WIDTH_HI ((unsigned)dtd[11] & (1|2)) -#define V_SYNC_OFFSET_HI (((unsigned)dtd[11] & (4|8)) >> 2) -#define H_SYNC_WIDTH_HI (((unsigned)dtd[11] & (16|32)) >> 4) -#define H_SYNC_OFFSET_HI (((unsigned)dtd[11] & (64|128)) >> 6) -#define V_SYNC_WIDTH COMBINE_HI_4LO(V_SYNC_WIDTH_HI, V_SYNC_WIDTH_LO) -#define V_SYNC_OFFSET COMBINE_HI_4LO(V_SYNC_OFFSET_HI, V_SYNC_OFFSET_LO) -#define H_SYNC_WIDTH COMBINE_HI_4LO(H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO) -#define H_SYNC_OFFSET COMBINE_HI_4LO(H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO) -#define H_SIZE_LO ((unsigned)dtd[12]) -#define V_SIZE_LO ((unsigned)dtd[13]) -#define H_SIZE_HI UPPER_NIBBLE((unsigned)dtd[14]) -#define V_SIZE_HI LOWER_NIBBLE((unsigned)dtd[14]) -#define H_SIZE COMBINE_HI_8LO(H_SIZE_HI, H_SIZE_LO) -#define V_SIZE COMBINE_HI_8LO(V_SIZE_HI, V_SIZE_LO) -#define H_BORDER ((unsigned)dtd[15]) -#define V_BORDER ((unsigned)dtd[16]) -#define FLAGS ((unsigned) dtd[17]) -#define INTERLACED (FLAGS & 128) -#define SYNC_TYPE (FLAGS & 3 << 3) /* bits 4,3 */ -#define SYNC_SEPARATE (3 << 3) -#define HSYNC_POSITIVE (FLAGS & 4) -#define VSYNC_POSITIVE (FLAGS & 2) - - int htotal, vtotal; - int i; - struct fb_videomode *t; - int fps; - int vmul; - - htotal = H_ACTIVE + H_BLANKING; - vtotal = V_ACTIVE + V_BLANKING; - - DBGMSG("Detail Timing: \"%dx%d\"\n", H_ACTIVE, V_ACTIVE); - DBGMSG("\tVfreq %dHz, Hfreq %dkHz\n", - PIXEL_CLOCK / (vtotal * htotal), - PIXEL_CLOCK / (htotal * 1000)); - DBGMSG("\tDotClock\t%d\n", PIXEL_CLOCK / 1000000); - DBGMSG("\tHTimings\t%u %u %u %u\n", H_ACTIVE, - H_ACTIVE + H_SYNC_OFFSET, - H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, - htotal); - - DBGMSG("\tVTimings\t%u %u %u %u\n", V_ACTIVE, - V_ACTIVE + V_SYNC_OFFSET, - V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, - vtotal); - - if (INTERLACED || (SYNC_TYPE == SYNC_SEPARATE)) { - DBGMSG("\tFlags\t%s\"%sHSync\" \"%sVSync\"\n", - INTERLACED ? "\"Interlace\" " : "", - HSYNC_POSITIVE ? "+" : "-", - VSYNC_POSITIVE ? "+" : "-"); - } - - for (i = 0; i < 4; i++) { - t = &info->detail_timing[i]; - if (t->pixclock == 0) - break; - } - - if (i >= 4) { - DBGMSG("*W* slot full\n"); - return 0; - } - - t->pixclock = KHZ2PICOS(PIXEL_CLOCK / 1000); - t->right_margin = H_SYNC_OFFSET; - t->hsync_len = H_SYNC_WIDTH; - t->xres = H_ACTIVE; - t->left_margin = H_BLANKING - (H_SYNC_WIDTH + H_SYNC_OFFSET); - t->vmode = INTERLACED ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED; - vmul = (INTERLACED) ? 2 : 1; - t->lower_margin = V_SYNC_OFFSET * vmul; - t->vsync_len = V_SYNC_WIDTH * vmul; - t->yres = V_ACTIVE * vmul; - t->upper_margin = V_BLANKING - (V_SYNC_WIDTH + V_SYNC_OFFSET); - - fps = vpp_calc_refresh(PIXEL_CLOCK, htotal, vtotal); - t->refresh = fps; - t->sync = HSYNC_POSITIVE ? (FB_SYNC_HOR_HIGH_ACT) : 0; - t->sync |= VSYNC_POSITIVE ? (FB_SYNC_VERT_HIGH_ACT) : 0; - - if (vout_check_ratio_16_9(H_ACTIVE, V_ACTIVE)) - info->option |= EDID_OPT_16_9; -#if 0 - DBGMSG("%dx%d,%d,%s\n", H_ACTIVE, V_ACTIVE, t->pixel_clock, - (info->option & EDID_OPT_16_9) ? "16:9" : "4:3"); -#endif - return 0; -} /* End of parse_timing_description() */ - -static int parse_dpms_capabilities(char flags) -{ -#define DPMS_ACTIVE_OFF (1 << 5) -#define DPMS_SUSPEND (1 << 6) -#define DPMS_STANDBY (1 << 7) - - DBGMSG("# DPMS capabilities: Active off:%s Suspend:%s Standby:%s\n\n", - (flags & DPMS_ACTIVE_OFF) ? "yes" : "no", - (flags & DPMS_SUSPEND) ? "yes" : "no", - (flags & DPMS_STANDBY) ? "yes" : "no"); - return 0; -} /* End of parse_dpms_capabilities() */ - -static int parse_monitor_limits(char *block, struct edid_info_t *info) -{ -#define V_MIN_RATE block[5] -#define V_MAX_RATE block[6] -#define H_MIN_RATE block[7] -#define H_MAX_RATE block[8] -#define MAX_PIXEL_CLOCK (((int)block[9]) * 10) -#define GTF_SUPPORT block[10] - - DBGMSG("Monitor limit\n"); - DBGMSG("\tHorizontal Frequency: %u-%u Hz\n", H_MIN_RATE, H_MAX_RATE); - DBGMSG("\tVertical Frequency: %u-%u kHz\n", V_MIN_RATE, V_MAX_RATE); - if (MAX_PIXEL_CLOCK == 10 * 0xff) { - DBGMSG("\tMax dot clock not given\n"); - } else { - DBGMSG("\tMax dot clock (video bandwidth) %u MHz\n", - (int)MAX_PIXEL_CLOCK); - info->pixel_clock_limit = MAX_PIXEL_CLOCK; - } - - if (GTF_SUPPORT) - DBGMSG("\tEDID version 3 GTF given: contact author\n"); - return 0; -} /* End of parse_monitor_limits() */ - -static int get_established_timing(char *edid, struct edid_info_t *info) -{ - char time_1, time_2; - - time_1 = edid[ESTABLISHED_TIMING_I]; - time_2 = edid[ESTABLISHED_TIMING_II]; - info->establish_timing = time_1 + (time_2 << 8); - - /*--------------------------------------------------------------------- - 35: ESTABLISHED TIMING I - bit 7-0: 720x400@70 Hz, 720x400@88 Hz, 640x480@60 Hz, 640x480@67 Hz, - 640x480@72 Hz, 640x480@75 Hz, 800x600@56 Hz, 800x600@60 Hz - ---------------------------------------------------------------------*/ - DBGMSG("Established Timimgs I: 0x%x\n", time_1); - if (time_1 & 0x80) - DBGMSG("\t%dx%d@%dHz\n", 720, 400, 70); - if (time_1 & 0x40) - DBGMSG("\t%dx%d@%dHz\n", 720, 400, 88); - if (time_1 & 0x20) - DBGMSG("\t%dx%d@%dHz\n", 640, 480, 60); - if (time_1 & 0x10) - DBGMSG("\t%dx%d@%dHz\n", 640, 480, 67); - if (time_1 & 0x08) - DBGMSG("\t%dx%d@%dHz\n", 640, 480, 72); - if (time_1 & 0x04) - DBGMSG("\t%dx%d@%dHz\n", 640, 480, 75); - if (time_1 & 0x02) - DBGMSG("\t%dx%d@%dHz\n", 800, 600, 56); - if (time_1 & 0x01) - DBGMSG("\t%dx%d@%dHz\n", 800, 600, 60); - - /*--------------------------------------------------------------------- - 36: ESTABLISHED TIMING II - bit 7-0: 800x600@72 Hz, 800x600@75 Hz, 832x624@75 Hz, - 1024x768@87 Hz (Interlaced), 1024x768@60 Hz, 1024x768@70 Hz, - 1024x768@75 Hz, 1280x1024@75 Hz - ---------------------------------------------------------------------*/ - DBGMSG("Established Timimgs II: 0x%x\n", time_2); - if (time_2 & 0x80) - DBGMSG("\t%dx%d@%dHz\n", 800, 600, 72); - if (time_2 & 0x40) - DBGMSG("\t%dx%d@%dHz\n", 800, 600, 75); - if (time_2 & 0x20) - DBGMSG("\t%dx%d@%dHz\n", 832, 624, 75); - if (time_2 & 0x10) - DBGMSG("\t%dx%d@%dHz (Interlace)\n", 1024, 768, 87); - if (time_2 & 0x08) - DBGMSG("\t%dx%d@%dHz\n", 1024, 768, 60); - if (time_2 & 0x04) - DBGMSG("\t%dx%d@%dHz\n", 1024, 768, 70); - if (time_2 & 0x02) - DBGMSG("\t%dx%d@%dHz\n", 1024, 768, 75); - if (time_2 & 0x01) - DBGMSG("\t%dx%d@%dHz\n", 1280, 1024, 75); - return 0; -} /* End of get_established_timing() */ - -static int get_standard_timing(char *edid, struct edid_info_t *info) -{ - char *ptr = edid + STANDARD_TIMING_IDENTIFICATION_START; - int h_res, v_res, v_freq; - int byte_1, byte_2, aspect, i; - - /*--------------------------------------------------------------------- - First byte - Horizontal resolution. Multiply by 8, then add 248 for actual value. - Second byte - bit 7-6: Aspect ratio. Actual vertical resolution depends on horizontal - resolution. - 00=16:10, 01=4:3, 10=5:4, 11=16:9 (00=1:1 prior to v1.3) - bit 5-0: Vertical frequency. Add 60 to get actual value. - ---------------------------------------------------------------------*/ - DBGMSG("Standard Timing Identification\n"); - for (i = 0; i < STANDARD_TIMING_IDENTIFICATION_SIZE / 2; i++) { - byte_1 = *ptr++; - byte_2 = *ptr++; - if ((byte_1 == 0x01) && (byte_2 == 0x01)) - break; - h_res = (byte_1 * 8) + 248; - aspect = byte_2 & 0xC0; - switch (aspect) { - default: - case 0x00: - v_res = h_res * 10/16; - break; - case 0x40: - v_res = h_res * 3/4; - break; - case 0x80: - v_res = h_res * 4/5; - break; - case 0xC0: - v_res = h_res * 9/16; - break; - } - v_freq = (byte_2 & 0x1F) + 60; - DBGMSG("\t%dx%d@%dHz\n", h_res, v_res, v_freq); - info->standard_timing[i].resx = h_res; - info->standard_timing[i].resy = v_res; - info->standard_timing[i].freq = v_freq; - } - return 0; -} /* End of get_standard_timing() */ - -static int edid_parse_v1(char *edid, struct edid_info_t *info) -{ - char *block; - char *monitor_name = 0; - char monitor_alt_name[100]; - char vendor_sign[4]; - int i, ret = 0; - - if (edid_checksum(edid, EDID_LENGTH)) { - DBG_ERR("checksum failed\n"); - ret = -1; - goto parse_end; - } - - if (memcmp(edid+EDID_HEADER, edid_v1_header, EDID_HEADER_END+1)) { - DBGMSG("*E* first bytes don't match EDID version 1 header\n"); - ret = -1; - goto parse_end; - } - - if(edid_msg_enable) - edid_dump(edid); - - DBGMSG("[EDID] EDID version: %d.%d\n", - (int)edid[EDID_STRUCT_VERSION], - (int)edid[EDID_STRUCT_REVISION]); - - get_vendor_sign(edid + ID_MANUFACTURER_NAME, (char *) &vendor_sign); - - info->width = edid[EDID_MAX_HOR_IMAGE_SIZE] * 10; - info->height = edid[EDID_MAX_VER_IMAGE_SIZE] * 10; - DBGMSG("[EDID] max hor %d cm ver %d cm\n", info->width, info->height); - - /*--------------------------------------------------------------------- - Parse Monitor name - ---------------------------------------------------------------------*/ - block = edid + DETAILED_TIMING_DESCRIPTIONS_START; - for (i = 0; i < NO_DETAILED_TIMING_DESCRIPTIONS; i++, - block += DETAILED_TIMING_DESCRIPTION_SIZE) { - if (block_type(block) == MONITOR_NAME) { - monitor_name = - get_monitor_name(block, monitor_alt_name); - break; - } - } - - if (!monitor_name) { - /* Stupid djgpp hasn't snDBGMSG so we have to - hack something together */ - if (strlen(vendor_sign) + 10 > sizeof(monitor_alt_name)) - vendor_sign[3] = 0; - - sprintf(monitor_alt_name, "%s:%02x%02x", - vendor_sign, edid[ID_MODEL], edid[ID_MODEL+1]); - monitor_name = monitor_alt_name; - } - - DBGMSG("Identifier \"%s\"\n", monitor_name); - DBGMSG("VendorName \"%s\"\n", vendor_sign); - DBGMSG("ModelName \"%s\"\n", monitor_name); - - memset(edid_parsed.tv_name.vendor_name, 0, sizeof(edid_parsed.tv_name.vendor_name)); - strcpy(edid_parsed.tv_name.vendor_name, vendor_sign); - - memset(edid_parsed.tv_name.monitor_name, 0, sizeof(edid_parsed.tv_name.monitor_name)); - if (strlen(monitor_name) < MONITOR_NAME_LEN) - strcpy(edid_parsed.tv_name.monitor_name, monitor_name); - else - strncpy(edid_parsed.tv_name.monitor_name, monitor_name, MONITOR_NAME_LEN - 1); - - parse_dpms_capabilities(edid[DPMS_FLAGS]); - - /*--------------------------------------------------------------------- - Parse ESTABLISHED TIMING I and II - ---------------------------------------------------------------------*/ - get_established_timing(edid, info); - - /*--------------------------------------------------------------------- - Parse STANDARD TIMING IDENTIFICATION - ---------------------------------------------------------------------*/ - get_standard_timing(edid, info); - - block = edid + DETAILED_TIMING_DESCRIPTIONS_START; - for (i = 0; i < NO_DETAILED_TIMING_DESCRIPTIONS; i++, - block += DETAILED_TIMING_DESCRIPTION_SIZE) { - if (block_type(block) == MONITOR_LIMITS) - parse_monitor_limits(block, info); - } - - block = edid + DETAILED_TIMING_DESCRIPTIONS_START; - for (i = 0; i < NO_DETAILED_TIMING_DESCRIPTIONS; i++, - block += DETAILED_TIMING_DESCRIPTION_SIZE) { - if (block_type(block) == DETAILED_TIMING_BLOCK) - parse_timing_description(block, info); - } -parse_end: - return ret; -} - -void edid_parse_CEA_VendorSpecDataBlock(char *block, int len, - struct edid_info_t *info) -{ - int index; - char temp; - - DBGMSG("Vendor Spec Data Block\n"); - if (len < 5) /* min size */ - return; - /* IEEE Registration Identifier 0x000C03 */ - if ((block[1] == 0x03) && (block[2] == 0x0C) && - (block[3] == 0x0)) { - info->option |= EDID_OPT_HDMI; - DBGMSG("\t support HDMI\n"); - } - DBGMSG("\t Source Physical Addr %d.%d.%d.%d\n", - (block[4] & 0xF0) >> 4, block[4] & 0x0F, - (block[5] & 0xF0) >> 4, block[5] & 0x0F); - info->hdmi_phy_addr = (block[4] << 8) + block[5]; - - /* extersion fields */ - if (len < 8) - return; - DBGMSG("\t%s support AI\n", - (block[6] & 0x80) ? "" : "no"); - DBGMSG("\t%s support 30 bits/pixel(10 bits/color)\n", - (block[6] & 0x40) ? "" : "no"); - DBGMSG("\t%s support 36 bits/pixel(12 bits/color)\n", - (block[6] & 0x20) ? "" : "no"); - DBGMSG("\t%s support 48 bits/pixel(16 bits/color)\n", - (block[6] & 0x10) ? "" : "no"); - DBGMSG("\t%s support YUV444 in Deep Color mode\n", - (block[6] & 0x08) ? "" : "no"); - DBGMSG("\t%s support DVI dual-link\n", - (block[6] & 0x01) ? "" : "no"); - DBGMSG("\tMax TMDS Clock %d MHz\n", block[7] * 5); - temp = block[8]; - index = 9; - - if (temp & BIT(7)) { - DBGMSG("\tVideo Latency %d,Audio Latency %d\n", - block[index], block[index+1]); - index += 2; - } - - if (temp & BIT(6)) { - DBGMSG("\tInterlaced Video Latency %d,Audio Latency %d\n", - block[index], block[index+1]); - index += 2; - } - - if (temp & BIT(5)) { - int hdmi_xx_len, hdmi_3d_len; - - DBGMSG("\tHDMI Video present\n"); - temp = block[index]; - if (temp & 0x80) - DBGMSG("\t\t3D present support Mandatory formats\n"); - if (temp & 0x60) - DBGMSG("\t\t3D Multi present %d\n", (temp & 0x60) >> 5); - DBGMSG("\t\tImage size %d\n", (temp & 0x18) >> 3); - hdmi_xx_len = (block[index + 1] & 0xE0) >> 5; - hdmi_3d_len = block[index + 1] & 0x1F; - DBGMSG("\t\thdmi_xx_len %d,hdmi_3d_len %d\n", - hdmi_xx_len, hdmi_3d_len); - index += 2; - - if (hdmi_xx_len) { - /* Refer to HDMI Spec Ver 1.4a */ - index += hdmi_xx_len; - } - - if (hdmi_3d_len) { - int struct_all_3d = 0; - int mask_3d = 0xFF; - int vic_order_2d; - char struct_3d, detail_3d; - int i; - - hdmi_3d_len += index; - switch (temp & 0x60) { - case 0x40: - struct_all_3d = (block[index] << 8) + - block[index + 1]; - mask_3d = (block[index + 2] << 8) + - block[index + 3]; /* 3D support mask */ - DBGMSG("\t\t3D struct 0x%x,mask 0x%x\n", - struct_all_3d, mask_3d); - index += 4; - break; - case 0x20: - struct_all_3d = (block[index] << 8) + - block[index + 1]; - DBGMSG("\t\t3D struct 0x%x\n", struct_all_3d); - index += 2; - break; - default: - break; - } - /* 3D support type */ - if (struct_all_3d & BIT0) - DBGMSG("\t\tSupport Frame packing\n"); - if (struct_all_3d & BIT6) - DBGMSG("\t\tSupport Top and Bottom\n"); - if (struct_all_3d & BIT8) - DBGMSG("\t\tSupport Side by Side\n"); - - for (i = 0; i < 16; i++) { - if (mask_3d & (0x1 << i)) - info->vic_3d[i].mask = struct_all_3d; - } - - DBGMSG("\t\t[3D Structure type 0-Frame packing"); - DBGMSG(",6-Top and Bottom,8-Side by Side]\n"); - while (index < hdmi_3d_len) { - vic_order_2d = (block[index] & 0xF0) >> 4; - struct_3d = block[index] & 0x0F; - index++; - if (struct_3d & 0x8) { - detail_3d = (block[index] & 0xF0) >> 4; - index++; - } else { - detail_3d = 0; - } - info->vic_3d[vic_order_2d].mask |= - (0x1 << struct_3d); - DBGMSG("\t\tVIC %d,3D struct %d,detail %d\n", - vic_order_2d, struct_3d, detail_3d); - } - } - } -} - -static int edid_parse_CEA(char *edid, struct edid_info_t *info) -{ - char *block, *block_end; - char checksum = 0; - int i, len; - char audio_format; - int num = 0, sadcnt_in_block; - - memset(edid_parsed.sad, 0, sizeof(edid_parsed.sad)); - - if (edid[0] != 0x2) - return -1; - - for (i = 0; i < EDID_LENGTH; i++) - checksum += edid[i]; - - if (checksum != 0) { - DPRINT("*E* CEA EDID checksum (0x%02x) - data is corrupt\n", - checksum); - info->option |= (EDID_OPT_HDMI + EDID_OPT_AUDIO); - edid_dump(edid); - return -1; - } - - if(edid_msg_enable) - edid_dump(edid); - - DBGMSG("[EDID] CEA EDID Version %d.%d\n", edid[0], edid[1]); - - if (edid[1] >= 2) { - info->option |= (edid[3] & 0xF0); - DBGMSG("\t%s support 422\n", (edid[3] & 0x10) ? "" : "no"); - DBGMSG("\t%s support 444\n", (edid[3] & 0x20) ? "" : "no"); - DBGMSG("\t%s support audio\n", (edid[3] & 0x40) ? "" : "no"); - DBGMSG("\t%s support underscan\n", - (edid[3] & 0x80) ? "" : "no"); - } - - block_end = edid + edid[2]; - block = edid + 4; - do { - len = block[0] & 0x1F; - switch (((block[0] & 0xE0) >> 5)) { - case 1: /* Audio Data Block */ - DBGMSG("Audio Data Block (0x%02X)\n", block[0]); - info->option |= EDID_OPT_AUDIO; - sadcnt_in_block = len / 3; - - for (i = 0; i < sadcnt_in_block; i++) { - if (num < AUD_SAD_NUM) { - edid_parsed.sad[num].flag = 1; - edid_parsed.sad[num].sad_byte[0] = - block[i * 3 + 1]; - edid_parsed.sad[num].sad_byte[1] = - block[i * 3 + 2]; - edid_parsed.sad[num].sad_byte[2] = - block[i * 3 + 3]; - num++; - } else { - DPRINT("Lose SAD info:%02X %02X %02X\n", - block[i * 3 + 1], - block[i * 3 + 2], - block[i * 3 + 3]); - } - - DBGMSG("\t ======== SDA %d ========\n", i); - DBGMSG("\t SDA Data: 0x%02X 0x%02X 0x%02X\n", - block[i * 3 + 1], - block[i * 3 + 2], - block[i * 3 + 3]); - - audio_format = (block[i * 3 + 1] & 0x78) >> 3; - switch (audio_format) { - default: - case 0: /* reserved */ - case 15:/* reserved */ - DBGMSG("\t Reserved Audio Fmt\n"); - break; - case 1: /* LPCM */ - DBGMSG("\t Audio Fmt: LPCM\n"); - break; - case 2: /* AC3 */ - DBGMSG("\t Audio Fmt: AC3\n"); - break; - case 3: /* MPEG1 */ - DBGMSG("\t Audio Fmt: MPEG1\n"); - break; - case 4: /* MP3 */ - DBGMSG("\t Audio Fmt: MP3\n"); - break; - case 5: /* MPEG2 */ - DBGMSG("\t Audio Fmt: MPEG2\n"); - break; - case 6: /* AAC */ - DBGMSG("\t Audio Fmt: AAC\n"); - break; - case 7: /* DTS */ - DBGMSG("\t Audio Fmt: DTS\n"); - break; - case 8: /* ATRAC */ - DBGMSG("\t Audio Fmt: ATRAC\n"); - break; - case 9: /* One bit audio */ - DBGMSG("\t Audio Fmt: ONE BIT AUDIO\n"); - break; - case 10:/* Dolby */ - DBGMSG("\t Audio Fmt: DOLBY\n"); - break; - case 11:/* DTS-HD */ - DBGMSG("\t Audio Fmt: DTS-HD\n"); - break; - case 12:/* MAT (MLP) */ - DBGMSG("\t Audio Fmt: MAT\n"); - break; - case 13:/* DST */ - DBGMSG("\t Audio Fmt: DST\n"); - break; - case 14:/* WMA Pro */ - DBGMSG("\t Audio Fmt: WMA Pro\n"); - break; - } - - DBGMSG("\t Max channel: %d\n", - (block[i * 3 + 1] & 0x7) + 1); - DBGMSG("\t %s support 32 KHz\n", - (block[i * 3 + 2] & 0x1) ? "" : "no"); - DBGMSG("\t %s support 44 KHz\n", - (block[i * 3 + 2] & 0x2) ? "" : "no"); - DBGMSG("\t %s support 48 KHz\n", - (block[i * 3 + 2] & 0x4) ? "" : "no"); - DBGMSG("\t %s support 88 KHz\n", - (block[i * 3 + 2] & 0x8) ? "" : "no"); - DBGMSG("\t %s support 96 KHz\n", - (block[i * 3 + 2] & 0x10) ? "" : "no"); - DBGMSG("\t %s support 176 KHz\n", - (block[i * 3 + 2] & 0x20) ? "" : "no"); - DBGMSG("\t %s support 192 KHz\n", - (block[i * 3 + 2] & 0x40) ? "" : "no"); - if (audio_format == 1) { /* For LPCM */ - DBGMSG("\t %s support 16 bit\n", - (block[i * 3 + 3] & 0x1) ? - "" : "no"); - DBGMSG("\t %s support 20 bit\n", - (block[i * 3 + 3] & 0x2) ? - "" : "no"); - DBGMSG("\t %s support 24 bit\n", - (block[i * 3 + 3] & 0x4) ? - "" : "no"); - } else if (audio_format >= 2 && - audio_format <= 8) { - /* From AC3 to ATRAC */ - DBGMSG("\t Max bitrate: %d kbit/s\n", - block[i * 3 + 3] * 8); - } else if (audio_format >= 9 && - audio_format <= 14) { - /* From One-bit-audio to WMA Pro*/ - DBGMSG("\t Audio Format Code:0x%02X\n", - block[i * 3 + 3]); - } - DBGMSG("\t ========================\n"); - } - break; - case 2: /* Video Data Block */ - DBGMSG("Video Data Block\n"); - for (i = 0; i < len; i++) { - unsigned int vic; - - vic = block[1 + i] & 0x7F; - info->cea_vic[vic / 8] |= (0x1 << (vic % 8)); - if (i < 16) - info->vic_3d[i].vic = vic; - DBGMSG("\t %2d : VIC %2d %dx%d@%d%s %s\n", i, - vic, hdmi_vic_info[vic].resx, - hdmi_vic_info[vic].resy, - hdmi_vic_info[vic].freq, - (hdmi_vic_info[vic].option - & HDMI_VIC_INTERLACE) ? "I" : "P", - (hdmi_vic_info[vic].option - & HDMI_VIC_4x3) ? "4:3" : "16:9"); - } - break; - case 3: /* Vendor Spec Data Block */ - edid_parse_CEA_VendorSpecDataBlock(block, len, info); - break; - case 4: /* Speaker Allocation Data Block */ - DBGMSG("Speaker Allocation Data Block\n"); - break; - case 5: /* VESA DTC Data Block */ - DBGMSG("VESA DTC Data Block\n"); - break; - case 7: /* Use Extended Tag */ - DBGMSG("Use Extended Tag\n"); - break; - case 0: /* Reserved */ - default: - len = 0; - break; - } - block += (1 + len); - } while (block < block_end); - - { - struct fb_videomode *p; - unsigned int fps; - - DBGMSG("Detail Timing\n"); - block = edid + edid[2]; - len = (128 - edid[2]) / 18; - for (i = 0; i < len; i++, block += 18) { - p = &info->cea_timing[i]; - p->pixclock = ((block[1] << 8) + block[0]) * 10000; - if (p->pixclock == 0) - break; - p->xres = ((block[4] & 0xF0) << 4) + block[2]; - p->left_margin = ((block[4] & 0x0F) << 8) + block[3]; - p->yres = ((block[7] & 0xF0) << 4) + block[5]; - p->upper_margin = ((block[7] & 0x0F) << 8) + block[6]; - fps = vpp_calc_refresh(p->pixclock, p->xres + p->left_margin, - p->yres + p->upper_margin); - p->right_margin = ((block[11] & 0xC0) << 2) + block[8]; - p->hsync_len = ((block[11] & 0x30) << 4) + block[9]; - p->left_margin = p->left_margin - - p->right_margin - p->hsync_len; - p->lower_margin = ((block[11] & 0x0C) << 2) + - ((block[10] & 0xF0) >> 4); - p->vsync_len = ((block[11] & 0x03) << 4) + (block[10] & 0x0F); - p->upper_margin = p->upper_margin - - p->lower_margin - p->vsync_len; - p->refresh = fps; - p->vmode = (block[17] & 0x80) ? - FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED; - p->sync = (block[17] & 0x04) ? FB_SYNC_VERT_HIGH_ACT : 0; - p->sync |= (block[17] & 0x02) ? FB_SYNC_HOR_HIGH_ACT : 0; - if (p->vmode & FB_VMODE_INTERLACED) { - p->yres *= 2; - p->upper_margin *= 2; - p->lower_margin *= 2; - p->vsync_len *= 2; - } - DBGMSG("\t%dx%d%s@%d,clk %d\n", p->xres, p->yres, - (block[17] & 0x80) ? "I" : "P", fps, p->pixclock); - DBGMSG("\t\tH bp %d,sync %d,fp %d\n", - p->left_margin, p->hsync_len, p->right_margin); - DBGMSG("\t\tV bp %d,sync %d,fp %d\n", - p->upper_margin, p->vsync_len, p->lower_margin); - DBGMSG("\t\thsync %d,vsync %d\n", - (p->sync & FB_SYNC_HOR_HIGH_ACT) ? 1 : 0, - (p->sync & FB_SYNC_VERT_HIGH_ACT) ? 1 : 0); - p->pixclock = KHZ2PICOS(p->pixclock / 1000); - } - } - return 0; -} - -void edid_dump(char *edid) -{ - int i; - - DPRINT("===================== EDID BlOCK ====================="); - for (i = 0; i < 128; i++) { - if ((i % 16) == 0) - DPRINT("\n"); - DPRINT("%02x ", edid[i]); - } - DPRINT("\n"); - DPRINT("======================================================\n"); -} - -int edid_checksum(char *edid, int len) -{ - char checksum = 0; - int i; - - for (i = 0; i < len; i++) - checksum += edid[i]; - - if (checksum) { -#ifdef DEBUG - edid_dump(edid); -#endif - } - return checksum; -} - -int edid_parse(char *edid, struct edid_info_t *info) -{ - int ext_cnt = 0; - - if (edid == 0) - return 0; - - if (info->option & EDID_OPT_VALID) { - DBG_MSG("[EDID] parse exist\n"); - return info->option; - } - - DBG_MSG("[EDID] Enter\n"); - - memset(info, 0, sizeof(struct edid_info_t)); - info->option = EDID_OPT_VALID; - if (edid_parse_v1(edid, info) == 0) { - ext_cnt = edid[0x7E]; - if (ext_cnt >= EDID_BLOCK_MAX) { - DPRINT("[EDID] *W* ext block cnt %d\n", ext_cnt); - ext_cnt = EDID_BLOCK_MAX - 1; - } - } else { - info->option = 0; - return 0; - } - - while (ext_cnt) { - edid += 128; - ext_cnt--; - if (edid_parse_CEA(edid, info) == 0) - continue; - - DPRINT("*W* not support EDID\n"); - edid_dump(edid); - } - return info->option; -} - -int edid_find_support(struct edid_info_t *info, unsigned int resx, - unsigned int resy, int freq, struct fb_videomode **vmode) -{ - struct fb_videomode *p; - int temp; - int ret; - int i; - - ret = 0; - *vmode = 0; - - if (!info) - return 0; - - /* find detail timing */ - for (i = 0; i < 4; i++) { - p = &info->detail_timing[i]; - if (p->pixclock == 0) - continue; - if (resx != p->xres) - continue; - if (resy != p->yres) - continue; - - temp = p->refresh; - temp |= (p->vmode & FB_VMODE_INTERLACED) ? - EDID_TMR_INTERLACE : 0; - if (freq != temp) - continue; - *vmode = p; - ret = 3; - goto find_end; - } - - /* find cea timing */ - for (i = 0; i < 6; i++) { - p = &info->cea_timing[i]; - - if (p->pixclock == 0) - continue; - if (resx != p->xres) - continue; - if (resy != p->yres) - continue; - - temp = p->refresh; - temp |= (p->vmode & FB_VMODE_INTERLACED) ? - EDID_TMR_INTERLACE : 0; - if (freq != temp) - continue; - - *vmode = p; - ret = 4; - goto find_end; - } - - /* find vic timing */ - for (i = 0; i < 64; i++) { - if ((info->cea_vic[i / 8] & (0x1 << (i % 8))) == 0) - continue; - - if (i >= HDMI_VIDEO_CODE_MAX) - continue; - - if (resx != hdmi_vic_info[i].resx) - continue; - if (resy != hdmi_vic_info[i].resy) - continue; - temp = hdmi_vic_info[i].freq; - temp |= (hdmi_vic_info[i].option & HDMI_VIC_INTERLACE) ? - EDID_TMR_INTERLACE : 0; - if (freq != temp) - continue; - ret = 5; - goto find_end; - } - - /* find established timing */ - if (info->establish_timing) { - for (i = 0; i < 17; i++) { - if (info->establish_timing & (0x1 << i)) { - if ((resx == edid_establish_timing[i].resx) && - (resy == edid_establish_timing[i].resy)) { - if (freq == - edid_establish_timing[i].freq) { - ret = 1; - goto find_end; - } - } - } - } - } - - /* find standard timing */ - for (i = 0; i < 8; i++) { - if (info->standard_timing[i].resx == 0) - continue; - if ((resx == info->standard_timing[i].resx) && - (resy == info->standard_timing[i].resy)) { - if (freq == info->standard_timing[i].freq) { - ret = 2; - goto find_end; - } - } - } - -find_end: -#if 0 - if ((resx == 1920) && (resy == 1080) && !(freq & EDID_TMR_INTERLACE)) - ret = 0; -#endif -#if 0 - if (!(freq & EDID_TMR_INTERLACE)) - ret = 0; -#endif -#if 0 - DPRINT("[EDID] %s support %dx%d@%d%s(ret %d)\n", - (ret) ? "" : "No", resx, resy, freq & EDID_TMR_FREQ, - (freq & EDID_TMR_INTERLACE) ? "I" : "P", ret); -#endif - return ret; -} - -unsigned int edid_get_hdmi_phy_addr(void) -{ - struct vout_t *vo; - - vo = vout_get_entry(VPP_VOUT_NUM_HDMI); - return vo->edid_info.hdmi_phy_addr; -} - -unsigned int edid_get_hdmi_3d_mask(struct edid_info_t *info, int vic) -{ - int i; - - if (!info) - return 0; - for (i = 0; i < 16; i++) { - if (info->vic_3d[i].vic == vic) - return info->vic_3d[i].mask; - } - return 0; -} - |