diff options
Diffstat (limited to 'drivers/gpu/drm/virtio/virtgpu_display.c')
| -rw-r--r-- | drivers/gpu/drm/virtio/virtgpu_display.c | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index 4b1252c04b7a..e972d9b015a9 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -32,6 +32,8 @@ #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> +#include <drm/drm_vblank.h> +#include <drm/drm_vblank_helper.h> #include "virtgpu_drv.h" @@ -55,6 +57,7 @@ static const struct drm_crtc_funcs virtio_gpu_crtc_funcs = { .reset = drm_atomic_helper_crtc_reset, .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, + DRM_CRTC_VBLANK_TIMER_FUNCS, }; static const struct drm_framebuffer_funcs virtio_gpu_fb_funcs = { @@ -99,6 +102,7 @@ static void virtio_gpu_crtc_mode_set_nofb(struct drm_crtc *crtc) static void virtio_gpu_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state) { + drm_crtc_vblank_on(crtc); } static void virtio_gpu_crtc_atomic_disable(struct drm_crtc *crtc, @@ -108,6 +112,8 @@ static void virtio_gpu_crtc_atomic_disable(struct drm_crtc *crtc, struct virtio_gpu_device *vgdev = dev->dev_private; struct virtio_gpu_output *output = drm_crtc_to_virtio_gpu_output(crtc); + drm_crtc_vblank_off(crtc); + virtio_gpu_cmd_set_scanout(vgdev, output->index, 0, 0, 0, 0, 0); virtio_gpu_notify(vgdev); } @@ -121,9 +127,10 @@ static int virtio_gpu_crtc_atomic_check(struct drm_crtc *crtc, static void virtio_gpu_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *state) { - struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, - crtc); + struct drm_device *dev = crtc->dev; + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); struct virtio_gpu_output *output = drm_crtc_to_virtio_gpu_output(crtc); + struct drm_pending_vblank_event *event; /* * virtio-gpu can't do modeset and plane update operations @@ -133,6 +140,20 @@ static void virtio_gpu_crtc_atomic_flush(struct drm_crtc *crtc, */ if (drm_atomic_crtc_needs_modeset(crtc_state)) output->needs_modeset = true; + + spin_lock_irq(&dev->event_lock); + + event = crtc_state->event; + crtc_state->event = NULL; + + if (event) { + if (drm_crtc_vblank_get(crtc) == 0) + drm_crtc_arm_vblank_event(crtc, event); + else + drm_crtc_send_vblank_event(crtc, event); + } + + spin_unlock_irq(&dev->event_lock); } static const struct drm_crtc_helper_funcs virtio_gpu_crtc_helper_funcs = { @@ -359,6 +380,10 @@ int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev) for (i = 0 ; i < vgdev->num_scanouts; ++i) vgdev_output_init(vgdev, i); + ret = drm_vblank_init(vgdev->ddev, vgdev->num_scanouts); + if (ret) + return ret; + drm_mode_config_reset(vgdev->ddev); return 0; } |