diff options
author | Zach Pfeffer <zach.pfeffer@linaro.org> | 2011-06-26 09:39:27 +0100 |
---|---|---|
committer | Andy Green <andy.green@linaro.org> | 2011-06-26 09:39:27 +0100 |
commit | 20b7045046128e5f4e3136008fd1bcac5f732899 (patch) | |
tree | 08507e90285df966b2ab13764888af49b41d84af /drivers | |
parent | ca0fd314c48699d2896fee9cef18043f58e9e831 (diff) |
Subject: [PATCH] hdmi: edid: read the resolution at runtime
Undo the force workaround and parse the returned edid for the correct
timing and resolution.
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/omap2/dss/Makefile | 2 | ||||
-rw-r--r-- | drivers/video/omap2/dss/edid.c | 393 | ||||
-rw-r--r-- | drivers/video/omap2/dss/hdmi.c | 200 |
3 files changed, 592 insertions, 3 deletions
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile index 10d9d3bb3e2..a3c738ea354 100644 --- a/drivers/video/omap2/dss/Makefile +++ b/drivers/video/omap2/dss/Makefile @@ -6,4 +6,4 @@ omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \ - hdmi_omap4_panel.o + hdmi_omap4_panel.o edid.o
\ No newline at end of file diff --git a/drivers/video/omap2/dss/edid.c b/drivers/video/omap2/dss/edid.c new file mode 100644 index 00000000000..48aaea35342 --- /dev/null +++ b/drivers/video/omap2/dss/edid.c @@ -0,0 +1,393 @@ +/* + * linux/drivers/video/omap2/dss/edid.c + * + * Copyright (C) 2009 Texas Instruments + * Author: Mythri P K <mythripk@ti.com> + * With EDID parsing for DVI Monitor from Rob Clark <rob@ti.com> + * + * EDID.c to read the EDID content , given the 256 Bytes EDID. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * 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/>. + * History: + * + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/clk.h> +#include <linux/err.h> + +#include <linux/completion.h> +#include <linux/delay.h> +#include <linux/string.h> +#include <linux/platform_device.h> + +#include <plat/cpu.h> + +#include <linux/slab.h> +#include <linux/cdev.h> +#include <linux/fs.h> +#include <plat/edid.h> + +int get_edid_timing_info(union HDMI_EDID_DTD *edid_dtd, + struct omap_video_timings *timings) +{ + printk("zp: start of %s\n", __FUNCTION__); + + if (edid_dtd->video.pixel_clock) { + struct HDMI_EDID_DTD_VIDEO *vid = &edid_dtd->video; + + timings->pixel_clock = 10 * vid->pixel_clock; + timings->x_res = vid->horiz_active | + (((u16)vid->horiz_high & 0xf0) << 4); + timings->y_res = vid->vert_active | + (((u16)vid->vert_high & 0xf0) << 4); + timings->hfp = vid->horiz_sync_offset | + (((u16)vid->sync_pulse_high & 0xc0) << 2); + timings->hsw = vid->horiz_sync_pulse | + (((u16)vid->sync_pulse_high & 0x30) << 4); + timings->hbp = (vid->horiz_blanking | + (((u16)vid->horiz_high & 0x0f) << 8)) - + (timings->hfp + timings->hsw); + timings->vfp = ((vid->vert_sync_pulse & 0xf0) >> 4) | + ((vid->sync_pulse_high & 0x0f) << 2); + timings->vsw = (vid->vert_sync_pulse & 0x0f) | + ((vid->sync_pulse_high & 0x03) << 4); + timings->vbp = (vid->vert_blanking | + (((u16)vid->vert_high & 0x0f) << 8)) - + (timings->vfp + timings->vsw); + return 0; + } + + switch (edid_dtd->monitor_name.block_type) { + case HDMI_EDID_DTD_TAG_STANDARD_TIMING_DATA: + printk(KERN_INFO "standard timing data\n"); + return 1; + case HDMI_EDID_DTD_TAG_COLOR_POINT_DATA: + printk(KERN_INFO "color point data\n"); + return 1; + case HDMI_EDID_DTD_TAG_MONITOR_NAME: + printk(KERN_INFO "monitor name: %s\n", + edid_dtd->monitor_name.text); + return 1; + case HDMI_EDID_DTD_TAG_MONITOR_LIMITS: + { + int i, max_area = 0; + struct HDMI_EDID_DTD_MONITOR *limits = + &edid_dtd->monitor_limits; + + printk(KERN_INFO "monitor limits\n"); + printk(KERN_INFO " min_vert_freq=%d\n", limits->min_vert_freq); + printk(KERN_INFO " max_vert_freq=%d\n", limits->max_vert_freq); + printk(KERN_INFO " min_horiz_freq=%d\n", + limits->min_horiz_freq); + printk(KERN_INFO " max_horiz_freq=%d\n", + limits->max_horiz_freq); + printk(KERN_INFO " pixel_clock_mhz=%d\n", + limits->pixel_clock_mhz * 10); + + /* find the highest matching resolution (w*h) */ + + /* + * XXX since this is mainly for DVI monitors, should we only + * support VESA timings? My monitor at home would pick + * 1920x1080 otherwise, but that seems to not work well (monitor + * blanks out and comes back, and picture doesn't fill full + * screen, but leaves a black bar on left (native res is + * 2048x1152). However if I only consider VESA timings, it picks + * 1680x1050 and the picture is stable and fills whole screen + */ + for (i = OMAP_HDMI_TIMINGS_VESA_START; + i < OMAP_HDMI_TIMINGS_NB; i++) { + const struct omap_video_timings *t = + hdmi_get_omap_timing(i); + int hz, hscan, pixclock; + int vtotal, htotal; + htotal = t->hbp + t->hfp + t->hsw + t->x_res; + vtotal = t->vbp + t->vfp + t->vsw + t->y_res; + + /* NOTE: We don't support interlaced mode for VESA */ + pixclock = t->pixel_clock * 1000; + hscan = (pixclock + htotal / 2) / htotal; + hscan = (hscan + 500) / 1000 * 1000; + hz = (hscan + vtotal / 2) / vtotal; + hscan /= 1000; + pixclock /= 1000000; + printk(KERN_DEBUG "debug only pixclock=%d, hscan=%d, hz=%d\n", + pixclock, hscan, hz); + if ((pixclock < (limits->pixel_clock_mhz * 10)) && + (limits->min_horiz_freq <= hscan) && + (hscan <= limits->max_horiz_freq) && + (limits->min_vert_freq <= hz) && + (hz <= limits->max_vert_freq)) { + int area = t->x_res * t->y_res; + printk(KERN_INFO " -> %d: %dx%d\n", i, + t->x_res, t->y_res); + if (area > max_area) { + max_area = area; + *timings = *t; + } + } + } + if (max_area) + printk(KERN_INFO "found best resolution: %dx%d\n", + timings->x_res, timings->y_res); + return 0; + } + case HDMI_EDID_DTD_TAG_ASCII_STRING: + printk(KERN_INFO "ascii string: %s\n", edid_dtd->ascii.text); + return 1; + case HDMI_EDID_DTD_TAG_MONITOR_SERIALNUM: + printk(KERN_INFO "monitor serialnum: %s\n", + edid_dtd->monitor_serial_number.text); + return 1; + default: + printk(KERN_INFO "unsupported EDID descriptor block format\n"); + return 1; + } +} + +void get_eedid_timing_info(int current_descriptor_addrs, u8 *edid , + struct omap_video_timings *timings) +{ + timings->x_res = (((edid[current_descriptor_addrs + 4] & 0xF0) << 4) + | edid[current_descriptor_addrs + 2]); + timings->y_res = (((edid[current_descriptor_addrs + 7] & 0xF0) << 4) + | edid[current_descriptor_addrs + 5]); + timings->pixel_clock = ((edid[current_descriptor_addrs + 1] << 8) + | edid[current_descriptor_addrs]); + timings->pixel_clock = 10 * timings->pixel_clock; + timings->hfp = edid[current_descriptor_addrs + 8]; + timings->hsw = edid[current_descriptor_addrs + 9]; + timings->hbp = (((edid[current_descriptor_addrs + 4] & 0x0F) << 8) + | edid[current_descriptor_addrs + 3]) - + (timings->hfp + timings->hsw); + timings->vfp = ((edid[current_descriptor_addrs + 10] & 0xF0) >> 4); + timings->vsw = (edid[current_descriptor_addrs + 10] & 0x0F); + timings->vbp = (((edid[current_descriptor_addrs + 7] & 0x0F) << 8) + | edid[current_descriptor_addrs + 6]) - + (timings->vfp + timings->vsw); +} + +int hdmi_get_datablock_offset(u8 *edid, enum extension_edid_db datablock, + int *offset) +{ + int current_byte, disp, i = 0, length = 0; + + if (edid[0x7e] == 0x00) + return 1; + + disp = edid[(0x80) + 2]; + printk(KERN_DEBUG "Extension block present db %d %x\n", datablock, disp); + if (disp == 0x4) + return 1; + + i = 0x80 + 0x4; + printk(KERN_DEBUG "%x\n", i); + while (i < (0x80 + disp)) { + current_byte = edid[i]; + printk(KERN_DEBUG "i = %x cur_byte = %x (cur_byte & EX_DATABLOCK_TAG_MASK) = %d\n", + i, current_byte, + (current_byte & HDMI_EDID_EX_DATABLOCK_TAG_MASK)); + if ((current_byte >> 5) == datablock) { + *offset = i; + printk(KERN_DEBUG "datablock %d %d\n", + datablock, *offset); + return 0; + } else { + length = (current_byte & + HDMI_EDID_EX_DATABLOCK_LEN_MASK) + 1; + i += length; + } + } + return 1; +} + +int hdmi_get_image_format(u8 *edid, struct image_format *format) +{ + int offset, current_byte, j = 0, length = 0; + enum extension_edid_db vsdb = DATABLOCK_VIDEO; + format->length = 0; + + memset(format->fmt, 0, sizeof(format->fmt)); + if (!hdmi_get_datablock_offset(edid, vsdb, &offset)) { + current_byte = edid[offset]; + length = current_byte & HDMI_EDID_EX_DATABLOCK_LEN_MASK; + + if (length >= HDMI_IMG_FORMAT_MAX_LENGTH) + format->length = HDMI_IMG_FORMAT_MAX_LENGTH; + else + format->length = length; + + for (j = 1 ; j < length ; j++) { + current_byte = edid[offset+j]; + format->fmt[j-1].code = current_byte & 0x7F; + format->fmt[j-1].pref = current_byte & 0x80; + } + } + return 0; +} + +int hdmi_get_audio_format(u8 *edid, struct audio_format *format) +{ + int offset, current_byte, j = 0, length = 0; + enum extension_edid_db vsdb = DATABLOCK_AUDIO; + + format->length = 0; + memset(format->fmt, 0, sizeof(format->fmt)); + + if (!hdmi_get_datablock_offset(edid, vsdb, &offset)) { + current_byte = edid[offset]; + length = current_byte & HDMI_EDID_EX_DATABLOCK_LEN_MASK; + + if (length >= HDMI_AUDIO_FORMAT_MAX_LENGTH) + format->length = HDMI_AUDIO_FORMAT_MAX_LENGTH; + else + format->length = length; + + for (j = 1 ; j < length ; j++) { + if (j%3 == 1) { + current_byte = edid[offset + j]; + format->fmt[j-1].format = current_byte & 0x78; + format->fmt[j-1].num_of_ch = + (current_byte & 0x07) + 1; + } + } + } + return 0; +} + +bool hdmi_has_ieee_id(u8 *edid) +{ + int offset, current_byte, length = 0; + enum extension_edid_db vsdb = DATABLOCK_VENDOR; + u32 hdmi_identifier = 0; + + if (!hdmi_get_datablock_offset(edid, vsdb, &offset)) { + current_byte = edid[offset]; + length = current_byte & HDMI_EDID_EX_DATABLOCK_LEN_MASK; + + if (length < 3) + return 0; + offset++; + hdmi_identifier = edid[offset] | edid[offset+1]<<8 + | edid[offset+2]<<16; + if (hdmi_identifier == HDMI_IEEE_REGISTRATION_ID) + return 1; + + } + return 0; +} + +int hdmi_get_video_svds(u8 *edid, int *offset, int *length) +{ + enum extension_edid_db vdb = DATABLOCK_VIDEO; + if ((offset == NULL) || (length == NULL)) + return 0; + if (!hdmi_get_datablock_offset(edid, vdb, offset)) { + *length = edid[*offset] & HDMI_EDID_EX_DATABLOCK_LEN_MASK; + (*offset)++; + return 1; + } + *length = 0; + *offset = 0; + return 0; +} + +void hdmi_get_av_delay(u8 *edid, struct latency *lat) +{ + int offset, current_byte, length = 0; + enum extension_edid_db vsdb = DATABLOCK_VENDOR; + + if (!hdmi_get_datablock_offset(edid, vsdb, &offset)) { + current_byte = edid[offset]; + length = current_byte & HDMI_EDID_EX_DATABLOCK_LEN_MASK; + if (length >= 8 && ((current_byte + 8) & 0x80)) { + lat->vid_latency = ((current_byte + 8) - 1) * 2; + lat->aud_latency = ((current_byte + 9) - 1) * 2; + } + if (length >= 8 && ((current_byte + 8) & 0xC0)) { + lat->int_vid_latency = ((current_byte + 10) - 1) * 2; + lat->int_aud_latency = ((current_byte + 11) - 1) * 2; + } + } +} + +void hdmi_deep_color_support_info(u8 *edid, struct deep_color *format) +{ + int offset, current_byte, length = 0; + enum extension_edid_db vsdb = DATABLOCK_VENDOR; + memset(format, 0, sizeof(*format)); + + if (!hdmi_get_datablock_offset(edid, vsdb, &offset)) { + current_byte = edid[offset]; + length = current_byte & HDMI_EDID_EX_DATABLOCK_LEN_MASK; + if (length >= 6) { + format->bit_30 = ((current_byte + 6) & 0x10); + format->bit_36 = ((current_byte + 6) & 0x20); + } + if (length >= 7) + format->max_tmds_freq = ((current_byte + 7)) * 5; + } +} + +int hdmi_tv_yuv_supported(u8 *edid) +{ + if (edid[0x7e] != 0x00 && edid[0x83] & 0x30) { + printk(KERN_INFO "YUV supported"); + return 1; + } + return 0; +} + +bool hdmi_s3d_supported(u8 *edid) +{ + bool s3d_support = false; + int offset, current_byte; + if (!hdmi_get_datablock_offset(edid, DATABLOCK_VENDOR, &offset)) { + offset += 8; + current_byte = edid[offset++]; + /*Latency_Fields_Present?*/ + if (current_byte & 0x80) + offset += 2; + /*I_Latency_Fields_Present?*/ + if (current_byte & 0x40) + offset += 2; + /*HDMI_Video_present?*/ + if (current_byte & 0x20) { + current_byte = edid[offset]; + /*3D_Present?*/ + if (current_byte & 0x80) { + printk(KERN_INFO "S3D supported\n"); + s3d_support = true; + } + } + } + return s3d_support; +} + +bool hdmi_ai_supported(u8 *edid) +{ + int offset, current_byte, length = 0; + + if (!hdmi_get_datablock_offset(edid, DATABLOCK_VENDOR, &offset)) { + current_byte = edid[offset]; + length = current_byte & HDMI_EDID_EX_DATABLOCK_LEN_MASK; + if (length < 6) + return false; + offset += 6; + if (edid[offset] & HDMI_EDID_EX_SUPPORTS_AI_MASK) + return true; + } + return false; +} diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 73490cf779a..f4e4b763733 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -37,6 +37,7 @@ #endif #include "dss.h" +#include <plat/edid.h> #include "hdmi.h" static int def_force_hdmi_code = 4; @@ -110,6 +111,50 @@ static const struct hdmi_timings cea_vesa_timings[OMAP_HDMI_TIMINGS_NB] = { { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1} }; +/* All supported timing values that OMAP4 supports */ +static const struct omap_video_timings all_timings_direct[] = { + {640, 480, 25200, 96, 16, 48, 2, 10, 33}, + {1280, 720, 74250, 40, 440, 220, 5, 5, 20}, + {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, + {720, 480, 27000, 62, 16, 60, 6, 9, 30}, + {2880, 576, 108000, 256, 48, 272, 5, 5, 39}, + {1440, 240, 27000, 124, 38, 114, 3, 4, 15}, + {1440, 288, 27000, 126, 24, 138, 3, 2, 19}, + {1920, 540, 74250, 44, 528, 148, 5, 2, 15}, + {1920, 540, 74250, 44, 88, 148, 5, 2, 15}, + {1920, 1080, 148500, 44, 88, 148, 5, 4, 36}, + {720, 576, 27000, 64, 12, 68, 5, 5, 39}, + {1440, 576, 54000, 128, 24, 136, 5, 5, 39}, + {1920, 1080, 148500, 44, 528, 148, 5, 4, 36}, + {2880, 480, 108000, 248, 64, 240, 6, 9, 30}, + {1920, 1080, 74250, 44, 638, 148, 5, 4, 36}, + /* Vesa frome here */ + {640, 480, 25175, 96, 16, 48, 2, 10, 33}, + {800, 600, 40000, 128, 40, 88, 4 , 1, 23}, + {848, 480, 33750, 112, 16, 112, 8 , 6, 23}, + {1280, 768, 79500, 128, 64, 192, 7 , 3, 20}, + {1280, 800, 83500, 128, 72, 200, 6 , 3, 22}, + {1360, 768, 85500, 112, 64, 256, 6 , 3, 18}, + {1280, 960, 108000, 112, 96, 312, 3 , 1, 36}, + {1280, 1024, 108000, 112, 48, 248, 3 , 1, 38}, + {1024, 768, 65000, 136, 24, 160, 6, 3, 29}, + {1400, 1050, 121750, 144, 88, 232, 4, 3, 32}, + {1440, 900, 106500, 152, 80, 232, 6, 3, 25}, + {1680, 1050, 146250, 176 , 104, 280, 6, 3, 30}, + {1366, 768, 85500, 143, 70, 213, 3, 3, 24}, + {1920, 1080, 148500, 44, 88, 148, 5, 4, 36}, + {1280, 768, 68250, 32, 48, 80, 7, 3, 12}, + {1400, 1050, 101000, 32, 48, 80, 4, 3, 23}, + {1680, 1050, 119000, 32, 48, 80, 6, 3, 21}, + {1280, 800, 79500, 32, 48, 80, 6, 3, 14}, + {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, + {1920, 1200, 154000, 32, 48, 80, 6, 3, 26}, + /* supported 3d timings UNDEROVER full frame */ + {1280, 1470, 148350, 40, 110, 220, 5, 5, 20}, + {1280, 1470, 148500, 40, 110, 220, 5, 5, 20}, + {1280, 1470, 148500, 40, 440, 220, 5, 5, 20} +}; + /* * This is a static mapping array which maps the timing values * with corresponding CEA / VESA code @@ -565,6 +610,148 @@ static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) return cm; } + +struct omap_video_timings edid_timings; + +static inline void print_omap_video_timings(struct omap_video_timings *timings) +{ + extern unsigned int dss_debug; + if (dss_debug) { + printk(KERN_INFO "Timing Info:\n"); + printk(KERN_INFO " pixel_clk = %d\n", timings->pixel_clock); + printk(KERN_INFO " x_res = %d\n", timings->x_res); + printk(KERN_INFO " y_res = %d\n", timings->y_res); + printk(KERN_INFO " hfp = %d\n", timings->hfp); + printk(KERN_INFO " hsw = %d\n", timings->hsw); + printk(KERN_INFO " hbp = %d\n", timings->hbp); + printk(KERN_INFO " vfp = %d\n", timings->vfp); + printk(KERN_INFO " vsw = %d\n", timings->vsw); + printk(KERN_INFO " vbp = %d\n", timings->vbp); + } +} + +/* + * Written mainly by 223a4fdb Ricard Neri + * git://git.linaro.org/people/asac/android/kernel/pandroid + */ +static int get_edid_timing_data(struct HDMI_EDID *edid) +{ + u8 i, j, code, offset = 0, addr = 0; + struct hdmi_cm cm; + bool audio_support = false; + int svd_base, svd_length, svd_code, svd_native; + + /* + * Verify if the sink supports audio + */ + /* check if EDID has CEA extension block */ + if ((edid->extension_edid != 0x00)) + /* check if CEA extension block is version 3 */ + if (edid->extention_rev == 3) + /* check if extension block has the IEEE HDMI ID*/ + if (hdmi_has_ieee_id((u8 *)edid)) + /* check if sink supports basic audio */ + if (edid->num_dtd & HDMI_AUDIO_BASIC_MASK) + audio_support = true; + + /* Seach block 0, there are 4 DTDs arranged in priority order */ + for (i = 0; i < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; i++) { + get_edid_timing_info(&edid->DTD[i], &edid_timings); + DSSDBG("Block0 [%d] timings:", i); + print_omap_video_timings(&edid_timings); + cm = hdmi_get_code(&edid_timings); + DSSDBG("Block0[%d] value matches code = %d , mode = %d", + i, cm.code, cm.mode); + if (cm.code == -1) + continue; +/* + if (hdmi.s3d_enabled && s3d_code_cea[cm.code] == -1) + continue; +*/ + /* if sink supports audio, use CEA video timing */ + if (audio_support && !cm.mode) + continue; + hdmi.code = cm.code; + hdmi.mode = cm.mode; + DSSDBG("code = %d , mode = %d", hdmi.code, hdmi.mode); + return 1; + } + /* Search SVDs in block 1 twice: first natives and then all */ + if (edid->extension_edid != 0x00) { + hdmi_get_video_svds((u8 *)edid, &svd_base, &svd_length); + for (j = 1; j >= 0; j--) { + for (i = 0; i < svd_length; i++) { + svd_native = ((u8 *)edid)[svd_base+i] + & HDMI_EDID_EX_VIDEO_NATIVE; + svd_code = ((u8 *)edid)[svd_base+i] + & HDMI_EDID_EX_VIDEO_MASK; + if (svd_code >= ARRAY_SIZE(code_cea)) + continue; + /* Check if this SVD is native*/ + if (!svd_native && j) + continue; + /* Check if this 3D CEA timing is supported*/ +/* + if (hdmi.s3d_enabled && + s3d_code_cea[svd_code] == -1) + continue; +*/ + /* Check if this CEA timing is supported*/ + if (code_cea[svd_code] == -1) + continue; + hdmi.code = svd_code; + hdmi.mode = 1; + return 1; + } + } + } + /* Search DTDs in block1 */ + if (edid->extension_edid != 0x00) { + offset = edid->offset_dtd; + if (offset != 0) + addr = EDID_DESCRIPTOR_BLOCK1_ADDRESS + offset; + for (i = 0; i < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR; i++) { + get_eedid_timing_info(addr, (u8 *)edid, &edid_timings); + addr += EDID_TIMING_DESCRIPTOR_SIZE; + cm = hdmi_get_code(&edid_timings); + DSSDBG("Block1[%d] value matches code = %d , mode = %d", + i, cm.code, cm.mode); + if (cm.code == -1) + continue; +/* + if (hdmi.s3d_enabled && s3d_code_cea[cm.code] == -1) + continue; +*/ + /* if sink supports audio, use CEA video timing */ + if (audio_support && !cm.mode) + continue; + hdmi.code = cm.code; + hdmi.mode = cm.mode; + DSSDBG("code = %d , mode = %d", hdmi.code, hdmi.mode); + return 1; + } + } + /*As last resort, check for best standard timing supported:*/ + if (edid->timing_1 & 0x01) { + DSSDBG("800x600@60Hz\n"); + hdmi.mode = 0; + hdmi.code = 9; + return 1; + } + if (edid->timing_2 & 0x08) { + DSSDBG("1024x768@60Hz\n"); + hdmi.mode = 0; + hdmi.code = 16; + return 1; + } + + hdmi.code = 4; /*setting default value of 640 480 VGA*/ + hdmi.mode = 0; + code = code_vesa[hdmi.code]; + edid_timings = all_timings_direct[code]; + return 1; +} + static void hdmi_read_edid() { int ret = 0; @@ -576,7 +763,8 @@ static void hdmi_read_edid() if (!ret) { if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) { - hdmi.edid_set = true; + if (get_edid_timing_data((struct HDMI_EDID *) hdmi.edid)) + hdmi.edid_set = true; } } else { pr_err("failed to read E-EDID\n"); @@ -1632,7 +1820,8 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev) } #endif - hdmi.code = def_force_hdmi_code; + /* hdmi.code = def_force_hdmi_code; */ + printk("zp: hdmi.code = def_force_hdmi_code"); hdmi.pdata = pdev->dev.platform_data; hdmi.pdev = pdev; @@ -1688,3 +1877,10 @@ void hdmi_uninit_platform_driver(void) { return platform_driver_unregister(&omapdss_hdmihw_driver); } + +const struct omap_video_timings *hdmi_get_omap_timing(int ix) +{ + if (ix < 0 || ix >= ARRAY_SIZE(all_timings_direct)) + return NULL; + return all_timings_direct + ix; +} |