Loading drivers/video/msm/mdss/mdss_debug.c +2 −1 Original line number Original line Diff line number Diff line Loading @@ -181,6 +181,7 @@ static ssize_t panel_debug_base_reg_write(struct file *file, if (mdata->debug_inf.debug_enable_clock) if (mdata->debug_inf.debug_enable_clock) mdata->debug_inf.debug_enable_clock(1); mdata->debug_inf.debug_enable_clock(1); if (ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT) mdss_dsi_cmdlist_put(ctrl_pdata, &cmdreq); mdss_dsi_cmdlist_put(ctrl_pdata, &cmdreq); if (mdata->debug_inf.debug_enable_clock) if (mdata->debug_inf.debug_enable_clock) Loading drivers/video/msm/mdss/mdss_dsi.c +15 −1 Original line number Original line Diff line number Diff line Loading @@ -1483,7 +1483,6 @@ static int mdss_dsi_unblank(struct mdss_panel_data *pdata) } } ATRACE_END("dsi_panel_on"); ATRACE_END("dsi_panel_on"); } } ctrl_pdata->ctrl_state |= CTRL_STATE_PANEL_INIT; } } if ((pdata->panel_info.type == MIPI_CMD_PANEL) && if ((pdata->panel_info.type == MIPI_CMD_PANEL) && Loading @@ -1493,6 +1492,8 @@ static int mdss_dsi_unblank(struct mdss_panel_data *pdata) enable_irq(gpio_to_irq(ctrl_pdata->disp_te_gpio)); enable_irq(gpio_to_irq(ctrl_pdata->disp_te_gpio)); } } ctrl_pdata->ctrl_state |= CTRL_STATE_PANEL_INIT; error: error: mdss_dsi_clk_ctrl(ctrl_pdata, ctrl_pdata->dsi_clk_handle, mdss_dsi_clk_ctrl(ctrl_pdata, ctrl_pdata->dsi_clk_handle, MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_OFF); MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_OFF); Loading Loading @@ -2343,6 +2344,15 @@ int mdss_dsi_register_recovery_handler(struct mdss_dsi_ctrl_pdata *ctrl, return 0; return 0; } } static int mdss_dsi_register_mdp_callback(struct mdss_dsi_ctrl_pdata *ctrl, struct mdss_intf_recovery *mdp_callback) { mutex_lock(&ctrl->mutex); ctrl->mdp_callback = mdp_callback; mutex_unlock(&ctrl->mutex); return 0; } static struct device_node *mdss_dsi_get_fb_node_cb(struct platform_device *pdev) static struct device_node *mdss_dsi_get_fb_node_cb(struct platform_device *pdev) { { struct device_node *fb_node; struct device_node *fb_node; Loading Loading @@ -2493,6 +2503,10 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata, rc = mdss_dsi_register_recovery_handler(ctrl_pdata, rc = mdss_dsi_register_recovery_handler(ctrl_pdata, (struct mdss_intf_recovery *)arg); (struct mdss_intf_recovery *)arg); break; break; case MDSS_EVENT_REGISTER_MDP_CALLBACK: rc = mdss_dsi_register_mdp_callback(ctrl_pdata, (struct mdss_intf_recovery *)arg); break; case MDSS_EVENT_DSI_DYNAMIC_SWITCH: case MDSS_EVENT_DSI_DYNAMIC_SWITCH: mode = (u32)(unsigned long) arg; mode = (u32)(unsigned long) arg; mdss_dsi_switch_mode(pdata, mode); mdss_dsi_switch_mode(pdata, mode); Loading drivers/video/msm/mdss/mdss_dsi.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -456,6 +456,7 @@ struct mdss_dsi_ctrl_pdata { u32 dsi_irq_mask; u32 dsi_irq_mask; struct mdss_hw *dsi_hw; struct mdss_hw *dsi_hw; struct mdss_intf_recovery *recovery; struct mdss_intf_recovery *recovery; struct mdss_intf_recovery *mdp_callback; struct dsi_panel_cmds on_cmds; struct dsi_panel_cmds on_cmds; struct dsi_panel_cmds post_dms_on_cmds; struct dsi_panel_cmds post_dms_on_cmds; Loading drivers/video/msm/mdss/mdss_dsi_host.c +54 −0 Original line number Original line Diff line number Diff line Loading @@ -2479,6 +2479,49 @@ int mdss_dsi_cmdlist_rx(struct mdss_dsi_ctrl_pdata *ctrl, return len; return len; } } static inline bool mdss_dsi_delay_cmd(struct mdss_dsi_ctrl_pdata *ctrl, bool from_mdp) { unsigned long flags; bool mdp_busy = false; bool need_wait = false; if (!ctrl->mdp_callback) goto exit; /* delay only for split dsi, cmd mode and burst mode enabled cases */ if (!mdss_dsi_is_hw_config_split(ctrl->shared_data) || !(ctrl->panel_mode == DSI_CMD_MODE) || !ctrl->burst_mode_enabled) goto exit; /* delay only if cmd is not from mdp and panel has been initialized */ if (from_mdp || !(ctrl->ctrl_state & CTRL_STATE_PANEL_INIT)) goto exit; /* if broadcast enabled, apply delay only if this is the ctrl trigger */ if (mdss_dsi_sync_wait_enable(ctrl) && !mdss_dsi_sync_wait_trigger(ctrl)) goto exit; spin_lock_irqsave(&ctrl->mdp_lock, flags); if (ctrl->mdp_busy == true) mdp_busy = true; spin_unlock_irqrestore(&ctrl->mdp_lock, flags); /* * apply delay only if: * mdp_busy bool is set - kickoff is being scheduled by sw * MDP_BUSY bit is not set - transfer is not on-going in hw yet */ if (mdp_busy && !(MIPI_INP(ctrl->ctrl_base + 0x008) & BIT(2))) need_wait = true; exit: MDSS_XLOG(need_wait, from_mdp, mdp_busy); return need_wait; } int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) { { struct dcs_cmd_req *req; struct dcs_cmd_req *req; Loading Loading @@ -2581,6 +2624,17 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle, MDSS_DSI_ALL_CLKS, mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle, MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_ON); MDSS_DSI_CLK_ON); /* * In ping pong split cases, check if we need to apply a * delay for any commands that are not coming from * mdp path */ mutex_lock(&ctrl->mutex); if (mdss_dsi_delay_cmd(ctrl, from_mdp)) ctrl->mdp_callback->fxn(ctrl->mdp_callback->data, MDP_INTF_CALLBACK_DSI_WAIT); mutex_unlock(&ctrl->mutex); if (req->flags & CMD_REQ_HS_MODE) if (req->flags & CMD_REQ_HS_MODE) mdss_dsi_set_tx_power_mode(0, &ctrl->panel_data); mdss_dsi_set_tx_power_mode(0, &ctrl->panel_data); Loading drivers/video/msm/mdss/mdss_mdp_intf_cmd.c +120 −0 Original line number Original line Diff line number Diff line Loading @@ -13,6 +13,8 @@ #include <linux/kernel.h> #include <linux/kernel.h> #include <linux/pm_runtime.h> #include <linux/pm_runtime.h> #include <linux/iopoll.h> #include <linux/delay.h> #include "mdss_mdp.h" #include "mdss_mdp.h" #include "mdss_panel.h" #include "mdss_panel.h" Loading Loading @@ -57,6 +59,8 @@ struct mdss_mdp_cmd_ctx { u8 ref_cnt; u8 ref_cnt; struct completion stop_comp; struct completion stop_comp; atomic_t rdptr_cnt; wait_queue_head_t rdptr_waitq; struct completion pp_done; struct completion pp_done; wait_queue_head_t pp_waitq; wait_queue_head_t pp_waitq; struct list_head vsync_handlers; struct list_head vsync_handlers; Loading Loading @@ -88,6 +92,7 @@ struct mdss_mdp_cmd_ctx { int vsync_irq_cnt; int vsync_irq_cnt; struct mdss_intf_recovery intf_recovery; struct mdss_intf_recovery intf_recovery; struct mdss_intf_recovery intf_mdp_callback; struct mdss_mdp_cmd_ctx *sync_ctx; /* for partial update */ struct mdss_mdp_cmd_ctx *sync_ctx; /* for partial update */ u32 pp_timeout_report_cnt; u32 pp_timeout_report_cnt; bool pingpong_split_slave; bool pingpong_split_slave; Loading @@ -101,6 +106,7 @@ static inline void mdss_mdp_cmd_clk_off(struct mdss_mdp_cmd_ctx *ctx); static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg); static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg); static int mdss_mdp_disable_autorefresh(struct mdss_mdp_ctl *ctl, static int mdss_mdp_disable_autorefresh(struct mdss_mdp_ctl *ctl, struct mdss_mdp_ctl *sctl); struct mdss_mdp_ctl *sctl); static int mdss_mdp_setup_vsync(struct mdss_mdp_cmd_ctx *ctx, bool enable); static bool __mdss_mdp_cmd_is_aux_pp_needed(struct mdss_data_type *mdata, static bool __mdss_mdp_cmd_is_aux_pp_needed(struct mdss_data_type *mdata, struct mdss_mdp_ctl *mctl) struct mdss_mdp_ctl *mctl) Loading Loading @@ -959,6 +965,17 @@ static void mdss_mdp_cmd_readptr_done(void *arg) MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt)); MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt)); complete_all(&ctx->rdptr_done); complete_all(&ctx->rdptr_done); /* If caller is waiting for the read pointer, notify. */ if (atomic_read(&ctx->rdptr_cnt)) { if (atomic_add_unless(&ctx->rdptr_cnt, -1, 0)) { MDSS_XLOG(atomic_read(&ctx->rdptr_cnt)); if (atomic_read(&ctx->rdptr_cnt)) pr_warn("%s: too many rdptrs=%d!\n", __func__, atomic_read(&ctx->rdptr_cnt)); } wake_up_all(&ctx->rdptr_waitq); } spin_lock(&ctx->clk_lock); spin_lock(&ctx->clk_lock); list_for_each_entry(tmp, &ctx->vsync_handlers, list) { list_for_each_entry(tmp, &ctx->vsync_handlers, list) { if (tmp->enabled && !tmp->cmd_post_flush) if (tmp->enabled && !tmp->cmd_post_flush) Loading @@ -967,6 +984,82 @@ static void mdss_mdp_cmd_readptr_done(void *arg) spin_unlock(&ctx->clk_lock); spin_unlock(&ctx->clk_lock); } } static int mdss_mdp_cmd_wait4readptr(struct mdss_mdp_cmd_ctx *ctx) { int rc = 0; rc = wait_event_timeout(ctx->rdptr_waitq, atomic_read(&ctx->rdptr_cnt) == 0, KOFF_TIMEOUT); if (rc <= 0) { if (atomic_read(&ctx->rdptr_cnt)) pr_err("timed out waiting for rdptr irq\n"); else rc = 1; } return rc; } static void mdss_mdp_cmd_intf_callback(void *data, int event) { struct mdss_mdp_cmd_ctx *ctx = data; struct mdss_mdp_pp_tear_check *te = NULL; u32 timeout_us = 3000, val = 0; struct mdss_mdp_mixer *mixer; if (!data) { pr_err("%s: invalid ctx\n", __func__); return; } if (!ctx->ctl) return; switch (event) { case MDP_INTF_CALLBACK_DSI_WAIT: pr_debug("%s: wait for frame cnt:%d event:%d\n", __func__, atomic_read(&ctx->rdptr_cnt), event); /* * if we are going to suspended or pp split is not enabled, * just return */ if (ctx->intf_stopped || !is_pingpong_split(ctx->ctl->mfd)) return; atomic_inc(&ctx->rdptr_cnt); /* enable clks and rd_ptr interrupt */ mdss_mdp_setup_vsync(ctx, true); mixer = mdss_mdp_mixer_get(ctx->ctl, MDSS_MDP_MIXER_MUX_LEFT); if (!mixer) { pr_err("%s: null mixer\n", __func__); return; } /* wait for read pointer */ MDSS_XLOG(atomic_read(&ctx->rdptr_cnt)); pr_debug("%s: wait for frame cnt:%d\n", __func__, atomic_read(&ctx->rdptr_cnt)); mdss_mdp_cmd_wait4readptr(ctx); /* wait for 3ms to make sure we are within the frame */ te = &ctx->ctl->panel_data->panel_info.te; readl_poll_timeout(mixer->pingpong_base + MDSS_MDP_REG_PP_INT_COUNT_VAL, val, (val & 0xffff) > (te->start_pos + te->sync_threshold_start), 10, timeout_us); /* disable rd_ptr interrupt */ mdss_mdp_setup_vsync(ctx, false); break; default: pr_debug("%s: unhandled event=%d\n", __func__, event); break; } } static void mdss_mdp_cmd_intf_recovery(void *data, int event) static void mdss_mdp_cmd_intf_recovery(void *data, int event) { { struct mdss_mdp_cmd_ctx *ctx = data; struct mdss_mdp_cmd_ctx *ctx = data; Loading Loading @@ -1757,6 +1850,11 @@ static int mdss_mdp_cmd_panel_on(struct mdss_mdp_ctl *ctl, (void *)&ctx->intf_recovery, (void *)&ctx->intf_recovery, CTL_INTF_EVENT_FLAG_DEFAULT); CTL_INTF_EVENT_FLAG_DEFAULT); mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_REGISTER_MDP_CALLBACK, (void *)&ctx->intf_mdp_callback, CTL_INTF_EVENT_FLAG_DEFAULT); ctx->intf_stopped = 0; ctx->intf_stopped = 0; if (sctx) if (sctx) sctx->intf_stopped = 0; sctx->intf_stopped = 0; Loading Loading @@ -2438,6 +2536,14 @@ int mdss_mdp_cmd_ctx_stop(struct mdss_mdp_ctl *ctl, /* intf stopped, no more kickoff */ /* intf stopped, no more kickoff */ ctx->intf_stopped = 1; ctx->intf_stopped = 1; /* Make sure any rd ptr for dsi callback is done before disable vsync */ if (is_pingpong_split(ctl->mfd)) { pr_debug("%s will wait for rd ptr:%d\n", __func__, atomic_read(&ctx->rdptr_cnt)); MDSS_XLOG(atomic_read(&ctx->rdptr_cnt)); mdss_mdp_cmd_wait4readptr(ctx); } /* /* * if any vsyncs are still enabled, loop until the refcount * if any vsyncs are still enabled, loop until the refcount * goes to zero, so the rd ptr interrupt is disabled. * goes to zero, so the rd ptr interrupt is disabled. Loading @@ -2455,6 +2561,10 @@ int mdss_mdp_cmd_ctx_stop(struct mdss_mdp_ctl *ctl, mdss_mdp_ctl_intf_event(ctl, mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_REGISTER_RECOVERY_HANDLER, MDSS_EVENT_REGISTER_RECOVERY_HANDLER, NULL, CTL_INTF_EVENT_FLAG_DEFAULT); NULL, CTL_INTF_EVENT_FLAG_DEFAULT); mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_REGISTER_MDP_CALLBACK, NULL, CTL_INTF_EVENT_FLAG_DEFAULT); } } /* shut down the MDP/DSI resources if still enabled */ /* shut down the MDP/DSI resources if still enabled */ Loading Loading @@ -2608,6 +2718,12 @@ int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl, int panel_power_state) MDSS_EVENT_REGISTER_RECOVERY_HANDLER, MDSS_EVENT_REGISTER_RECOVERY_HANDLER, (void *)&ctx->intf_recovery, (void *)&ctx->intf_recovery, CTL_INTF_EVENT_FLAG_DEFAULT); CTL_INTF_EVENT_FLAG_DEFAULT); mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_REGISTER_MDP_CALLBACK, (void *)&ctx->intf_mdp_callback, CTL_INTF_EVENT_FLAG_DEFAULT); ctx->intf_stopped = 0; ctx->intf_stopped = 0; if (sctx) if (sctx) sctx->intf_stopped = 0; sctx->intf_stopped = 0; Loading Loading @@ -2762,6 +2878,7 @@ static int mdss_mdp_cmd_ctx_setup(struct mdss_mdp_ctl *ctl, ctx->pingpong_split_slave = pingpong_split_slave; ctx->pingpong_split_slave = pingpong_split_slave; ctx->pp_timeout_report_cnt = 0; ctx->pp_timeout_report_cnt = 0; init_waitqueue_head(&ctx->pp_waitq); init_waitqueue_head(&ctx->pp_waitq); init_waitqueue_head(&ctx->rdptr_waitq); init_completion(&ctx->stop_comp); init_completion(&ctx->stop_comp); init_completion(&ctx->autorefresh_ppdone); init_completion(&ctx->autorefresh_ppdone); init_completion(&ctx->rdptr_done); init_completion(&ctx->rdptr_done); Loading @@ -2784,6 +2901,9 @@ static int mdss_mdp_cmd_ctx_setup(struct mdss_mdp_ctl *ctl, ctx->intf_recovery.fxn = mdss_mdp_cmd_intf_recovery; ctx->intf_recovery.fxn = mdss_mdp_cmd_intf_recovery; ctx->intf_recovery.data = ctx; ctx->intf_recovery.data = ctx; ctx->intf_mdp_callback.fxn = mdss_mdp_cmd_intf_callback; ctx->intf_mdp_callback.data = ctx; ctx->intf_stopped = 0; ctx->intf_stopped = 0; pr_debug("%s: ctx=%p num=%d aux=%d\n", __func__, ctx, pr_debug("%s: ctx=%p num=%d aux=%d\n", __func__, ctx, Loading Loading
drivers/video/msm/mdss/mdss_debug.c +2 −1 Original line number Original line Diff line number Diff line Loading @@ -181,6 +181,7 @@ static ssize_t panel_debug_base_reg_write(struct file *file, if (mdata->debug_inf.debug_enable_clock) if (mdata->debug_inf.debug_enable_clock) mdata->debug_inf.debug_enable_clock(1); mdata->debug_inf.debug_enable_clock(1); if (ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT) mdss_dsi_cmdlist_put(ctrl_pdata, &cmdreq); mdss_dsi_cmdlist_put(ctrl_pdata, &cmdreq); if (mdata->debug_inf.debug_enable_clock) if (mdata->debug_inf.debug_enable_clock) Loading
drivers/video/msm/mdss/mdss_dsi.c +15 −1 Original line number Original line Diff line number Diff line Loading @@ -1483,7 +1483,6 @@ static int mdss_dsi_unblank(struct mdss_panel_data *pdata) } } ATRACE_END("dsi_panel_on"); ATRACE_END("dsi_panel_on"); } } ctrl_pdata->ctrl_state |= CTRL_STATE_PANEL_INIT; } } if ((pdata->panel_info.type == MIPI_CMD_PANEL) && if ((pdata->panel_info.type == MIPI_CMD_PANEL) && Loading @@ -1493,6 +1492,8 @@ static int mdss_dsi_unblank(struct mdss_panel_data *pdata) enable_irq(gpio_to_irq(ctrl_pdata->disp_te_gpio)); enable_irq(gpio_to_irq(ctrl_pdata->disp_te_gpio)); } } ctrl_pdata->ctrl_state |= CTRL_STATE_PANEL_INIT; error: error: mdss_dsi_clk_ctrl(ctrl_pdata, ctrl_pdata->dsi_clk_handle, mdss_dsi_clk_ctrl(ctrl_pdata, ctrl_pdata->dsi_clk_handle, MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_OFF); MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_OFF); Loading Loading @@ -2343,6 +2344,15 @@ int mdss_dsi_register_recovery_handler(struct mdss_dsi_ctrl_pdata *ctrl, return 0; return 0; } } static int mdss_dsi_register_mdp_callback(struct mdss_dsi_ctrl_pdata *ctrl, struct mdss_intf_recovery *mdp_callback) { mutex_lock(&ctrl->mutex); ctrl->mdp_callback = mdp_callback; mutex_unlock(&ctrl->mutex); return 0; } static struct device_node *mdss_dsi_get_fb_node_cb(struct platform_device *pdev) static struct device_node *mdss_dsi_get_fb_node_cb(struct platform_device *pdev) { { struct device_node *fb_node; struct device_node *fb_node; Loading Loading @@ -2493,6 +2503,10 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata, rc = mdss_dsi_register_recovery_handler(ctrl_pdata, rc = mdss_dsi_register_recovery_handler(ctrl_pdata, (struct mdss_intf_recovery *)arg); (struct mdss_intf_recovery *)arg); break; break; case MDSS_EVENT_REGISTER_MDP_CALLBACK: rc = mdss_dsi_register_mdp_callback(ctrl_pdata, (struct mdss_intf_recovery *)arg); break; case MDSS_EVENT_DSI_DYNAMIC_SWITCH: case MDSS_EVENT_DSI_DYNAMIC_SWITCH: mode = (u32)(unsigned long) arg; mode = (u32)(unsigned long) arg; mdss_dsi_switch_mode(pdata, mode); mdss_dsi_switch_mode(pdata, mode); Loading
drivers/video/msm/mdss/mdss_dsi.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -456,6 +456,7 @@ struct mdss_dsi_ctrl_pdata { u32 dsi_irq_mask; u32 dsi_irq_mask; struct mdss_hw *dsi_hw; struct mdss_hw *dsi_hw; struct mdss_intf_recovery *recovery; struct mdss_intf_recovery *recovery; struct mdss_intf_recovery *mdp_callback; struct dsi_panel_cmds on_cmds; struct dsi_panel_cmds on_cmds; struct dsi_panel_cmds post_dms_on_cmds; struct dsi_panel_cmds post_dms_on_cmds; Loading
drivers/video/msm/mdss/mdss_dsi_host.c +54 −0 Original line number Original line Diff line number Diff line Loading @@ -2479,6 +2479,49 @@ int mdss_dsi_cmdlist_rx(struct mdss_dsi_ctrl_pdata *ctrl, return len; return len; } } static inline bool mdss_dsi_delay_cmd(struct mdss_dsi_ctrl_pdata *ctrl, bool from_mdp) { unsigned long flags; bool mdp_busy = false; bool need_wait = false; if (!ctrl->mdp_callback) goto exit; /* delay only for split dsi, cmd mode and burst mode enabled cases */ if (!mdss_dsi_is_hw_config_split(ctrl->shared_data) || !(ctrl->panel_mode == DSI_CMD_MODE) || !ctrl->burst_mode_enabled) goto exit; /* delay only if cmd is not from mdp and panel has been initialized */ if (from_mdp || !(ctrl->ctrl_state & CTRL_STATE_PANEL_INIT)) goto exit; /* if broadcast enabled, apply delay only if this is the ctrl trigger */ if (mdss_dsi_sync_wait_enable(ctrl) && !mdss_dsi_sync_wait_trigger(ctrl)) goto exit; spin_lock_irqsave(&ctrl->mdp_lock, flags); if (ctrl->mdp_busy == true) mdp_busy = true; spin_unlock_irqrestore(&ctrl->mdp_lock, flags); /* * apply delay only if: * mdp_busy bool is set - kickoff is being scheduled by sw * MDP_BUSY bit is not set - transfer is not on-going in hw yet */ if (mdp_busy && !(MIPI_INP(ctrl->ctrl_base + 0x008) & BIT(2))) need_wait = true; exit: MDSS_XLOG(need_wait, from_mdp, mdp_busy); return need_wait; } int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) { { struct dcs_cmd_req *req; struct dcs_cmd_req *req; Loading Loading @@ -2581,6 +2624,17 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle, MDSS_DSI_ALL_CLKS, mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle, MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_ON); MDSS_DSI_CLK_ON); /* * In ping pong split cases, check if we need to apply a * delay for any commands that are not coming from * mdp path */ mutex_lock(&ctrl->mutex); if (mdss_dsi_delay_cmd(ctrl, from_mdp)) ctrl->mdp_callback->fxn(ctrl->mdp_callback->data, MDP_INTF_CALLBACK_DSI_WAIT); mutex_unlock(&ctrl->mutex); if (req->flags & CMD_REQ_HS_MODE) if (req->flags & CMD_REQ_HS_MODE) mdss_dsi_set_tx_power_mode(0, &ctrl->panel_data); mdss_dsi_set_tx_power_mode(0, &ctrl->panel_data); Loading
drivers/video/msm/mdss/mdss_mdp_intf_cmd.c +120 −0 Original line number Original line Diff line number Diff line Loading @@ -13,6 +13,8 @@ #include <linux/kernel.h> #include <linux/kernel.h> #include <linux/pm_runtime.h> #include <linux/pm_runtime.h> #include <linux/iopoll.h> #include <linux/delay.h> #include "mdss_mdp.h" #include "mdss_mdp.h" #include "mdss_panel.h" #include "mdss_panel.h" Loading Loading @@ -57,6 +59,8 @@ struct mdss_mdp_cmd_ctx { u8 ref_cnt; u8 ref_cnt; struct completion stop_comp; struct completion stop_comp; atomic_t rdptr_cnt; wait_queue_head_t rdptr_waitq; struct completion pp_done; struct completion pp_done; wait_queue_head_t pp_waitq; wait_queue_head_t pp_waitq; struct list_head vsync_handlers; struct list_head vsync_handlers; Loading Loading @@ -88,6 +92,7 @@ struct mdss_mdp_cmd_ctx { int vsync_irq_cnt; int vsync_irq_cnt; struct mdss_intf_recovery intf_recovery; struct mdss_intf_recovery intf_recovery; struct mdss_intf_recovery intf_mdp_callback; struct mdss_mdp_cmd_ctx *sync_ctx; /* for partial update */ struct mdss_mdp_cmd_ctx *sync_ctx; /* for partial update */ u32 pp_timeout_report_cnt; u32 pp_timeout_report_cnt; bool pingpong_split_slave; bool pingpong_split_slave; Loading @@ -101,6 +106,7 @@ static inline void mdss_mdp_cmd_clk_off(struct mdss_mdp_cmd_ctx *ctx); static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg); static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg); static int mdss_mdp_disable_autorefresh(struct mdss_mdp_ctl *ctl, static int mdss_mdp_disable_autorefresh(struct mdss_mdp_ctl *ctl, struct mdss_mdp_ctl *sctl); struct mdss_mdp_ctl *sctl); static int mdss_mdp_setup_vsync(struct mdss_mdp_cmd_ctx *ctx, bool enable); static bool __mdss_mdp_cmd_is_aux_pp_needed(struct mdss_data_type *mdata, static bool __mdss_mdp_cmd_is_aux_pp_needed(struct mdss_data_type *mdata, struct mdss_mdp_ctl *mctl) struct mdss_mdp_ctl *mctl) Loading Loading @@ -959,6 +965,17 @@ static void mdss_mdp_cmd_readptr_done(void *arg) MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt)); MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt)); complete_all(&ctx->rdptr_done); complete_all(&ctx->rdptr_done); /* If caller is waiting for the read pointer, notify. */ if (atomic_read(&ctx->rdptr_cnt)) { if (atomic_add_unless(&ctx->rdptr_cnt, -1, 0)) { MDSS_XLOG(atomic_read(&ctx->rdptr_cnt)); if (atomic_read(&ctx->rdptr_cnt)) pr_warn("%s: too many rdptrs=%d!\n", __func__, atomic_read(&ctx->rdptr_cnt)); } wake_up_all(&ctx->rdptr_waitq); } spin_lock(&ctx->clk_lock); spin_lock(&ctx->clk_lock); list_for_each_entry(tmp, &ctx->vsync_handlers, list) { list_for_each_entry(tmp, &ctx->vsync_handlers, list) { if (tmp->enabled && !tmp->cmd_post_flush) if (tmp->enabled && !tmp->cmd_post_flush) Loading @@ -967,6 +984,82 @@ static void mdss_mdp_cmd_readptr_done(void *arg) spin_unlock(&ctx->clk_lock); spin_unlock(&ctx->clk_lock); } } static int mdss_mdp_cmd_wait4readptr(struct mdss_mdp_cmd_ctx *ctx) { int rc = 0; rc = wait_event_timeout(ctx->rdptr_waitq, atomic_read(&ctx->rdptr_cnt) == 0, KOFF_TIMEOUT); if (rc <= 0) { if (atomic_read(&ctx->rdptr_cnt)) pr_err("timed out waiting for rdptr irq\n"); else rc = 1; } return rc; } static void mdss_mdp_cmd_intf_callback(void *data, int event) { struct mdss_mdp_cmd_ctx *ctx = data; struct mdss_mdp_pp_tear_check *te = NULL; u32 timeout_us = 3000, val = 0; struct mdss_mdp_mixer *mixer; if (!data) { pr_err("%s: invalid ctx\n", __func__); return; } if (!ctx->ctl) return; switch (event) { case MDP_INTF_CALLBACK_DSI_WAIT: pr_debug("%s: wait for frame cnt:%d event:%d\n", __func__, atomic_read(&ctx->rdptr_cnt), event); /* * if we are going to suspended or pp split is not enabled, * just return */ if (ctx->intf_stopped || !is_pingpong_split(ctx->ctl->mfd)) return; atomic_inc(&ctx->rdptr_cnt); /* enable clks and rd_ptr interrupt */ mdss_mdp_setup_vsync(ctx, true); mixer = mdss_mdp_mixer_get(ctx->ctl, MDSS_MDP_MIXER_MUX_LEFT); if (!mixer) { pr_err("%s: null mixer\n", __func__); return; } /* wait for read pointer */ MDSS_XLOG(atomic_read(&ctx->rdptr_cnt)); pr_debug("%s: wait for frame cnt:%d\n", __func__, atomic_read(&ctx->rdptr_cnt)); mdss_mdp_cmd_wait4readptr(ctx); /* wait for 3ms to make sure we are within the frame */ te = &ctx->ctl->panel_data->panel_info.te; readl_poll_timeout(mixer->pingpong_base + MDSS_MDP_REG_PP_INT_COUNT_VAL, val, (val & 0xffff) > (te->start_pos + te->sync_threshold_start), 10, timeout_us); /* disable rd_ptr interrupt */ mdss_mdp_setup_vsync(ctx, false); break; default: pr_debug("%s: unhandled event=%d\n", __func__, event); break; } } static void mdss_mdp_cmd_intf_recovery(void *data, int event) static void mdss_mdp_cmd_intf_recovery(void *data, int event) { { struct mdss_mdp_cmd_ctx *ctx = data; struct mdss_mdp_cmd_ctx *ctx = data; Loading Loading @@ -1757,6 +1850,11 @@ static int mdss_mdp_cmd_panel_on(struct mdss_mdp_ctl *ctl, (void *)&ctx->intf_recovery, (void *)&ctx->intf_recovery, CTL_INTF_EVENT_FLAG_DEFAULT); CTL_INTF_EVENT_FLAG_DEFAULT); mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_REGISTER_MDP_CALLBACK, (void *)&ctx->intf_mdp_callback, CTL_INTF_EVENT_FLAG_DEFAULT); ctx->intf_stopped = 0; ctx->intf_stopped = 0; if (sctx) if (sctx) sctx->intf_stopped = 0; sctx->intf_stopped = 0; Loading Loading @@ -2438,6 +2536,14 @@ int mdss_mdp_cmd_ctx_stop(struct mdss_mdp_ctl *ctl, /* intf stopped, no more kickoff */ /* intf stopped, no more kickoff */ ctx->intf_stopped = 1; ctx->intf_stopped = 1; /* Make sure any rd ptr for dsi callback is done before disable vsync */ if (is_pingpong_split(ctl->mfd)) { pr_debug("%s will wait for rd ptr:%d\n", __func__, atomic_read(&ctx->rdptr_cnt)); MDSS_XLOG(atomic_read(&ctx->rdptr_cnt)); mdss_mdp_cmd_wait4readptr(ctx); } /* /* * if any vsyncs are still enabled, loop until the refcount * if any vsyncs are still enabled, loop until the refcount * goes to zero, so the rd ptr interrupt is disabled. * goes to zero, so the rd ptr interrupt is disabled. Loading @@ -2455,6 +2561,10 @@ int mdss_mdp_cmd_ctx_stop(struct mdss_mdp_ctl *ctl, mdss_mdp_ctl_intf_event(ctl, mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_REGISTER_RECOVERY_HANDLER, MDSS_EVENT_REGISTER_RECOVERY_HANDLER, NULL, CTL_INTF_EVENT_FLAG_DEFAULT); NULL, CTL_INTF_EVENT_FLAG_DEFAULT); mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_REGISTER_MDP_CALLBACK, NULL, CTL_INTF_EVENT_FLAG_DEFAULT); } } /* shut down the MDP/DSI resources if still enabled */ /* shut down the MDP/DSI resources if still enabled */ Loading Loading @@ -2608,6 +2718,12 @@ int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl, int panel_power_state) MDSS_EVENT_REGISTER_RECOVERY_HANDLER, MDSS_EVENT_REGISTER_RECOVERY_HANDLER, (void *)&ctx->intf_recovery, (void *)&ctx->intf_recovery, CTL_INTF_EVENT_FLAG_DEFAULT); CTL_INTF_EVENT_FLAG_DEFAULT); mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_REGISTER_MDP_CALLBACK, (void *)&ctx->intf_mdp_callback, CTL_INTF_EVENT_FLAG_DEFAULT); ctx->intf_stopped = 0; ctx->intf_stopped = 0; if (sctx) if (sctx) sctx->intf_stopped = 0; sctx->intf_stopped = 0; Loading Loading @@ -2762,6 +2878,7 @@ static int mdss_mdp_cmd_ctx_setup(struct mdss_mdp_ctl *ctl, ctx->pingpong_split_slave = pingpong_split_slave; ctx->pingpong_split_slave = pingpong_split_slave; ctx->pp_timeout_report_cnt = 0; ctx->pp_timeout_report_cnt = 0; init_waitqueue_head(&ctx->pp_waitq); init_waitqueue_head(&ctx->pp_waitq); init_waitqueue_head(&ctx->rdptr_waitq); init_completion(&ctx->stop_comp); init_completion(&ctx->stop_comp); init_completion(&ctx->autorefresh_ppdone); init_completion(&ctx->autorefresh_ppdone); init_completion(&ctx->rdptr_done); init_completion(&ctx->rdptr_done); Loading @@ -2784,6 +2901,9 @@ static int mdss_mdp_cmd_ctx_setup(struct mdss_mdp_ctl *ctl, ctx->intf_recovery.fxn = mdss_mdp_cmd_intf_recovery; ctx->intf_recovery.fxn = mdss_mdp_cmd_intf_recovery; ctx->intf_recovery.data = ctx; ctx->intf_recovery.data = ctx; ctx->intf_mdp_callback.fxn = mdss_mdp_cmd_intf_callback; ctx->intf_mdp_callback.data = ctx; ctx->intf_stopped = 0; ctx->intf_stopped = 0; pr_debug("%s: ctx=%p num=%d aux=%d\n", __func__, ctx, pr_debug("%s: ctx=%p num=%d aux=%d\n", __func__, ctx, Loading