diff options
| author | Ajay Singh Parmar <aparmar@codeaurora.org> | 2014-11-14 00:45:14 -0800 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:37:25 -0700 |
| commit | 33c63a3a5d371e933bb6a6629be7f08a46cec819 (patch) | |
| tree | 472d617f8e15f173d9c84c142941ced393de129a /drivers/video/fbdev | |
| parent | b19a1c8b158540b5a24f7e02760d4d8bc766d5ab (diff) | |
msm: mdss: hdmi: optimize resolution data base
HDMI has a large number of resolutions supported and currently
for all supported resolutions, related modules maintain static
tables which are populated at boot time. This results in huge
static memory usage. Also, it limits the system to support only
the define resolutions.
Remove static table which stores all the resolution details.
Get individual resolution details on need basis. Also, remove
the dependency to support only the defined resolution. HDMI driver
can support any non standard resolution within the allowed range.
Change-Id: I0972bc3a0ab96051ea642d685d10c4e5535b7051
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 | 118 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_hdmi_edid.h | 3 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_hdmi_tx.c | 170 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_hdmi_tx.h | 6 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_hdmi_util.c | 124 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_hdmi_util.h | 13 |
6 files changed, 241 insertions, 193 deletions
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_edid.c b/drivers/video/fbdev/msm/mdss_hdmi_edid.c index deec2471977e..4014589d3ab2 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_edid.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_edid.c @@ -227,9 +227,6 @@ static ssize_t hdmi_edid_sysfs_rda_modes(struct device *dev, struct disp_mode_info *video_mode = edid_ctrl->sink_data.disp_mode_list; for (i = 0; i < edid_ctrl->sink_data.num_of_elements; i++) { - if (!hdmi_get_supported_mode( - video_mode[i].video_format)) - continue; if (ret > 0) ret += scnprintf(buf + ret, PAGE_SIZE - ret, ",%d", video_mode[i].video_format); @@ -558,12 +555,15 @@ static void hdmi_edid_set_y420_support(struct hdmi_edid_ctrl *edid_ctrl, } } -static void hdmi_edid_add_sink_y420_format(struct hdmi_edid_sink_data *sink, +static void hdmi_edid_add_sink_y420_format(struct hdmi_edid_ctrl *edid_ctrl, u32 video_format) { - const struct msm_hdmi_mode_timing_info *timing = - hdmi_get_supported_mode(video_format); - u32 supported = timing != NULL; + struct msm_hdmi_mode_timing_info timing = {0}; + u32 ret = hdmi_get_supported_mode(&timing, + edid_ctrl->init_data.ds_data, + video_format); + u32 supported = timing.supported; + struct hdmi_edid_sink_data *sink = &edid_ctrl->sink_data; if (video_format >= HDMI_VFRMT_MAX) { DEV_ERR("%s: video format: %s is not supported\n", __func__, @@ -580,7 +580,7 @@ static void hdmi_edid_add_sink_y420_format(struct hdmi_edid_sink_data *sink, video_format, msm_hdmi_mode_2string(video_format), supported ? "Supported" : "Not-Supported"); - if (supported) { + if (!ret && supported) { sink->disp_mode_list[sink->num_of_elements].video_format = video_format; sink->disp_mode_list[sink->num_of_elements].y420_support @@ -606,8 +606,7 @@ static void hdmi_edid_parse_Y420VDB(struct hdmi_edid_ctrl *edid_ctrl, in_buf += 2; for (i = 0; i < len; i++) { video_format = *in_buf & 0x7F; - hdmi_edid_add_sink_y420_format(&edid_ctrl->sink_data, - video_format); + hdmi_edid_add_sink_y420_format(edid_ctrl, video_format); } } @@ -1005,7 +1004,8 @@ static u32 hdmi_edid_check_header(const u8 *edid_buf) && (edid_buf[6] == 0xff) && (edid_buf[7] == 0x00); } /* hdmi_edid_check_header */ -static void hdmi_edid_detail_desc(const u8 *data_buf, u32 *disp_mode) +static void hdmi_edid_detail_desc(struct hdmi_edid_ctrl *edid_ctrl, + const u8 *data_buf, u32 *disp_mode) { u32 aspect_ratio_4_3 = false; u32 interlaced = false; @@ -1090,23 +1090,25 @@ static void hdmi_edid_detail_desc(const u8 *data_buf, u32 *disp_mode) *disp_mode = HDMI_VFRMT_FORCE_32BIT; for (ndx = HDMI_VFRMT_UNKNOWN + 1; ndx < HDMI_VFRMT_MAX; ndx++) { - const struct msm_hdmi_mode_timing_info *timing = NULL; - timing = hdmi_get_supported_mode(ndx); + struct msm_hdmi_mode_timing_info timing = {0}; + u32 ret = hdmi_get_supported_mode(&timing, + edid_ctrl->init_data.ds_data, + ndx); - if (!timing) + if (ret || !timing.supported) continue; - if ((interlaced == timing->interlaced) && - (active_h == timing->active_h) && - (blank_h == (timing->front_porch_h + - timing->pulse_width_h + - timing->back_porch_h)) && - (blank_v == (timing->front_porch_v + - timing->pulse_width_v + - timing->back_porch_v)) && - ((active_v == timing->active_v) || - (active_v == (timing->active_v + 1)))) { - *disp_mode = timing->video_format; + if ((interlaced == timing.interlaced) && + (active_h == timing.active_h) && + (blank_h == (timing.front_porch_h + + timing.pulse_width_h + + timing.back_porch_h)) && + (blank_v == (timing.front_porch_v + + timing.pulse_width_v + + timing.back_porch_v)) && + ((active_v == timing.active_v) || + (active_v == (timing.active_v + 1)))) { + *disp_mode = timing.video_format; /* * There can be 16:9 and 4:3 aspect ratio of same @@ -1115,10 +1117,10 @@ static void hdmi_edid_detail_desc(const u8 *data_buf, u32 *disp_mode) */ if (aspect_ratio_4_3 && - (timing->ar != HDMI_RES_AR_4_3)) + (timing.ar != HDMI_RES_AR_4_3)) continue; else if (!aspect_ratio_4_3 && - (timing->ar == HDMI_RES_AR_4_3)) + (timing.ar == HDMI_RES_AR_4_3)) continue; else break; @@ -1154,12 +1156,15 @@ static void hdmi_edid_add_sink_3d_format(struct hdmi_edid_sink_data *sink_data, string, added ? "added" : "NOT added"); } /* hdmi_edid_add_sink_3d_format */ -static void hdmi_edid_add_sink_video_format( - struct hdmi_edid_sink_data *sink_data, u32 video_format) +static void hdmi_edid_add_sink_video_format(struct hdmi_edid_ctrl *edid_ctrl, + u32 video_format) { - const struct msm_hdmi_mode_timing_info *timing = - hdmi_get_supported_mode(video_format); - u32 supported = timing != NULL; + struct msm_hdmi_mode_timing_info timing = {0}; + u32 ret = hdmi_get_supported_mode(&timing, + edid_ctrl->init_data.ds_data, + video_format); + u32 supported = timing.supported; + struct hdmi_edid_sink_data *sink_data = &edid_ctrl->sink_data; struct disp_mode_info *disp_mode_list = sink_data->disp_mode_list; if (video_format >= HDMI_VFRMT_MAX) { @@ -1172,7 +1177,7 @@ static void hdmi_edid_add_sink_video_format( video_format, msm_hdmi_mode_2string(video_format), supported ? "Supported" : "Not-Supported"); - if (supported) { + if (!ret && supported) { /* todo: MHL */ disp_mode_list[sink_data->num_of_elements].video_format = video_format; @@ -1364,7 +1369,7 @@ static void hdmi_edid_get_extended_video_formats( for (i = 0; i < hdmi_vic_len; i++) { video_format = HDMI_VFRMT_END + vsd[offset + 2 + i]; - hdmi_edid_add_sink_video_format(&edid_ctrl->sink_data, + hdmi_edid_add_sink_video_format(edid_ctrl, video_format); } } @@ -1409,7 +1414,7 @@ static void hdmi_edid_parse_et3(struct hdmi_edid_ctrl *edid_ctrl, iter++; if (edid_blk0[iter] & BIT(3)) { pr_debug("%s: DMT 848x480@60\n", __func__); - hdmi_edid_add_sink_video_format(sink_data, + hdmi_edid_add_sink_video_format(edid_ctrl, HDMI_VFRMT_848x480p60_16_9); } @@ -1417,13 +1422,13 @@ static void hdmi_edid_parse_et3(struct hdmi_edid_ctrl *edid_ctrl, iter++; if (edid_blk0[iter] & BIT(1)) { pr_debug("%s: DMT 1280x1024@60\n", __func__); - hdmi_edid_add_sink_video_format(sink_data, + hdmi_edid_add_sink_video_format(edid_ctrl, HDMI_VFRMT_1280x1024p60_5_4); } if (edid_blk0[iter] & BIT(3)) { pr_debug("%s: DMT 1280x960@60\n", __func__); - hdmi_edid_add_sink_video_format(sink_data, + hdmi_edid_add_sink_video_format(edid_ctrl, HDMI_VFRMT_1280x960p60_4_3); } @@ -1431,19 +1436,19 @@ static void hdmi_edid_parse_et3(struct hdmi_edid_ctrl *edid_ctrl, iter++; if (edid_blk0[iter] & BIT(1)) { pr_debug("%s: DMT 1400x1050@60\n", __func__); - hdmi_edid_add_sink_video_format(sink_data, + hdmi_edid_add_sink_video_format(edid_ctrl, HDMI_VFRMT_1400x1050p60_4_3); } if (edid_blk0[iter] & BIT(5)) { pr_debug("%s: DMT 1440x900@60\n", __func__); - hdmi_edid_add_sink_video_format(sink_data, + hdmi_edid_add_sink_video_format(edid_ctrl, HDMI_VFRMT_1440x900p60_16_10); } if (edid_blk0[iter] & BIT(7)) { pr_debug("%s: DMT 1360x768@60\n", __func__); - hdmi_edid_add_sink_video_format(sink_data, + hdmi_edid_add_sink_video_format(edid_ctrl, HDMI_VFRMT_1360x768p60_16_9); } @@ -1451,13 +1456,13 @@ static void hdmi_edid_parse_et3(struct hdmi_edid_ctrl *edid_ctrl, iter++; if (edid_blk0[iter] & BIT(2)) { pr_debug("%s: DMT 1600x1200@60\n", __func__); - hdmi_edid_add_sink_video_format(sink_data, + hdmi_edid_add_sink_video_format(edid_ctrl, HDMI_VFRMT_1600x1200p60_4_3); } if (edid_blk0[iter] & BIT(5)) { pr_debug("%s: DMT 1680x1050@60\n", __func__); - hdmi_edid_add_sink_video_format(sink_data, + hdmi_edid_add_sink_video_format(edid_ctrl, HDMI_VFRMT_1680x1050p60_16_10); } @@ -1465,7 +1470,7 @@ static void hdmi_edid_parse_et3(struct hdmi_edid_ctrl *edid_ctrl, iter++; if (edid_blk0[iter] & BIT(0)) { pr_debug("%s: DMT 1920x1200@60\n", __func__); - hdmi_edid_add_sink_video_format(sink_data, + hdmi_edid_add_sink_video_format(edid_ctrl, HDMI_VFRMT_1920x1200p60_16_10); } @@ -1521,7 +1526,7 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl, * CEA_861D spec */ video_format = (*svd & 0x7F); - hdmi_edid_add_sink_video_format(sink_data, + hdmi_edid_add_sink_video_format(edid_ctrl, video_format); /* Make a note of the preferred video format */ if (i == 0) @@ -1561,14 +1566,15 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl, * timing descriptor has block size of 18 */ while (4 > i && 0 != edid_blk0[0x36+desc_offset]) { - hdmi_edid_detail_desc(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(sink_data, + hdmi_edid_add_sink_video_format(edid_ctrl, video_format); if (video_format == HDMI_VFRMT_640x480p60_4_3) @@ -1590,14 +1596,15 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl, * Read EDID block[0] as above */ while (4 > i && 0 != edid_blk0[0x36+desc_offset]) { - hdmi_edid_detail_desc(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(sink_data, + hdmi_edid_add_sink_video_format(edid_ctrl, video_format); if (video_format == HDMI_VFRMT_640x480p60_4_3) @@ -1623,14 +1630,15 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl, */ desc_offset = edid_blk1[0x02]; while (0 != edid_blk1[desc_offset]) { - hdmi_edid_detail_desc(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)); - hdmi_edid_add_sink_video_format(sink_data, + hdmi_edid_add_sink_video_format(edid_ctrl, video_format); if (video_format == HDMI_VFRMT_640x480p60_4_3) has480p = true; @@ -1652,14 +1660,14 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl, (edid_blk0[0x26 + offset + 1] == 0x80)) { pr_debug("%s: 108MHz: off=[%x] stdblk=[%x]\n", __func__, offset, std_blk); - hdmi_edid_add_sink_video_format(sink_data, + hdmi_edid_add_sink_video_format(edid_ctrl, HDMI_VFRMT_1280x1024p60_5_4); } if ((edid_blk0[0x26 + offset] == 0x61) && (edid_blk0[0x26 + offset + 1] == 0x40)) { pr_debug("%s: 65MHz: off=[%x] stdblk=[%x]\n", __func__, offset, std_blk); - hdmi_edid_add_sink_video_format(sink_data, + hdmi_edid_add_sink_video_format(edid_ctrl, HDMI_VFRMT_1024x768p60_4_3); break; } else { @@ -1671,7 +1679,7 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl, /* Established Timing I */ if (edid_blk0[0x23] & BIT(0)) { pr_debug("%s: DMT: ETI: HDMI_VFRMT_800x600_4_3\n", __func__); - hdmi_edid_add_sink_video_format(sink_data, + hdmi_edid_add_sink_video_format(edid_ctrl, HDMI_VFRMT_800x600p60_4_3); } @@ -1679,7 +1687,7 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl, if (edid_blk0[0x24] & BIT(3)) { pr_debug("%s: DMT: ETII: HDMI_VFRMT_1024x768p60_4_3\n", __func__); - hdmi_edid_add_sink_video_format(sink_data, + hdmi_edid_add_sink_video_format(edid_ctrl, HDMI_VFRMT_1024x768p60_4_3); } @@ -1727,7 +1735,7 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl, * All DTV sink devices should support this mode */ if (!has480p) - hdmi_edid_add_sink_video_format(sink_data, + hdmi_edid_add_sink_video_format(edid_ctrl, HDMI_VFRMT_640x480p60_4_3); } /* hdmi_edid_get_display_mode */ diff --git a/drivers/video/fbdev/msm/mdss_hdmi_edid.h b/drivers/video/fbdev/msm/mdss_hdmi_edid.h index 6e796fa7e0a6..d226de74f3de 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_edid.h +++ b/drivers/video/fbdev/msm/mdss_hdmi_edid.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -22,6 +22,7 @@ struct hdmi_edid_init_data { struct kobject *sysfs_kobj; struct hdmi_tx_ddc_ctrl *ddc_ctrl; + struct hdmi_util_ds_data *ds_data; }; int hdmi_edid_read(void *edid_ctrl); diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c index 70cdb45106de..5622a07c7cf7 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c @@ -410,7 +410,12 @@ static int hdmi_tx_get_vic_from_panel_info(struct hdmi_tx_ctrl *hdmi_ctrl, } if (pinfo->vic) { - if (hdmi_get_supported_mode(pinfo->vic)) { + struct msm_hdmi_mode_timing_info info = {0}; + u32 ret = hdmi_get_supported_mode(&info, + &hdmi_ctrl->ds_data, pinfo->vic); + u32 supported = info.supported; + + if (!ret && supported) { new_vic = pinfo->vic; DEV_DBG("%s: %s is supported\n", __func__, msm_hdmi_mode_2string(new_vic)); @@ -451,7 +456,7 @@ static int hdmi_tx_get_vic_from_panel_info(struct hdmi_tx_ctrl *hdmi_ctrl, DEV_DBG("%s: pixel_freq=%d refresh_rate=%d\n", __func__, timing.pixel_freq, timing.refresh_rate); - new_vic = hdmi_get_video_id_code(&timing); + new_vic = hdmi_get_video_id_code(&timing, &hdmi_ctrl->ds_data); } return new_vic; @@ -680,7 +685,7 @@ static ssize_t hdmi_tx_sysfs_wta_hpd(struct device *dev, return rc; } - if (hdmi_ctrl->mhl_max_pclk && hpd && + if (hdmi_ctrl->ds_registered && hpd && (!hdmi_ctrl->mhl_hpd_on || hdmi_ctrl->hpd_feature_on)) return 0; @@ -956,6 +961,72 @@ static ssize_t hdmi_tx_sysfs_wta_avi_cn_bits(struct device *dev, return ret; } /* hdmi_tx_sysfs_wta_cn_bits */ +static ssize_t hdmi_tx_sysfs_wta_res_info(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int rc, res_info_id; + ssize_t ret = strnlen(buf, PAGE_SIZE); + struct hdmi_tx_ctrl *hdmi_ctrl = NULL; + + hdmi_ctrl = hdmi_tx_get_drvdata_from_sysfs_dev(dev); + + if (!hdmi_ctrl) { + DEV_ERR("%s: invalid input\n", __func__); + return -EINVAL; + } + + rc = kstrtoint(buf, 10, &res_info_id); + if (rc) { + DEV_ERR("%s: kstrtoint failed. rc=%d\n", __func__, rc); + return rc; + } + + if (res_info_id >= 0 && res_info_id < HDMI_VFRMT_MAX) + hdmi_ctrl->res_info_id = res_info_id; + else + hdmi_ctrl->res_info_id = 0; + + DEV_DBG("%s: %d\n", __func__, hdmi_ctrl->res_info_id); + return ret; +} + +static ssize_t hdmi_tx_sysfs_rda_res_info(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t ret; + struct msm_hdmi_mode_timing_info info = {0}; + struct hdmi_tx_ctrl *hdmi_ctrl = + hdmi_tx_get_drvdata_from_sysfs_dev(dev); + u32 size = sizeof(info) < PAGE_SIZE ? sizeof(info) : PAGE_SIZE; + + if (!hdmi_ctrl) { + DEV_ERR("%s: invalid input\n", __func__); + return -EINVAL; + } + + if (!hdmi_ctrl->res_info_id) + return -EINVAL; + + ret = hdmi_get_supported_mode(&info, &hdmi_ctrl->ds_data, + hdmi_ctrl->res_info_id); + + if (ret) + return -EINVAL; + + memcpy(buf, &info, size); + + DEV_DBG("%s: %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", + __func__, + info.video_format, info.active_h, info.front_porch_h, + info.pulse_width_h, info.back_porch_h, info.active_low_h, + info.active_v, info.front_porch_v, info.pulse_width_v, + info.back_porch_v, info.active_low_v, info.pixel_freq, + info.refresh_rate, info.interlaced, info.supported, + info.ar); + + return size; +} + static DEVICE_ATTR(connected, S_IRUGO, hdmi_tx_sysfs_rda_connected, NULL); static DEVICE_ATTR(video_mode, S_IRUGO, hdmi_tx_sysfs_rda_video_mode, NULL); static DEVICE_ATTR(hpd, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_hpd, @@ -967,6 +1038,8 @@ static DEVICE_ATTR(product_description, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_wta_product_description); static DEVICE_ATTR(avi_itc, S_IWUSR, NULL, hdmi_tx_sysfs_wta_avi_itc); static DEVICE_ATTR(avi_cn0_1, S_IWUSR, NULL, hdmi_tx_sysfs_wta_avi_cn_bits); +static DEVICE_ATTR(res_info, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_res_info, + hdmi_tx_sysfs_wta_res_info); static struct attribute *hdmi_tx_fs_attrs[] = { &dev_attr_connected.attr, @@ -976,6 +1049,7 @@ static struct attribute *hdmi_tx_fs_attrs[] = { &dev_attr_product_description.attr, &dev_attr_avi_itc.attr, &dev_attr_avi_cn0_1.attr, + &dev_attr_res_info.attr, NULL, }; static struct attribute_group hdmi_tx_fs_attrs_group = { @@ -1150,6 +1224,7 @@ static int hdmi_tx_init_features(struct hdmi_tx_ctrl *hdmi_ctrl) edid_init_data.mutex = &hdmi_ctrl->mutex; edid_init_data.sysfs_kobj = hdmi_ctrl->kobj; edid_init_data.ddc_ctrl = &hdmi_ctrl->ddc_ctrl; + edid_init_data.ds_data = &hdmi_ctrl->ds_data; hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID] = hdmi_edid_init(&edid_init_data); @@ -1217,31 +1292,33 @@ static inline u32 hdmi_tx_is_controller_on(struct hdmi_tx_ctrl *hdmi_ctrl) static int hdmi_tx_init_panel_info(struct hdmi_tx_ctrl *hdmi_ctrl) { struct mdss_panel_info *pinfo; - const struct msm_hdmi_mode_timing_info *timing; + struct msm_hdmi_mode_timing_info timing = {0}; + u32 ret; if (!hdmi_ctrl) { DEV_ERR("%s: invalid input\n", __func__); return -EINVAL; } - timing = hdmi_get_supported_mode(hdmi_ctrl->vid_cfg.vic); + ret = hdmi_get_supported_mode(&timing, &hdmi_ctrl->ds_data, + hdmi_ctrl->vid_cfg.vic); pinfo = &hdmi_ctrl->panel_data.panel_info; - if (!timing || !pinfo) { + if (ret || !timing.supported || !pinfo) { DEV_ERR("%s: invalid timing data\n", __func__); return -EINVAL; } - pinfo->xres = timing->active_h; - pinfo->yres = timing->active_v; - pinfo->clk_rate = timing->pixel_freq*1000; + pinfo->xres = timing.active_h; + pinfo->yres = timing.active_v; + pinfo->clk_rate = timing.pixel_freq * 1000; - pinfo->lcdc.h_back_porch = timing->back_porch_h; - pinfo->lcdc.h_front_porch = timing->front_porch_h; - pinfo->lcdc.h_pulse_width = timing->pulse_width_h; - pinfo->lcdc.v_back_porch = timing->back_porch_v; - pinfo->lcdc.v_front_porch = timing->front_porch_v; - pinfo->lcdc.v_pulse_width = timing->pulse_width_v; + pinfo->lcdc.h_back_porch = timing.back_porch_h; + pinfo->lcdc.h_front_porch = timing.front_porch_h; + pinfo->lcdc.h_pulse_width = timing.pulse_width_h; + pinfo->lcdc.v_back_porch = timing.back_porch_v; + pinfo->lcdc.v_front_porch = timing.front_porch_v; + pinfo->lcdc.v_pulse_width = timing.pulse_width_v; pinfo->type = DTV_PANEL; pinfo->pdest = DISPLAY_2; @@ -1258,30 +1335,6 @@ static int hdmi_tx_init_panel_info(struct hdmi_tx_ctrl *hdmi_ctrl) return 0; } /* hdmi_tx_init_panel_info */ -/* Table tuned to indicate video formats supported by the MHL Tx */ -/* Valid pclk rates (Mhz): 25.2, 27, 27.03, 74.25 */ -static void hdmi_tx_setup_mhl_video_mode_lut(struct hdmi_tx_ctrl *hdmi_ctrl) -{ - u32 i; - struct msm_hdmi_mode_timing_info *temp_timing; - - if (!hdmi_ctrl->mhl_max_pclk) { - DEV_WARN("%s: mhl max pclk not set!\n", __func__); - return; - } - DEV_DBG("%s: max mode set to [%u]\n", - __func__, hdmi_ctrl->mhl_max_pclk); - for (i = 0; i < HDMI_VFRMT_MAX; i++) { - temp_timing = - (struct msm_hdmi_mode_timing_info *)hdmi_get_supported_mode(i); - if (!temp_timing) - continue; - /* formats that exceed max mhl line clk bw */ - if (temp_timing->pixel_freq > hdmi_ctrl->mhl_max_pclk) - hdmi_del_supported_mode(i); - } -} /* hdmi_tx_setup_mhl_video_mode_lut */ - static int hdmi_tx_read_sink_info(struct hdmi_tx_ctrl *hdmi_ctrl) { int status; @@ -1406,9 +1459,9 @@ static int hdmi_tx_set_video_fmt(struct hdmi_tx_ctrl *hdmi_ctrl, struct mdss_panel_info *pinfo) { int new_vic = -1; - const struct msm_hdmi_mode_timing_info *timing = NULL; int res_changed = RESOLUTION_UNCHANGED; struct hdmi_video_config *vid_cfg = NULL; + u32 ret; if (!hdmi_ctrl || !pinfo) { DEV_ERR("%s: invalid input\n", __func__); @@ -1430,16 +1483,16 @@ static int hdmi_tx_set_video_fmt(struct hdmi_tx_ctrl *hdmi_ctrl, vid_cfg->vic = (u32)new_vic; - timing = hdmi_get_supported_mode(vid_cfg->vic); + ret = hdmi_get_supported_mode(&vid_cfg->timing, &hdmi_ctrl->ds_data, + vid_cfg->vic); - if (!timing) { + if (ret || !vid_cfg->timing.supported) { DEV_ERR("%s: invalid input\n", __func__); return -EINVAL; } /* Setup AVI Infoframe content */ vid_cfg->vic = new_vic; - vid_cfg->timing = timing; vid_cfg->avi_iframe.pixel_format = pinfo->out_format; vid_cfg->avi_iframe.scan_info = hdmi_edid_get_sink_scaninfo( hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID], @@ -1448,9 +1501,11 @@ static int hdmi_tx_set_video_fmt(struct hdmi_tx_ctrl *hdmi_ctrl, vid_cfg->avi_iframe.pixel_format = pinfo->out_format; vid_cfg->avi_iframe.bar_info.end_of_top_bar = 0x0; - vid_cfg->avi_iframe.bar_info.start_of_bottom_bar = timing->active_v + 1; + vid_cfg->avi_iframe.bar_info.start_of_bottom_bar = + vid_cfg->timing.active_v + 1; vid_cfg->avi_iframe.bar_info.end_of_left_bar = 0; - vid_cfg->avi_iframe.bar_info.start_of_right_bar = timing->active_h + 1; + vid_cfg->avi_iframe.bar_info.start_of_right_bar = + vid_cfg->timing.active_h + 1; vid_cfg->avi_iframe.act_fmt_info_present = true; vid_cfg->avi_iframe.rgb_quantization_range = HDMI_QUANTIZATION_DEFAULT; @@ -1464,7 +1519,7 @@ static int hdmi_tx_set_video_fmt(struct hdmi_tx_ctrl *hdmi_ctrl, vid_cfg->avi_iframe.pixel_rpt_factor = 0; /* todo: find a better way */ hdmi_ctrl->pdata.power_data[HDMI_TX_CORE_PM].clk_config[0].rate = - timing->pixel_freq * 1000; + vid_cfg->timing.pixel_freq * 1000; hdmi_edid_set_video_resolution( hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID], vid_cfg->vic); @@ -1482,14 +1537,13 @@ static int hdmi_tx_video_setup(struct hdmi_tx_ctrl *hdmi_ctrl) u32 end_v = 0; u32 div = 0; struct dss_io_data *io = NULL; - const struct msm_hdmi_mode_timing_info *timing = NULL; - + struct msm_hdmi_mode_timing_info *timing = NULL; if (!hdmi_ctrl) { DEV_ERR("%s: invalid input\n", __func__); return -EINVAL; } - timing = hdmi_ctrl->vid_cfg.timing; + timing = &hdmi_ctrl->vid_cfg.timing; if (timing == NULL) { DEV_ERR("%s: video format not supported: %d\n", __func__, @@ -1562,7 +1616,7 @@ static void hdmi_tx_set_avi_infoframe(struct hdmi_tx_ctrl *hdmi_ctrl) u32 sum, reg_val; struct dss_io_data *io = NULL; struct hdmi_avi_infoframe_config *avi_info; - const struct msm_hdmi_mode_timing_info *timing; + struct msm_hdmi_mode_timing_info *timing; if (!hdmi_ctrl) { DEV_ERR("%s: invalid input\n", __func__); @@ -1571,7 +1625,7 @@ static void hdmi_tx_set_avi_infoframe(struct hdmi_tx_ctrl *hdmi_ctrl) io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO]; avi_info = &hdmi_ctrl->vid_cfg.avi_iframe; - timing = hdmi_ctrl->vid_cfg.timing; + timing = &hdmi_ctrl->vid_cfg.timing; if (!io->base) { DEV_ERR("%s: Core io is not initialized\n", __func__); @@ -2311,8 +2365,8 @@ static int hdmi_tx_audio_acr_setup(struct hdmi_tx_ctrl *hdmi_ctrl, acr_pck_ctrl_reg = DSS_REG_R(io, HDMI_ACR_PKT_CTRL); if (enabled) { - const struct msm_hdmi_mode_timing_info *timing = - hdmi_ctrl->vid_cfg.timing; + struct msm_hdmi_mode_timing_info *timing = + &hdmi_ctrl->vid_cfg.timing; const struct hdmi_tx_audio_acr_arry *audio_acr = &hdmi_tx_audio_acr_lut[0]; const int lut_size = sizeof(hdmi_tx_audio_acr_lut) @@ -2649,12 +2703,13 @@ static int hdmi_tx_set_mhl_max_pclk(struct platform_device *pdev, u32 max_val) return -ENODEV; } if (max_val) { - hdmi_ctrl->mhl_max_pclk = max_val; - hdmi_tx_setup_mhl_video_mode_lut(hdmi_ctrl); + hdmi_ctrl->ds_data.ds_max_clk = max_val; + hdmi_ctrl->ds_data.ds_registered = true; } else { DEV_ERR("%s: invalid max pclk val\n", __func__); return -EINVAL; } + return 0; } @@ -2792,7 +2847,7 @@ static int hdmi_tx_setup_scrambler(struct hdmi_tx_ctrl *hdmi_ctrl) u32 reg_val = 0; bool scrambler_on = false; struct dss_io_data *io = NULL; - const struct msm_hdmi_mode_timing_info *timing = NULL; + struct msm_hdmi_mode_timing_info *timing = NULL; if (!hdmi_ctrl) { DEV_ERR("%s: Bad input parameters\n", __func__); @@ -2805,7 +2860,7 @@ static int hdmi_tx_setup_scrambler(struct hdmi_tx_ctrl *hdmi_ctrl) return -EINVAL; } - timing = hdmi_ctrl->vid_cfg.timing; + timing = &hdmi_ctrl->vid_cfg.timing; if (!timing) { DEV_ERR("%s: Invalid timing info\n", __func__); return -EINVAL; @@ -3406,7 +3461,6 @@ static int hdmi_tx_dev_init(struct hdmi_tx_ctrl *hdmi_ctrl) /* irq enable/disable will be handled in hpd on/off */ hdmi_tx_hw.ptr = (void *)hdmi_ctrl; - hdmi_setup_video_mode_lut(); mutex_init(&hdmi_ctrl->mutex); mutex_init(&hdmi_ctrl->lut_lock); mutex_init(&hdmi_ctrl->cable_notify_mutex); diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.h b/drivers/video/fbdev/msm/mdss_hdmi_tx.h index edfae7c29a72..d6b5fadaf9a7 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_tx.h +++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.h @@ -119,7 +119,7 @@ struct hdmi_avi_infoframe_config { struct hdmi_video_config { u32 vic; - const struct msm_hdmi_mode_timing_info *timing; + struct msm_hdmi_mode_timing_info timing; struct hdmi_avi_infoframe_config avi_iframe; }; @@ -154,9 +154,11 @@ struct hdmi_tx_ctrl { u32 hpd_feature_on; u32 hpd_initialized; u32 vote_hdmi_core_on; + u32 res_info_id; u8 timing_gen_on; - u32 mhl_max_pclk; u8 mhl_hpd_on; + + struct hdmi_util_ds_data ds_data; struct completion hpd_done; struct work_struct hpd_int_work; diff --git a/drivers/video/fbdev/msm/mdss_hdmi_util.c b/drivers/video/fbdev/msm/mdss_hdmi_util.c index 88c26d901ca9..b18c303f67aa 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_util.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_util.c @@ -19,9 +19,6 @@ #define HDMI_SCDC_UNKNOWN_REGISTER "Unknown register" -static struct msm_hdmi_mode_timing_info - hdmi_supported_video_mode_lut[HDMI_VFRMT_MAX]; - static char res_buf[RESOLUTION_NAME_STR_LEN]; static void hdmi_scrambler_status_timer_setup(struct hdmi_tx_ddc_ctrl *ctrl, @@ -82,24 +79,46 @@ static inline char *hdmi_scdc_reg2string(u32 type) } } +int hdmi_get_supported_mode(struct msm_hdmi_mode_timing_info *info, + struct hdmi_util_ds_data *ds_data, u32 mode) +{ + int ret; + + if (!info || !ds_data) + return -EINVAL; + + if (mode >= HDMI_VFRMT_MAX) + return -EINVAL; + + ret = msm_hdmi_get_timing_info(info, mode); + + if (!ret && ds_data && ds_data->ds_registered && ds_data->ds_max_clk) { + if (info->pixel_freq > ds_data->ds_max_clk) + info->supported = false; + } + + return ret; +} /* hdmi_get_supported_mode */ + const char *msm_hdmi_mode_2string(u32 mode) { - static struct msm_hdmi_mode_timing_info *ri; + static struct msm_hdmi_mode_timing_info ri = {0}; char *aspect_ratio; if (mode >= HDMI_VFRMT_MAX) return "???"; - ri = &hdmi_supported_video_mode_lut[mode]; + if (hdmi_get_supported_mode(&ri, NULL, mode)) + return "???"; memset(res_buf, 0, sizeof(res_buf)); - if (!ri->supported) { + if (!ri.supported) { snprintf(res_buf, RESOLUTION_NAME_STR_LEN, "%d", mode); return res_buf; } - switch (ri->ar) { + switch (ri.ar) { case HDMI_RES_AR_4_3: aspect_ratio = "4/3"; break; @@ -117,41 +136,18 @@ const char *msm_hdmi_mode_2string(u32 mode) }; snprintf(res_buf, RESOLUTION_NAME_STR_LEN, "%dx%d %s%dHz %s", - ri->active_h, ri->active_v, ri->interlaced ? "i" : "p", - ri->refresh_rate / 1000, aspect_ratio); + ri.active_h, ri.active_v, ri.interlaced ? "i" : "p", + ri.refresh_rate / 1000, aspect_ratio); return res_buf; } -void hdmi_del_supported_mode(u32 mode) -{ - struct msm_hdmi_mode_timing_info *ret = NULL; - DEV_DBG("%s: removing %s\n", __func__, - msm_hdmi_mode_2string(mode)); - ret = &hdmi_supported_video_mode_lut[mode]; - if (ret != NULL && ret->supported) - ret->supported = false; -} - -const struct msm_hdmi_mode_timing_info *hdmi_get_supported_mode(u32 mode) -{ - const struct msm_hdmi_mode_timing_info *ret = NULL; - - if (mode >= HDMI_VFRMT_MAX) - return NULL; - - ret = &hdmi_supported_video_mode_lut[mode]; - - if (ret == NULL || !ret->supported) - return NULL; - - return ret; -} /* hdmi_get_supported_mode */ - -int hdmi_get_video_id_code(struct msm_hdmi_mode_timing_info *timing_in) +int hdmi_get_video_id_code(struct msm_hdmi_mode_timing_info *timing_in, + struct hdmi_util_ds_data *ds_data) { int i, vic = -1; - struct msm_hdmi_mode_timing_info *supported_timing; + struct msm_hdmi_mode_timing_info supported_timing = {0}; + u32 ret; if (!timing_in) { DEV_ERR("%s: invalid input\n", __func__); @@ -160,45 +156,46 @@ 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++) { - supported_timing = &hdmi_supported_video_mode_lut[i]; + ret = hdmi_get_supported_mode(&supported_timing, ds_data, i); - if (!supported_timing->supported) + if (ret || !supported_timing.supported) continue; - if (timing_in->active_h != supported_timing->active_h) + if (timing_in->active_h != supported_timing.active_h) continue; - if (timing_in->front_porch_h != supported_timing->front_porch_h) + if (timing_in->front_porch_h != supported_timing.front_porch_h) continue; - if (timing_in->pulse_width_h != supported_timing->pulse_width_h) + if (timing_in->pulse_width_h != supported_timing.pulse_width_h) continue; - if (timing_in->back_porch_h != supported_timing->back_porch_h) + if (timing_in->back_porch_h != supported_timing.back_porch_h) continue; - if (timing_in->active_v != supported_timing->active_v) + if (timing_in->active_v != supported_timing.active_v) continue; - if (timing_in->front_porch_v != supported_timing->front_porch_v) + if (timing_in->front_porch_v != supported_timing.front_porch_v) continue; - if (timing_in->pulse_width_v != supported_timing->pulse_width_v) + if (timing_in->pulse_width_v != supported_timing.pulse_width_v) continue; - if (timing_in->back_porch_v != supported_timing->back_porch_v) + 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 != supported_timing.pixel_freq) continue; - if (timing_in->refresh_rate != supported_timing->refresh_rate) + if (timing_in->refresh_rate != supported_timing.refresh_rate) continue; - vic = (int)supported_timing->video_format; + vic = (int)supported_timing.video_format; break; } if (vic < 0) { for (i = 0; i < HDMI_VFRMT_MAX; i++) { - supported_timing = &hdmi_supported_video_mode_lut[i]; - if (!supported_timing->supported) + ret = hdmi_get_supported_mode(&supported_timing, + ds_data, i); + if (ret || !supported_timing.supported) continue; - if (timing_in->active_h != supported_timing->active_h) + if (timing_in->active_h != supported_timing.active_h) continue; - if (timing_in->active_v != supported_timing->active_v) + if (timing_in->active_v != supported_timing.active_v) continue; - vic = (int)supported_timing->video_format; + vic = (int)supported_timing.video_format; break; } } @@ -215,25 +212,6 @@ exit: return vic; } /* hdmi_get_video_id_code */ -/* Table indicating the video format supported by the HDMI TX Core */ -/* Valid pclk rates (Mhz): 25.2, 27, 27.03, 74.25, 148.5, 268.5, 297 */ -void hdmi_setup_video_mode_lut(void) -{ - MSM_HDMI_MODES_INIT_TIMINGS(hdmi_supported_video_mode_lut); - - /* Add all supported CEA modes to the lut */ - MSM_HDMI_MODES_SET_SUPP_TIMINGS( - hdmi_supported_video_mode_lut, MSM_HDMI_MODES_CEA); - - /* Add all supported extended hdmi modes to the lut */ - MSM_HDMI_MODES_SET_SUPP_TIMINGS( - hdmi_supported_video_mode_lut, MSM_HDMI_MODES_XTND); - - /* Add any other specific DVI timings (DVI modes, etc.) */ - MSM_HDMI_MODES_SET_SUPP_TIMINGS( - hdmi_supported_video_mode_lut, MSM_HDMI_MODES_DVI); -} /* hdmi_setup_video_mode_lut */ - static const char *hdmi_get_single_video_3d_fmt_2string(u32 format) { switch (format) { diff --git a/drivers/video/fbdev/msm/mdss_hdmi_util.h b/drivers/video/fbdev/msm/mdss_hdmi_util.h index f3f510c1d694..bf3b3ff269de 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_util.h +++ b/drivers/video/fbdev/msm/mdss_hdmi_util.h @@ -311,11 +311,16 @@ struct hdmi_tx_ddc_data { int retry; }; +struct hdmi_util_ds_data { + bool ds_registered; + u32 ds_max_clk; +}; + /* video timing related utility routines */ -void hdmi_setup_video_mode_lut(void); -int hdmi_get_video_id_code(struct msm_hdmi_mode_timing_info *timing_in); -const struct msm_hdmi_mode_timing_info *hdmi_get_supported_mode(u32 mode); -void hdmi_del_supported_mode(u32 mode); +int hdmi_get_video_id_code(struct msm_hdmi_mode_timing_info *timing_in, + struct hdmi_util_ds_data *ds_data); +int hdmi_get_supported_mode(struct msm_hdmi_mode_timing_info *info, + struct hdmi_util_ds_data *ds_data, u32 mode); ssize_t hdmi_get_video_3d_fmt_2string(u32 format, char *buf, u32 size); const char *msm_hdmi_mode_2string(u32 mode); |
