diff options
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dp.c | 136 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dp.h | 12 |
2 files changed, 80 insertions, 68 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c index 4e68952d33a9..e8e9da0e928f 100644 --- a/drivers/video/fbdev/msm/mdss_dp.c +++ b/drivers/video/fbdev/msm/mdss_dp.c @@ -1360,6 +1360,7 @@ edid_error: mdss_dp_clk_ctrl(dp_drv, DP_CORE_PM, false); clk_error: mdss_dp_regulator_ctrl(dp_drv, false); + mdss_dp_config_gpios(dp_drv, false); vreg_error: return ret; } @@ -1964,10 +1965,50 @@ static void usbpd_disconnect_callback(struct usbpd_svid_handler *hdlr) pr_debug("cable disconnected\n"); mutex_lock(&dp_drv->pd_msg_mutex); dp_drv->cable_connected = false; + dp_drv->alt_mode.current_state = UNKNOWN_STATE; mutex_unlock(&dp_drv->pd_msg_mutex); mdss_dp_notify_clients(dp_drv, false); } +static int mdss_dp_validate_callback(u8 cmd, + enum usbpd_svdm_cmd_type cmd_type, int num_vdos) +{ + int ret = 0; + + if (cmd_type == SVDM_CMD_TYPE_RESP_NAK) { + pr_err("error: NACK\n"); + ret = -EINVAL; + goto end; + } + + if (cmd_type == SVDM_CMD_TYPE_RESP_BUSY) { + pr_err("error: BUSY\n"); + ret = -EBUSY; + goto end; + } + + if (cmd == USBPD_SVDM_ATTENTION) { + if (cmd_type != SVDM_CMD_TYPE_INITIATOR) { + pr_err("error: invalid cmd type for attention\n"); + ret = -EINVAL; + goto end; + } + + if (!num_vdos) { + pr_err("error: no vdo provided\n"); + ret = -EINVAL; + goto end; + } + } else { + if (cmd_type != SVDM_CMD_TYPE_RESP_ACK) { + pr_err("error: invalid cmd type\n"); + ret = -EINVAL; + } + } +end: + return ret; +} + static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd, enum usbpd_svdm_cmd_type cmd_type, const u32 *vdos, int num_vdos) @@ -1983,80 +2024,51 @@ static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd, pr_debug("callback -> cmd: 0x%x, *vdos = 0x%x, num_vdos = %d\n", cmd, *vdos, num_vdos); + if (mdss_dp_validate_callback(cmd, cmd_type, num_vdos)) + return; + switch (cmd) { case USBPD_SVDM_DISCOVER_MODES: - if (cmd_type == SVDM_CMD_TYPE_RESP_ACK) { - dp_drv->alt_mode.dp_cap.response = *vdos; - mdss_dp_usbpd_ext_capabilities - (&dp_drv->alt_mode.dp_cap); - dp_drv->alt_mode.current_state = DISCOVER_MODES_DONE; - dp_send_events(dp_drv, EV_USBPD_ENTER_MODE); - } else { - pr_err("unknown response: %d for Discover_modes\n", - cmd_type); - } + dp_drv->alt_mode.dp_cap.response = *vdos; + mdss_dp_usbpd_ext_capabilities(&dp_drv->alt_mode.dp_cap); + dp_drv->alt_mode.current_state |= DISCOVER_MODES_DONE; + dp_send_events(dp_drv, EV_USBPD_ENTER_MODE); break; case USBPD_SVDM_ENTER_MODE: - if (cmd_type == SVDM_CMD_TYPE_RESP_ACK) { - dp_drv->alt_mode.current_state = ENTER_MODE_DONE; - dp_send_events(dp_drv, EV_USBPD_DP_STATUS); - } else { - pr_err("unknown response: %d for Enter_mode\n", - cmd_type); - } + dp_drv->alt_mode.current_state |= ENTER_MODE_DONE; + dp_send_events(dp_drv, EV_USBPD_DP_STATUS); break; case USBPD_SVDM_ATTENTION: - if (cmd_type == SVDM_CMD_TYPE_INITIATOR) { - pr_debug("Attention. cmd_type=%d\n", - cmd_type); - if (!(dp_drv->alt_mode.current_state - == ENTER_MODE_DONE)) { - pr_debug("sending discover_mode\n"); - dp_send_events(dp_drv, EV_USBPD_DISCOVER_MODES); - break; - } - if (num_vdos == 1) { - dp_drv->alt_mode.dp_status.response = *vdos; - mdss_dp_usbpd_ext_dp_status - (&dp_drv->alt_mode.dp_status); - if (dp_drv->alt_mode.dp_status.hpd_high) { - pr_debug("HPD high\n"); - dp_drv->alt_mode.current_state = - DP_STATUS_DONE; - dp_send_events - (dp_drv, EV_USBPD_DP_CONFIGURE); - } - } - } else { - pr_debug("unknown response: %d for Attention\n", - cmd_type); - } + dp_drv->alt_mode.dp_status.response = *vdos; + mdss_dp_usbpd_ext_dp_status(&dp_drv->alt_mode.dp_status); + + if (!dp_drv->alt_mode.dp_status.hpd_high) + return; + + pr_debug("HPD high\n"); + + dp_drv->alt_mode.current_state |= DP_STATUS_DONE; + + if (dp_drv->alt_mode.current_state & DP_CONFIGURE_DONE) + mdss_dp_host_init(&dp_drv->panel_data); + else + dp_send_events(dp_drv, EV_USBPD_DP_CONFIGURE); break; case DP_VDM_STATUS: - if (cmd_type == SVDM_CMD_TYPE_RESP_ACK) { - dp_drv->alt_mode.dp_status.response = *vdos; - mdss_dp_usbpd_ext_dp_status - (&dp_drv->alt_mode.dp_status); - if (dp_drv->alt_mode.dp_status.hpd_high) { - pr_debug("HDP high\n"); - dp_drv->alt_mode.current_state = - DP_STATUS_DONE; - dp_send_events(dp_drv, EV_USBPD_DP_CONFIGURE); - } - } else { - pr_err("unknown response: %d for DP_Status\n", - cmd_type); + dp_drv->alt_mode.dp_status.response = *vdos; + mdss_dp_usbpd_ext_dp_status(&dp_drv->alt_mode.dp_status); + + if (!(dp_drv->alt_mode.current_state & DP_CONFIGURE_DONE)) { + dp_drv->alt_mode.current_state |= DP_STATUS_DONE; + dp_send_events(dp_drv, EV_USBPD_DP_CONFIGURE); } break; case DP_VDM_CONFIGURE: - if (cmd_type == SVDM_CMD_TYPE_RESP_ACK) { - dp_drv->alt_mode.current_state = DP_CONFIGURE_DONE; - pr_debug("config USBPD to DP done\n"); + dp_drv->alt_mode.current_state |= DP_CONFIGURE_DONE; + pr_debug("config USBPD to DP done\n"); + + if (dp_drv->alt_mode.dp_status.hpd_high) mdss_dp_host_init(&dp_drv->panel_data); - } else { - pr_err("unknown response: %d for DP_Configure\n", - cmd_type); - } break; default: pr_err("unknown cmd: %d\n", cmd); diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h index 6c391f6f7de0..a434d9c07800 100644 --- a/drivers/video/fbdev/msm/mdss_dp.h +++ b/drivers/video/fbdev/msm/mdss_dp.h @@ -170,12 +170,12 @@ struct usbpd_dp_status { }; enum dp_alt_mode_state { - ALT_MODE_INIT_STATE = 0, - DISCOVER_MODES_DONE, - ENTER_MODE_DONE, - DP_STATUS_DONE, - DP_CONFIGURE_DONE, - UNKNOWN_STATE, + UNKNOWN_STATE = 0, + ALT_MODE_INIT_STATE = BIT(0), + DISCOVER_MODES_DONE = BIT(1), + ENTER_MODE_DONE = BIT(2), + DP_STATUS_DONE = BIT(3), + DP_CONFIGURE_DONE = BIT(4), }; struct dp_alt_mode { |
