From: Marek Szyprowski Date: Thu, 16 Nov 2023 09:36:32 +0000 (+0100) Subject: drm: virtio_gpu: add fake timer based vblank handler X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f33ed9b205bb80d3a191d3eeefe4c1ec6764730d;p=sdk%2Femulator%2Femulator-kernel.git drm: virtio_gpu: add fake timer based vblank handler Signed-off-by: Marek Szyprowski --- diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index 9ea7611a9e0f..80691ea6020a 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "virtgpu_drv.h" @@ -44,9 +45,56 @@ #define XRES_MAX 8192 #define YRES_MAX 8192 +#define FAKE_VBLANK_TIME (1000 / 50) + #define drm_connector_to_virtio_gpu_output(x) \ container_of(x, struct virtio_gpu_output, conn) +static void virtio_gpu_fake_vblank_timer(struct timer_list *t) +{ + struct virtio_gpu_device *vgdev = from_timer(vgdev, t, + fake_vblank_timer); + /* TODO: use proper output index */ + 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); +} + +static int virtio_gpu_crtc_enable_vblank(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct virtio_gpu_device *vgdev = dev->dev_private; + + mod_timer(&vgdev->fake_vblank_timer, + jiffies + msecs_to_jiffies(FAKE_VBLANK_TIME) - 1); + + return 0; +} + +static void virtio_gpu_crtc_disable_vblank(struct drm_crtc *crtc) +{ +} + +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, @@ -55,6 +103,8 @@ 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, + .enable_vblank = virtio_gpu_crtc_enable_vblank, + .disable_vblank = virtio_gpu_crtc_disable_vblank, }; static const struct drm_framebuffer_funcs virtio_gpu_fb_funcs = { @@ -98,6 +148,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, @@ -107,6 +158,14 @@ 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); + 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); virtio_gpu_notify(vgdev); } @@ -133,6 +192,8 @@ static void virtio_gpu_crtc_atomic_flush(struct drm_crtc *crtc, if (drm_atomic_crtc_needs_modeset(crtc_state)) { output->needs_modeset = true; } + + virtio_gpu_crtc_handle_event(crtc); } static const struct drm_crtc_helper_funcs virtio_gpu_crtc_helper_funcs = { @@ -334,27 +395,34 @@ 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, ret; - ret = drmm_mode_config_init(vgdev->ddev); + ret = drmm_mode_config_init(dev); if (ret) return ret; - vgdev->ddev->mode_config.quirk_addfb_prefer_host_byte_order = true; - vgdev->ddev->mode_config.funcs = &virtio_gpu_mode_funcs; + timer_setup(&vgdev->fake_vblank_timer, virtio_gpu_fake_vblank_timer, 0); + + dev->mode_config.quirk_addfb_prefer_host_byte_order = true; + dev->mode_config.funcs = &virtio_gpu_mode_funcs; /* modes will be validated against the framebuffer size */ - vgdev->ddev->mode_config.min_width = XRES_MIN; - vgdev->ddev->mode_config.min_height = YRES_MIN; - vgdev->ddev->mode_config.max_width = XRES_MAX; - vgdev->ddev->mode_config.max_height = YRES_MAX; + dev->mode_config.min_width = XRES_MIN; + dev->mode_config.min_height = YRES_MIN; + dev->mode_config.max_width = XRES_MAX; + dev->mode_config.max_height = YRES_MAX; vgdev->ddev->mode_config.fb_modifiers_not_supported = true; for (i = 0 ; i < vgdev->num_scanouts; ++i) vgdev_output_init(vgdev, i); - drm_mode_config_reset(vgdev->ddev); + ret = drm_vblank_init(dev, dev->mode_config.num_crtc); + if (ret) + return ret; + + drm_mode_config_reset(dev); return 0; } diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 9b98470593b0..6083966a34a6 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -262,6 +262,8 @@ struct virtio_gpu_device { spinlock_t resource_export_lock; /* protects map state and host_visible_mm */ spinlock_t host_visible_lock; + + struct timer_list fake_vblank_timer; }; struct virtio_gpu_fpriv {