diff options
| author | Ujwal Patel <ujwalp@codeaurora.org> | 2015-03-05 18:43:53 -0800 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:38:34 -0700 |
| commit | eca9b5401e9c5aafb25d408fdc02a568f17f5d95 (patch) | |
| tree | c81f805d49013776a54c8dd565cc60528603977e | |
| parent | 65ded8d75deeb5eda2ab508f3880609d4dd807a2 (diff) | |
msm: mdss: fix right_blend pipe assignment for validate layer path
When source split is enabled, a layer mixer can have two pipes staged
on a same z_order, or stage. To support this, pipe on the right side of
the blending is recognized as right_blend. Current validate ioctl path
is missing implementation for this use-case which is causing unexpected
behaviour when source split is enabled. Fix this by bringing a logic to
identify pipe as a right blend.
Change-Id: Ia117afbad993d9d60f28f1ea6641b780ba866783
Signed-off-by: Ujwal Patel <ujwalp@codeaurora.org>
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_layer.c | 66 |
1 files changed, 54 insertions, 12 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c index e01830903923..2a31123bb8eb 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_layer.c +++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c @@ -45,6 +45,15 @@ enum { MDSS_MDP_RETIRE_FENCE, }; +static inline bool is_layer_right_blend(struct mdp_rect *left_blend, + struct mdp_rect *right_blend, u32 left_lm_w) +{ + return ((left_blend->x + left_blend->w) == right_blend->x) && + ((left_blend->x + left_blend->w) != left_lm_w) && + (left_blend->y == right_blend->y) && + (left_blend->h == right_blend->h); +} + static bool is_pipe_type_vig(struct mdss_data_type *mdata, u32 ndx) { u32 i; @@ -335,7 +344,8 @@ exit_fail: static int __configure_pipe_params(struct msm_fb_data_type *mfd, struct mdp_input_layer *layer, struct mdss_mdp_pipe *pipe, - bool is_single_layer, bool right_layer_mixer, u32 mixer_mux) + struct mdss_mdp_pipe *left_blend_pipe, bool is_single_layer, + u32 mixer_mux) { int ret = 0; u32 left_lm_w = left_lm_w_from_mfd(mfd); @@ -375,8 +385,6 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd, pipe->flags |= MDP_DEINTERLACE; if (layer->flags & MDP_LAYER_BWC) pipe->flags |= MDP_BWC_EN; - if (right_layer_mixer) - pipe->flags |= MDSS_MDP_RIGHT_MIXER; pipe->scale.enable_pxl_ext = layer->flags & MDP_LAYER_ENABLE_PIXEL_EXT; pipe->is_fg = layer->flags & MDP_LAYER_FORGROUND; @@ -409,6 +417,27 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd, * staging, same pipe will be stagged on both layer mixers. */ if (mdata->has_src_split) { + if (left_blend_pipe) { + if (pipe->priority <= left_blend_pipe->priority) { + pr_err("priority limitation. left:%d right%d\n", + left_blend_pipe->priority, + pipe->priority); + ret = -EPERM; + goto end; + } else { + pr_debug("pipe%d is a right_pipe\n", pipe->num); + pipe->is_right_blend = true; + } + } else if (pipe->is_right_blend) { + /* + * pipe used to be right blend. So 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; + } + if ((mixer_mux == MDSS_MDP_MIXER_MUX_LEFT) && ((layer->dst_rect.x + layer->dst_rect.w) > mixer->width)) { if (layer->dst_rect.x >= mixer->width) { @@ -905,15 +934,14 @@ static int __validate_layers(struct msm_fb_data_type *mfd, u32 mixer_mux, dst_x; int layer_count = commit->input_layer_cnt; - struct mdss_mdp_pipe *pipe, *tmp; + struct mdss_mdp_pipe *pipe, *tmp, *left_blend_pipe; struct mdss_mdp_pipe *right_plist[MAX_PIPES_PER_LM] = {0}; struct mdss_mdp_pipe *left_plist[MAX_PIPES_PER_LM] = {0}; struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); - struct mdss_data_type *mdata = mfd_to_mdata(mfd); struct mdss_mdp_mixer *mixer = NULL; - struct mdp_input_layer *layer, *layer_list; - bool is_single_layer = false, right_layer_mixer = false; + struct mdp_input_layer *layer, *prev_layer, *layer_list; + bool is_single_layer = false; bool new_pipe = false; ret = mutex_lock_interruptible(&mdp5_data->ov_lock); @@ -940,13 +968,27 @@ static int __validate_layers(struct msm_fb_data_type *mfd, for (i = 0; i < layer_count; i++) { layer = &layer_list[i]; dst_x = layer->dst_rect.x; - right_layer_mixer = false; + left_blend_pipe = NULL; + + prev_layer = (i > 0) ? &layer_list[i - 1] : NULL; + /* + * check if current layer is at same z_order as + * previous one and qualifies as a right blend. If yes, + * pass a pointer to the pipe representing previous + * overlay or in other terms left blend layer. + * + * Following logic of selecting left_blend has an inherent + * assumption that layer list is sorted on dst_x within a + * same z_order. + */ + if (prev_layer && (prev_layer->z_order == layer->z_order) && + is_layer_right_blend(&prev_layer->dst_rect, + &layer->dst_rect, left_lm_w)) + left_blend_pipe = pipe; if (layer->dst_rect.x >= left_lm_w) { is_single_layer = (right_lm_layers == 1); mixer_mux = MDSS_MDP_MIXER_MUX_RIGHT; - if (!mdata->has_src_split) - right_layer_mixer = true; } else { is_single_layer = (left_lm_layers == 1); mixer_mux = MDSS_MDP_MIXER_MUX_LEFT; @@ -1010,8 +1052,8 @@ static int __validate_layers(struct msm_fb_data_type *mfd, if (new_pipe) release_ndx |= pipe->ndx; - ret = __configure_pipe_params(mfd, layer, pipe, is_single_layer, - right_layer_mixer, mixer_mux); + ret = __configure_pipe_params(mfd, layer, pipe, + left_blend_pipe, is_single_layer, mixer_mux); if (ret) { pr_err("configure pipe param failed: pipe index= %d\n", pipe->ndx); |
