From b0e45a94fcd0987a23f3320cdba073c10e034d78 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Thu, 16 Nov 2023 10:36:32 +0100 Subject: [PATCH] drm: virtio_gpu: add fake timer based vblank handler Signed-off-by: Marek Szyprowski --- drivers/gpu/drm/virtio/virtgpu_display.c | 84 +++++++++++++++++++++++++++++--- drivers/gpu/drm/virtio/virtgpu_drv.h | 2 + 2 files changed, 78 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index 9ea7611..13cfe88 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,53 @@ #define XRES_MAX 8192 #define YRES_MAX 8192 +#define VIDI_REFRESH_TIME (1000 / 50) + #define drm_connector_to_virtio_gpu_output(x) \ container_of(x, struct virtio_gpu_output, conn) +static void vidi_fake_vblank_timer(struct timer_list *t) +{ + struct virtio_gpu_device *vgdev = from_timer(vgdev, t, fake_vblank_timer); + struct virtio_gpu_output *output = vgdev->outputs + 0; //index; + struct drm_crtc *crtc = &output->crtc; + + if (drm_crtc_handle_vblank(crtc)) + mod_timer(&vgdev->fake_vblank_timer, + jiffies + msecs_to_jiffies(VIDI_REFRESH_TIME) - 1); +} + +static int exynos_drm_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(VIDI_REFRESH_TIME) - 1); + + return 0; +} + +static void exynos_drm_crtc_disable_vblank(struct drm_crtc *crtc) +{ +} + +static void exynos_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; + + WARN_ON(drm_crtc_vblank_get(crtc) != 0); + + spin_lock_irqsave(&crtc->dev->event_lock, flags); + drm_crtc_arm_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 +100,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 = exynos_drm_crtc_enable_vblank, + .disable_vblank = exynos_drm_crtc_disable_vblank, }; static const struct drm_framebuffer_funcs virtio_gpu_fb_funcs = { @@ -98,6 +145,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 +155,16 @@ 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); + + if (crtc->state->event && !crtc->state->active) { + spin_lock_irq(&crtc->dev->event_lock); + drm_crtc_send_vblank_event(crtc, crtc->state->event); + spin_unlock_irq(&crtc->dev->event_lock); + + crtc->state->event = NULL; + } + virtio_gpu_cmd_set_scanout(vgdev, output->index, 0, 0, 0, 0, 0); virtio_gpu_notify(vgdev); } @@ -133,6 +191,8 @@ static void virtio_gpu_crtc_atomic_flush(struct drm_crtc *crtc, if (drm_atomic_crtc_needs_modeset(crtc_state)) { output->needs_modeset = true; } + + exynos_crtc_handle_event(crtc); } static const struct drm_crtc_helper_funcs virtio_gpu_crtc_helper_funcs = { @@ -334,27 +394,35 @@ 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, vidi_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); + printk("drm_vblank_init %d\n", ret); + 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 9b98470..6083966 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 { -- 2.7.4