Lines Matching +full:video +full:- +full:mux

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * video stream multiplexer controlled via mux control
6 * Copyright (C) 2016-2017 Pengutronix, Philipp Zabel <kernel@pengutronix.de>
12 #include <linux/mux/consumer.h>
17 #include <media/v4l2-async.h>
18 #include <media/v4l2-device.h>
19 #include <media/v4l2-fwnode.h>
20 #include <media/v4l2-mc.h>
21 #include <media/v4l2-subdev.h>
27 struct mux_control *mux; member
56 u16 source_pad = entity->num_pads - 1; in video_mux_link_setup()
60 * The mux state is determined by the enabled sink pad link. in video_mux_link_setup()
63 if (local->flags & MEDIA_PAD_FL_SOURCE) in video_mux_link_setup()
66 dev_dbg(sd->dev, "link setup '%s':%d->'%s':%d[%d]", in video_mux_link_setup()
67 remote->entity->name, remote->index, local->entity->name, in video_mux_link_setup()
68 local->index, flags & MEDIA_LNK_FL_ENABLED); in video_mux_link_setup()
70 mutex_lock(&vmux->lock); in video_mux_link_setup()
76 if (vmux->active == local->index) in video_mux_link_setup()
79 if (vmux->active >= 0) { in video_mux_link_setup()
80 ret = -EBUSY; in video_mux_link_setup()
84 dev_dbg(sd->dev, "setting %d active\n", local->index); in video_mux_link_setup()
85 ret = mux_control_try_select(vmux->mux, local->index); in video_mux_link_setup()
88 vmux->active = local->index; in video_mux_link_setup()
95 vmux->active); in video_mux_link_setup()
98 if (vmux->active != local->index) in video_mux_link_setup()
101 dev_dbg(sd->dev, "going inactive\n"); in video_mux_link_setup()
102 mux_control_deselect(vmux->mux); in video_mux_link_setup()
103 vmux->active = -1; in video_mux_link_setup()
107 mutex_unlock(&vmux->lock); in video_mux_link_setup()
123 if (vmux->active == -1) { in video_mux_s_stream()
124 dev_err(sd->dev, "Can not start streaming on inactive mux\n"); in video_mux_s_stream()
125 return -EINVAL; in video_mux_s_stream()
128 pad = media_pad_remote_pad_first(&sd->entity.pads[vmux->active]); in video_mux_s_stream()
130 dev_err(sd->dev, "Failed to find remote source pad\n"); in video_mux_s_stream()
131 return -ENOLINK; in video_mux_s_stream()
134 if (!is_media_entity_v4l2_subdev(pad->entity)) { in video_mux_s_stream()
135 dev_err(sd->dev, "Upstream entity is not a v4l2 subdev\n"); in video_mux_s_stream()
136 return -ENODEV; in video_mux_s_stream()
139 upstream_sd = media_entity_to_v4l2_subdev(pad->entity); in video_mux_s_stream()
141 return v4l2_subdev_call(upstream_sd, video, s_stream, enable); in video_mux_s_stream()
154 struct media_pad *pad = &vmux->pads[sdformat->pad]; in video_mux_set_format()
155 u16 source_pad = sd->entity.num_pads - 1; in video_mux_set_format()
157 mbusformat = v4l2_subdev_state_get_format(sd_state, sdformat->pad); in video_mux_set_format()
159 return -EINVAL; in video_mux_set_format()
163 return -EINVAL; in video_mux_set_format()
166 v4l_bound_align_image(&sdformat->format.width, 1, 65536, 0, in video_mux_set_format()
167 &sdformat->format.height, 1, 65536, 0, 0); in video_mux_set_format()
170 switch (sdformat->format.code) { in video_mux_set_format()
261 sdformat->format.code = MEDIA_BUS_FMT_Y8_1X8; in video_mux_set_format()
264 if (sdformat->format.field == V4L2_FIELD_ANY) in video_mux_set_format()
265 sdformat->format.field = V4L2_FIELD_NONE; in video_mux_set_format()
267 mutex_lock(&vmux->lock); in video_mux_set_format()
270 if ((pad->flags & MEDIA_PAD_FL_SOURCE) && vmux->active >= 0) in video_mux_set_format()
271 sdformat->format = *v4l2_subdev_state_get_format(sd_state, in video_mux_set_format()
272 vmux->active); in video_mux_set_format()
274 *mbusformat = sdformat->format; in video_mux_set_format()
277 if ((pad->flags & MEDIA_PAD_FL_SINK) && (pad->index == vmux->active)) in video_mux_set_format()
278 *source_mbusformat = sdformat->format; in video_mux_set_format()
280 mutex_unlock(&vmux->lock); in video_mux_set_format()
292 mutex_lock(&vmux->lock); in video_mux_init_state()
294 for (i = 0; i < sd->entity.num_pads; i++) { in video_mux_init_state()
299 mutex_unlock(&vmux->lock); in video_mux_init_state()
311 .video = &video_mux_subdev_video_ops,
324 return v4l2_create_fwnode_links(sd, &vmux->subdev); in video_mux_notify_bound()
337 v4l2_async_subdev_nf_init(&vmux->notifier, &vmux->subdev); in video_mux_async_register()
344 dev_fwnode(vmux->subdev.dev), i, 0, in video_mux_async_register()
357 asd = v4l2_async_nf_add_fwnode_remote(&vmux->notifier, ep, in video_mux_async_register()
365 if (ret != -EEXIST) in video_mux_async_register()
370 vmux->notifier.ops = &video_mux_notify_ops; in video_mux_async_register()
372 ret = v4l2_async_nf_register(&vmux->notifier); in video_mux_async_register()
376 ret = v4l2_async_register_subdev(&vmux->subdev); in video_mux_async_register()
383 v4l2_async_nf_unregister(&vmux->notifier); in video_mux_async_register()
385 v4l2_async_nf_cleanup(&vmux->notifier); in video_mux_async_register()
391 struct device_node *np = pdev->dev.of_node; in video_mux_probe()
392 struct device *dev = &pdev->dev; in video_mux_probe()
401 return -ENOMEM; in video_mux_probe()
405 v4l2_subdev_init(&vmux->subdev, &video_mux_subdev_ops); in video_mux_probe()
406 vmux->subdev.internal_ops = &video_mux_internal_ops; in video_mux_probe()
407 snprintf(vmux->subdev.name, sizeof(vmux->subdev.name), "%pOFn", np); in video_mux_probe()
408 vmux->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; in video_mux_probe()
409 vmux->subdev.dev = dev; in video_mux_probe()
424 return -EINVAL; in video_mux_probe()
427 vmux->mux = devm_mux_control_get(dev, NULL); in video_mux_probe()
428 if (IS_ERR(vmux->mux)) { in video_mux_probe()
429 ret = PTR_ERR(vmux->mux); in video_mux_probe()
430 return dev_err_probe(dev, ret, "Failed to get mux\n"); in video_mux_probe()
433 mutex_init(&vmux->lock); in video_mux_probe()
434 vmux->active = -1; in video_mux_probe()
435 vmux->pads = devm_kcalloc(dev, num_pads, sizeof(*vmux->pads), in video_mux_probe()
437 if (!vmux->pads) in video_mux_probe()
438 return -ENOMEM; in video_mux_probe()
441 vmux->pads[i].flags = (i < num_pads - 1) ? MEDIA_PAD_FL_SINK in video_mux_probe()
444 vmux->subdev.entity.function = MEDIA_ENT_F_VID_MUX; in video_mux_probe()
445 ret = media_entity_pads_init(&vmux->subdev.entity, num_pads, in video_mux_probe()
446 vmux->pads); in video_mux_probe()
450 vmux->subdev.entity.ops = &video_mux_ops; in video_mux_probe()
452 ret = v4l2_subdev_init_finalize(&vmux->subdev); in video_mux_probe()
456 ret = video_mux_async_register(vmux, num_pads - 1); in video_mux_probe()
463 v4l2_subdev_cleanup(&vmux->subdev); in video_mux_probe()
465 media_entity_cleanup(&vmux->subdev.entity); in video_mux_probe()
472 struct v4l2_subdev *sd = &vmux->subdev; in video_mux_remove()
474 v4l2_async_nf_unregister(&vmux->notifier); in video_mux_remove()
475 v4l2_async_nf_cleanup(&vmux->notifier); in video_mux_remove()
478 media_entity_cleanup(&sd->entity); in video_mux_remove()
482 { .compatible = "video-mux", },
492 .name = "video-mux",
498 MODULE_DESCRIPTION("video stream multiplexer");