struct drm_property *dtrc_table_ofs;
struct completion disable_completion;
+ struct drm_pending_vblank_event *event;
+ int vblank_cnt;
};
static void dcss_crtc_reset(struct drm_crtc *crtc)
static void dcss_crtc_atomic_begin(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
- drm_crtc_vblank_on(crtc);
+ struct dcss_crtc *dcss_crtc = container_of(crtc, struct dcss_crtc,
+ base);
- spin_lock_irq(&crtc->dev->event_lock);
if (crtc->state->event) {
- WARN_ON(drm_crtc_vblank_get(crtc));
- drm_crtc_arm_vblank_event(crtc, crtc->state->event);
+ crtc->state->event->pipe = drm_crtc_index(crtc);
+
+ WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+ dcss_crtc->event = crtc->state->event;
crtc->state->event = NULL;
+ dcss_crtc->vblank_cnt = 0;
}
- spin_unlock_irq(&crtc->dev->event_lock);
}
static void dcss_crtc_atomic_flush(struct drm_crtc *crtc,
dcss_dtg_enable(dcss, true, NULL);
dcss_ctxld_enable(dcss);
+ drm_crtc_vblank_on(crtc);
+
crtc->enabled = true;
}
static irqreturn_t dcss_crtc_irq_handler(int irq, void *dev_id)
{
struct dcss_crtc *dcss_crtc = dev_id;
+ struct drm_device *drm = dcss_crtc->base.dev;
+ struct drm_crtc *crtc = &dcss_crtc->base;
struct dcss_soc *dcss = dev_get_drvdata(dcss_crtc->dev->parent);
+ unsigned long flags;
drm_crtc_handle_vblank(&dcss_crtc->base);
+ spin_lock_irqsave(&drm->event_lock, flags);
+ if (dcss_crtc->event && !dcss_crtc->vblank_cnt--) {
+ drm_crtc_send_vblank_event(crtc, dcss_crtc->event);
+ drm_crtc_vblank_put(crtc);
+ dcss_crtc->event = NULL;
+ }
+ spin_unlock_irqrestore(&drm->event_lock, flags);
+
dcss_vblank_irq_clear(dcss);
return IRQ_HANDLED;