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

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

Merge "drm/msm/dp: complete link training before hot plug notification"

parents 175e38e4 fd273d2c
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -607,7 +607,6 @@
			 <&clock_gcc GCC_USB3_PRIM_PHY_PIPE_CLK>,
			 <&clock_dispcc DISP_CC_MDSS_DP_LINK_CLK>,
			 <&clock_dispcc DISP_CC_MDSS_DP_LINK_INTF_CLK>,
			 <&clock_dispcc DISP_CC_MDSS_DP_PIXEL_CLK>,
			 <&clock_dispcc DISP_CC_MDSS_DP_CRYPTO_CLK>,
			 <&clock_dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>,
			 <&mdss_dp_pll DP_VCO_DIVIDED_CLK_SRC_MUX>,
@@ -616,9 +615,8 @@
			 <&clock_dispcc DISP_CC_MDSS_DP_PIXEL_CLK>,
			 <&clock_dispcc DISP_CC_MDSS_DP_PIXEL1_CLK>;
		clock-names = "core_aux_clk", "core_usb_ref_clk_src",
			"core_usb_ref_clk",
			"core_usb_pipe_clk", "ctrl_link_clk",
			"ctrl_link_iface_clk", "ctrl_pixel_clk",
			"core_usb_ref_clk", "core_usb_pipe_clk",
			"link_clk", "link_iface_clk",
			"crypto_clk", "pixel_clk_rcg", "pixel_parent",
			"pixel1_clk_rcg", "pixel1_parent",
			"strm0_pixel_clk", "strm1_pixel_clk";
+9 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ struct dp_aux_private {
	bool read;
	bool no_send_addr;
	bool no_send_stop;
	bool enabled;

	u32 offset;
	u32 segment;
@@ -623,12 +624,16 @@ static void dp_aux_init(struct dp_aux *dp_aux, struct dp_aux_cfg *aux_cfg)

	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);

	if (aux->enabled)
		return;

	dp_aux_reset_phy_config_indices(aux_cfg);
	aux->catalog->setup(aux->catalog, aux_cfg);
	aux->catalog->reset(aux->catalog);
	aux->catalog->enable(aux->catalog, true);
	atomic_set(&aux->aborted, 0);
	aux->retry_cnt = 0;
	aux->enabled = true;
}

static void dp_aux_deinit(struct dp_aux *dp_aux)
@@ -642,8 +647,12 @@ static void dp_aux_deinit(struct dp_aux *dp_aux)

	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);

	if (!aux->enabled)
		return;

	atomic_set(&aux->aborted, 1);
	aux->catalog->enable(aux->catalog, false);
	aux->enabled = false;
}

static int dp_aux_register(struct dp_aux *dp_aux)
+82 −109
Original line number Diff line number Diff line
@@ -122,19 +122,12 @@ static void dp_ctrl_state_ctrl(struct dp_ctrl_private *ctrl, u32 state)
	ctrl->catalog->state_ctrl(ctrl->catalog, state);
}

static void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl, enum dp_stream_id strm)
static void dp_ctrl_push_idle(struct dp_ctrl_private *ctrl,
				enum dp_stream_id strm)
{
	int const idle_pattern_completion_timeout_ms = 3 * HZ / 100;
	struct dp_ctrl_private *ctrl;
	int const idle_pattern_completion_timeout_ms = HZ / 10;
	u32 state = 0x0;

	if (!dp_ctrl) {
		pr_err("Invalid input data\n");
		return;
	}

	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);

	if (!ctrl->power_on) {
		pr_err("CTRL off, return\n");
		return;
@@ -158,7 +151,7 @@ static void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl, enum dp_stream_id strm)

	if (!wait_for_completion_timeout(&ctrl->idle_comp,
			idle_pattern_completion_timeout_ms))
		pr_warn("PUSH_IDLE time out\n");
		pr_warn("time out\n");

	pr_debug("mainlink off done\n");
}
@@ -301,7 +294,12 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl)

	tries = 0;
	old_v_level = ctrl->link->phy_params.v_level;
	while (!atomic_read(&ctrl->aborted)) {
	while (1) {
		if (atomic_read(&ctrl->aborted)) {
			ret = -EINVAL;
			break;
		}

		drm_dp_link_train_clock_recovery_delay(ctrl->panel->dpcd);

		ret = dp_ctrl_read_link_status(ctrl, link_status);
@@ -417,6 +415,11 @@ static int dp_ctrl_link_training_2(struct dp_ctrl_private *ctrl)
	}

	do  {
		if (atomic_read(&ctrl->aborted)) {
			ret = -EINVAL;
			break;
		}

		drm_dp_link_train_channel_eq_delay(ctrl->panel->dpcd);

		ret = dp_ctrl_read_link_status(ctrl, link_status);
@@ -439,7 +442,7 @@ static int dp_ctrl_link_training_2(struct dp_ctrl_private *ctrl)
			ret = -EINVAL;
			break;
		}
	} while (!atomic_read(&ctrl->aborted));
	} while (1);
