static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
{
	int ret;

	
	ret = media_entity_call(link->source->entity, link_setup,
				link->source, link->sink, flags);
	if (ret < 0 && ret != -ENOIOCTLCMD)
		return ret;

	ret = media_entity_call(link->sink->entity, link_setup,
				link->sink, link->source, flags);
	if (ret < 0 && ret != -ENOIOCTLCMD) {
		media_entity_call(link->source->entity, link_setup,
				  link->source, link->sink, link->flags);
		return ret;
	}

	link->flags = flags;
	link->reverse->flags = link->flags;

	return 0;
}
/**
 * __fimc_md_create_fimc_links - create links to all FIMC entities
 * @fmd: fimc media device
 * @source: the source entity to create links to all fimc entities from
 * @sensor: sensor subdev linked to FIMC[fimc_id] entity, may be null
 * @pad: the source entity pad index
 * @fimc_id: index of the fimc device for which link should be enabled
 */
static int __fimc_md_create_fimc_links(struct fimc_md *fmd,
				       struct media_entity *source,
				       struct v4l2_subdev *sensor,
				       int pad, int fimc_id)
{
	struct fimc_sensor_info *s_info;
	struct media_entity *sink;
	unsigned int flags;
	int ret, i;

	for (i = 0; i < FIMC_MAX_DEVS; i++) {
		if (!fmd->fimc[i])
			break;
		/*
		 * Some FIMC variants are not fitted with camera capture
		 * interface. Skip creating a link from sensor for those.
		 */
		if (sensor->grp_id == SENSOR_GROUP_ID &&
		    !fmd->fimc[i]->variant->has_cam_if)
			continue;

		flags = (i == fimc_id) ? MEDIA_LNK_FL_ENABLED : 0;
		sink = &fmd->fimc[i]->vid_cap.subdev->entity;
		ret = media_entity_create_link(source, pad, sink,
					      FIMC_SD_PAD_SINK, flags);
		if (ret)
			return ret;

		/* Notify FIMC capture subdev entity */
		ret = media_entity_call(sink, link_setup, &sink->pads[0],
					&source->pads[pad], flags);
		if (ret)
			break;

		v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]",
			  source->name, flags ? '=' : '-', sink->name);

		if (flags == 0)
			continue;
		s_info = v4l2_get_subdev_hostdata(sensor);
		if (!WARN_ON(s_info == NULL)) {
			unsigned long irq_flags;
			spin_lock_irqsave(&fmd->slock, irq_flags);
			s_info->host = fmd->fimc[i];
			spin_unlock_irqrestore(&fmd->slock, irq_flags);
		}
	}
	return 0;
}
static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
{
	const u32 mask = MEDIA_LNK_FL_ENABLED;
	int ret;

	/* Notify both entities. */
	ret = media_entity_call(link->source->entity, link_setup,
				link->source, link->sink, flags);
	if (ret < 0 && ret != -ENOIOCTLCMD)
		return ret;

	ret = media_entity_call(link->sink->entity, link_setup,
				link->sink, link->source, flags);
	if (ret < 0 && ret != -ENOIOCTLCMD) {
		media_entity_call(link->source->entity, link_setup,
				  link->source, link->sink, link->flags);
		return ret;
	}

	link->flags = (link->flags & ~mask) | (flags & mask);
	link->reverse->flags = link->flags;

	return 0;
}
Exemple #4
0
/**
 * __fimc_md_create_fimc_links - create links to all FIMC entities
 * @fmd: fimc media device
 * @source: the source entity to create links to all fimc entities from
 * @sensor: sensor subdev linked to FIMC[fimc_id] entity, may be null
 * @pad: the source entity pad index
 * @link_mask: bitmask of the fimc devices for which link should be enabled
 */
