#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 "virtgpu_drv.h"
#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,
.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 = {
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,
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);
}
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 = {
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;
}