Loading drivers/video/msm/mdss/mdss_mdp.h +1 −0 Original line number Diff line number Diff line Loading @@ -620,6 +620,7 @@ int mdss_mdp_mixer_pipe_update(struct mdss_mdp_pipe *pipe, struct mdss_mdp_mixer *mixer, int params_changed); int mdss_mdp_mixer_pipe_unstage(struct mdss_mdp_pipe *pipe, struct mdss_mdp_mixer *mixer); void mdss_mdp_mixer_unstage_all(struct mdss_mdp_mixer *mixer); int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg); int mdss_mdp_display_wait4comp(struct mdss_mdp_ctl *ctl); int mdss_mdp_display_wait4pingpong(struct mdss_mdp_ctl *ctl); Loading drivers/video/msm/mdss/mdss_mdp_ctl.c +27 −5 Original line number Diff line number Diff line Loading @@ -2398,6 +2398,33 @@ int mdss_mdp_mixer_pipe_update(struct mdss_mdp_pipe *pipe, return 0; } /** * mdss_mdp_mixer_unstage_all() - Unstage all pipes from mixer * @mixer: Mixer from which to unstage all pipes * * Unstage any pipes that are currently attached to mixer. * * NOTE: this will not update the pipe structure, and thus a full * deinitialization or reconfiguration of all pipes is expected after this call. */ void mdss_mdp_mixer_unstage_all(struct mdss_mdp_mixer *mixer) { struct mdss_mdp_pipe *tmp; int i; if (!mixer) return; for (i = 0; i < MAX_PIPES_PER_LM; i++) { tmp = mixer->stage_pipe[i]; if (tmp) { mixer->stage_pipe[i] = NULL; mixer->params_changed++; tmp->params_changed++; } } } int mdss_mdp_mixer_pipe_unstage(struct mdss_mdp_pipe *pipe, struct mdss_mdp_mixer *mixer) { Loading @@ -2418,11 +2445,6 @@ int mdss_mdp_mixer_pipe_unstage(struct mdss_mdp_pipe *pipe, mixer->params_changed++; mixer->stage_pipe[index] = NULL; if (mixer->is_right_mixer) pipe->mixer_right = NULL; else pipe->mixer_left = NULL; } return 0; Loading drivers/video/msm/mdss/mdss_mdp_overlay.c +103 −58 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ static int mdss_mdp_overlay_free_fb_pipe(struct msm_fb_data_type *mfd); static int mdss_mdp_overlay_fb_parse_dt(struct msm_fb_data_type *mfd); static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd); static int mdss_mdp_overlay_splash_parse_dt(struct msm_fb_data_type *mfd); static void __overlay_kickoff_requeue(struct msm_fb_data_type *mfd); static inline bool is_ov_right_blend(struct mdp_rect *left_blend, struct mdp_rect *right_blend, u32 left_lm_w) Loading Loading @@ -613,6 +614,10 @@ static int mdss_mdp_overlay_pipe_setup(struct msm_fb_data_type *mfd, pipe->is_right_blend = true; } } else if (pipe->is_right_blend) { /* * pipe used to be right blend 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; Loading Loading @@ -660,9 +665,11 @@ static int mdss_mdp_overlay_pipe_setup(struct msm_fb_data_type *mfd, pipe->src_split_req = true; } } else { if (pipe->src_split_req) if (pipe->src_split_req) { mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_right); pipe->mixer_right = NULL; } pipe->src_split_req = false; } } Loading Loading @@ -943,6 +950,8 @@ static void mdss_mdp_overlay_cleanup(struct msm_fb_data_type *mfd) { struct mdss_mdp_pipe *pipe, *tmp; struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); bool recovery_mode = false; LIST_HEAD(destroy_pipes); mutex_lock(&mfd->lock); Loading @@ -951,7 +960,27 @@ static void mdss_mdp_overlay_cleanup(struct msm_fb_data_type *mfd) list_move(&pipe->cleanup_list, &destroy_pipes); /* make sure pipe fetch has been halted before freeing buffer */ mdss_mdp_pipe_fetch_halt(pipe); if (mdss_mdp_pipe_fetch_halt(pipe)) { /* * if pipe is not able to halt. Enter recovery mode, * by un-staging any pipes that are attached to mixer * so that any freed pipes that are not able to halt * can be staged in solid fill mode and be reset * with next vsync */ if (!recovery_mode) { recovery_mode = true; mdss_mdp_mixer_unstage_all(ctl->mixer_left); mdss_mdp_mixer_unstage_all(ctl->mixer_right); } pipe->params_changed++; mdss_mdp_pipe_queue_data(pipe, NULL); } } if (recovery_mode) { pr_warn("performing recovery sequence for fb%d\n", mfd->index); __overlay_kickoff_requeue(mfd); } __mdss_mdp_overlay_free_list_purge(mfd); Loading Loading @@ -1144,61 +1173,13 @@ static void mdss_mdp_overlay_update_pm(struct mdss_overlay_private *mdp5_data) activate_event_timer(mdp5_data->cpu_pm_hdl, wakeup_time); } int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, struct mdp_display_commit *data) static int __overlay_queue_pipes(struct msm_fb_data_type *mfd) { struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); struct mdss_mdp_pipe *pipe; struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); struct mdss_mdp_ctl *tmp; int ret = 0; int sd_in_pipe = 0; if (!ctl) { pr_warn("kickoff on fb=%d without a ctl attched\n", mfd->index); return ret; } if (ctl->shared_lock) mutex_lock(ctl->shared_lock); mutex_lock(&mdp5_data->ov_lock); mutex_lock(&mfd->lock); /* * check if there is a secure display session */ list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) { if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) { sd_in_pipe = 1; pr_debug("Secure pipe: %u : %08X\n", pipe->num, pipe->flags); } } /* * If there is no secure display session and sd_enabled, disable the * secure display session */ if (!sd_in_pipe && mdp5_data->sd_enabled) { if (0 == mdss_mdp_overlay_sd_ctrl(mfd, 0)) mdp5_data->sd_enabled = 0; } mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_BEGIN); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false); if (data) mdss_mdp_set_roi(ctl, data); /* * Setup pipe in solid fill before unstaging, * to ensure no fetches are happening after dettach or reattach. */ list_for_each_entry(pipe, &mdp5_data->pipes_cleanup, cleanup_list) { mdss_mdp_pipe_queue_data(pipe, NULL); mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_left); mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_right); } list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) { struct mdss_mdp_data *buf; Loading Loading @@ -1229,17 +1210,13 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, if (ret) { pr_err("can't reset DMA pipe ret=%d ctl=%d\n", ret, ctl->num); mutex_unlock(&mfd->lock); goto commit_fail; return ret; } tmp = mdss_mdp_ctl_mixer_switch(ctl, MDSS_MDP_WB_CTL_TYPE_LINE); if (!tmp) { mutex_unlock(&mfd->lock); ret = -EINVAL; goto commit_fail; } if (!tmp) return -EINVAL; pipe->mixer_left = mdss_mdp_mixer_get(tmp, MDSS_MDP_MIXER_MUX_DEFAULT); } Loading Loading @@ -1268,6 +1245,74 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, } } return 0; } static void __overlay_kickoff_requeue(struct msm_fb_data_type *mfd) { struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); mdss_mdp_display_commit(ctl, NULL); mdss_mdp_display_wait4comp(ctl); __overlay_queue_pipes(mfd); mdss_mdp_display_commit(ctl, NULL); mdss_mdp_display_wait4comp(ctl); } 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; struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); int ret = 0; int sd_in_pipe = 0; if (ctl->shared_lock) mutex_lock(ctl->shared_lock); mutex_lock(&mdp5_data->ov_lock); mutex_lock(&mfd->lock); /* * check if there is a secure display session */ list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) { if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) { sd_in_pipe = 1; pr_debug("Secure pipe: %u : %08X\n", pipe->num, pipe->flags); } } /* * If there is no secure display session and sd_enabled, disable the * secure display session */ if (!sd_in_pipe && mdp5_data->sd_enabled) { if (0 == mdss_mdp_overlay_sd_ctrl(mfd, 0)) mdp5_data->sd_enabled = 0; } mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_BEGIN); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false); if (data) mdss_mdp_set_roi(ctl, data); /* * Setup pipe in solid fill before unstaging, * to ensure no fetches are happening after dettach or reattach. */ list_for_each_entry(pipe, &mdp5_data->pipes_cleanup, cleanup_list) { mdss_mdp_pipe_queue_data(pipe, NULL); mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_left); mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_right); } ret = __overlay_queue_pipes(mfd); if (mfd->panel.type == WRITEBACK_PANEL) ret = mdss_mdp_wb_kickoff(mfd); else Loading Loading
drivers/video/msm/mdss/mdss_mdp.h +1 −0 Original line number Diff line number Diff line Loading @@ -620,6 +620,7 @@ int mdss_mdp_mixer_pipe_update(struct mdss_mdp_pipe *pipe, struct mdss_mdp_mixer *mixer, int params_changed); int mdss_mdp_mixer_pipe_unstage(struct mdss_mdp_pipe *pipe, struct mdss_mdp_mixer *mixer); void mdss_mdp_mixer_unstage_all(struct mdss_mdp_mixer *mixer); int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg); int mdss_mdp_display_wait4comp(struct mdss_mdp_ctl *ctl); int mdss_mdp_display_wait4pingpong(struct mdss_mdp_ctl *ctl); Loading
drivers/video/msm/mdss/mdss_mdp_ctl.c +27 −5 Original line number Diff line number Diff line Loading @@ -2398,6 +2398,33 @@ int mdss_mdp_mixer_pipe_update(struct mdss_mdp_pipe *pipe, return 0; } /** * mdss_mdp_mixer_unstage_all() - Unstage all pipes from mixer * @mixer: Mixer from which to unstage all pipes * * Unstage any pipes that are currently attached to mixer. * * NOTE: this will not update the pipe structure, and thus a full * deinitialization or reconfiguration of all pipes is expected after this call. */ void mdss_mdp_mixer_unstage_all(struct mdss_mdp_mixer *mixer) { struct mdss_mdp_pipe *tmp; int i; if (!mixer) return; for (i = 0; i < MAX_PIPES_PER_LM; i++) { tmp = mixer->stage_pipe[i]; if (tmp) { mixer->stage_pipe[i] = NULL; mixer->params_changed++; tmp->params_changed++; } } } int mdss_mdp_mixer_pipe_unstage(struct mdss_mdp_pipe *pipe, struct mdss_mdp_mixer *mixer) { Loading @@ -2418,11 +2445,6 @@ int mdss_mdp_mixer_pipe_unstage(struct mdss_mdp_pipe *pipe, mixer->params_changed++; mixer->stage_pipe[index] = NULL; if (mixer->is_right_mixer) pipe->mixer_right = NULL; else pipe->mixer_left = NULL; } return 0; Loading
drivers/video/msm/mdss/mdss_mdp_overlay.c +103 −58 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ static int mdss_mdp_overlay_free_fb_pipe(struct msm_fb_data_type *mfd); static int mdss_mdp_overlay_fb_parse_dt(struct msm_fb_data_type *mfd); static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd); static int mdss_mdp_overlay_splash_parse_dt(struct msm_fb_data_type *mfd); static void __overlay_kickoff_requeue(struct msm_fb_data_type *mfd); static inline bool is_ov_right_blend(struct mdp_rect *left_blend, struct mdp_rect *right_blend, u32 left_lm_w) Loading Loading @@ -613,6 +614,10 @@ static int mdss_mdp_overlay_pipe_setup(struct msm_fb_data_type *mfd, pipe->is_right_blend = true; } } else if (pipe->is_right_blend) { /* * pipe used to be right blend 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; Loading Loading @@ -660,9 +665,11 @@ static int mdss_mdp_overlay_pipe_setup(struct msm_fb_data_type *mfd, pipe->src_split_req = true; } } else { if (pipe->src_split_req) if (pipe->src_split_req) { mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_right); pipe->mixer_right = NULL; } pipe->src_split_req = false; } } Loading Loading @@ -943,6 +950,8 @@ static void mdss_mdp_overlay_cleanup(struct msm_fb_data_type *mfd) { struct mdss_mdp_pipe *pipe, *tmp; struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); bool recovery_mode = false; LIST_HEAD(destroy_pipes); mutex_lock(&mfd->lock); Loading @@ -951,7 +960,27 @@ static void mdss_mdp_overlay_cleanup(struct msm_fb_data_type *mfd) list_move(&pipe->cleanup_list, &destroy_pipes); /* make sure pipe fetch has been halted before freeing buffer */ mdss_mdp_pipe_fetch_halt(pipe); if (mdss_mdp_pipe_fetch_halt(pipe)) { /* * if pipe is not able to halt. Enter recovery mode, * by un-staging any pipes that are attached to mixer * so that any freed pipes that are not able to halt * can be staged in solid fill mode and be reset * with next vsync */ if (!recovery_mode) { recovery_mode = true; mdss_mdp_mixer_unstage_all(ctl->mixer_left); mdss_mdp_mixer_unstage_all(ctl->mixer_right); } pipe->params_changed++; mdss_mdp_pipe_queue_data(pipe, NULL); } } if (recovery_mode) { pr_warn("performing recovery sequence for fb%d\n", mfd->index); __overlay_kickoff_requeue(mfd); } __mdss_mdp_overlay_free_list_purge(mfd); Loading Loading @@ -1144,61 +1173,13 @@ static void mdss_mdp_overlay_update_pm(struct mdss_overlay_private *mdp5_data) activate_event_timer(mdp5_data->cpu_pm_hdl, wakeup_time); } int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, struct mdp_display_commit *data) static int __overlay_queue_pipes(struct msm_fb_data_type *mfd) { struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); struct mdss_mdp_pipe *pipe; struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); struct mdss_mdp_ctl *tmp; int ret = 0; int sd_in_pipe = 0; if (!ctl) { pr_warn("kickoff on fb=%d without a ctl attched\n", mfd->index); return ret; } if (ctl->shared_lock) mutex_lock(ctl->shared_lock); mutex_lock(&mdp5_data->ov_lock); mutex_lock(&mfd->lock); /* * check if there is a secure display session */ list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) { if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) { sd_in_pipe = 1; pr_debug("Secure pipe: %u : %08X\n", pipe->num, pipe->flags); } } /* * If there is no secure display session and sd_enabled, disable the * secure display session */ if (!sd_in_pipe && mdp5_data->sd_enabled) { if (0 == mdss_mdp_overlay_sd_ctrl(mfd, 0)) mdp5_data->sd_enabled = 0; } mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_BEGIN); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false); if (data) mdss_mdp_set_roi(ctl, data); /* * Setup pipe in solid fill before unstaging, * to ensure no fetches are happening after dettach or reattach. */ list_for_each_entry(pipe, &mdp5_data->pipes_cleanup, cleanup_list) { mdss_mdp_pipe_queue_data(pipe, NULL); mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_left); mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_right); } list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) { struct mdss_mdp_data *buf; Loading Loading @@ -1229,17 +1210,13 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, if (ret) { pr_err("can't reset DMA pipe ret=%d ctl=%d\n", ret, ctl->num); mutex_unlock(&mfd->lock); goto commit_fail; return ret; } tmp = mdss_mdp_ctl_mixer_switch(ctl, MDSS_MDP_WB_CTL_TYPE_LINE); if (!tmp) { mutex_unlock(&mfd->lock); ret = -EINVAL; goto commit_fail; } if (!tmp) return -EINVAL; pipe->mixer_left = mdss_mdp_mixer_get(tmp, MDSS_MDP_MIXER_MUX_DEFAULT); } Loading Loading @@ -1268,6 +1245,74 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, } } return 0; } static void __overlay_kickoff_requeue(struct msm_fb_data_type *mfd) { struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); mdss_mdp_display_commit(ctl, NULL); mdss_mdp_display_wait4comp(ctl); __overlay_queue_pipes(mfd); mdss_mdp_display_commit(ctl, NULL); mdss_mdp_display_wait4comp(ctl); } 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; struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); int ret = 0; int sd_in_pipe = 0; if (ctl->shared_lock) mutex_lock(ctl->shared_lock); mutex_lock(&mdp5_data->ov_lock); mutex_lock(&mfd->lock); /* * check if there is a secure display session */ list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) { if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) { sd_in_pipe = 1; pr_debug("Secure pipe: %u : %08X\n", pipe->num, pipe->flags); } } /* * If there is no secure display session and sd_enabled, disable the * secure display session */ if (!sd_in_pipe && mdp5_data->sd_enabled) { if (0 == mdss_mdp_overlay_sd_ctrl(mfd, 0)) mdp5_data->sd_enabled = 0; } mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_BEGIN); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false); if (data) mdss_mdp_set_roi(ctl, data); /* * Setup pipe in solid fill before unstaging, * to ensure no fetches are happening after dettach or reattach. */ list_for_each_entry(pipe, &mdp5_data->pipes_cleanup, cleanup_list) { mdss_mdp_pipe_queue_data(pipe, NULL); mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_left); mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_right); } ret = __overlay_queue_pipes(mfd); if (mfd->panel.type == WRITEBACK_PANEL) ret = mdss_mdp_wb_kickoff(mfd); else Loading