@@ -10,6 +10,7 @@
* or (at your option) any later version.
*/
+#include <linux/async.h>
#include <linux/bug.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
@@ -186,6 +187,13 @@ error:
return ret;
}
+static void __fimc_pipeline_power_async(void *data, async_cookie_t cookie)
+{
+ struct fimc_pipeline *p = data;
+
+ WARN_ON(fimc_pipeline_s_power(p, true) < 0);
+}
+
/**
* __fimc_pipeline_open - update the pipeline information, enable power
* of all pipeline subdevs and the sensor clock
@@ -219,14 +227,13 @@ static int __fimc_pipeline_open(struct exynos_media_pipeline *ep,
return ret;
}
- ret = fimc_pipeline_s_power(p, 1);
- if (!ret)
- return 0;
+ async_schedule_domain(__fimc_pipeline_power_async, p,
+ &ep->async_domain);
if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP])
clk_disable_unprepare(fmd->wbclk[CLK_IDX_WB_B]);
- return ret;
+ return 0;
}
/**
@@ -275,6 +282,9 @@ static int __fimc_pipeline_s_stream(struct exynos_media_pipeline *ep, bool on)
if (p->subdevs[IDX_SENSOR] == NULL)
return -ENODEV;
+ /* Wait until all devices in the chain are powered up */
+ async_synchronize_full_domain(&ep->async_domain);
+
for (i = 0; i < IDX_MAX; i++) {
unsigned int idx = seq[on][i];
@@ -309,6 +319,7 @@ static struct exynos_media_pipeline *fimc_md_pipeline_create(
return NULL;
list_add_tail(&p->list, &fmd->pipelines);
+ async_domain_init_exclusive(&p->ep.async_domain);
p->ep.ops = &fimc_pipeline_ops;
return &p->ep;
@@ -12,6 +12,7 @@
#ifndef S5P_FIMC_H_
#define S5P_FIMC_H_
+#include <linux/async.h>
#include <media/media-entity.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-mediabus.h>
@@ -146,6 +147,7 @@ struct exynos_video_entity {
struct exynos_media_pipeline {
struct media_pipeline mp;
const struct exynos_media_pipeline_ops *ops;
+ struct async_domain async_domain;
};
static inline struct exynos_video_entity *vdev_to_exynos_video_entity(