aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorGreg Hackmann <ghackmann@google.com>2012-04-09 11:10:17 -0700
committerGreg Hackmann <ghackmann@google.com>2012-04-24 16:47:40 -0700
commitb2ffbf603ef3910c056cd6c6c20aff2160302eba (patch)
tree03008850bde219134ea67d40f483afc8b1b8076b /drivers/video
parentd5814c37cde157c5d23431d40466220843e86e44 (diff)
downloadkernel_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-xdrivers/video/samsung/s3cfb.c19
-rw-r--r--drivers/video/samsung/s3cfb.h4
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;