diff options
author | Jeykumar Sankaran <jsanka@codeaurora.org> | 2016-06-09 14:58:43 -0700 |
---|---|---|
committer | Kyle Yan <kyan@codeaurora.org> | 2016-06-30 16:49:30 -0700 |
commit | b11b49207482ad4633e7408bd0d2f061f8f86827 (patch) | |
tree | 86a2b626ef345d5d08827c37fa5aee8e9fe7e845 /drivers/video | |
parent | 54e3106b814db1f3cee469bf16519b1d34b4865c (diff) |
msm: mdss: Fix fence handling for CWB
Creates a work queue for concurrent writeback to wait and signal
the CWB retire fence on WB done interrupt.
Change-Id: I169e3df1a68616be93377defdc30e3c326aff79f
Signed-off-by: Jeykumar Sankaran <jsanka@codeaurora.org>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/fbdev/msm/mdss_fb.c | 8 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp.c | 4 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp.h | 4 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_ctl.c | 17 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c | 67 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_overlay.c | 28 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_pipe.c | 2 |
7 files changed, 87 insertions, 43 deletions
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c index 5888ad9e36be..6655da7ca5a5 100644 --- a/drivers/video/fbdev/msm/mdss_fb.c +++ b/drivers/video/fbdev/msm/mdss_fb.c @@ -1054,6 +1054,7 @@ static int mdss_fb_probe(struct platform_device *pdev) struct msm_fb_data_type *mfd = NULL; struct mdss_panel_data *pdata; struct fb_info *fbi; + struct mdss_overlay_private *mdp5_data = NULL; int rc; if (fbi_list_index >= MAX_FBI_LIST) @@ -1189,6 +1190,13 @@ static int mdss_fb_probe(struct platform_device *pdev) } mfd->mdp_sync_pt_data.notifier.notifier_call = __mdss_fb_sync_buf_done_callback; + + /* Initialize CWB notifier callback */ + mdp5_data = mfd_to_mdp5_data(mfd); + if (test_bit(MDSS_CAPS_CWB_SUPPORTED, + mdp5_data->mdata->mdss_caps_map)) + mdp5_data->cwb.cwb_sync_pt_data.notifier.notifier_call = + __mdss_fb_sync_buf_done_callback; } mdss_fb_set_mdp_sync_pt_threshold(mfd, mfd->panel.type); diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index a7b90d149c27..164bf0273597 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -4543,14 +4543,14 @@ static void apply_dynamic_ot_limit(u32 *ot_lim, return; /* Dynamic OT setting done only for rotator and WFD */ - if (!((params->is_rot && params->is_yuv) || params->is_wb)) + if (!((params->is_rot && params->is_yuv) || params->is_wfd)) return; res = params->width * params->height; pr_debug("w:%d h:%d rot:%d yuv:%d wb:%d res:%d fps:%d\n", params->width, params->height, params->is_rot, - params->is_yuv, params->is_wb, res, params->frame_rate); + params->is_yuv, params->is_wfd, res, params->frame_rate); switch (mdata->mdp_rev) { case MDSS_MDP_HW_REV_114: diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h index e7bc1c607d70..8d1d4e42a006 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.h +++ b/drivers/video/fbdev/msm/mdss_mdp.h @@ -397,6 +397,8 @@ struct mdss_mdp_cwb { void *priv_data; struct msm_sync_pt_data cwb_sync_pt_data; struct blocking_notifier_head notifier_head; + struct workqueue_struct *cwb_work_queue; + struct work_struct cwb_work; }; struct mdss_mdp_ctl { @@ -897,7 +899,7 @@ struct mdss_mdp_set_ot_params { u32 height; u16 frame_rate; bool is_rot; - bool is_wb; + bool is_wfd; bool is_yuv; bool is_vbif_nrt; u32 reg_off_vbif_lim_conf; diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index fcea868ff082..96f2375a6f7d 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -3358,9 +3358,12 @@ int mdss_mdp_cwb_setup(struct mdss_mdp_ctl *ctl) if (cwb->priv_data == NULL) { pr_err("fail to get writeback context\n"); rc = -ENOMEM; - goto cwb_setup_done; + goto cwb_setup_fail; } + /* reset wb to null to avoid deferencing in ctl free */ + ctl->wb = NULL; + mutex_lock(&cwb->queue_lock); cwb_data = list_first_entry_or_null(&cwb->data_queue, struct mdss_mdp_wb_data, next); @@ -3368,13 +3371,13 @@ int mdss_mdp_cwb_setup(struct mdss_mdp_ctl *ctl) if (cwb_data == NULL) { pr_err("no output buffer for cwb\n"); rc = -ENOMEM; - goto cwb_setup_done; + goto cwb_setup_fail; } rc = mdss_mdp_data_map(&cwb_data->data, true, DMA_FROM_DEVICE); if (rc) { pr_err("fail to acquire CWB output buffer\n"); - goto cwb_setup_done; + goto cwb_setup_fail; } memset(&wb_args, 0, sizeof(wb_args)); @@ -3383,7 +3386,7 @@ int mdss_mdp_cwb_setup(struct mdss_mdp_ctl *ctl) rc = mdss_mdp_writeback_prepare_cwb(ctl, &wb_args); if (rc) { pr_err("failed to writeback prepare cwb\n"); - goto cwb_setup_done; + goto cwb_setup_fail; } /* Select MEM_SEL to WB */ @@ -3409,11 +3412,13 @@ int mdss_mdp_cwb_setup(struct mdss_mdp_ctl *ctl) sctl->opmode; mdss_mdp_ctl_write(sctl, MDSS_MDP_REG_CTL_TOP, opmode); } + goto cwb_setup_done; -cwb_setup_done: - cwb->valid = 0; +cwb_setup_fail: atomic_add_unless(&mdp5_data->wb_busy, -1, 0); +cwb_setup_done: + cwb->valid = 0; return 0; } diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c b/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c index 237157c81515..9026b99cd87a 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c @@ -124,6 +124,28 @@ static inline void mdp_wb_write(struct mdss_mdp_writeback_ctx *ctx, writel_relaxed(val, ctx->base + reg); } +static void mdss_mdp_set_ot_limit_wb(struct mdss_mdp_writeback_ctx *ctx, + int is_wfd) +{ + struct mdss_mdp_set_ot_params ot_params; + struct mdss_data_type *mdata = mdss_mdp_get_mdata(); + + ot_params.xin_id = ctx->xin_id; + ot_params.num = ctx->wb_num; + ot_params.width = ctx->width; + ot_params.height = ctx->height; + ot_params.frame_rate = ctx->frame_rate; + ot_params.reg_off_vbif_lim_conf = MMSS_VBIF_WR_LIM_CONF; + ot_params.reg_off_mdp_clk_ctrl = ctx->clk_ctrl.reg_off; + ot_params.bit_off_mdp_clk_ctrl = ctx->clk_ctrl.bit_off; + ot_params.is_rot = (ctx->type == MDSS_MDP_WRITEBACK_TYPE_ROTATOR); + ot_params.is_wfd = is_wfd; + ot_params.is_yuv = ctx->dst_fmt->is_yuv; + ot_params.is_vbif_nrt = mdss_mdp_is_nrt_vbif_base_defined(mdata); + + mdss_mdp_set_ot_limit(&ot_params); +} + static int mdss_mdp_writeback_addr_setup(struct mdss_mdp_writeback_ctx *ctx, const struct mdss_mdp_data *in_data) { @@ -202,18 +224,18 @@ static void mdss_mdp_writeback_cwb_overflow(void *arg) { struct mdss_mdp_ctl *ctl = arg; struct mdss_overlay_private *mdp5_data = NULL; + struct mdss_mdp_writeback_ctx *ctx = NULL; pr_err("Buffer overflow triggered ctl=%d\n", ctl->num); MDSS_XLOG(ctl->num); - if (ctl->mfd) + if (!ctl->mfd) return; mdp5_data = mfd_to_mdp5_data(ctl->mfd); + ctx = mdp5_data->cwb.priv_data; mdp5_data->cwb.valid = 0; - blocking_notifier_call_chain(&mdp5_data->cwb.notifier_head, - MDP_NOTIFY_FRAME_TIMEOUT, NULL); - + mdss_mdp_irq_disable_nosync(ctx->intr_type, ctx->intf_num); mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_CWB_OVERFLOW, CWB_PPB_0); if (mdss_mdp_get_split_ctl(ctl)) mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_CWB_OVERFLOW, @@ -231,7 +253,7 @@ static void mdss_mdp_writeback_cwb_intr_done(void *arg) struct mdss_overlay_private *mdp5_data = NULL; struct mdss_mdp_writeback_ctx *ctx = NULL; - if (ctl->mfd) + if (!ctl->mfd) return; mdp5_data = mfd_to_mdp5_data(ctl->mfd); @@ -239,9 +261,12 @@ static void mdss_mdp_writeback_cwb_intr_done(void *arg) mdp5_data->cwb.valid = 0; mdss_mdp_irq_disable_nosync(ctx->intr_type, ctx->intf_num); + mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_CWB_OVERFLOW, CWB_PPB_0); + if (mdss_mdp_get_split_ctl(ctl)) + mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_CWB_OVERFLOW, + CWB_PPB_1); - blocking_notifier_call_chain(&mdp5_data->cwb.notifier_head, - MDP_NOTIFY_FRAME_DONE, NULL); + queue_work(mdp5_data->cwb.cwb_work_queue, &mdp5_data->cwb.cwb_work); if (!atomic_add_unless(&mdp5_data->wb_busy, -1, 0)) pr_err("Invalid state for WB\n"); @@ -462,6 +487,10 @@ int mdss_mdp_writeback_prepare_cwb(struct mdss_mdp_ctl *ctl, sctl->intf_num, mdss_mdp_writeback_cwb_overflow, sctl); } + + if (ctl->mdata->default_ot_wr_limit || ctl->mdata->default_ot_rd_limit) + mdss_mdp_set_ot_limit_wb(ctx, false); + return ret; } @@ -840,28 +869,6 @@ static int mdss_mdp_wb_wait4comp(struct mdss_mdp_ctl *ctl, void *arg) return rc; } -static void mdss_mdp_set_ot_limit_wb(struct mdss_mdp_writeback_ctx *ctx) -{ - struct mdss_mdp_set_ot_params ot_params; - struct mdss_data_type *mdata = mdss_mdp_get_mdata(); - - ot_params.xin_id = ctx->xin_id; - ot_params.num = ctx->wb_num; - ot_params.width = ctx->width; - ot_params.height = ctx->height; - ot_params.frame_rate = ctx->frame_rate; - ot_params.reg_off_vbif_lim_conf = MMSS_VBIF_WR_LIM_CONF; - ot_params.reg_off_mdp_clk_ctrl = ctx->clk_ctrl.reg_off; - ot_params.bit_off_mdp_clk_ctrl = ctx->clk_ctrl.bit_off; - ot_params.is_rot = (ctx->type == MDSS_MDP_WRITEBACK_TYPE_ROTATOR); - ot_params.is_wb = true; - ot_params.is_yuv = ctx->dst_fmt->is_yuv; - ot_params.is_vbif_nrt = mdss_mdp_is_nrt_vbif_base_defined(mdata); - - mdss_mdp_set_ot_limit(&ot_params); - -} - static int mdss_mdp_writeback_display(struct mdss_mdp_ctl *ctl, void *arg) { struct mdss_mdp_writeback_ctx *ctx; @@ -884,7 +891,7 @@ static int mdss_mdp_writeback_display(struct mdss_mdp_ctl *ctl, void *arg) if (ctl->mdata->default_ot_wr_limit || ctl->mdata->default_ot_rd_limit) - mdss_mdp_set_ot_limit_wb(ctx); + mdss_mdp_set_ot_limit_wb(ctx, true); wb_args = (struct mdss_mdp_writeback_arg *) arg; if (!wb_args) diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index 0173f73ffe6b..5a5c9946c3f9 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -54,6 +54,7 @@ static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd); static void __overlay_kickoff_requeue(struct msm_fb_data_type *mfd); static void __vsync_retire_signal(struct msm_fb_data_type *mfd, int val); static int __vsync_set_vsync_handler(struct msm_fb_data_type *mfd); +static void __cwb_wq_handler(struct work_struct *cwb_work); static int mdss_mdp_update_panel_info(struct msm_fb_data_type *mfd, int mode, int dest_ctrl); static int mdss_mdp_set_cfg(struct msm_fb_data_type *mfd, @@ -5300,6 +5301,15 @@ __vsync_retire_get_fence(struct msm_sync_pt_data *sync_pt_data) "mdp-retire", value); } +static void __cwb_wq_handler(struct work_struct *cwb_work) +{ + struct mdss_mdp_cwb *cwb = NULL; + + cwb = container_of(cwb_work, struct mdss_mdp_cwb, cwb_work); + blocking_notifier_call_chain(&cwb->notifier_head, + MDP_NOTIFY_FRAME_DONE, NULL); +} + static int __vsync_set_vsync_handler(struct msm_fb_data_type *mfd) { struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); @@ -5492,15 +5502,22 @@ int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd) mutex_init(&mdp5_data->list_lock); mutex_init(&mdp5_data->ov_lock); mutex_init(&mdp5_data->dfps_lock); + + mfd->mdp.private1 = mdp5_data; + mfd->wait_for_kickoff = true; + mdp5_data->hw_refresh = true; mdp5_data->cursor_ndx[CURSOR_PIPE_LEFT] = MSMFB_NEW_REQUEST; mdp5_data->cursor_ndx[CURSOR_PIPE_RIGHT] = MSMFB_NEW_REQUEST; init_waitqueue_head(&mdp5_data->wb_waitq); + atomic_set(&mdp5_data->wb_busy, 0); mutex_init(&mdp5_data->cwb.queue_lock); + mutex_init(&mdp5_data->cwb.cwb_sync_pt_data.sync_mutex); INIT_LIST_HEAD(&mdp5_data->cwb.data_queue); snprintf(timeline_name, sizeof(timeline_name), "cwb%d", mfd->index); + mdp5_data->cwb.cwb_sync_pt_data.fence_name = "cwb-fence"; mdp5_data->cwb.cwb_sync_pt_data.timeline = sw_sync_timeline_create(timeline_name); if (mdp5_data->cwb.cwb_sync_pt_data.timeline == NULL) { @@ -5509,10 +5526,15 @@ int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd) } blocking_notifier_chain_register(&mdp5_data->cwb.notifier_head, - &mfd->mdp_sync_pt_data.notifier); + &mdp5_data->cwb.cwb_sync_pt_data.notifier); + mdp5_data->cwb.cwb_work_queue = alloc_ordered_workqueue("%s", + WQ_UNBOUND | WQ_MEM_RECLAIM, "cwb_wq"); + if (!mdp5_data->cwb.cwb_work_queue) { + pr_err("failed to create cwb work queue\n"); + return -EPERM; + } - mfd->mdp.private1 = mdp5_data; - mfd->wait_for_kickoff = true; + INIT_WORK(&mdp5_data->cwb.cwb_work, __cwb_wq_handler); rc = mdss_mdp_overlay_fb_parse_dt(mfd); if (rc) diff --git a/drivers/video/fbdev/msm/mdss_mdp_pipe.c b/drivers/video/fbdev/msm/mdss_mdp_pipe.c index e011e35ac62e..220f2b503716 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pipe.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pipe.c @@ -2379,7 +2379,7 @@ static void mdss_mdp_set_ot_limit_pipe(struct mdss_mdp_pipe *pipe) ot_params.bit_off_mdp_clk_ctrl = pipe->clk_ctrl.bit_off + CLK_FORCE_ON_OFFSET; ot_params.is_rot = pipe->mixer_left->rotator_mode; - ot_params.is_wb = ctl->intf_num == MDSS_MDP_NO_INTF; + ot_params.is_wfd = ctl->intf_num == MDSS_MDP_NO_INTF; ot_params.is_yuv = pipe->src_fmt->is_yuv; ot_params.frame_rate = pipe->frame_rate; |