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

Commit b71d87e8 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: mdss: Handle case when pipe is not idle during cleanup."

parents 35d6da7d 1aa7be2c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -620,6 +620,7 @@ int mdss_mdp_mixer_pipe_update(struct mdss_mdp_pipe *pipe,
	struct mdss_mdp_mixer *mixer, int params_changed);
int mdss_mdp_mixer_pipe_unstage(struct mdss_mdp_pipe *pipe,
	struct mdss_mdp_mixer *mixer);
void mdss_mdp_mixer_unstage_all(struct mdss_mdp_mixer *mixer);
int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg);
int mdss_mdp_display_wait4comp(struct mdss_mdp_ctl *ctl);
int mdss_mdp_display_wait4pingpong(struct mdss_mdp_ctl *ctl);
+27 −5
Original line number Diff line number Diff line
@@ -2398,6 +2398,33 @@ int mdss_mdp_mixer_pipe_update(struct mdss_mdp_pipe *pipe,
	return 0;
}

/**
 * mdss_mdp_mixer_unstage_all() - Unstage all pipes from mixer
 * @mixer:	Mixer from which to unstage all pipes
 *
 * Unstage any pipes that are currently attached to mixer.
 *
 * NOTE: this will not update the pipe structure, and thus a full
 * deinitialization or reconfiguration of all pipes is expected after this call.
 */
void mdss_mdp_mixer_unstage_all(struct mdss_mdp_mixer *mixer)
{
	struct mdss_mdp_pipe *tmp;
	int i;

	if (!mixer)
		return;

	for (i = 0; i < MAX_PIPES_PER_LM; i++) {
		tmp = mixer->stage_pipe[i];
		if (tmp) {
			mixer->stage_pipe[i] = NULL;
			mixer->params_changed++;
			tmp->params_changed++;
		}
	}
}

int mdss_mdp_mixer_pipe_unstage(struct mdss_mdp_pipe *pipe,
	struct mdss_mdp_mixer *mixer)
{
@@ -2418,11 +2445,6 @@ int mdss_mdp_mixer_pipe_unstage(struct mdss_mdp_pipe *pipe,

		mixer->params_changed++;
		mixer->stage_pipe[index] = NULL;

		if (mixer->is_right_mixer)
			pipe->mixer_right = NULL;
		else
			pipe->mixer_left = NULL;
	}

	return 0;
+103 −58
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ static int mdss_mdp_overlay_free_fb_pipe(struct msm_fb_data_type *mfd);
static int mdss_mdp_overlay_fb_parse_dt(struct msm_fb_data_type *mfd);
static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd);
static int mdss_mdp_overlay_splash_parse_dt(struct msm_fb_data_type *mfd);
static void __overlay_kickoff_requeue(struct msm_fb_data_type *mfd);

static inline bool is_ov_right_blend(struct mdp_rect *left_blend,
	struct mdp_rect *right_blend, u32 left_lm_w)
@@ -613,6 +614,10 @@ static int mdss_mdp_overlay_pipe_setup(struct msm_fb_data_type *mfd,
			pipe->is_right_blend = true;
		}
	} else if (pipe->is_right_blend) {
		/*
		 * pipe used to be right blend need to update mixer
		 * configuration to remove it as a right blend
		 */
		mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_left);
		mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_right);
		pipe->is_right_blend = false;
@@ -660,9 +665,11 @@ static int mdss_mdp_overlay_pipe_setup(struct msm_fb_data_type *mfd,
				pipe->src_split_req = true;
			}
		} else {
			if (pipe->src_split_req)
			if (pipe->src_split_req) {
				mdss_mdp_mixer_pipe_unstage(pipe,
					pipe->mixer_right);
				pipe->mixer_right = NULL;
			}
			pipe->src_split_req = false;
		}
	}
@@ -943,6 +950,8 @@ static void mdss_mdp_overlay_cleanup(struct msm_fb_data_type *mfd)
{
	struct mdss_mdp_pipe *pipe, *tmp;
	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
	struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
	bool recovery_mode = false;
	LIST_HEAD(destroy_pipes);

	mutex_lock(&mfd->lock);
@@ -951,7 +960,27 @@ static void mdss_mdp_overlay_cleanup(struct msm_fb_data_type *mfd)
		list_move(&pipe->cleanup_list, &destroy_pipes);

		/* make sure pipe fetch has been halted before freeing buffer */
		mdss_mdp_pipe_fetch_halt(pipe);
		if (mdss_mdp_pipe_fetch_halt(pipe)) {
			/*
			 * if pipe is not able to halt. Enter recovery mode,
			 * by un-staging any pipes that are attached to mixer
			 * so that any freed pipes that are not able to halt
			 * can be staged in solid fill mode and be reset
			 * with next vsync
			 */
			if (!recovery_mode) {
				recovery_mode = true;
				mdss_mdp_mixer_unstage_all(ctl->mixer_left);
				mdss_mdp_mixer_unstage_all(ctl->mixer_right);
			}
			pipe->params_changed++;
			mdss_mdp_pipe_queue_data(pipe, NULL);
		}
	}

	if (recovery_mode) {
		pr_warn("performing recovery sequence for fb%d\n", mfd->index);
		__overlay_kickoff_requeue(mfd);
	}

	__mdss_mdp_overlay_free_list_purge(mfd);
