mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
drm/rockchip: vop2: Add vcnt event
Change-Id: If00eeee975d8f073d27ae584c096e6a7de1df95b Signed-off-by: Andy Yan <andy.yan@rock-chips.com> Signed-off-by: Sandy Huang <hjc@rock-chips.com>
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user