diff options
| author | Huaibin Yang <huaibiny@codeaurora.org> | 2013-07-16 17:01:44 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:21:01 -0700 |
| commit | 883f81b408fb8ee8ce4d424150d3befee99c8282 (patch) | |
| tree | d3d13d59b15c50f903f0f1442aaaa7cc2f0efa2f /drivers/video/fbdev/msm | |
| parent | b27d139526f86f2315bd80a6bb44c5b2ea5cb96a (diff) | |
msm: mdss: expose mdss tearing check parameters
Tearing may happen for command mode panels when data transfer from mdp
to panel is not synced with panel's own update. These panel dependent
mdp parameters are used by mdp h/w logic to avoid tearing, so they can
be tuned through device tree settings for different panels.
CRs-fixed: 514910
Change-Id: Ibe9e27233692f8e50f36ce3b8be521a4d0097146
Signed-off-by: Huaibin Yang <huaibiny@codeaurora.org>
Diffstat (limited to 'drivers/video/fbdev/msm')
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi_panel.c | 37 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c | 147 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_panel.h | 13 |
3 files changed, 114 insertions, 83 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c index 4ec1b8b13c85..5f746722400d 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_panel.c +++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c @@ -499,6 +499,41 @@ static int mdss_dsi_parse_fbc_params(struct device_node *np, return 0; } +static void mdss_panel_parse_te_params(struct device_node *np, + struct mdss_panel_info *panel_info) +{ + + u32 tmp; + int rc = 0; + /* + * TE default: dsi byte clock calculated base on 70 fps; + * around 14 ms to complete a kickoff cycle if te disabled; + * vclk_line base on 60 fps; write is faster than read; + * init == start == rdptr; + */ + panel_info->te.tear_check_en = + !of_property_read_bool(np, "qcom,mdss-tear-check-disable"); + rc = of_property_read_u32 + (np, "qcom,mdss-tear-check-sync-cfg-height", &tmp); + panel_info->te.sync_cfg_height = (!rc ? tmp : 0xfff0); + rc = of_property_read_u32 + (np, "qcom,mdss-tear-check-sync-init-val", &tmp); + panel_info->te.vsync_init_val = (!rc ? tmp : panel_info->yres); + rc = of_property_read_u32 + (np, "qcom,mdss-tear-check-sync-threshold-start", &tmp); + panel_info->te.sync_threshold_start = (!rc ? tmp : 4); + rc = of_property_read_u32 + (np, "qcom,mdss-tear-check-sync-threshold-continue", &tmp); + panel_info->te.sync_threshold_continue = (!rc ? tmp : 4); + rc = of_property_read_u32(np, "qcom,mdss-tear-check-start-pos", &tmp); + panel_info->te.start_pos = (!rc ? tmp : panel_info->yres); + rc = of_property_read_u32 + (np, "qcom,mdss-tear-check-rd-ptr-trigger-intr", &tmp); + panel_info->te.rd_ptr_irq = (!rc ? tmp : panel_info->yres + 1); + rc = of_property_read_u32(np, "qcom,mdss-tear-check-frame-rate", &tmp); + panel_info->te.refx100 = (!rc ? tmp : 6000); +} + static int mdss_panel_parse_dt(struct device_node *np, struct mdss_dsi_ctrl_pdata *ctrl_pdata) @@ -748,6 +783,8 @@ static int mdss_panel_parse_dt(struct device_node *np, mdss_dsi_parse_fbc_params(np, pinfo); + mdss_panel_parse_te_params(np, pinfo); + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->on_cmds, "qcom,mdss-dsi-on-command", "qcom,mdss-dsi-on-command-state"); diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c index 6a5917b106fb..fc2041e671a6 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c @@ -18,9 +18,6 @@ #define VSYNC_EXPIRE_TICK 4 -#define START_THRESHOLD 4 -#define CONTINUE_THRESHOLD 4 - #define MAX_SESSIONS 2 /* wait for at most 2 vsync for lowest refresh rate (24hz) */ @@ -43,13 +40,6 @@ struct mdss_mdp_cmd_ctx { struct mutex clk_mtx; spinlock_t clk_lock; struct work_struct clk_work; - - /* te config */ - u8 tear_check; - u16 height; /* panel height */ - u16 vporch; /* vertical porches */ - u16 start_threshold; - u32 vclk_line; /* vsync clock per line */ }; struct mdss_mdp_cmd_ctx mdss_mdp_cmd_ctx_list[MAX_SESSIONS]; @@ -98,98 +88,88 @@ exit: return cnt; } -/* - * TE configuration: - * dsi byte clock calculated base on 70 fps - * around 14 ms to complete a kickoff cycle if te disabled - * vclk_line base on 60 fps - * write is faster than read - * init == start == rdptr - */ -static int mdss_mdp_cmd_tearcheck_cfg(struct mdss_mdp_mixer *mixer, - struct mdss_mdp_cmd_ctx *ctx, int enable) -{ - u32 cfg; - - cfg = BIT(19); /* VSYNC_COUNTER_EN */ - if (ctx->tear_check) - cfg |= BIT(20); /* VSYNC_IN_EN */ - cfg |= ctx->vclk_line; - - mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC, cfg); - mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_SYNC_CONFIG_HEIGHT, - 0xfff0); /* set to verh height */ - - mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_VSYNC_INIT_VAL, - ctx->height); - - mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_RD_PTR_IRQ, - ctx->height + 1); - - mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_START_POS, - ctx->height); - - mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_SYNC_THRESH, - (CONTINUE_THRESHOLD << 16) | (ctx->start_threshold)); - - mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_TEAR_CHECK_EN, enable); - return 0; -} -static int mdss_mdp_cmd_tearcheck_setup(struct mdss_mdp_ctl *ctl, int enable) +static int mdss_mdp_cmd_tearcheck_cfg(struct mdss_mdp_ctl *ctl, + struct mdss_mdp_mixer *mixer) { - struct mdss_mdp_cmd_ctx *ctx = ctl->priv_data; + struct mdss_mdp_pp_tear_check *te; struct mdss_panel_info *pinfo; - struct mdss_mdp_mixer *mixer; + u32 vsync_clk_speed_hz, total_lines, vclks_line, cfg; - pinfo = &ctl->panel_data->panel_info; + if (IS_ERR_OR_NULL(ctl->panel_data)) { + pr_err("no panel data\n"); + return -ENODEV; + } - if (pinfo->mipi.vsync_enable && enable) { - u32 mdp_vsync_clk_speed_hz, total_lines; + pinfo = &ctl->panel_data->panel_info; + te = &ctl->panel_data->panel_info.te; - mdss_mdp_vsync_clk_enable(1); + mdss_mdp_vsync_clk_enable(1); - mdp_vsync_clk_speed_hz = + vsync_clk_speed_hz = mdss_mdp_get_clk_rate(MDSS_CLK_MDP_VSYNC); - pr_debug("%s: vsync_clk_rate=%d\n", __func__, - mdp_vsync_clk_speed_hz); - if (mdp_vsync_clk_speed_hz == 0) { - pr_err("can't get clk speed\n"); - return -EINVAL; - } + total_lines = mdss_panel_get_vtotal(pinfo); - ctx->tear_check = pinfo->mipi.hw_vsync_mode; - ctx->height = pinfo->yres; - ctx->vporch = pinfo->lcdc.v_back_porch + - pinfo->lcdc.v_front_porch + - pinfo->lcdc.v_pulse_width; + total_lines *= pinfo->mipi.frame_rate; - ctx->start_threshold = START_THRESHOLD; + vclks_line = (total_lines) ? vsync_clk_speed_hz / total_lines : 0; - total_lines = ctx->height + ctx->vporch; - total_lines *= pinfo->mipi.frame_rate; - ctx->vclk_line = mdp_vsync_clk_speed_hz / total_lines; + cfg = BIT(19); + if (pinfo->mipi.hw_vsync_mode) + cfg |= BIT(20); - pr_debug("%s: fr=%d tline=%d vcnt=%d thold=%d vrate=%d\n", - __func__, pinfo->mipi.frame_rate, total_lines, - ctx->vclk_line, ctx->start_threshold, - mdp_vsync_clk_speed_hz); - } else { - enable = 0; + if (te->refx100) + vclks_line = vclks_line * pinfo->mipi.frame_rate * + 100 / te->refx100; + else { + pr_warn("refx100 cannot be zero! Use 6000 as default\n"); + vclks_line = vclks_line * pinfo->mipi.frame_rate * + 100 / 6000; } - mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_LEFT); - if (mixer) - mdss_mdp_cmd_tearcheck_cfg(mixer, ctx, enable); + cfg |= vclks_line; - mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_RIGHT); - if (mixer) - mdss_mdp_cmd_tearcheck_cfg(mixer, ctx, enable); + pr_debug("%s: yres=%d vclks=%x height=%d init=%d rd=%d start=%d ", + __func__, pinfo->yres, vclks_line, te->sync_cfg_height, + te->vsync_init_val, te->rd_ptr_irq, te->start_pos); + pr_debug("thrd_start =%d thrd_cont=%d\n", + te->sync_threshold_start, te->sync_threshold_continue); + mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC, cfg); + mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_SYNC_CONFIG_HEIGHT, + te->sync_cfg_height); + mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_VSYNC_INIT_VAL, + te->vsync_init_val); + mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_RD_PTR_IRQ, + te->rd_ptr_irq); + mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_START_POS, + te->start_pos); + mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_SYNC_THRESH, + ((te->sync_threshold_continue << 16) | + te->sync_threshold_start)); + mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_TEAR_CHECK_EN, + te->tear_check_en); return 0; } +static int mdss_mdp_cmd_tearcheck_setup(struct mdss_mdp_ctl *ctl) +{ + struct mdss_mdp_mixer *mixer; + int rc = 0; + mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_LEFT); + if (mixer) { + rc = mdss_mdp_cmd_tearcheck_cfg(ctl, mixer); + if (rc) + goto err; + } + mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_RIGHT); + if (mixer) + rc = mdss_mdp_cmd_tearcheck_cfg(ctl, mixer); + err: + return rc; +} + static inline void mdss_mdp_cmd_clk_on(struct mdss_mdp_cmd_ctx *ctx) { unsigned long flags; @@ -557,7 +537,8 @@ int mdss_mdp_cmd_start(struct mdss_mdp_ctl *ctl) mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num, mdss_mdp_cmd_pingpong_done, ctl); - ret = mdss_mdp_cmd_tearcheck_setup(ctl, 1); + ret = mdss_mdp_cmd_tearcheck_setup(ctl); + if (ret) { pr_err("tearcheck setup failed\n"); return ret; diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index 72bb6584a4f8..9dd861975d0d 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -252,6 +252,17 @@ struct fbc_panel_info { u32 lossy_mode_idx; }; +struct mdss_mdp_pp_tear_check { + u32 tear_check_en; + u32 sync_cfg_height; + u32 vsync_init_val; + u32 sync_threshold_start; + u32 sync_threshold_continue; + u32 start_pos; + u32 rd_ptr_irq; + u32 refx100; +}; + struct mdss_panel_info { u32 xres; u32 yres; @@ -284,6 +295,8 @@ struct mdss_panel_info { struct ion_handle *splash_ihdl; u32 panel_power_on; + struct mdss_mdp_pp_tear_check te; + struct lcd_panel_info lcdc; struct fbc_panel_info fbc; struct mipi_panel_info mipi; |
