mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
To: Marijn Suijten <marijn.suijten@somainline.org>,
	phone-devel@vger.kernel.org,
	Abhinav Kumar <quic_abhinavk@quicinc.com>,
	Neil Armstrong <neil.armstrong@linaro.org>
Cc: ~postmarketos/upstreaming@lists.sr.ht,
	AngeloGioacchino Del Regno 
	<angelogioacchino.delregno@somainline.org>,
	Konrad Dybcio <konrad.dybcio@linaro.org>,
	Martin Botka <martin.botka@somainline.org>,
	Jami Kettunen <jami.kettunen@somainline.org>,
	Rob Clark <robdclark@gmail.com>, Sean Paul <sean@poorly.run>,
	David Airlie <airlied@gmail.com>, Daniel Vetter <daniel@ffwll.ch>,
	Stephen Boyd <swboyd@chromium.org>, Vinod Koul <vkoul@kernel.org>,
	Bjorn Andersson <andersson@kernel.org>,
	Kuogee Hsieh <quic_khsieh@quicinc.com>,
	Jessica Zhang <quic_jesszhan@quicinc.com>,
	Konrad Dybcio <konrad.dybcio@somainline.org>,
	Loic Poulain <loic.poulain@linaro.org>,
	Vinod Polimera <quic_vpolimer@quicinc.com>,
	Adam Skladowski <a39.skl@gmail.com>,
	linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org,
	freedreno@lists.freedesktop.org, linux-kernel@vger.kernel.org
Subject: Re: [RFC PATCH 6/7] drm/msm/dpu: Implement tearcheck support on INTF block
Date: Sun, 1 Jan 2023 15:32:11 +0200	[thread overview]
Message-ID: <593cae1c-ade3-c68a-25d3-84ba1b968175@linaro.org> (raw)
In-Reply-To: <20221231215006.211860-7-marijn.suijten@somainline.org>

On 31/12/2022 23:50, Marijn Suijten wrote:
> Since DPU 5.0.0 the TEARCHECK registers and interrupts moved out of the
> PINGPONG block and into the INTF.  Implement the necessary callbacks in
> the INTF block, and use these callbacks together with the INTF_TEAR
> interrupts
> 
> Signed-off-by: Marijn Suijten <marijn.suijten@somainline.org>

Generally I have the same question as for the patch 2. Can we have some 
higher level functions in the hw_pp and hw_intf files? Moreover, as I 
review your patch I have the feeling that it would make sense to have to 
two sets of encoder callbacks, one for the hw_pp tearing handling and 
another set for hw_intf-based one.

