summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAjay Singh Parmar <aparmar@codeaurora.org>2015-08-28 23:10:32 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:45:21 -0700
commit746fd7db83461d54a340c061a2870ecf3a952a8a (patch)
treef1cf9053c2c7f69f56bd51a9406febf8f7516767 /drivers
parent559d29938bf6aa7c377f967195b89f6775dc8491 (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.c75
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_util.c15
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_util.h1
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 */