end:
	ctrl->aux->state &= ~DP_STATE_TRAIN_2_STARTED;

@@ -467,8 +470,10 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl)
	link_info.capabilities = ctrl->panel->link_info.capabilities;

	ret = drm_dp_link_configure(ctrl->aux->drm_aux, &link_info);
	if (ret)
	if (ret) {
		pr_err_ratelimited("link_configure failed, rc=%d\n", ret);
		goto end;
	}

	ret = drm_dp_dpcd_write(ctrl->aux->drm_aux,
		DP_MAIN_LINK_CHANNEL_CODING_SET, &encoding, 1);
@@ -504,7 +509,7 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl)
	return ret;
}

static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl, bool train)
static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl)
{
	int ret = 0;

@@ -513,9 +518,6 @@ static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl, bool train)
	if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN)
		goto end;

	if (!train)
		goto end;

	/*
	 * As part of previous calls, DP controller state might have
	 * transitioned to PUSH_IDLE. In order to start transmitting a link
@@ -548,14 +550,17 @@ static void dp_ctrl_set_clock_rate(struct dp_ctrl_private *ctrl,
		pr_err("%s clock could not be set with rate %d\n", name, rate);
}

static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl)
static int dp_ctrl_enable_link_clock(struct dp_ctrl_private *ctrl)
{
	int ret = 0;
	u32 rate = drm_dp_bw_code_to_link_rate(ctrl->link->link_params.bw_code);
	enum dp_pm_type type = DP_LINK_PM;

	dp_ctrl_set_clock_rate(ctrl, "ctrl_link_clk", DP_CTRL_PM,
		drm_dp_bw_code_to_link_rate(ctrl->link->link_params.bw_code));
	pr_debug("rate=%d\n", rate);

	ret = ctrl->power->clk_enable(ctrl->power, DP_CTRL_PM, true);
	dp_ctrl_set_clock_rate(ctrl, "link_clk", type, rate);

	ret = ctrl->power->clk_enable(ctrl->power, type, true);
	if (ret) {
		pr_err("Unabled to start link clocks\n");
		ret = -EINVAL;
@@ -564,9 +569,46 @@ static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl)
	return ret;
}

static int dp_ctrl_disable_mainlink_clocks(struct dp_ctrl_private *ctrl)
static void dp_ctrl_disable_link_clock(struct dp_ctrl_private *ctrl)
{
	return ctrl->power->clk_enable(ctrl->power, DP_CTRL_PM, false);
	ctrl->power->clk_enable(ctrl->power, DP_LINK_PM, false);
}

static int dp_ctrl_link_setup(struct dp_ctrl_private *ctrl)
{
	int rc = -EINVAL;
	u32 link_train_max_retries = 100;
	struct dp_catalog_ctrl *catalog;
	struct dp_link_params *link_params;

	catalog = ctrl->catalog;
	link_params = &ctrl->link->link_params;

	catalog->hpd_config(catalog, true);
	catalog->phy_lane_cfg(catalog, ctrl->orientation,
				link_params->lane_count);

	while (--link_train_max_retries || !atomic_read(&ctrl->aborted)) {
		pr_debug("bw_code=%d, lane_count=%d\n",
			link_params->bw_code, link_params->lane_count);

		dp_ctrl_enable_link_clock(ctrl);
		dp_ctrl_configure_source_link_params(ctrl, true);

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

		dp_ctrl_link_rate_down_shift(ctrl);

		dp_ctrl_configure_source_link_params(ctrl, false);
		dp_ctrl_disable_link_clock(ctrl);

		/* hw recommended delays before retrying link training */
		msleep(20);
	}

	return rc;
}

