Use the new VRR state tracking to handle VRR front porch adjustment.

To avoid indenting too deeply, refactor the vblank handling into its own
function while at it, where scope-based cleanup helpers for the lock can
be used.

Co-developed-by: Derek Foreman <[email protected]>
Signed-off-by: Derek Foreman <[email protected]>
Signed-off-by: Nicolas Frattaroli <[email protected]>
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 62 ++++++++++++++++++++++------
 drivers/gpu/drm/rockchip/rockchip_drm_vop2.h |  9 ++++
 2 files changed, 59 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
index bfb384142568..e79081c04437 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
@@ -24,6 +24,7 @@
 #include <drm/drm_atomic_uapi.h>
 #include <drm/drm_blend.h>
 #include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
 #include <linux/debugfs.h>
 #include <drm/drm_debugfs.h>
 #include <drm/drm_flip_work.h>
@@ -2011,6 +2012,25 @@ static void vop2_crtc_atomic_begin(struct drm_crtc *crtc,
        vop2->ops->setup_overlay(vp);
 }
 
+static void vop2_vp_set_vrr_vtotal(struct vop2_video_port *vp, unsigned int 
vtotal)
+{
+       const u32 mask = RK3568_VP_DSP_VTOTAL_VS_END__DSP_VTOTAL |
+                        RK3568_VP_DSP_VTOTAL_VS_END__IMD;
+
+       if (!vtotal) {
+               vop2_vp_update_bits(vp, RK3568_VP_DSP_VTOTAL_VS_END,
+                                   RK3568_VP_DSP_VTOTAL_VS_END__IMD, 0);
+               return;
+       }
+
+       /* Value is 13 bits at most, saturate it if too large */
+       if (vtotal > RK3568_VP_DSP_VTOTAL_VS_END__DSP_VTOTAL >> 16)
+               vtotal = RK3568_VP_DSP_VTOTAL_VS_END__DSP_VTOTAL >> 16;
+
+       vop2_vp_update_bits(vp, RK3568_VP_DSP_VTOTAL_VS_END, mask,
+                           vtotal << 16 | RK3568_VP_DSP_VTOTAL_VS_END__IMD);
+}
+
 static void vop2_crtc_atomic_flush(struct drm_crtc *crtc,
                                   struct drm_atomic_commit *state)
 {
@@ -2029,6 +2049,11 @@ static void vop2_crtc_atomic_flush(struct drm_crtc *crtc,
 
        spin_lock_irq(&crtc->dev->event_lock);
 
+       if (crtc_state->vrr_enabled) {
+               if (drm_crtc_helper_vrr_flush(crtc_state))
+                       vop2_vp_set_vrr_vtotal(vp, 
crtc_state->vrr_state.cur_vtotal);
+       }
+
        if (crtc->state->event) {
                WARN_ON(drm_crtc_vblank_get(crtc));
                vp->event = crtc->state->event;
@@ -2371,6 +2396,30 @@ static irqreturn_t rk3576_vp_isr(int irq, void *data)
        return ret;
 }
 
+static void vop2_vp_handle_vblank(struct vop2_video_port *vp)
+{
+       struct drm_crtc *crtc = &vp->crtc;
+       struct vop2 *vop2 = vp->vop2;
+       u32 val;
+
+       guard(spinlock)(&crtc->dev->event_lock);
+
+       if (!vp->event)
+               return;
+
+       val = vop2_readl(vop2, RK3568_REG_CFG_DONE);
+
+       if (!(val & BIT(vp->id))) {
+               drm_crtc_send_vblank_event(crtc, vp->event);
+               vp->event = NULL;
+               drm_crtc_vblank_put(crtc);
+
+               if (crtc->state->vrr_enabled)
+                       if (drm_crtc_helper_vrr_vsync(crtc->state))
+                               vop2_vp_set_vrr_vtotal(vp, 
crtc->state->vrr_state.cur_vtotal);
+       }
+}
+
 static irqreturn_t vop2_isr(int irq, void *data)
 {
        struct vop2 *vop2 = data;
@@ -2402,18 +2451,7 @@ static irqreturn_t vop2_isr(int irq, void *data)
 
                        if (irqs & VP_INT_FS_FIELD) {
                                drm_crtc_handle_vblank(crtc);
-                               spin_lock(&crtc->dev->event_lock);
-                               if (vp->event) {
-                                       u32 val = vop2_readl(vop2, 
RK3568_REG_CFG_DONE);
-
-                                       if (!(val & BIT(vp->id))) {
-                                               
drm_crtc_send_vblank_event(crtc, vp->event);
-                                               vp->event = NULL;
-                                               drm_crtc_vblank_put(crtc);
-                                       }
-                               }
-                               spin_unlock(&crtc->dev->event_lock);
-
+                               vop2_vp_handle_vblank(vp);
                                ret = IRQ_HANDLED;
                        }
 
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h
index ffcb39c130aa..fdb2030e3ad4 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h
@@ -655,6 +655,9 @@ enum dst_factor_mode {
 
 #define RK3588_VP_DSP_CTRL__GAMMA_UPDATE_EN            BIT(22)
 
+#define RK3568_VP_DSP_VTOTAL_VS_END__DSP_VTOTAL                GENMASK(28, 16)
+#define RK3568_VP_DSP_VTOTAL_VS_END__IMD               BIT(15)
+
 #define RK3588_VP_CLK_CTRL__DCLK_OUT_DIV               GENMASK(3, 2)
 #define RK3588_VP_CLK_CTRL__DCLK_CORE_DIV              GENMASK(1, 0)
 
@@ -810,6 +813,12 @@ static inline void vop2_vp_write(struct vop2_video_port 
*vp, u32 offset, u32 v)
        regmap_write(vp->vop2->map, vp->data->offset + offset, v);
 }
 
+static inline void vop2_vp_update_bits(struct vop2_video_port *vp, u32 offset,
+                                      u32 mask, u32 v)
+{
+       regmap_update_bits(vp->vop2->map, vp->data->offset + offset, mask, v);
+}
+
 static inline u32 vop2_readl(struct vop2 *vop2, u32 offset)
 {
        u32 val;

-- 
2.55.0

Reply via email to