From b17b3c93780156a5f3fbdaf836413f21f668d9f2 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Fri, 18 Oct 2013 18:27:43 +0200 Subject: [PATCH] uterm: drm: retry DRM wakeup after short timeout If drm-wakeup fails, we now retry after 20ms continously to gain DRM-Master again. If we succeed we send UTERM_REFRESH events for all available displays so existing code can pick it up. Signed-off-by: David Herrmann --- src/uterm_drm2d_video.c | 4 +++- src/uterm_drm3d_video.c | 4 +++- src/uterm_drm_shared.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/uterm_drm_shared_internal.h | 2 ++ src/uterm_video.h | 1 + 5 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/uterm_drm2d_video.c b/src/uterm_drm2d_video.c index cf40312..a784c0c 100644 --- a/src/uterm_drm2d_video.c +++ b/src/uterm_drm2d_video.c @@ -362,8 +362,10 @@ static int video_wake_up(struct uterm_video *video) int ret; ret = uterm_drm_video_wake_up(video); - if (ret) + if (ret) { + uterm_drm_video_arm_vt_timer(video); return ret; + } show_displays(video); return 0; diff --git a/src/uterm_drm3d_video.c b/src/uterm_drm3d_video.c index c291c8a..2184e71 100644 --- a/src/uterm_drm3d_video.c +++ b/src/uterm_drm3d_video.c @@ -551,8 +551,10 @@ static int video_wake_up(struct uterm_video *video) int ret; ret = uterm_drm_video_wake_up(video); - if (ret) + if (ret) { + uterm_drm_video_arm_vt_timer(video); return ret; + } show_displays(video); return 0; diff --git a/src/uterm_drm_shared.c b/src/uterm_drm_shared.c index c66ed8f..75830f3 100644 --- a/src/uterm_drm_shared.c +++ b/src/uterm_drm_shared.c @@ -461,6 +461,36 @@ static void io_event(struct ev_fd *fd, int mask, void *data) } } +static void vt_timeout(struct ev_timer *timer, uint64_t exp, void *data) +{ + struct uterm_video *video = data; + struct uterm_drm_video *vdrm = video->data; + struct uterm_display *disp; + struct shl_dlist *iter; + int r; + + r = uterm_drm_video_wake_up(video); + if (!r) { + ev_timer_update(vdrm->vt_timer, NULL); + shl_dlist_for_each(iter, &video->displays) { + disp = shl_dlist_entry(iter, struct uterm_display, list); + VIDEO_CB(video, disp, UTERM_REFRESH); + } + } +} + +void uterm_drm_video_arm_vt_timer(struct uterm_video *video) +{ + struct uterm_drm_video *vdrm = video->data; + struct itimerspec spec; + + spec.it_value.tv_sec = 0; + spec.it_value.tv_nsec = 20L * 1000L * 1000L; /* 20ms */ + spec.it_interval = spec.it_value; + + ev_timer_update(vdrm->vt_timer, &spec); +} + int uterm_drm_video_init(struct uterm_video *video, const char *node, const struct display_ops *display_ops, uterm_drm_page_flip_t pflip, void *data) @@ -497,9 +527,16 @@ int uterm_drm_video_init(struct uterm_video *video, const char *node, if (ret) goto err_fd; + ret = ev_eloop_new_timer(video->eloop, &vdrm->vt_timer, NULL, + vt_timeout, video); + if (ret) + goto err_timer; + video->flags |= VIDEO_HOTPLUG; return 0; +err_timer: + shl_timer_free(vdrm->timer); err_fd: ev_eloop_rm_fd(vdrm->efd); err_close: @@ -513,6 +550,7 @@ void uterm_drm_video_destroy(struct uterm_video *video) { struct uterm_drm_video *vdrm = video->data; + ev_eloop_rm_timer(vdrm->vt_timer); ev_eloop_unregister_idle_cb(video->eloop, do_pflips, video, EV_SINGLE); shl_timer_free(vdrm->timer); ev_eloop_rm_fd(vdrm->efd); @@ -705,6 +743,8 @@ void uterm_drm_video_sleep(struct uterm_video *video) struct uterm_drm_video *vdrm = video->data; drmDropMaster(vdrm->fd); + ev_timer_drain(vdrm->vt_timer, NULL); + ev_timer_update(vdrm->vt_timer, NULL); } int uterm_drm_video_poll(struct uterm_video *video) diff --git a/src/uterm_drm_shared_internal.h b/src/uterm_drm_shared_internal.h index e76ec33..c2191e6 100644 --- a/src/uterm_drm_shared_internal.h +++ b/src/uterm_drm_shared_internal.h @@ -98,6 +98,7 @@ struct uterm_drm_video { uterm_drm_page_flip_t page_flip; void *data; struct shl_timer *timer; + struct ev_timer *vt_timer; const struct display_ops *display_ops; }; @@ -113,6 +114,7 @@ void uterm_drm_video_sleep(struct uterm_video *video); int uterm_drm_video_poll(struct uterm_video *video); int uterm_drm_video_wait_pflip(struct uterm_video *video, unsigned int *mtimeout); +void uterm_drm_video_arm_vt_timer(struct uterm_video *video); static inline void *uterm_drm_video_get_data(struct uterm_video *video) { diff --git a/src/uterm_video.h b/src/uterm_video.h index 4fe3845..9f516c5 100644 --- a/src/uterm_video.h +++ b/src/uterm_video.h @@ -80,6 +80,7 @@ enum uterm_video_action { UTERM_SLEEP, UTERM_NEW, UTERM_GONE, + UTERM_REFRESH, }; struct uterm_video_hotplug { -- 2.7.4