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

Commit 42e5b4a7 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: enable partial update with ping-pong split"

parents 2771bc71 ea0914cf
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -237,6 +237,7 @@ struct mdss_mdp_ctl {
	int power_state;

	u32 intf_num;
	u32 slave_intf_num; /* ping-pong split */
	u32 intf_type;

	u32 opmode;
+71 −23
Original line number Diff line number Diff line
@@ -2380,10 +2380,10 @@ static void mdss_mdp_ctl_split_display_enable(int enable,
	}
}

static void mdss_mdp_ctl_dst_split_display_enable(int enable,
static void mdss_mdp_ctl_pp_split_display_enable(bool enable,
		struct mdss_mdp_ctl *ctl)
{
	u32 config = 0, cntl = 0;
	u32 cfg = 0, cntl = 0;

	if (ctl->mdata->nppb == 0) {
		pr_err("No PPB to enable PP split\n");
@@ -2393,14 +2393,12 @@ static void mdss_mdp_ctl_dst_split_display_enable(int enable,
	mdss_mdp_ctl_split_display_enable(enable, ctl, NULL);

	if (enable) {
		/* Set slave intf */
		config = ((ctl->intf_num + 1) - MDSS_MDP_INTF0) << 20;
		config |= BIT(16); /* Set horizontal split*/
		cfg = ctl->slave_intf_num << 20; /* Set slave intf */
		cfg |= BIT(16);			 /* Set horizontal split */
		cntl = BIT(5);			 /* enable dst split */
	}

	writel_relaxed(config, ctl->mdata->mdp_base +
			ctl->mdata->ppb[0].cfg_off);
	writel_relaxed(cfg, ctl->mdata->mdp_base + ctl->mdata->ppb[0].cfg_off);
	writel_relaxed(cntl, ctl->mdata->mdp_base + ctl->mdata->ppb[0].ctl_off);
}

@@ -2608,7 +2606,8 @@ int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl, bool handoff)
			mdp_mixer_write(mixer, MDSS_MDP_REG_LM_OUT_SIZE, out);
			mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_PACK_3D, 0);
		} else if (is_pingpong_split(ctl->mfd)) {
			mdss_mdp_ctl_dst_split_display_enable(1, ctl);
			ctl->slave_intf_num = (ctl->intf_num + 1);
			mdss_mdp_ctl_pp_split_display_enable(true, ctl);
		}
	}

@@ -3549,9 +3548,6 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
		ATRACE_END("mixer_programming");
	}

	ctl->roi_bkup.w = ctl->roi.w;
	ctl->roi_bkup.h = ctl->roi.h;

	/*
	 * With partial frame update, enable split display bit only
	 * when validity of ROI's on both the DSI's are identical
@@ -3574,17 +3570,6 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,

	mdss_mdp_xlog_mixer_reg(ctl);

	if (ctl->panel_data &&
			ctl->panel_data->panel_info.partial_update_enabled) {
		/*
		 * update roi of panel_info which will be
		 * used by dsi to set col_page addr of panel
		 */
		ctl->panel_data->panel_info.roi = ctl->roi;
		if (sctl && sctl->panel_data)
			sctl->panel_data->panel_info.roi = sctl->roi;
	}

	ATRACE_BEGIN("frame_ready");
	mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_CFG_DONE);
	if (commit_cb)
