[PATCH] drm: stm: implement get_scanout_position function

Yannick FERTRE yannick.fertre at st.com
Thu Sep 27 11:32:00 UTC 2018


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

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


More information about the dri-devel mailing list