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

Commit 39bc4416 authored by Yujun Zhang's avatar Yujun Zhang
Browse files

disp: msm: dsi: unify dynamic clk support for command mode



Currently the dynamic bit clock switch trigger for command mode
is supported via sysfs node. This might lead to unnecessary
race conditions, when dsi driver is enabling the dsi bit clock
as part of commit and at the same time if bit rate change via
sysfs happens. So make the trigger happens via kernel mode set
call as done for video mode.

Change-Id: I17acb408d2b6dbd6fa41994e56262e31e43d088b
Signed-off-by: default avatarRitesh Kumar <riteshk@codeaurora.org>
Signed-off-by: default avatarYujun Zhang <yujunzhang@codeaurora.org>
parent b0f2e222
Loading
Loading
Loading
Loading
+58 −12
Original line number Diff line number Diff line
@@ -2987,7 +2987,10 @@ static int dsi_display_clocks_init(struct dsi_display *display)
				goto error;
			}

			if (dyn_clk_caps->dyn_clk_support) {
			if (dyn_clk_caps->dyn_clk_support &&
				(display->panel->panel_mode ==
					 DSI_OP_VIDEO_MODE)) {

				if (dsi_display_check_prefix(src_byte,
							clk_name))
					src->byte_clk = NULL;
@@ -4016,7 +4019,7 @@ static int _dsi_display_dyn_update_clks(struct dsi_display *display,
	return rc;
}

static int dsi_display_dynamic_clk_switch(struct dsi_display *display,
static int dsi_display_dynamic_clk_switch_vid(struct dsi_display *display,
					  struct dsi_display_mode *mode)
{
	int rc = 0, mask, i;
@@ -4085,6 +4088,39 @@ static int dsi_display_dynamic_clk_switch(struct dsi_display *display,
	return rc;
}

static int dsi_display_dynamic_clk_configure_cmd(struct dsi_display *display,
		int clk_rate)
{
	int rc = 0;

	if (clk_rate <= 0) {
		pr_err("%s: bitrate should be greater than 0\n", __func__);
		return -EINVAL;
	}

	if (clk_rate == display->cached_clk_rate) {
		pr_info("%s: ignore duplicated DSI clk setting\n", __func__);
		return rc;
	}

	display->cached_clk_rate = clk_rate;

	rc = dsi_display_update_dsi_bitrate(display, clk_rate);
	if (!rc) {
		pr_info("%s: bit clk is ready to be configured to '%d'\n",
				__func__, clk_rate);
		atomic_set(&display->clkrate_change_pending, 1);
	} else {
		pr_err("%s: Failed to prepare to configure '%d'. rc = %d\n",
				__func__, clk_rate, rc);
		/* Caching clock failed, so don't go on doing so. */
		atomic_set(&display->clkrate_change_pending, 0);
		display->cached_clk_rate = 0;
	}

	return rc;
}

static int dsi_display_dfps_update(struct dsi_display *display,
				   struct dsi_display_mode *dsi_mode)
{
@@ -4318,7 +4354,7 @@ static int dsi_display_set_mode_sub(struct dsi_display *display,
				    struct dsi_display_mode *mode,
				    u32 flags)
{
	int rc = 0;
	int rc = 0, clk_rate = 0;
	int i;
	struct dsi_display_ctrl *ctrl;
	struct dsi_display_mode_priv_info *priv_info;
@@ -4355,15 +4391,25 @@ static int dsi_display_set_mode_sub(struct dsi_display *display,
			goto error;
		}
	} else if (mode->dsi_mode_flags & DSI_MODE_FLAG_DYN_CLK) {
		rc = dsi_display_dynamic_clk_switch(display, mode);
		if (display->panel->panel_mode == DSI_OP_VIDEO_MODE) {
			rc = dsi_display_dynamic_clk_switch_vid(display, mode);
			if (rc)
				pr_err("dynamic clk change failed %d\n", rc);
			/*
			 * skip rest of the opearations since
		 * dsi_display_dynamic_clk_switch() already takes
			 * dsi_display_dynamic_clk_switch_vid() already takes
			 * care of them.
			 */
			return rc;
		} else if (display->panel->panel_mode == DSI_OP_CMD_MODE) {
			clk_rate = mode->timing.clk_rate_hz;
			rc = dsi_display_dynamic_clk_configure_cmd(display,
					clk_rate);
			if (rc) {
				pr_err("Failed to configure dynamic clk\n");
				return rc;
			}
		}
	}

	display_for_each_ctrl(i, display) {
+2 −1
Original line number Diff line number Diff line
@@ -231,7 +231,8 @@ static void dsi_bridge_enable(struct drm_bridge *bridge)
	}

	if (c_bridge->dsi_mode.dsi_mode_flags &
			(DSI_MODE_FLAG_SEAMLESS | DSI_MODE_FLAG_VRR)) {
			(DSI_MODE_FLAG_SEAMLESS | DSI_MODE_FLAG_VRR |
			 DSI_MODE_FLAG_DYN_CLK)) {
		pr_debug("[%d] seamless enable\n", c_bridge->id);
		return;
	}
+9 −7
Original line number Diff line number Diff line
@@ -3093,12 +3093,9 @@ struct dsi_panel *dsi_panel_get(struct device *parent,
			pr_err("failed to parse qsync features, rc=%d\n", rc);
	}

	if (panel->panel_mode == DSI_OP_VIDEO_MODE) {
	rc = dsi_panel_parse_dyn_clk_caps(panel);
	if (rc)
			pr_err("failed to parse dynamic clk config, rc=%d\n",
					rc);
	}
		pr_err("failed to parse dynamic clk config, rc=%d\n", rc);

	rc = dsi_panel_parse_phy_props(panel);
	if (rc) {
@@ -3522,6 +3519,7 @@ int dsi_panel_get_host_cfg_for_mode(struct dsi_panel *panel,
				    struct dsi_host_config *config)
{
	int rc = 0;
	struct dsi_dyn_clk_caps *dyn_clk_caps = &panel->dyn_clk_caps;

	if (!panel || !mode || !config) {
		pr_err("invalid params\n");
@@ -3549,7 +3547,11 @@ int dsi_panel_get_host_cfg_for_mode(struct dsi_panel *panel,
	config->video_timing.dsc_enabled = mode->priv_info->dsc_enabled;
	config->video_timing.dsc = &mode->priv_info->dsc;

	if (dyn_clk_caps->dyn_clk_support)
		config->bit_clk_rate_hz_override = mode->timing.clk_rate_hz;
	else
		config->bit_clk_rate_hz_override = mode->priv_info->clk_rate_hz;

	config->esc_clk_rate_hz = 19200000;
	mutex_unlock(&panel->panel_lock);
	return rc;
+3 −1
Original line number Diff line number Diff line
@@ -4057,7 +4057,9 @@ static void sde_crtc_enable(struct drm_crtc *crtc,

	/* return early if crtc is already enabled, do this after UIDLE check */
	if (sde_crtc->enabled) {
		if (msm_is_mode_seamless_dms(&crtc->state->adjusted_mode))
		if (msm_is_mode_seamless_dms(&crtc->state->adjusted_mode) ||
		msm_is_mode_seamless_dyn_clk(&crtc->state->adjusted_mode))

			SDE_DEBUG("%s extra crtc enable expected during DMS\n",
					sde_crtc->name);
		else
+10 −5
Original line number Diff line number Diff line
@@ -2792,7 +2792,8 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
		sde_encoder_virt_mode_switch(intf_mode, sde_enc, adj_mode);

	/* release resources before seamless mode change */
	if (msm_is_mode_seamless_dms(adj_mode)) {
	if (msm_is_mode_seamless_dms(adj_mode) ||
			msm_is_mode_seamless_dyn_clk(adj_mode)) {
		/* restore resource state before releasing them */
		ret = sde_encoder_resource_control(drm_enc,
				SDE_ENC_RC_EVENT_PRE_MODESET);
@@ -2866,7 +2867,8 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
	}

	/* update resources after seamless mode change */
	if (msm_is_mode_seamless_dms(adj_mode))
	if (msm_is_mode_seamless_dms(adj_mode) ||
			msm_is_mode_seamless_dyn_clk(adj_mode))
		sde_encoder_resource_control(&sde_enc->base,
						SDE_ENC_RC_EVENT_POST_MODESET);
}
@@ -3147,7 +3149,8 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
	}

	/* register input handler if not already registered */
	if (sde_enc->input_handler && !msm_is_mode_seamless_dms(cur_mode)) {
	if (sde_enc->input_handler && !msm_is_mode_seamless_dms(cur_mode) &&
			!msm_is_mode_seamless_dyn_clk(cur_mode)) {
		ret = _sde_encoder_input_handler_register(
				sde_enc->input_handler);
		if (ret)
@@ -3193,7 +3196,8 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
			 * already. Invoke restore to reconfigure the
			 * new mode.
			 */
			if (msm_is_mode_seamless_dms(cur_mode) &&
			if ((msm_is_mode_seamless_dms(cur_mode) ||
				msm_is_mode_seamless_dyn_clk(cur_mode)) &&
					phys->ops.restore)
				phys->ops.restore(phys);
			else if (phys->ops.enable)
@@ -3206,7 +3210,8 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
						sde_enc->misr_frame_count);
	}

	if (msm_is_mode_seamless_dms(cur_mode) &&
	if ((msm_is_mode_seamless_dms(cur_mode) ||
			msm_is_mode_seamless_dyn_clk(cur_mode)) &&
			sde_enc->cur_master->ops.restore)
		sde_enc->cur_master->ops.restore(sde_enc->cur_master);
	else if (sde_enc->cur_master->ops.enable)