diff options
author | Greg Hackmann <ghackmann@google.com> | 2012-04-09 11:10:17 -0700 |
---|---|---|
committer | Greg Hackmann <ghackmann@google.com> | 2012-04-24 16:47:40 -0700 |
commit | b2ffbf603ef3910c056cd6c6c20aff2160302eba (patch) | |
tree | 03008850bde219134ea67d40f483afc8b1b8076b /drivers/video | |
parent | d5814c37cde157c5d23431d40466220843e86e44 (diff) | |
download | kernel_samsung_aries-b2ffbf603ef3910c056cd6c6c20aff2160302eba.zip kernel_samsung_aries-b2ffbf603ef3910c056cd6c6c20aff2160302eba.tar.gz kernel_samsung_aries-b2ffbf603ef3910c056cd6c6c20aff2160302eba.tar.bz2 |
s3cfb: replace vsync completion with waitqueue
Completions can't be reused after complete_all() unless they're reinitialized. Borrow intelfb's approach of using a wq and a counter instead.
Change-Id: Idf8faa308fbbb1a75989d99c44be76c6e6f3f5ab
Signed-off-by: Greg Hackmann <ghackmann@google.com>
Diffstat (limited to 'drivers/video')
-rwxr-xr-x | drivers/video/samsung/s3cfb.c | 19 | ||||
-rw-r--r-- | drivers/video/samsung/s3cfb.h | 4 |
2 files changed, 18 insertions, 5 deletions
diff --git a/drivers/video/samsung/s3cfb.c b/drivers/video/samsung/s3cfb.c index 21f758c..c45acfd 100755 --- a/drivers/video/samsung/s3cfb.c +++ b/drivers/video/samsung/s3cfb.c @@ -113,10 +113,18 @@ static irqreturn_t s3cfb_irq_frame(int irq, void *data) s3cfb_clear_interrupt(fbdev); - complete_all(&fbdev->fb_complete); + fbdev->vsync_timestamp = ktime_get(); + wmb(); + wake_up_interruptible(&fbdev->vsync_wq); return IRQ_HANDLED; } +static int s3cfb_vsync_timestamp_changed(struct s3cfb_global *fbdev, + ktime_t prev_timestamp) +{ + rmb(); + return !ktime_equal(prev_timestamp, fbdev->vsync_timestamp); +} static void s3cfb_set_window(struct s3cfb_global *ctrl, int id, int enable) { struct s3cfb_window *win = ctrl->fb[id]->par; @@ -134,7 +142,7 @@ static int s3cfb_init_global(struct s3cfb_global *ctrl) ctrl->output = OUTPUT_RGB; ctrl->rgb_mode = MODE_RGB_P; - init_completion(&ctrl->fb_complete); + init_waitqueue_head(&ctrl->vsync_wq); mutex_init(&ctrl->lock); s3cfb_set_output(ctrl); @@ -561,12 +569,15 @@ static int s3cfb_release(struct fb_info *fb, int user) static int s3cfb_wait_for_vsync(struct s3cfb_global *ctrl) { + ktime_t prev_timestamp; int ret; dev_dbg(ctrl->dev, "waiting for VSYNC interrupt\n"); - ret = wait_for_completion_interruptible_timeout( - &ctrl->fb_complete, msecs_to_jiffies(100)); + prev_timestamp = ctrl->vsync_timestamp; + ret = wait_event_interruptible_timeout(ctrl->vsync_wq, + s3cfb_vsync_timestamp_changed(ctrl, prev_timestamp), + msecs_to_jiffies(100)); if (ret == 0) return -ETIMEDOUT; if (ret < 0) diff --git a/drivers/video/samsung/s3cfb.h b/drivers/video/samsung/s3cfb.h index 190d90a..3fb1956 100644 --- a/drivers/video/samsung/s3cfb.h +++ b/drivers/video/samsung/s3cfb.h @@ -231,7 +231,9 @@ struct s3cfb_global { struct regulator *vlcd; int irq; struct fb_info **fb; - struct completion fb_complete; + + wait_queue_head_t vsync_wq; + ktime_t vsync_timestamp; /* fimd */ int enabled; |