static int dp_ctrl_enable_stream_clocks(struct dp_ctrl_private *ctrl,
@@ -645,6 +687,7 @@ static int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip, bool reset)
		catalog->phy_reset(ctrl->catalog);
	}
	catalog->enable_irq(ctrl->catalog, true);
	atomic_set(&ctrl->aborted, 0);

	return 0;
}
@@ -686,51 +729,24 @@ static int dp_ctrl_link_maintenance(struct dp_ctrl *dp_ctrl)

	if (!ctrl->power_on || atomic_read(&ctrl->aborted)) {
		pr_err("CTRL off, return\n");
		return -EINVAL;
		ret = -EINVAL;
		goto end;
	}

	ctrl->aux->state &= ~DP_STATE_LINK_MAINTENANCE_COMPLETED;
	ctrl->aux->state &= ~DP_STATE_LINK_MAINTENANCE_FAILED;
	ctrl->aux->state |= DP_STATE_LINK_MAINTENANCE_STARTED;

	ctrl->dp_ctrl.reset(&ctrl->dp_ctrl);

	do {
		if (ret == -EAGAIN) {
			/* try with lower link rate */
			dp_ctrl_link_rate_down_shift(ctrl);

			dp_ctrl_configure_source_link_params(ctrl, false);
		}

		ctrl->catalog->phy_lane_cfg(ctrl->catalog,
			ctrl->orientation, ctrl->link->link_params.lane_count);

		/*
		 * Disable and re-enable the mainlink clock since the
		 * link clock might have been adjusted as part of the
		 * link maintenance.
		 */
		dp_ctrl_disable_mainlink_clocks(ctrl);

		ret = dp_ctrl_enable_mainlink_clocks(ctrl);
		if (ret)
			continue;

		dp_ctrl_configure_source_link_params(ctrl, true);

		reinit_completion(&ctrl->idle_comp);

		ret = dp_ctrl_setup_main_link(ctrl, true);
	} while (ret == -EAGAIN);
	ctrl->catalog->reset(ctrl->catalog);
	dp_ctrl_disable_link_clock(ctrl);
	ret = dp_ctrl_link_setup(ctrl);

	ctrl->aux->state &= ~DP_STATE_LINK_MAINTENANCE_STARTED;

	if (ret)
		ctrl->aux->state |= DP_STATE_LINK_MAINTENANCE_FAILED;
	else
		ctrl->aux->state |= DP_STATE_LINK_MAINTENANCE_COMPLETED;

end:
	return ret;
}

@@ -753,13 +769,13 @@ static void dp_ctrl_process_phy_test_request(struct dp_ctrl *dp_ctrl)

	pr_debug("start\n");

	ctrl->dp_ctrl.push_idle(&ctrl->dp_ctrl, DP_STREAM_0);
	/*
	 * The global reset will need DP link ralated clocks to be
	 * running. Add the global reset just before disabling the
	 * link clocks and core clocks.
	 */
	ctrl->dp_ctrl.reset(&ctrl->dp_ctrl);
	ctrl->catalog->reset(ctrl->catalog);
	ctrl->dp_ctrl.stream_pre_off(&ctrl->dp_ctrl, ctrl->panel);
	ctrl->dp_ctrl.stream_off(&ctrl->dp_ctrl, ctrl->panel);
	ctrl->dp_ctrl.off(&ctrl->dp_ctrl);

@@ -826,19 +842,6 @@ static void dp_ctrl_send_phy_test_pattern(struct dp_ctrl_private *ctrl)
			dp_link_get_phy_test_pattern(pattern_requested));
}

static void dp_ctrl_reset(struct dp_ctrl *dp_ctrl)
{
	struct dp_ctrl_private *ctrl;

	if (!dp_ctrl) {
		pr_err("invalid params\n");
		return;
	}

	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
	ctrl->catalog->reset(ctrl->catalog);
}

static void dp_ctrl_send_video(struct dp_ctrl_private *ctrl)
{
	ctrl->catalog->state_ctrl(ctrl->catalog, ST_SEND_VIDEO);
@@ -1052,12 +1055,16 @@ static void dp_ctrl_mst_stream_pre_off(struct dp_ctrl *dp_ctrl,
static void dp_ctrl_stream_pre_off(struct dp_ctrl *dp_ctrl,
		struct dp_panel *panel)
{
	struct dp_ctrl_private *ctrl;

	if (!dp_ctrl || !panel) {
		pr_err("invalid input\n");
		return;
	}

	dp_ctrl_push_idle(dp_ctrl, panel->stream_id);
	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);

	dp_ctrl_push_idle(ctrl, panel->stream_id);

	dp_ctrl_mst_stream_pre_off(dp_ctrl, panel);
}
@@ -1081,7 +1088,6 @@ static int dp_ctrl_on(struct dp_ctrl *dp_ctrl, bool mst_mode)
	int rc = 0;
	struct dp_ctrl_private *ctrl;
	u32 rate = 0;
	u32 link_train_max_retries = 100;

	if (!dp_ctrl) {
		rc = -EINVAL;
@@ -1090,13 +1096,9 @@ static int dp_ctrl_on(struct dp_ctrl *dp_ctrl, bool mst_mode)

	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);

	atomic_set(&ctrl->aborted, 0);

	ctrl->mst_mode = mst_mode;
	rate = ctrl->panel->link_info.rate;

	ctrl->catalog->hpd_config(ctrl->catalog, true);

	if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) {
		pr_debug("using phy test link parameters\n");
	} else {
@@ -1110,38 +1112,11 @@ 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);

	ctrl->catalog->phy_lane_cfg(ctrl->catalog,
			ctrl->orientation, ctrl->link->link_params.lane_count);

	rc = dp_ctrl_enable_mainlink_clocks(ctrl);
	rc = dp_ctrl_link_setup(ctrl);
	if (rc)
		goto end;

	reinit_completion(&ctrl->idle_comp);

	dp_ctrl_configure_source_link_params(ctrl, true);

	while (--link_train_max_retries && !atomic_read(&ctrl->aborted)) {
		rc = dp_ctrl_setup_main_link(ctrl, true);
		if (!rc)
			break;

		/* try with lower link rate */
		dp_ctrl_link_rate_down_shift(ctrl);

		dp_ctrl_configure_source_link_params(ctrl, false);

		dp_ctrl_disable_mainlink_clocks(ctrl);
		/* hw recommended delay before re-enabling clocks */
		msleep(20);

		dp_ctrl_enable_mainlink_clocks(ctrl);
	}

	ctrl->power_on = true;

	pr_debug("End-\n");

