diff options
| author | Ajay Singh Parmar <aparmar@codeaurora.org> | 2016-10-06 18:21:23 -0700 |
|---|---|---|
| committer | Ajay Singh Parmar <aparmar@codeaurora.org> | 2016-10-08 23:12:30 -0700 |
| commit | a03fd4699aa9bc709551f20055ea3240044cef0d (patch) | |
| tree | 8aec2c1ccb53bf28253e6fc500e0807b6fcbe3d7 /drivers/video | |
| parent | 057bdafd976ca7609ed223dbd4473d535bcb6459 (diff) | |
msm: mdss: edid: parse dtd and proper fps and pclk check
Parse the Detailed Timing Descriptors of both EDID blocks for
resolutions. Check if the resolution is already added in local
data base. Also, add tolerance to fps and pclk variations for
a give resolution so that EDID parser can capture all the
resolutions correctly as published by the sink's EDID.
Change-Id: I113988eb21f82eef022723c421b1c1c9d4dead9f
Signed-off-by: Ajay Singh Parmar <aparmar@codeaurora.org>
Diffstat (limited to 'drivers/video')
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_hdmi_edid.c | 170 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_hdmi_util.c | 17 |
2 files changed, 88 insertions, 99 deletions
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_edid.c b/drivers/video/fbdev/msm/mdss_hdmi_edid.c index 4f1435d006b2..2047a047b537 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_edid.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_edid.c @@ -698,7 +698,6 @@ static ssize_t hdmi_edid_sysfs_rda_3d_modes(struct device *dev, } } - DEV_DBG("%s: '%s'\n", __func__, buf); ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n"); return ret; @@ -1567,7 +1566,9 @@ static void hdmi_edid_detail_desc(struct hdmi_edid_ctrl *edid_ctrl, frame_data = (active_h + blank_h) * (active_v + blank_v); if (frame_data) { - int refresh_rate_khz = (pixel_clk * khz_to_hz) / frame_data; + u64 refresh_rate = (u64)pixel_clk * khz_to_hz * khz_to_hz; + + do_div(refresh_rate, frame_data); timing.active_h = active_h; timing.front_porch_h = front_porch_h; @@ -1582,19 +1583,24 @@ static void hdmi_edid_detail_desc(struct hdmi_edid_ctrl *edid_ctrl, (front_porch_v + pulse_width_v); timing.active_low_v = active_low_v; timing.pixel_freq = pixel_clk; - timing.refresh_rate = refresh_rate_khz * khz_to_hz; + timing.refresh_rate = refresh_rate; timing.interlaced = interlaced; timing.supported = true; timing.ar = aspect_ratio_4_3 ? HDMI_RES_AR_4_3 : (aspect_ratio_5_4 ? HDMI_RES_AR_5_4 : HDMI_RES_AR_16_9); - DEV_DBG("%s: new res: %dx%d%s@%dHz\n", __func__, + DEV_DBG("%s: new res: %dx%d%s@%d.%d%d%dHz\n", __func__, timing.active_h, timing.active_v, interlaced ? "i" : "p", - timing.refresh_rate / khz_to_hz); - - rc = hdmi_set_resv_timing_info(&timing); + timing.refresh_rate / khz_to_hz, + (timing.refresh_rate % khz_to_hz) / 100, + (timing.refresh_rate % 100) / 10, + timing.refresh_rate % 10); + + rc = hdmi_get_video_id_code(&timing, NULL); + if (rc < 0) + rc = hdmi_set_resv_timing_info(&timing); } else { DEV_ERR("%s: Invalid frame data\n", __func__); rc = -EINVAL; @@ -1642,6 +1648,7 @@ static void hdmi_edid_add_sink_video_format(struct hdmi_edid_ctrl *edid_ctrl, u32 supported = hdmi_edid_is_mode_supported(edid_ctrl, &timing); struct hdmi_edid_sink_data *sink_data = &edid_ctrl->sink_data; struct disp_mode_info *disp_mode_list = sink_data->disp_mode_list; + u32 i = 0; if (video_format >= HDMI_VFRMT_MAX) { DEV_ERR("%s: video format: %s is not supported\n", __func__, @@ -1653,6 +1660,15 @@ static void hdmi_edid_add_sink_video_format(struct hdmi_edid_ctrl *edid_ctrl, video_format, msm_hdmi_mode_2string(video_format), supported ? "Supported" : "Not-Supported"); + for (i = 0; i < sink_data->num_of_elements; i++) { + u32 vic = disp_mode_list[i].video_format; + + if (vic == video_format) { + DEV_DBG("%s: vic %d already added\n", __func__, vic); + return; + } + } + if (!ret && supported) { /* todo: MHL */ disp_mode_list[sink_data->num_of_elements].video_format = @@ -1970,6 +1986,7 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl) const u8 *svd = NULL; u32 has60hz_mode = false; u32 has50hz_mode = false; + u32 desc_offset = 0; bool read_block0_res = false; struct hdmi_edid_sink_data *sink_data = NULL; @@ -2033,103 +2050,66 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl) if (video_format == HDMI_VFRMT_640x480p60_4_3) has480p = true; } - } else if (!num_of_cea_blocks || read_block0_res) { - /* Detailed timing descriptors */ - u32 desc_offset = 0; - /* - * * Maximum 4 timing descriptor in block 0 - No CEA - * extension in this case - * * EDID_FIRST_TIMING_DESC[0x36] - 1st detailed timing - * descriptor - * * EDID_DETAIL_TIMING_DESC_BLCK_SZ[0x12] - Each detailed - * timing descriptor has block size of 18 - */ - while (4 > i && 0 != edid_blk0[0x36+desc_offset]) { - hdmi_edid_detail_desc(edid_ctrl, - edid_blk0+0x36+desc_offset, - &video_format); - - DEV_DBG("[%s:%d] Block-0 Adding vid fmt = [%s]\n", - __func__, __LINE__, - msm_hdmi_mode_2string(video_format)); - - hdmi_edid_add_sink_video_format(edid_ctrl, - video_format); - - if (video_format == HDMI_VFRMT_640x480p60_4_3) - has480p = true; - - /* Make a note of the preferred video format */ - if (i == 0) { - sink_data->preferred_video_format = - video_format; - } - desc_offset += 0x12; - ++i; - } - } else if (1 == num_of_cea_blocks) { - u32 desc_offset = 0; - - /* - * Read from both block 0 and block 1 - * Read EDID block[0] as above - */ - while (4 > i && 0 != edid_blk0[0x36+desc_offset]) { - hdmi_edid_detail_desc(edid_ctrl, - edid_blk0+0x36+desc_offset, - &video_format); + } - DEV_DBG("[%s:%d] Block-0 Adding vid fmt = [%s]\n", - __func__, __LINE__, - msm_hdmi_mode_2string(video_format)); + i = 0; + /* Read DTD resolutions from block0 */ + while (4 > i && 0 != edid_blk0[0x36+desc_offset]) { + hdmi_edid_detail_desc(edid_ctrl, + edid_blk0+0x36+desc_offset, + &video_format); + + DEV_DBG("[%s:%d] Block-0 Adding vid fmt = [%s]\n", + __func__, __LINE__, + msm_hdmi_mode_2string(video_format)); - hdmi_edid_add_sink_video_format(edid_ctrl, - video_format); + hdmi_edid_add_sink_video_format(edid_ctrl, + video_format); - if (video_format == HDMI_VFRMT_640x480p60_4_3) - has480p = true; + if (video_format == HDMI_VFRMT_640x480p60_4_3) + has480p = true; - /* Make a note of the preferred video format */ - if (i == 0) { - sink_data->preferred_video_format = - video_format; - } - desc_offset += 0x12; - ++i; + /* Make a note of the preferred video format */ + if (i == 0) { + sink_data->preferred_video_format = + video_format; } + desc_offset += 0x12; + ++i; + } - /* - * * Parse block 1 - CEA extension byte offset of first - * detailed timing generation - offset is relevant to - * the offset of block 1 - * * EDID_CEA_EXTENSION_FIRST_DESC[0x82]: Offset to CEA - * extension first timing desc - indicate the offset of - * the first detailed timing descriptor - * * EDID_BLOCK_SIZE = 0x80 Each page size in the EDID ROM - */ - desc_offset = edid_blk1[0x02]; - while (0 != edid_blk1[desc_offset]) { - hdmi_edid_detail_desc(edid_ctrl, - edid_blk1+desc_offset, - &video_format); - - DEV_DBG("[%s:%d] Block-1 Adding vid fmt = [%s]\n", - __func__, __LINE__, - msm_hdmi_mode_2string(video_format)); + /* + * * Parse block 1 - CEA extension byte offset of first + * detailed timing generation - offset is relevant to + * the offset of block 1 + * * EDID_CEA_EXTENSION_FIRST_DESC[0x82]: Offset to CEA + * extension first timing desc - indicate the offset of + * the first detailed timing descriptor + * * EDID_BLOCK_SIZE = 0x80 Each page size in the EDID ROM + */ + desc_offset = edid_blk1[0x02]; + i = 0; + while (!edid_blk1[desc_offset]) { + hdmi_edid_detail_desc(edid_ctrl, + edid_blk1+desc_offset, + &video_format); - hdmi_edid_add_sink_video_format(edid_ctrl, - video_format); - if (video_format == HDMI_VFRMT_640x480p60_4_3) - has480p = true; + DEV_DBG("[%s:%d] Block-1 Adding vid fmt = [%s]\n", + __func__, __LINE__, + msm_hdmi_mode_2string(video_format)); - /* Make a note of the preferred video format */ - if (i == 0) { - sink_data->preferred_video_format = - video_format; - } - desc_offset += 0x12; - ++i; + hdmi_edid_add_sink_video_format(edid_ctrl, + video_format); + if (video_format == HDMI_VFRMT_640x480p60_4_3) + has480p = true; + + /* Make a note of the preferred video format */ + if (i == 0) { + sink_data->preferred_video_format = + video_format; } + desc_offset += 0x12; + ++i; } std_blk = 0; diff --git a/drivers/video/fbdev/msm/mdss_hdmi_util.c b/drivers/video/fbdev/msm/mdss_hdmi_util.c index 9ed909e9a387..7e256fe8296b 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_util.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_util.c @@ -625,7 +625,7 @@ int hdmi_get_video_id_code(struct msm_hdmi_mode_timing_info *timing_in, { int i, vic = -1; struct msm_hdmi_mode_timing_info supported_timing = {0}; - u32 ret; + u32 ret, pclk_delta, pclk, fps_delta, fps; if (!timing_in) { pr_err("invalid input\n"); @@ -633,9 +633,16 @@ int hdmi_get_video_id_code(struct msm_hdmi_mode_timing_info *timing_in, } /* active_low_h, active_low_v and interlaced are not checked against */ - for (i = 0; i < HDMI_VFRMT_MAX; i++) { + for (i = 1; i < HDMI_VFRMT_MAX; i++) { ret = hdmi_get_supported_mode(&supported_timing, ds_data, i); + pclk = supported_timing.pixel_freq; + fps = supported_timing.refresh_rate; + + /* as per standard, 0.5% of deviation is allowed */ + pclk_delta = (pclk / HDMI_KHZ_TO_HZ) * 5; + fps_delta = (fps / HDMI_KHZ_TO_HZ) * 5; + if (ret || !supported_timing.supported) continue; if (timing_in->active_h != supported_timing.active_h) @@ -654,9 +661,11 @@ int hdmi_get_video_id_code(struct msm_hdmi_mode_timing_info *timing_in, continue; if (timing_in->back_porch_v != supported_timing.back_porch_v) continue; - if (timing_in->pixel_freq != supported_timing.pixel_freq) + if (timing_in->pixel_freq < (pclk - pclk_delta) || + timing_in->pixel_freq > (pclk + pclk_delta)) continue; - if (timing_in->refresh_rate != supported_timing.refresh_rate) + if (timing_in->refresh_rate < (fps - fps_delta) || + timing_in->refresh_rate > (fps + fps_delta)) continue; vic = (int)supported_timing.video_format; |
