linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] drm: stm: implement get_scanout_position function
@ 2018-09-03 13:49 Benjamin Gaignard
  0 siblings, 0 replies; 5+ messages in thread
From: Benjamin Gaignard @ 2018-09-03 13:49 UTC (permalink / raw)
  To: yannick.fertre, philippe.cornu, airlied
  Cc: dri-devel, linux-kernel, Benjamin Gaignard, Benjamin Gaignard

Hardware allow to read the position in scanout buffer so
we can use this information to make wait of vblank more accurate.

Active area bounds (start, end, total height) have already been
computed and written in ltdc registers, read them and get the
current line position to compute vpos value.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
 drivers/gpu/drm/stm/drv.c  |  2 ++
 drivers/gpu/drm/stm/ltdc.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/stm/ltdc.h |  5 +++++
 3 files changed, 52 insertions(+)

diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c
index 8698e08313e1..ac53383350e3 100644
--- a/drivers/gpu/drm/stm/drv.c
+++ b/drivers/gpu/drm/stm/drv.c
@@ -72,6 +72,8 @@ static struct drm_driver drv_driver = {
 	.gem_prime_vmap = drm_gem_cma_prime_vmap,
 	.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
 	.gem_prime_mmap = drm_gem_cma_prime_mmap,
+	.get_scanout_position = ltdc_crtc_scanoutpos,
+	.get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos,
 };
 
 static int drv_load(struct drm_device *ddev)
diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c
index d997a6014d6c..05b714673042 100644
--- a/drivers/gpu/drm/stm/ltdc.c
+++ b/drivers/gpu/drm/stm/ltdc.c
@@ -148,6 +148,8 @@
 #define IER_TERRIE	BIT(2)		/* Transfer ERRor Interrupt Enable */
 #define IER_RRIE	BIT(3)		/* Register Reload Interrupt enable */
 
+#define CPSR_CYPOS	GENMASK(15, 0)	/* Current Y position */
+
 #define ISR_LIF		BIT(0)		/* Line Interrupt Flag */
 #define ISR_FUIF	BIT(1)		/* Fifo Underrun Interrupt Flag */
 #define ISR_TERRIF	BIT(2)		/* Transfer ERRor Interrupt Flag */
@@ -622,6 +624,49 @@ static void ltdc_crtc_disable_vblank(struct drm_crtc *crtc)
 	reg_clear(ldev->regs, LTDC_IER, IER_LIE);
 }
 
+bool ltdc_crtc_scanoutpos(struct drm_device *ddev, unsigned int pipe,
+			  bool in_vblank_irq, int *vpos, int *hpos,
+			  ktime_t *stime, ktime_t *etime,
+			  const struct drm_display_mode *mode)
+{
+	struct ltdc_device *ldev = ddev->dev_private;
+	int line, vactive_start, vactive_end, vtotal;
+
+	if (stime)
+		*stime = ktime_get();
+
+	/* The active area starts after vsync + front porch and ends
+	 * at vsync + front porc + display size.
+	 * The total height also include back porch.
+	 * We have 3 possible cases to handle:
+	 * - line < vactive_start: vpos = line - vactive_start and will be
+	 * negative
+	 * - vactive_start < line < vactive_end: vpos = line - vactive_start
+	 * and will be positive
+	 * - line > vactive_end: vpos = line - vtotal - vactive_start
+	 * and will negative
+	 *
+	 * Computation for the two first cases are identical so we can
+	 * simplify the code and only test if line > vactive_end
+	 */
+	line = reg_read(ldev->regs, LTDC_CPSR) & CPSR_CYPOS;
+	vactive_start = reg_read(ldev->regs, LTDC_BPCR) & BPCR_AVBP;
+	vactive_end = reg_read(ldev->regs, LTDC_AWCR) & AWCR_AAH;
+	vtotal = reg_read(ldev->regs, LTDC_TWCR) & TWCR_TOTALH;
+
+	if (line > vactive_end)
+		*vpos = line - vtotal - vactive_start;
+	else
+		*vpos = line - vactive_start;
+
+	*hpos = 0;
+
+	if (etime)
+		*etime = ktime_get();
+
+	return true;
+}
+
 static const struct drm_crtc_funcs ltdc_crtc_funcs = {
 	.destroy = drm_crtc_cleanup,
 	.set_config = drm_atomic_helper_set_config,
diff --git a/drivers/gpu/drm/stm/ltdc.h b/drivers/gpu/drm/stm/ltdc.h
index 1e16d6afb0d2..b8c5cc41e17a 100644
--- a/drivers/gpu/drm/stm/ltdc.h
+++ b/drivers/gpu/drm/stm/ltdc.h
@@ -37,6 +37,11 @@ struct ltdc_device {
 	struct fps_info plane_fpsi[LTDC_MAX_LAYER];
 };
 
+bool ltdc_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
+			  bool in_vblank_irq, int *vpos, int *hpos,
+			  ktime_t *stime, ktime_t *etime,
+			  const struct drm_display_mode *mode);
+
 int ltdc_load(struct drm_device *ddev);
 void ltdc_unload(struct drm_device *ddev);
 
