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

Commit b481c227 authored by Ujwal Patel's avatar Ujwal Patel
Browse files

msm: mdss: fix single layer calculation during PREPARE IOCTL



BW calculations of display controller depends on how many pipes are
staged on a given layer mixer (LM). Currently BW calculations are done
twice, once during PREPARE IOCTL to check if BW is within system defined
limits and other during commit IOCTL. During both calculations, we need
to find out how many pipes are staged on a give LM. When these
calculations are done during frame (n)'s PREPARE IOCTL, frame (n-1)'s
pipe stage information is used rather than frame (n)'s. This can lead to
false BW checks in PREPARE IOCTL and allows display controller with
configuration beyond its BW limits. Fix this by propagating frame (n)'s
intended number of staged pipes to BW calculation function.

Change-Id: I7561f6b020dc46ca356efac3f690bda1eb810ca4
Signed-off-by: default avatarUjwal Patel <ujwalp@codeaurora.org>
Signed-off-by: default avatarIngrid Gallardo <ingridg@codeaurora.org>
parent c8100225
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -607,7 +607,7 @@ int mdss_mdp_overlay_get_buf(struct msm_fb_data_type *mfd,
			     u32 flags);
int mdss_mdp_overlay_pipe_setup(struct msm_fb_data_type *mfd,
	struct mdp_overlay *req, struct mdss_mdp_pipe **ppipe,
	struct mdss_mdp_pipe *left_blend_pipe);
	struct mdss_mdp_pipe *left_blend_pipe, bool is_single_layer);
void mdss_mdp_handoff_cleanup_pipes(struct msm_fb_data_type *mfd,
							u32 type);
int mdss_mdp_overlay_release(struct msm_fb_data_type *mfd, int ndx);
@@ -643,7 +643,7 @@ int mdss_mdp_perf_bw_check_pipe(struct mdss_mdp_perf_params *perf,
		struct mdss_mdp_pipe *pipe);
int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe,
	struct mdss_mdp_perf_params *perf, struct mdss_rect *roi,
	bool apply_fudge);
	bool apply_fudge, bool is_single_layer);
u32 mdss_mdp_get_mdp_clk_rate(struct mdss_data_type *mdata);
int mdss_mdp_ctl_notify(struct mdss_mdp_ctl *ctl, int event);
void mdss_mdp_ctl_notifier_register(struct mdss_mdp_ctl *ctl,
+22 −28
Original line number Diff line number Diff line
@@ -335,32 +335,14 @@ u32 mdss_mdp_perf_calc_pipe_prefill_single(struct mdss_mdp_prefill_params
	return prefill_bytes;
}

static inline bool mdss_mdp_is_single_pipe_per_mixer(
	struct mdss_mdp_mixer *mixer)
{
	bool is_single = true;
	int cnt = 0;
	int i;

	for (i = 0; i < MAX_PIPES_PER_LM; i++) {
		struct mdss_mdp_pipe *pipe = mixer->stage_pipe[i];
		if (pipe) {
			cnt++;
			if (cnt > 1) {
				is_single = false;
				break;
			}
		}
	}
	return is_single;
}

/**
 * mdss_mdp_perf_calc_pipe() - calculate performance numbers required by pipe
 * @pipe:	Source pipe struct containing updated pipe params
 * @perf:	Structure containing values that should be updated for
 *		performance tuning
 * @apply_fudge:	Boolean to determine if mdp clock fudge is applicable
 * @is_single_layer: Indicate if the calculation is for a single pipe staged
 *		in the layer mixer
 *
 * Function calculates the minimum required performance calculations in order
 * to avoid MDP underflow. The calculations are based on the way MDP
@@ -369,7 +351,7 @@ static inline bool mdss_mdp_is_single_pipe_per_mixer(
 */
int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe,
	struct mdss_mdp_perf_params *perf, struct mdss_rect *roi,
	bool apply_fudge)
	bool apply_fudge, bool is_single_layer)
{
	struct mdss_mdp_mixer *mixer;
	int fps = DEFAULT_FRAME_RATE;
@@ -480,7 +462,7 @@ int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe,
	prefill_params.is_hflip = pipe->flags & MDP_FLIP_LR;
	prefill_params.is_cmd = !mixer->ctl->is_video_mode;

	if (mdss_mdp_is_single_pipe_per_mixer(mixer))
	if (is_single_layer)
		perf->prefill_bytes =
			mdss_mdp_perf_calc_pipe_prefill_single(&prefill_params);
	else if (!prefill_params.is_cmd)
@@ -602,7 +584,7 @@ static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer,
			continue;

		if (mdss_mdp_perf_calc_pipe(pipe, &tmp, &mixer->roi,
			apply_fudge))
			apply_fudge, (num_pipes == 1)))
			continue;

		prefill_bytes += tmp.prefill_bytes;
