[PATCH] drm: stm: implement get_scanout_position function

Benjamin Gaignard benjamin.gaignard at linaro.org
Thu Sep 27 13:17:01 UTC 2018


Le jeu. 27 sept. 2018 à 13:32, Yannick FERTRE <yannick.fertre at st.com> a écrit :
>
> Reviewed-by: Yannick Fertré <yannick.fertre at st.com>
> Tested-by: Yannick Fertré <yannick.fertre at 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 at 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 at linaro.org>
> > To: yannick.fertre at st.com, philippe.cornu at st.com, airlied at linux.ie
> > CC: dri-devel at lists.freedesktop.org, linux-kernel at vger.kernel.org,
> > Benjamin Gaignard <benjamin.gaignard at linaro.org>, Benjamin Gaignard
> > <benjamin.gaignard at 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 at 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 at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel


More information about the dri-devel mailing list