diff options
| author | Abhijit Kulkarni <kabhijit@codeaurora.org> | 2017-01-30 18:05:43 -0800 |
|---|---|---|
| committer | Abhijit Kulkarni <kabhijit@codeaurora.org> | 2017-01-31 15:12:26 -0800 |
| commit | f04daa236be0768fd580ec1a6979b74f2744fe7c (patch) | |
| tree | 746d0e56ad31d6121c6e633c4511564906e2f888 | |
| parent | ea4719da1fbdb56ef368b725496c3acdb4dde51c (diff) | |
msm: mdss: enable dest_scaler data protection
This change enables the mutex for driver dest_scaler data structure.
Before this change display_thread could be updating the registers
based on the dest scaler data for the previous commit and the user
thread could go ahead and update the same data strcture for the
same commit. This could cause incorrect register programming.
This change necessitated moving the dest scaler update
out of pp updates so that we don't block the mutex till the end of
the commit.
CRs-Fixed: 1105994
Change-Id: I75d6f159e02fb1c0ed95bc5b6224843c61ec2da2
Signed-off-by: Abhijit Kulkarni <kabhijit@codeaurora.org>
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp.h | 2 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_ctl.c | 1 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_layer.c | 7 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_overlay.c | 20 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_pp.c | 14 |
5 files changed, 34 insertions, 10 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h index cb9cc08140f0..0613ad786092 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.h +++ b/drivers/video/fbdev/msm/mdss_mdp.h @@ -555,6 +555,7 @@ struct mdss_mdp_ctl { bool switch_with_handoff; struct mdss_mdp_avr_info avr_info; bool commit_in_progress; + struct mutex ds_lock; }; struct mdss_mdp_mixer { @@ -1969,6 +1970,7 @@ void mdss_mdp_enable_hw_irq(struct mdss_data_type *mdata); void mdss_mdp_disable_hw_irq(struct mdss_data_type *mdata); void mdss_mdp_set_supported_formats(struct mdss_data_type *mdata); +int mdss_mdp_dest_scaler_setup_locked(struct mdss_mdp_mixer *mixer); #ifdef CONFIG_FB_MSM_MDP_NONE struct mdss_data_type *mdss_mdp_get_mdata(void) diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index ffbf156e9eed..8b31ff648942 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -2407,6 +2407,7 @@ struct mdss_mdp_ctl *mdss_mdp_ctl_alloc(struct mdss_data_type *mdata, mutex_init(&ctl->flush_lock); mutex_init(&ctl->rsrc_lock); spin_lock_init(&ctl->spin_lock); + mutex_init(&ctl->ds_lock); BLOCKING_INIT_NOTIFIER_HEAD(&ctl->notifier_head); pr_debug("alloc ctl_num=%d\n", ctl->num); break; diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c index 0eb82dd8371d..c9e32d69d444 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_layer.c +++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c @@ -399,6 +399,7 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd, ctl = mfd_to_ctl(mfd); sctl = mdss_mdp_get_split_ctl(ctl); + mutex_lock(&ctl->ds_lock); if (ctl->mixer_left) ds_left = ctl->mixer_left->ds; @@ -412,6 +413,7 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd, case DS_DUAL_MODE: if (!ds_left || !ds_right) { pr_err("Cannot support DUAL mode dest scaling\n"); + mutex_unlock(&ctl->ds_lock); return -EINVAL; } @@ -457,6 +459,7 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd, case DS_LEFT: if (!ds_left) { pr_err("LM in ctl does not support Destination Scaler\n"); + mutex_unlock(&ctl->ds_lock); return -EINVAL; } ds_left->flags &= ~(DS_DUAL_MODE|DS_RIGHT); @@ -486,6 +489,7 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd, case DS_RIGHT: if (!ds_right) { pr_err("Cannot setup DS_RIGHT because only single DS assigned to ctl\n"); + mutex_unlock(&ctl->ds_lock); return -EINVAL; } @@ -522,7 +526,6 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd, ds_right->src_height, ds_right->flags); break; } - } else { pr_err("NULL destionation scaler data\n"); return -EFAULT; @@ -559,6 +562,7 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd, goto reset_mixer; } + mutex_unlock(&ctl->ds_lock); return ret; reset_mixer: @@ -592,6 +596,7 @@ reset_mixer: ctl->mixer_right->height); } + mutex_unlock(&ctl->ds_lock); return ret; } diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index 9864d611e8e4..a5e2dccb2501 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -1471,6 +1471,23 @@ static void __unstage_pipe_and_clean_buf(struct msm_fb_data_type *mfd, __pipe_buf_mark_cleanup(mfd, buf); } +static int __dest_scaler_setup(struct msm_fb_data_type *mfd) +{ + struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); + + mutex_lock(&ctl->ds_lock); + + if (ctl->mixer_left) + mdss_mdp_dest_scaler_setup_locked(ctl->mixer_left); + + if (ctl->mixer_right) + mdss_mdp_dest_scaler_setup_locked(ctl->mixer_right); + + mutex_unlock(&ctl->ds_lock); + + return 0; +} + static int __overlay_queue_pipes(struct msm_fb_data_type *mfd) { struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); @@ -2394,6 +2411,9 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, mutex_unlock(&mdp5_data->list_lock); mdp5_data->kickoff_released = false; + ATRACE_BEGIN("dest_scaler_programming"); + ret = __dest_scaler_setup(mfd); + ATRACE_END("dest_scaler_programming"); if (mfd->panel.type == WRITEBACK_PANEL) { ATRACE_BEGIN("wb_kickoff"); diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.c b/drivers/video/fbdev/msm/mdss_mdp_pp.c index d83bedacec28..7212de8a43f9 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp.c @@ -2559,7 +2559,7 @@ dspp_exit: return ret; } -static int pp_dest_scaler_setup(struct mdss_mdp_mixer *mixer) +int mdss_mdp_dest_scaler_setup_locked(struct mdss_mdp_mixer *mixer) { struct mdss_mdp_ctl *ctl; struct mdss_data_type *mdata; @@ -2618,7 +2618,8 @@ static int pp_dest_scaler_setup(struct mdss_mdp_mixer *mixer) writel_relaxed(op_mode, MDSS_MDP_REG_DEST_SCALER_OP_MODE + ds_offset); - if (ds->flags & DS_SCALE_UPDATE) { + if ((ds->flags & DS_SCALE_UPDATE) || + (ds->flags & DS_ENHANCER_UPDATE)) { ret = mdss_mdp_qseed3_setup(&ds->scaler, ds->scaler_base, ds->lut_base, &dest_scaler_fmt); @@ -2631,11 +2632,6 @@ static int pp_dest_scaler_setup(struct mdss_mdp_mixer *mixer) * for each commit if there is no change. */ ds->flags &= ~DS_SCALE_UPDATE; - } - - if (ds->flags & DS_ENHANCER_UPDATE) { - mdss_mdp_scaler_detail_enhance_cfg(&ds->scaler.detail_enhance, - ds->scaler_base); ds->flags &= ~DS_ENHANCER_UPDATE; } @@ -2643,7 +2639,9 @@ static int pp_dest_scaler_setup(struct mdss_mdp_mixer *mixer) if (ds->flags & (DS_ENABLE | DS_VALIDATE)) { pr_debug("FLUSH[%d]: flags:%X, op_mode:%x\n", ds->num, ds->flags, op_mode); + mutex_lock(&ctl->flush_lock); ctl->flush_bits |= BIT(13 + ds->num); + mutex_unlock(&ctl->flush_lock); } ds->flags &= ~DS_VALIDATE; @@ -2760,13 +2758,11 @@ int mdss_mdp_pp_setup_locked(struct mdss_mdp_ctl *ctl) } if (ctl->mixer_left) { - pp_dest_scaler_setup(ctl->mixer_left); pp_mixer_setup(ctl->mixer_left); pp_dspp_setup(disp_num, ctl->mixer_left); pp_ppb_setup(ctl->mixer_left); } if (ctl->mixer_right) { - pp_dest_scaler_setup(ctl->mixer_right); pp_mixer_setup(ctl->mixer_right); pp_dspp_setup(disp_num, ctl->mixer_right); pp_ppb_setup(ctl->mixer_right); |