@@ -3597,6 +3582,69 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
	if (ctl->ops.wait_pingpong && !mdata->serialize_wait4pp)
		mdss_mdp_display_wait4pingpong(ctl, false);

	/*
	 * if serialize_wait4pp is false then roi_bkup used in wait4pingpong
	 * will be of previous frame as expected.
	 */
	ctl->roi_bkup.w = ctl->roi.w;
	ctl->roi_bkup.h = ctl->roi.h;

	/*
	 * update roi of panel_info which will be
	 * used by dsi to set col_page addr of panel.
	 */
	if (ctl->panel_data &&
	    ctl->panel_data->panel_info.partial_update_enabled) {

		if (is_pingpong_split(ctl->mfd)) {
			bool pp_split = false;
			struct mdss_rect l_roi, r_roi, temp = {0};
			u32 opmode = mdss_mdp_ctl_read(ctl,
			     MDSS_MDP_REG_CTL_TOP) & ~0xF0; /* clear OUT_SEL */
			/*
			 * with pp split enabled, it is a requirement that both
			 * panels share equal load, so split-point is center.
			 */
			u32 left_panel_w = left_lm_w_from_mfd(ctl->mfd) / 2;

			mdss_rect_split(&ctl->roi, &l_roi, &r_roi,
				left_panel_w);

			/*
			 * If update is only on left panel then we still send
			 * zeroed out right panel ROIs to DSI driver. Based on
			 * zeroed ROI, DSI driver identifies which panel is not
			 * transmitting.
			 */
			ctl->panel_data->panel_info.roi = l_roi;
			ctl->panel_data->next->panel_info.roi = r_roi;

			/* based on the roi, update ctl topology */
			if (!mdss_rect_cmp(&temp, &l_roi) &&
			    !mdss_rect_cmp(&temp, &r_roi)) {
				/* left + right */
				opmode |= (ctl->intf_num << 4);
				pp_split = true;
			} else if (mdss_rect_cmp(&temp, &l_roi)) {
				/* right only */
				opmode |= (ctl->slave_intf_num << 4);
				pp_split = false;
			} else {
				/* left only */
				opmode |= (ctl->intf_num << 4);
				pp_split = false;
			}

			mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_TOP, opmode);

			mdss_mdp_ctl_pp_split_display_enable(pp_split, ctl);
		} else {
			ctl->panel_data->panel_info.roi = ctl->roi;
			if (sctl && sctl->panel_data)
				sctl->panel_data->panel_info.roi = sctl->roi;
		}
	}

	if (commit_cb)
		commit_cb->commit_cb_fnc(MDP_COMMIT_STAGE_READY_FOR_KICKOFF,
			commit_cb->data);
+3 −5
Original line number Diff line number Diff line
@@ -607,9 +607,6 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)

	pdata = ctl->panel_data;

	ctl->roi_bkup.w = ctl->width;
	ctl->roi_bkup.h = ctl->height;

	MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->clk_enabled,
			ctx->rdptr_enabled, ctl->roi_bkup.w,
			ctl->roi_bkup.h);
@@ -1278,7 +1275,8 @@ end:

