Exemplo n.º 1
0
static struct v4l2_flash *__v4l2_flash_init(
	struct device *dev, struct fwnode_handle *fwn,
	struct led_classdev_flash *fled_cdev, struct led_classdev *iled_cdev,
	const struct v4l2_flash_ops *ops, struct v4l2_flash_config *config)
{
	struct v4l2_flash *v4l2_flash;
	struct v4l2_subdev *sd;
	int ret;

	if (!config)
		return ERR_PTR(-EINVAL);

	v4l2_flash = devm_kzalloc(dev, sizeof(*v4l2_flash), GFP_KERNEL);
	if (!v4l2_flash)
		return ERR_PTR(-ENOMEM);

	sd = &v4l2_flash->sd;
	v4l2_flash->fled_cdev = fled_cdev;
	v4l2_flash->iled_cdev = iled_cdev;
	v4l2_flash->ops = ops;
	sd->dev = dev;
	sd->fwnode = fwn ? fwn : dev_fwnode(dev);
	v4l2_subdev_init(sd, &v4l2_flash_subdev_ops);
	sd->internal_ops = &v4l2_flash_subdev_internal_ops;
	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
	strlcpy(sd->name, config->dev_name, sizeof(sd->name));

	ret = media_entity_pads_init(&sd->entity, 0, NULL);
	if (ret < 0)
		return ERR_PTR(ret);

	sd->entity.function = MEDIA_ENT_F_FLASH;

	ret = v4l2_flash_init_controls(v4l2_flash, config);
	if (ret < 0)
		goto err_init_controls;

	fwnode_handle_get(sd->fwnode);

	ret = v4l2_async_register_subdev(sd);
	if (ret < 0)
		goto err_async_register_sd;

	return v4l2_flash;

err_async_register_sd:
	fwnode_handle_put(sd->fwnode);
	v4l2_ctrl_handler_free(sd->ctrl_handler);
err_init_controls:
	media_entity_cleanup(&sd->entity);

	return ERR_PTR(ret);
}
Exemplo n.º 2
0
/**
 * fwnode_graph_get_endpoint_by_id - get endpoint by port and endpoint numbers
 * @fwnode: parent fwnode_handle containing the graph
 * @port: identifier of the port node
 * @endpoint: identifier of the endpoint node under the port node
 * @flags: fwnode lookup flags
 *
 * Return the fwnode handle of the local endpoint corresponding the port and
 * endpoint IDs or NULL if not found.
 *
 * If FWNODE_GRAPH_ENDPOINT_NEXT is passed in @flags and the specified endpoint
 * has not been found, look for the closest endpoint ID greater than the
 * specified one and return the endpoint that corresponds to it, if present.
 *
 * Do not return endpoints that belong to disabled devices, unless
 * FWNODE_GRAPH_DEVICE_DISABLED is passed in @flags.
 *
 * The returned endpoint needs to be released by calling fwnode_handle_put() on
 * it when it is not needed any more.
 */
struct fwnode_handle *
fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode,
				u32 port, u32 endpoint, unsigned long flags)
{
	struct fwnode_handle *ep = NULL, *best_ep = NULL;
	unsigned int best_ep_id = 0;
	bool endpoint_next = flags & FWNODE_GRAPH_ENDPOINT_NEXT;
	bool enabled_only = !(flags & FWNODE_GRAPH_DEVICE_DISABLED);

	while ((ep = fwnode_graph_get_next_endpoint(fwnode, ep))) {
		struct fwnode_endpoint fwnode_ep = { 0 };
		int ret;

		if (enabled_only) {
			struct fwnode_handle *dev_node;
			bool available;

			dev_node = fwnode_graph_get_remote_port_parent(ep);
			available = fwnode_device_is_available(dev_node);
			fwnode_handle_put(dev_node);
			if (!available)
				continue;
		}

		ret = fwnode_graph_parse_endpoint(ep, &fwnode_ep);
		if (ret < 0)
			continue;

		if (fwnode_ep.port != port)
			continue;

		if (fwnode_ep.id == endpoint)
			return ep;

		if (!endpoint_next)
			continue;

		/*
		 * If the endpoint that has just been found is not the first
		 * matching one and the ID of the one found previously is closer
		 * to the requested endpoint ID, skip it.
		 */
		if (fwnode_ep.id < endpoint ||
		    (best_ep && best_ep_id < fwnode_ep.id))
			continue;

		fwnode_handle_put(best_ep);
		best_ep = fwnode_handle_get(ep);
		best_ep_id = fwnode_ep.id;
	}

	return best_ep;
}