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

Commit 128fd8c1 authored by Ujwal Patel's avatar Ujwal Patel Committed by Gerrit - the friendly Code Review server
Browse files

msm: mdss: enable source split with dual-dsi partial update



Enable source split with dual-dsi partial update. When source split
is used, it is a HW requirement that both layer mixer (LM) width be
of same size. Based on this requirement validate ROIs passed by
user program for the correctness and program the MDP HW and display
panel according to the ROIs. In order to simplify the logic, whenever
source split is enabled, dual-dsi or not, user program will always
sent merged ROI through l_roi during commit IOCTL.

Change-Id: Ic07deab12aa43bc4f61762303ed367fe3131389f
Signed-off-by: default avatarUjwal Patel <ujwalp@codeaurora.org>
parent 5dc82e31
Loading
Loading
Loading
Loading
+18 −2
Original line number Diff line number Diff line
@@ -312,6 +312,15 @@ struct mdss_mdp_mixer {
	u16 cursor_hoty;
	u8 rotator_mode;

	/*
	 * src_split_req is valid only for right layer mixer.
	 *
	 * VIDEO mode panels: Always true if source split is enabled.
	 * CMD mode panels: Only true if source split is enabled and
	 *                  for a given commit left and right both ROIs
	 *                  are valid.
	 */
	bool src_split_req;
	bool is_right_mixer;
	struct mdss_mdp_ctl *ctl;
	struct mdss_mdp_pipe *stage_pipe[MAX_PIPES_PER_LM];
@@ -475,6 +484,8 @@ struct mdss_mdp_pipe {

	u32 flags;
	u32 bwc_mode;

	/* valid only when pipe's output is crossing both layer mixers */
	bool src_split_req;
	bool is_right_blend;

@@ -1053,13 +1064,18 @@ void mdss_mdp_data_free(struct mdss_mdp_data *data);

u32 mdss_get_panel_framerate(struct msm_fb_data_type *mfd);
int mdss_mdp_calc_phase_step(u32 src, u32 dst, u32 *out_phase);

void mdss_mdp_intersect_rect(struct mdss_rect *res_rect,
	const struct mdss_rect *dst_rect,
	const struct mdss_rect *sci_rect);
void mdss_mdp_crop_rect(struct mdss_rect *src_rect,
	struct mdss_rect *dst_rect,
	const struct mdss_rect *sci_rect);

void rect_copy_mdss_to_mdp(struct mdp_rect *user, struct mdss_rect *kernel);
void rect_copy_mdp_to_mdss(struct mdp_rect *user, struct mdss_rect *kernel);
bool mdss_rect_overlap_check(struct mdss_rect *rect1, struct mdss_rect *rect2);
void mdss_rect_split(struct mdss_rect *in_roi, struct mdss_rect *l_roi,
	struct mdss_rect *r_roi, u32 splitpoint);

int mdss_mdp_wb_kickoff(struct msm_fb_data_type *mfd,
		struct mdss_mdp_commit_cb *commit_cb);
@@ -1080,7 +1096,7 @@ int mdss_mdp_writeback_display_commit(struct mdss_mdp_ctl *ctl, void *arg);
struct mdss_mdp_ctl *mdss_mdp_ctl_mixer_switch(struct mdss_mdp_ctl *ctl,
					       u32 return_type);
void mdss_mdp_set_roi(struct mdss_mdp_ctl *ctl,
					struct mdp_display_commit *data);
	struct mdss_rect *l_roi, struct mdss_rect *r_roi);

int mdss_mdp_wb_set_format(struct msm_fb_data_type *mfd, u32 dst_format);
int mdss_mdp_wb_get_format(struct msm_fb_data_type *mfd,
+29 −31
Original line number Diff line number Diff line
@@ -2710,7 +2710,8 @@ int mdss_mdp_ctl_reset(struct mdss_mdp_ctl *ctl)
	return 0;
}

void mdss_mdp_set_mixer_roi(struct mdss_mdp_ctl *ctl, struct mdss_rect *roi)
static void mdss_mdp_set_mixer_roi(struct mdss_mdp_ctl *ctl,
	struct mdss_rect *roi)
{
	struct mdss_rect mixer_roi;

@@ -2747,39 +2748,29 @@ static inline u32 mdss_mdp_mpq_pipe_num_map(u32 pipe_num)
}

void mdss_mdp_set_roi(struct mdss_mdp_ctl *ctl,
		struct mdp_display_commit *data)
	struct mdss_rect *l_roi, struct mdss_rect *r_roi)
{
	struct mdss_rect l_roi, r_roi;

