summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbhijit Kulkarni <kabhijit@codeaurora.org>2017-01-30 18:05:43 -0800
committerAbhijit Kulkarni <kabhijit@codeaurora.org>2017-01-31 15:12:26 -0800
commitf04daa236be0768fd580ec1a6979b74f2744fe7c (patch)
tree746d0e56ad31d6121c6e633c4511564906e2f888
parentea4719da1fbdb56ef368b725496c3acdb4dde51c (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.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c1
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_layer.c7
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c20
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pp.c14
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);