drm: virtio_gpu: add fake timer based vblank handler sandbox/mmajewski2/4.9
authorMarek Szyprowski <m.szyprowski@samsung.com>
Thu, 16 Nov 2023 09:36:32 +0000 (10:36 +0100)
committerMarek Szyprowski <m.szyprowski@samsung.com>
Mon, 3 Jun 2024 09:33:39 +0000 (11:33 +0200)
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
drivers/gpu/drm/virtio/virtgpu_display.c
drivers/gpu/drm/virtio/virtgpu_drv.c
drivers/gpu/drm/virtio/virtgpu_drv.h

index 58048709c34e6ca0f48b03b3bc5638a3b93d7226..1ea7f21855719a7811a3a6b378c33a0be7a8513b 100644 (file)
 #define XRES_MAX  8192
 #define YRES_MAX  8192
 
+#define FAKE_VBLANK_TIME (1000 / 50)
+
+static void virio_gpu_fake_vblank_timer(unsigned long arg)
+{
+       struct virtio_gpu_device *vgdev = (void *)arg;
+       struct virtio_gpu_output *output = vgdev->outputs + 0;
+
+       if (drm_crtc_handle_vblank(&output->crtc))
+               mod_timer(&vgdev->fake_vblank_timer,
+                       jiffies + msecs_to_jiffies(FAKE_VBLANK_TIME) - 1);
+}
+
+int virtio_gpu_enable_vblank(struct drm_device *dev, unsigned int num)
+{
+       struct virtio_gpu_device *vgdev = dev->dev_private;
+
+       mod_timer(&vgdev->fake_vblank_timer,
+               jiffies + msecs_to_jiffies(FAKE_VBLANK_TIME) - 1);
+
+       return 0;
+}
+
+void virtio_gpu_disable_vblank(struct drm_device *dev, unsigned int num)
+{
+}
+
+static void virtio_gpu_crtc_handle_event(struct drm_crtc *crtc)
+{
+       struct drm_pending_vblank_event *event = crtc->state->event;
+       unsigned long flags;
+
+       if (!event)
+               return;
+
+       crtc->state->event = NULL;
+
+       spin_lock_irqsave(&crtc->dev->event_lock, flags);
+       if (drm_crtc_vblank_get(crtc) == 0)
+               drm_crtc_arm_vblank_event(crtc, event);
+       else
+               drm_crtc_send_vblank_event(crtc, event);
+       spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+}
+
 static const struct drm_crtc_funcs virtio_gpu_crtc_funcs = {
        .set_config             = drm_atomic_helper_set_config,
        .destroy                = drm_crtc_cleanup,
@@ -114,6 +158,7 @@ static void virtio_gpu_crtc_mode_set_nofb(struct drm_crtc *crtc)
 
 static void virtio_gpu_crtc_enable(struct drm_crtc *crtc)
 {
+       drm_crtc_vblank_on(crtc);
 }
 
 static void virtio_gpu_crtc_disable(struct drm_crtc *crtc)
@@ -122,6 +167,14 @@ static void virtio_gpu_crtc_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);
 
+       spin_lock_irq(&dev->event_lock);
+       if (crtc->state->event) {
+               drm_crtc_send_vblank_event(crtc, crtc->state->event);
+               crtc->state->event = NULL;
+       }
+       spin_unlock_irq(&dev->event_lock);
+
+       drm_crtc_vblank_off(crtc);
        virtio_gpu_cmd_set_scanout(vgdev, output->index, 0, 0, 0, 0, 0);
 }
 
@@ -134,13 +187,7 @@ static int virtio_gpu_crtc_atomic_check(struct drm_crtc *crtc,
 static void virtio_gpu_crtc_atomic_flush(struct drm_crtc *crtc,
                                         struct drm_crtc_state *old_state)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(&crtc->dev->event_lock, flags);
-       if (crtc->state->event)
-               drm_crtc_send_vblank_event(crtc, crtc->state->event);
-       crtc->state->event = NULL;
-       spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+       virtio_gpu_crtc_handle_event(crtc);
 }
 
 static const struct drm_crtc_helper_funcs virtio_gpu_crtc_helper_funcs = {
@@ -358,9 +405,11 @@ static const struct drm_mode_config_funcs virtio_gpu_mode_funcs = {
 
 int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev)
 {
+       struct drm_device *dev = vgdev->ddev;
        int i;
 
        drm_mode_config_init(vgdev->ddev);
+       setup_timer(&vgdev->fake_vblank_timer, virio_gpu_fake_vblank_timer, (unsigned long)vgdev);
        vgdev->ddev->mode_config.funcs = &virtio_gpu_mode_funcs;
        vgdev->ddev->mode_config.helper_private = &virtio_mode_config_helpers;
 
@@ -374,6 +423,8 @@ int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev)
                vgdev_output_init(vgdev, i);
 
         drm_mode_config_reset(vgdev->ddev);
+       drm_vblank_init(dev, dev->mode_config.num_crtc);
+
        return 0;
 }
 
index 5820b7020ae5ab07dad986ddf5fb91ac17a0ca43..128ef4a281ccaf253b161686df940f01cabfb440 100644 (file)
@@ -127,6 +127,10 @@ static struct drm_driver driver = {
        .dumb_map_offset = virtio_gpu_mode_dumb_mmap,
        .dumb_destroy = virtio_gpu_mode_dumb_destroy,
 
+       .get_vblank_counter     = drm_vblank_no_hw_counter,
+       .enable_vblank          = virtio_gpu_enable_vblank,
+       .disable_vblank         = virtio_gpu_disable_vblank,
+
 #if defined(CONFIG_DEBUG_FS)
        .debugfs_init = virtio_gpu_debugfs_init,
        .debugfs_cleanup = virtio_gpu_debugfs_takedown,
index 3949b688c714280239d089f57885f165e4eb53d0..d3b7148481795a3926ae98606423046c9d029adb 100644 (file)
@@ -205,6 +205,8 @@ struct virtio_gpu_device {
        struct virtio_gpu_drv_capset *capsets;
        uint32_t num_capsets;
        struct list_head cap_cache;
+
+       struct timer_list fake_vblank_timer;
 };
 
 struct virtio_gpu_fpriv {
@@ -428,4 +430,7 @@ static inline void virtio_gpu_object_unreserve(struct virtio_gpu_object *bo)
 int virtio_gpu_debugfs_init(struct drm_minor *minor);
 void virtio_gpu_debugfs_takedown(struct drm_minor *minor);
 
+int virtio_gpu_enable_vblank(struct drm_device *, unsigned int);
+void virtio_gpu_disable_vblank(struct drm_device *, unsigned int);
+
 #endif