[media] media: Change media device link_notify behaviour

Currently the media device link_notify callback is invoked before the
actual change of state of a link when the link is being enabled, and
after the actual change of state when the link is being disabled.
This doesn't allow a media device driver to perform any operations
on a full graph before a link is disabled, as well as performing
any tasks on a modified graph right after a link's state is changed.
This patch modifies signature of the link_notify callback. This
callback is now called always before and after a link's state change.
To distinguish the notifications a 'notification' argument is added
to the link_notify callback: MEDIA_DEV_NOTIFY_PRE_LINK_CH indicates
notification before link's state change and
MEDIA_DEV_NOTIFY_POST_LINK_CH corresponds to a notification after
link flags change.

[mchehab@redhat.com: whitespace cleanups]
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@iki.fi>

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Sylwester Nawrocki 2013-05-31 10:37:26 -03:00 committed by Mauro Carvalho Chehab
parent 4434adff80
commit 813f5c0ac5
4 changed files with 47 additions and 39 deletions

View File

@ -496,25 +496,17 @@ int __media_entity_setup_link(struct media_link *link, u32 flags)
mdev = source->parent; mdev = source->parent;
if ((flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify) { if (mdev->link_notify) {
ret = mdev->link_notify(link->source, link->sink, ret = mdev->link_notify(link, flags,
MEDIA_LNK_FL_ENABLED); MEDIA_DEV_NOTIFY_PRE_LINK_CH);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
ret = __media_entity_setup_link_notify(link, flags); ret = __media_entity_setup_link_notify(link, flags);
if (ret < 0)
goto err;
if (!(flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify) if (mdev->link_notify)
mdev->link_notify(link->source, link->sink, 0); mdev->link_notify(link, flags, MEDIA_DEV_NOTIFY_POST_LINK_CH);
return 0;
err:
if ((flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify)
mdev->link_notify(link->source, link->sink, 0);
return ret; return ret;
} }

View File

@ -1287,34 +1287,36 @@ 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_pad *source, static int fimc_md_link_notify(struct media_link *link, u32 flags,
struct media_pad *sink, u32 flags) unsigned int notification)
{ {
struct media_entity *sink = link->sink->entity;
struct exynos_video_entity *ve; struct exynos_video_entity *ve;
struct video_device *vdev; struct video_device *vdev;
struct fimc_pipeline *pipeline; struct fimc_pipeline *pipeline;
int i, ret = 0; int i, ret = 0;
if (media_entity_type(sink->entity) != MEDIA_ENT_T_DEVNODE_V4L) if (media_entity_type(sink) != MEDIA_ENT_T_DEVNODE_V4L ||
notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH)
return 0; return 0;
vdev = media_entity_to_video_device(sink->entity); 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); pipeline = to_fimc_pipeline(ve->pipe);
if (!(flags & MEDIA_LNK_FL_ENABLED) && pipeline->subdevs[IDX_SENSOR]) { if (!(link->flags & MEDIA_LNK_FL_ENABLED) && pipeline->subdevs[IDX_SENSOR]) {
if (sink->entity->use_count > 0) if (sink->use_count > 0)
ret = __fimc_pipeline_close(ve->pipe); ret = __fimc_pipeline_close(ve->pipe);
for (i = 0; i < IDX_MAX; i++) for (i = 0; i < IDX_MAX; i++)
pipeline->subdevs[i] = NULL; pipeline->subdevs[i] = NULL;
} else if (sink->entity->use_count > 0) { } else if (sink->use_count > 0) {
/* /*
* Link activation. Enable power of pipeline elements only if * Link activation. Enable power of pipeline elements only if
* the pipeline is already in use, i.e. its video node is open. * the pipeline is already in use, i.e. its video node is open.
* Recreate the controls destroyed during the link deactivation. * Recreate the controls destroyed during the link deactivation.
*/ */
ret = __fimc_pipeline_open(ve->pipe, sink->entity, true); ret = __fimc_pipeline_open(ve->pipe, sink, true);
} }
return ret ? -EPIPE : ret; return ret ? -EPIPE : ret;

View File

@ -792,9 +792,9 @@ int omap3isp_pipeline_pm_use(struct media_entity *entity, int use)
/* /*
* isp_pipeline_link_notify - Link management notification callback * isp_pipeline_link_notify - Link management notification callback
* @source: Pad at the start of the link * @link: The link
* @sink: Pad at the end of the link
* @flags: New link flags that will be applied * @flags: New link flags that will be applied
* @notification: The link's state change notification type (MEDIA_DEV_NOTIFY_*)
* *
* React to link management on powered pipelines by updating the use count of * React to link management on powered pipelines by updating the use count of
* all entities in the source and sink sides of the link. Entities are powered * all entities in the source and sink sides of the link. Entities are powered
@ -804,29 +804,38 @@ int omap3isp_pipeline_pm_use(struct media_entity *entity, int use)
* off is assumed to never fail. This function will not fail for disconnection * off is assumed to never fail. This function will not fail for disconnection
* events. * events.
*/ */
static int isp_pipeline_link_notify(struct media_pad *source, static int isp_pipeline_link_notify(struct media_link *link, u32 flags,
struct media_pad *sink, u32 flags) unsigned int notification)
{ {
int source_use = isp_pipeline_pm_use_count(source->entity); struct media_entity *source = link->source->entity;
int sink_use = isp_pipeline_pm_use_count(sink->entity); struct media_entity *sink = link->sink->entity;
int source_use = isp_pipeline_pm_use_count(source);
int sink_use = isp_pipeline_pm_use_count(sink);
int ret; int ret;
if (!(flags & MEDIA_LNK_FL_ENABLED)) { if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH &&
!(link->flags & MEDIA_LNK_FL_ENABLED)) {
/* Powering off entities is assumed to never fail. */ /* Powering off entities is assumed to never fail. */
isp_pipeline_pm_power(source->entity, -sink_use); isp_pipeline_pm_power(source, -sink_use);
isp_pipeline_pm_power(sink->entity, -source_use); isp_pipeline_pm_power(sink, -source_use);
return 0; return 0;
} }
ret = isp_pipeline_pm_power(source->entity, sink_use); if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH &&
if (ret < 0) (flags & MEDIA_LNK_FL_ENABLED)) {
ret = isp_pipeline_pm_power(source, sink_use);
if (ret < 0)
return ret;
ret = isp_pipeline_pm_power(sink, source_use);
if (ret < 0)
isp_pipeline_pm_power(source, -sink_use);
return ret; return ret;
}
ret = isp_pipeline_pm_power(sink->entity, source_use); return 0;
if (ret < 0)
isp_pipeline_pm_power(source->entity, -sink_use);
return ret;
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------

View File

@ -45,6 +45,7 @@ struct device;
* @entities: List of registered entities * @entities: List of registered entities
* @lock: Entities list lock * @lock: Entities list lock
* @graph_mutex: Entities graph operation lock * @graph_mutex: Entities graph operation lock
* @link_notify: Link state change notification callback
* *
* This structure represents an abstract high-level media device. It allows easy * This structure represents an abstract high-level media device. It allows easy
* access to entities and provides basic media device-level support. The * access to entities and provides basic media device-level support. The
@ -75,10 +76,14 @@ struct media_device {
/* Serializes graph operations. */ /* Serializes graph operations. */
struct mutex graph_mutex; struct mutex graph_mutex;
int (*link_notify)(struct media_pad *source, int (*link_notify)(struct media_link *link, u32 flags,
struct media_pad *sink, u32 flags); unsigned int notification);
}; };
/* Supported link_notify @notification values. */
#define MEDIA_DEV_NOTIFY_PRE_LINK_CH 0
#define MEDIA_DEV_NOTIFY_POST_LINK_CH 1
/* media_devnode to media_device */ /* media_devnode to media_device */
#define to_media_device(node) container_of(node, struct media_device, devnode) #define to_media_device(node) container_of(node, struct media_device, devnode)