Merge "msm: mdss: expose mdss tearing check parameters"

This commit is contained in:
Linux Build Service Account
2014-04-25 15:16:25 -07:00
committed by Gerrit - the friendly Code Review server
4 changed files with 153 additions and 79 deletions
@@ -257,6 +257,37 @@ Optional properties:
- qcom,mdss-dsi-rx-eot-ignore: Boolean used to enable ignoring end of transmission packets.
- qcom,mdss-dsi-tx-eot-append: Boolean used to enable appending end of transmission packets.
- qcom,ulps-enabled: Boolean to enable support for Ultra Low Power State (ULPS) mode.
- qcom,mdss-tear-check-disable: Boolean to disable mdp tear check. Tear check is enabled by default to avoid
tearing. Other tear-check properties are ignored if this property is present.
The below tear check configuration properties can be individually tuned if
tear check is enabled.
- qcom,mdss-tear-check-sync-cfg-height: Specifies the vertical total number of lines.
The default value is 0xfff0.
- qcom,mdss-tear-check-sync-init-val: Specifies the init value at which the read pointer gets loaded
at vsync edge. The reader pointer refers to the line number of
panel buffer that is currently being updated.
The default value is panel height.
- qcom,mdss-tear-check-sync-threshold-start:
Allows the first ROI line write to an panel when read pointer is
between the range of ROI start line and ROI start line plus this
setting.
The default value is 4.
- qcom,mdss-tear-check-sync-threshold-continue:
The minimum number of lines the write pointer needs to be
above the read pointer so that it is safe to write to the panel.
(This check is not done for the first ROI line write of an update)
The default value is 4.
- qcom,mdss-tear-check-start-pos: Specify the y position from which the start_threshold value is
added and write is kicked off if the read pointer falls within that
region.
The default value is panel height.
- qcom,mdss-tear-check-rd-ptr-trigger-intr:
Specify the read pointer value at which an interrupt has to be
generated.
The default value is panel height + 1.
- qcom,mdss-tear-check-frame-rate: Specify the value to be a real frame rate(fps) x 100 factor to tune the
timing of TE simulation with more precision.
The default value is 6000 with 60 fps.
Note, if a given optional qcom,* binding is not present, then the driver will configure
the default values specified.
@@ -354,5 +385,12 @@ Example:
mdss-dsi-rx-eot-ignore;
mdss-dsi-tx-eot-append;
qcom,ulps-enabled;
qcom,mdss-tear-check-sync-cfg-height = <0xfff0>;
qcom,mdss-tear-check-sync-init-val = <1280>;
qcom,mdss-tear-check-sync-threshold-start = <4>;
qcom,mdss-tear-check-sync-threshold-continue = <4>;
qcom,mdss-tear-check-start-pos = <1280>;
qcom,mdss-tear-check-rd-ptr-trigger-intr = <1281>;
qcom,mdss-tear-check-frame-rate = <6000>;
};
};
+36
View File
@@ -664,6 +664,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_dsi_parse_reset_seq(struct device_node *np,
u32 rst_seq[MDSS_DSI_RST_SEQ_LEN], u32 *rst_len,
@@ -994,6 +1029,7 @@ static int mdss_panel_parse_dt(struct device_node *np,
mdss_dsi_parse_reset_seq(np, pinfo->rst_seq, &(pinfo->rst_seq_len),
"qcom,mdss-dsi-reset-sequence");
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");
+67 -79
View File
@@ -19,9 +19,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) */
@@ -105,96 +102,86 @@ 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;
static int mdss_mdp_cmd_tearcheck_cfg(struct mdss_mdp_ctl *ctl,
struct mdss_mdp_mixer *mixer)
{
struct mdss_mdp_pp_tear_check *te;
struct mdss_panel_info *pinfo;
u32 vsync_clk_speed_hz, total_lines, vclks_line, cfg;
if (IS_ERR_OR_NULL(ctl->panel_data)) {
pr_err("no panel data\n");
return -ENODEV;
}
pinfo = &ctl->panel_data->panel_info;
te = &ctl->panel_data->panel_info.te;
mdss_mdp_vsync_clk_enable(1);
vsync_clk_speed_hz =
mdss_mdp_get_clk_rate(MDSS_CLK_MDP_VSYNC);
total_lines = mdss_panel_get_vtotal(pinfo);
total_lines *= pinfo->mipi.frame_rate;
vclks_line = (total_lines) ? vsync_clk_speed_hz / total_lines : 0;
cfg = BIT(19);
if (pinfo->mipi.hw_vsync_mode)
cfg |= BIT(20);
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;
}
cfg |= vclks_line;
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,
0xfff0); /* set to verh height */
te->sync_cfg_height);
mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_VSYNC_INIT_VAL,
ctx->height);
te->vsync_init_val);
mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_RD_PTR_IRQ,
ctx->height + 1);
te->rd_ptr_irq);
mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_START_POS,
ctx->height);
te->start_pos);
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);
((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, int enable)
static int mdss_mdp_cmd_tearcheck_setup(struct mdss_mdp_ctl *ctl)
{
struct mdss_mdp_cmd_ctx *ctx = ctl->priv_data;
struct mdss_panel_info *pinfo;
struct mdss_mdp_mixer *mixer;
pinfo = &ctl->panel_data->panel_info;
if (pinfo->mipi.vsync_enable && enable) {
u32 mdp_vsync_clk_speed_hz, total_lines;
mdss_mdp_vsync_clk_enable(1);
mdp_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;
}
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;
ctx->start_threshold = START_THRESHOLD;
total_lines = ctx->height + ctx->vporch;
total_lines *= pinfo->mipi.frame_rate;
ctx->vclk_line = mdp_vsync_clk_speed_hz / total_lines;
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;
}
int rc = 0;
mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_LEFT);
if (mixer)
mdss_mdp_cmd_tearcheck_cfg(mixer, ctx, enable);
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)
mdss_mdp_cmd_tearcheck_cfg(mixer, ctx, enable);
return 0;
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)
@@ -216,7 +203,7 @@ static inline void mdss_mdp_cmd_clk_on(struct mdss_mdp_cmd_ctx *ctx)
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
if (ctx->ulps) {
if (mdss_mdp_cmd_tearcheck_setup(ctx->ctl, 1))
if (mdss_mdp_cmd_tearcheck_setup(ctx->ctl))
pr_warn("tearcheck setup failed\n");
mdss_mdp_ctl_intf_event(ctx->ctl,
MDSS_EVENT_DSI_ULPS_CTRL, (void *)0);
@@ -774,7 +761,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;
+12
View File
@@ -274,6 +274,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;
@@ -316,6 +327,7 @@ struct mdss_panel_info {
u32 panel_power_on;
uint32_t panel_dead;
struct mdss_mdp_pp_tear_check te;
struct lcd_panel_info lcdc;
struct fbc_panel_info fbc;