Loading drivers/video/msm/mdss/mdss_mdp.h +18 −2 Original line number Diff line number Diff line Loading @@ -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]; Loading Loading @@ -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; Loading Loading @@ -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); Loading @@ -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, Loading drivers/video/msm/mdss/mdss_mdp_ctl.c +29 −31 Original line number Diff line number Diff line Loading @@ -2716,7 +2716,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; Loading Loading @@ -2753,39 +2754,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, Loading @@ -2807,7 +2798,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; Loading @@ -2834,7 +2825,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 || Loading @@ -2859,6 +2850,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; } Loading Loading @@ -2936,7 +2929,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) && Loading Loading @@ -2997,7 +2990,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); Loading @@ -3007,8 +3000,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, Loading Loading @@ -3530,6 +3524,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)) { Loading drivers/video/msm/mdss/mdss_mdp_overlay.c +125 −77 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -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; Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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 Loading drivers/video/msm/mdss/mdss_mdp_pipe.c +25 −6 Original line number Diff line number Diff line Loading @@ -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", Loading Loading @@ -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); Loading drivers/video/msm/mdss/mdss_mdp_util.c +105 −0 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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 Loading
drivers/video/msm/mdss/mdss_mdp.h +18 −2 Original line number Diff line number Diff line Loading @@ -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]; Loading Loading @@ -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; Loading Loading @@ -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); Loading @@ -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, Loading
drivers/video/msm/mdss/mdss_mdp_ctl.c +29 −31 Original line number Diff line number Diff line Loading @@ -2716,7 +2716,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; Loading Loading @@ -2753,39 +2754,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, Loading @@ -2807,7 +2798,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; Loading @@ -2834,7 +2825,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 || Loading @@ -2859,6 +2850,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; } Loading Loading @@ -2936,7 +2929,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) && Loading Loading @@ -2997,7 +2990,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); Loading @@ -3007,8 +3000,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, Loading Loading @@ -3530,6 +3524,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)) { Loading
drivers/video/msm/mdss/mdss_mdp_overlay.c +125 −77 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -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; Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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 Loading
drivers/video/msm/mdss/mdss_mdp_pipe.c +25 −6 Original line number Diff line number Diff line Loading @@ -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", Loading Loading @@ -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); Loading
drivers/video/msm/mdss/mdss_mdp_util.c +105 −0 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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