Exemple #1
0
/* Return a pointer to the ISP video instance at the far end of the pipeline. */
static int isp_video_get_graph_data(struct isp_video *video,
				    struct isp_pipeline *pipe)
{
	struct media_entity_graph graph;
	struct media_entity *entity = &video->video.entity;
	struct media_device *mdev = entity->graph_obj.mdev;
	struct isp_video *far_end = NULL;
	int ret;

	mutex_lock(&mdev->graph_mutex);
	ret = media_entity_graph_walk_init(&graph, entity->graph_obj.mdev);
	if (ret) {
		mutex_unlock(&mdev->graph_mutex);
		return ret;
	}

	media_entity_graph_walk_start(&graph, entity);

	while ((entity = media_entity_graph_walk_next(&graph))) {
		struct isp_video *__video;

		media_entity_enum_set(&pipe->ent_enum, entity);

		if (far_end != NULL)
			continue;

		if (entity == &video->video.entity)
			continue;

		if (!is_media_entity_v4l2_video_device(entity))
			continue;

		__video = to_isp_video(media_entity_to_video_device(entity));
		if (__video->type != video->type)
			far_end = __video;
	}

	mutex_unlock(&mdev->graph_mutex);

	media_entity_graph_walk_cleanup(&graph);

	if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
		pipe->input = far_end;
		pipe->output = video;
	} else {
		if (far_end == NULL)
			return -EPIPE;

		pipe->input = video;
		pipe->output = far_end;
	}

	return 0;
}
Exemple #2
0
/* Locking: called with entity->graph_obj.mdev->graph_mutex mutex held. */
static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable,
				      struct media_entity_graph *graph)
{
	struct media_entity *entity_err = entity;
	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 (!is_media_entity_v4l2_video_device(entity))
			continue;

		ret  = __fimc_md_modify_pipeline(entity, enable);

		if (ret < 0)
			goto err;
	}

	return 0;

err:
	media_entity_graph_walk_start(graph, entity_err);

	while ((entity_err = media_entity_graph_walk_next(graph))) {
		if (!is_media_entity_v4l2_video_device(entity_err))
			continue;

		__fimc_md_modify_pipeline(entity_err, !enable);

		if (entity_err == entity)
			break;
	}

	return ret;
}
Exemple #3
0
/*
 * pipeline_pm_use_count - Count the number of users of a pipeline
 * @entity: The entity
 *
 * Return the total number of users of all video device nodes in the pipeline.
 */
static int pipeline_pm_use_count(struct media_entity *entity,
	struct media_entity_graph *graph)
{
	int use = 0;

	media_entity_graph_walk_start(graph, entity);

	while ((entity = media_entity_graph_walk_next(graph))) {
		if (is_media_entity_v4l2_video_device(entity))
			use += entity->use_count;
	}

	return use;
}
Exemple #4
0
/* make a note of pipeline details */
static int vpfe_prepare_pipeline(struct vpfe_video_device *video)
{
	struct media_graph graph;
	struct media_entity *entity = &video->video_dev.entity;
	struct media_device *mdev = entity->graph_obj.mdev;
	struct vpfe_pipeline *pipe = &video->pipe;
	struct vpfe_video_device *far_end = NULL;
	int ret;

	pipe->input_num = 0;
	pipe->output_num = 0;

	if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
		pipe->inputs[pipe->input_num++] = video;
	else
		pipe->outputs[pipe->output_num++] = video;

	mutex_lock(&mdev->graph_mutex);
	ret = media_graph_walk_init(&graph, mdev);
	if (ret) {
		mutex_unlock(&mdev->graph_mutex);
		return -ENOMEM;
	}
	media_graph_walk_start(&graph, entity);
	while ((entity = media_graph_walk_next(&graph))) {
		if (entity == &video->video_dev.entity)
			continue;
		if (!is_media_entity_v4l2_video_device(entity))
			continue;
		far_end = to_vpfe_video(media_entity_to_video_device(entity));
		if (far_end->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
			pipe->inputs[pipe->input_num++] = far_end;
		else
			pipe->outputs[pipe->output_num++] = far_end;
	}
	media_graph_walk_cleanup(&graph);
	mutex_unlock(&mdev->graph_mutex);

	return 0;
}
Exemple #5
0
static int vdic_link_setup(struct media_entity *entity,
			    const struct media_pad *local,
			    const struct media_pad *remote, u32 flags)
{
	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
	struct vdic_priv *priv = v4l2_get_subdevdata(sd);
	struct v4l2_subdev *remote_sd;
	int ret = 0;

	dev_dbg(priv->dev, "link setup %s -> %s", remote->entity->name,
		local->entity->name);

	mutex_lock(&priv->lock);

	if (local->flags & MEDIA_PAD_FL_SOURCE) {
		if (!is_media_entity_v4l2_subdev(remote->entity)) {
			ret = -EINVAL;
			goto out;
		}

		remote_sd = media_entity_to_v4l2_subdev(remote->entity);

		if (flags & MEDIA_LNK_FL_ENABLED) {
			if (priv->sink_sd) {
				ret = -EBUSY;
				goto out;
			}
			priv->sink_sd = remote_sd;
		} else {
			priv->sink_sd = NULL;
		}

		goto out;
	}

	/* this is a sink pad */

	if (flags & MEDIA_LNK_FL_ENABLED) {
		if (priv->src) {
			ret = -EBUSY;
			goto out;
		}
	} else {
		priv->src = NULL;
		goto out;
	}

	if (local->index == VDIC_SINK_PAD_IDMAC) {
		struct imx_media_video_dev *vdev = priv->vdev;

		if (!is_media_entity_v4l2_video_device(remote->entity)) {
			ret = -EINVAL;
			goto out;
		}
		if (!vdev) {
			ret = -ENODEV;
			goto out;
		}

		priv->csi_direct = false;
	} else {
		if (!is_media_entity_v4l2_subdev(remote->entity)) {
			ret = -EINVAL;
			goto out;
		}

		remote_sd = media_entity_to_v4l2_subdev(remote->entity);

		/* direct pad must connect to a CSI */
		if (!(remote_sd->grp_id & IMX_MEDIA_GRP_ID_IPU_CSI) ||
		    remote->index != CSI_SRC_PAD_DIRECT) {
			ret = -EINVAL;
			goto out;
		}

		priv->csi_direct = true;
	}

	priv->src = remote->entity;
	/* record which input pad is now active */
	priv->active_input_pad = local->index;
out:
	mutex_unlock(&priv->lock);
	return ret;
}