Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b9ee31e6 authored by Sylwester Nawrocki's avatar Sylwester Nawrocki Committed by Mauro Carvalho Chehab
Browse files

[media] s5p-fimc: Add pipeline ops to separate FIMC-LITE module



In order to reuse the FIMC-LITE module on Exynos4 and Exynos5
SoC introduce a set of callbacks for the media pipeline control
from within FIMC/FIMC-LITE video node. It lets us avoid symbol
dependencies between FIMC-LITE and the whole media device driver,
which simplifies the initialization sequences and doesn't
introduce issues preventing common kernel image for exynos4 and
exynos5 SoCs.
This patch also corrects following build errors:
drivers/built-in.o: In function `buffer_queue':
drivers/media/video/s5p-fimc/fimc-lite.c:414: undefined reference
to `fimc_pipeline_s_stream'
drivers/built-in.o: In function `fimc_lite_resume':
drivers/media/video/s5p-fimc/fimc-lite.c:1518: undefined reference
to `fimc_pipeline_initialize'
drivers/built-in.o: In function `fimc_lite_suspend':
drivers/media/video/s5p-fimc/fimc-lite.c:1544: undefined reference
to `fimc_pipeline_shutdown'
when only CONFIG_VIDEO_EXYNOS_FIMC_LITE is selected, without
CONFIG_VIDEO_S5P_FIMC.

Reported-by: default avatarSachin Kamat <sachin.kamat@linaro.org>
Signed-off-by: default avatarSylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent b5146c96
Loading
Loading
Loading
Loading
+12 −9
Original line number Diff line number Diff line
@@ -118,7 +118,8 @@ static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend)
	spin_unlock_irqrestore(&fimc->slock, flags);

	if (streaming)
		return fimc_pipeline_s_stream(&fimc->pipeline, 0);
		return fimc_pipeline_call(fimc, set_stream,
					  &fimc->pipeline, 0);
	else
		return 0;
}
@@ -264,7 +265,8 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
		fimc_activate_capture(ctx);

		if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state))
			fimc_pipeline_s_stream(&fimc->pipeline, 1);
			fimc_pipeline_call(fimc, set_stream,
					   &fimc->pipeline, 1);
	}

	return 0;
@@ -288,7 +290,7 @@ int fimc_capture_suspend(struct fimc_dev *fimc)
	int ret = fimc_stop_capture(fimc, suspend);
	if (ret)
		return ret;
	return fimc_pipeline_shutdown(&fimc->pipeline);
	return fimc_pipeline_call(fimc, close, &fimc->pipeline);
}

static void buffer_queue(struct vb2_buffer *vb);
@@ -304,8 +306,8 @@ int fimc_capture_resume(struct fimc_dev *fimc)

	INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q);
	vid_cap->buf_index = 0;
	fimc_pipeline_initialize(&fimc->pipeline, &vid_cap->vfd.entity,
				 false);
	fimc_pipeline_call(fimc, open, &fimc->pipeline,
			   &vid_cap->vfd.entity, false);
	fimc_capture_hw_init(fimc);

	clear_bit(ST_CAPT_SUSPENDED, &fimc->state);
@@ -422,7 +424,8 @@ static void buffer_queue(struct vb2_buffer *vb)
		spin_unlock_irqrestore(&fimc->slock, flags);

		if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state))
			fimc_pipeline_s_stream(&fimc->pipeline, 1);
			fimc_pipeline_call(fimc, set_stream,
					   &fimc->pipeline, 1);
		return;
	}
	spin_unlock_irqrestore(&fimc->slock, flags);