static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
					    struct media_entity *source,
					    struct v4l2_subdev *sensor,
					    int pad, int link_mask)
{
	struct fimc_source_info *si = NULL;
	struct media_entity *sink;
	unsigned int flags = 0;
	int i, ret = 0;

	if (sensor) {
		si = v4l2_get_subdev_hostdata(sensor);
		/* Skip direct FIMC links in the logical FIMC-IS sensor path */
		if (si && si->fimc_bus_type == FIMC_BUS_TYPE_ISP_WRITEBACK)
			ret = 1;
	}

	for (i = 0; !ret && i < FIMC_MAX_DEVS; i++) {
		if (!fmd->fimc[i])
			continue;
		/*
		 * Some FIMC variants are not fitted with camera capture
		 * interface. Skip creating a link from sensor for those.
		 */
		if (!fmd->fimc[i]->variant->has_cam_if)
			continue;

		flags = ((1 << i) & link_mask) ? MEDIA_LNK_FL_ENABLED : 0;

		sink = &fmd->fimc[i]->vid_cap.subdev.entity;
		ret = media_create_pad_link(source, pad, sink,
					      FIMC_SD_PAD_SINK_CAM, flags);
		if (ret)
			return ret;

		/* Notify FIMC capture subdev entity */
		ret = media_entity_call(sink, link_setup, &sink->pads[0],
					&source->pads[pad], flags);
		if (ret)
			break;

		v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]\n",
			  source->name, flags ? '=' : '-', sink->name);
	}

	for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) {
		if (!fmd->fimc_lite[i])
			continue;

		sink = &fmd->fimc_lite[i]->subdev.entity;
		ret = media_create_pad_link(source, pad, sink,
					       FLITE_SD_PAD_SINK, 0);
		if (ret)
			return ret;

		/* Notify FIMC-LITE subdev entity */
		ret = media_entity_call(sink, link_setup, &sink->pads[0],
					&source->pads[pad], 0);
		if (ret)
			break;

		v4l2_info(&fmd->v4l2_dev, "created link [%s] -> [%s]\n",
			  source->name, sink->name);
	}
	return 0;
}
Exemple #5
0
/**
 * fimc_md_create_links - create default links between registered entities
 *
 * Parallel interface sensor entities are connected directly to FIMC capture
 * entities. The sensors using MIPI CSIS bus are connected through immutable
 * link with CSI receiver entity specified by mux_id. Any registered CSIS
 * entity has a link to each registered FIMC capture entity. Enabled links
 * are created by default between each subsequent registered sensor and
 * subsequent FIMC capture entity. The number of default active links is
 * determined by the number of available sensors or FIMC entities,
 * whichever is less.
 */