-- 
2.15.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] drm: stm: implement get_scanout_position function
  2018-09-27 11:32   ` Yannick FERTRE
@ 2018-09-27 13:17     ` Benjamin Gaignard
  0 siblings, 0 replies; 5+ messages in thread
From: Benjamin Gaignard @ 2018-09-27 13:17 UTC (permalink / raw)
  To: Yannick Fertre
  Cc: Philippe Cornu, Benjamin GAIGNARD, David Airlie,
	Linux Kernel Mailing List, ML dri-devel

Le jeu. 27 sept. 2018 à 13:32, Yannick FERTRE <yannick.fertre@st.com> a écrit :
>
> Reviewed-by: Yannick Fertré <yannick.fertre@st.com>
> Tested-by: Yannick Fertré <yannick.fertre@st.com>

Applied on drm-misc-next,
Thanks,
Benjamin

>
> On 09/27/2018 10:15 AM, Yannick FERTRE wrote:
> > Reviewed-by/tested-by: yannick.fertre@st.com
> >
> > -------- Forwarded Message --------
> > Subject: [PATCH] drm: stm: implement get_scanout_position function
> > Date: Fri, 29 Jun 2018 15:01:40 +0200
> > From: Benjamin Gaignard <benjamin.gaignard@linaro.org>
> > To: yannick.fertre@st.com, philippe.cornu@st.com, airlied@linux.ie
> > CC: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
> > Benjamin Gaignard <benjamin.gaignard@linaro.org>, Benjamin Gaignard
> > <benjamin.gaignard@st.com>
> >
> > Hardware allow to read the position in scanout buffer so
> > we can use this information to make wait of vblank more accurate.
> >
> > Active area bounds (start, end, total height) have already been
> > computed and written in ltdc registers, read them and get the
> > current line position to compute vpos value.
> >
> > Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
> > ---
> >   drivers/gpu/drm/stm/drv.c  |  2 ++
> >   drivers/gpu/drm/stm/ltdc.c | 45
> > +++++++++++++++++++++++++++++++++++++++++++++
> >   drivers/gpu/drm/stm/ltdc.h |  5 +++++
> >   3 files changed, 52 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c
> > index 8698e08313e1..ac53383350e3 100644
> > --- a/drivers/gpu/drm/stm/drv.c
> > +++ b/drivers/gpu/drm/stm/drv.c
> > @@ -72,6 +72,8 @@ static struct drm_driver drv_driver = {
> >       .gem_prime_vmap = drm_gem_cma_prime_vmap,
> >       .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
> >       .gem_prime_mmap = drm_gem_cma_prime_mmap,
> > +    .get_scanout_position = ltdc_crtc_scanoutpos,
> > +    .get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos,
> >   };
> >    static int drv_load(struct drm_device *ddev)
> > diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c
> > index d997a6014d6c..05b714673042 100644
> > --- a/drivers/gpu/drm/stm/ltdc.c
> > +++ b/drivers/gpu/drm/stm/ltdc.c
> > @@ -148,6 +148,8 @@
> >   #define IER_TERRIE    BIT(2)        /* Transfer ERRor Interrupt
> > Enable */
> >   #define IER_RRIE    BIT(3)        /* Register Reload Interrupt
> > enable */
> >   +#define CPSR_CYPOS    GENMASK(15, 0)    /* Current Y position */
> > +
> >   #define ISR_LIF        BIT(0)        /* Line Interrupt Flag */
> >   #define ISR_FUIF    BIT(1)        /* Fifo Underrun Interrupt Flag */
> >   #define ISR_TERRIF    BIT(2)        /* Transfer ERRor Interrupt Flag */
> > @@ -622,6 +624,49 @@ static void ltdc_crtc_disable_vblank(struct
> > drm_crtc *crtc)
> >       reg_clear(ldev->regs, LTDC_IER, IER_LIE);
> >   }
> >   +bool ltdc_crtc_scanoutpos(struct drm_device *ddev, unsigned int pipe,
> > +              bool in_vblank_irq, int *vpos, int *hpos,
> > +              ktime_t *stime, ktime_t *etime,
> > +              const struct drm_display_mode *mode)
> > +{
> > +    struct ltdc_device *ldev = ddev->dev_private;
> > +    int line, vactive_start, vactive_end, vtotal;
> > +
> > +    if (stime)
> > +        *stime = ktime_get();
> > +
> > +    /* The active area starts after vsync + front porch and ends
> > +     * at vsync + front porc + display size.
> > +     * The total height also include back porch.
> > +     * We have 3 possible cases to handle:
> > +     * - line < vactive_start: vpos = line - vactive_start and will be
> > +     * negative
> > +     * - vactive_start < line < vactive_end: vpos = line - vactive_start
> > +     * and will be positive
> > +     * - line > vactive_end: vpos = line - vtotal - vactive_start
> > +     * and will negative
> > +     *
> > +     * Computation for the two first cases are identical so we can
> > +     * simplify the code and only test if line > vactive_end
> > +     */
> > +    line = reg_read(ldev->regs, LTDC_CPSR) & CPSR_CYPOS;
> > +    vactive_start = reg_read(ldev->regs, LTDC_BPCR) & BPCR_AVBP;
> > +    vactive_end = reg_read(ldev->regs, LTDC_AWCR) & AWCR_AAH;
> > +    vtotal = reg_read(ldev->regs, LTDC_TWCR) & TWCR_TOTALH;
> > +
> > +    if (line > vactive_end)
> > +        *vpos = line - vtotal - vactive_start;
> > +    else
> > +        *vpos = line - vactive_start;
> > +
> > +    *hpos = 0;
> > +
> > +    if (etime)
> > +        *etime = ktime_get();
> > +
> > +    return true;
> > +}
> > +
> >   static const struct drm_crtc_funcs ltdc_crtc_funcs = {
> >       .destroy = drm_crtc_cleanup,
> >       .set_config = drm_atomic_helper_set_config,
> > diff --git a/drivers/gpu/drm/stm/ltdc.h b/drivers/gpu/drm/stm/ltdc.h
> > index 1e16d6afb0d2..b8c5cc41e17a 100644
> > --- a/drivers/gpu/drm/stm/ltdc.h
> > +++ b/drivers/gpu/drm/stm/ltdc.h
> > @@ -37,6 +37,11 @@ struct ltdc_device {
> >       struct fps_info plane_fpsi[LTDC_MAX_LAYER];
> >   };
> >   +bool ltdc_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
> > +              bool in_vblank_irq, int *vpos, int *hpos,
> > +              ktime_t *stime, ktime_t *etime,
> > +              const struct drm_display_mode *mode);
> > +
> >   int ltdc_load(struct drm_device *ddev);
> >   void ltdc_unload(struct drm_device *ddev);
> >   -- 2.15.0
> >
>
> --
> Yannick Fertré | TINA: 166 7152 | Tel: +33 244027152 | Mobile: +33 620600270
> Microcontrollers and Digital ICs Group | Microcontrolleurs Division
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] drm: stm: implement get_scanout_position function
  2018-09-27  8:15 ` Yannick FERTRE
@ 2018-09-27 11:32   ` Yannick FERTRE
  2018-09-27 13:17     ` Benjamin Gaignard
  0 siblings, 1 reply; 5+ messages in thread
From: Yannick FERTRE @ 2018-09-27 11:32 UTC (permalink / raw)
  To: Philippe CORNU, Benjamin GAIGNARD, airlied; +Cc: dri-devel, linux-kernel

Reviewed-by: Yannick Fertré <yannick.fertre@st.com>
Tested-by: Yannick Fertré <yannick.fertre@st.com>

On 09/27/2018 10:15 AM, Yannick FERTRE wrote:
> Reviewed-by/tested-by: yannick.fertre@st.com
>
> -------- Forwarded Message --------
> Subject: [PATCH] drm: stm: implement get_scanout_position function
> Date: Fri, 29 Jun 2018 15:01:40 +0200
> From: Benjamin Gaignard <benjamin.gaignard@linaro.org>
> To: yannick.fertre@st.com, philippe.cornu@st.com, airlied@linux.ie
> CC: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
> Benjamin Gaignard <benjamin.gaignard@linaro.org>, Benjamin Gaignard
> <benjamin.gaignard@st.com>
>
> Hardware allow to read the position in scanout buffer so
> we can use this information to make wait of vblank more accurate.
>
> Active area bounds (start, end, total height) have already been
> computed and written in ltdc registers, read them and get the
> current line position to compute vpos value.
>
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
> ---
>   drivers/gpu/drm/stm/drv.c  |  2 ++
>   drivers/gpu/drm/stm/ltdc.c | 45
> +++++++++++++++++++++++++++++++++++++++++++++
>   drivers/gpu/drm/stm/ltdc.h |  5 +++++
>   3 files changed, 52 insertions(+)
>
> diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c
> index 8698e08313e1..ac53383350e3 100644
> --- a/drivers/gpu/drm/stm/drv.c
> +++ b/drivers/gpu/drm/stm/drv.c
> @@ -72,6 +72,8 @@ static struct drm_driver drv_driver = {
>       .gem_prime_vmap = drm_gem_cma_prime_vmap,
>       .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
>       .gem_prime_mmap = drm_gem_cma_prime_mmap,
> +    .get_scanout_position = ltdc_crtc_scanoutpos,
> +    .get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos,
>   };
>    static int drv_load(struct drm_device *ddev)
> diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c
> index d997a6014d6c..05b714673042 100644
> --- a/drivers/gpu/drm/stm/ltdc.c
> +++ b/drivers/gpu/drm/stm/ltdc.c
> @@ -148,6 +148,8 @@
>   #define IER_TERRIE    BIT(2)        /* Transfer ERRor Interrupt 
> Enable */
>   #define IER_RRIE    BIT(3)        /* Register Reload Interrupt 
> enable */
>   +#define CPSR_CYPOS    GENMASK(15, 0)    /* Current Y position */
> +
>   #define ISR_LIF        BIT(0)        /* Line Interrupt Flag */
>   #define ISR_FUIF    BIT(1)        /* Fifo Underrun Interrupt Flag */
>   #define ISR_TERRIF    BIT(2)        /* Transfer ERRor Interrupt Flag */
> @@ -622,6 +624,49 @@ static void ltdc_crtc_disable_vblank(struct
> drm_crtc *crtc)
>       reg_clear(ldev->regs, LTDC_IER, IER_LIE);
>   }
>   +bool ltdc_crtc_scanoutpos(struct drm_device *ddev, unsigned int pipe,
> +              bool in_vblank_irq, int *vpos, int *hpos,
> +              ktime_t *stime, ktime_t *etime,
> +              const struct drm_display_mode *mode)
> +{
> +    struct ltdc_device *ldev = ddev->dev_private;
> +    int line, vactive_start, vactive_end, vtotal;
> +
> +    if (stime)
> +        *stime = ktime_get();
> +
> +    /* The active area starts after vsync + front porch and ends
> +     * at vsync + front porc + display size.
> +     * The total height also include back porch.
> +     * We have 3 possible cases to handle:
> +     * - line < vactive_start: vpos = line - vactive_start and will be
> +     * negative
> +     * - vactive_start < line < vactive_end: vpos = line - vactive_start
> +     * and will be positive
> +     * - line > vactive_end: vpos = line - vtotal - vactive_start
> +     * and will negative
> +     *
> +     * Computation for the two first cases are identical so we can
> +     * simplify the code and only test if line > vactive_end
> +     */
> +    line = reg_read(ldev->regs, LTDC_CPSR) & CPSR_CYPOS;
> +    vactive_start = reg_read(ldev->regs, LTDC_BPCR) & BPCR_AVBP;
> +    vactive_end = reg_read(ldev->regs, LTDC_AWCR) & AWCR_AAH;
> +    vtotal = reg_read(ldev->regs, LTDC_TWCR) & TWCR_TOTALH;
> +
> +    if (line > vactive_end)
> +        *vpos = line - vtotal - vactive_start;
> +    else
> +        *vpos = line - vactive_start;
> +
> +    *hpos = 0;
> +
> +    if (etime)
> +        *etime = ktime_get();
> +
> +    return true;
> +}
> +
>   static const struct drm_crtc_funcs ltdc_crtc_funcs = {
>       .destroy = drm_crtc_cleanup,
>       .set_config = drm_atomic_helper_set_config,
> diff --git a/drivers/gpu/drm/stm/ltdc.h b/drivers/gpu/drm/stm/ltdc.h
> index 1e16d6afb0d2..b8c5cc41e17a 100644
> --- a/drivers/gpu/drm/stm/ltdc.h
> +++ b/drivers/gpu/drm/stm/ltdc.h
> @@ -37,6 +37,11 @@ struct ltdc_device {
>       struct fps_info plane_fpsi[LTDC_MAX_LAYER];
>   };
>   +bool ltdc_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
> +              bool in_vblank_irq, int *vpos, int *hpos,
> +              ktime_t *stime, ktime_t *etime,
> +              const struct drm_display_mode *mode);
> +
>   int ltdc_load(struct drm_device *ddev);
>   void ltdc_unload(struct drm_device *ddev);
>   -- 2.15.0
>

-- 
Yannick Fertré | TINA: 166 7152 | Tel: +33 244027152 | Mobile: +33 620600270
Microcontrollers and Digital ICs Group | Microcontrolleurs Division

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH] drm: stm: implement get_scanout_position function
       [not found] <7441c31c-7427-da4e-c877-6d58b5bd869f@st.com>
@ 2018-09-27  8:15 ` Yannick FERTRE
  2018-09-27 11:32   ` Yannick FERTRE
  0 siblings, 1 reply; 5+ messages in thread
From: Yannick FERTRE @ 2018-09-27  8:15 UTC (permalink / raw)
  To: Philippe CORNU, Benjamin GAIGNARD, airlied; +Cc: dri-devel, linux-kernel

Reviewed-by/tested-by: yannick.fertre@st.com

-------- Forwarded Message --------
Subject: [PATCH] drm: stm: implement get_scanout_position function
Date: Fri, 29 Jun 2018 15:01:40 +0200
From: Benjamin Gaignard <benjamin.gaignard@linaro.org>
To: yannick.fertre@st.com, philippe.cornu@st.com, airlied@linux.ie
CC: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
Benjamin Gaignard <benjamin.gaignard@linaro.org>, Benjamin Gaignard
<benjamin.gaignard@st.com>

Hardware allow to read the position in scanout buffer so
we can use this information to make wait of vblank more accurate.

Active area bounds (start, end, total height) have already been
computed and written in ltdc registers, read them and get the
current line position to compute vpos value.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
   drivers/gpu/drm/stm/drv.c  |  2 ++
   drivers/gpu/drm/stm/ltdc.c | 45
+++++++++++++++++++++++++++++++++++++++++++++
   drivers/gpu/drm/stm/ltdc.h |  5 +++++
   3 files changed, 52 insertions(+)

diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c
index 8698e08313e1..ac53383350e3 100644
--- a/drivers/gpu/drm/stm/drv.c
+++ b/drivers/gpu/drm/stm/drv.c
@@ -72,6 +72,8 @@ static struct drm_driver drv_driver = {
   	.gem_prime_vmap = drm_gem_cma_prime_vmap,
   	.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
   	.gem_prime_mmap = drm_gem_cma_prime_mmap,
+	.get_scanout_position = ltdc_crtc_scanoutpos,
+	.get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos,
   };
    static int drv_load(struct drm_device *ddev)
diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c
index d997a6014d6c..05b714673042 100644
--- a/drivers/gpu/drm/stm/ltdc.c
+++ b/drivers/gpu/drm/stm/ltdc.c
@@ -148,6 +148,8 @@
   #define IER_TERRIE	BIT(2)		/* Transfer ERRor Interrupt Enable */
   #define IER_RRIE	BIT(3)		/* Register Reload Interrupt enable */
   +#define CPSR_CYPOS	GENMASK(15, 0)	/* Current Y position */
+
   #define ISR_LIF		BIT(0)		/* Line Interrupt Flag */
   #define ISR_FUIF	BIT(1)		/* Fifo Underrun Interrupt Flag */
   #define ISR_TERRIF	BIT(2)		/* Transfer ERRor Interrupt Flag */
@@ -622,6 +624,49 @@ static void ltdc_crtc_disable_vblank(struct
drm_crtc *crtc)
   	reg_clear(ldev->regs, LTDC_IER, IER_LIE);
   }
   +bool ltdc_crtc_scanoutpos(struct drm_device *ddev, unsigned int pipe,
+			  bool in_vblank_irq, int *vpos, int *hpos,
+			  ktime_t *stime, ktime_t *etime,
+			  const struct drm_display_mode *mode)
+{
+	struct ltdc_device *ldev = ddev->dev_private;
+	int line, vactive_start, vactive_end, vtotal;
+
+	if (stime)
+		*stime = ktime_get();
+
+	/* The active area starts after vsync + front porch and ends
+	 * at vsync + front porc + display size.
+	 * The total height also include back porch.
+	 * We have 3 possible cases to handle:
+	 * - line < vactive_start: vpos = line - vactive_start and will be
+	 * negative
+	 * - vactive_start < line < vactive_end: vpos = line - vactive_start
+	 * and will be positive
+	 * - line > vactive_end: vpos = line - vtotal - vactive_start
+	 * and will negative
+	 *
+	 * Computation for the two first cases are identical so we can
+	 * simplify the code and only test if line > vactive_end
+	 */
+	line = reg_read(ldev->regs, LTDC_CPSR) & CPSR_CYPOS;
+	vactive_start = reg_read(ldev->regs, LTDC_BPCR) & BPCR_AVBP;
+	vactive_end = reg_read(ldev->regs, LTDC_AWCR) & AWCR_AAH;
+	vtotal = reg_read(ldev->regs, LTDC_TWCR) & TWCR_TOTALH;
+
+	if (line > vactive_end)
+		*vpos = line - vtotal - vactive_start;
+	else
+		*vpos = line - vactive_start;
+
+	*hpos = 0;
+
+	if (etime)
+		*etime = ktime_get();
+
+	return true;
+}
+
   static const struct drm_crtc_funcs ltdc_crtc_funcs = {
   	.destroy = drm_crtc_cleanup,
   	.set_config = drm_atomic_helper_set_config,
diff --git a/drivers/gpu/drm/stm/ltdc.h b/drivers/gpu/drm/stm/ltdc.h
index 1e16d6afb0d2..b8c5cc41e17a 100644
--- a/drivers/gpu/drm/stm/ltdc.h
+++ b/drivers/gpu/drm/stm/ltdc.h
@@ -37,6 +37,11 @@ struct ltdc_device {
   	struct fps_info plane_fpsi[LTDC_MAX_LAYER];
   };
   +bool ltdc_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
+			  bool in_vblank_irq, int *vpos, int *hpos,
+			  ktime_t *stime, ktime_t *etime,
+			  const struct drm_display_mode *mode);
+
   int ltdc_load(struct drm_device *ddev);
   void ltdc_unload(struct drm_device *ddev);
   -- 2.15.0

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH] drm: stm: implement get_scanout_position function
@ 2018-06-29 13:01 Benjamin Gaignard
  0 siblings, 0 replies; 5+ messages in thread
From: Benjamin Gaignard @ 2018-06-29 13:01 UTC (permalink / raw)
  To: yannick.fertre, philippe.cornu, airlied
  Cc: dri-devel, linux-kernel, Benjamin Gaignard, Benjamin Gaignard

Hardware allow to read the position in scanout buffer so
we can use this information to make wait of vblank more accurate.

Active area bounds (start, end, total height) have already been
computed and written in ltdc registers, read them and get the
current line position to compute vpos value.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
 drivers/gpu/drm/stm/drv.c  |  2 ++
 drivers/gpu/drm/stm/ltdc.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/stm/ltdc.h |  5 +++++
 3 files changed, 52 insertions(+)

diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c
index 8698e08313e1..ac53383350e3 100644
--- a/drivers/gpu/drm/stm/drv.c
+++ b/drivers/gpu/drm/stm/drv.c
@@ -72,6 +72,8 @@ static struct drm_driver drv_driver = {
 	.gem_prime_vmap = drm_gem_cma_prime_vmap,
 	.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
 	.gem_prime_mmap = drm_gem_cma_prime_mmap,
+	.get_scanout_position = ltdc_crtc_scanoutpos,
+	.get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos,
 };
 
 static int drv_load(struct drm_device *ddev)
diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c
index d997a6014d6c..05b714673042 100644
--- a/drivers/gpu/drm/stm/ltdc.c
+++ b/drivers/gpu/drm/stm/ltdc.c
@@ -148,6 +148,8 @@
 #define IER_TERRIE	BIT(2)		/* Transfer ERRor Interrupt Enable */
 #define IER_RRIE	BIT(3)		/* Register Reload Interrupt enable */
 
+#define CPSR_CYPOS	GENMASK(15, 0)	/* Current Y position */
+
 #define ISR_LIF		BIT(0)		/* Line Interrupt Flag */
 #define ISR_FUIF	BIT(1)		/* Fifo Underrun Interrupt Flag */
 #define ISR_TERRIF	BIT(2)		/* Transfer ERRor Interrupt Flag */
@@ -622,6 +624,49 @@ static void ltdc_crtc_disable_vblank(struct drm_crtc *crtc)
 	reg_clear(ldev->regs, LTDC_IER, IER_LIE);
 }
 
+bool ltdc_crtc_scanoutpos(struct drm_device *ddev, unsigned int pipe,
+			  bool in_vblank_irq, int *vpos, int *hpos,
+			  ktime_t *stime, ktime_t *etime,
+			  const struct drm_display_mode *mode)
+{
+	struct ltdc_device *ldev = ddev->dev_private;
+	int line, vactive_start, vactive_end, vtotal;
+
+	if (stime)
+		*stime = ktime_get();
+
+	/* The active area starts after vsync + front porch and ends
+	 * at vsync + front porc + display size.
+	 * The total height also include back porch.
+	 * We have 3 possible cases to handle:
+	 * - line < vactive_start: vpos = line - vactive_start and will be
+	 * negative
+	 * - vactive_start < line < vactive_end: vpos = line - vactive_start
+	 * and will be positive
+	 * - line > vactive_end: vpos = line - vtotal - vactive_start
+	 * and will negative
+	 *
+	 * Computation for the two first cases are identical so we can
+	 * simplify the code and only test if line > vactive_end
+	 */
+	line = reg_read(ldev->regs, LTDC_CPSR) & CPSR_CYPOS;
+	vactive_start = reg_read(ldev->regs, LTDC_BPCR) & BPCR_AVBP;
+	vactive_end = reg_read(ldev->regs, LTDC_AWCR) & AWCR_AAH;
+	vtotal = reg_read(ldev->regs, LTDC_TWCR) & TWCR_TOTALH;
+
+	if (line > vactive_end)
+		*vpos = line - vtotal - vactive_start;
+	else
+		*vpos = line - vactive_start;
+
+	*hpos = 0;
+
+	if (etime)
+		*etime = ktime_get();
+
+	return true;
+}
+
 static const struct drm_crtc_funcs ltdc_crtc_funcs = {
 	.destroy = drm_crtc_cleanup,
 	.set_config = drm_atomic_helper_set_config,
diff --git a/drivers/gpu/drm/stm/ltdc.h b/drivers/gpu/drm/stm/ltdc.h
index 1e16d6afb0d2..b8c5cc41e17a 100644
--- a/drivers/gpu/drm/stm/ltdc.h
+++ b/drivers/gpu/drm/stm/ltdc.h
@@ -37,6 +37,11 @@ struct ltdc_device {
 	struct fps_info plane_fpsi[LTDC_MAX_LAYER];
 };
 
+bool ltdc_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
+			  bool in_vblank_irq, int *vpos, int *hpos,
+			  ktime_t *stime, ktime_t *etime,
+			  const struct drm_display_mode *mode);
+
 int ltdc_load(struct drm_device *ddev);
 void ltdc_unload(struct drm_device *ddev);
 
-- 
2.15.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2018-09-27 13:17 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-03 13:49 [PATCH] drm: stm: implement get_scanout_position function Benjamin Gaignard
     [not found] <7441c31c-7427-da4e-c877-6d58b5bd869f@st.com>
2018-09-27  8:15 ` Yannick FERTRE
2018-09-27 11:32   ` Yannick FERTRE
2018-09-27 13:17     ` Benjamin Gaignard
  -- strict thread matches above, loose matches on Subject: below --
2018-06-29 13:01 Benjamin Gaignard

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).