From 4d56f3cc519a8b7906b3b536b938bfc6cf6682bf Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Fri, 16 Jul 2021 19:11:21 +0800 Subject: [PATCH] drm/rockchip: vop2: Add vcnt event Change-Id: If00eeee975d8f073d27ae584c096e6a7de1df95b Signed-off-by: Andy Yan Signed-off-by: Sandy Huang --- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 1 + drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 98 +++++++++++++++++++- 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 29c66036f72f..d2f6a6fc924b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -101,6 +101,7 @@ struct rockchip_crtc_state { int color_space; int eotf; u32 background; + u32 line_flag; u8 mode_update; struct rockchip_hdr_state hdr; }; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 05290112e9b2..8a67a7214937 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -540,6 +540,7 @@ struct vop2 { struct drm_property *vp_id_prop; struct drm_property *aclk_prop; struct drm_property *bg_prop; + struct drm_property *line_flag_prop; struct drm_prop_enum_list *plane_name_list; bool is_iommu_enabled; bool is_iommu_needed; @@ -3506,6 +3507,49 @@ static void vop2_crtc_cancel_pending_vblank(struct drm_crtc *crtc, spin_unlock_irqrestore(&drm->event_lock, flags); } +static int vop2_crtc_enable_line_flag_event(struct drm_crtc *crtc, uint32_t line) +{ + struct vop2_video_port *vp = to_vop2_video_port(crtc); + struct vop2 *vop2 = vp->vop2; + const struct vop2_data *vop2_data = vop2->data; + const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id]; + const struct vop_intr *intr = vp_data->intr; + unsigned long flags; + + if (WARN_ON(!vop2->is_enabled)) + return -EPERM; + + spin_lock_irqsave(&vop2->irq_lock, flags); + + VOP_INTR_SET(vop2, intr, line_flag_num[1], line); + + VOP_INTR_SET_TYPE(vop2, intr, clear, LINE_FLAG1_INTR, 1); + VOP_INTR_SET_TYPE(vop2, intr, enable, LINE_FLAG1_INTR, 1); + + spin_unlock_irqrestore(&vop2->irq_lock, flags); + + return 0; +} + +static void vop2_crtc_disable_line_flag_event(struct drm_crtc *crtc) +{ + struct vop2_video_port *vp = to_vop2_video_port(crtc); + struct vop2 *vop2 = vp->vop2; + const struct vop2_data *vop2_data = vop2->data; + const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id]; + const struct vop_intr *intr = vp_data->intr; + unsigned long flags; + + if (WARN_ON(!vop2->is_enabled)) + return; + + spin_lock_irqsave(&vop2->irq_lock, flags); + + VOP_INTR_SET_TYPE(vop2, intr, enable, LINE_FLAG1_INTR, 0); + + spin_unlock_irqrestore(&vop2->irq_lock, flags); +} + static int vop2_crtc_loader_protect(struct drm_crtc *crtc, bool on) { struct vop2_video_port *vp = to_vop2_video_port(crtc); @@ -5177,6 +5221,11 @@ static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state VOP_MODULE_SET(vop2, vp, cubic_lut_update_en, 0); } + if (vcstate->line_flag) + vop2_crtc_enable_line_flag_event(crtc, vcstate->line_flag); + else + vop2_crtc_disable_line_flag_event(crtc); + spin_lock_irqsave(&vop2->irq_lock, flags); vop2_wb_commit(crtc); vop2_cfg_done(crtc); @@ -5386,6 +5435,11 @@ static int vop2_crtc_atomic_get_property(struct drm_crtc *crtc, return 0; } + if (property == vop2->line_flag_prop) { + *val = vcstate->line_flag; + return 0; + } + DRM_ERROR("failed to get vop2 crtc property: %s\n", property->name); return -EINVAL; @@ -5428,6 +5482,11 @@ static int vop2_crtc_atomic_set_property(struct drm_crtc *crtc, return 0; } + if (property == vop2->line_flag_prop) { + vcstate->line_flag = val; + return 0; + } + DRM_ERROR("failed to set vop2 crtc property %s\n", property->name); return -EINVAL; @@ -5476,6 +5535,33 @@ static void vop2_handle_vblank(struct vop2 *vop2, struct drm_crtc *crtc) drm_flip_work_commit(&vp->fb_unref_work, system_unbound_wq); } +static void vop2_handle_vcnt(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct rockchip_drm_private *priv = dev->dev_private; + struct rockchip_drm_vcnt *vcnt; + struct drm_pending_vblank_event *e; + struct timespec64 now; + unsigned long irqflags; + int pipe; + + now = ktime_to_timespec64(ktime_get()); + + spin_lock_irqsave(&dev->event_lock, irqflags); + pipe = drm_crtc_index(crtc); + vcnt = &priv->vcnt[pipe]; + vcnt->sequence++; + if (vcnt->event) { + e = vcnt->event; + e->event.vbl.tv_sec = now.tv_sec; + e->event.vbl.tv_usec = now.tv_nsec / NSEC_PER_USEC; + e->event.vbl.sequence = vcnt->sequence; + drm_send_event_locked(dev, &e->base); + vcnt->event = NULL; + } + spin_unlock_irqrestore(&dev->event_lock, irqflags); +} + static u32 vop2_read_and_clear_active_vp_irqs(struct vop2 *vop2, int vp_id) { const struct vop2_data *vop2_data = vop2->data; @@ -5605,6 +5691,12 @@ static irqreturn_t vop2_isr(int irq, void *data) ret = IRQ_HANDLED; } + if (active_irqs & LINE_FLAG1_INTR) { + vop2_handle_vcnt(crtc); + active_irqs &= ~LINE_FLAG1_INTR; + ret = IRQ_HANDLED; + } + if (active_irqs & FS_FIELD_INTR) { vop2_wb_handler(vp); drm_crtc_handle_vblank(crtc); @@ -6026,6 +6118,7 @@ static int vop2_create_crtc(struct vop2 *vop2) drm_object_attach_property(&crtc->base, vop2->vp_id_prop, vp->id); drm_object_attach_property(&crtc->base, vop2->aclk_prop, 0); drm_object_attach_property(&crtc->base, vop2->bg_prop, 0); + drm_object_attach_property(&crtc->base, vop2->line_flag_prop, 0); drm_object_attach_property(&crtc->base, drm_dev->mode_config.tv_left_margin_property, 100); drm_object_attach_property(&crtc->base, @@ -6204,7 +6297,10 @@ static int vop2_win_init(struct vop2 *vop2) vop2->aclk_prop = drm_property_create_range(vop2->drm_dev, 0, "ACLK", 0, UINT_MAX); vop2->bg_prop = drm_property_create_range(vop2->drm_dev, 0, "BACKGROUND", 0, UINT_MAX); - if (!vop2->soc_id_prop || !vop2->vp_id_prop || !vop2->aclk_prop || !vop2->bg_prop) { + vop2->line_flag_prop = drm_property_create_range(vop2->drm_dev, 0, "LINE_FLAG1", 0, UINT_MAX); + + if (!vop2->soc_id_prop || !vop2->vp_id_prop || !vop2->aclk_prop || !vop2->bg_prop || + !vop2->line_flag_prop) { DRM_DEV_ERROR(vop2->dev, "failed to create soc_id/vp_id/aclk property\n"); return -ENOMEM; }