diff options
| author | Ajay Singh Parmar <aparmar@codeaurora.org> | 2014-09-26 11:49:26 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:47:48 -0700 |
| commit | 8355f8eb237f6fd0fd2d1cf8e3812805afaa69d6 (patch) | |
| tree | a1b28395fd5ed04c51f531cd9a6c5a70baf71a00 /drivers/video/fbdev | |
| parent | b7a03e20810dba1ad0b3f54a9096b90546011abe (diff) | |
msm: mdss: hdmi: add resolution overwrite support
Add support to let the user select and switch to a particular
resolution over HDMI.
Change-Id: I8cd056fe120c9a459e9df22d3121203278973f4c
Signed-off-by: Ajay Singh Parmar <aparmar@codeaurora.org>
Diffstat (limited to 'drivers/video/fbdev')
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_hdmi_edid.c | 100 |
1 files changed, 89 insertions, 11 deletions
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_edid.c b/drivers/video/fbdev/msm/mdss_hdmi_edid.c index 3eab12860633..0eb5869bdfe3 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_edid.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_edid.c @@ -134,12 +134,23 @@ struct hdmi_edid_ctrl { u8 edid_buf[MAX_EDID_SIZE]; char vendor_id[EDID_VENDOR_ID_SIZE]; bool keep_resv_timings; + u32 edid_override; struct hdmi_edid_sink_data sink_data; struct hdmi_edid_init_data init_data; struct hdmi_edid_sink_caps sink_caps; }; +static bool hdmi_edid_is_mode_supported(struct hdmi_edid_ctrl *edid_ctrl, + struct msm_hdmi_mode_timing_info *timing) +{ + if (!timing->supported || + timing->pixel_freq > edid_ctrl->init_data.max_pclk_khz) + return false; + + return true; +} + static int hdmi_edid_reset_parser(struct hdmi_edid_ctrl *edid_ctrl) { if (!edid_ctrl) { @@ -301,6 +312,77 @@ static ssize_t hdmi_edid_sysfs_rda_spkr_alloc_data_block(struct device *dev, static DEVICE_ATTR(spkr_alloc_data_block, S_IRUGO, hdmi_edid_sysfs_rda_spkr_alloc_data_block, NULL); +static ssize_t hdmi_edid_sysfs_wta_modes(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int scrambling, vic, format, sink; + ssize_t ret = strnlen(buf, PAGE_SIZE); + int rc; + struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev); + struct hdmi_edid_sink_data *sd; + struct msm_hdmi_mode_timing_info info = {0}; + + if (!edid_ctrl) { + DEV_ERR("%s: invalid ctrl\n", __func__); + ret = -EINVAL; + goto error; + } + + sd = &edid_ctrl->sink_data; + + if (sscanf(buf, "%d %d %d %d", + &scrambling, &sink, &format, &vic) != 4) { + DEV_ERR("could not read input\n"); + ret = -EINVAL; + goto bail; + } + + if ((sink != SINK_MODE_DVI && sink != SINK_MODE_HDMI) || + !(format & (MSM_HDMI_RGB_888_24BPP_FORMAT | + MSM_HDMI_YUV_420_12BPP_FORMAT)) || + vic <= HDMI_VFRMT_UNKNOWN || vic >= HDMI_VFRMT_MAX) { + DEV_ERR("%s: invalid input: sink %d, format %d, vic %d\n", + __func__, sink, format, vic); + ret = -EINVAL; + goto bail; + } + + rc = hdmi_get_supported_mode(&info, + edid_ctrl->init_data.ds_data, vic); + if (rc) { + DEV_ERR("%s: error getting res details\n", __func__); + ret = -EINVAL; + goto bail; + } + + if (!hdmi_edid_is_mode_supported(edid_ctrl, &info)) { + DEV_ERR("%s: %d vic not supported\n", __func__, vic); + ret = -EINVAL; + goto bail; + } + + sd->num_of_elements = 1; + sd->disp_mode_list[0].video_format = vic; + + if (format & MSM_HDMI_RGB_888_24BPP_FORMAT) + sd->disp_mode_list[0].rgb_support = true; + + if (format & MSM_HDMI_YUV_420_12BPP_FORMAT) + sd->disp_mode_list[0].y420_support = true; + + edid_ctrl->sink_mode = sink; + edid_ctrl->sink_caps.scramble_support = !!scrambling; + edid_ctrl->sink_caps.scdc_present = !!scrambling; + + edid_ctrl->edid_override = true; + return ret; +bail: + DEV_DBG("%s: reset edid override\n", __func__); + edid_ctrl->edid_override = false; +error: + return ret; +} + static ssize_t hdmi_edid_sysfs_rda_modes(struct device *dev, struct device_attribute *attr, char *buf) { @@ -335,7 +417,8 @@ static ssize_t hdmi_edid_sysfs_rda_modes(struct device *dev, return ret; } /* hdmi_edid_sysfs_rda_modes */ -static DEVICE_ATTR(edid_modes, S_IRUGO, hdmi_edid_sysfs_rda_modes, NULL); +static DEVICE_ATTR(edid_modes, S_IRUGO | S_IWUSR, hdmi_edid_sysfs_rda_modes, + hdmi_edid_sysfs_wta_modes); static ssize_t hdmi_edid_sysfs_wta_res_info(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -651,16 +734,6 @@ static struct attribute_group hdmi_edid_fs_attrs_group = { .attrs = hdmi_edid_fs_attrs, }; -static bool hdmi_edid_is_mode_supported(struct hdmi_edid_ctrl *edid_ctrl, - struct msm_hdmi_mode_timing_info *timing) -{ - if (!timing->supported || - timing->pixel_freq > edid_ctrl->init_data.max_pclk_khz) - return false; - - return true; -} - static const u8 *hdmi_edid_find_block(const u8 *in_buf, u32 start_offset, u8 type, u8 *len) { @@ -2030,6 +2103,11 @@ int hdmi_edid_parser(void *input) goto err_invalid_data; } + if (edid_ctrl->edid_override) { + DEV_DBG("edid override enabled\n"); + goto err_invalid_data; + } + /* reset edid data for new hdmi connection */ hdmi_edid_reset_parser(edid_ctrl); |
