summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNarender Ankam <nankam@codeaurora.org>2020-09-17 13:37:00 +0530
committerGerrit - the friendly Code Review server <code-review@localhost>2020-11-10 00:35:34 -0800
commitdfb161642804efbcfdd674f20150e0532b7dae01 (patch)
tree788635e0c1e34074889248ac4ef143feaedb00a4
parent0ac4b189f1d32a8511f0f3aff88c77ccacc2ab46 (diff)
msm: mdss: hdmi: parse physical screen dimensions from EDID
Parse Basic Display Parameters/Features of EDID and store Horizontal and Vertical Screen size of downstream HDMI sink. Change-Id: Ic538a881f877f27a66983a34d6869bf9663567e9 Signed-off-by: Narender Ankam <nankam@codeaurora.org>
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_edid.c128
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_edid.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.c5
3 files changed, 135 insertions, 0 deletions
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_edid.c b/drivers/video/fbdev/msm/mdss_hdmi_edid.c
index 6f0234500d70..5095f4ae49b5 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_edid.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_edid.c
@@ -65,6 +65,11 @@
#define EDID_VENDOR_ID_SIZE 4
#define EDID_IEEE_REG_ID 0x0c03
+enum edid_screen_orientation {
+ LANDSCAPE = 1,
+ PORTRAIT = 2,
+};
+
enum edid_sink_mode {
SINK_MODE_DVI,
SINK_MODE_HDMI
@@ -143,6 +148,8 @@ struct hdmi_edid_ctrl {
u8 cea_blks;
/* DC: MSB -> LSB: Y420_48|Y420_36|Y420_30|RGB48|RGB36|RGB30|Y444 */
u8 deep_color;
+ u8 physical_width;
+ u8 physical_height;
u16 physical_address;
u32 video_resolution; /* selected by user */
u32 sink_mode; /* HDMI or DVI */
@@ -167,6 +174,9 @@ struct hdmi_edid_ctrl {
bool y420_cmdb_supports_all;
struct hdmi_edid_y420_cmdb y420_cmdb;
+ enum edid_screen_orientation orientation;
+ enum aspect_ratio aspect_ratio;
+
struct hdmi_edid_sink_data sink_data;
struct hdmi_edid_init_data init_data;
struct hdmi_edid_sink_caps sink_caps;
@@ -254,6 +264,11 @@ int hdmi_edid_reset_parser(void *input)
edid_ctrl->y420_cmdb_supports_all = false;
kfree(edid_ctrl->y420_cmdb.vic_list);
memset(&edid_ctrl->y420_cmdb, 0, sizeof(edid_ctrl->y420_cmdb));
+
+ edid_ctrl->physical_width = 0;
+ edid_ctrl->physical_height = 0;
+ edid_ctrl->orientation = 0;
+ edid_ctrl->aspect_ratio = HDMI_RES_AR_INVALID;
return 0;
}
@@ -449,6 +464,30 @@ static ssize_t hdmi_edid_sysfs_rda_modes(struct device *dev,
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_rda_screen_size(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+ struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev);
+
+ if (!edid_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%d",
+ (edid_ctrl->physical_width * 10));
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret, " %d",
+ (edid_ctrl->physical_height * 10));
+
+ DEV_DBG("%s: '%s'\n", __func__, buf);
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
+
+ return ret;
+} /* hdmi_edid_sysfs_rda_screen_size */
+static DEVICE_ATTR(edid_screen_size, S_IRUGO, hdmi_edid_sysfs_rda_screen_size,
+ NULL);
+
static ssize_t hdmi_edid_sysfs_rda_res_info_data(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -855,6 +894,7 @@ static DEVICE_ATTR(hdr_data, S_IRUGO, hdmi_edid_sysfs_rda_hdr_data, NULL);
static struct attribute *hdmi_edid_fs_attrs[] = {
&dev_attr_edid_modes.attr,
+ &dev_attr_edid_screen_size.attr,
&dev_attr_pa.attr,
&dev_attr_scan_info.attr,
&dev_attr_edid_3d_modes.attr,
@@ -1515,6 +1555,68 @@ static u32 hdmi_edid_extract_ieee_reg_id(struct hdmi_edid_ctrl *edid_ctrl,
return ((u32)vsd[3] << 16) + ((u32)vsd[2] << 8) + (u32)vsd[1];
} /* hdmi_edid_extract_ieee_reg_id */
+static void hdmi_edid_extract_bdpf(struct hdmi_edid_ctrl *edid_ctrl)
+{
+ u8 *edid_buf = NULL;
+
+ if (!edid_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return;
+ }
+
+ edid_buf = edid_ctrl->edid_buf;
+ if (edid_buf[21] && edid_buf[22]) {
+ edid_ctrl->physical_width = edid_buf[21];
+ edid_ctrl->physical_height = edid_buf[22];
+
+ DEV_DBG("%s: EDID: Horizontal Screen Size = %d cm\n",
+ __func__, edid_ctrl->physical_width);
+ DEV_DBG("%s: EDID: Vertical Screen Size = %d cm\n",
+ __func__, edid_ctrl->physical_height);
+ } else if (edid_buf[21]) {
+ edid_ctrl->orientation = LANDSCAPE;
+ switch (edid_buf[21]) {
+ case 0x4F:
+ edid_ctrl->aspect_ratio = HDMI_RES_AR_16_9;
+ break;
+ case 0x3D:
+ edid_ctrl->aspect_ratio = HDMI_RES_AR_16_10;
+ break;
+ case 0x22:
+ edid_ctrl->aspect_ratio = HDMI_RES_AR_4_3;
+ break;
+ case 0x1A:
+ edid_ctrl->aspect_ratio = HDMI_RES_AR_5_4;
+ break;
+ }
+ DEV_DBG("%s: EDID: Landscape Aspect Ratio = %d\n",
+ __func__, edid_ctrl->aspect_ratio);
+ } else if (edid_buf[22]) {
+ edid_ctrl->orientation = PORTRAIT;
+ switch (edid_buf[22]) {
+ case 0x4F:
+ edid_ctrl->aspect_ratio = HDMI_RES_AR_16_9;
+ break;
+ case 0x3D:
+ edid_ctrl->aspect_ratio = HDMI_RES_AR_16_10;
+ break;
+ case 0x22:
+ edid_ctrl->aspect_ratio = HDMI_RES_AR_4_3;
+ break;
+ case 0x1A:
+ edid_ctrl->aspect_ratio = HDMI_RES_AR_5_4;
+ break;
+ }
+ DEV_DBG("%s: EDID: Portrait Aspect Ratio = %d\n",
+ __func__, edid_ctrl->aspect_ratio);
+ } else {
+ pr_debug("%s: Undefined Screen size/Aspect ratio\n", __func__);
+ edid_ctrl->orientation = 0;
+ edid_ctrl->physical_width = 0;
+ edid_ctrl->physical_height = 0;
+ }
+}
+
static void hdmi_edid_extract_vendor_id(struct hdmi_edid_ctrl *edid_ctrl)
{
char *vendor_id;
@@ -2462,6 +2564,8 @@ int hdmi_edid_parser(void *input)
hdmi_edid_extract_vendor_id(edid_ctrl);
+ hdmi_edid_extract_bdpf(edid_ctrl);
+
/* EDID_CEA_EXTENSION_FLAG[0x7E] - CEC extension byte */
num_of_cea_blocks = edid_buf[EDID_BLOCK_SIZE - 2];
DEV_DBG("%s: No. of CEA/Extended EDID blocks is [%u]\n", __func__,
@@ -2914,6 +3018,30 @@ bool hdmi_edid_is_audio_supported(void *input)
return (edid_ctrl->basic_audio_supp || edid_ctrl->adb_size);
}
+u32 hdmi_edid_get_phys_width(void *input)
+{
+ struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
+
+ if (!edid_ctrl) {
+ DEV_ERR("%s: invalid edid_ctrl data\n", __func__);
+ return 0;
+ }
+
+ return (u32)edid_ctrl->physical_width * 10; /* return in mm */
+}
+
+u32 hdmi_edid_get_phys_height(void *input)
+{
+ struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
+
+ if (!edid_ctrl) {
+ DEV_ERR("%s: invalid edid_ctrl data\n", __func__);
+ return 0;
+ }
+
+ return (u32)edid_ctrl->physical_height * 10; /* return in mm */
+}
+
void hdmi_edid_deinit(void *input)
{
struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_edid.h b/drivers/video/fbdev/msm/mdss_hdmi_edid.h
index d258aa9f95bc..9b3b5fa952b4 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_edid.h
+++ b/drivers/video/fbdev/msm/mdss_hdmi_edid.h
@@ -94,5 +94,7 @@ void hdmi_edid_set_max_pclk_rate(void *input, u32 max_pclk_khz);
bool hdmi_edid_is_audio_supported(void *input);
u32 hdmi_edid_get_sink_caps_max_tmds_clk(void *input);
u8 hdmi_edid_get_colorimetry(void *input);
+u32 hdmi_edid_get_phys_width(void *input);
+u32 hdmi_edid_get_phys_height(void *input);
#endif /* __HDMI_EDID_H__ */
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
index 747c245bf78e..8623a14df4ab 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
@@ -4125,6 +4125,7 @@ sysfs_err:
static int hdmi_tx_evt_handle_check_param(struct hdmi_tx_ctrl *hdmi_ctrl)
{
struct mdss_panel_info *pinfo = &hdmi_ctrl->panel_data.panel_info;
+ void *data = NULL;
int new_vic = -1;
int rc = 0;
@@ -4136,6 +4137,10 @@ static int hdmi_tx_evt_handle_check_param(struct hdmi_tx_ctrl *hdmi_ctrl)
goto end;
}
+ data = hdmi_tx_get_fd(HDMI_TX_FEAT_EDID);
+ pinfo->physical_width = hdmi_edid_get_phys_width(data);
+ pinfo->physical_height = hdmi_edid_get_phys_height(data);
+
/*
* return value of 1 lets mdss know that panel
* needs a reconfig due to new resolution and