From cfabc2bcfe357aa6e523274e2036752e91816f92 Mon Sep 17 00:00:00 2001 From: Chandan Uddaraju Date: Tue, 26 Jul 2016 16:01:54 -0700 Subject: [PATCH] mdss: display-port: add support to send HPD event to framework Add support to send switch event to framework when the HDP status changes. This switch event is shared between HDMI and DP. Change-Id: I13161bd8b2a7777abbe2521178c5b1b1b6416eea Signed-off-by: Chandan Uddaraju --- drivers/video/fbdev/msm/mdss_dp.c | 106 ++++++++++++++++++++-- drivers/video/fbdev/msm/mdss_dp.h | 4 + drivers/video/fbdev/msm/mdss_fb.c | 4 +- drivers/video/fbdev/msm/mdss_hdmi_panel.c | 2 +- drivers/video/fbdev/msm/mdss_hdmi_panel.h | 3 + drivers/video/fbdev/msm/mdss_mdp_ctl.c | 4 +- drivers/video/fbdev/msm/mdss_panel.h | 6 +- 7 files changed, 112 insertions(+), 17 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c index eefea9f117c0..0ac5ef4f750c 100644 --- a/drivers/video/fbdev/msm/mdss_dp.c +++ b/drivers/video/fbdev/msm/mdss_dp.c @@ -33,6 +33,7 @@ #include "mdss.h" #include "mdss_dp.h" #include "mdss_dp_util.h" +#include "mdss_hdmi_panel.h" #include "mdss_debug.h" #define RGB_COMPONENTS 3 @@ -863,7 +864,7 @@ int mdss_dp_wait4train(struct mdss_dp_drv_pdata *dp_drv) #define DEFAULT_VIDEO_RESOLUTION HDMI_VFRMT_640x480p60_4_3 -static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv) +static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv, u32 vic) { struct mdss_panel_info *pinfo; struct msm_hdmi_mode_timing_info timing = {0}; @@ -875,8 +876,7 @@ static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv) } dp_drv->ds_data.ds_registered = false; - ret = hdmi_get_supported_mode(&timing, &dp_drv->ds_data, - DEFAULT_VIDEO_RESOLUTION); + ret = hdmi_get_supported_mode(&timing, &dp_drv->ds_data, vic); pinfo = &dp_drv->panel_data.panel_info; if (ret || !timing.supported || !pinfo) { @@ -884,6 +884,7 @@ static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv) return -EINVAL; } + dp_drv->vic = vic; pinfo->xres = timing.active_h; pinfo->yres = timing.active_v; pinfo->clk_rate = timing.pixel_freq * 1000; @@ -895,7 +896,7 @@ static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv) pinfo->lcdc.v_front_porch = timing.front_porch_v; pinfo->lcdc.v_pulse_width = timing.pulse_width_v; - pinfo->type = EDP_PANEL; + pinfo->type = DP_PANEL; pinfo->pdest = DISPLAY_4; pinfo->wait_cycle = 0; pinfo->bpp = 24; @@ -904,6 +905,10 @@ static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv) pinfo->lcdc.border_clr = 0; /* blk */ pinfo->lcdc.underflow_clr = 0xff; /* blue */ pinfo->lcdc.hsync_skew = 0; + pinfo->is_pluggable = true; + + pr_debug("update res. vic= %d, pclk_rate = %llu\n", + dp_drv->vic, pinfo->clk_rate); return 0; } /* dp_init_panel_info */ @@ -963,6 +968,9 @@ int mdss_dp_on(struct mdss_panel_data *pdata) } + if (dp_drv->new_vic && (dp_drv->new_vic != dp_drv->vic)) + dp_init_panel_info(dp_drv, dp_drv->new_vic); + mdss_dp_phy_aux_setup(&dp_drv->phy_io); mdss_dp_irq_enable(dp_drv); @@ -1072,6 +1080,44 @@ int mdss_dp_off(struct mdss_panel_data *pdata) return 0; } +static void mdss_dp_send_cable_notification( + struct mdss_dp_drv_pdata *dp, int val) +{ + int state = 0; + + if (!dp) { + DEV_ERR("%s: invalid input\n", __func__); + return; + } + state = dp->sdev.state; + + switch_set_state(&dp->sdev, val); + + DEV_INFO("%s: cable state %s %d\n", __func__, + dp->sdev.state == state ? + "is same" : "switched to", + dp->sdev.state); +} + +static int mdss_dp_register_switch_event(struct mdss_dp_drv_pdata *dp) +{ + int rc = -EINVAL; + + if (!dp) { + DEV_ERR("%s: invalid input\n", __func__); + goto end; + } + + dp->sdev.name = "hdmi"; + rc = switch_dev_register(&dp->sdev); + if (rc) { + DEV_ERR("%s: display switch registration failed\n", __func__); + goto end; + } +end: + return rc; +} + static int mdss_dp_edid_init(struct mdss_panel_data *pdata) { struct mdss_dp_drv_pdata *dp_drv = NULL; @@ -1097,9 +1143,6 @@ static int mdss_dp_edid_init(struct mdss_panel_data *pdata) return -ENODEV; } - edid_init_data.buf = edid_init_data.buf; - edid_init_data.buf_size = edid_init_data.buf_size; - /* Use the existing EDID buffer for 1080p */ memcpy(edid_init_data.buf, edid_buf1, sizeof(edid_buf1)); dp_drv->panel_data.panel_info.edid_data = edid_data; @@ -1152,6 +1195,8 @@ static int mdss_dp_host_init(struct mdss_panel_data *pdata) goto edid_parser_error; } + mdss_dp_send_cable_notification(dp_drv, true); + return ret; edid_parser_error: @@ -1162,6 +1207,44 @@ vreg_error: return ret; } +static int mdss_dp_check_params(struct mdss_dp_drv_pdata *dp, void *arg) +{ + struct mdss_panel_info *var_pinfo, *pinfo; + int rc = 0; + int new_vic = -1; + + if (!dp || !arg) + return 0; + + pinfo = &dp->panel_data.panel_info; + var_pinfo = (struct mdss_panel_info *)arg; + + pr_debug("reconfig xres: %d yres: %d, current xres: %d yres: %d\n", + var_pinfo->xres, var_pinfo->yres, + pinfo->xres, pinfo->yres); + + new_vic = hdmi_panel_get_vic(var_pinfo, &dp->ds_data); + + if ((new_vic < 0) || (new_vic > HDMI_VFRMT_MAX)) { + DEV_ERR("%s: invalid or not supported vic\n", __func__); + goto end; + } + + /* + * return value of 1 lets mdss know that panel + * needs a reconfig due to new resolution and + * it will issue close and open subsequently. + */ + if (new_vic != dp->vic) { + rc = 1; + DEV_ERR("%s: res change %d ==> %d\n", __func__, + dp->vic, new_vic); + } + dp->new_vic = new_vic; +end: + return rc; +} + static int mdss_dp_event_handler(struct mdss_panel_data *pdata, int event, void *arg) { @@ -1194,9 +1277,13 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata, dp->kobj = &fbi->dev->kobj; dp->fb_node = fbi->node; mdss_dp_edid_init(pdata); + mdss_dp_register_switch_event(dp); + break; + case MDSS_EVENT_CHECK_PARAMS: + rc = mdss_dp_check_params(dp, arg); break; default: - pr_debug("%s: unhandled event=%d\n", __func__, event); + pr_debug("unhandled event=%d\n", event); break; } return rc; @@ -1220,7 +1307,7 @@ static int mdss_dp_device_register(struct mdss_dp_drv_pdata *dp_drv) { int ret; - ret = dp_init_panel_info(dp_drv); + ret = dp_init_panel_info(dp_drv, DEFAULT_VIDEO_RESOLUTION); if (ret) { DEV_ERR("%s: dp_init_panel_info failed\n", __func__); return ret; @@ -1493,6 +1580,7 @@ static void usbpd_disconnect_callback(struct usbpd_svid_handler *hdlr) mutex_lock(&dp_drv->pd_msg_mutex); dp_drv->cable_connected = false; mutex_unlock(&dp_drv->pd_msg_mutex); + mdss_dp_send_cable_notification(dp_drv, false); } static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd, diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h index 10fcdec49515..03646cd7cc65 100644 --- a/drivers/video/fbdev/msm/mdss_dp.h +++ b/drivers/video/fbdev/msm/mdss_dp.h @@ -21,6 +21,7 @@ #include #include #include +#include #include "mdss_hdmi_util.h" #include "mdss_hdmi_edid.h" @@ -430,8 +431,11 @@ struct mdss_dp_drv_pdata { spinlock_t event_lock; spinlock_t lock; struct hdmi_util_ds_data ds_data; + struct switch_dev sdev; struct kobject *kobj; u32 max_pclk_khz; + u32 vic; + u32 new_vic; int fb_node; }; diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c index cc8ce49c7387..43e8373f18df 100644 --- a/drivers/video/fbdev/msm/mdss_fb.c +++ b/drivers/video/fbdev/msm/mdss_fb.c @@ -331,8 +331,8 @@ static ssize_t mdss_fb_get_type(struct device *dev, case WRITEBACK_PANEL: ret = snprintf(buf, PAGE_SIZE, "writeback panel\n"); break; - case EDP_PANEL: - ret = snprintf(buf, PAGE_SIZE, "edp panel\n"); + case DP_PANEL: + ret = snprintf(buf, PAGE_SIZE, "dp panel\n"); break; default: ret = snprintf(buf, PAGE_SIZE, "unknown panel\n"); diff --git a/drivers/video/fbdev/msm/mdss_hdmi_panel.c b/drivers/video/fbdev/msm/mdss_hdmi_panel.c index b4d3dad50d45..0335bf900866 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_panel.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_panel.c @@ -150,7 +150,7 @@ enum hdmi_scaling_info { HDMI_SCALING_HORZ_VERT, }; -static int hdmi_panel_get_vic(struct mdss_panel_info *pinfo, +int hdmi_panel_get_vic(struct mdss_panel_info *pinfo, struct hdmi_util_ds_data *ds_data) { int new_vic = -1; diff --git a/drivers/video/fbdev/msm/mdss_hdmi_panel.h b/drivers/video/fbdev/msm/mdss_hdmi_panel.h index 24d3b9b52798..e5cc1486f222 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_panel.h +++ b/drivers/video/fbdev/msm/mdss_hdmi_panel.h @@ -104,4 +104,7 @@ void *hdmi_panel_init(struct hdmi_panel_init_data *data); */ void hdmi_panel_deinit(void *input); +int hdmi_panel_get_vic(struct mdss_panel_info *pinfo, + struct hdmi_util_ds_data *ds_data); + #endif /* __MDSS_HDMI_PANEL_H__ */ diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index 3fc6d94393d5..3f2de6915c7e 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -2668,7 +2668,7 @@ int mdss_mdp_ctl_splash_finish(struct mdss_mdp_ctl *ctl, bool handoff) { switch (ctl->panel_data->panel_info.type) { case MIPI_VIDEO_PANEL: - case EDP_PANEL: + case DP_PANEL: case DTV_PANEL: return mdss_mdp_video_reconfigure_splash_done(ctl, handoff); case MIPI_CMD_PANEL: @@ -3686,7 +3686,7 @@ struct mdss_mdp_ctl *mdss_mdp_ctl_init(struct mdss_panel_data *pdata, ctl->disable_prefill = false; switch (pdata->panel_info.type) { - case EDP_PANEL: + case DP_PANEL: ctl->is_video_mode = true; ctl->intf_num = MDSS_MDP_INTF0; ctl->intf_type = MDSS_INTF_EDP; diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index 7a49f37660dd..bde137269422 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -51,7 +51,7 @@ struct panel_id { #define MIPI_CMD_PANEL 9 /* MIPI */ #define WRITEBACK_PANEL 10 /* Wifi display */ #define LVDS_PANEL 11 /* LVDS */ -#define EDP_PANEL 12 /* LVDS */ +#define DP_PANEL 12 /* LVDS */ #define DSC_PPS_LEN 128 @@ -61,7 +61,7 @@ static inline const char *mdss_panel2str(u32 panel) #define PANEL_NAME(n) [n ## _PANEL] = __stringify(n) PANEL_NAME(MIPI_VIDEO), PANEL_NAME(MIPI_CMD), - PANEL_NAME(EDP), + PANEL_NAME(DP), PANEL_NAME(HDMI), PANEL_NAME(DTV), PANEL_NAME(WRITEBACK), @@ -811,7 +811,7 @@ static inline u32 mdss_panel_get_framerate(struct mdss_panel_info *panel_info) case MIPI_CMD_PANEL: frame_rate = panel_info->mipi.frame_rate; break; - case EDP_PANEL: + case DP_PANEL: frame_rate = panel_info->edp.frame_rate; break; case WRITEBACK_PANEL: