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

Commit 7b634e3e authored by Ramakant Singh's avatar Ramakant Singh Committed by Gerrit - the friendly Code Review server
Browse files

msm: mdss: fix to handle multi-rect configuration in error cases



In case of an error when configuring a pipe during kickoff,
driver unstages from HW the pipe that had the error, so it
makes sure this dirty pipe is not used by HW.
This is a problem if the pipe is configured in multi-rect
mode and we only fail one of the two multi-rect pipes since
in this case HW is expecting both multi-rect pipes that
represent the two HW rectangles and we are only configuring
one due the error that happened.
Fix this problem by making sure that if the configuration of
one multi-rect fail, we unstage both multi-rect pipes.

Change-Id: I78e7f89c19ee018eadba22a2ad71cf007c0874fb
Signed-off-by: default avatarRamakant Singh <ramaka@codeaurora.org>
parent a72b085f
Loading
Loading
Loading
Loading
+44 −8
Original line number Diff line number Diff line
@@ -1457,6 +1457,21 @@ static void mdss_mdp_overlay_update_pm(struct mdss_overlay_private *mdp5_data)
	activate_event_timer(mdp5_data->cpu_pm_hdl, wakeup_time);
}

static void __unstage_pipe_and_clean_buf(struct msm_fb_data_type *mfd,
		struct mdss_mdp_pipe *pipe, struct mdss_mdp_data *buf)
{

	pr_debug("unstaging pipe:%d rect:%d buf:%d\n",
			pipe->num, pipe->multirect.num, !buf);
	MDSS_XLOG(pipe->num, pipe->multirect.num, !buf);
	mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_left);
	mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_right);
	pipe->dirty = true;

	if (buf)
		__pipe_buf_mark_cleanup(mfd, buf);
}

static int __overlay_queue_pipes(struct msm_fb_data_type *mfd)
{
	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
@@ -1568,7 +1583,6 @@ static int __overlay_queue_pipes(struct msm_fb_data_type *mfd)
				pipe->num);
			ret = -EINVAL;
		}

		/*
		 * if we reach here without errors and buf == NULL
		 * then solid fill will be set
@@ -1577,14 +1591,36 @@ static int __overlay_queue_pipes(struct msm_fb_data_type *mfd)
			ret = mdss_mdp_pipe_queue_data(pipe, buf);

		if (IS_ERR_VALUE(ret)) {
			pr_warn("Unable to queue data for pnum=%d\n",
			pr_warn("Unable to queue data for pnum=%d rect=%d\n",
					pipe->num, pipe->multirect.num);

			/*
			 * If we fail for a multi-rect pipe, unstage both rects
			 * so we don't leave the pipe configured in multi-rect
			 * mode with only one rectangle staged.
			 */
			if (pipe->multirect.mode !=
					MDSS_MDP_PIPE_MULTIRECT_NONE) {
				struct mdss_mdp_pipe *next_pipe =
					(struct mdss_mdp_pipe *)
					pipe->multirect.next;

				if (next_pipe) {
					struct mdss_mdp_data *next_buf =
						list_first_entry_or_null(
							&next_pipe->buf_queue,
							struct mdss_mdp_data,
							pipe_list);

					__unstage_pipe_and_clean_buf(mfd,
							next_pipe, next_buf);
				} else {
					pr_warn("cannot find rect pnum=%d\n",
							pipe->num);
			mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_left);
			mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_right);
			pipe->dirty = true;
				}
			}

			if (buf)
				__pipe_buf_mark_cleanup(mfd, buf);
			__unstage_pipe_and_clean_buf(mfd, pipe, buf);
		}
	}

+6 −4
Original line number Diff line number Diff line
@@ -2664,20 +2664,22 @@ int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
		pipe->params_changed = 0;
		mdss_mdp_pipe_solidfill_setup(pipe);

		MDSS_XLOG(pipe->num, pipe->mixer_left->num, pipe->play_cnt,
			0x111);
		MDSS_XLOG(pipe->num, pipe->multirect.num,
			pipe->mixer_left->num, pipe->play_cnt, 0x111);

		goto update_nobuf;
	}

	MDSS_XLOG(pipe->num, pipe->mixer_left->num, pipe->play_cnt, 0x222);
	MDSS_XLOG(pipe->num, pipe->multirect.num, pipe->mixer_left->num,
						pipe->play_cnt, 0x222);

	if (params_changed) {
		pipe->params_changed = 0;

		ret = mdss_mdp_pipe_pp_setup(pipe, &opmode);
		if (ret) {
			pr_err("pipe pp setup error for pnum=%d\n", pipe->num);
			pr_err("pipe pp setup error for pnum=%d rect=%d\n",
					pipe->num, pipe->multirect.num);
			goto done;
		}