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

Commit e172c2c0 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm/dp: fix suspend/resume hot plug handling"

parents 7888bbf8 b5d5b854
Loading
Loading
Loading
Loading
+34 −27
Original line number Diff line number Diff line
@@ -80,6 +80,7 @@ struct dp_ctrl_private {
	atomic_t aborted;

	u32 vic;
	u32 stream_count;
	struct dp_mst_channel_info mst_ch_info;
};

@@ -150,7 +151,7 @@ static void dp_ctrl_push_idle(struct dp_ctrl_private *ctrl,
	if (!wait_for_completion_timeout(&ctrl->idle_comp,
			idle_pattern_completion_timeout_ms))
		pr_warn("time out\n");

	else
		pr_debug("mainlink off done\n");
}

@@ -176,17 +177,10 @@ static void dp_ctrl_configure_source_link_params(struct dp_ctrl_private *ctrl,
	}
}

static int dp_ctrl_wait4video_ready(struct dp_ctrl_private *ctrl)
static void dp_ctrl_wait4video_ready(struct dp_ctrl_private *ctrl)
{
	int ret = 0;

	ret = wait_for_completion_timeout(&ctrl->video_comp, HZ / 2);
	if (ret <= 0) {
		pr_err("SEND_VIDEO time out (%d)\n", ret);
		return -EINVAL;
	}

	return 0;
	if (!wait_for_completion_timeout(&ctrl->video_comp, HZ / 2))
		pr_warn("SEND_VIDEO time out\n");
}

static int dp_ctrl_update_sink_vx_px(struct dp_ctrl_private *ctrl,
@@ -567,7 +561,7 @@ static void dp_ctrl_disable_link_clock(struct dp_ctrl_private *ctrl)
	ctrl->power->clk_enable(ctrl->power, DP_LINK_PM, false);
}

static int dp_ctrl_link_setup(struct dp_ctrl_private *ctrl)
static int dp_ctrl_link_setup(struct dp_ctrl_private *ctrl, bool shallow)
{
	int rc = -EINVAL;
	u32 link_train_max_retries = 100;
@@ -585,13 +579,26 @@ static int dp_ctrl_link_setup(struct dp_ctrl_private *ctrl)
		pr_debug("bw_code=%d, lane_count=%d\n",
			link_params->bw_code, link_params->lane_count);

		dp_ctrl_enable_link_clock(ctrl);
		rc = dp_ctrl_enable_link_clock(ctrl);
		if (rc)
			break;

		dp_ctrl_configure_source_link_params(ctrl, true);

		rc = dp_ctrl_setup_main_link(ctrl);
		if (!rc)
			break;

		/*
		 * Shallow means link training failure is not important.
		 * If it fails, we still keep the link clocks on.
		 * In this mode, the system expects DP to be up
		 * even though the cable is removed. Disconnect interrupt
		 * will eventually trigger and shutdown DP.
		 */
		if (shallow)
			break;

		dp_ctrl_link_rate_down_shift(ctrl);

		dp_ctrl_configure_source_link_params(ctrl, false);
@@ -748,8 +755,10 @@ static int dp_ctrl_link_maintenance(struct dp_ctrl *dp_ctrl)

	ctrl->aux->state |= DP_STATE_LINK_MAINTENANCE_COMPLETED;

	if (ctrl->stream_count) {
		dp_ctrl_send_video(ctrl);
	ret = dp_ctrl_wait4video_ready(ctrl);
		dp_ctrl_wait4video_ready(ctrl);
	}
end:
	return ret;
}
@@ -785,7 +794,7 @@ static void dp_ctrl_process_phy_test_request(struct dp_ctrl *dp_ctrl)

	ctrl->aux->init(ctrl->aux, ctrl->parser->aux_cfg);

	ret = ctrl->dp_ctrl.on(&ctrl->dp_ctrl, ctrl->mst_mode);
	ret = ctrl->dp_ctrl.on(&ctrl->dp_ctrl, ctrl->mst_mode, false);
	if (ret)
		pr_err("failed to enable DP controller\n");

@@ -1008,18 +1017,14 @@ static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel)

	dp_ctrl_mst_send_act(ctrl);

	rc = dp_ctrl_wait4video_ready(ctrl);
	if (rc)
		goto error;
	dp_ctrl_wait4video_ready(ctrl);

	ctrl->stream_count++;

	link_ready = ctrl->catalog->mainlink_ready(ctrl->catalog);
	pr_debug("mainlink %s\n", link_ready ? "READY" : "NOT READY");

	return rc;

error:
	dp_ctrl_disable_stream_clocks(ctrl, panel);
	return rc;
}

static void dp_ctrl_mst_stream_pre_off(struct dp_ctrl *dp_ctrl,
@@ -1083,9 +1088,10 @@ static void dp_ctrl_stream_off(struct dp_ctrl *dp_ctrl, struct dp_panel *panel)
	panel->hw_cfg(panel, false);

	dp_ctrl_disable_stream_clocks(ctrl, panel);
	ctrl->stream_count--;
}

