From 03a1feb1b65e53a1a6a9fc5e683e5f12c68fec2c Mon Sep 17 00:00:00 2001 From: Ajay Singh Parmar Date: Tue, 13 Dec 2016 14:59:22 -0800 Subject: [PATCH] msm: mdss: dp: fix cable connection from boot-up Wait for the user modules to come up during boot up before sending events. In case user modules are not yet up, events sent to them are ignored. If the cable is connected at boot up, wait for user modules to enable hpd (Hot Plug Detect). On receiving hpd, check if the cable is already connected, if so, notify user modules so that power on sequence can be initialized. Change-Id: I91242fbfd32a478324b98edba4349081d9e55601 Signed-off-by: Ajay Singh Parmar --- drivers/video/fbdev/msm/mdss_dp.c | 62 ++++++++++++++++++++++++++++++- drivers/video/fbdev/msm/mdss_dp.h | 1 + 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c index 90284f31f78e..f81226b6fe15 100644 --- a/drivers/video/fbdev/msm/mdss_dp.c +++ b/drivers/video/fbdev/msm/mdss_dp.c @@ -68,6 +68,7 @@ static int mdss_dp_off_irq(struct mdss_dp_drv_pdata *dp_drv); static void mdss_dp_mainlink_push_idle(struct mdss_panel_data *pdata); static inline void mdss_dp_link_retraining(struct mdss_dp_drv_pdata *dp); static void mdss_dp_handle_attention(struct mdss_dp_drv_pdata *dp_drv); +static void dp_send_events(struct mdss_dp_drv_pdata *dp, u32 events); static void mdss_dp_put_dt_clk_data(struct device *dev, struct dss_module_power *module_power) @@ -1868,13 +1869,69 @@ static ssize_t mdss_dp_sysfs_rda_s3d_mode(struct device *dev, return ret; } +static ssize_t mdss_dp_wta_hpd(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int hpd; + ssize_t ret = strnlen(buf, PAGE_SIZE); + struct mdss_dp_drv_pdata *dp = mdss_dp_get_drvdata(dev); + + if (!dp) { + pr_err("invalid data\n"); + ret = -EINVAL; + goto end; + } + + ret = kstrtoint(buf, 10, &hpd); + if (ret) { + pr_err("kstrtoint failed. ret=%d\n", (int)ret); + goto end; + } + + dp->hpd = !!hpd; + pr_debug("hpd=%d\n", dp->hpd); + + if (dp->hpd && dp->cable_connected) { + if (dp->alt_mode.current_state & DP_CONFIGURE_DONE) { + mdss_dp_host_init(&dp->panel_data); + mdss_dp_process_hpd_high(dp); + } else { + dp_send_events(dp, EV_USBPD_DISCOVER_MODES); + } + } else if (!dp->hpd && dp->power_on) { + mdss_dp_notify_clients(dp, false); + } +end: + return ret; +} + +static ssize_t mdss_dp_rda_hpd(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t ret; + struct mdss_dp_drv_pdata *dp = mdss_dp_get_drvdata(dev); + + if (!dp) { + pr_err("invalid input\n"); + return -EINVAL; + } + + ret = snprintf(buf, PAGE_SIZE, "%d\n", dp->hpd); + pr_debug("hpd: %d\n", dp->hpd); + + return ret; +} + static DEVICE_ATTR(connected, S_IRUGO, mdss_dp_rda_connected, NULL); static DEVICE_ATTR(s3d_mode, S_IRUGO | S_IWUSR, mdss_dp_sysfs_rda_s3d_mode, mdss_dp_sysfs_wta_s3d_mode); +static DEVICE_ATTR(hpd, S_IRUGO | S_IWUSR, mdss_dp_rda_hpd, + mdss_dp_wta_hpd); static struct attribute *mdss_dp_fs_attrs[] = { &dev_attr_connected.attr, &dev_attr_s3d_mode.attr, + &dev_attr_hpd.attr, NULL, }; @@ -2341,8 +2398,9 @@ static void usbpd_connect_callback(struct usbpd_svid_handler *hdlr) } mdss_dp_update_cable_status(dp_drv, true); - dp_send_events(dp_drv, EV_USBPD_DISCOVER_MODES); - pr_debug("discover_mode event sent\n"); + + if (dp_drv->hpd) + dp_send_events(dp_drv, EV_USBPD_DISCOVER_MODES); } static void usbpd_disconnect_callback(struct usbpd_svid_handler *hdlr) diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h index 3b9420e1c791..9b1fb7fc3dcd 100644 --- a/drivers/video/fbdev/msm/mdss_dp.h +++ b/drivers/video/fbdev/msm/mdss_dp.h @@ -400,6 +400,7 @@ struct mdss_dp_drv_pdata { bool link_clks_on; bool power_on; bool sink_info_read; + bool hpd; /* dp specific */ unsigned char *base;