@@ -816,14 +798,26 @@ int mdss_mdp_perf_bw_check_pipe(struct mdss_mdp_perf_params *perf,
static void mdss_mdp_perf_calc_ctl(struct mdss_mdp_ctl *ctl,
		struct mdss_mdp_perf_params *perf)
{
	struct mdss_mdp_pipe **left_plist, **right_plist;
	struct mdss_mdp_pipe *left_plist[MAX_PIPES_PER_LM];
	struct mdss_mdp_pipe *right_plist[MAX_PIPES_PER_LM];
	int i, left_cnt = 0, right_cnt = 0;

	left_plist = ctl->mixer_left ? ctl->mixer_left->stage_pipe : NULL;
	right_plist = ctl->mixer_right ? ctl->mixer_right->stage_pipe : NULL;
	for (i = 0; i < MAX_PIPES_PER_LM; i++) {
		if (ctl->mixer_left && ctl->mixer_left->stage_pipe[i]) {
			left_plist[left_cnt] =
					ctl->mixer_left->stage_pipe[i];
			left_cnt++;
		}

		if (ctl->mixer_right && ctl->mixer_right->stage_pipe[i]) {
			right_plist[right_cnt] =
					ctl->mixer_right->stage_pipe[i];
			right_cnt++;
		}
	}

	__mdss_mdp_perf_calc_ctl_helper(ctl, perf,
			left_plist, (left_plist ? MAX_PIPES_PER_LM : 0),
			right_plist, (right_plist ? MAX_PIPES_PER_LM : 0));
		left_plist, left_cnt, right_plist, right_cnt);

	if (ctl->is_video_mode) {
		if (perf->bw_overlap > perf->bw_prefill)
+1 −1
Original line number Diff line number Diff line
@@ -467,7 +467,7 @@ static bool mdss_mdp_traffic_shaper_helper(struct mdss_mdp_ctl *ctl,

		if (enable) {
			if (mdss_mdp_perf_calc_pipe(pipe, &perf, &mixer->roi,
				false))
				false, true))
				continue;

			clk_rate = max(mdss_mdp_get_mdp_clk_rate(ctl->mdata),
+33 −10
Original line number Diff line number Diff line
@@ -401,14 +401,16 @@ int mdss_mdp_overlay_req_check(struct msm_fb_data_type *mfd,
	return 0;
}

static int __mdp_pipe_tune_perf(struct mdss_mdp_pipe *pipe)
static int __mdp_pipe_tune_perf(struct mdss_mdp_pipe *pipe,
	bool is_single_layer)
{
	struct mdss_data_type *mdata = pipe->mixer_left->ctl->mdata;
	struct mdss_mdp_perf_params perf;
	int rc;

	for (;;) {
		rc = mdss_mdp_perf_calc_pipe(pipe, &perf, NULL, true);
		rc = mdss_mdp_perf_calc_pipe(pipe, &perf, NULL, true,
			is_single_layer);

		if (!rc && (perf.mdp_clk_rate <= mdata->max_mdp_clk_rate)) {
			rc = mdss_mdp_perf_bw_check_pipe(&perf, pipe);
@@ -499,7 +501,7 @@ static inline void __mdss_mdp_overlay_set_chroma_sample(

int mdss_mdp_overlay_pipe_setup(struct msm_fb_data_type *mfd,
	struct mdp_overlay *req, struct mdss_mdp_pipe **ppipe,
	struct mdss_mdp_pipe *left_blend_pipe)
	struct mdss_mdp_pipe *left_blend_pipe, bool is_single_layer)
{
	struct mdss_mdp_format_params *fmt;
	struct mdss_mdp_pipe *pipe;
@@ -868,7 +870,7 @@ int mdss_mdp_overlay_pipe_setup(struct msm_fb_data_type *mfd,
		}
	}

	ret = __mdp_pipe_tune_perf(pipe);
	ret = __mdp_pipe_tune_perf(pipe, is_single_layer);
	if (ret) {
		pr_debug("unable to satisfy performance. ret=%d\n", ret);
		goto exit_fail;
@@ -946,7 +948,7 @@ static int mdss_mdp_overlay_set(struct msm_fb_data_type *mfd,
		/* userspace zorder start with stage 0 */
		req->z_order += MDSS_MDP_STAGE_0;

		ret = mdss_mdp_overlay_pipe_setup(mfd, req, &pipe, NULL);
		ret = mdss_mdp_overlay_pipe_setup(mfd, req, &pipe, NULL, false);

		req->z_order -= MDSS_MDP_STAGE_0;
	}
@@ -1283,7 +1285,7 @@ static int __overlay_queue_pipes(struct msm_fb_data_type *mfd)
		    (ctl->mdata->wfd_mode == MDSS_MDP_WFD_SHARED))) {
			if (ctl->mdata->mixer_switched) {
				ret = mdss_mdp_overlay_pipe_setup(mfd,
					&pipe->req_data, &pipe, NULL);
					&pipe->req_data, &pipe, NULL, false);
				pr_debug("reseting DMA pipe for ctl=%d",
					 ctl->num);
			}
@@ -1791,7 +1793,8 @@ static int mdss_mdp_overlay_get_fb_pipe(struct msm_fb_data_type *mfd,

		pr_debug("allocating base pipe mux=%d\n", mixer_mux);

		ret = mdss_mdp_overlay_pipe_setup(mfd, &req, &pipe, NULL);
		ret = mdss_mdp_overlay_pipe_setup(mfd, &req, &pipe, NULL,
			false);
		if (ret)
			return ret;
	}
@@ -2768,6 +2771,8 @@ static int __handle_overlay_prepare(struct msm_fb_data_type *mfd,
	int new_reqs = 0, left_cnt = 0, right_cnt = 0;
	int num_ovs = ovlist->num_overlays;
	u32 left_lm_w = left_lm_w_from_mfd(mfd);
	u32 left_lm_ovs = 0, right_lm_ovs = 0;
	bool is_single_layer = false;

	struct mdss_data_type *mdata = mfd_to_mdata(mfd);
	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
@@ -2807,6 +2812,17 @@ static int __handle_overlay_prepare(struct msm_fb_data_type *mfd,

	pr_debug("prepare fb%d num_ovs=%d\n", mfd->index, num_ovs);

	for (i = 0; i < num_ovs; i++) {
		if (IS_RIGHT_MIXER_OV(ip_ovs[i].flags, ip_ovs[i].dst_rect.x,
			left_lm_w))
			right_lm_ovs++;
		else
			left_lm_ovs++;

		if ((left_lm_ovs > 1) && (right_lm_ovs > 1))
			break;
	}

	for (i = 0; i < num_ovs; i++) {
		left_blend_pipe = NULL;

@@ -2829,9 +2845,15 @@ static int __handle_overlay_prepare(struct msm_fb_data_type *mfd,
			req = &ip_ovs[i];
		}

		if (IS_RIGHT_MIXER_OV(ip_ovs[i].flags, ip_ovs[i].dst_rect.x,
			left_lm_w))
			is_single_layer = (right_lm_ovs == 1);
		else
			is_single_layer = (left_lm_ovs == 1);

		req->z_order += MDSS_MDP_STAGE_0;
		ret = mdss_mdp_overlay_pipe_setup(mfd, req, &pipe,
			left_blend_pipe);
			left_blend_pipe, is_single_layer);
		req->z_order -= MDSS_MDP_STAGE_0;

		if (IS_ERR_VALUE(ret))
@@ -2875,8 +2897,9 @@ validate_exit:
		ovlist->processed_overlays = i;

	if (IS_ERR_VALUE(ret)) {
		pr_debug("err=%d total_ovs:%d processed:%d\n",
			ret, num_ovs, ovlist->processed_overlays);
		pr_debug("err=%d total_ovs:%d processed:%d left:%d right:%d\n",
			ret, num_ovs, ovlist->processed_overlays, left_lm_ovs,
			right_lm_ovs);
		mdss_mdp_overlay_release(mfd, new_reqs);
	}
	mutex_unlock(&mdp5_data->ov_lock);
+1 −1
Original line number Diff line number Diff line
@@ -264,7 +264,7 @@ static struct mdss_mdp_pipe *mdss_mdp_splash_get_pipe(
	uint32_t image_size = SPLASH_IMAGE_WIDTH * SPLASH_IMAGE_HEIGHT
						* SPLASH_IMAGE_BPP;

	ret = mdss_mdp_overlay_pipe_setup(mfd, req, &pipe, NULL);
	ret = mdss_mdp_overlay_pipe_setup(mfd, req, &pipe, NULL, true);
	if (ret)
		return NULL;