Loading drivers/video/msm/mdss/mdss_fb.c +86 −30 Original line number Diff line number Diff line Loading @@ -444,17 +444,27 @@ static int mdss_fb_probe(struct platform_device *pdev) mfd->mdp_sync_pt_data.timeline = sw_sync_timeline_create(timeline_name); if (mfd->mdp_sync_pt_data.timeline == NULL) { pr_err("%s: cannot create time line", __func__); pr_err("cannot create release fence time line\n"); return -ENOMEM; } mfd->mdp_sync_pt_data.notifier.notifier_call = __mdss_fb_sync_buf_done_callback; } if ((mfd->panel.type == WRITEBACK_PANEL) || (mfd->panel.type == MIPI_CMD_PANEL)) switch (mfd->panel.type) { case WRITEBACK_PANEL: mfd->mdp_sync_pt_data.threshold = 1; else mfd->mdp_sync_pt_data.retire_threshold = 0; break; case MIPI_CMD_PANEL: mfd->mdp_sync_pt_data.threshold = 1; mfd->mdp_sync_pt_data.retire_threshold = 1; break; default: mfd->mdp_sync_pt_data.threshold = 2; mfd->mdp_sync_pt_data.retire_threshold = 0; break; } if (mfd->splash_logo_enabled) { mfd->splash_thread = kthread_run(mdss_fb_splash_thread, mfd, Loading Loading @@ -2041,42 +2051,37 @@ static int mdss_fb_set_lut(struct fb_info *info, void __user *p) } /** * mdss_fb_sync_get_rel_fence() - get release fence from sync pt timeline * @sync_pt_data: Sync pt structure holding timeline and fence info. * mdss_fb_sync_get_fence() - get fence from timeline * @timeline: Timeline to create the fence on * @fence_name: Name of the fence that will be created for debugging * @val: Timeline value at which the fence will be signaled * * Function returns a release fence on the timeline associated with the * sync pt struct given and it's associated information. The release fence * created can be used to signal when buffers provided will be released. * Function returns a fence on the timeline given with the name provided. * The fence created will be signaled when the timeline is advanced. */ static struct sync_fence *__mdss_fb_sync_get_rel_fence( struct msm_sync_pt_data *sync_pt_data) struct sync_fence *mdss_fb_sync_get_fence(struct sw_sync_timeline *timeline, const char *fence_name, int val) { struct sync_pt *rel_sync_pt; struct sync_fence *rel_fence; int val; val = sync_pt_data->timeline_value + sync_pt_data->threshold + atomic_read(&sync_pt_data->commit_cnt); struct sync_pt *sync_pt; struct sync_fence *fence; pr_debug("%s: buf sync rel fence timeline=%d\n", sync_pt_data->fence_name, val); pr_debug("%s: buf sync fence timeline=%d\n", fence_name, val); rel_sync_pt = sw_sync_pt_create(sync_pt_data->timeline, val); if (rel_sync_pt == NULL) { pr_err("%s: cannot create sync point\n", sync_pt_data->fence_name); sync_pt = sw_sync_pt_create(timeline, val); if (sync_pt == NULL) { pr_err("%s: cannot create sync point\n", fence_name); return NULL; } /* create fence */ rel_fence = sync_fence_create(sync_pt_data->fence_name, rel_sync_pt); if (rel_fence == NULL) { sync_pt_free(rel_sync_pt); pr_err("%s: cannot create fence\n", sync_pt_data->fence_name); fence = sync_fence_create(fence_name, sync_pt); if (fence == NULL) { sync_pt_free(sync_pt); pr_err("%s: cannot create fence\n", fence_name); return NULL; } return rel_fence; return fence; } static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data, Loading @@ -2084,8 +2089,10 @@ static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data, { int i, ret = 0; int acq_fen_fd[MDP_MAX_FENCE_FD]; struct sync_fence *fence, *rel_fence; struct sync_fence *fence, *rel_fence, *retire_fence; int rel_fen_fd; int retire_fen_fd; int val; if ((buf_sync->acq_fen_fd_cnt > MDP_MAX_FENCE_FD) || (sync_pt_data->timeline == NULL)) Loading Loading @@ -2120,7 +2127,12 @@ static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data, if (ret) goto buf_sync_err_1; rel_fence = __mdss_fb_sync_get_rel_fence(sync_pt_data); val = sync_pt_data->timeline_value + sync_pt_data->threshold + atomic_read(&sync_pt_data->commit_cnt); /* Set release fence */ rel_fence = mdss_fb_sync_get_fence(sync_pt_data->timeline, sync_pt_data->fence_name, val); if (IS_ERR_OR_NULL(rel_fence)) { pr_err("%s: unable to retrieve release fence\n", sync_pt_data->fence_name); Loading @@ -2144,6 +2156,50 @@ static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data, pr_err("%s: copy_to_user failed\n", sync_pt_data->fence_name); goto buf_sync_err_3; } if (!(buf_sync->flags & MDP_BUF_SYNC_FLAG_RETIRE_FENCE)) goto skip_retire_fence; if (sync_pt_data->get_retire_fence) retire_fence = sync_pt_data->get_retire_fence(sync_pt_data); else retire_fence = NULL; if (IS_ERR_OR_NULL(retire_fence)) { val += sync_pt_data->retire_threshold; retire_fence = mdss_fb_sync_get_fence( sync_pt_data->timeline, "mdp-retire", val); } if (IS_ERR_OR_NULL(retire_fence)) { pr_err("%s: unable to retrieve retire fence\n", sync_pt_data->fence_name); ret = retire_fence ? PTR_ERR(rel_fence) : -ENOMEM; goto buf_sync_err_3; } retire_fen_fd = get_unused_fd_flags(0); if (retire_fen_fd < 0) { pr_err("%s: get_unused_fd_flags failed for retire fence\n", sync_pt_data->fence_name); ret = -EIO; sync_fence_put(retire_fence); goto buf_sync_err_3; } sync_fence_install(retire_fence, retire_fen_fd); ret = copy_to_user(buf_sync->retire_fen_fd, &retire_fen_fd, sizeof(int)); if (ret) { pr_err("%s: copy_to_user failed for retire fence\n", sync_pt_data->fence_name); put_unused_fd(retire_fen_fd); sync_fence_put(retire_fence); goto buf_sync_err_3; } skip_retire_fence: mutex_unlock(&sync_pt_data->sync_mutex); if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT) Loading drivers/video/msm/mdss/mdss_fb.h +6 −1 Original line number Diff line number Diff line Loading @@ -98,13 +98,16 @@ struct msm_sync_pt_data { struct sw_sync_timeline *timeline; int timeline_value; u32 threshold; u32 retire_threshold; atomic_t commit_cnt; bool flushed; bool async_wait_fences; struct mutex sync_mutex; struct notifier_block notifier; struct sync_fence *(*get_retire_fence) (struct msm_sync_pt_data *sync_pt_data); }; struct msm_fb_data_type; Loading Loading @@ -248,6 +251,8 @@ void mdss_fb_set_backlight(struct msm_fb_data_type *mfd, u32 bkl_lvl); void mdss_fb_update_backlight(struct msm_fb_data_type *mfd); int mdss_fb_wait_for_fence(struct msm_sync_pt_data *sync_pt_data); void mdss_fb_signal_timeline(struct msm_sync_pt_data *sync_pt_data); struct sync_fence *mdss_fb_sync_get_fence(struct sw_sync_timeline *timeline, const char *fence_name, int val); int mdss_fb_register_mdp_instance(struct msm_mdp_interface *mdp); int mdss_fb_dcm(struct msm_fb_data_type *mfd, int req_state); #endif /* MDSS_FB_H */ drivers/video/msm/mdss/mdss_mdp.h +5 −0 Original line number Diff line number Diff line Loading @@ -432,6 +432,11 @@ struct mdss_overlay_private { u32 splash_mem_addr; u32 splash_mem_size; u32 sd_enabled; struct sw_sync_timeline *vsync_timeline; struct mdss_mdp_vsync_handler vsync_retire_handler; struct work_struct retire_work; int retire_cnt; }; /** Loading drivers/video/msm/mdss/mdss_mdp_overlay.c +108 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <linux/delay.h> #include <linux/msm_mdp.h> #include <linux/memblock.h> #include <linux/sw_sync.h> #include <linux/msm_iommu_domains.h> #include <mach/event_timer.h> Loading Loading @@ -2775,6 +2776,107 @@ static int mdss_mdp_overlay_splash_image(struct msm_fb_data_type *mfd, return rc; } static void __vsync_retire_handle_vsync(struct mdss_mdp_ctl *ctl, ktime_t t) { struct msm_fb_data_type *mfd = ctl->mfd; struct mdss_overlay_private *mdp5_data; if (!mfd || !mfd->mdp.private1) { pr_warn("Invalid handle for vsync\n"); return; } mdp5_data = mfd_to_mdp5_data(mfd); schedule_work(&mdp5_data->retire_work); } static void __vsync_retire_work_handler(struct work_struct *work) { struct mdss_overlay_private *mdp5_data = container_of(work, typeof(*mdp5_data), retire_work); struct msm_sync_pt_data *sync_pt_data; if (!mdp5_data->ctl || !mdp5_data->ctl->mfd) return; if (!mdp5_data->ctl->remove_vsync_handler) return; sync_pt_data = &mdp5_data->ctl->mfd->mdp_sync_pt_data; mutex_lock(&sync_pt_data->sync_mutex); if (mdp5_data->retire_cnt > 0) { sw_sync_timeline_inc(mdp5_data->vsync_timeline, 1); mdp5_data->retire_cnt--; if (mdp5_data->retire_cnt == 0) { mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false); mdp5_data->ctl->remove_vsync_handler(mdp5_data->ctl, &mdp5_data->vsync_retire_handler); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false); } } mutex_unlock(&sync_pt_data->sync_mutex); } static struct sync_fence * __vsync_retire_get_fence(struct msm_sync_pt_data *sync_pt_data) { struct msm_fb_data_type *mfd; struct mdss_overlay_private *mdp5_data; struct mdss_mdp_ctl *ctl; int rc, value; mfd = container_of(sync_pt_data, typeof(*mfd), mdp_sync_pt_data); mdp5_data = mfd_to_mdp5_data(mfd); if (!mdp5_data || !mdp5_data->ctl) return ERR_PTR(-ENODEV); ctl = mdp5_data->ctl; if (!ctl->add_vsync_handler) return ERR_PTR(-EOPNOTSUPP); if (!ctl->power_on) { pr_debug("fb%d vsync pending first update\n", mfd->index); return ERR_PTR(-EPERM); } if (mdp5_data->retire_cnt == 0) { mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false); rc = ctl->add_vsync_handler(ctl, &mdp5_data->vsync_retire_handler); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false); if (IS_ERR_VALUE(rc)) return ERR_PTR(rc); } value = mdp5_data->vsync_timeline->value + 1 + mdp5_data->retire_cnt; mdp5_data->retire_cnt++; return mdss_fb_sync_get_fence(mdp5_data->vsync_timeline, "mdp-retire", value); } static int __vsync_retire_setup(struct msm_fb_data_type *mfd) { struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); char name[24]; snprintf(name, sizeof(name), "mdss_fb%d_retire", mfd->index); mdp5_data->vsync_timeline = sw_sync_timeline_create(name); if (mdp5_data->vsync_timeline == NULL) { pr_err("cannot vsync create time line"); return -ENOMEM; } mfd->mdp_sync_pt_data.get_retire_fence = __vsync_retire_get_fence; mdp5_data->vsync_retire_handler.vsync_handler = __vsync_retire_handle_vsync; mdp5_data->vsync_retire_handler.cmd_post_flush = false; INIT_WORK(&mdp5_data->retire_work, __vsync_retire_work_handler); return 0; } int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd) { struct device *dev = mfd->fbi->dev; Loading Loading @@ -2846,6 +2948,12 @@ int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd) pr_err("Error dfps sysfs creation ret=%d\n", rc); goto init_fail; } } else if (mfd->panel_info->type == MIPI_CMD_PANEL) { rc = __vsync_retire_setup(mfd); if (IS_ERR_VALUE(rc)) { pr_err("unable to create vsync timeline\n"); goto init_fail; } } mfd->mdp_sync_pt_data.async_wait_fences = true; Loading include/uapi/linux/msm_mdp.h +2 −8 Original line number Diff line number Diff line Loading @@ -994,6 +994,7 @@ struct msmfb_metadata { #define MDP_MAX_FENCE_FD 32 #define MDP_BUF_SYNC_FLAG_WAIT 1 #define MDP_BUF_SYNC_FLAG_RETIRE_FENCE 0x10 struct mdp_buf_sync { uint32_t flags; Loading @@ -1001,6 +1002,7 @@ struct mdp_buf_sync { uint32_t session_id; int *acq_fen_fd; int *rel_fen_fd; int *retire_fen_fd; }; struct mdp_async_blit_req_list { Loading @@ -1010,19 +1012,11 @@ struct mdp_async_blit_req_list { }; #define MDP_DISPLAY_COMMIT_OVERLAY 1 struct mdp_buf_fence { uint32_t flags; uint32_t acq_fen_fd_cnt; int acq_fen_fd[MDP_MAX_FENCE_FD]; int rel_fen_fd[MDP_MAX_FENCE_FD]; }; struct mdp_display_commit { uint32_t flags; uint32_t wait_for_finish; struct fb_var_screeninfo var; struct mdp_buf_fence buf_fence; struct mdp_rect roi; }; Loading Loading
drivers/video/msm/mdss/mdss_fb.c +86 −30 Original line number Diff line number Diff line Loading @@ -444,17 +444,27 @@ static int mdss_fb_probe(struct platform_device *pdev) mfd->mdp_sync_pt_data.timeline = sw_sync_timeline_create(timeline_name); if (mfd->mdp_sync_pt_data.timeline == NULL) { pr_err("%s: cannot create time line", __func__); pr_err("cannot create release fence time line\n"); return -ENOMEM; } mfd->mdp_sync_pt_data.notifier.notifier_call = __mdss_fb_sync_buf_done_callback; } if ((mfd->panel.type == WRITEBACK_PANEL) || (mfd->panel.type == MIPI_CMD_PANEL)) switch (mfd->panel.type) { case WRITEBACK_PANEL: mfd->mdp_sync_pt_data.threshold = 1; else mfd->mdp_sync_pt_data.retire_threshold = 0; break; case MIPI_CMD_PANEL: mfd->mdp_sync_pt_data.threshold = 1; mfd->mdp_sync_pt_data.retire_threshold = 1; break; default: mfd->mdp_sync_pt_data.threshold = 2; mfd->mdp_sync_pt_data.retire_threshold = 0; break; } if (mfd->splash_logo_enabled) { mfd->splash_thread = kthread_run(mdss_fb_splash_thread, mfd, Loading Loading @@ -2041,42 +2051,37 @@ static int mdss_fb_set_lut(struct fb_info *info, void __user *p) } /** * mdss_fb_sync_get_rel_fence() - get release fence from sync pt timeline * @sync_pt_data: Sync pt structure holding timeline and fence info. * mdss_fb_sync_get_fence() - get fence from timeline * @timeline: Timeline to create the fence on * @fence_name: Name of the fence that will be created for debugging * @val: Timeline value at which the fence will be signaled * * Function returns a release fence on the timeline associated with the * sync pt struct given and it's associated information. The release fence * created can be used to signal when buffers provided will be released. * Function returns a fence on the timeline given with the name provided. * The fence created will be signaled when the timeline is advanced. */ static struct sync_fence *__mdss_fb_sync_get_rel_fence( struct msm_sync_pt_data *sync_pt_data) struct sync_fence *mdss_fb_sync_get_fence(struct sw_sync_timeline *timeline, const char *fence_name, int val) { struct sync_pt *rel_sync_pt; struct sync_fence *rel_fence; int val; val = sync_pt_data->timeline_value + sync_pt_data->threshold + atomic_read(&sync_pt_data->commit_cnt); struct sync_pt *sync_pt; struct sync_fence *fence; pr_debug("%s: buf sync rel fence timeline=%d\n", sync_pt_data->fence_name, val); pr_debug("%s: buf sync fence timeline=%d\n", fence_name, val); rel_sync_pt = sw_sync_pt_create(sync_pt_data->timeline, val); if (rel_sync_pt == NULL) { pr_err("%s: cannot create sync point\n", sync_pt_data->fence_name); sync_pt = sw_sync_pt_create(timeline, val); if (sync_pt == NULL) { pr_err("%s: cannot create sync point\n", fence_name); return NULL; } /* create fence */ rel_fence = sync_fence_create(sync_pt_data->fence_name, rel_sync_pt); if (rel_fence == NULL) { sync_pt_free(rel_sync_pt); pr_err("%s: cannot create fence\n", sync_pt_data->fence_name); fence = sync_fence_create(fence_name, sync_pt); if (fence == NULL) { sync_pt_free(sync_pt); pr_err("%s: cannot create fence\n", fence_name); return NULL; } return rel_fence; return fence; } static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data, Loading @@ -2084,8 +2089,10 @@ static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data, { int i, ret = 0; int acq_fen_fd[MDP_MAX_FENCE_FD]; struct sync_fence *fence, *rel_fence; struct sync_fence *fence, *rel_fence, *retire_fence; int rel_fen_fd; int retire_fen_fd; int val; if ((buf_sync->acq_fen_fd_cnt > MDP_MAX_FENCE_FD) || (sync_pt_data->timeline == NULL)) Loading Loading @@ -2120,7 +2127,12 @@ static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data, if (ret) goto buf_sync_err_1; rel_fence = __mdss_fb_sync_get_rel_fence(sync_pt_data); val = sync_pt_data->timeline_value + sync_pt_data->threshold + atomic_read(&sync_pt_data->commit_cnt); /* Set release fence */ rel_fence = mdss_fb_sync_get_fence(sync_pt_data->timeline, sync_pt_data->fence_name, val); if (IS_ERR_OR_NULL(rel_fence)) { pr_err("%s: unable to retrieve release fence\n", sync_pt_data->fence_name); Loading @@ -2144,6 +2156,50 @@ static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data, pr_err("%s: copy_to_user failed\n", sync_pt_data->fence_name); goto buf_sync_err_3; } if (!(buf_sync->flags & MDP_BUF_SYNC_FLAG_RETIRE_FENCE)) goto skip_retire_fence; if (sync_pt_data->get_retire_fence) retire_fence = sync_pt_data->get_retire_fence(sync_pt_data); else retire_fence = NULL; if (IS_ERR_OR_NULL(retire_fence)) { val += sync_pt_data->retire_threshold; retire_fence = mdss_fb_sync_get_fence( sync_pt_data->timeline, "mdp-retire", val); } if (IS_ERR_OR_NULL(retire_fence)) { pr_err("%s: unable to retrieve retire fence\n", sync_pt_data->fence_name); ret = retire_fence ? PTR_ERR(rel_fence) : -ENOMEM; goto buf_sync_err_3; } retire_fen_fd = get_unused_fd_flags(0); if (retire_fen_fd < 0) { pr_err("%s: get_unused_fd_flags failed for retire fence\n", sync_pt_data->fence_name); ret = -EIO; sync_fence_put(retire_fence); goto buf_sync_err_3; } sync_fence_install(retire_fence, retire_fen_fd); ret = copy_to_user(buf_sync->retire_fen_fd, &retire_fen_fd, sizeof(int)); if (ret) { pr_err("%s: copy_to_user failed for retire fence\n", sync_pt_data->fence_name); put_unused_fd(retire_fen_fd); sync_fence_put(retire_fence); goto buf_sync_err_3; } skip_retire_fence: mutex_unlock(&sync_pt_data->sync_mutex); if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT) Loading
drivers/video/msm/mdss/mdss_fb.h +6 −1 Original line number Diff line number Diff line Loading @@ -98,13 +98,16 @@ struct msm_sync_pt_data { struct sw_sync_timeline *timeline; int timeline_value; u32 threshold; u32 retire_threshold; atomic_t commit_cnt; bool flushed; bool async_wait_fences; struct mutex sync_mutex; struct notifier_block notifier; struct sync_fence *(*get_retire_fence) (struct msm_sync_pt_data *sync_pt_data); }; struct msm_fb_data_type; Loading Loading @@ -248,6 +251,8 @@ void mdss_fb_set_backlight(struct msm_fb_data_type *mfd, u32 bkl_lvl); void mdss_fb_update_backlight(struct msm_fb_data_type *mfd); int mdss_fb_wait_for_fence(struct msm_sync_pt_data *sync_pt_data); void mdss_fb_signal_timeline(struct msm_sync_pt_data *sync_pt_data); struct sync_fence *mdss_fb_sync_get_fence(struct sw_sync_timeline *timeline, const char *fence_name, int val); int mdss_fb_register_mdp_instance(struct msm_mdp_interface *mdp); int mdss_fb_dcm(struct msm_fb_data_type *mfd, int req_state); #endif /* MDSS_FB_H */
drivers/video/msm/mdss/mdss_mdp.h +5 −0 Original line number Diff line number Diff line Loading @@ -432,6 +432,11 @@ struct mdss_overlay_private { u32 splash_mem_addr; u32 splash_mem_size; u32 sd_enabled; struct sw_sync_timeline *vsync_timeline; struct mdss_mdp_vsync_handler vsync_retire_handler; struct work_struct retire_work; int retire_cnt; }; /** Loading
drivers/video/msm/mdss/mdss_mdp_overlay.c +108 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <linux/delay.h> #include <linux/msm_mdp.h> #include <linux/memblock.h> #include <linux/sw_sync.h> #include <linux/msm_iommu_domains.h> #include <mach/event_timer.h> Loading Loading @@ -2775,6 +2776,107 @@ static int mdss_mdp_overlay_splash_image(struct msm_fb_data_type *mfd, return rc; } static void __vsync_retire_handle_vsync(struct mdss_mdp_ctl *ctl, ktime_t t) { struct msm_fb_data_type *mfd = ctl->mfd; struct mdss_overlay_private *mdp5_data; if (!mfd || !mfd->mdp.private1) { pr_warn("Invalid handle for vsync\n"); return; } mdp5_data = mfd_to_mdp5_data(mfd); schedule_work(&mdp5_data->retire_work); } static void __vsync_retire_work_handler(struct work_struct *work) { struct mdss_overlay_private *mdp5_data = container_of(work, typeof(*mdp5_data), retire_work); struct msm_sync_pt_data *sync_pt_data; if (!mdp5_data->ctl || !mdp5_data->ctl->mfd) return; if (!mdp5_data->ctl->remove_vsync_handler) return; sync_pt_data = &mdp5_data->ctl->mfd->mdp_sync_pt_data; mutex_lock(&sync_pt_data->sync_mutex); if (mdp5_data->retire_cnt > 0) { sw_sync_timeline_inc(mdp5_data->vsync_timeline, 1); mdp5_data->retire_cnt--; if (mdp5_data->retire_cnt == 0) { mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false); mdp5_data->ctl->remove_vsync_handler(mdp5_data->ctl, &mdp5_data->vsync_retire_handler); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false); } } mutex_unlock(&sync_pt_data->sync_mutex); } static struct sync_fence * __vsync_retire_get_fence(struct msm_sync_pt_data *sync_pt_data) { struct msm_fb_data_type *mfd; struct mdss_overlay_private *mdp5_data; struct mdss_mdp_ctl *ctl; int rc, value; mfd = container_of(sync_pt_data, typeof(*mfd), mdp_sync_pt_data); mdp5_data = mfd_to_mdp5_data(mfd); if (!mdp5_data || !mdp5_data->ctl) return ERR_PTR(-ENODEV); ctl = mdp5_data->ctl; if (!ctl->add_vsync_handler) return ERR_PTR(-EOPNOTSUPP); if (!ctl->power_on) { pr_debug("fb%d vsync pending first update\n", mfd->index); return ERR_PTR(-EPERM); } if (mdp5_data->retire_cnt == 0) { mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false); rc = ctl->add_vsync_handler(ctl, &mdp5_data->vsync_retire_handler); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false); if (IS_ERR_VALUE(rc)) return ERR_PTR(rc); } value = mdp5_data->vsync_timeline->value + 1 + mdp5_data->retire_cnt; mdp5_data->retire_cnt++; return mdss_fb_sync_get_fence(mdp5_data->vsync_timeline, "mdp-retire", value); } static int __vsync_retire_setup(struct msm_fb_data_type *mfd) { struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); char name[24]; snprintf(name, sizeof(name), "mdss_fb%d_retire", mfd->index); mdp5_data->vsync_timeline = sw_sync_timeline_create(name); if (mdp5_data->vsync_timeline == NULL) { pr_err("cannot vsync create time line"); return -ENOMEM; } mfd->mdp_sync_pt_data.get_retire_fence = __vsync_retire_get_fence; mdp5_data->vsync_retire_handler.vsync_handler = __vsync_retire_handle_vsync; mdp5_data->vsync_retire_handler.cmd_post_flush = false; INIT_WORK(&mdp5_data->retire_work, __vsync_retire_work_handler); return 0; } int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd) { struct device *dev = mfd->fbi->dev; Loading Loading @@ -2846,6 +2948,12 @@ int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd) pr_err("Error dfps sysfs creation ret=%d\n", rc); goto init_fail; } } else if (mfd->panel_info->type == MIPI_CMD_PANEL) { rc = __vsync_retire_setup(mfd); if (IS_ERR_VALUE(rc)) { pr_err("unable to create vsync timeline\n"); goto init_fail; } } mfd->mdp_sync_pt_data.async_wait_fences = true; Loading
include/uapi/linux/msm_mdp.h +2 −8 Original line number Diff line number Diff line Loading @@ -994,6 +994,7 @@ struct msmfb_metadata { #define MDP_MAX_FENCE_FD 32 #define MDP_BUF_SYNC_FLAG_WAIT 1 #define MDP_BUF_SYNC_FLAG_RETIRE_FENCE 0x10 struct mdp_buf_sync { uint32_t flags; Loading @@ -1001,6 +1002,7 @@ struct mdp_buf_sync { uint32_t session_id; int *acq_fen_fd; int *rel_fen_fd; int *retire_fen_fd; }; struct mdp_async_blit_req_list { Loading @@ -1010,19 +1012,11 @@ struct mdp_async_blit_req_list { }; #define MDP_DISPLAY_COMMIT_OVERLAY 1 struct mdp_buf_fence { uint32_t flags; uint32_t acq_fen_fd_cnt; int acq_fen_fd[MDP_MAX_FENCE_FD]; int rel_fen_fd[MDP_MAX_FENCE_FD]; }; struct mdp_display_commit { uint32_t flags; uint32_t wait_for_finish; struct fb_var_screeninfo var; struct mdp_buf_fence buf_fence; struct mdp_rect roi; }; Loading