summaryrefslogtreecommitdiff
path: root/drivers/video
diff options
context:
space:
mode:
authorJeykumar Sankaran <jsanka@codeaurora.org>2016-06-09 14:58:43 -0700
committerKyle Yan <kyan@codeaurora.org>2016-06-30 16:49:30 -0700
commitb11b49207482ad4633e7408bd0d2f061f8f86827 (patch)
tree86a2b626ef345d5d08827c37fa5aee8e9fe7e845 /drivers/video
parent54e3106b814db1f3cee469bf16519b1d34b4865c (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.c8
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.c4
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h4
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c17
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c67
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c28
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pipe.c2
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;