static int fimc_md_create_links(struct fimc_md *fmd)
{
	struct v4l2_subdev *sensor, *csis;
	struct fimc_sensor_info *s_info;
	struct s5p_fimc_isp_info *pdata;
	struct media_entity *source, *sink;
	int i, j, ret = 0;
	u32 flags = 0;

	for (j = 0; j < fmd->num_sensors; j++) {
		if (fmd->sensor[j].subdev == NULL) {
			v4l2_warn(&fmd->v4l2_dev,
				"fmd->sensor[%d].subdev = NULL!!\n", j);
			continue;
		}

		sensor = fmd->sensor[j].subdev;
		s_info = v4l2_get_subdev_hostdata(sensor);
		if (!s_info) {
			v4l2_warn(&fmd->v4l2_dev,
				"(%d) fimc_sensor_info = NULL!!\n", j);
			continue;
		}
		pdata = &s_info->pdata;
		switch (pdata->bus_type) {
		case FIMC_ITU_601...FIMC_ITU_656:
			/* TODO : add ITU configuration */
			break;
		case FIMC_MIPI_CSI2:
			/* 1. create link beween sensor and mipi-csi */
			if (WARN(pdata->mux_id >= CSIS_MAX_ENTITIES,
				"Wrong CSI channel id: %d\n", pdata->mux_id))
				return -EINVAL;
			csis = fmd->csis[pdata->mux_id].sd;
			if (WARN(csis == NULL,
				 "MIPI-CSI interface specified "
				 "but s5p-csis module is not loaded!\n"))
				return -EINVAL;

			ret = media_entity_create_link(&sensor->entity, 0,
					      &csis->entity, CSIS_PAD_SINK,
					      flags);
			if (ret)
				return ret;

			v4l2_info(&fmd->v4l2_dev, "created link [%s] -> [%s]",
				  sensor->entity.name, csis->entity.name);

			/* 2. create link beween mipi-csi and fimc */
			source = &csis->entity;
			for (i = 0; i < FIMC_MAX_DEVS; i++) {
				if (!fmd->fimc[i])
					continue;
				/*
				 * Some FIMC variants are not fitted with camera capture
				 * interface. Skip creating a link from sensor for those.
				 */
				if (!fmd->fimc[i]->variant->has_cam_if)
					continue;
				sink = &fmd->fimc[i]->vid_cap.subdev.entity;

				ret = media_entity_create_link(source,
					CSIS_PAD_SOURCE,
					sink,
					FIMC_SD_PAD_SINK, flags);
				if (ret)
					return ret;

				/* Notify FIMC capture subdev entity */
				ret = media_entity_call(sink, link_setup,
					&sink->pads[FIMC_SD_PAD_SINK],
					&source->pads[CSIS_PAD_SOURCE], flags);

				if (ret)
					break;
				v4l2_info(&fmd->v4l2_dev,
					"created link [%s] %c> [%s]",
					source->name, flags ? '=' : '-',
					sink->name);
			}
			break;
		case FIMC_IS_WB:
			/* 1. create link beween sensor and mipi-csi */
			if (WARN(pdata->mux_id >= CSIS_MAX_ENTITIES,
				"Wrong CSI channel id: %d\n", pdata->mux_id))
				return -EINVAL;
			csis = fmd->csis[pdata->mux_id].sd;
			if (WARN(csis == NULL,
				 "MIPI-CSI interface specified "
				 "but s5p-csis module is not loaded!\n"))
				return -EINVAL;

			ret = media_entity_create_link(&sensor->entity, 0,
					      &csis->entity, CSIS_PAD_SINK,
					      flags);
			if (ret)
				return ret;

			v4l2_info(&fmd->v4l2_dev, "created link [%s] -> [%s]",
				  sensor->entity.name, csis->entity.name);
			/* 2. create link beween mipi-csi and fimc-lite */
			source = &csis->entity;
			sink = &fmd->fimc_lite[pdata->mux_id]->subdev.entity;
			ret = media_entity_create_link(source, CSIS_PAD_SOURCE,
					sink, FLITE_SD_PAD_SINK,
					flags);
			if (ret)
				return ret;
			/* Notify FIMC-LITE subdev entity */
			ret = media_entity_call(sink, link_setup,
					&source->pads[CSIS_PAD_SOURCE],
					&sink->pads[FLITE_SD_PAD_SINK],
					flags);
			if (ret)
				break;

			v4l2_info(&fmd->v4l2_dev, "created link [%s] -> [%s]",
				source->name, sink->name);
			/* 3. create link beween fimc-lite and fimc-is */
			source = &fmd->fimc_lite[pdata->mux_id]->subdev.entity;
			sink = &fmd->fimc_is->isp.subdev.entity;
			ret = media_entity_create_link(source,
					FLITE_SD_PAD_SOURCE,
					sink, FIMC_IS_SD_PAD_SINK,
					flags);
			if (ret)
				return ret;

			/* Notify FIMC-IS subdev entity */
			ret = media_entity_call(sink, link_setup,
					&source->pads[FLITE_SD_PAD_SOURCE],
					&sink->pads[FIMC_IS_SD_PAD_SINK],
					flags);

			v4l2_info(&fmd->v4l2_dev, "created link [%s] -> [%s]",
				source->name, sink->name);

			/* 4. create link beween fimc-is and fimc */
			source = &fmd->fimc_is->isp.subdev.entity;
			for (i = 0; i < (FIMC_MAX_DEVS - 1); i++) {
				if (!fmd->fimc[i])
					continue;
				/*
				 * Some FIMC variants are not fitted with camera capture
				 * interface. Skip creating a link from sensor for those.
				 */
				if (!fmd->fimc[i]->variant->has_cam_if)
					continue;
				sink = &fmd->fimc[i]->vid_cap.subdev.entity;

				ret = media_entity_create_link(source,
					CSIS_PAD_SOURCE,
					sink,
					FIMC_SD_PAD_SINK, flags);
				if (ret)
					return ret;

				/* Notify FIMC capture subdev entity */
				ret = media_entity_call(sink, link_setup,
					&source->pads[CSIS_PAD_SOURCE],
					&sink->pads[FIMC_SD_PAD_SINK],
					flags);

				if (ret)
					break;
				v4l2_info(&fmd->v4l2_dev,
					"created link [%s] %c> [%s]",
					source->name, flags ? '=' : '-',
					sink->name);
			}
			break;
		default:
			v4l2_err(&fmd->v4l2_dev, "Wrong bus_type: %x\n",
				 pdata->bus_type);
			return -EINVAL;
		}
	}

	/* Create immutable link between each FIMC's subdev and video node */
	flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED;
	for (i = 0; i < FIMC_MAX_DEVS; i++) {
		if (!fmd->fimc[i])
			continue;
		source = &fmd->fimc[i]->vid_cap.subdev.entity;
		sink = &fmd->fimc[i]->vid_cap.vfd.entity;
		ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE,
					      sink, 0, flags);
		if (ret)
			break;
		v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]",
				source->name, flags ? '=' : '-', sink->name);
	}
	return ret;
}
Exemple #6
0
/**
 * __fimc_md_create_fimc_links - create links to all FIMC entities
 * @fmd: fimc media device
 * @source: the source entity to create links to all fimc entities from
 * @sensor: sensor subdev linked to FIMC[fimc_id] entity, may be null
 * @pad: the source entity pad index
 * @link_mask: bitmask of the fimc devices for which link should be enabled
 */
