Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0410649f authored by Ajay Singh Parmar's avatar Ajay Singh Parmar
Browse files

msm: mdss: displayport: fix alt mode sequence



Some sinks expect configure command before notifying hpd
as high in status or attention command. Do not wait for
hpd to go high to send configure command to sink. Once the
configure command has been sent to sink, sink may send attention
command back to source with hpd high. Configure source power on
if attention command is received with hpd high.

Change-Id: Ic5254da65f3720a8313881bc419ec912a0ed6997
Signed-off-by: default avatarAjay Singh Parmar <aparmar@codeaurora.org>
parent c30ea8b0
Loading
Loading
Loading
Loading
+74 −62
Original line number Diff line number Diff line
@@ -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;
		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);
		}
		break;
	case USBPD_SVDM_ENTER_MODE:
		if (cmd_type == SVDM_CMD_TYPE_RESP_ACK) {
			dp_drv->alt_mode.current_state = ENTER_MODE_DONE;
		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);
		}
		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) {
		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;
					dp_send_events
						(dp_drv, EV_USBPD_DP_CONFIGURE);
				}
			}
		} else {
			pr_debug("unknown response: %d for Attention\n",
			       cmd_type);
		}

		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;
		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);
		}
		} else {
			pr_err("unknown response: %d for DP_Status\n",
			       cmd_type);
		}
		break;
	case DP_VDM_CONFIGURE:
		if (cmd_type == SVDM_CMD_TYPE_RESP_ACK) {
			dp_drv->alt_mode.current_state = DP_CONFIGURE_DONE;
		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);
+6 −6
Original line number Diff line number Diff line
@@ -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 {