Re: [PATCH] drm: stm: implement get_scanout_position function
From: Benjamin Gaignard
Date: Thu Sep 27 2018 - 09:17:16 EST
Le jeu. 27 sept. 2018 Ã 13:32, Yannick FERTRE <yannick.fertre@xxxxxx> a Ãcrit :
>
> Reviewed-by: Yannick Fertrà <yannick.fertre@xxxxxx>
> Tested-by: Yannick Fertrà <yannick.fertre@xxxxxx>
Applied on drm-misc-next,
Thanks,
Benjamin
>
> On 09/27/2018 10:15 AM, Yannick FERTRE wrote:
> > Reviewed-by/tested-by: yannick.fertre@xxxxxx
> >
> > -------- 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@xxxxxxxxxx>
> > To: yannick.fertre@xxxxxx, philippe.cornu@xxxxxx, airlied@xxxxxxxx
> > CC: dri-devel@xxxxxxxxxxxxxxxxxxxxx, linux-kernel@xxxxxxxxxxxxxxx,
> > Benjamin Gaignard <benjamin.gaignard@xxxxxxxxxx>, Benjamin Gaignard
> > <benjamin.gaignard@xxxxxx>
> >
> > 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@xxxxxx>
> > ---
> > 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@xxxxxxxxxxxxxxxxxxxxx
> https://lists.freedesktop.org/mailman/listinfo/dri-devel