[8895] media: smfc: add sync mode for hwfc
authorWon Jung <w00.jung@samsung.com>
Wed, 1 Jun 2016 06:48:09 +0000 (15:48 +0900)
committerSeungchul Kim <sc377.kim@samsung.com>
Mon, 28 May 2018 05:31:19 +0000 (14:31 +0900)
add sync mode for hwfc. This mode is to inform camera
that hwjpeg compression is done in HWFC mode.

Change-Id: I7cdf276069b3ffb83a342aeb50f338bdf9d7c5ae
Signed-off-by: Won Jung <w00.jung@samsung.com>
drivers/media/platform/exynos/smfc/smfc-sync.h [new file with mode: 0644]
drivers/media/platform/exynos/smfc/smfc.c

diff --git a/drivers/media/platform/exynos/smfc/smfc-sync.h b/drivers/media/platform/exynos/smfc/smfc-sync.h
new file mode 100644 (file)
index 0000000..8a5e692
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * The main header file of Samsung Exynos SMFC Driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _MEDIA_EXYNOS_SMFC_SYNC_H_
+#define _MEDIA_EXYNOS_SMFC_SYNC_H_
+
+int exynos_smfc_wait_done(bool enable_hwfc);
+
+#endif /* _MEDIA_EXYNOS_SMFC_SYNC_H_ */
index 384d1cea22df0a74cf3e616cd3e25f659303aac2..39d2f7bab80b2dae925343a3473f4fd85d1ed740 100644 (file)
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/mutex.h>
+#include <linux/wait.h>
 #include <linux/exynos_iovmm.h>
 
 #include <media/videobuf2-core.h>
 #include <media/videobuf2-dma-sg.h>
 
 #include "smfc.h"
+#include "smfc-sync.h"
+
+static atomic_t smfc_hwfc_state;
+static wait_queue_head_t smfc_hwfc_sync_wq;
+
+enum {
+       SMFC_HWFC_STANDBY = 0,
+       SMFC_HWFC_RUN,
+       SMFC_HWFC_WAIT,
+};
 
 static irqreturn_t exynos_smfc_irq_handler(int irq, void *priv)
 {
@@ -88,6 +99,11 @@ static irqreturn_t exynos_smfc_irq_handler(int irq, void *priv)
                        }
 
                        v4l2_m2m_buf_done(vb, state);
+
+                       if ((!!(ctx->flags & SMFC_CTX_COMPRESS)) && ctx->enable_hwfc) {
+                               atomic_set(&smfc_hwfc_state, SMFC_HWFC_STANDBY);
+                               wake_up(&smfc_hwfc_sync_wq);
+                       }
                }
 
                vb->vb2_buf.timestamp =
@@ -377,6 +393,26 @@ static int smfc_queue_init(void *priv, struct vb2_queue *src_vq,
        return vb2_queue_init(dst_vq);
 }
 
+int exynos_smfc_wait_done(bool enable_hwfc)
+{
+       int prev, new;
+       int ret = 0;
+
+       ret = wait_event_interruptible(smfc_hwfc_sync_wq,
+                       atomic_read(&smfc_hwfc_state) < SMFC_HWFC_WAIT);
+
+       if(ret < 0)
+               return ret;
+
+       prev = atomic_read(&smfc_hwfc_state);
+       while (enable_hwfc && prev == SMFC_HWFC_RUN
+                       && (new = atomic_cmpxchg((&smfc_hwfc_state),
+                                       prev, SMFC_HWFC_WAIT)) != prev)
+               prev = new;
+
+       return ret;
+}
+
 static int exynos_smfc_open(struct file *filp)
 {
        struct smfc_dev *smfc = video_drvdata(filp);
@@ -577,8 +613,10 @@ static void smfc_m2m_device_run(void *priv)
         * SMFC internal timer is unavailable if HWFC is enabled
         * Therefore, S/W timer object is used to detect unexpected delay.
         */
-       if (!!enable_hwfc)
+       if (!!enable_hwfc) {
                mod_timer(&ctx->smfc->timer, jiffies + HZ); /* 1 sec. */
+               atomic_set(&smfc_hwfc_state, SMFC_HWFC_RUN);
+       }
 
        ctx->ktime_beg = ktime_get();
 
@@ -816,6 +854,9 @@ static int exynos_smfc_probe(struct platform_device *pdev)
        const struct of_device_id *of_id;
        int ret;
 
+       atomic_set(&smfc_hwfc_state, SMFC_HWFC_STANDBY);
+       init_waitqueue_head(&smfc_hwfc_sync_wq);
+
        smfc = devm_kzalloc(&pdev->dev, sizeof(*smfc), GFP_KERNEL);
        if (!smfc) {
                dev_err(&pdev->dev, "Failed to get allocate drvdata");