> ---
>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   |  11 +
>   .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  10 +-
>   .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c  | 113 +++++++---
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c   | 206 ++++++++++++++++++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h   |  29 +++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |   2 +
>   6 files changed, 340 insertions(+), 31 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 9c6817b5a194..8b9070220ab2 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -673,6 +673,7 @@ static void _dpu_encoder_update_vsync_source(struct dpu_encoder_virt *dpu_enc,
>   	struct dpu_kms *dpu_kms;
>   	struct dpu_hw_mdp *hw_mdptop;
>   	struct drm_encoder *drm_enc;
> +	struct dpu_encoder_phys *phys_enc;
>   	int i;
>   
>   	if (!dpu_enc || !disp_info) {
> @@ -703,12 +704,22 @@ static void _dpu_encoder_update_vsync_source(struct dpu_encoder_virt *dpu_enc,
>   			vsync_cfg.ppnumber[i] = dpu_enc->hw_pp[i]->idx;
>   
>   		vsync_cfg.pp_count = dpu_enc->num_phys_encs;
> +		vsync_cfg.frame_rate = drm_mode_vrefresh(&dpu_enc->base.crtc->state->adjusted_mode);
> +
>   		if (disp_info->is_te_using_watchdog_timer)
>   			vsync_cfg.vsync_source = DPU_VSYNC_SOURCE_WD_TIMER_0;
>   		else
>   			vsync_cfg.vsync_source = DPU_VSYNC0_SOURCE_GPIO;
>   
>   		hw_mdptop->ops.setup_vsync_source(hw_mdptop, &vsync_cfg);
> +
> +		for (i = 0; i < dpu_enc->num_phys_encs; i++) {
> +			phys_enc = dpu_enc->phys_encs[i];
> +
> +			if (phys_enc->has_intf_te && phys_enc->hw_intf->ops.vsync_sel)
> +				phys_enc->hw_intf->ops.vsync_sel(phys_enc->hw_intf,
> +						vsync_cfg.vsync_source);
> +		}
>   	}
>   }
>   
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> index f2af07d87f56..47e79401032c 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> @@ -148,10 +148,10 @@ struct dpu_encoder_phys_ops {
>   /**
>    * enum dpu_intr_idx - dpu encoder interrupt index
>    * @INTR_IDX_VSYNC:    Vsync interrupt for video mode panel
> - * @INTR_IDX_PINGPONG: Pingpong done unterrupt for cmd mode panel
> - * @INTR_IDX_UNDERRUN: Underrun unterrupt for video and cmd mode panel
> - * @INTR_IDX_RDPTR:    Readpointer done unterrupt for cmd mode panel
> - * @INTR_IDX_WB_DONE:  Writeback fone interrupt for virtual connector
> + * @INTR_IDX_PINGPONG: Pingpong done interrupt for cmd mode panel
> + * @INTR_IDX_UNDERRUN: Underrun interrupt for video and cmd mode panel
> + * @INTR_IDX_RDPTR:    Readpointer done interrupt for cmd mode panel
> + * @INTR_IDX_WB_DONE:  Writeback done interrupt for virtual connector
>    */
>   enum dpu_intr_idx {
>   	INTR_IDX_VSYNC,
> @@ -195,6 +195,7 @@ enum dpu_intr_idx {
>    *                              pending.
>    * @pending_kickoff_wq:		Wait queue for blocking until kickoff completes
>    * @irq:			IRQ indices
> + * @has_intf_te:		Interface TE configuration support
>    */
>   struct dpu_encoder_phys {
>   	struct drm_encoder *parent;
> @@ -220,6 +221,7 @@ struct dpu_encoder_phys {
>   	atomic_t pending_kickoff_cnt;
>   	wait_queue_head_t pending_kickoff_wq;
>   	int irq[INTR_IDX_MAX];
> +	bool has_intf_te;
>   };
>   
>   static inline int dpu_encoder_phys_inc_pending(struct dpu_encoder_phys *phys)
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
> index 7e5ba52197cd..ca44a8087f01 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
> @@ -100,12 +100,12 @@ static void dpu_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx)
>   	DPU_ATRACE_END("pp_done_irq");
>   }
>   
> -static void dpu_encoder_phys_cmd_pp_rd_ptr_irq(void *arg, int irq_idx)
> +static void dpu_encoder_phys_cmd_te_rd_ptr_irq(void *arg, int irq_idx)
>   {
>   	struct dpu_encoder_phys *phys_enc = arg;
>   	struct dpu_encoder_phys_cmd *cmd_enc;
>   
> -	if (!phys_enc->hw_pp)
> +	if (!phys_enc->hw_pp || !phys_enc->hw_intf)
>   		return;
>   
>   	DPU_ATRACE_BEGIN("rd_ptr_irq");
> @@ -147,11 +147,19 @@ static void dpu_encoder_phys_cmd_atomic_mode_set(
>   		struct drm_crtc_state *crtc_state,
>   		struct drm_connector_state *conn_state)
>   {
> +	if (phys_enc->has_intf_te && !phys_enc->hw_intf) {
> +		DPU_ERROR("invalid intf configuration\n");
> +		return;
> +	}
> +
>   	phys_enc->irq[INTR_IDX_CTL_START] = phys_enc->hw_ctl->caps->intr_start;
>   
>   	phys_enc->irq[INTR_IDX_PINGPONG] = phys_enc->hw_pp->caps->intr_done;
>   
> -	phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_pp->caps->intr_rdptr;
> +	if (phys_enc->has_intf_te)
> +		phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_intf->cap->intr_tear_rd_ptr;
> +	else
> +		phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_pp->caps->intr_rdptr;
>   
>   	phys_enc->irq[INTR_IDX_UNDERRUN] = phys_enc->hw_intf->cap->intr_underrun;
>   }
> @@ -264,7 +272,7 @@ static int dpu_encoder_phys_cmd_control_vblank_irq(
>   	if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1)
>   		ret = dpu_core_irq_register_callback(phys_enc->dpu_kms,
>   				phys_enc->irq[INTR_IDX_RDPTR],
> -				dpu_encoder_phys_cmd_pp_rd_ptr_irq,
> +				dpu_encoder_phys_cmd_te_rd_ptr_irq,
>   				phys_enc);
>   	else if (!enable && atomic_dec_return(&phys_enc->vblank_refcount) == 0)
>   		ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms,
> @@ -336,10 +344,18 @@ static void dpu_encoder_phys_cmd_tearcheck_config(
>   
>   	DPU_DEBUG_CMDENC(cmd_enc, "pp %d\n", phys_enc->hw_pp->idx - PINGPONG_0);
>   
> -	if (!phys_enc->hw_pp->ops.setup_tearcheck ||
> -		!phys_enc->hw_pp->ops.enable_tearcheck) {
> -		DPU_DEBUG_CMDENC(cmd_enc, "tearcheck not supported\n");
> -		return;
> +	if (phys_enc->has_intf_te) {
> +		if (!phys_enc->hw_intf->ops.setup_tearcheck ||
> +			!phys_enc->hw_intf->ops.enable_tearcheck) {
> +			DPU_DEBUG_CMDENC(cmd_enc, "tearcheck not supported\n");
> +			return;
> +		}
> +	} else {
> +		if (!phys_enc->hw_pp->ops.setup_tearcheck ||
> +			!phys_enc->hw_pp->ops.enable_tearcheck) {
> +			DPU_DEBUG_CMDENC(cmd_enc, "tearcheck not supported\n");
> +			return;
> +		}
>   	}
>   
>   	dpu_kms = phys_enc->dpu_kms;
> @@ -392,8 +408,13 @@ static void dpu_encoder_phys_cmd_tearcheck_config(
>   		phys_enc->hw_pp->idx - PINGPONG_0, tc_cfg.sync_cfg_height,
>   		tc_cfg.sync_threshold_start, tc_cfg.sync_threshold_continue);
>   
> -	phys_enc->hw_pp->ops.setup_tearcheck(phys_enc->hw_pp, &tc_cfg);
> -	phys_enc->hw_pp->ops.enable_tearcheck(phys_enc->hw_pp, tc_enable);

A simple random example: setup_tearcheck is always followed with the 
enable_tearcheck. If we merge them, the code would be simpler.

> +	if (phys_enc->has_intf_te) {
> +		phys_enc->hw_intf->ops.setup_tearcheck(phys_enc->hw_intf, &tc_cfg);
> +		phys_enc->hw_intf->ops.enable_tearcheck(phys_enc->hw_intf, tc_enable);
> +	} else {
> +		phys_enc->hw_pp->ops.setup_tearcheck(phys_enc->hw_pp, &tc_cfg);
> +		phys_enc->hw_pp->ops.enable_tearcheck(phys_enc->hw_pp, tc_enable);
> +	}
>   }
>   
>   static void _dpu_encoder_phys_cmd_pingpong_config(
> @@ -470,11 +491,19 @@ static void dpu_encoder_phys_cmd_enable(struct dpu_encoder_phys *phys_enc)
>   static void _dpu_encoder_phys_cmd_connect_te(
>   		struct dpu_encoder_phys *phys_enc, bool enable)
>   {
> -	if (!phys_enc->hw_pp || !phys_enc->hw_pp->ops.connect_external_te)
> -		return;
> +	if (phys_enc->has_intf_te) {
> +		if (!phys_enc->hw_intf || !phys_enc->hw_intf->ops.connect_external_te)
> +			return;
>   
> -	trace_dpu_enc_phys_cmd_connect_te(DRMID(phys_enc->parent), enable);
> -	phys_enc->hw_pp->ops.connect_external_te(phys_enc->hw_pp, enable);
> +		trace_dpu_enc_phys_cmd_connect_te(DRMID(phys_enc->parent), enable);
> +		phys_enc->hw_intf->ops.connect_external_te(phys_enc->hw_intf, enable);
> +	} else {
> +		if (!phys_enc->hw_pp || !phys_enc->hw_pp->ops.connect_external_te)
> +			return;
> +
> +		trace_dpu_enc_phys_cmd_connect_te(DRMID(phys_enc->parent), enable);
> +		phys_enc->hw_pp->ops.connect_external_te(phys_enc->hw_pp, enable);
> +	}
>   }
>   
>   static void dpu_encoder_phys_cmd_prepare_idle_pc(
> @@ -487,6 +516,7 @@ static int dpu_encoder_phys_cmd_get_line_count(
>   		struct dpu_encoder_phys *phys_enc)
>   {
>   	struct dpu_hw_pingpong *hw_pp;
> +	struct dpu_hw_intf *hw_intf;
>   
>   	if (!phys_enc->hw_pp)
>   		return -EINVAL;
> @@ -494,10 +524,16 @@ static int dpu_encoder_phys_cmd_get_line_count(
>   	if (!dpu_encoder_phys_cmd_is_master(phys_enc))
>   		return -EINVAL;
>   
> +	if (phys_enc->has_intf_te) {
> +		hw_intf = phys_enc->hw_intf;
> +		if (!hw_intf->ops.get_line_count)
> +			return -EINVAL;
> +		return hw_intf->ops.get_line_count(hw_intf);
> +	}
> +
>   	hw_pp = phys_enc->hw_pp;
>   	if (!hw_pp->ops.get_line_count)
>   		return -EINVAL;
> -
>   	return hw_pp->ops.get_line_count(hw_pp);
>   }
>   
> @@ -520,7 +556,9 @@ static void dpu_encoder_phys_cmd_disable(struct dpu_encoder_phys *phys_enc)
>   		return;
>   	}
>   
> -	if (phys_enc->hw_pp->ops.enable_tearcheck)
> +	if (phys_enc->has_intf_te && phys_enc->hw_intf->ops.enable_tearcheck)
> +		phys_enc->hw_intf->ops.enable_tearcheck(phys_enc->hw_intf, false);
> +	else if (phys_enc->hw_pp->ops.enable_tearcheck)
>   		phys_enc->hw_pp->ops.enable_tearcheck(phys_enc->hw_pp, false);
>   
>   	if (phys_enc->hw_intf->ops.bind_pingpong_blk) {
> @@ -582,10 +620,19 @@ static bool dpu_encoder_phys_cmd_is_ongoing_pptx(
>   {
>   	struct dpu_hw_pp_vsync_info info;
>   
> -	if (!phys_enc || !phys_enc->hw_pp->ops.get_vsync_info)
> +	if (!phys_enc)
>   		return false;
>   
> -	phys_enc->hw_pp->ops.get_vsync_info(phys_enc->hw_pp, &info);
> +	if (phys_enc->has_intf_te) {
> +		if (!phys_enc->hw_intf->ops.get_vsync_info)
> +			return false;
> +		phys_enc->hw_intf->ops.get_vsync_info(phys_enc->hw_intf, &info);
> +	} else {
> +		if (!phys_enc->hw_pp->ops.get_vsync_info)
> +			return false;
> +		phys_enc->hw_pp->ops.get_vsync_info(phys_enc->hw_pp, &info);
> +	}
> +
>   	if (info.wr_ptr_line_count > 0 &&
>   	    info.wr_ptr_line_count < phys_enc->cached_mode.vdisplay)
>   		return true;
> @@ -602,17 +649,23 @@ static void dpu_encoder_phys_cmd_prepare_commit(
>   
>   	if (!phys_enc)
>   		return;
> -	if (!phys_enc->hw_pp)
> -		return;
>   	if (!dpu_encoder_phys_cmd_is_master(phys_enc))
>   		return;
>   
> -	if (!phys_enc->hw_pp->ops.get_autorefresh || !phys_enc->hw_pp->ops.setup_autorefresh)
> -		return;
> -
>   	/* If autorefresh is already disabled, we have nothing to do */
> -	if (!phys_enc->hw_pp->ops.get_autorefresh(phys_enc->hw_pp, NULL))
> -		return;
> +	if (phys_enc->has_intf_te) {
> +		if (!phys_enc->hw_intf || !phys_enc->hw_intf->ops.get_autorefresh ||
> +				!phys_enc->hw_intf->ops.setup_autorefresh)
> +			return;
> +		if (!phys_enc->hw_intf->ops.get_autorefresh(phys_enc->hw_intf, NULL))
> +			return;
> +	} else {
> +		if (!phys_enc->hw_pp || !phys_enc->hw_pp->ops.get_autorefresh ||
> +				!phys_enc->hw_pp->ops.setup_autorefresh)
> +			return;
> +		if (!phys_enc->hw_pp->ops.get_autorefresh(phys_enc->hw_pp, NULL))
> +			return;
> +	}
>   
>   	/*
>   	 * If autorefresh is enabled, disable it and make sure it is safe to
> @@ -623,7 +676,10 @@ static void dpu_encoder_phys_cmd_prepare_commit(
>   	 * 5. Enable TE back
>   	 */
>   	_dpu_encoder_phys_cmd_connect_te(phys_enc, false);
> -	phys_enc->hw_pp->ops.setup_autorefresh(phys_enc->hw_pp, 0, false);
> +	if (phys_enc->has_intf_te)
> +		phys_enc->hw_intf->ops.setup_autorefresh(phys_enc->hw_intf, 0, false);
> +	else
> +		phys_enc->hw_pp->ops.setup_autorefresh(phys_enc->hw_pp, 0, false);
>   
>   	do {
>   		udelay(DPU_ENC_MAX_POLL_TIMEOUT_US);
> @@ -717,7 +773,7 @@ static int dpu_encoder_phys_cmd_wait_for_vblank(
>   
>   	rc = dpu_encoder_helper_wait_for_irq(phys_enc,
>   			phys_enc->irq[INTR_IDX_RDPTR],
> -			dpu_encoder_phys_cmd_pp_rd_ptr_irq,
> +			dpu_encoder_phys_cmd_te_rd_ptr_irq,
>   			&wait_info);
>   
>   	return rc;
> @@ -793,6 +849,9 @@ struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(
>   	for (i = 0; i < ARRAY_SIZE(phys_enc->irq); i++)
>   		phys_enc->irq[i] = -EINVAL;
>   
> +	phys_enc->has_intf_te = test_bit(DPU_INTF_TE,
> +			&phys_enc->dpu_kms->catalog->intf[p->intf_idx - INTF_0].features);
> +
>   	atomic_set(&phys_enc->vblank_refcount, 0);
>   	atomic_set(&phys_enc->pending_kickoff_cnt, 0);
>   	atomic_set(&phys_enc->pending_ctlstart_cnt, 0);
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> index 7ce66bf3f4c8..42929278df8e 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> @@ -9,6 +9,8 @@
>   #include "dpu_hw_intf.h"
>   #include "dpu_kms.h"
>   
> +#include <linux/iopoll.h>
> +
>   #define INTF_TIMING_ENGINE_EN           0x000
>   #define INTF_CONFIG                     0x004
>   #define INTF_HSYNC_CTL                  0x008
> @@ -62,6 +64,27 @@
>   #define   INTF_LINE_COUNT               0x0B0
>   
>   #define   INTF_MUX                      0x25C
> +#define   INTF_MISR_SIGNATURE           0x184
> +
> +#define INTF_STATUS                     0x26C
> +#define INTF_AVR_CONTROL                0x270
> +#define INTF_AVR_MODE                   0x274
> +#define INTF_AVR_TRIGGER                0x278
> +#define INTF_AVR_VTOTAL                 0x27C
> +#define INTF_TEAR_MDP_VSYNC_SEL         0x280
> +#define INTF_TEAR_TEAR_CHECK_EN         0x284
> +#define INTF_TEAR_SYNC_CONFIG_VSYNC     0x288
> +#define INTF_TEAR_SYNC_CONFIG_HEIGHT    0x28C
> +#define INTF_TEAR_SYNC_WRCOUNT          0x290
> +#define INTF_TEAR_VSYNC_INIT_VAL        0x294
> +#define INTF_TEAR_INT_COUNT_VAL         0x298
> +#define INTF_TEAR_SYNC_THRESH           0x29C
> +#define INTF_TEAR_START_POS             0x2A0
> +#define INTF_TEAR_RD_PTR_IRQ            0x2A4
> +#define INTF_TEAR_WR_PTR_IRQ            0x2A8
> +#define INTF_TEAR_OUT_LINE_COUNT        0x2AC
> +#define INTF_TEAR_LINE_COUNT            0x2B0
> +#define INTF_TEAR_AUTOREFRESH_CONFIG    0x2B4
>   
>   #define INTF_CFG_ACTIVE_H_EN	BIT(29)
>   #define INTF_CFG_ACTIVE_V_EN	BIT(30)
> @@ -309,6 +332,22 @@ static void dpu_hw_intf_get_status(
>   	}
>   }
>   
> +static void dpu_hw_intf_v1_get_status(
> +		struct dpu_hw_intf *intf,
> +		struct intf_status *s)
> +{
> +	struct dpu_hw_blk_reg_map *c = &intf->hw;
> +
> +	s->is_en = DPU_REG_READ(c, INTF_STATUS) & BIT(0);
> +	if (s->is_en) {
> +		s->frame_count = DPU_REG_READ(c, INTF_FRAME_COUNT);
> +		s->line_count = DPU_REG_READ(c, INTF_LINE_COUNT);
> +	} else {
> +		s->line_count = 0;
> +		s->frame_count = 0;
> +	}
> +}
> +
>   static u32 dpu_hw_intf_get_line_count(struct dpu_hw_intf *intf)
>   {
>   	struct dpu_hw_blk_reg_map *c;
> @@ -331,6 +370,161 @@ static int dpu_hw_intf_collect_misr(struct dpu_hw_intf *intf, u32 *misr_value)
>   	return dpu_hw_collect_misr(&intf->hw, INTF_MISR_CTRL, INTF_MISR_SIGNATURE, misr_value);
>   }
>   
> +static int dpu_hw_intf_setup_te_config(struct dpu_hw_intf *intf,
> +		struct dpu_hw_tear_check *te)
> +{
> +	struct dpu_hw_blk_reg_map *c;
> +	int cfg;
> +
> +	if (!intf)
> +		return -EINVAL;
> +
> +	c = &intf->hw;
> +
> +	cfg = BIT(19); /* VSYNC_COUNTER_EN */
> +	if (te->hw_vsync_mode)
> +		cfg |= BIT(20);
> +
> +	cfg |= te->vsync_count;
> +
> +	DPU_REG_WRITE(c, INTF_TEAR_SYNC_CONFIG_VSYNC, cfg);
> +	DPU_REG_WRITE(c, INTF_TEAR_SYNC_CONFIG_HEIGHT, te->sync_cfg_height);
> +	DPU_REG_WRITE(c, INTF_TEAR_VSYNC_INIT_VAL, te->vsync_init_val);
> +	DPU_REG_WRITE(c, INTF_TEAR_RD_PTR_IRQ, te->rd_ptr_irq);
> +	DPU_REG_WRITE(c, INTF_TEAR_START_POS, te->start_pos);
> +	DPU_REG_WRITE(c, INTF_TEAR_SYNC_THRESH,
> +			((te->sync_threshold_continue << 16) |
> +			 te->sync_threshold_start));
> +	DPU_REG_WRITE(c, INTF_TEAR_SYNC_WRCOUNT,
> +			(te->start_pos + te->sync_threshold_start + 1));
> +
> +	return 0;
> +}
> +
> +static void dpu_hw_intf_setup_autorefresh_config(struct dpu_hw_intf *intf,
> +		u32 frame_count, bool enable)
> +{
> +	struct dpu_hw_blk_reg_map *c;
> +	u32 refresh_cfg;
> +
> +	c = &intf->hw;
> +	refresh_cfg = DPU_REG_READ(c, INTF_TEAR_AUTOREFRESH_CONFIG);
> +	if (enable)
> +		refresh_cfg = BIT(31) | frame_count;
> +	else
> +		refresh_cfg &= ~BIT(31);
> +
> +	DPU_REG_WRITE(c, INTF_TEAR_AUTOREFRESH_CONFIG, refresh_cfg);
> +}
> +
> +/*
> + * dpu_hw_intf_get_autorefresh_config - Get autorefresh config from HW
> + * @intf:        DPU intf structure
> + * @frame_count: Used to return the current frame count from hw
> + *
> + * Returns: True if autorefresh enabled, false if disabled.
> + */
> +static bool dpu_hw_intf_get_autorefresh_config(struct dpu_hw_intf *intf,
> +		u32 *frame_count)
> +{
> +	u32 val = DPU_REG_READ(&intf->hw, INTF_TEAR_AUTOREFRESH_CONFIG);
> +
> +	if (frame_count != NULL)
> +		*frame_count = val & 0xffff;
> +	return !!((val & BIT(31)) >> 31);
> +}
> +
> +static int dpu_hw_intf_poll_timeout_wr_ptr(struct dpu_hw_intf *intf,
> +		u32 timeout_us)
> +{
> +	struct dpu_hw_blk_reg_map *c;
> +	u32 val;
> +	int rc;
> +
> +	if (!intf)
> +		return -EINVAL;
> +
> +	c = &intf->hw;
> +	rc = readl_poll_timeout(c->blk_addr + INTF_TEAR_LINE_COUNT,
> +			val, (val & 0xffff) >= 1, 10, timeout_us);
> +
> +	return rc;
> +}
> +
> +static int dpu_hw_intf_enable_te(struct dpu_hw_intf *intf, bool enable)
> +{
> +	struct dpu_hw_blk_reg_map *c;
> +
> +	if (!intf)
> +		return -EINVAL;
> +
> +	c = &intf->hw;
> +	DPU_REG_WRITE(c, INTF_TEAR_TEAR_CHECK_EN, enable);
> +	return 0;
> +}
> +
> +static int dpu_hw_intf_connect_external_te(struct dpu_hw_intf *intf,
> +		bool enable_external_te)
> +{
> +	struct dpu_hw_blk_reg_map *c = &intf->hw;
> +	u32 cfg;
> +	int orig;
> +
> +	if (!intf)
> +		return -EINVAL;
> +
> +	c = &intf->hw;
> +	cfg = DPU_REG_READ(c, INTF_TEAR_SYNC_CONFIG_VSYNC);
> +	orig = (bool)(cfg & BIT(20));
> +	if (enable_external_te)
> +		cfg |= BIT(20);
> +	else
> +		cfg &= ~BIT(20);
> +	DPU_REG_WRITE(c, INTF_TEAR_SYNC_CONFIG_VSYNC, cfg);
> +
> +	return orig;
> +}
> +
> +static int dpu_hw_intf_get_vsync_info(struct dpu_hw_intf *intf,
> +		struct dpu_hw_pp_vsync_info *info)
> +{
> +	struct dpu_hw_blk_reg_map *c = &intf->hw;
> +	u32 val;
> +
> +	if (!intf || !info)
> +		return -EINVAL;
> +
> +	c = &intf->hw;
> +
> +	val = DPU_REG_READ(c, INTF_TEAR_VSYNC_INIT_VAL);
> +	info->rd_ptr_init_val = val & 0xffff;
> +
> +	val = DPU_REG_READ(c, INTF_TEAR_INT_COUNT_VAL);
> +	info->rd_ptr_frame_count = (val & 0xffff0000) >> 16;
> +	info->rd_ptr_line_count = val & 0xffff;
> +
> +	val = DPU_REG_READ(c, INTF_TEAR_LINE_COUNT);
> +	info->wr_ptr_line_count = val & 0xffff;
> +
> +	val = DPU_REG_READ(c, INTF_FRAME_COUNT);
> +	info->intf_frame_count = val;
> +
> +	return 0;
> +}
> +
> +static void dpu_hw_intf_vsync_sel(struct dpu_hw_intf *intf,
> +		u32 vsync_source)
> +{
> +	struct dpu_hw_blk_reg_map *c;
> +
> +	if (!intf)
> +		return;
> +
> +	c = &intf->hw;
> +
> +	DPU_REG_WRITE(c, INTF_TEAR_MDP_VSYNC_SEL, (vsync_source & 0xf));
> +}
> +
>   static void _setup_intf_ops(struct dpu_hw_intf_ops *ops,
>   		unsigned long cap)
>   {
> @@ -343,6 +537,18 @@ static void _setup_intf_ops(struct dpu_hw_intf_ops *ops,
>   		ops->bind_pingpong_blk = dpu_hw_intf_bind_pingpong_blk;
>   	ops->setup_misr = dpu_hw_intf_setup_misr;
>   	ops->collect_misr = dpu_hw_intf_collect_misr;
> +
> +	if (cap & BIT(DPU_INTF_TE)) {
> +		ops->setup_tearcheck = dpu_hw_intf_setup_te_config;
> +		ops->enable_tearcheck = dpu_hw_intf_enable_te;
> +		ops->connect_external_te = dpu_hw_intf_connect_external_te;
> +		ops->get_vsync_info = dpu_hw_intf_get_vsync_info;
> +		ops->setup_autorefresh = dpu_hw_intf_setup_autorefresh_config;
> +		ops->get_autorefresh = dpu_hw_intf_get_autorefresh_config;
> +		ops->poll_timeout_wr_ptr = dpu_hw_intf_poll_timeout_wr_ptr;
> +		ops->vsync_sel = dpu_hw_intf_vsync_sel;
> +		ops->get_status = dpu_hw_intf_v1_get_status;
> +	}
>   }
>   
>   struct dpu_hw_intf *dpu_hw_intf_init(enum dpu_intf idx,
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
> index 643dd10bc030..1521c9475fad 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
> @@ -60,6 +60,17 @@ struct intf_status {
>    *                     feed pixels to this interface
>    * @setup_misr: enable/disable MISR
>    * @collect_misr: read MISR signature
> + * @setup_tearcheck:            Enables vsync generation and sets up init value of read
> + *                              pointer and programs the tear check configuration
> + * @enable_tearcheck:           Enables tearcheck block
> + * @connect_external_te:        Read, modify, write to either set or clear listening to external TE
> + *                              Return: 1 if TE was originally connected, 0 if not, or -ERROR
> + * @get_vsync_info:             Provides the programmed and current line_count
> + * @setup_autorefresh:          Configure and enable the autorefresh config
> + * @get_autorefresh:            Retrieve autorefresh config from hardware
> + * @poll_timeout_wr_ptr:        Poll until write pointer transmission starts
> + *                              Return: 0 on success, -ETIMEDOUT on timeout
> + * @vsync_sel:                  Select vsync signal for tear-effect configuration
>    */
>   struct dpu_hw_intf_ops {
>   	void (*setup_timing_gen)(struct dpu_hw_intf *intf,
> @@ -82,6 +93,24 @@ struct dpu_hw_intf_ops {
>   			const enum dpu_pingpong pp);
>   	void (*setup_misr)(struct dpu_hw_intf *intf, bool enable, u32 frame_count);
>   	int (*collect_misr)(struct dpu_hw_intf *intf, u32 *misr_value);
> +
> +	// Tearcheck on INTF since DPU 5.0.0
> +
> +	int (*setup_tearcheck)(struct dpu_hw_intf *intf, struct dpu_hw_tear_check *cfg);
> +
> +	int (*enable_tearcheck)(struct dpu_hw_intf *intf, bool enable);
> +
> +	int (*connect_external_te)(struct dpu_hw_intf *intf, bool enable_external_te);
> +
> +	int (*get_vsync_info)(struct dpu_hw_intf *intf, struct dpu_hw_pp_vsync_info *info);
> +
> +	void (*setup_autorefresh)(struct dpu_hw_intf *intf, u32 frame_count, bool enable);
> +
> +	bool (*get_autorefresh)(struct dpu_hw_intf *intf, u32 *frame_count);
> +
> +	int (*poll_timeout_wr_ptr)(struct dpu_hw_intf *intf, u32 timeout_us);
> +
> +	void (*vsync_sel)(struct dpu_hw_intf *intf, u32 vsync_source);
>   };
>   
>   struct dpu_hw_intf {
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> index 64b2bf219a34..773579906961 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> @@ -494,12 +494,14 @@ struct dpu_hw_tear_check {
>    * @rd_ptr_frame_count: Num frames sent since enabling interface
>    * @rd_ptr_line_count:  Current line on panel (rd ptr)
>    * @wr_ptr_line_count:  Current line within pp fifo (wr ptr)
> + * @intf_frame_count:   Frames read from intf
>    */
>   struct dpu_hw_pp_vsync_info {
>   	u32 rd_ptr_init_val;
>   	u32 rd_ptr_frame_count;
>   	u32 rd_ptr_line_count;
>   	u32 wr_ptr_line_count;
> +	u32 intf_frame_count;
>   };
>   
>   #endif  /* _DPU_HW_MDSS_H */

-- 
With best wishes
Dmitry


  reply	other threads:[~2023-01-01 13:32 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-31 21:49 [RFC PATCH 0/7] " Marijn Suijten
2022-12-31 21:50 ` [RFC PATCH 1/7] drm/msm/dpu: Remove unused INTF0 interrupt mask from sm6115/qcm2290 Marijn Suijten
2023-01-01  4:18   ` Dmitry Baryshkov
2023-01-02  9:29   ` Konrad Dybcio
2023-01-02 10:12     ` Marijn Suijten
2022-12-31 21:50 ` [RFC PATCH 2/7] drm/msm/dpu: Disable pingpong TE on DPU 5.0.0 and above Marijn Suijten
2023-01-01  4:28   ` Dmitry Baryshkov
2023-01-02 10:25     ` Marijn Suijten
2023-01-02 14:02       ` Dmitry Baryshkov
2022-12-31 21:50 ` [RFC PATCH 3/7] drm/msm/dpu: Disable MDP vsync source selection " Marijn Suijten
2022-12-31 21:52   ` Marijn Suijten
2023-01-01 12:28     ` Dmitry Baryshkov
2023-01-02  9:30     ` Konrad Dybcio
2023-01-02 10:18       ` Marijn Suijten
2023-01-02 10:19         ` Konrad Dybcio
2022-12-31 21:50 ` [RFC PATCH 4/7] drm/msm/dpu: Move dpu_hw_{tear_check,pp_vsync_info} to dpu_hw_mdss.h Marijn Suijten
2023-01-01 12:37   ` Dmitry Baryshkov
2022-12-31 21:50 ` [RFC PATCH 5/7] drm/msm/dpu: Document and enable TEAR interrupts on DSI interfaces Marijn Suijten
2023-01-01 13:12   ` Dmitry Baryshkov
2023-01-02 10:38     ` Marijn Suijten
2023-02-13 19:37   ` Jessica Zhang
2023-02-13 21:46     ` Dmitry Baryshkov
2023-02-14  3:09       ` Abhinav Kumar
2023-02-14 13:06         ` Marijn Suijten
2023-02-14 17:54           ` Abhinav Kumar
2023-04-17 19:41             ` Marijn Suijten
2023-04-17 19:59               ` Abhinav Kumar
2022-12-31 21:50 ` [RFC PATCH 6/7] drm/msm/dpu: Implement tearcheck support on INTF block Marijn Suijten
2023-01-01 13:32   ` Dmitry Baryshkov [this message]
2023-01-02 11:06     ` Marijn Suijten
2023-01-02 15:48       ` Dmitry Baryshkov
2022-12-31 21:50 ` [RFC PATCH 7/7] drm/msm/dpu: Remove intr_rdptr from DPU >= 5.0.0 pingpong config Marijn Suijten
2023-01-01 12:27   ` Dmitry Baryshkov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=593cae1c-ade3-c68a-25d3-84ba1b968175@linaro.org \
    --to=dmitry.baryshkov@linaro.org \
    --cc=a39.skl@gmail.com \
    --cc=airlied@gmail.com \
    --cc=andersson@kernel.org \
    --cc=angelogioacchino.delregno@somainline.org \
    --cc=daniel@ffwll.ch \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=freedreno@lists.freedesktop.org \
    --cc=jami.kettunen@somainline.org \
    --cc=konrad.dybcio@linaro.org \
    --cc=konrad.dybcio@somainline.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=loic.poulain@linaro.org \
    --cc=marijn.suijten@somainline.org \
    --cc=martin.botka@somainline.org \
    --cc=neil.armstrong@linaro.org \
    --cc=phone-devel@vger.kernel.org \
    --cc=quic_abhinavk@quicinc.com \
    --cc=quic_jesszhan@quicinc.com \
    --cc=quic_khsieh@quicinc.com \
    --cc=quic_vpolimer@quicinc.com \
    --cc=robdclark@gmail.com \
    --cc=sean@poorly.run \
    --cc=swboyd@chromium.org \
    --cc=vkoul@kernel.org \
    --cc=~postmarketos/upstreaming@lists.sr.ht \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®