@@ -502,7 +505,7 @@ static int fimc_capture_open(struct file *file)
	}

	if (++fimc->vid_cap.refcnt == 1) {
		ret = fimc_pipeline_initialize(&fimc->pipeline,
		ret = fimc_pipeline_call(fimc, open, &fimc->pipeline,
					 &fimc->vid_cap.vfd.entity, true);

		if (!ret && !fimc->vid_cap.user_subdev_api)
@@ -536,7 +539,7 @@ static int fimc_capture_close(struct file *file)
	if (--fimc->vid_cap.refcnt == 0) {
		clear_bit(ST_CAPT_BUSY, &fimc->state);
		fimc_stop_capture(fimc, false);
		fimc_pipeline_shutdown(&fimc->pipeline);
		fimc_pipeline_call(fimc, close, &fimc->pipeline);
		clear_bit(ST_CAPT_SUSPENDED, &fimc->state);
	}

+1 −0
Original line number Diff line number Diff line
@@ -440,6 +440,7 @@ struct fimc_dev {
	unsigned long			state;
	struct vb2_alloc_ctx		*alloc_ctx;
	struct fimc_pipeline		pipeline;
	const struct fimc_pipeline_ops	*pipeline_ops;
};

/**
+13 −8
Original line number Diff line number Diff line
@@ -28,9 +28,11 @@
#include <media/v4l2-mem2mem.h>
#include <media/videobuf2-core.h>
#include <media/videobuf2-dma-contig.h>
#include <media/s5p_fimc.h>

#include "fimc-mdevice.h"
#include "fimc-core.h"
#include "fimc-lite.h"
#include "fimc-lite-reg.h"

static int debug;
@@ -193,7 +195,7 @@ static int fimc_lite_reinit(struct fimc_lite *fimc, bool suspend)
	if (!streaming)
		return 0;

	return fimc_pipeline_s_stream(&fimc->pipeline, 0);
	return fimc_pipeline_call(fimc, set_stream, &fimc->pipeline, 0);
}

static int fimc_lite_stop_capture(struct fimc_lite *fimc, bool suspend)
@@ -307,7 +309,8 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
		flite_hw_capture_start(fimc);

		if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state))
			fimc_pipeline_s_stream(&fimc->pipeline, 1);
			fimc_pipeline_call(fimc, set_stream,
					   &fimc->pipeline, 1);
	}
	if (debug > 0)
		flite_hw_dump_regs(fimc, __func__);
@@ -411,7 +414,8 @@ static void buffer_queue(struct vb2_buffer *vb)
		spin_unlock_irqrestore(&fimc->slock, flags);

		if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state))
			fimc_pipeline_s_stream(&fimc->pipeline, 1);
			fimc_pipeline_call(fimc, set_stream,
					   &fimc->pipeline, 1);
		return;
	}
	spin_unlock_irqrestore(&fimc->slock, flags);
@@ -466,7 +470,7 @@ static int fimc_lite_open(struct file *file)
		goto done;

	if (++fimc->ref_count == 1 && fimc->out_path == FIMC_IO_DMA) {
		ret = fimc_pipeline_initialize(&fimc->pipeline,
		ret = fimc_pipeline_call(fimc, open, &fimc->pipeline,
					 &fimc->vfd.entity, true);
		if (ret < 0) {
			pm_runtime_put_sync(&fimc->pdev->dev);
@@ -493,7 +497,7 @@ static int fimc_lite_close(struct file *file)
	if (--fimc->ref_count == 0 && fimc->out_path == FIMC_IO_DMA) {
		clear_bit(ST_FLITE_IN_USE, &fimc->state);
		fimc_lite_stop_capture(fimc, false);
		fimc_pipeline_shutdown(&fimc->pipeline);
		fimc_pipeline_call(fimc, close, &fimc->pipeline);
		clear_bit(ST_FLITE_SUSPENDED, &fimc->state);
	}

@@ -1508,7 +1512,8 @@ static int fimc_lite_resume(struct device *dev)
		return 0;

	INIT_LIST_HEAD(&fimc->active_buf_q);
	fimc_pipeline_initialize(&fimc->pipeline, &fimc->vfd.entity, false);
	fimc_pipeline_call(fimc, open, &fimc->pipeline,
			   &fimc->vfd.entity, false);
	fimc_lite_hw_init(fimc);
	clear_bit(ST_FLITE_SUSPENDED, &fimc->state);

@@ -1534,7 +1539,7 @@ static int fimc_lite_suspend(struct device *dev)
	if (ret < 0 || !fimc_lite_active(fimc))
		return ret;

	return fimc_pipeline_shutdown(&fimc->pipeline);
	return fimc_pipeline_call(fimc, close, &fimc->pipeline);
}
#endif /* CONFIG_PM_SLEEP */

+2 −0
Original line number Diff line number Diff line
@@ -108,6 +108,7 @@ struct flite_buffer {
 * @test_pattern: test pattern controls
 * @index: FIMC-LITE platform device index
 * @pipeline: video capture pipeline data structure
 * @pipeline_ops: media pipeline ops for the video node driver
 * @slock: spinlock protecting this data structure and the hw registers
 * @lock: mutex serializing video device and the subdev operations
 * @clock: FIMC-LITE gate clock
@@ -142,6 +143,7 @@ struct fimc_lite {
	struct v4l2_ctrl	*test_pattern;
	u32			index;
	struct fimc_pipeline	pipeline;
	const struct fimc_pipeline_ops *pipeline_ops;

	struct mutex		lock;
	spinlock_t		slock;
+31 −21
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <media/v4l2-ctrls.h>
#include <media/media-device.h>
#include <media/s5p_fimc.h>

#include "fimc-core.h"
#include "fimc-lite.h"
@@ -38,7 +39,8 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd,
 *
 * Caller holds the graph mutex.
 */
void fimc_pipeline_prepare(struct fimc_pipeline *p, struct media_entity *me)
static void fimc_pipeline_prepare(struct fimc_pipeline *p,
				  struct media_entity *me)
{
	struct media_pad *pad = &me->pads[0];
	struct v4l2_subdev *sd;
@@ -114,7 +116,7 @@ static int __subdev_set_power(struct v4l2_subdev *sd, int on)
 *
 * Needs to be called with the graph mutex held.
 */
int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state)
static int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state)
{
	unsigned int i;
	int ret;
@@ -134,14 +136,14 @@ int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state)
}

/**
 * __fimc_pipeline_initialize - update the pipeline information, enable power
 * __fimc_pipeline_open - update the pipeline information, enable power
 *                        of all pipeline subdevs and the sensor clock
 * @me: media entity to start graph walk with
 * @prep: true to acquire sensor (and csis) subdevs
 *
 * This function must be called with the graph mutex held.
 */
static int __fimc_pipeline_initialize(struct fimc_pipeline *p,
static int __fimc_pipeline_open(struct fimc_pipeline *p,
				struct media_entity *me, bool prep)
{
	int ret;
@@ -159,28 +161,27 @@ static int __fimc_pipeline_initialize(struct fimc_pipeline *p,
	return fimc_pipeline_s_power(p, 1);
}

int fimc_pipeline_initialize(struct fimc_pipeline *p, struct media_entity *me,
			     bool prep)
static int fimc_pipeline_open(struct fimc_pipeline *p,
			      struct media_entity *me, bool prep)
{
	int ret;

	mutex_lock(&me->parent->graph_mutex);
	ret =  __fimc_pipeline_initialize(p, me, prep);
	ret =  __fimc_pipeline_open(p, me, prep);
	mutex_unlock(&me->parent->graph_mutex);

	return ret;
}
EXPORT_SYMBOL_GPL(fimc_pipeline_initialize);

/**
 * __fimc_pipeline_shutdown - disable the sensor clock and pipeline power
 * __fimc_pipeline_close - disable the sensor clock and pipeline power
 * @fimc: fimc device terminating the pipeline
 *
 * Disable power of all subdevs in the pipeline and turn off the external
 * sensor clock.
 * Called with the graph mutex held.
 */
static int __fimc_pipeline_shutdown(struct fimc_pipeline *p)
static int __fimc_pipeline_close(struct fimc_pipeline *p)
{
	int ret = 0;

@@ -191,7 +192,7 @@ static int __fimc_pipeline_shutdown(struct fimc_pipeline *p)
	return ret == -ENXIO ? 0 : ret;
}

int fimc_pipeline_shutdown(struct fimc_pipeline *p)
static int fimc_pipeline_close(struct fimc_pipeline *p)
{
	struct media_entity *me;
	int ret;
@@ -201,12 +202,11 @@ int fimc_pipeline_shutdown(struct fimc_pipeline *p)

	me = &p->subdevs[IDX_SENSOR]->entity;
	mutex_lock(&me->parent->graph_mutex);
	ret = __fimc_pipeline_shutdown(p);
	ret = __fimc_pipeline_close(p);
	mutex_unlock(&me->parent->graph_mutex);

	return ret;
}
EXPORT_SYMBOL_GPL(fimc_pipeline_shutdown);

/**
 * fimc_pipeline_s_stream - invoke s_stream on pipeline subdevs
@@ -232,7 +232,13 @@ int fimc_pipeline_s_stream(struct fimc_pipeline *p, bool on)
	return 0;

}
EXPORT_SYMBOL_GPL(fimc_pipeline_s_stream);

/* Media pipeline operations for the FIMC/FIMC-LITE video device driver */
static const struct fimc_pipeline_ops fimc_pipeline_ops = {
	.open		= fimc_pipeline_open,
	.close		= fimc_pipeline_close,
	.set_stream	= fimc_pipeline_s_stream,
};

/*
 * Sensor subdevice helper functions
@@ -347,6 +353,7 @@ static int fimc_register_callback(struct device *dev, void *p)
	if (fimc->pdev->id < 0 || fimc->pdev->id >= FIMC_MAX_DEVS)
		return 0;

	fimc->pipeline_ops = &fimc_pipeline_ops;
	fmd->fimc[fimc->pdev->id] = fimc;
	sd->grp_id = FIMC_GROUP_ID;

@@ -372,6 +379,7 @@ static int fimc_lite_register_callback(struct device *dev, void *p)
	if (fimc->index >= FIMC_LITE_MAX_DEVS)
		return 0;

	fimc->pipeline_ops = &fimc_pipeline_ops;
	fmd->fimc_lite[fimc->index] = fimc;
	sd->grp_id = FLITE_GROUP_ID;

@@ -473,12 +481,14 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd)
		if (fmd->fimc[i] == NULL)
			continue;
		v4l2_device_unregister_subdev(&fmd->fimc[i]->vid_cap.subdev);
		fmd->fimc[i]->pipeline_ops = NULL;
		fmd->fimc[i] = NULL;
	}
	for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) {
		if (fmd->fimc_lite[i] == NULL)
			continue;
		v4l2_device_unregister_subdev(&fmd->fimc_lite[i]->subdev);
		fmd->fimc[i]->pipeline_ops = NULL;
		fmd->fimc_lite[i] = NULL;
	}
	for (i = 0; i < CSIS_MAX_ENTITIES; i++) {
@@ -832,7 +842,7 @@ static int fimc_md_link_notify(struct media_pad *source,
	}

	if (!(flags & MEDIA_LNK_FL_ENABLED)) {
		ret = __fimc_pipeline_shutdown(pipeline);
		ret = __fimc_pipeline_close(pipeline);
		pipeline->subdevs[IDX_SENSOR] = NULL;
		pipeline->subdevs[IDX_CSIS] = NULL;

@@ -851,7 +861,7 @@ static int fimc_md_link_notify(struct media_pad *source,
	if (fimc) {
		mutex_lock(&fimc->lock);
		if (fimc->vid_cap.refcnt > 0) {
			ret = __fimc_pipeline_initialize(pipeline,
			ret = __fimc_pipeline_open(pipeline,
						   source->entity, true);
		if (!ret)
			ret = fimc_capture_ctrls_create(fimc);
@@ -860,7 +870,7 @@ static int fimc_md_link_notify(struct media_pad *source,
	} else {
		mutex_lock(&fimc_lite->lock);
		if (fimc_lite->ref_count > 0) {
			ret = __fimc_pipeline_initialize(pipeline,
			ret = __fimc_pipeline_open(pipeline,
						   source->entity, true);
		}
		mutex_unlock(&fimc_lite->lock);
Loading