return true;
}
-static enum hrtimer_restart
-vmw_vkms_vblank_simulate(struct hrtimer *timer)
-{
- struct vmw_display_unit *du = container_of(timer, struct vmw_display_unit, vkms.timer);
- struct drm_crtc *crtc = &du->crtc;
- u64 ret_overrun;
- bool success;
-
- ret_overrun = hrtimer_forward_now(&du->vkms.timer,
- du->vkms.period_ns);
- if (ret_overrun != 1)
- drm_dbg_driver(crtc->dev, "vblank timer missed %lld frames.\n",
- ret_overrun - 1);
-
- success = vmw_vkms_handle_vblank_timeout(crtc);
- if (!success)
- return HRTIMER_NORESTART;
-
- return HRTIMER_RESTART;
-}
-
void
vmw_vkms_init(struct vmw_private *vmw)
{
ktime_t *vblank_time,
bool in_vblank_irq)
{
- struct drm_device *dev = crtc->dev;
- struct vmw_private *vmw = vmw_priv(dev);
- struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
- struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
+ struct vmw_private *vmw = vmw_priv(crtc->dev);
if (!vmw->vkms_enabled)
return false;
- if (!READ_ONCE(vblank->enabled)) {
- *vblank_time = ktime_get();
- return true;
- }
-
- *vblank_time = READ_ONCE(du->vkms.timer.node.expires);
-
- if (WARN_ON(*vblank_time == vblank->time))
- return true;
-
- /*
- * To prevent races we roll the hrtimer forward before we do any
- * interrupt processing - this is how real hw works (the interrupt is
- * only generated after all the vblank registers are updated) and what
- * the vblank core expects. Therefore we need to always correct the
- * timestampe by one frame.
- */
- *vblank_time -= du->vkms.period_ns;
+ drm_crtc_vblank_get_vblank_timeout(crtc, vblank_time);
return true;
}
{
struct drm_device *dev = crtc->dev;
struct vmw_private *vmw = vmw_priv(dev);
- struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
- struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
if (!vmw->vkms_enabled)
return -EINVAL;
- drm_calc_timestamping_constants(crtc, &crtc->mode);
-
- hrtimer_setup(&du->vkms.timer, &vmw_vkms_vblank_simulate, CLOCK_MONOTONIC,
- HRTIMER_MODE_REL);
- du->vkms.period_ns = ktime_set(0, vblank->framedur_ns);
- hrtimer_start(&du->vkms.timer, du->vkms.period_ns, HRTIMER_MODE_REL);
-
- return 0;
+ return drm_crtc_vblank_start_timer(crtc);
}
void
if (!vmw->vkms_enabled)
return;
- hrtimer_cancel(&du->vkms.timer);
+ drm_crtc_vblank_cancel_timer(crtc);
+
du->vkms.surface = NULL;
- du->vkms.period_ns = ktime_set(0, 0);
}
enum vmw_vkms_lock_state {
void
vmw_vkms_crtc_cleanup(struct drm_crtc *crtc)
{
+ struct vmw_private *vmw = vmw_priv(crtc->dev);
struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
+ if (vmw->vkms_enabled)
+ drm_crtc_vblank_cancel_timer(crtc);
+
if (du->vkms.surface)
vmw_surface_unreference(&du->vkms.surface);
WARN_ON(work_pending(&du->vkms.crc_generator_work));
- hrtimer_cancel(&du->vkms.timer);
}
void