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

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

[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: default avatarSylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Acked-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: default avatarSakari Ailus <sakari.ailus@iki.fi>

Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 4434adff
Loading
Loading
Loading
Loading
+5 −13
Original line number Diff line number Diff line
@@ -496,25 +496,17 @@ int __media_entity_setup_link(struct media_link *link, u32 flags)

	mdev = source->parent;

	if ((flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify) {
		ret = mdev->link_notify(link->source, link->sink,
					MEDIA_LNK_FL_ENABLED);
	if (mdev->link_notify) {
		ret = mdev->link_notify(link, flags,
					MEDIA_DEV_NOTIFY_PRE_LINK_CH);
		if (ret < 0)
			return ret;
	}

	ret = __media_entity_setup_link_notify(link, flags);
	if (ret < 0)
		goto err;

	if (!(flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify)
		mdev->link_notify(link->source, link->sink, 0);

	return 0;

err:
	if ((flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify)
		mdev->link_notify(link->source, link->sink, 0);
	if (mdev->link_notify)
		mdev->link_notify(link, flags, MEDIA_DEV_NOTIFY_POST_LINK_CH);

	return ret;
}
+10 −8
Original line number Diff line number Diff line
@@ -1287,34 +1287,36 @@ int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on)
	return __fimc_md_set_camclk(fmd, si, on);
}

static int fimc_md_link_notify(struct media_pad *source,
			       struct media_pad *sink, u32 flags)
static int fimc_md_link_notify(struct media_link *link, u32 flags,
						unsigned int notification)
{
	struct media_entity *sink = link->sink->entity;
	struct exynos_video_entity *ve;
	struct video_device *vdev;
	struct fimc_pipeline *pipeline;
	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;

	vdev = media_entity_to_video_device(sink->entity);
	vdev = media_entity_to_video_device(sink);
	ve = vdev_to_exynos_video_entity(vdev);
	pipeline = to_fimc_pipeline(ve->pipe);

	if (!(flags & MEDIA_LNK_FL_ENABLED) && pipeline->subdevs[IDX_SENSOR]) {
		if (sink->entity->use_count > 0)
	if (!(link->flags & MEDIA_LNK_FL_ENABLED) && pipeline->subdevs[IDX_SENSOR]) {
		if (sink->use_count > 0)
			ret = __fimc_pipeline_close(ve->pipe);

		for (i = 0; i < IDX_MAX; i++)
			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
		 * the pipeline is already in use, i.e. its video node is open.
		 * 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;
+25 −16
Original line number Diff line number Diff line
@@ -792,9 +792,9 @@ int omap3isp_pipeline_pm_use(struct media_entity *entity, int use)

/*
 * isp_pipeline_link_notify - Link management notification callback
 * @source: Pad at the start of the link
 * @sink: Pad at the end of the link
 * @link: The link
 * @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
 * all entities in the source and sink sides of the link. Entities are powered
@@ -804,31 +804,40 @@ int omap3isp_pipeline_pm_use(struct media_entity *entity, int use)
 * off is assumed to never fail. This function will not fail for disconnection
 * events.
 */
static int isp_pipeline_link_notify(struct media_pad *source,
				    struct media_pad *sink, u32 flags)
static int isp_pipeline_link_notify(struct media_link *link, u32 flags,
				    unsigned int notification)
{
	int source_use = isp_pipeline_pm_use_count(source->entity);
	int sink_use = isp_pipeline_pm_use_count(sink->entity);
	struct media_entity *source = link->source->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;

	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. */
		isp_pipeline_pm_power(source->entity, -sink_use);
		isp_pipeline_pm_power(sink->entity, -source_use);
		isp_pipeline_pm_power(source, -sink_use);
		isp_pipeline_pm_power(sink, -source_use);
		return 0;
	}

	ret = isp_pipeline_pm_power(source->entity, sink_use);
	if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH &&
		(flags & MEDIA_LNK_FL_ENABLED)) {

		ret = isp_pipeline_pm_power(source, sink_use);
		if (ret < 0)
			return ret;

	ret = isp_pipeline_pm_power(sink->entity, source_use);
		ret = isp_pipeline_pm_power(sink, source_use);
		if (ret < 0)
		isp_pipeline_pm_power(source->entity, -sink_use);
			isp_pipeline_pm_power(source, -sink_use);

		return ret;
	}

	return 0;
}

/* -----------------------------------------------------------------------------
 * Pipeline stream management
 */
+7 −2
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ struct device;
 * @entities:	List of registered entities
 * @lock:	Entities list 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
 * access to entities and provides basic media device-level support. The
@@ -75,10 +76,14 @@ struct media_device {
	/* Serializes graph operations. */
	struct mutex graph_mutex;

	int (*link_notify)(struct media_pad *source,
			   struct media_pad *sink, u32 flags);
	int (*link_notify)(struct media_link *link, 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 */
#define to_media_device(node) container_of(node, struct media_device, devnode)