forked from rubenslte/android_kernel_samsung_msm8226
Merge "msm: mdss: expose mdss tearing check parameters"
This commit is contained in:
committed by
Gerrit - the friendly Code Review server
commit
1d19332f16
@@ -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>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user