Message ID | c1148671-4df1-3815-bd62-75541873bad6@st.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | drm: stm: implement get_scanout_position function | expand |
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 >
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
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 _______________________________________________