From: Luo wei <lw@rock-chips.com>
Date: Wed, 18 Jan 2017 09:49:34 +0000 (+0800)
Subject: video: rockchip: add auto dp support for vr product
X-Git-Tag: firefly_0821_release~659
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=ec6d8f10b90b74a2ded026e98cfbb6a02d794edb;p=firefly-linux-kernel-4.4.55.git

video: rockchip: add auto dp support for vr product

Change-Id: Ic4e4a3c0214c23bd55d883df6d2106646ef33614
Signed-off-by: Luo wei <lw@rock-chips.com>
---

diff --git a/drivers/video/rockchip/display-sys.c b/drivers/video/rockchip/display-sys.c
index 4d9e6670f2f2..6db202ae63be 100644
--- a/drivers/video/rockchip/display-sys.c
+++ b/drivers/video/rockchip/display-sys.c
@@ -448,6 +448,22 @@ static ssize_t debug_store(struct device *dev,
 
 static DEVICE_ATTR_RW(debug);
 
+static ssize_t prop_show(struct device *dev,
+			 struct device_attribute *attr, char *buf)
+{
+	struct rk_display_device *dsp = dev_get_drvdata(dev);
+	int ret = -EINVAL;
+
+	mutex_lock(&dsp->lock);
+	if (dsp->ops && dsp->ops->getvrinfo)
+		ret = dsp->ops->getvrinfo(dsp, buf);
+	mutex_unlock(&dsp->lock);
+
+	return ret;
+}
+
+static DEVICE_ATTR_RO(prop);
+
 static struct attribute *display_device_attrs[] = {
 	&dev_attr_name.attr,
 	&dev_attr_type.attr,
@@ -462,6 +478,7 @@ static struct attribute *display_device_attrs[] = {
 	&dev_attr_audioinfo.attr,
 	&dev_attr_monspecs.attr,
 	&dev_attr_debug.attr,
+	&dev_attr_prop.attr,
 	NULL,
 };
 
diff --git a/drivers/video/rockchip/dp/rockchip_dp.c b/drivers/video/rockchip/dp/rockchip_dp.c
index 6570937a9c9c..0e14cf392e44 100644
--- a/drivers/video/rockchip/dp/rockchip_dp.c
+++ b/drivers/video/rockchip/dp/rockchip_dp.c
@@ -1,5 +1,6 @@
 #include "rockchip_dp.h"
 #include <linux/delay.h>
+#include <linux/of_gpio.h>
 
 static int rockchip_dp_removed(struct hdmi *hdmi_drv)
 {
@@ -201,6 +202,62 @@ static int rockchip_dp_fb_event_notify(struct notifier_block *self,
 	return NOTIFY_OK;
 }
 
+static int cdn_dp_get_prop_dts(struct hdmi *hdmi, struct device_node *np)
+{
+	const struct property *prop;
+	int i = 0, nstates = 0;
+	const __be32 *val;
+	int value;
+	struct edid_prop_value *pval = NULL;
+
+	if (!hdmi || !np)
+		return -EINVAL;
+
+	if (!of_property_read_u32(np, "dp_edid_auto_support", &value))
+		hdmi->edid_auto_support = value;
+
+	prop = of_find_property(np, "dp_edid_prop_value", NULL);
+	if (!prop || !prop->value) {
+		pr_info("%s:No edid-prop-value, %d\n", __func__, !prop);
+		return -EINVAL;
+	}
+
+	nstates = (prop->length / sizeof(struct edid_prop_value));
+	pval = kcalloc(nstates, sizeof(struct edid_prop_value), GFP_NOWAIT);
+	if (!pval)
+		return -ENOMEM;
+
+	for (i = 0, val = prop->value; i < nstates; i++) {
+		pval[i].vid = be32_to_cpup(val++);
+		pval[i].pid = be32_to_cpup(val++);
+		pval[i].sn = be32_to_cpup(val++);
+		pval[i].xres = be32_to_cpup(val++);
+		pval[i].yres = be32_to_cpup(val++);
+		pval[i].vic = be32_to_cpup(val++);
+		pval[i].width = be32_to_cpup(val++);
+		pval[i].height = be32_to_cpup(val++);
+		pval[i].x_w = be32_to_cpup(val++);
+		pval[i].x_h = be32_to_cpup(val++);
+		pval[i].hwrotation = be32_to_cpup(val++);
+		pval[i].einit = be32_to_cpup(val++);
+		pval[i].vsync = be32_to_cpup(val++);
+		pval[i].panel = be32_to_cpup(val++);
+		pval[i].scan = be32_to_cpup(val++);
+
+		pr_info("%s: 0x%x 0x%x 0x%x %d %d %d %d %d %d %d %d %d %d %d %d\n",
+			__func__, pval[i].vid, pval[i].pid, pval[i].sn,
+			pval[i].width, pval[i].height, pval[i].xres,
+			pval[i].yres, pval[i].vic, pval[i].x_w,
+			pval[i].x_h, pval[i].hwrotation, pval[i].einit,
+			pval[i].vsync, pval[i].panel, pval[i].scan);
+	}
+
+	hdmi->pvalue = pval;
+	hdmi->nstates = nstates;
+
+	return 0;
+}
+
 int cdn_dp_fb_register(struct platform_device *pdev, void *dp)
 {
 	struct hdmi_ops *rk_dp_ops;
@@ -260,6 +317,7 @@ int cdn_dp_fb_register(struct platform_device *pdev, void *dp)
 	dp_dev->hdmi->colormode = HDMI_COLOR_RGB_0_255;
 	dp_dev->dp = dp;
 
+	cdn_dp_get_prop_dts(dp_dev->hdmi, np);
 	dp_dev->fb_notif.notifier_call = rockchip_dp_fb_event_notify;
 	fb_register_client(&dp_dev->fb_notif);
 	dev_set_drvdata(dev, dp_dev);
diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmi-core.c b/drivers/video/rockchip/hdmi/rockchip-hdmi-core.c
index bd490b09a323..f3e75177a9fc 100644
--- a/drivers/video/rockchip/hdmi/rockchip-hdmi-core.c
+++ b/drivers/video/rockchip/hdmi/rockchip-hdmi-core.c
@@ -132,7 +132,14 @@ static void hdmi_wq_set_video(struct hdmi *hdmi)
 		video->color_input = HDMI_COLOR_RGB_0_255;
 
 	if ((hdmi->vic & HDMI_VIDEO_DMT) || (hdmi->vic & HDMI_VIDEO_DISCRETE_VR)) {
-		video->vic = hdmi->vic;
+		if (hdmi->edid_auto_support) {
+			if (hdmi->prop.value.vic)
+				video->vic = hdmi->prop.value.vic;
+			else
+				video->vic = hdmi->vic;
+		} else {
+			video->vic = hdmi->vic;
+		}
 		video->color_output_depth = 8;
 	} else {
 		video->vic = hdmi->vic & HDMI_VIC_MASK;
@@ -181,7 +188,8 @@ static void hdmi_wq_parse_edid(struct hdmi *hdmi)
 			continue;
 		}
 
-		rc = hdmi_edid_parse_base(pedid->raw[0], &extendblock, pedid);
+		rc = hdmi_edid_parse_base(hdmi,
+					  pedid->raw[0], &extendblock, pedid);
 		if (rc) {
 			dev_err(hdmi->dev,
 				"[HDMI] parse edid base block error\n");
diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmi-edid.c b/drivers/video/rockchip/hdmi/rockchip-hdmi-edid.c
index b8c4b3949549..70564716dd71 100644
--- a/drivers/video/rockchip/hdmi/rockchip-hdmi-edid.c
+++ b/drivers/video/rockchip/hdmi/rockchip-hdmi-edid.c
@@ -78,7 +78,30 @@ static int hdmi_edid_parse_dtd(unsigned char *block, struct fb_videomode *mode)
 	return E_HDMI_EDID_SUCCESS;
 }
 
-int hdmi_edid_parse_base(unsigned char *buf,
+static int edid_parse_prop_value(unsigned char *buf,
+				 struct hdmi_edid *pedid)
+{
+	unsigned char *block = &buf[0x36];
+
+	pedid->value.vid = ((buf[ID_MANUFACTURER_NAME_END] << 8) |
+				(buf[ID_MANUFACTURER_NAME]));
+	pedid->value.pid = ((buf[ID_MODEL + 1] << 8) |
+				(buf[ID_MODEL]));
+	pedid->value.sn = ((buf[ID_SERIAL_NUMBER + 3] << 24) |
+				(buf[ID_SERIAL_NUMBER + 2] << 16) |
+				(buf[ID_SERIAL_NUMBER + 1] << 8) |
+				buf[ID_SERIAL_NUMBER]);
+	pedid->value.xres = H_ACTIVE;
+	pedid->value.yres = V_ACTIVE;
+
+	pr_info("%s:read:vid=0x%x,pid=0x%x,sn=0x%x,xres=%d,yres=%d\n",
+		__func__, pedid->value.vid, pedid->value.pid,
+		pedid->value.sn, pedid->value.xres, pedid->value.yres);
+
+	return 0;
+}
+
+int hdmi_edid_parse_base(struct hdmi *hdmi, unsigned char *buf,
 			 int *extend_num, struct hdmi_edid *pedid)
 {
 	int rc = E_HDMI_EDID_SUCCESS;
@@ -119,6 +142,9 @@ int hdmi_edid_parse_base(unsigned char *buf,
 
 	fb_edid_to_monspecs(buf, pedid->specs);
 
+	if (hdmi->edid_auto_support)
+		edid_parse_prop_value(buf, pedid);
+
 out:
 	/* For some sink, edid checksum is failed because several
 	 * byte is wrong. To fix this case, we think it is a good
diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmi-lcdc.c b/drivers/video/rockchip/hdmi/rockchip-hdmi-lcdc.c
index d2fd1724ded0..1d3cce5a3fd2 100644
--- a/drivers/video/rockchip/hdmi/rockchip-hdmi-lcdc.c
+++ b/drivers/video/rockchip/hdmi/rockchip-hdmi-lcdc.c
@@ -862,6 +862,29 @@ static const struct hdmi_video_timing hdmi_mode[] = {
 		.pixelrepeat = 1,
 		.interface = OUT_P888,
 	},
+	{
+		/* samsung */
+		.mode = {
+			.name = "1440x2560@70Hz",
+			.refresh = 70,
+			.xres = 1440,
+			.yres = 2560,
+			.pixclock = 285000000,
+			.left_margin = 40,
+			.right_margin = 80,
+			.upper_margin = 2,
+			.lower_margin = 6,
+			.hsync_len = 20,
+			.vsync_len = 8,
+			.sync = 0,
+			.vmode = 0,
+			.flag = 0,
+		},
+		.vic = HDMI_VIDEO_DISCRETE_VR | 6,
+		.vic_2nd = 0,
+		.pixelrepeat = 1,
+		.interface = OUT_P888,
+	},
 };
 
 static int hdmi_set_info(struct rk_screen *screen, struct hdmi *hdmi)
@@ -875,10 +898,24 @@ static int hdmi_set_info(struct rk_screen *screen, struct hdmi *hdmi)
 	if (hdmi->vic == 0)
 		hdmi->vic = hdmi->property->defaultmode;
 
-	if ((hdmi->vic & HDMI_VIDEO_DMT) || (hdmi->vic & HDMI_VIDEO_DISCRETE_VR))
-		vic = hdmi->vic;
-	else
-		vic = hdmi->vic & HDMI_VIC_MASK;
+	if (hdmi->edid_auto_support) {
+		if ((hdmi->vic & HDMI_VIDEO_DMT) ||
+		    (hdmi->vic & HDMI_VIDEO_DISCRETE_VR)) {
+			if (hdmi->prop.value.vic)
+				vic = hdmi->prop.value.vic;
+			else
+				vic = hdmi->vic;
+		} else {
+			vic = hdmi->vic & HDMI_VIC_MASK;
+		}
+	} else {
+		if ((hdmi->vic & HDMI_VIDEO_DMT) ||
+		    (hdmi->vic & HDMI_VIDEO_DISCRETE_VR))
+			vic = hdmi->vic;
+		else
+			vic = hdmi->vic & HDMI_VIC_MASK;
+	}
+
 	for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
 		if (hdmi_mode[i].vic == vic ||
 		    hdmi_mode[i].vic_2nd == vic)
@@ -959,6 +996,15 @@ static int hdmi_set_info(struct rk_screen *screen, struct hdmi *hdmi)
 	screen->overscan.top = hdmi->yscale;
 	screen->overscan.right = hdmi->xscale;
 	screen->overscan.bottom = hdmi->yscale;
+
+	screen->width = hdmi->prop.value.width;
+	screen->height = hdmi->prop.value.height;
+	pr_info("%s:line=%d %d %d %d %d %d %d %d %d\n",
+		__func__, __LINE__, screen->mode.xres, screen->mode.yres,
+		screen->mode.left_margin, screen->mode.right_margin,
+		screen->mode.upper_margin, screen->mode.lower_margin,
+		screen->mode.hsync_len, screen->mode.vsync_len);
+
 	return 0;
 }
 
@@ -1240,6 +1286,66 @@ static void hdmi_sort_modelist(struct hdmi_edid *edid, int feature)
 	}
 }
 
+static int edid_select_prop_value(struct hdmi *hdmi)
+{
+	struct edid_prop_value *prop_value = NULL;
+	int nstates = 0;
+	int i, vid, pid, sn, xres, yres, reboot = 0;
+
+	prop_value = hdmi->pvalue;
+	nstates = hdmi->nstates;
+
+	if (!prop_value) {
+		pr_info("%s:pvalue is NULL\n", __func__);
+		return -1;
+	}
+
+	vid = hdmi->edid.value.vid;
+	pid = hdmi->edid.value.pid;
+	sn = hdmi->edid.value.sn;
+	xres = hdmi->edid.value.xres;
+	yres = hdmi->edid.value.yres;
+
+	for (i = 0; i < nstates; i++) {
+		if ((prop_value[i].vid == vid) &&
+		    (prop_value[i].pid == pid) &&
+		    (prop_value[i].sn == sn) &&
+		    (prop_value[i].xres == xres) &&
+		    (prop_value[i].yres == yres)) {
+			hdmi->edid.value = prop_value[i];
+			hdmi->prop.value = prop_value[i];
+			if ((hdmi->prop.valid) &&
+			    ((hdmi->prop.last_vid != vid) ||
+			    (hdmi->prop.last_pid != pid) ||
+			    (hdmi->prop.last_sn != sn) ||
+			    (hdmi->prop.last_xres != xres) ||
+			    (hdmi->prop.last_yres != yres))) {
+				reboot = 1;
+			} else {
+				reboot = 0;
+			}
+
+			hdmi->prop.last_vid = vid;
+			hdmi->prop.last_pid = pid;
+			hdmi->prop.last_sn = sn;
+			hdmi->prop.last_xres = xres;
+			hdmi->prop.last_yres = yres;
+			hdmi->prop.valid = 1;
+			pr_info("%s:i=%d reboot=%d,valid=%d\n",
+				__func__, i, reboot, hdmi->prop.valid);
+
+			break;
+		}
+	}
+
+	if (reboot) {
+		dev_info(hdmi->dev, "%s:kernel_restart\n", __func__);
+		kernel_restart(NULL);
+	}
+
+	return 0;
+}
+
 /**
  * hdmi_ouputmode_select - select hdmi transmitter output mode: hdmi or dvi?
  * @hdmi: handle of hdmi
@@ -1261,6 +1367,9 @@ int hdmi_ouputmode_select(struct hdmi *hdmi, int edid_ok)
 		hdmi->edid.ycbcr422 = 0;
 	}
 
+	if (hdmi->edid_auto_support)
+		edid_select_prop_value(hdmi);
+
 	if (head->next == head) {
 		dev_info(hdmi->dev,
 			 "warning: no CEA video mode parsed from EDID !!!!\n");
diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmi-sysfs.c b/drivers/video/rockchip/hdmi/rockchip-hdmi-sysfs.c
index 5b4831332f39..d5d965049db7 100644
--- a/drivers/video/rockchip/hdmi/rockchip-hdmi-sysfs.c
+++ b/drivers/video/rockchip/hdmi/rockchip-hdmi-sysfs.c
@@ -541,6 +541,30 @@ static int hdmi_get_debug(struct rk_display_device *device, char *buf)
 	return len;
 }
 
+static int vr_get_info(struct rk_display_device *device, char *buf)
+{
+	struct hdmi *hdmi = device->priv_data;
+	int valid, width, height, x_w, x_h, hwr, einit, vsync, panel, scan;
+	int len = 0;
+
+	valid = hdmi->prop.valid;
+	width = hdmi->prop.value.width;
+	height = hdmi->prop.value.height;
+	x_w = hdmi->prop.value.x_w;
+	x_h = hdmi->prop.value.x_h;
+	hwr = hdmi->prop.value.hwrotation;
+	einit = hdmi->prop.value.einit;
+	vsync = hdmi->prop.value.vsync;
+	panel = hdmi->prop.value.panel;
+	scan = hdmi->prop.value.scan;
+
+	len = snprintf(buf, PAGE_SIZE,
+		"valid=%d,width=%d,height=%d,xres=%d,yres=%d,hwrotation=%d,orientation=%d,vsync=%d,panel=%d,scan=%d\n",
+		valid, width, height, x_w, x_h, hwr, einit, vsync, panel, scan);
+
+	return len;
+}
+
 static struct rk_display_ops hdmi_display_ops = {
 	.setenable = hdmi_set_enable,
 	.getenable = hdmi_get_enable,
@@ -557,6 +581,7 @@ static struct rk_display_ops hdmi_display_ops = {
 	.setscale = hdmi_set_scale,
 	.getscale = hdmi_get_scale,
 	.getdebug = hdmi_get_debug,
+	.getvrinfo = vr_get_info,
 };
 
 static int hdmi_display_probe(struct rk_display_device *device, void *devdata)
@@ -565,6 +590,11 @@ static int hdmi_display_probe(struct rk_display_device *device, void *devdata)
 
 	device->owner = THIS_MODULE;
 	strcpy(device->type, "HDMI");
+	if (strstr(hdmi->property->name, "dp"))
+		strcpy(device->type, "DP");
+	else
+		strcpy(device->type, "HDMI");
+
 	device->priority = DISPLAY_PRIORITY_HDMI;
 	device->name = hdmi->property->name;
 	device->property = hdmi->property->display;
diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmi.h b/drivers/video/rockchip/hdmi/rockchip-hdmi.h
index a5e8dd548080..75e1c9f6420e 100644
--- a/drivers/video/rockchip/hdmi/rockchip-hdmi.h
+++ b/drivers/video/rockchip/hdmi/rockchip-hdmi.h
@@ -8,6 +8,7 @@
 #include <linux/switch.h>
 #endif
 #include <sound/pcm_params.h>
+#include <linux/reboot.h>
 
 #define HDMI_VIDEO_NORMAL				0
 #define HDMI_VIDEO_DMT					BIT(9)
@@ -284,6 +285,36 @@ struct hdmi_audio {
 };
 
 #define HDMI_MAX_EDID_BLOCK		8
+
+struct edid_prop_value {
+	int vid;
+	int pid;
+	int sn;
+	int xres;
+	int yres;
+	int vic;
+	int width;
+	int height;
+	int x_w;
+	int x_h;
+	int hwrotation;
+	int einit;
+	int vsync;
+	int panel;
+	int scan;
+};
+
+struct edid_prop_data {
+	struct edid_prop_value value;
+
+	int valid;
+	int last_vid;
+	int last_pid;
+	int last_sn;
+	int last_xres;
+	int last_yres;
+};
+
 /* HDMI EDID Information */
 struct hdmi_edid {
 	unsigned char sink_hdmi;	/* HDMI display device flag */
@@ -313,6 +344,8 @@ struct hdmi_edid {
 	unsigned char dual_view;
 	unsigned char osd_disparity_3d;
 
+	struct edid_prop_value value;
+
 	unsigned int colorimetry;
 	struct fb_monspecs	*specs;	/*Device spec*/
 	struct list_head modelist;	/*Device supported display mode list*/
@@ -414,6 +447,11 @@ struct hdmi {
 	int colormode;			/* Output color mode*/
 	int colorimetry;		/* Output colorimetry */
 	struct hdmi_edid edid;		/* EDID information*/
+	struct edid_prop_data prop;	/* Property for dp */
+	struct edid_prop_value *pvalue;
+	int nstates;
+	int edid_auto_support;		/* Auto dp enable flag */
+
 	int enable;			/* Enable flag*/
 	int sleep;			/* Sleep flag*/
 	int vic;			/* HDMI output video information code*/
@@ -515,7 +553,7 @@ struct rk_display_device *hdmi_register_display_sysfs(struct hdmi *hdmi,
 						      struct device *parent);
 void hdmi_unregister_display_sysfs(struct hdmi *hdmi);
 
-int hdmi_edid_parse_base(unsigned char *buf,
+int hdmi_edid_parse_base(struct hdmi *hdmi, unsigned char *buf,
 			 int *extend_num, struct hdmi_edid *pedid);
 int hdmi_edid_parse_extensions(unsigned char *buf,
 			       struct hdmi_edid *pedid);
diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2.c b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2.c
index 4f7ee815035e..2fe24374eff2 100644
--- a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2.c
+++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2.c
@@ -424,6 +424,62 @@ static const struct of_device_id rk_hdmi_dt_ids[] = {
 	{}
 };
 
+static int hdmi_get_prop_dts(struct hdmi *hdmi, struct device_node *np)
+{
+	const struct property *prop;
+	int i = 0, nstates = 0;
+	const __be32 *val;
+	int value;
+	struct edid_prop_value *pval = NULL;
+
+	if (!hdmi || !np) {
+		pr_info("%s:line=%d hdmi or np is null\n", __func__, __LINE__);
+		return -1;
+	}
+
+	if (!of_property_read_u32(np, "hdmi_edid_auto_support", &value))
+		hdmi->edid_auto_support = value;
+
+	prop = of_find_property(np, "hdmi_edid_prop_value", NULL);
+	if (!prop || !prop->value) {
+		pr_info("%s:No edid-prop-value, %d\n", __func__, !prop);
+		return -1;
+	}
+
+	nstates = (prop->length / sizeof(struct edid_prop_value));
+	pval = kcalloc(nstates, sizeof(struct edid_prop_value), GFP_NOWAIT);
+
+	for (i = 0, val = prop->value; i < nstates; i++) {
+		pval[i].vid = be32_to_cpup(val++);
+		pval[i].pid = be32_to_cpup(val++);
+		pval[i].sn = be32_to_cpup(val++);
+		pval[i].xres = be32_to_cpup(val++);
+		pval[i].yres = be32_to_cpup(val++);
+		pval[i].vic = be32_to_cpup(val++);
+		pval[i].width = be32_to_cpup(val++);
+		pval[i].height = be32_to_cpup(val++);
+		pval[i].x_w = be32_to_cpup(val++);
+		pval[i].x_h = be32_to_cpup(val++);
+		pval[i].hwrotation = be32_to_cpup(val++);
+		pval[i].einit = be32_to_cpup(val++);
+		pval[i].vsync = be32_to_cpup(val++);
+		pval[i].panel = be32_to_cpup(val++);
+		pval[i].scan = be32_to_cpup(val++);
+
+		pr_info("%s: 0x%x 0x%x 0x%x %d %d %d %d %d %d %d %d %d %d %d %d\n",
+			__func__, pval[i].vid, pval[i].pid, pval[i].sn,
+			pval[i].width, pval[i].height, pval[i].xres,
+			pval[i].yres, pval[i].vic, pval[i].x_w,
+			pval[i].x_h, pval[i].hwrotation, pval[i].einit,
+			pval[i].vsync, pval[i].panel, pval[i].scan);
+	}
+
+	hdmi->pvalue = pval;
+	hdmi->nstates = nstates;
+
+	return 0;
+}
+
 static int rockchip_hdmiv2_parse_dt(struct hdmi_dev *hdmi_dev)
 {
 	int val = 0;
@@ -636,6 +692,8 @@ static int rockchip_hdmiv2_probe(struct platform_device *pdev)
 		ret = -ENOMEM;
 		goto failed1;
 	}
+
+	hdmi_get_prop_dts(hdmi_dev->hdmi, hdmi_dev->dev->of_node);
 	mutex_init(&hdmi_dev->ddc_lock);
 	hdmi_dev->hdmi->dev = &pdev->dev;
 	hdmi_dev->hdmi->soctype = hdmi_dev->soctype;
diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c
index bfe70d372d77..f38a1d8ce6e2 100644
--- a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c
+++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c
@@ -75,6 +75,8 @@ static const struct phy_mpll_config_tab PHY_MPLL_TABLE[] = {
 		1,	3,	0,	0,	0,	0,	3},
 	{269390000,	269390000,	0,	8,	0,	0,	0,
 		1,	0,	0,	0,	0,	0,	3},
+	{285000000,	285000000,	0,	8,	0,	0,	0,
+		1,	0,	0,	0,	0,	0,	3},
 	{297000000,	148500000,	0,	8,	0,	0,	0,
 		1,	0,	1,	0,	0,	0,	3},
 	{297000000,	297000000,	0,	8,	0,	0,	0,
diff --git a/drivers/video/rockchip/rk_fb.c b/drivers/video/rockchip/rk_fb.c
index 1be959bc7dc8..49fb77db091f 100644
--- a/drivers/video/rockchip/rk_fb.c
+++ b/drivers/video/rockchip/rk_fb.c
@@ -3777,6 +3777,15 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id)
 	}
 	kobject_uevent_env(&dev_drv->dev->kobj, KOBJ_CHANGE, envp);
 
+	if (dev_drv->cur_screen->width && dev_drv->cur_screen->height) {
+		/* for vr auto dp support */
+		info = rk_fb->fb[dev_drv->fb_index_base];
+		info->var.width = dev_drv->cur_screen->width;
+		info->var.height = dev_drv->cur_screen->height;
+		pr_info("%s:info->var.width=%d, info->var.height=%d\n",
+			__func__, info->var.width, info->var.height);
+	}
+
 	hdmi_switch_state = 1;
 	load_screen = true;
 	dev_drv->hdmi_switch = 0;
diff --git a/include/linux/display-sys.h b/include/linux/display-sys.h
old mode 100755
new mode 100644
index 5ce29973c5dd..ac3f3870c16b
--- a/include/linux/display-sys.h
+++ b/include/linux/display-sys.h
@@ -66,6 +66,7 @@ struct rk_display_ops {
 				char *audioinfo, int len);
 	int (*getmonspecs)(struct rk_display_device *,
 			   struct fb_monspecs *monspecs);
+	int (*getvrinfo)(struct rk_display_device *, char *);
 };
 
 struct rk_display_device {