diff --git a/msm/sde/sde_encoder_phys_cmd.c b/msm/sde/sde_encoder_phys_cmd.c index 42e8a0f39a..3d88099564 100644 --- a/msm/sde/sde_encoder_phys_cmd.c +++ b/msm/sde/sde_encoder_phys_cmd.c @@ -384,7 +384,8 @@ static void sde_encoder_phys_cmd_wr_ptr_irq(void *arg, int irq_idx) info[0].pp_idx, info[0].intf_idx, info[0].wr_ptr_line_count, info[1].pp_idx, info[1].intf_idx, info[1].wr_ptr_line_count, qsync_mode); - if (qsync_mode) + if (qsync_mode && + !test_bit(SDE_INTF_TE_SINGLE_UPDATE, &phys_enc->hw_intf->cap->features)) sde_encoder_override_tearcheck_rd_ptr(phys_enc); /* Signal any waiting wr_ptr start interrupt */ @@ -1904,12 +1905,16 @@ static void _sde_encoder_autorefresh_disable_seq2( autorefresh_status = hw_mdp->ops.get_autorefresh_status(hw_mdp, phys_enc->intf_idx); hw_intf->ops.check_and_reset_tearcheck(hw_intf, &tear_status); - pr_err("enc:%d autofresh status:0x%x intf:%d tear_read:0x%x tear_write:0x%x\n", - DRMID(phys_enc->parent), autorefresh_status, phys_enc->intf_idx - INTF_0, - tear_status.read_count, tear_status.write_count); - SDE_EVT32(DRMID(phys_enc->parent), phys_enc->intf_idx - INTF_0, - autorefresh_status, tear_status.read_count, - tear_status.write_count); + pr_err("enc:%d autofresh status:0x%x intf:%d\n", + DRMID(phys_enc->parent), autorefresh_status, + phys_enc->intf_idx - INTF_0); + pr_err("tear_read_frame_count:%d tear_read_line_count:%d\n", + tear_status.read_frame_count, tear_status.read_line_count); + pr_err("tear_write_frame_count:%d tear_write_line_count:%d\n", + tear_status.write_frame_count, tear_status.write_line_count); + SDE_EVT32(DRMID(phys_enc->parent), phys_enc->intf_idx - INTF_0, autorefresh_status, + tear_status.read_frame_count, tear_status.read_line_count, + tear_status.write_frame_count, tear_status.write_line_count); } } static void _sde_encoder_phys_disable_autorefresh(struct sde_encoder_phys *phys_enc) diff --git a/msm/sde/sde_hw_catalog.c b/msm/sde/sde_hw_catalog.c index 2085a96d0f..ef6e7f6800 100644 --- a/msm/sde/sde_hw_catalog.c +++ b/msm/sde/sde_hw_catalog.c @@ -2381,8 +2381,11 @@ static int sde_intf_parse_dt(struct device_node *np, set_bit(SDE_INTF_WD_JITTER, &intf->features); } - if (SDE_HW_MAJOR(sde_cfg->hw_rev) >= SDE_HW_MAJOR(SDE_HW_VER_A00)) + if (SDE_HW_MAJOR(sde_cfg->hw_rev) >= SDE_HW_MAJOR(SDE_HW_VER_A00)) { set_bit(SDE_INTF_MDP_VSYNC_FC, &intf->features); + set_bit(SDE_INTF_TE_32BIT, &intf->features); + set_bit(SDE_INTF_TE_SINGLE_UPDATE, &intf->features); + } } end: diff --git a/msm/sde/sde_hw_catalog.h b/msm/sde/sde_hw_catalog.h index 2ae9ed78f7..24b55274d7 100644 --- a/msm/sde/sde_hw_catalog.h +++ b/msm/sde/sde_hw_catalog.h @@ -579,6 +579,8 @@ enum { * pixel data arrives to this INTF * @SDE_INTF_TE INTF block has TE configuration support * @SDE_INTF_TE_ALIGN_VSYNC INTF block has POMS Align vsync support + * @SDE_INTF_TE_32BIT INTF block has 32bit TE configuration support + * @SDE_INTF_TE_SINGLE_UPDATE INTF block has single frame per TE support * @SDE_INTF_WD_TIMER INTF block has WD Timer support * @SDE_INTF_STATUS INTF block has INTF_STATUS register * @SDE_INTF_RESET_COUNTER INTF block has frame/line counter reset support @@ -593,6 +595,8 @@ enum { SDE_INTF_INPUT_CTRL = 0x1, SDE_INTF_TE, SDE_INTF_TE_ALIGN_VSYNC, + SDE_INTF_TE_32BIT, + SDE_INTF_TE_SINGLE_UPDATE, SDE_INTF_WD_TIMER, SDE_INTF_STATUS, SDE_INTF_RESET_COUNTER, diff --git a/msm/sde/sde_hw_intf.c b/msm/sde/sde_hw_intf.c index e6c5915220..bb2ab03ba2 100644 --- a/msm/sde/sde_hw_intf.c +++ b/msm/sde/sde_hw_intf.c @@ -98,6 +98,12 @@ #define INTF_TEAR_LINE_COUNT 0x2B0 #define INTF_TEAR_AUTOREFRESH_CONFIG 0x2B4 #define INTF_TEAR_TEAR_DETECT_CTRL 0x2B8 +#define INTF_TEAR_PROG_FETCH_START 0x2C4 +#define INTF_TEAR_DSI_DMA_SCHD_CTRL0 0x2C8 +#define INTF_TEAR_DSI_DMA_SCHD_CTRL1 0x2CC +#define INTF_TEAR_INT_COUNT_VAL_EXT 0x2DC +#define INTF_TEAR_SYNC_THRESH_EXT 0x2E0 +#define INTF_TEAR_SYNC_WRCOUNT_EXT 0x2E4 static struct sde_intf_cfg *_intf_offset(enum sde_intf intf, struct sde_mdss_cfg *m, @@ -678,7 +684,7 @@ static int sde_hw_intf_setup_te_config(struct sde_hw_intf *intf, struct sde_hw_tear_check *te) { struct sde_hw_blk_reg_map *c; - u32 cfg = 0; + u32 cfg = 0, val; spinlock_t tearcheck_spinlock; if (!intf) @@ -698,8 +704,10 @@ static int sde_hw_intf_setup_te_config(struct sde_hw_intf *intf, * less than 2^16 vsync clk cycles. */ spin_lock(&tearcheck_spinlock); - SDE_REG_WRITE(c, INTF_TEAR_SYNC_WRCOUNT, - (te->start_pos + te->sync_threshold_start + 1)); + val = te->start_pos + te->sync_threshold_start + 1; + if (intf->cap->features & BIT(SDE_INTF_TE_32BIT)) + SDE_REG_WRITE(c, INTF_TEAR_SYNC_WRCOUNT_EXT, (val >> 16)); + SDE_REG_WRITE(c, INTF_TEAR_SYNC_WRCOUNT, (val & 0xffff)); SDE_REG_WRITE(c, INTF_TEAR_SYNC_CONFIG_VSYNC, cfg); wmb(); /* disable vsync counter before updating single buffer registers */ SDE_REG_WRITE(c, INTF_TEAR_SYNC_CONFIG_HEIGHT, te->sync_cfg_height); @@ -707,9 +715,13 @@ static int sde_hw_intf_setup_te_config(struct sde_hw_intf *intf, SDE_REG_WRITE(c, INTF_TEAR_RD_PTR_IRQ, te->rd_ptr_irq); SDE_REG_WRITE(c, INTF_TEAR_WR_PTR_IRQ, te->wr_ptr_irq); SDE_REG_WRITE(c, INTF_TEAR_START_POS, te->start_pos); + if (intf->cap->features & BIT(SDE_INTF_TE_32BIT)) + SDE_REG_WRITE(c, INTF_TEAR_SYNC_THRESH_EXT, + ((te->sync_threshold_continue & 0xffff0000) | + (te->sync_threshold_start >> 16))); SDE_REG_WRITE(c, INTF_TEAR_SYNC_THRESH, ((te->sync_threshold_continue << 16) | - te->sync_threshold_start)); + (te->sync_threshold_start & 0xffff))); cfg |= BIT(19); /* VSYNC_COUNTER_EN */ SDE_REG_WRITE(c, INTF_TEAR_SYNC_CONFIG_VSYNC, cfg); spin_unlock(&tearcheck_spinlock); @@ -760,25 +772,38 @@ static int sde_hw_intf_poll_timeout_wr_ptr(struct sde_hw_intf *intf, u32 timeout_us) { struct sde_hw_blk_reg_map *c; - u32 val; + u32 val, mask = 0; if (!intf) return -EINVAL; + if (intf->cap->features & BIT(SDE_INTF_TE_32BIT)) + mask = 0xffffffff; + else + mask = 0xffff; + c = &intf->hw; - return read_poll_timeout(sde_reg_read, val, (val & 0xffff) >= 1, 10, false, timeout_us, + return read_poll_timeout(sde_reg_read, val, (val & mask) >= 1, 10, false, timeout_us, c, INTF_TEAR_LINE_COUNT); } static int sde_hw_intf_enable_te(struct sde_hw_intf *intf, bool enable) { struct sde_hw_blk_reg_map *c; + uint32_t val = 0; if (!intf) return -EINVAL; c = &intf->hw; - SDE_REG_WRITE(c, INTF_TEAR_TEAR_CHECK_EN, enable); + + if (enable) + val |= BIT(0); + + if (intf->cap->features & BIT(SDE_INTF_TE_SINGLE_UPDATE)) + val |= BIT(3); + + SDE_REG_WRITE(c, INTF_TEAR_TEAR_CHECK_EN, val); if (enable && (intf->cap->features & (BIT(SDE_INTF_PANEL_VSYNC_TS) | BIT(SDE_INTF_MDP_VSYNC_TS)))) SDE_REG_WRITE(c, INTF_VSYNC_TIMESTAMP_CTRL, BIT(0)); @@ -836,14 +861,22 @@ static int sde_hw_intf_get_vsync_info(struct sde_hw_intf *intf, c = &intf->hw; val = SDE_REG_READ(c, INTF_TEAR_VSYNC_INIT_VAL); - info->rd_ptr_init_val = val & 0xffff; + if (intf->cap->features & BIT(SDE_INTF_TE_32BIT)) + info->rd_ptr_init_val = val; + else + info->rd_ptr_init_val = val & 0xffff; val = SDE_REG_READ(c, INTF_TEAR_INT_COUNT_VAL); info->rd_ptr_frame_count = (val & 0xffff0000) >> 16; info->rd_ptr_line_count = val & 0xffff; + if (intf->cap->features & BIT(SDE_INTF_TE_32BIT)) { + val = SDE_REG_READ(c, INTF_TEAR_INT_COUNT_VAL_EXT); + info->rd_ptr_line_count |= (val << 16); + } + val = SDE_REG_READ(c, INTF_TEAR_LINE_COUNT); - info->wr_ptr_line_count = val & 0xffff; + info->wr_ptr_line_count = val; val = sde_hw_intf_get_frame_count(intf); info->intf_frame_count = val; @@ -855,19 +888,28 @@ static int sde_hw_intf_v1_check_and_reset_tearcheck(struct sde_hw_intf *intf, struct intf_tear_status *status) { struct sde_hw_blk_reg_map *c = &intf->hw; - u32 start_pos; + u32 start_pos, val; if (!intf || !status) return -EINVAL; c = &intf->hw; - status->read_count = SDE_REG_READ(c, INTF_TEAR_INT_COUNT_VAL); + status->read_line_count = SDE_REG_READ(c, INTF_TEAR_INT_COUNT_VAL); + if (intf->cap->features & BIT(SDE_INTF_TE_32BIT)) + status->read_line_count |= (SDE_REG_READ(c, INTF_TEAR_INT_COUNT_VAL_EXT) << 16); start_pos = SDE_REG_READ(c, INTF_TEAR_START_POS); - status->write_count = SDE_REG_READ(c, INTF_TEAR_SYNC_WRCOUNT); - status->write_count &= 0xffff0000; - status->write_count |= start_pos; - SDE_REG_WRITE(c, INTF_TEAR_SYNC_WRCOUNT, status->write_count); + val = SDE_REG_READ(c, INTF_TEAR_SYNC_WRCOUNT); + status->write_frame_count = val >> 16; + status->write_line_count = start_pos; + + if (intf->cap->features & BIT(SDE_INTF_TE_32BIT)) { + val = (status->write_line_count & 0xffff0000) >> 16; + SDE_REG_WRITE(c, INTF_TEAR_SYNC_WRCOUNT_EXT, val); + } + + val = (status->write_frame_count << 16) | (status->write_line_count & 0xffff); + SDE_REG_WRITE(c, INTF_TEAR_SYNC_WRCOUNT, val); return 0; } diff --git a/msm/sde/sde_hw_intf.h b/msm/sde/sde_hw_intf.h index f33ac1dc5e..698832126e 100644 --- a/msm/sde/sde_hw_intf.h +++ b/msm/sde/sde_hw_intf.h @@ -56,8 +56,10 @@ struct intf_status { }; struct intf_tear_status { - u32 read_count; /* frame & line count for tear init value */ - u32 write_count; /* frame & line count for tear write */ + u32 read_frame_count; /* frame count for tear init value */ + u32 read_line_count; /* line count for tear init value */ + u32 write_frame_count; /* frame count for tear write */ + u32 write_line_count; /* line count for tear write */ }; struct intf_avr_params {