end:
	return rc;
}
@@ -1161,7 +1136,7 @@ static void dp_ctrl_off(struct dp_ctrl *dp_ctrl)
	/* Make sure DP is disabled before clk disable */
	wmb();

	dp_ctrl_disable_mainlink_clocks(ctrl);
	dp_ctrl_disable_link_clock(ctrl);

	ctrl->mst_mode = false;
	ctrl->power_on = false;
@@ -1249,10 +1224,8 @@ struct dp_ctrl *dp_ctrl_get(struct dp_ctrl_in *in)
	dp_ctrl->deinit    = dp_ctrl_host_deinit;
	dp_ctrl->on        = dp_ctrl_on;
	dp_ctrl->off       = dp_ctrl_off;
	dp_ctrl->push_idle = dp_ctrl_push_idle;
	dp_ctrl->abort     = dp_ctrl_abort;
	dp_ctrl->isr       = dp_ctrl_isr;
	dp_ctrl->reset	   = dp_ctrl_reset;
	dp_ctrl->link_maintenance = dp_ctrl_link_maintenance;
	dp_ctrl->process_phy_test_request = dp_ctrl_process_phy_test_request;
	dp_ctrl->stream_on = dp_ctrl_stream_on;
+0 −2
Original line number Diff line number Diff line
@@ -27,8 +27,6 @@ struct dp_ctrl {
	void (*deinit)(struct dp_ctrl *dp_ctrl);
	int (*on)(struct dp_ctrl *dp_ctrl, bool mst_mode);
	void (*off)(struct dp_ctrl *dp_ctrl);
	void (*reset)(struct dp_ctrl *dp_ctrl);
	void (*push_idle)(struct dp_ctrl *dp_ctrl, enum dp_stream_id strm);
	void (*abort)(struct dp_ctrl *dp_ctrl);
	void (*isr)(struct dp_ctrl *dp_ctrl);
	bool (*handle_sink_request)(struct dp_ctrl *dp_ctrl);
+1 −16
Original line number Diff line number Diff line
@@ -35,8 +35,6 @@ struct dp_debug_private {
	u8 *dpcd;
	u32 dpcd_size;

	int vdo;

	char exe_mode[SZ_32];
	char reg_dump[SZ_32];

@@ -47,7 +45,6 @@ struct dp_debug_private {
	struct dp_catalog *catalog;
	struct drm_connector **connector;
	struct device *dev;
	struct work_struct sim_work;
	struct dp_debug dp_debug;
	struct dp_parser *parser;
};
@@ -1068,9 +1065,7 @@ static ssize_t dp_debug_write_attention(struct file *file,
	if (kstrtoint(buf, 10, &vdo) != 0)
		goto end;

	debug->vdo = vdo;

	schedule_work(&debug->sim_work);
	debug->hpd->simulate_attention(debug->hpd, vdo);
end:
	return len;
}
@@ -1399,14 +1394,6 @@ static int dp_debug_init(struct dp_debug *dp_debug)
	return rc;
}

static void dp_debug_sim_work(struct work_struct *work)
{
	struct dp_debug_private *debug =
		container_of(work, typeof(*debug), sim_work);

	debug->hpd->simulate_attention(debug->hpd, debug->vdo);
}

u8 *dp_debug_get_edid(struct dp_debug *dp_debug)
{
	struct dp_debug_private *debug;
@@ -1441,8 +1428,6 @@ struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
		goto error;
	}

	INIT_WORK(&debug->sim_work, dp_debug_sim_work);

	debug->dp_debug.debug_en = false;
	debug->hpd = hpd;
	debug->link = link;
Loading