diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2016-10-10 18:28:12 -0700 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-10-10 18:28:11 -0700 |
| commit | d0a8d1d5919214441db607016d1da03db772c9b4 (patch) | |
| tree | c96092df6bdcbcf02635df2da82b68fab5b4ddf7 /drivers/video/fbdev | |
| parent | de4737612cca451329416facd4c017b2558b45dd (diff) | |
| parent | 1675d1884aab50d051dc99e4eab709a75ce11dff (diff) | |
Merge "msm: mdss: add mdp guard window property"
Diffstat (limited to 'drivers/video/fbdev')
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi_panel.c | 44 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c | 84 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_panel.h | 4 |
3 files changed, 119 insertions, 13 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c index 8ffba091e2b2..01fc01425a3a 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_panel.c +++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c @@ -856,6 +856,48 @@ static int mdss_dsi_panel_low_power_config(struct mdss_panel_data *pdata, return 0; } +static void mdss_dsi_parse_mdp_kickoff_threshold(struct device_node *np, + struct mdss_panel_info *pinfo) +{ + int len, rc; + const u32 *src; + u32 tmp; + u32 max_delay_us; + + pinfo->mdp_koff_thshold = false; + src = of_get_property(np, "qcom,mdss-mdp-kickoff-threshold", &len); + if (!src || (len == 0)) + return; + + rc = of_property_read_u32(np, "qcom,mdss-mdp-kickoff-delay", &tmp); + if (!rc) + pinfo->mdp_koff_delay = tmp; + else + return; + + if (pinfo->mipi.frame_rate == 0) { + pr_err("cannot enable guard window, unexpected panel fps\n"); + return; + } + + pinfo->mdp_koff_thshold_low = be32_to_cpu(src[0]); + pinfo->mdp_koff_thshold_high = be32_to_cpu(src[1]); + max_delay_us = 1000000 / pinfo->mipi.frame_rate; + + /* enable the feature if threshold is valid */ + if ((pinfo->mdp_koff_thshold_low < pinfo->mdp_koff_thshold_high) && + ((pinfo->mdp_koff_delay > 0) || + (pinfo->mdp_koff_delay < max_delay_us))) + pinfo->mdp_koff_thshold = true; + + pr_debug("panel kickoff thshold:[%d, %d] delay:%d (max:%d) enable:%d\n", + pinfo->mdp_koff_thshold_low, + pinfo->mdp_koff_thshold_high, + pinfo->mdp_koff_delay, + max_delay_us, + pinfo->mdp_koff_thshold); +} + static void mdss_dsi_parse_trigger(struct device_node *np, char *trigger, char *trigger_key) { @@ -2497,6 +2539,8 @@ static int mdss_panel_parse_dt(struct device_node *np, rc = of_property_read_u32(np, "qcom,mdss-mdp-transfer-time-us", &tmp); pinfo->mdp_transfer_time_us = (!rc ? tmp : DEFAULT_MDP_TRANSFER_TIME); + mdss_dsi_parse_mdp_kickoff_threshold(np, pinfo); + pinfo->mipi.lp11_init = of_property_read_bool(np, "qcom,mdss-dsi-lp11-init"); rc = of_property_read_u32(np, "qcom,mdss-dsi-init-delay-us", &tmp); diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c index 72d6175686b7..4eb121f01aca 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c @@ -73,6 +73,7 @@ struct mdss_mdp_cmd_ctx { struct mutex clk_mtx; spinlock_t clk_lock; spinlock_t koff_lock; + spinlock_t ctlstart_lock; struct work_struct gate_clk_work; struct delayed_work delayed_off_clk_work; struct work_struct pp_done_work; @@ -144,15 +145,11 @@ static inline u32 mdss_mdp_cmd_line_count(struct mdss_mdp_ctl *ctl) u32 init; u32 height; - mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); - mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_LEFT); if (!mixer) { mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_RIGHT); - if (!mixer) { - mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); + if (!mixer) goto exit; - } } init = mdss_mdp_pingpong_read(mixer->pingpong_base, @@ -160,10 +157,8 @@ static inline u32 mdss_mdp_cmd_line_count(struct mdss_mdp_ctl *ctl) height = mdss_mdp_pingpong_read(mixer->pingpong_base, MDSS_MDP_REG_PP_SYNC_CONFIG_HEIGHT) & 0xffff; - if (height < init) { - mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); + if (height < init) goto exit; - } cnt = mdss_mdp_pingpong_read(mixer->pingpong_base, MDSS_MDP_REG_PP_INT_COUNT_VAL) & 0xffff; @@ -173,13 +168,21 @@ static inline u32 mdss_mdp_cmd_line_count(struct mdss_mdp_ctl *ctl) else cnt -= init; - mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); - pr_debug("cnt=%d init=%d height=%d\n", cnt, init, height); exit: return cnt; } +static inline u32 mdss_mdp_cmd_line_count_wrapper(struct mdss_mdp_ctl *ctl) +{ + u32 ret; + + mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); + ret = mdss_mdp_cmd_line_count(ctl); + mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); + return ret; +} + static int mdss_mdp_tearcheck_enable(struct mdss_mdp_ctl *ctl, bool enable) { struct mdss_data_type *mdata = mdss_mdp_get_mdata(); @@ -2677,12 +2680,42 @@ static int mdss_mdp_disable_autorefresh(struct mdss_mdp_ctl *ctl, return 0; } +static bool wait_for_read_ptr_if_late(struct mdss_mdp_ctl *ctl, + struct mdss_mdp_ctl *sctl, struct mdss_panel_info *pinfo) +{ + u32 line_count; + u32 sline_count = 0; + bool ret = true; + u32 low_threshold = pinfo->mdp_koff_thshold_low; + u32 high_threshold = pinfo->mdp_koff_thshold_high; + + /* read the line count */ + line_count = mdss_mdp_cmd_line_count(ctl); + if (sctl) + sline_count = mdss_mdp_cmd_line_count(sctl); + + /* if line count is between the range, return to trigger transfer */ + if (((line_count > low_threshold) && (line_count < high_threshold)) && + (!sctl || ((sline_count > low_threshold) && + (sline_count < high_threshold)))) + ret = false; + + pr_debug("threshold:[%d, %d]\n", low_threshold, high_threshold); + pr_debug("line:%d sline:%d ret:%d\n", line_count, sline_count, ret); + MDSS_XLOG(line_count, sline_count, ret); + + return ret; +} static void __mdss_mdp_kickoff(struct mdss_mdp_ctl *ctl, - struct mdss_mdp_cmd_ctx *ctx) + struct mdss_mdp_ctl *sctl, struct mdss_mdp_cmd_ctx *ctx) { struct mdss_data_type *mdata = mdss_mdp_get_mdata(); bool is_pp_split = is_pingpong_split(ctl->mfd); + struct mdss_panel_info *pinfo = NULL; + + if (ctl->panel_data) + pinfo = &ctl->panel_data->panel_info; MDSS_XLOG(ctx->autorefresh_state); @@ -2707,9 +2740,33 @@ static void __mdss_mdp_kickoff(struct mdss_mdp_ctl *ctl, ctx->autorefresh_state = MDP_AUTOREFRESH_ON; } else { + + /* + * Some panels can require that mdp is within some range + * of the scanlines in order to trigger the tansfer. + * If that is the case, make sure the panel scanline + * is within the limit to start. + * Acquire an spinlock for this operation to raise the + * priority of this thread and make sure the context + * is maintained, so we can have the less time possible + * between the check of the scanline and the kickoff. + */ + if (pinfo && pinfo->mdp_koff_thshold) { + spin_lock(&ctx->ctlstart_lock); + if (wait_for_read_ptr_if_late(ctl, sctl, pinfo)) { + spin_unlock(&ctx->ctlstart_lock); + usleep_range(pinfo->mdp_koff_delay, + pinfo->mdp_koff_delay + 10); + spin_lock(&ctx->ctlstart_lock); + } + } + /* SW Kickoff */ mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_START, 1); MDSS_XLOG(0x11, ctx->autorefresh_state); + + if (pinfo && pinfo->mdp_koff_thshold) + spin_unlock(&ctx->ctlstart_lock); } } @@ -2841,7 +2898,7 @@ static int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg) } /* Kickoff */ - __mdss_mdp_kickoff(ctl, ctx); + __mdss_mdp_kickoff(ctl, sctl, ctx); mdss_mdp_cmd_post_programming(ctl); @@ -3267,6 +3324,7 @@ static int mdss_mdp_cmd_ctx_setup(struct mdss_mdp_ctl *ctl, init_completion(&ctx->autorefresh_done); spin_lock_init(&ctx->clk_lock); spin_lock_init(&ctx->koff_lock); + spin_lock_init(&ctx->ctlstart_lock); mutex_init(&ctx->clk_mtx); mutex_init(&ctx->mdp_rdptr_lock); mutex_init(&ctx->mdp_wrptr_lock); @@ -3557,7 +3615,7 @@ int mdss_mdp_cmd_start(struct mdss_mdp_ctl *ctl) ctl->ops.wait_pingpong = mdss_mdp_cmd_wait4pingpong; ctl->ops.add_vsync_handler = mdss_mdp_cmd_add_vsync_handler; ctl->ops.remove_vsync_handler = mdss_mdp_cmd_remove_vsync_handler; - ctl->ops.read_line_cnt_fnc = mdss_mdp_cmd_line_count; + ctl->ops.read_line_cnt_fnc = mdss_mdp_cmd_line_count_wrapper; ctl->ops.restore_fnc = mdss_mdp_cmd_restore; ctl->ops.early_wake_up_fnc = mdss_mdp_cmd_early_wake_up; ctl->ops.reconfigure = mdss_mdp_cmd_reconfigure; diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index a633528b5373..463d26643dde 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -635,6 +635,10 @@ struct mdss_panel_info { u32 saved_fporch; /* current fps, once is programmed in hw */ int current_fps; + u32 mdp_koff_thshold_low; + u32 mdp_koff_thshold_high; + bool mdp_koff_thshold; + u32 mdp_koff_delay; int panel_max_fps; int panel_max_vtotal; |