static int mdss_mdp_cmd_ctx_setup(struct mdss_mdp_ctl *ctl,
	struct mdss_mdp_cmd_ctx *ctx, int pp_num,
		int pingpong_split_slave) {
	int pingpong_split_slave)
{
	int ret = 0;

	ctx->ctl = ctl;
+32 −7
Original line number Diff line number Diff line
@@ -1567,9 +1567,24 @@ static int mdss_mdp_commit_cb(enum mdp_commit_stage_type commit_stage,
	return ret;
}

static bool __validate_roi(struct mdss_mdp_pipe *pipe,
/**
 * __is_roi_valid() - Check if ctl roi is valid for a given pipe.
 * @pipe: pipe to check against.
 * @ctl_roi: roi of the ctl path.
 *
 * Validate ctl roi against pipe's destination rectangle by checking following
 * conditions. If any of these conditions are met then return failure,
 * success otherwise.
 *
 * 1. Pipe has scaling and pipe's destination is intersecting with ctl roi.
 * 2. Pipe's destination and ctl roi overlap, meaning pipe's output is
 *    intersecting or within ctl roi. In such cases, pipe should not be
 *    part of used list and should have been omitted by user-land program.
 */
static bool __is_roi_valid(struct mdss_mdp_pipe *pipe,
	struct mdss_rect *ctl_roi)
{
	/* condition #1 above */
	if (pipe->scale.enable_pxl_ext ||
	    (pipe->src.w != pipe->dst.w) ||
	    (pipe->src.h != pipe->dst.h)) {
@@ -1578,10 +1593,14 @@ static bool __validate_roi(struct mdss_mdp_pipe *pipe,
		mdss_mdp_intersect_rect(&res, &pipe->dst, ctl_roi);

		if (!mdss_rect_cmp(&res, &pipe->dst))
			return true;
			return false;
	}

	/* condition #2 above */
	if (mdss_rect_overlap_check(&pipe->dst, ctl_roi))
		return false;

	return true;
}

void mdss_pend_mode_switch(struct msm_fb_data_type *mfd, bool pend_switch)
@@ -1735,9 +1754,9 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
	if (data && ctl->panel_data->panel_info.partial_update_enabled) {
		struct mdss_rect ctl_roi;
		struct mdp_rect *in_roi;

		skip_partial_update = false;
		list_for_each_entry(pipe, &mdp5_data->pipes_used, list) {

			in_roi = pipe->mixer_left->is_right_mixer ?
				&data->r_roi : &data->l_roi;

@@ -1746,10 +1765,14 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
			ctl_roi.w = in_roi->w;
			ctl_roi.h = in_roi->h;

			if (__validate_roi(pipe, &ctl_roi)) {
			if (!__is_roi_valid(pipe, &ctl_roi)) {
				skip_partial_update = true;
				pr_err("error. invalid config with partial update for pipe%d\n",
				pr_debug("error. invalid config with partial update for pipe%d\n",
					pipe->num);
				pr_debug("ctl_roi: %d,%d,%d,%d pipe->dst: %d,%d,%d,%d\n",
					ctl_roi.x, ctl_roi.y, ctl_roi.w,
					ctl_roi.h, pipe->dst.x, pipe->dst.y,
					pipe->dst.w, pipe->dst.h);
				break;
			}
		}
@@ -1758,6 +1781,8 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
	if (!skip_partial_update) {
		mdss_mdp_set_roi(ctl, data);
	} else {
		memset(&temp_data, 0, sizeof(temp_data));

		temp_data.l_roi = (struct mdp_rect){0, 0,
			ctl->mixer_left->width, ctl->mixer_left->height};
		if (ctl->mixer_right) {
@@ -3511,7 +3536,7 @@ static int mdss_mdp_histo_ioctl(struct msm_fb_data_type *mfd, u32 cmd,

	if (mfd->panel_info->partial_update_enabled && mdp5_data->dyn_pu_state
			&& (cmd != MSMFB_HISTOGRAM_STOP)) {
		pr_err("Partial update feature is enabled.\n");
		pr_debug("Partial update feature is enabled.\n");
		return -EPERM;
	}

+66 −0
Original line number Diff line number Diff line
@@ -536,6 +536,72 @@ static inline int mdss_rect_cmp(struct mdss_rect *rect1,
		rect1->w == rect2->w && rect1->h == rect2->h);
}

/*
 * mdss_rect_overlap_check() - compare two rects and check if they overlap
 * @rect1 - rect value to compare
 * @rect2 - rect value to compare
 *
 * Returns true if rects overlap, false otherwise.
 */
static inline bool mdss_rect_overlap_check(struct mdss_rect *rect1,
	struct mdss_rect *rect2)
{
	u32 rect1_left = rect1->x, rect1_right = rect1->x + rect1->w;
	u32 rect1_top = rect1->y, rect1_bottom = rect1->y + rect1->h;
	u32 rect2_left = rect2->x, rect2_right = rect2->x + rect2->w;
	u32 rect2_top = rect2->y, rect2_bottom = rect2->y + rect2->h;

	if ((rect1_right <= rect2_left) ||
	    (rect1_left >= rect2_right) ||
	    (rect1_bottom <= rect2_top) ||
	    (rect1_top >= rect2_bottom))
		return true;

	return false;
}

/*
 * mdss_rect_split() - split roi into two with regards to split-point.
 * @in_roi - input roi, non-split
 * @l_roi  - left roi after split
 * @r_roi  - right roi after split
 *
 * Split input ROI into left and right ROIs with respect to split-point. This
 * is useful during partial update with ping-pong split enabled, where user-land
 * program is aware of only one frame-buffer but physically there are two
 * distinct panels which requires their own ROIs.
 */
static inline void mdss_rect_split(struct mdss_rect *in_roi,
	struct mdss_rect *l_roi, struct mdss_rect *r_roi, u32 splitpoint)
{
	memset(l_roi, 0x0, sizeof(*l_roi));
	memset(r_roi, 0x0, sizeof(*r_roi));

	/* left update needed */
	if (in_roi->x < splitpoint) {
		*l_roi = *in_roi;

		if (l_roi->x + l_roi->w >= splitpoint)
			l_roi->w = splitpoint - in_roi->x;
	}

	/* right update needed */
	if ((in_roi->x + in_roi->w) > splitpoint) {
		*r_roi = *in_roi;

		if (in_roi->x < splitpoint) {
			r_roi->x = 0;
			r_roi->w = in_roi->x + in_roi->w - splitpoint;
		} else {
			r_roi->x = in_roi->x - splitpoint;
		}
	}

	pr_debug("left: %d,%d,%d,%d right: %d,%d,%d,%d\n",
		l_roi->x, l_roi->y, l_roi->w, l_roi->h,
		r_roi->x, r_roi->y, r_roi->w, r_roi->h);
}

/*
 * mdss_panel_get_vtotal() - return panel vertical height
 * @pinfo:	Pointer to panel info containing all panel information