@@ -1144,61 +1173,13 @@ static void mdss_mdp_overlay_update_pm(struct mdss_overlay_private *mdp5_data)
	activate_event_timer(mdp5_data->cpu_pm_hdl, wakeup_time);
}

int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
				struct mdp_display_commit *data)
static int __overlay_queue_pipes(struct msm_fb_data_type *mfd)
{
	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
	struct mdss_mdp_pipe *pipe;
	struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
	struct mdss_mdp_ctl *tmp;
	int ret = 0;
	int sd_in_pipe = 0;

	if (!ctl) {
		pr_warn("kickoff on fb=%d without a ctl attched\n", mfd->index);
		return ret;
	}

	if (ctl->shared_lock)
		mutex_lock(ctl->shared_lock);

	mutex_lock(&mdp5_data->ov_lock);
	mutex_lock(&mfd->lock);

	/*
	 * check if there is a secure display session
	 */
	list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) {
		if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) {
			sd_in_pipe = 1;
			pr_debug("Secure pipe: %u : %08X\n",
					pipe->num, pipe->flags);
		}
	}
	/*
	 * If there is no secure display session and sd_enabled, disable the
	 * secure display session
	 */
	if (!sd_in_pipe && mdp5_data->sd_enabled) {
		if (0 == mdss_mdp_overlay_sd_ctrl(mfd, 0))
			mdp5_data->sd_enabled = 0;
	}

	mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_BEGIN);
	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);

	if (data)
		mdss_mdp_set_roi(ctl, data);

	/*
	 * Setup pipe in solid fill before unstaging,
	 * to ensure no fetches are happening after dettach or reattach.
	 */
	list_for_each_entry(pipe, &mdp5_data->pipes_cleanup, cleanup_list) {
		mdss_mdp_pipe_queue_data(pipe, NULL);
		mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_left);
		mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_right);
	}

	list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) {
		struct mdss_mdp_data *buf;
@@ -1229,17 +1210,13 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
			if (ret) {
				pr_err("can't reset DMA pipe ret=%d ctl=%d\n",
					ret, ctl->num);
				mutex_unlock(&mfd->lock);
				goto commit_fail;
				return ret;
			}

			tmp = mdss_mdp_ctl_mixer_switch(ctl,
					MDSS_MDP_WB_CTL_TYPE_LINE);
			if (!tmp) {
				mutex_unlock(&mfd->lock);
				ret = -EINVAL;
				goto commit_fail;
			}
			if (!tmp)
				return -EINVAL;
			pipe->mixer_left = mdss_mdp_mixer_get(tmp,
					MDSS_MDP_MIXER_MUX_DEFAULT);
		}
@@ -1268,6 +1245,74 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
		}
	}

	return 0;
}

static void __overlay_kickoff_requeue(struct msm_fb_data_type *mfd)
{
	struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);

	mdss_mdp_display_commit(ctl, NULL);
	mdss_mdp_display_wait4comp(ctl);

	__overlay_queue_pipes(mfd);

	mdss_mdp_display_commit(ctl, NULL);
	mdss_mdp_display_wait4comp(ctl);
}

int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
				struct mdp_display_commit *data)
{
	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
	struct mdss_mdp_pipe *pipe;
	struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
	int ret = 0;
	int sd_in_pipe = 0;

	if (ctl->shared_lock)
		mutex_lock(ctl->shared_lock);

	mutex_lock(&mdp5_data->ov_lock);
	mutex_lock(&mfd->lock);

	/*
	 * check if there is a secure display session
	 */
	list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) {
		if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) {
			sd_in_pipe = 1;
			pr_debug("Secure pipe: %u : %08X\n",
					pipe->num, pipe->flags);
		}
	}
	/*
	 * If there is no secure display session and sd_enabled, disable the
	 * secure display session
	 */
	if (!sd_in_pipe && mdp5_data->sd_enabled) {
		if (0 == mdss_mdp_overlay_sd_ctrl(mfd, 0))
			mdp5_data->sd_enabled = 0;
	}

	mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_BEGIN);
	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);

	if (data)
		mdss_mdp_set_roi(ctl, data);

	/*
	 * Setup pipe in solid fill before unstaging,
	 * to ensure no fetches are happening after dettach or reattach.
	 */
	list_for_each_entry(pipe, &mdp5_data->pipes_cleanup, cleanup_list) {
		mdss_mdp_pipe_queue_data(pipe, NULL);
		mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_left);
		mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_right);
	}

	ret = __overlay_queue_pipes(mfd);

	if (mfd->panel.type == WRITEBACK_PANEL)
		ret = mdss_mdp_wb_kickoff(mfd);
	else