static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
					    struct media_entity *source,
					    struct v4l2_subdev *sensor,
					    int pad, int link_mask)
{
	struct fimc_sensor_info *s_info;
	struct media_entity *sink;
	unsigned int flags = 0;
	int ret, i;

	for (i = 0; i < FIMC_MAX_DEVS; i++) {
		if (!fmd->fimc[i])
			continue;
		/*
		 * Some FIMC variants are not fitted with camera capture
		 * interface. Skip creating a link from sensor for those.
		 */
		if (!fmd->fimc[i]->variant->has_cam_if)
			continue;

		flags = ((1 << i) & link_mask) ? MEDIA_LNK_FL_ENABLED : 0;

		sink = &fmd->fimc[i]->vid_cap.subdev.entity;
		ret = media_entity_create_link(source, pad, sink,
					      FIMC_SD_PAD_SINK, flags);
		if (ret)
			return ret;

		/* Notify FIMC capture subdev entity */
		ret = media_entity_call(sink, link_setup, &sink->pads[0],
					&source->pads[pad], flags);
		if (ret)
			break;

		v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]",
			  source->name, flags ? '=' : '-', sink->name);

		if (flags == 0 || sensor == NULL)
			continue;
		s_info = v4l2_get_subdev_hostdata(sensor);
		if (!(s_info == NULL)&&!i) {
			unsigned long irq_flags;
			spin_lock_irqsave(&fmd->slock, irq_flags);
			s_info->host = fmd->fimc[i];
			spin_unlock_irqrestore(&fmd->slock, irq_flags);
		}
	}

	for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) {
		if (!fmd->fimc_lite[i])
			continue;

		if (link_mask & (1 << (i + FIMC_MAX_DEVS)))
			flags = MEDIA_LNK_FL_ENABLED;
		else
			flags = 0;

		sink = &fmd->fimc_lite[i]->subdev.entity;
		ret = media_entity_create_link(source, pad, sink,
					       FLITE_SD_PAD_SINK, flags);
		if (ret)
			return ret;

		/* Notify FIMC-LITE subdev entity */
		ret = media_entity_call(sink, link_setup, &sink->pads[0],
					&source->pads[pad], flags);
		if (ret)
			break;

		v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]",
			  source->name, flags ? '=' : '-', sink->name);
	}
	return 0;
}