From 156b563354ca5214b00cec41b21c53d6edc29bef Mon Sep 17 00:00:00 2001 From: Won Jung Date: Wed, 1 Jun 2016 15:48:09 +0900 Subject: [PATCH] [8895] media: smfc: add sync mode for hwfc 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 --- .../media/platform/exynos/smfc/smfc-sync.h | 17 ++++++++ drivers/media/platform/exynos/smfc/smfc.c | 43 ++++++++++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 drivers/media/platform/exynos/smfc/smfc-sync.h diff --git a/drivers/media/platform/exynos/smfc/smfc-sync.h b/drivers/media/platform/exynos/smfc/smfc-sync.h new file mode 100644 index 000000000000..8a5e69263bb1 --- /dev/null +++ b/drivers/media/platform/exynos/smfc/smfc-sync.h @@ -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_ */ diff --git a/drivers/media/platform/exynos/smfc/smfc.c b/drivers/media/platform/exynos/smfc/smfc.c index 384d1cea22df..39d2f7bab80b 100644 --- a/drivers/media/platform/exynos/smfc/smfc.c +++ b/drivers/media/platform/exynos/smfc/smfc.c @@ -19,12 +19,23 @@ #include #include #include +#include #include #include #include #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"); -- 2.20.1