	l_roi.x = data->l_roi.x;
	l_roi.y = data->l_roi.y;
	l_roi.w = data->l_roi.w;
	l_roi.h = data->l_roi.h;

	r_roi.x = data->r_roi.x;
	r_roi.y = data->r_roi.y;
	r_roi.w = data->r_roi.w;
	r_roi.h = data->r_roi.h;

	/* Reset ROI when we have (1) invalid ROI (2) feature disabled */
	if ((!l_roi.w && l_roi.h) || (l_roi.w && !l_roi.h) ||
		(!r_roi.w && r_roi.h) || (r_roi.w && !r_roi.h) ||
		(!l_roi.w && !l_roi.h && !r_roi.w && !r_roi.h) ||
	if ((!l_roi->w && l_roi->h) || (l_roi->w && !l_roi->h) ||
	    (!r_roi->w && r_roi->h) || (r_roi->w && !r_roi->h) ||
	    (!l_roi->w && !l_roi->h && !r_roi->w && !r_roi->h) ||
	    !ctl->panel_data->panel_info.partial_update_enabled) {
		l_roi = (struct mdss_rect)
		{0, 0, ctl->mixer_left->width, ctl->mixer_left->height};

		*l_roi = (struct mdss_rect) {0, 0,
				ctl->mixer_left->width,
				ctl->mixer_left->height};

		if (ctl->mixer_right) {
			r_roi = (struct mdss_rect)
				{0, 0, ctl->mixer_right->width,
			*r_roi = (struct mdss_rect) {0, 0,
					ctl->mixer_right->width,
					ctl->mixer_right->height};
		}
	}

	mdss_mdp_set_mixer_roi(ctl, &l_roi);
	mdss_mdp_set_mixer_roi(ctl, l_roi);

	if (ctl->mixer_right)
		mdss_mdp_set_mixer_roi(ctl->mixer_right->ctl, &r_roi);
		mdss_mdp_set_mixer_roi(ctl->mixer_right->ctl, r_roi);
}

static void mdss_mdp_mixer_setup(struct mdss_mdp_ctl *master_ctl,
@@ -2801,7 +2792,7 @@ static void mdss_mdp_mixer_setup(struct mdss_mdp_ctl *master_ctl,
		return;

	ctl = mixer->ctl;
	if (!ctl)
	if (!ctl || !ctl->valid_roi)
		return;

	mixer->params_changed = 0;
@@ -2828,7 +2819,7 @@ static void mdss_mdp_mixer_setup(struct mdss_mdp_ctl *master_ctl,
	if (pipe == NULL) {
		mixercfg = MDSS_MDP_LM_BORDER_COLOR;
	} else {
		if (ctl->mdata->mdp_rev == MDSS_MDP_HW_REV_200) {
		if (mdata->mdp_rev == MDSS_MDP_HW_REV_200) {
			mpq_num = mdss_mdp_mpq_pipe_num_map(pipe->num);
			mixercfg = 1 << (3 * mpq_num);
		} else if (pipe->num == MDSS_MDP_SSPP_VIG3 ||
@@ -2853,6 +2844,8 @@ static void mdss_mdp_mixer_setup(struct mdss_mdp_ctl *master_ctl,

		stage = i / MAX_PIPES_PER_STAGE;
		if (stage != pipe->mixer_stage) {
			pr_err("pipe%d stage mismatch. pipe->mixer_stage=%d, mixer->stage_pipe=%d. skip staging it\n",
				pipe->num, pipe->mixer_stage, stage);
			mixer->stage_pipe[i] = NULL;
			continue;
		}
@@ -2930,7 +2923,7 @@ static void mdss_mdp_mixer_setup(struct mdss_mdp_ctl *master_ctl,
		if (!pipe->src_fmt->alpha_enable && bg_alpha_enable)
			mixer_op_mode = 0;

		if (ctl->mdata->mdp_rev == MDSS_MDP_HW_REV_200) {
		if (mdata->mdp_rev == MDSS_MDP_HW_REV_200) {
			mpq_num = mdss_mdp_mpq_pipe_num_map(pipe->num);
			mixercfg |= stage << (3 * mpq_num);
		} else if ((stage < MDSS_MDP_STAGE_6) &&
@@ -2991,7 +2984,7 @@ update_mixer:
	mixer_op_mode |=
		(mdp_mixer_read(mixer, MDSS_MDP_REG_LM_OP_MODE) & BIT(0));

	if (mdata->has_src_split && mixer_mux == MDSS_MDP_MIXER_MUX_RIGHT)
	if (mixer->src_split_req && mixer_mux == MDSS_MDP_MIXER_MUX_RIGHT)
		mixer_op_mode |= BIT(31);

	mdp_mixer_write(mixer, MDSS_MDP_REG_LM_OP_MODE, mixer_op_mode);
@@ -3001,8 +2994,9 @@ update_mixer:
	mdss_mdp_ctl_write(ctl, off + MDSS_MDP_REG_CTL_LAYER_EXTN_OFFSET,
		mixercfg_extn);

	pr_debug("mixer=%d mixer_cfg=0%x mixercfg_extn=0x%x\n",
		mixer->num, mixercfg, mixercfg_extn);
	pr_debug("mixer=%d cfg=0%08x cfg_extn=0x%08x op_mode=0x%08x w=%d h=%d\n",
		mixer->num, mixercfg, mixercfg_extn,
		mixer_op_mode, mixer->roi.w, mixer->roi.h);
}

int mdss_mdp_mixer_addr_setup(struct mdss_data_type *mdata,
@@ -3524,6 +3518,10 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
			PERF_SW_COMMIT_STATE, PERF_STATUS_BUSY);
	}

	if (sctl && mdata->has_src_split)
		sctl->mixer_left->src_split_req =
			(ctl->valid_roi == sctl->valid_roi);

	if (is_bw_released || ctl->force_screen_state ||
		(ctl->mixer_left && ctl->mixer_left->params_changed) ||
		(ctl->mixer_right && ctl->mixer_right->params_changed)) {
+125 −77
Original line number Diff line number Diff line
@@ -1575,37 +1575,59 @@ static int mdss_mdp_commit_cb(enum mdp_commit_stage_type commit_stage,
/**
 * __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.
 * @l_roi: roi of the left ctl path.
 * @r_roi: roi of the right ctl path.
 *
 * Validate ctl roi against pipe's destination rectangle by checking following
 * Validate 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.
 * 1. Pipe has scaling and pipe's destination is intersecting with roi.
 * 2. Pipe's destination and roi do not overlap, In such cases, pipe should
 *    not be part of used list and should have been omitted by user program.
 */
static bool __is_roi_valid(struct mdss_mdp_pipe *pipe,
	struct mdss_rect *ctl_roi)
	struct mdss_rect *l_roi, struct mdss_rect *r_roi)
{
	bool ret = true;
	bool is_right_mixer = pipe->mixer_left->is_right_mixer;
	struct mdss_rect roi = is_right_mixer ? *r_roi : *l_roi;
	struct mdss_rect dst = pipe->dst;
	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
	u32 left_lm_w = left_lm_w_from_mfd(pipe->mfd);

	if (pipe->src_split_req)
		roi.w += r_roi->w;

	if (mdata->has_src_split && is_right_mixer)
		dst.x -= left_lm_w;

	/* condition #1 above */
	if (pipe->scale.enable_pxl_ext ||
	    (pipe->src.w != pipe->dst.w) ||
	    (pipe->src.h != pipe->dst.h)) {
	if ((pipe->scale.enable_pxl_ext) ||
	    (pipe->src.w != dst.w) || (pipe->src.h != dst.h)) {
		struct mdss_rect res;

		struct mdss_rect res = pipe->dst;
		mdss_mdp_intersect_rect(&res, &pipe->dst, ctl_roi);
		mdss_mdp_intersect_rect(&res, &dst, &roi);

		if (!mdss_rect_cmp(&res, &pipe->dst))
			return false;
		if (!mdss_rect_cmp(&res, &dst)) {
			pr_err("error. pipe%d has scaling and its output is interesecting with roi.\n",
				pipe->num);
			pr_err("pipe_dst:-> %d %d %d %d roi:-> %d %d %d %d\n",
				dst.x, dst.y, dst.w, dst.h,
				roi.x, roi.y, roi.w, roi.h);
			ret = false;
			goto end;
		}
	}

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

	return true;
	if (!mdss_rect_overlap_check(&dst, &roi)) {
		pr_err("error. pipe%d's output is outside of ROI.\n",
			pipe->num);
		ret = false;
	}
end:
	return ret;
}

void mdss_pend_mode_switch(struct msm_fb_data_type *mfd, bool pend_switch)
@@ -1616,7 +1638,7 @@ void mdss_pend_mode_switch(struct msm_fb_data_type *mfd, bool pend_switch)

int mdss_mode_switch(struct msm_fb_data_type *mfd, u32 mode)
{
	struct mdp_display_commit temp_data;
	struct mdss_rect l_roi, r_roi;
	struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
	int rc;

@@ -1628,14 +1650,15 @@ int mdss_mode_switch(struct msm_fb_data_type *mfd, u32 mode)
		 * Need to reset roi if there was partial update in previous
		 * Command frame
		 */
		temp_data.l_roi = (struct mdp_rect){0, 0,
			ctl->mixer_left->width, ctl->mixer_left->height};
		l_roi = (struct mdss_rect){0, 0,
				ctl->mixer_left->width,
				ctl->mixer_left->height};
		if (ctl->mixer_right) {
			temp_data.r_roi = (struct mdp_rect) {0, 0,
			r_roi = (struct mdss_rect) {0, 0,
				ctl->mixer_right->width,
				ctl->mixer_right->height};
		}
		mdss_mdp_set_roi(ctl, &temp_data);
		mdss_mdp_set_roi(ctl, &l_roi, &r_roi);
		mdss_mdp_switch_roi_reset(ctl);

		mdss_mdp_switch_to_cmd_mode(ctl, 1);
@@ -1698,16 +1721,92 @@ int mdss_mode_switch_post(struct msm_fb_data_type *mfd, u32 mode)
	return rc;
}

static void __validate_and_set_roi(struct msm_fb_data_type *mfd,
	struct mdp_display_commit *commit)
{
	struct mdss_mdp_pipe *pipe;
	struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
	struct mdss_rect l_roi, r_roi;
	bool skip_partial_update = true;

	if (commit) {
		rect_copy_mdp_to_mdss(&commit->l_roi, &l_roi);
		rect_copy_mdp_to_mdss(&commit->r_roi, &r_roi);

		pr_debug("input: l_roi:-> %d %d %d %d r_roi:-> %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);

		if (!ctl->panel_data->panel_info.partial_update_enabled)
			goto set_roi;

		skip_partial_update = false;

		if (is_split_lm(mfd) && mdp5_data->mdata->has_src_split) {
			u32 left_lm_w = left_lm_w_from_mfd(mfd);
			struct mdss_rect merged_roi = l_roi;

			/*
			 * When source split is enabled on split LM displays,
			 * user program merges left and right ROI and sends
			 * it through l_roi. Split this merged ROI into
			 * left/right ROI for validation.
			 */
			mdss_rect_split(&merged_roi, &l_roi, &r_roi, left_lm_w);

			/*
			 * When source split is enabled on split LM displays,
			 * it is a HW requirement that both LM have same width
			 * if update is on both sides. Since ROIs are
			 * generated by user-land program, validate against
			 * this requirement.
			 */
			if (l_roi.w && r_roi.w && (l_roi.w != r_roi.w)) {
				pr_err("error. ROI's do not match. violating src_split requirement\n");
				pr_err("l_roi:-> %d %d %d %d r_roi:-> %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);
				skip_partial_update = true;
				goto set_roi;
			}
		}

		list_for_each_entry(pipe, &mdp5_data->pipes_used, list) {
			if (!__is_roi_valid(pipe, &l_roi, &r_roi)) {
				skip_partial_update = true;
				pr_err("error. invalid pu config for pipe%d: %d,%d,%d,%d\n",
					pipe->num,
					pipe->dst.x, pipe->dst.y,
					pipe->dst.w, pipe->dst.h);
				break;
			}
		}
	}

set_roi:
	if (skip_partial_update) {
		l_roi = (struct mdss_rect){0, 0,
				ctl->mixer_left->width,
				ctl->mixer_left->height};
		if (ctl->mixer_right) {
			r_roi = (struct mdss_rect) {0, 0,
					ctl->mixer_right->width,
					ctl->mixer_right->height};
		}
	}
	mdss_mdp_set_roi(ctl, &l_roi, &r_roi);
}

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, *tmp;
	struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
	struct mdp_display_commit temp_data;
	int ret = 0;
	int sd_in_pipe = 0;
	bool need_cleanup = false, skip_partial_update = true;
	bool need_cleanup = false;
	struct mdss_mdp_commit_cb commit_cb;
	LIST_HEAD(destroy_pipes);

@@ -1771,55 +1870,7 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);

	__vsync_set_vsync_handler(mfd);


	/*
	 * partial update should not be enabled if the source pipe has
	 * scaling enabled and that pipe's dst roi is intersecting with
	 * final roi. If this condition is detected then it is too late
	 * to return an error and force fallback strategy. Instead change
	 * the ROI to be full screen and continue with the update.
	 */
	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;

			ctl_roi.x = in_roi->x;
			ctl_roi.y = in_roi->y;
			ctl_roi.w = in_roi->w;
			ctl_roi.h = in_roi->h;

			if (!__is_roi_valid(pipe, &ctl_roi)) {
				skip_partial_update = true;
				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;
			}
		}
	}

	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) {
			temp_data.r_roi = (struct mdp_rect) {0, 0,
			ctl->mixer_right->width, ctl->mixer_right->height};
		}
		mdss_mdp_set_roi(ctl, &temp_data);
	}
	__validate_and_set_roi(mfd, data);

	if (ctl->ops.wait_pingpong && mdp5_data->mdata->serialize_wait4pp)
		mdss_mdp_display_wait4pingpong(ctl, true);
@@ -4797,9 +4848,6 @@ int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd)
	if (is_panel_split(mfd) && mdp5_data->mdata->has_pingpong_split)
		mfd->split_mode = MDP_PINGPONG_SPLIT;

	if (mfd->panel_info->partial_update_enabled && is_split_lm(mfd))
		mdp5_data->mdata->has_src_split = false;

	if (mfd->panel_info->partial_update_enabled)
		mdp5_data->mdata->pp_enable = MDP_PP_DISABLE;
	else
+25 −6
Original line number Diff line number Diff line
@@ -1355,8 +1355,8 @@ static int mdss_mdp_image_setup(struct mdss_mdp_pipe *pipe,
	u32 decimation, reg_data;
	u32 tmp_src_xy, tmp_src_size;
	int ret = 0;
	struct mdss_rect dst, src;
	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
	struct mdss_rect sci, dst, src;
	bool rotation = false;

	pr_debug("ctl: %d pnum=%d wh=%dx%d src={%d,%d,%d,%d} dst={%d,%d,%d,%d}\n",
@@ -1395,14 +1395,33 @@ static int mdss_mdp_image_setup(struct mdss_mdp_pipe *pipe,
		pr_debug("Image decimation h=%d v=%d\n",
				pipe->horz_deci, pipe->vert_deci);

	sci = pipe->mixer_left->ctl->roi;
	dst = pipe->dst;
	src = pipe->src;

	if ((pipe->mixer_left->type != MDSS_MDP_MIXER_TYPE_WRITEBACK) &&
		!pipe->mixer_left->ctl->is_video_mode &&
		!pipe->src_split_req) {
		mdss_mdp_crop_rect(&src, &dst, &sci);
	if (!pipe->mixer_left->ctl->is_video_mode &&
	    (pipe->mixer_left->type != MDSS_MDP_MIXER_TYPE_WRITEBACK)) {
		struct mdss_rect ctl_roi = pipe->mixer_left->ctl->roi;
		bool is_right_mixer = pipe->mixer_left->is_right_mixer;
		/* sctl can be NULL, check validity before use */
		struct mdss_mdp_ctl *sctl =
			mdss_mdp_get_split_ctl(pipe->mixer_left->ctl);
		/* main_ctl can be NULL, check validity before use */
		struct mdss_mdp_ctl *main_ctl =
			mdss_mdp_get_main_ctl(pipe->mixer_left->ctl);

		if (pipe->src_split_req && sctl)
			ctl_roi.w += sctl->roi.w;
		else if (mdata->has_src_split && is_right_mixer && main_ctl)
			dst.x -= main_ctl->mixer_left->width;

		mdss_mdp_crop_rect(&src, &dst, &ctl_roi);

		if (is_right_mixer && main_ctl) {
			/* left + right */
			if (main_ctl->valid_roi)
				dst.x += main_ctl->roi.w;
		}

		if (pipe->flags & MDP_FLIP_LR) {
			src.x = pipe->src.x + (pipe->src.x + pipe->src.w)
				- (src.x + src.w);
+105 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include "mdss_mdp.h"
#include "mdss_mdp_formats.h"
#include "mdss_debug.h"
#include "mdss_panel.h"

enum {
	MDP_INTR_VSYNC_INTF_0,
@@ -283,6 +284,110 @@ void mdss_mdp_crop_rect(struct mdss_rect *src_rect,
	}
}

/*
 * rect_copy_mdp_to_mdss() - copy mdp_rect struct to mdss_rect
 * @mdp  - pointer to mdp_rect, destination of the copy
 * @mdss - pointer to mdss_rect, source of the copy
 */
void rect_copy_mdss_to_mdp(struct mdp_rect *mdp, struct mdss_rect *mdss)
{
	mdp->x = mdss->x;
	mdp->y = mdss->y;
	mdp->w = mdss->w;
	mdp->h = mdss->h;
}

/*
 * rect_copy_mdp_to_mdss() - copy mdp_rect struct to mdss_rect
 * @mdp  - pointer to mdp_rect, source of the copy
 * @mdss - pointer to mdss_rect, destination of the copy
 */
void rect_copy_mdp_to_mdss(struct mdp_rect *mdp, struct mdss_rect *mdss)
{
	mdss->x = mdp->x;
	mdss->y = mdp->y;
	mdss->w = mdp->w;
	mdss->h = mdp->h;
}

/*
 * mdss_rect_cmp() - compares two rects
 * @rect1 - rect value to compare
 * @rect2 - rect value to compare
 *
 * Returns 1 if the rects are same, 0 otherwise.
 */
int mdss_rect_cmp(struct mdss_rect *rect1, struct mdss_rect *rect2)
{
	return rect1->x == rect2->x && rect1->y == rect2->y &&
	       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.
 */
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 false;

	return true;
}

/*
 * 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.
 */
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);
}

int mdss_mdp_get_rau_strides(u32 w, u32 h,
			       struct mdss_mdp_format_params *fmt,
			       struct mdss_mdp_plane_sizes *ps)
Loading