diff options
author | Ajay Singh Parmar <aparmar@codeaurora.org> | 2015-08-28 23:10:32 -0700 |
---|---|---|
committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:45:21 -0700 |
commit | 746fd7db83461d54a340c061a2870ecf3a952a8a (patch) | |
tree | f1cf9053c2c7f69f56bd51a9406febf8f7516767 /drivers | |
parent | 559d29938bf6aa7c377f967195b89f6775dc8491 (diff) |
msm: mdss: hdmi: add support to dynamically add new resolutions
Add sysfs node to allow adding new resolution to the resolutions
database and let the system configure to that resolution.
Change-Id: I881be3cf9a441502e25c7501ea5d5cf456f2f58e
Signed-off-by: Ajay Singh Parmar <aparmar@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/fbdev/msm/mdss_hdmi_edid.c | 75 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/mdss_hdmi_util.c | 15 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/mdss_hdmi_util.h | 1 |
3 files changed, 90 insertions, 1 deletions
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_edid.c b/drivers/video/fbdev/msm/mdss_hdmi_edid.c index 277ebc7f1671..25f58db02a9e 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_edid.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_edid.c @@ -132,6 +132,7 @@ struct hdmi_edid_ctrl { int sadb_size; u8 edid_buf[MAX_EDID_SIZE]; char vendor_id[EDID_VENDOR_ID_SIZE]; + bool keep_resv_timings; struct hdmi_edid_sink_data sink_data; struct hdmi_edid_init_data init_data; @@ -176,7 +177,8 @@ static int hdmi_edid_reset_parser(struct hdmi_edid_ctrl *edid_ctrl) edid_ctrl->sadb_size = 0; /* reset new resolution details */ - hdmi_reset_resv_timing_info(); + if (!edid_ctrl->keep_resv_timings) + hdmi_reset_resv_timing_info(); return 0; } @@ -573,6 +575,60 @@ static ssize_t hdmi_common_rda_edid_raw_data(struct device *dev, } /* hdmi_common_rda_edid_raw_data */ static DEVICE_ATTR(edid_raw_data, S_IRUGO, hdmi_common_rda_edid_raw_data, NULL); +static ssize_t hdmi_edid_sysfs_wta_add_resolution(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int rc; + ssize_t ret = strnlen(buf, PAGE_SIZE); + struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev); + struct msm_hdmi_mode_timing_info timing; + + if (!edid_ctrl) { + DEV_ERR("%s: invalid input\n", __func__); + return -EINVAL; + } + + rc = sscanf(buf, + "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", + (unsigned long *) &timing.active_h, + (unsigned long *) &timing.front_porch_h, + (unsigned long *) &timing.pulse_width_h, + (unsigned long *) &timing.back_porch_h, + (unsigned long *) &timing.active_low_h, + (unsigned long *) &timing.active_v, + (unsigned long *) &timing.front_porch_v, + (unsigned long *) &timing.pulse_width_v, + (unsigned long *) &timing.back_porch_v, + (unsigned long *) &timing.active_low_v, + (unsigned long *) &timing.pixel_freq, + (unsigned long *) &timing.refresh_rate, + (unsigned long *) &timing.interlaced, + (unsigned long *) &timing.supported, + (unsigned long *) &timing.ar); + + if (rc != 15) { + DEV_ERR("%s: error reading buf\n", __func__); + goto err; + } + + rc = hdmi_set_resv_timing_info(&timing); + + if (!IS_ERR_VALUE(rc)) { + DEV_DBG("%s: added new res %d\n", __func__, rc); + } else { + DEV_ERR("%s: error adding new res %d\n", __func__, rc); + goto err; + } + + edid_ctrl->keep_resv_timings = true; + return ret; + +err: + edid_ctrl->keep_resv_timings = false; + return -EFAULT; +} +static DEVICE_ATTR(add_res, S_IWUSR, NULL, hdmi_edid_sysfs_wta_add_resolution); + static struct attribute *hdmi_edid_fs_attrs[] = { &dev_attr_edid_modes.attr, &dev_attr_pa.attr, @@ -584,6 +640,7 @@ static struct attribute *hdmi_edid_fs_attrs[] = { &dev_attr_edid_audio_latency.attr, &dev_attr_edid_video_latency.attr, &dev_attr_res_info.attr, + &dev_attr_add_res.attr, NULL, }; @@ -1942,6 +1999,19 @@ end: return ret; } +static void hdmi_edid_add_resv_timings(struct hdmi_edid_ctrl *edid_ctrl) +{ + int i = HDMI_VFRMT_RESERVE1; + + while (i <= RESERVE_VFRMT_END) { + if (hdmi_is_valid_resv_timing(i)) + hdmi_edid_add_sink_video_format(edid_ctrl, i); + else + break; + i++; + } +} + int hdmi_edid_parser(void *input) { u8 *edid_buf = NULL; @@ -2022,6 +2092,9 @@ bail: hdmi_edid_get_display_mode(edid_ctrl); + if (edid_ctrl->keep_resv_timings) + hdmi_edid_add_resv_timings(edid_ctrl); + return 0; err_invalid_header: diff --git a/drivers/video/fbdev/msm/mdss_hdmi_util.c b/drivers/video/fbdev/msm/mdss_hdmi_util.c index 1f0e43304c91..7f4ab5817d8d 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_util.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_util.c @@ -114,6 +114,21 @@ int hdmi_set_resv_timing_info(struct msm_hdmi_mode_timing_info *mode) return -ENOMEM; } +bool hdmi_is_valid_resv_timing(int mode) +{ + struct msm_hdmi_mode_timing_info *info; + + if (mode < HDMI_VFRMT_RESERVE1 || mode > RESERVE_VFRMT_END) { + DEV_ERR("%s: invalid mode %d\n", __func__, mode); + return false; + } + + info = &hdmi_resv_timings[mode - HDMI_VFRMT_RESERVE1]; + + return info->video_format >= HDMI_VFRMT_RESERVE1 && + info->video_format <= RESERVE_VFRMT_END; +} + void hdmi_reset_resv_timing_info(void) { int i; diff --git a/drivers/video/fbdev/msm/mdss_hdmi_util.h b/drivers/video/fbdev/msm/mdss_hdmi_util.h index 56ebfdb4e808..b69bd85b8064 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_util.h +++ b/drivers/video/fbdev/msm/mdss_hdmi_util.h @@ -459,6 +459,7 @@ int hdmi_get_supported_mode(struct msm_hdmi_mode_timing_info *info, ssize_t hdmi_get_video_3d_fmt_2string(u32 format, char *buf, u32 size); const char *msm_hdmi_mode_2string(u32 mode); int hdmi_set_resv_timing_info(struct msm_hdmi_mode_timing_info *mode); +bool hdmi_is_valid_resv_timing(int mode); void hdmi_reset_resv_timing_info(void); /* todo: Fix this. Right now this is defined in mdss_hdmi_tx.c */ |