static int dp_ctrl_on(struct dp_ctrl *dp_ctrl, bool mst_mode)
static int dp_ctrl_on(struct dp_ctrl *dp_ctrl, bool mst_mode, bool shallow)
{
	int rc = 0;
	struct dp_ctrl_private *ctrl;
@@ -1117,8 +1123,9 @@ static int dp_ctrl_on(struct dp_ctrl *dp_ctrl, bool mst_mode)
		ctrl->link->link_params.bw_code,
		ctrl->link->link_params.lane_count);

	rc = dp_ctrl_link_setup(ctrl);
	if (rc)
	rc = dp_ctrl_link_setup(ctrl, shallow);
	/* Ignore errors in case of shallow processing */
	if (!shallow && rc)
		goto end;

	ctrl->power_on = true;
+1 −1
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@
struct dp_ctrl {
	int (*init)(struct dp_ctrl *dp_ctrl, bool flip, bool reset);
	void (*deinit)(struct dp_ctrl *dp_ctrl);
	int (*on)(struct dp_ctrl *dp_ctrl, bool mst_mode);
	int (*on)(struct dp_ctrl *dp_ctrl, bool mst_mode, bool shallow);
	void (*off)(struct dp_ctrl *dp_ctrl);
	void (*abort)(struct dp_ctrl *dp_ctrl);
	void (*isr)(struct dp_ctrl *dp_ctrl);
+20 −40
Original line number Diff line number Diff line
@@ -495,14 +495,8 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp)

	dp->aux->state |= DP_STATE_NOTIFICATION_SENT;

	if (!dp->mst.mst_active) {
		if (dp->dp_display.is_sst_connected == hpd) {
			pr_debug("SKIPPED:hpd:%d\n", hpd);
			goto skip_wait;
		}

	if (!dp->mst.mst_active)
		dp->dp_display.is_sst_connected = hpd;
	}

	reinit_completion(&dp->notification_comp);
	dp_display_send_hpd_event(dp);
@@ -566,31 +560,6 @@ static void dp_display_host_init(struct dp_display_private *dp)
	dp->core_initialized = true;
}

static int dp_display_update_pclk(struct dp_display_private *dp)
{
	int rc = 0;
	u32 rate, max_pclk_khz;
	u32 const enc_factx10 = 8;
	u32 const default_bpp = 30;

	if (dp->debug->max_pclk_khz) {
		dp->dp_display.max_pclk_khz = dp->debug->max_pclk_khz;
		goto end;
	}

	rate = drm_dp_bw_code_to_link_rate(dp->link->link_params.bw_code);
	rate /= default_bpp;

	max_pclk_khz = dp->link->link_params.lane_count * rate * enc_factx10;

	dp->dp_display.max_pclk_khz = min(dp->parser->max_pclk_khz,
						max_pclk_khz);

	pr_debug("dp max_pclk_khz = %d\n", dp->dp_display.max_pclk_khz);
end:
	return rc;
}

static void dp_display_host_deinit(struct dp_display_private *dp)
{
	if (!dp->core_initialized) {
@@ -623,6 +592,8 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp)

	dp->is_connected = true;

	dp->dp_display.max_pclk_khz = dp->parser->max_pclk_khz;

	dp_display_host_init(dp);

	if (dp->debug->psm_enabled) {
@@ -648,13 +619,7 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp)
	dp_display_process_mst_hpd_high(dp);

	mutex_lock(&dp->session_lock);
	rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active);
	if (rc) {
		mutex_unlock(&dp->session_lock);
		goto end;
	}

	rc = dp_display_update_pclk(dp);
	rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active, false);
	if (rc) {
		mutex_unlock(&dp->session_lock);
		goto end;
@@ -958,6 +923,11 @@ static int dp_display_usbpd_attention_cb(struct device *dev)
			dp->power_on);

	if (!dp->hpd->hpd_high) {
		if (!dp->is_connected) {
			pr_debug("already disconnected\n");
			return 0;
		}

		/* cancel any pending request */
		atomic_set(&dp->aborted, 1);
		dp->ctrl->abort(dp->ctrl);
@@ -1285,7 +1255,17 @@ static int dp_display_prepare(struct dp_display *dp_display, void *panel)

	dp_display_host_init(dp);

	rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active);
	/*
	 * Execute the dp controller power on in shallow mode here.
	 * In normal cases, controller should have been powered on
	 * by now. In some cases like suspend/resume or framework
	 * reboot, we end up here without a powered on controller.
	 * Cable may have been removed in suspended state. In that
	 * case, link training is bound to fail on system resume.
	 * So, we execute in shallow mode here to do only minimal
	 * and required things.
	 */
	rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active, true);
	if (rc)
		goto end;