mirror of
https://github.com/torvalds/linux.git
synced 2024-11-01 17:51:43 +00:00
[media] exynos4-is: Extend link_notify handler to support fimc-is/lite pipelines
This patch corrects the link_notify handler to support more complex pipelines, including fimc-lite and fimc-is entities. After the FIMC-IS driver addition the assumptions made in the link_notify callback are no longer valid, e.g. the link between fimc-lite subdev and its video node is not immutable any more and there is more subdevs than just sensor, MIPI-CSIS and FIMC(-LITE). The graph is now walked and for each video node found a media pipeline which ends at this node is disabled/enabled (the subdevs are powered on/off). 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>
This commit is contained in:
parent
813f5c0ac5
commit
d3775fa76b
@ -1287,39 +1287,98 @@ int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on)
|
|||||||
return __fimc_md_set_camclk(fmd, si, on);
|
return __fimc_md_set_camclk(fmd, si, on);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fimc_md_link_notify(struct media_link *link, u32 flags,
|
static int __fimc_md_modify_pipeline(struct media_entity *entity, bool enable)
|
||||||
unsigned int notification)
|
|
||||||
{
|
{
|
||||||
struct media_entity *sink = link->sink->entity;
|
|
||||||
struct exynos_video_entity *ve;
|
struct exynos_video_entity *ve;
|
||||||
|
struct fimc_pipeline *p;
|
||||||
struct video_device *vdev;
|
struct video_device *vdev;
|
||||||
struct fimc_pipeline *pipeline;
|
int ret;
|
||||||
int i, ret = 0;
|
|
||||||
|
|
||||||
if (media_entity_type(sink) != MEDIA_ENT_T_DEVNODE_V4L ||
|
vdev = media_entity_to_video_device(entity);
|
||||||
notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH)
|
if (vdev->entity.use_count == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
vdev = media_entity_to_video_device(sink);
|
|
||||||
ve = vdev_to_exynos_video_entity(vdev);
|
ve = vdev_to_exynos_video_entity(vdev);
|
||||||
pipeline = to_fimc_pipeline(ve->pipe);
|
p = to_fimc_pipeline(ve->pipe);
|
||||||
|
/*
|
||||||
|
* Nothing to do if we are disabling the pipeline, some link
|
||||||
|
* has been disconnected and p->subdevs array is cleared now.
|
||||||
|
*/
|
||||||
|
if (!enable && p->subdevs[IDX_SENSOR] == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!(link->flags & MEDIA_LNK_FL_ENABLED) && pipeline->subdevs[IDX_SENSOR]) {
|
if (enable)
|
||||||
if (sink->use_count > 0)
|
ret = __fimc_pipeline_open(ve->pipe, entity, true);
|
||||||
ret = __fimc_pipeline_close(ve->pipe);
|
else
|
||||||
|
ret = __fimc_pipeline_close(ve->pipe);
|
||||||
|
|
||||||
for (i = 0; i < IDX_MAX; i++)
|
if (ret == 0 && !enable)
|
||||||
pipeline->subdevs[i] = NULL;
|
memset(p->subdevs, 0, sizeof(p->subdevs));
|
||||||
} else if (sink->use_count > 0) {
|
|
||||||
/*
|
return ret;
|
||||||
* Link activation. Enable power of pipeline elements only if
|
}
|
||||||
* the pipeline is already in use, i.e. its video node is open.
|
|
||||||
* Recreate the controls destroyed during the link deactivation.
|
/* Locking: called with entity->parent->graph_mutex mutex held. */
|
||||||
*/
|
static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable)
|
||||||
ret = __fimc_pipeline_open(ve->pipe, sink, true);
|
{
|
||||||
|
struct media_entity *entity_err = entity;
|
||||||
|
struct media_entity_graph graph;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Walk current graph and call the pipeline open/close routine for each
|
||||||
|
* opened video node that belongs to the graph of entities connected
|
||||||
|
* through active links. This is needed as we cannot power on/off the
|
||||||
|
* subdevs in random order.
|
||||||
|
*/
|
||||||
|
media_entity_graph_walk_start(&graph, entity);
|
||||||
|
|
||||||
|
while ((entity = media_entity_graph_walk_next(&graph))) {
|
||||||
|
if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret = __fimc_md_modify_pipeline(entity, enable);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret ? -EPIPE : ret;
|
return 0;
|
||||||
|
err:
|
||||||
|
media_entity_graph_walk_start(&graph, entity_err);
|
||||||
|
|
||||||
|
while ((entity_err = media_entity_graph_walk_next(&graph))) {
|
||||||
|
if (media_entity_type(entity_err) != MEDIA_ENT_T_DEVNODE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
__fimc_md_modify_pipeline(entity_err, !enable);
|
||||||
|
|
||||||
|
if (entity_err == entity)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fimc_md_link_notify(struct media_link *link, unsigned int flags,
|
||||||
|
unsigned int notification)
|
||||||
|
{
|
||||||
|
struct media_entity *sink = link->sink->entity;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
/* Before link disconnection */
|
||||||
|
if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH) {
|
||||||
|
if (!(flags & MEDIA_LNK_FL_ENABLED))
|
||||||
|
ret = __fimc_md_modify_pipelines(sink, false);
|
||||||
|
else
|
||||||
|
; /* TODO: Link state change validation */
|
||||||
|
/* After link activation */
|
||||||
|
} else if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH &&
|
||||||
|
(link->flags & MEDIA_LNK_FL_ENABLED)) {
|
||||||
|
ret = __fimc_md_modify_pipelines(sink, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret ? -EPIPE : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t fimc_md_sysfs_show(struct device *dev,
|
static ssize_t fimc_md_sysfs_show(struct device *dev,
|
||||||
|
Loading…
Reference in New Issue
Block a user