Skip to content

Commit

Permalink
[media] s5p-fimc: Add pipeline ops to separate FIMC-LITE module
Browse files Browse the repository at this point in the history
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: Sachin Kamat <sachin.kamat@linaro.org>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Sylwester Nawrocki authored and Mauro Carvalho Chehab committed Oct 1, 2012
1 parent b5146c9 commit b9ee31e
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 44 deletions.
21 changes: 12 additions & 9 deletions drivers/media/platform/s5p-fimc/fimc-capture.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -502,8 +505,8 @@ static int fimc_capture_open(struct file *file)
}

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

if (!ret && !fimc->vid_cap.user_subdev_api)
ret = fimc_capture_set_default_format(fimc);
Expand Down Expand Up @@ -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);
}

Expand Down
1 change: 1 addition & 0 deletions drivers/media/platform/s5p-fimc/fimc-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

/**
Expand Down
21 changes: 13 additions & 8 deletions drivers/media/platform/s5p-fimc/fimc-lite.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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__);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -466,8 +470,8 @@ 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,
&fimc->vfd.entity, true);
ret = fimc_pipeline_call(fimc, open, &fimc->pipeline,
&fimc->vfd.entity, true);
if (ret < 0) {
pm_runtime_put_sync(&fimc->pdev->dev);
fimc->ref_count--;
Expand All @@ -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);
}

Expand Down Expand Up @@ -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);

Expand All @@ -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 */

Expand Down
2 changes: 2 additions & 0 deletions drivers/media/platform/s5p-fimc/fimc-lite.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
52 changes: 31 additions & 21 deletions drivers/media/platform/s5p-fimc/fimc-mdevice.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -134,15 +136,15 @@ int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state)
}

/**
* __fimc_pipeline_initialize - update the pipeline information, enable power
* of all pipeline subdevs and the sensor clock
* __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,
struct media_entity *me, bool prep)
static int __fimc_pipeline_open(struct fimc_pipeline *p,
struct media_entity *me, bool prep)
{
int ret;

Expand All @@ -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;

Expand All @@ -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;
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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;

Expand All @@ -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;

Expand Down Expand Up @@ -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++) {
Expand Down Expand Up @@ -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;

Expand All @@ -851,17 +861,17 @@ 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,
source->entity, true);
ret = __fimc_pipeline_open(pipeline,
source->entity, true);
if (!ret)
ret = fimc_capture_ctrls_create(fimc);
}
mutex_unlock(&fimc->lock);
} else {
mutex_lock(&fimc_lite->lock);
if (fimc_lite->ref_count > 0) {
ret = __fimc_pipeline_initialize(pipeline,
source->entity, true);
ret = __fimc_pipeline_open(pipeline,
source->entity, true);
}
mutex_unlock(&fimc_lite->lock);
}
Expand Down
6 changes: 0 additions & 6 deletions drivers/media/platform/s5p-fimc/fimc-mdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,5 @@ static inline void fimc_md_graph_unlock(struct fimc_dev *fimc)
}

int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on);
void fimc_pipeline_prepare(struct fimc_pipeline *p, struct media_entity *me);
int fimc_pipeline_initialize(struct fimc_pipeline *p, struct media_entity *me,
bool resume);
int fimc_pipeline_shutdown(struct fimc_pipeline *p);
int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state);
int fimc_pipeline_s_stream(struct fimc_pipeline *p, bool state);

#endif
18 changes: 18 additions & 0 deletions include/media/s5p_fimc.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#ifndef S5P_FIMC_H_
#define S5P_FIMC_H_

#include <media/media-entity.h>

enum cam_bus_type {
FIMC_ITU_601 = 1,
FIMC_ITU_656,
Expand Down Expand Up @@ -80,4 +82,20 @@ struct fimc_pipeline {
struct media_pipeline *m_pipeline;
};

/*
* Media pipeline operations to be called from within the fimc(-lite)
* video node when it is the last entity of the pipeline. Implemented
* by corresponding media device driver.
*/
struct fimc_pipeline_ops {
int (*open)(struct fimc_pipeline *p, struct media_entity *me,
bool resume);
int (*close)(struct fimc_pipeline *p);
int (*set_stream)(struct fimc_pipeline *p, bool state);
};

#define fimc_pipeline_call(f, op, p, args...) \
(!(f) ? -ENODEV : (((f)->pipeline_ops && (f)->pipeline_ops->op) ? \
(f)->pipeline_ops->op((p), ##args) : -ENOIOCTLCMD))

#endif /* S5P_FIMC_H_ */

0 comments on commit b9ee31e

Please sign in to comment.