1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (C) 2010 Nokia Corporation
7 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
8 * Sakari Ailus <sakari.ailus@iki.fi>
11 #include <linux/bitmap.h>
12 #include <linux/list.h>
13 #include <linux/property.h>
14 #include <linux/slab.h>
15 #include <media/media-entity.h>
16 #include <media/media-device.h>
18 static inline const char *intf_type(struct media_interface
*intf
)
21 case MEDIA_INTF_T_DVB_FE
:
22 return "dvb-frontend";
23 case MEDIA_INTF_T_DVB_DEMUX
:
25 case MEDIA_INTF_T_DVB_DVR
:
27 case MEDIA_INTF_T_DVB_CA
:
29 case MEDIA_INTF_T_DVB_NET
:
31 case MEDIA_INTF_T_V4L_VIDEO
:
33 case MEDIA_INTF_T_V4L_VBI
:
35 case MEDIA_INTF_T_V4L_RADIO
:
37 case MEDIA_INTF_T_V4L_SUBDEV
:
39 case MEDIA_INTF_T_V4L_SWRADIO
:
41 case MEDIA_INTF_T_V4L_TOUCH
:
44 return "unknown-intf";
48 static inline const char *link_type_name(struct media_link
*link
)
50 switch (link
->flags
& MEDIA_LNK_FL_LINK_TYPE
) {
51 case MEDIA_LNK_FL_DATA_LINK
:
53 case MEDIA_LNK_FL_INTERFACE_LINK
:
55 case MEDIA_LNK_FL_ANCILLARY_LINK
:
62 __must_check
int media_entity_enum_init(struct media_entity_enum
*ent_enum
,
63 struct media_device
*mdev
)
67 idx_max
= ALIGN(mdev
->entity_internal_idx_max
+ 1, BITS_PER_LONG
);
68 ent_enum
->bmap
= bitmap_zalloc(idx_max
, GFP_KERNEL
);
72 ent_enum
->idx_max
= idx_max
;
76 EXPORT_SYMBOL_GPL(media_entity_enum_init
);
78 void media_entity_enum_cleanup(struct media_entity_enum
*ent_enum
)
80 bitmap_free(ent_enum
->bmap
);
82 EXPORT_SYMBOL_GPL(media_entity_enum_cleanup
);
85 * dev_dbg_obj - Prints in debug mode a change on some object
87 * @event_name: Name of the event to report. Could be __func__
88 * @gobj: Pointer to the object
90 * Enabled only if DEBUG or CONFIG_DYNAMIC_DEBUG. Otherwise, it
91 * won't produce any code.
93 static void dev_dbg_obj(const char *event_name
, struct media_gobj
*gobj
)
95 #if defined(DEBUG) || defined (CONFIG_DYNAMIC_DEBUG)
96 switch (media_type(gobj
)) {
97 case MEDIA_GRAPH_ENTITY
:
98 dev_dbg(gobj
->mdev
->dev
,
99 "%s id %u: entity '%s'\n",
100 event_name
, media_id(gobj
),
101 gobj_to_entity(gobj
)->name
);
103 case MEDIA_GRAPH_LINK
:
105 struct media_link
*link
= gobj_to_link(gobj
);
107 dev_dbg(gobj
->mdev
->dev
,
108 "%s id %u: %s link id %u ==> id %u\n",
109 event_name
, media_id(gobj
), link_type_name(link
),
110 media_id(link
->gobj0
),
111 media_id(link
->gobj1
));
114 case MEDIA_GRAPH_PAD
:
116 struct media_pad
*pad
= gobj_to_pad(gobj
);
118 dev_dbg(gobj
->mdev
->dev
,
119 "%s id %u: %s%spad '%s':%d\n",
120 event_name
, media_id(gobj
),
121 pad
->flags
& MEDIA_PAD_FL_SINK
? "sink " : "",
122 pad
->flags
& MEDIA_PAD_FL_SOURCE
? "source " : "",
123 pad
->entity
->name
, pad
->index
);
126 case MEDIA_GRAPH_INTF_DEVNODE
:
128 struct media_interface
*intf
= gobj_to_intf(gobj
);
129 struct media_intf_devnode
*devnode
= intf_to_devnode(intf
);
131 dev_dbg(gobj
->mdev
->dev
,
132 "%s id %u: intf_devnode %s - major: %d, minor: %d\n",
133 event_name
, media_id(gobj
),
135 devnode
->major
, devnode
->minor
);
142 void media_gobj_create(struct media_device
*mdev
,
143 enum media_gobj_type type
,
144 struct media_gobj
*gobj
)
150 /* Create a per-type unique object ID */
151 gobj
->id
= media_gobj_gen_id(type
, ++mdev
->id
);
154 case MEDIA_GRAPH_ENTITY
:
155 list_add_tail(&gobj
->list
, &mdev
->entities
);
157 case MEDIA_GRAPH_PAD
:
158 list_add_tail(&gobj
->list
, &mdev
->pads
);
160 case MEDIA_GRAPH_LINK
:
161 list_add_tail(&gobj
->list
, &mdev
->links
);
163 case MEDIA_GRAPH_INTF_DEVNODE
:
164 list_add_tail(&gobj
->list
, &mdev
->interfaces
);
168 mdev
->topology_version
++;
170 dev_dbg_obj(__func__
, gobj
);
173 void media_gobj_destroy(struct media_gobj
*gobj
)
175 /* Do nothing if the object is not linked. */
176 if (gobj
->mdev
== NULL
)
179 dev_dbg_obj(__func__
, gobj
);
181 gobj
->mdev
->topology_version
++;
183 /* Remove the object from mdev list */
184 list_del(&gobj
->list
);
190 * TODO: Get rid of this.
192 #define MEDIA_ENTITY_MAX_PADS 512
194 int media_entity_pads_init(struct media_entity
*entity
, u16 num_pads
,
195 struct media_pad
*pads
)
197 struct media_device
*mdev
= entity
->graph_obj
.mdev
;
198 struct media_pad
*iter
;
202 if (num_pads
>= MEDIA_ENTITY_MAX_PADS
)
205 entity
->num_pads
= num_pads
;
209 mutex_lock(&mdev
->graph_mutex
);
211 media_entity_for_each_pad(entity
, iter
) {
212 iter
->entity
= entity
;
215 if (hweight32(iter
->flags
& (MEDIA_PAD_FL_SINK
|
216 MEDIA_PAD_FL_SOURCE
)) != 1) {
222 media_gobj_create(mdev
, MEDIA_GRAPH_PAD
,
227 media_entity_for_each_pad(entity
, iter
)
228 media_gobj_destroy(&iter
->graph_obj
);
232 mutex_unlock(&mdev
->graph_mutex
);
236 EXPORT_SYMBOL_GPL(media_entity_pads_init
);
238 /* -----------------------------------------------------------------------------
243 * media_entity_has_pad_interdep - Check interdependency between two pads
245 * @entity: The entity
246 * @pad0: The first pad index
247 * @pad1: The second pad index
249 * This function checks the interdependency inside the entity between @pad0
250 * and @pad1. If two pads are interdependent they are part of the same pipeline
251 * and enabling one of the pads means that the other pad will become "locked"
252 * and doesn't allow configuration changes.
254 * This function uses the &media_entity_operations.has_pad_interdep() operation
255 * to check the dependency inside the entity between @pad0 and @pad1. If the
256 * has_pad_interdep operation is not implemented, all pads of the entity are
257 * considered to be interdependent.
259 * One of @pad0 and @pad1 must be a sink pad and the other one a source pad.
260 * The function returns false if both pads are sinks or sources.
262 * The caller must hold entity->graph_obj.mdev->mutex.
264 * Return: true if the pads are connected internally and false otherwise.
266 static bool media_entity_has_pad_interdep(struct media_entity
*entity
,
267 unsigned int pad0
, unsigned int pad1
)
269 if (pad0
>= entity
->num_pads
|| pad1
>= entity
->num_pads
)
272 if (entity
->pads
[pad0
].flags
& entity
->pads
[pad1
].flags
&
273 (MEDIA_PAD_FL_SINK
| MEDIA_PAD_FL_SOURCE
))
276 if (!entity
->ops
|| !entity
->ops
->has_pad_interdep
)
279 return entity
->ops
->has_pad_interdep(entity
, pad0
, pad1
);
282 static struct media_entity
*
283 media_entity_other(struct media_entity
*entity
, struct media_link
*link
)
285 if (link
->source
->entity
== entity
)
286 return link
->sink
->entity
;
288 return link
->source
->entity
;
291 /* push an entity to traversal stack */
292 static void stack_push(struct media_graph
*graph
,
293 struct media_entity
*entity
)
295 if (graph
->top
== MEDIA_ENTITY_ENUM_MAX_DEPTH
- 1) {
300 graph
->stack
[graph
->top
].link
= entity
->links
.next
;
301 graph
->stack
[graph
->top
].entity
= entity
;
304 static struct media_entity
*stack_pop(struct media_graph
*graph
)
306 struct media_entity
*entity
;
308 entity
= graph
->stack
[graph
->top
].entity
;
314 #define link_top(en) ((en)->stack[(en)->top].link)
315 #define stack_top(en) ((en)->stack[(en)->top].entity)
318 * media_graph_walk_init - Allocate resources for graph walk
319 * @graph: Media graph structure that will be used to walk the graph
320 * @mdev: Media device
322 * Reserve resources for graph walk in media device's current
323 * state. The memory must be released using
324 * media_graph_walk_cleanup().
326 * Returns error on failure, zero on success.
328 __must_check
int media_graph_walk_init(
329 struct media_graph
*graph
, struct media_device
*mdev
)
331 return media_entity_enum_init(&graph
->ent_enum
, mdev
);
333 EXPORT_SYMBOL_GPL(media_graph_walk_init
);
336 * media_graph_walk_cleanup - Release resources related to graph walking
337 * @graph: Media graph structure that was used to walk the graph
339 void media_graph_walk_cleanup(struct media_graph
*graph
)
341 media_entity_enum_cleanup(&graph
->ent_enum
);
343 EXPORT_SYMBOL_GPL(media_graph_walk_cleanup
);
345 void media_graph_walk_start(struct media_graph
*graph
,
346 struct media_entity
*entity
)
348 media_entity_enum_zero(&graph
->ent_enum
);
349 media_entity_enum_set(&graph
->ent_enum
, entity
);
352 graph
->stack
[graph
->top
].entity
= NULL
;
353 stack_push(graph
, entity
);
354 dev_dbg(entity
->graph_obj
.mdev
->dev
,
355 "begin graph walk at '%s'\n", entity
->name
);
357 EXPORT_SYMBOL_GPL(media_graph_walk_start
);
359 static void media_graph_walk_iter(struct media_graph
*graph
)
361 struct media_entity
*entity
= stack_top(graph
);
362 struct media_link
*link
;
363 struct media_entity
*next
;
365 link
= list_entry(link_top(graph
), typeof(*link
), list
);
367 /* If the link is not a data link, don't follow it */
368 if ((link
->flags
& MEDIA_LNK_FL_LINK_TYPE
) != MEDIA_LNK_FL_DATA_LINK
) {
369 link_top(graph
) = link_top(graph
)->next
;
373 /* The link is not enabled so we do not follow. */
374 if (!(link
->flags
& MEDIA_LNK_FL_ENABLED
)) {
375 link_top(graph
) = link_top(graph
)->next
;
376 dev_dbg(entity
->graph_obj
.mdev
->dev
,
377 "walk: skipping disabled link '%s':%u -> '%s':%u\n",
378 link
->source
->entity
->name
, link
->source
->index
,
379 link
->sink
->entity
->name
, link
->sink
->index
);
383 /* Get the entity at the other end of the link. */
384 next
= media_entity_other(entity
, link
);
386 /* Has the entity already been visited? */
387 if (media_entity_enum_test_and_set(&graph
->ent_enum
, next
)) {
388 link_top(graph
) = link_top(graph
)->next
;
389 dev_dbg(entity
->graph_obj
.mdev
->dev
,
390 "walk: skipping entity '%s' (already seen)\n",
395 /* Push the new entity to stack and start over. */
396 link_top(graph
) = link_top(graph
)->next
;
397 stack_push(graph
, next
);
398 dev_dbg(entity
->graph_obj
.mdev
->dev
, "walk: pushing '%s' on stack\n",
400 lockdep_assert_held(&entity
->graph_obj
.mdev
->graph_mutex
);
403 struct media_entity
*media_graph_walk_next(struct media_graph
*graph
)
405 struct media_entity
*entity
;
407 if (stack_top(graph
) == NULL
)
411 * Depth first search. Push entity to stack and continue from
412 * top of the stack until no more entities on the level can be
415 while (link_top(graph
) != &stack_top(graph
)->links
)
416 media_graph_walk_iter(graph
);
418 entity
= stack_pop(graph
);
419 dev_dbg(entity
->graph_obj
.mdev
->dev
,
420 "walk: returning entity '%s'\n", entity
->name
);
424 EXPORT_SYMBOL_GPL(media_graph_walk_next
);
426 /* -----------------------------------------------------------------------------
427 * Pipeline management
431 * The pipeline traversal stack stores pads that are reached during graph
432 * traversal, with a list of links to be visited to continue the traversal.
433 * When a new pad is reached, an entry is pushed on the top of the stack and
434 * points to the incoming pad and the first link of the entity.
436 * To find further pads in the pipeline, the traversal algorithm follows
437 * internal pad dependencies in the entity, and then links in the graph. It
438 * does so by iterating over all links of the entity, and following enabled
439 * links that originate from a pad that is internally connected to the incoming
440 * pad, as reported by the media_entity_has_pad_interdep() function.
444 * struct media_pipeline_walk_entry - Entry in the pipeline traversal stack
446 * @pad: The media pad being visited
447 * @links: Links left to be visited
449 struct media_pipeline_walk_entry
{
450 struct media_pad
*pad
;
451 struct list_head
*links
;
455 * struct media_pipeline_walk - State used by the media pipeline traversal
458 * @mdev: The media device
459 * @stack: Depth-first search stack
460 * @stack.size: Number of allocated entries in @stack.entries
461 * @stack.top: Index of the top stack entry (-1 if the stack is empty)
462 * @stack.entries: Stack entries
464 struct media_pipeline_walk
{
465 struct media_device
*mdev
;
470 struct media_pipeline_walk_entry
*entries
;
474 #define MEDIA_PIPELINE_STACK_GROW_STEP 16
476 static struct media_pipeline_walk_entry
*
477 media_pipeline_walk_top(struct media_pipeline_walk
*walk
)
479 return &walk
->stack
.entries
[walk
->stack
.top
];
482 static bool media_pipeline_walk_empty(struct media_pipeline_walk
*walk
)
484 return walk
->stack
.top
== -1;
487 /* Increase the stack size by MEDIA_PIPELINE_STACK_GROW_STEP elements. */
488 static int media_pipeline_walk_resize(struct media_pipeline_walk
*walk
)
490 struct media_pipeline_walk_entry
*entries
;
491 unsigned int new_size
;
493 /* Safety check, to avoid stack overflows in case of bugs. */
494 if (walk
->stack
.size
>= 256)
497 new_size
= walk
->stack
.size
+ MEDIA_PIPELINE_STACK_GROW_STEP
;
499 entries
= krealloc(walk
->stack
.entries
,
500 new_size
* sizeof(*walk
->stack
.entries
),
505 walk
->stack
.entries
= entries
;
506 walk
->stack
.size
= new_size
;
511 /* Push a new entry on the stack. */
512 static int media_pipeline_walk_push(struct media_pipeline_walk
*walk
,
513 struct media_pad
*pad
)
515 struct media_pipeline_walk_entry
*entry
;
518 if (walk
->stack
.top
+ 1 >= walk
->stack
.size
) {
519 ret
= media_pipeline_walk_resize(walk
);
525 entry
= media_pipeline_walk_top(walk
);
527 entry
->links
= pad
->entity
->links
.next
;
529 dev_dbg(walk
->mdev
->dev
,
530 "media pipeline: pushed entry %u: '%s':%u\n",
531 walk
->stack
.top
, pad
->entity
->name
, pad
->index
);
537 * Move the top entry link cursor to the next link. If all links of the entry
538 * have been visited, pop the entry itself. Return true if the entry has been
541 static bool media_pipeline_walk_pop(struct media_pipeline_walk
*walk
)
543 struct media_pipeline_walk_entry
*entry
;
545 if (WARN_ON(walk
->stack
.top
< 0))
548 entry
= media_pipeline_walk_top(walk
);
550 if (entry
->links
->next
== &entry
->pad
->entity
->links
) {
551 dev_dbg(walk
->mdev
->dev
,
552 "media pipeline: entry %u has no more links, popping\n",
559 entry
->links
= entry
->links
->next
;
561 dev_dbg(walk
->mdev
->dev
,
562 "media pipeline: moved entry %u to next link\n",
568 /* Free all memory allocated while walking the pipeline. */
569 static void media_pipeline_walk_destroy(struct media_pipeline_walk
*walk
)
571 kfree(walk
->stack
.entries
);
574 /* Add a pad to the pipeline and push it to the stack. */
575 static int media_pipeline_add_pad(struct media_pipeline
*pipe
,
576 struct media_pipeline_walk
*walk
,
577 struct media_pad
*pad
)
579 struct media_pipeline_pad
*ppad
;
581 list_for_each_entry(ppad
, &pipe
->pads
, list
) {
582 if (ppad
->pad
== pad
) {
583 dev_dbg(pad
->graph_obj
.mdev
->dev
,
584 "media pipeline: already contains pad '%s':%u\n",
585 pad
->entity
->name
, pad
->index
);
590 ppad
= kzalloc(sizeof(*ppad
), GFP_KERNEL
);
597 list_add_tail(&ppad
->list
, &pipe
->pads
);
599 dev_dbg(pad
->graph_obj
.mdev
->dev
,
600 "media pipeline: added pad '%s':%u\n",
601 pad
->entity
->name
, pad
->index
);
603 return media_pipeline_walk_push(walk
, pad
);
606 /* Explore the next link of the entity at the top of the stack. */
607 static int media_pipeline_explore_next_link(struct media_pipeline
*pipe
,
608 struct media_pipeline_walk
*walk
)
610 struct media_pipeline_walk_entry
*entry
= media_pipeline_walk_top(walk
);
611 struct media_pad
*origin
;
612 struct media_link
*link
;
613 struct media_pad
*local
;
614 struct media_pad
*remote
;
619 link
= list_entry(entry
->links
, typeof(*link
), list
);
620 last_link
= media_pipeline_walk_pop(walk
);
622 if ((link
->flags
& MEDIA_LNK_FL_LINK_TYPE
) != MEDIA_LNK_FL_DATA_LINK
) {
623 dev_dbg(walk
->mdev
->dev
,
624 "media pipeline: skipping link (not data-link)\n");
628 dev_dbg(walk
->mdev
->dev
,
629 "media pipeline: exploring link '%s':%u -> '%s':%u\n",
630 link
->source
->entity
->name
, link
->source
->index
,
631 link
->sink
->entity
->name
, link
->sink
->index
);
633 /* Get the local pad and remote pad. */
634 if (link
->source
->entity
== origin
->entity
) {
635 local
= link
->source
;
639 remote
= link
->source
;
643 * Skip links that originate from a different pad than the incoming pad
644 * that is not connected internally in the entity to the incoming pad.
646 if (origin
!= local
&&
647 !media_entity_has_pad_interdep(origin
->entity
, origin
->index
,
649 dev_dbg(walk
->mdev
->dev
,
650 "media pipeline: skipping link (no route)\n");
655 * Add the local pad of the link to the pipeline and push it to the
656 * stack, if not already present.
658 ret
= media_pipeline_add_pad(pipe
, walk
, local
);
662 /* Similarly, add the remote pad, but only if the link is enabled. */
663 if (!(link
->flags
& MEDIA_LNK_FL_ENABLED
)) {
664 dev_dbg(walk
->mdev
->dev
,
665 "media pipeline: skipping link (disabled)\n");
669 ret
= media_pipeline_add_pad(pipe
, walk
, remote
);
675 * If we're done iterating over links, iterate over pads of the entity.
676 * This is necessary to discover pads that are not connected with any
677 * link. Those are dead ends from a pipeline exploration point of view,
678 * but are still part of the pipeline and need to be added to enable
684 dev_dbg(walk
->mdev
->dev
,
685 "media pipeline: adding unconnected pads of '%s'\n",
686 local
->entity
->name
);
688 media_entity_for_each_pad(origin
->entity
, local
) {
690 * Skip the origin pad (already handled), pad that have links
691 * (already discovered through iterating over links) and pads
692 * not internally connected.
694 if (origin
== local
|| !local
->num_links
||
695 !media_entity_has_pad_interdep(origin
->entity
, origin
->index
,
699 ret
= media_pipeline_add_pad(pipe
, walk
, local
);
707 static void media_pipeline_cleanup(struct media_pipeline
*pipe
)
709 while (!list_empty(&pipe
->pads
)) {
710 struct media_pipeline_pad
*ppad
;
712 ppad
= list_first_entry(&pipe
->pads
, typeof(*ppad
), list
);
713 list_del(&ppad
->list
);
718 static int media_pipeline_populate(struct media_pipeline
*pipe
,
719 struct media_pad
*pad
)
721 struct media_pipeline_walk walk
= { };
722 struct media_pipeline_pad
*ppad
;
726 * Populate the media pipeline by walking the media graph, starting
729 INIT_LIST_HEAD(&pipe
->pads
);
730 pipe
->mdev
= pad
->graph_obj
.mdev
;
732 walk
.mdev
= pipe
->mdev
;
734 ret
= media_pipeline_add_pad(pipe
, &walk
, pad
);
739 * Use a depth-first search algorithm: as long as the stack is not
740 * empty, explore the next link of the top entry. The
741 * media_pipeline_explore_next_link() function will either move to the
742 * next link, pop the entry if fully visited, or add new entries on
745 while (!media_pipeline_walk_empty(&walk
)) {
746 ret
= media_pipeline_explore_next_link(pipe
, &walk
);
751 dev_dbg(pad
->graph_obj
.mdev
->dev
,
752 "media pipeline populated, found pads:\n");
754 list_for_each_entry(ppad
, &pipe
->pads
, list
)
755 dev_dbg(pad
->graph_obj
.mdev
->dev
, "- '%s':%u\n",
756 ppad
->pad
->entity
->name
, ppad
->pad
->index
);
758 WARN_ON(walk
.stack
.top
!= -1);
763 media_pipeline_walk_destroy(&walk
);
766 media_pipeline_cleanup(pipe
);
771 __must_check
int __media_pipeline_start(struct media_pad
*origin
,
772 struct media_pipeline
*pipe
)
774 struct media_device
*mdev
= origin
->graph_obj
.mdev
;
775 struct media_pipeline_pad
*err_ppad
;
776 struct media_pipeline_pad
*ppad
;
779 lockdep_assert_held(&mdev
->graph_mutex
);
782 * If the pad is already part of a pipeline, that pipeline must be the
783 * same as the pipe given to media_pipeline_start().
785 if (WARN_ON(origin
->pipe
&& origin
->pipe
!= pipe
))
789 * If the pipeline has already been started, it is guaranteed to be
790 * valid, so just increase the start count.
792 if (pipe
->start_count
) {
798 * Populate the pipeline. This populates the media_pipeline pads list
799 * with media_pipeline_pad instances for each pad found during graph
802 ret
= media_pipeline_populate(pipe
, origin
);
807 * Now that all the pads in the pipeline have been gathered, perform
808 * the validation steps.
811 list_for_each_entry(ppad
, &pipe
->pads
, list
) {
812 struct media_pad
*pad
= ppad
->pad
;
813 struct media_entity
*entity
= pad
->entity
;
814 bool has_enabled_link
= false;
815 struct media_link
*link
;
817 dev_dbg(mdev
->dev
, "Validating pad '%s':%u\n", pad
->entity
->name
,
821 * 1. Ensure that the pad doesn't already belong to a different
825 dev_dbg(mdev
->dev
, "Failed to start pipeline: pad '%s':%u busy\n",
826 pad
->entity
->name
, pad
->index
);
832 * 2. Validate all active links whose sink is the current pad.
833 * Validation of the source pads is performed in the context of
834 * the connected sink pad to avoid duplicating checks.
836 for_each_media_entity_data_link(entity
, link
) {
837 /* Skip links unrelated to the current pad. */
838 if (link
->sink
!= pad
&& link
->source
!= pad
)
841 /* Record if the pad has links and enabled links. */
842 if (link
->flags
& MEDIA_LNK_FL_ENABLED
)
843 has_enabled_link
= true;
846 * Validate the link if it's enabled and has the
847 * current pad as its sink.
849 if (!(link
->flags
& MEDIA_LNK_FL_ENABLED
))
852 if (link
->sink
!= pad
)
855 if (!entity
->ops
|| !entity
->ops
->link_validate
)
858 ret
= entity
->ops
->link_validate(link
);
861 "Link '%s':%u -> '%s':%u failed validation: %d\n",
862 link
->source
->entity
->name
,
864 link
->sink
->entity
->name
,
865 link
->sink
->index
, ret
);
870 "Link '%s':%u -> '%s':%u is valid\n",
871 link
->source
->entity
->name
,
873 link
->sink
->entity
->name
,
878 * 3. If the pad has the MEDIA_PAD_FL_MUST_CONNECT flag set,
879 * ensure that it has either no link or an enabled link.
881 if ((pad
->flags
& MEDIA_PAD_FL_MUST_CONNECT
) &&
884 "Pad '%s':%u must be connected by an enabled link\n",
885 pad
->entity
->name
, pad
->index
);
890 /* Validation passed, store the pipe pointer in the pad. */
900 * Link validation on graph failed. We revert what we did and
904 list_for_each_entry(err_ppad
, &pipe
->pads
, list
) {
905 if (err_ppad
== ppad
)
908 err_ppad
->pad
->pipe
= NULL
;
911 media_pipeline_cleanup(pipe
);
915 EXPORT_SYMBOL_GPL(__media_pipeline_start
);
917 __must_check
int media_pipeline_start(struct media_pad
*origin
,
918 struct media_pipeline
*pipe
)
920 struct media_device
*mdev
= origin
->graph_obj
.mdev
;
923 mutex_lock(&mdev
->graph_mutex
);
924 ret
= __media_pipeline_start(origin
, pipe
);
925 mutex_unlock(&mdev
->graph_mutex
);
928 EXPORT_SYMBOL_GPL(media_pipeline_start
);
930 void __media_pipeline_stop(struct media_pad
*pad
)
932 struct media_pipeline
*pipe
= pad
->pipe
;
933 struct media_pipeline_pad
*ppad
;
936 * If the following check fails, the driver has performed an
937 * unbalanced call to media_pipeline_stop()
942 if (--pipe
->start_count
)
945 list_for_each_entry(ppad
, &pipe
->pads
, list
)
946 ppad
->pad
->pipe
= NULL
;
948 media_pipeline_cleanup(pipe
);
953 EXPORT_SYMBOL_GPL(__media_pipeline_stop
);
955 void media_pipeline_stop(struct media_pad
*pad
)
957 struct media_device
*mdev
= pad
->graph_obj
.mdev
;
959 mutex_lock(&mdev
->graph_mutex
);
960 __media_pipeline_stop(pad
);
961 mutex_unlock(&mdev
->graph_mutex
);
963 EXPORT_SYMBOL_GPL(media_pipeline_stop
);
965 __must_check
int media_pipeline_alloc_start(struct media_pad
*pad
)
967 struct media_device
*mdev
= pad
->graph_obj
.mdev
;
968 struct media_pipeline
*new_pipe
= NULL
;
969 struct media_pipeline
*pipe
;
972 mutex_lock(&mdev
->graph_mutex
);
975 * Is the pad already part of a pipeline? If not, we need to allocate
978 pipe
= media_pad_pipeline(pad
);
980 new_pipe
= kzalloc(sizeof(*new_pipe
), GFP_KERNEL
);
987 pipe
->allocated
= true;
990 ret
= __media_pipeline_start(pad
, pipe
);
995 mutex_unlock(&mdev
->graph_mutex
);
999 EXPORT_SYMBOL_GPL(media_pipeline_alloc_start
);
1002 __media_pipeline_pad_iter_next(struct media_pipeline
*pipe
,
1003 struct media_pipeline_pad_iter
*iter
,
1004 struct media_pad
*pad
)
1007 iter
->cursor
= pipe
->pads
.next
;
1009 if (iter
->cursor
== &pipe
->pads
)
1012 pad
= list_entry(iter
->cursor
, struct media_pipeline_pad
, list
)->pad
;
1013 iter
->cursor
= iter
->cursor
->next
;
1017 EXPORT_SYMBOL_GPL(__media_pipeline_pad_iter_next
);
1019 int media_pipeline_entity_iter_init(struct media_pipeline
*pipe
,
1020 struct media_pipeline_entity_iter
*iter
)
1022 return media_entity_enum_init(&iter
->ent_enum
, pipe
->mdev
);
1024 EXPORT_SYMBOL_GPL(media_pipeline_entity_iter_init
);
1026 void media_pipeline_entity_iter_cleanup(struct media_pipeline_entity_iter
*iter
)
1028 media_entity_enum_cleanup(&iter
->ent_enum
);
1030 EXPORT_SYMBOL_GPL(media_pipeline_entity_iter_cleanup
);
1032 struct media_entity
*
1033 __media_pipeline_entity_iter_next(struct media_pipeline
*pipe
,
1034 struct media_pipeline_entity_iter
*iter
,
1035 struct media_entity
*entity
)
1038 iter
->cursor
= pipe
->pads
.next
;
1040 while (iter
->cursor
!= &pipe
->pads
) {
1041 struct media_pipeline_pad
*ppad
;
1042 struct media_entity
*entity
;
1044 ppad
= list_entry(iter
->cursor
, struct media_pipeline_pad
, list
);
1045 entity
= ppad
->pad
->entity
;
1046 iter
->cursor
= iter
->cursor
->next
;
1048 if (!media_entity_enum_test_and_set(&iter
->ent_enum
, entity
))
1054 EXPORT_SYMBOL_GPL(__media_pipeline_entity_iter_next
);
1056 /* -----------------------------------------------------------------------------
1060 static struct media_link
*media_add_link(struct list_head
*head
)
1062 struct media_link
*link
;
1064 link
= kzalloc(sizeof(*link
), GFP_KERNEL
);
1068 list_add_tail(&link
->list
, head
);
1073 static void __media_entity_remove_link(struct media_entity
*entity
,
1074 struct media_link
*link
)
1076 struct media_link
*rlink
, *tmp
;
1077 struct media_entity
*remote
;
1079 /* Remove the reverse links for a data link. */
1080 if ((link
->flags
& MEDIA_LNK_FL_LINK_TYPE
) == MEDIA_LNK_FL_DATA_LINK
) {
1081 link
->source
->num_links
--;
1082 link
->sink
->num_links
--;
1084 if (link
->source
->entity
== entity
)
1085 remote
= link
->sink
->entity
;
1087 remote
= link
->source
->entity
;
1089 list_for_each_entry_safe(rlink
, tmp
, &remote
->links
, list
) {
1090 if (rlink
!= link
->reverse
)
1093 if (link
->source
->entity
== entity
)
1094 remote
->num_backlinks
--;
1096 /* Remove the remote link */
1097 list_del(&rlink
->list
);
1098 media_gobj_destroy(&rlink
->graph_obj
);
1101 if (--remote
->num_links
== 0)
1106 list_del(&link
->list
);
1107 media_gobj_destroy(&link
->graph_obj
);
1111 int media_get_pad_index(struct media_entity
*entity
, u32 pad_type
,
1112 enum media_pad_signal_type sig_type
)
1119 for (i
= 0; i
< entity
->num_pads
; i
++) {
1120 if ((entity
->pads
[i
].flags
&
1121 (MEDIA_PAD_FL_SINK
| MEDIA_PAD_FL_SOURCE
)) != pad_type
)
1124 if (entity
->pads
[i
].sig_type
== sig_type
)
1129 EXPORT_SYMBOL_GPL(media_get_pad_index
);
1132 media_create_pad_link(struct media_entity
*source
, u16 source_pad
,
1133 struct media_entity
*sink
, u16 sink_pad
, u32 flags
)
1135 struct media_link
*link
;
1136 struct media_link
*backlink
;
1138 if (flags
& MEDIA_LNK_FL_LINK_TYPE
)
1141 flags
|= MEDIA_LNK_FL_DATA_LINK
;
1143 if (WARN_ON(!source
|| !sink
) ||
1144 WARN_ON(source_pad
>= source
->num_pads
) ||
1145 WARN_ON(sink_pad
>= sink
->num_pads
))
1147 if (WARN_ON(!(source
->pads
[source_pad
].flags
& MEDIA_PAD_FL_SOURCE
)))
1149 if (WARN_ON(!(sink
->pads
[sink_pad
].flags
& MEDIA_PAD_FL_SINK
)))
1152 link
= media_add_link(&source
->links
);
1156 link
->source
= &source
->pads
[source_pad
];
1157 link
->sink
= &sink
->pads
[sink_pad
];
1158 link
->flags
= flags
;
1160 /* Initialize graph object embedded at the new link */
1161 media_gobj_create(source
->graph_obj
.mdev
, MEDIA_GRAPH_LINK
,
1164 /* Create the backlink. Backlinks are used to help graph traversal and
1165 * are not reported to userspace.
1167 backlink
= media_add_link(&sink
->links
);
1168 if (backlink
== NULL
) {
1169 __media_entity_remove_link(source
, link
);
1173 backlink
->source
= &source
->pads
[source_pad
];
1174 backlink
->sink
= &sink
->pads
[sink_pad
];
1175 backlink
->flags
= flags
;
1176 backlink
->is_backlink
= true;
1178 /* Initialize graph object embedded at the new link */
1179 media_gobj_create(sink
->graph_obj
.mdev
, MEDIA_GRAPH_LINK
,
1180 &backlink
->graph_obj
);
1182 link
->reverse
= backlink
;
1183 backlink
->reverse
= link
;
1185 sink
->num_backlinks
++;
1187 source
->num_links
++;
1189 link
->source
->num_links
++;
1190 link
->sink
->num_links
++;
1194 EXPORT_SYMBOL_GPL(media_create_pad_link
);
1196 int media_create_pad_links(const struct media_device
*mdev
,
1197 const u32 source_function
,
1198 struct media_entity
*source
,
1199 const u16 source_pad
,
1200 const u32 sink_function
,
1201 struct media_entity
*sink
,
1204 const bool allow_both_undefined
)
1206 struct media_entity
*entity
;
1210 /* Trivial case: 1:1 relation */
1212 return media_create_pad_link(source
, source_pad
,
1213 sink
, sink_pad
, flags
);
1215 /* Worse case scenario: n:n relation */
1216 if (!source
&& !sink
) {
1217 if (!allow_both_undefined
)
1219 media_device_for_each_entity(source
, mdev
) {
1220 if (source
->function
!= source_function
)
1222 media_device_for_each_entity(sink
, mdev
) {
1223 if (sink
->function
!= sink_function
)
1225 ret
= media_create_pad_link(source
, source_pad
,
1230 flags
&= ~(MEDIA_LNK_FL_ENABLED
|
1231 MEDIA_LNK_FL_IMMUTABLE
);
1237 /* Handle 1:n and n:1 cases */
1239 function
= sink_function
;
1241 function
= source_function
;
1243 media_device_for_each_entity(entity
, mdev
) {
1244 if (entity
->function
!= function
)
1248 ret
= media_create_pad_link(source
, source_pad
,
1249 entity
, sink_pad
, flags
);
1251 ret
= media_create_pad_link(entity
, source_pad
,
1252 sink
, sink_pad
, flags
);
1255 flags
&= ~(MEDIA_LNK_FL_ENABLED
| MEDIA_LNK_FL_IMMUTABLE
);
1259 EXPORT_SYMBOL_GPL(media_create_pad_links
);
1261 void __media_entity_remove_links(struct media_entity
*entity
)
1263 struct media_link
*link
, *tmp
;
1265 list_for_each_entry_safe(link
, tmp
, &entity
->links
, list
)
1266 __media_entity_remove_link(entity
, link
);
1268 entity
->num_links
= 0;
1269 entity
->num_backlinks
= 0;
1271 EXPORT_SYMBOL_GPL(__media_entity_remove_links
);
1273 void media_entity_remove_links(struct media_entity
*entity
)
1275 struct media_device
*mdev
= entity
->graph_obj
.mdev
;
1277 /* Do nothing if the entity is not registered. */
1281 mutex_lock(&mdev
->graph_mutex
);
1282 __media_entity_remove_links(entity
);
1283 mutex_unlock(&mdev
->graph_mutex
);
1285 EXPORT_SYMBOL_GPL(media_entity_remove_links
);
1287 static int __media_entity_setup_link_notify(struct media_link
*link
, u32 flags
)
1291 /* Notify both entities. */
1292 ret
= media_entity_call(link
->source
->entity
, link_setup
,
1293 link
->source
, link
->sink
, flags
);
1294 if (ret
< 0 && ret
!= -ENOIOCTLCMD
)
1297 ret
= media_entity_call(link
->sink
->entity
, link_setup
,
1298 link
->sink
, link
->source
, flags
);
1299 if (ret
< 0 && ret
!= -ENOIOCTLCMD
) {
1300 media_entity_call(link
->source
->entity
, link_setup
,
1301 link
->source
, link
->sink
, link
->flags
);
1305 link
->flags
= flags
;
1306 link
->reverse
->flags
= link
->flags
;
1311 int __media_entity_setup_link(struct media_link
*link
, u32 flags
)
1313 const u32 mask
= MEDIA_LNK_FL_ENABLED
;
1314 struct media_device
*mdev
;
1315 struct media_pad
*source
, *sink
;
1321 /* The non-modifiable link flags must not be modified. */
1322 if ((link
->flags
& ~mask
) != (flags
& ~mask
))
1325 if (link
->flags
& MEDIA_LNK_FL_IMMUTABLE
)
1326 return link
->flags
== flags
? 0 : -EINVAL
;
1328 if (link
->flags
== flags
)
1331 source
= link
->source
;
1334 if (!(link
->flags
& MEDIA_LNK_FL_DYNAMIC
) &&
1335 (media_pad_is_streaming(source
) || media_pad_is_streaming(sink
)))
1338 mdev
= source
->graph_obj
.mdev
;
1340 if (mdev
->ops
&& mdev
->ops
->link_notify
) {
1341 ret
= mdev
->ops
->link_notify(link
, flags
,
1342 MEDIA_DEV_NOTIFY_PRE_LINK_CH
);
1347 ret
= __media_entity_setup_link_notify(link
, flags
);
1349 if (mdev
->ops
&& mdev
->ops
->link_notify
)
1350 mdev
->ops
->link_notify(link
, flags
,
1351 MEDIA_DEV_NOTIFY_POST_LINK_CH
);
1355 EXPORT_SYMBOL_GPL(__media_entity_setup_link
);
1357 int media_entity_setup_link(struct media_link
*link
, u32 flags
)
1361 mutex_lock(&link
->graph_obj
.mdev
->graph_mutex
);
1362 ret
= __media_entity_setup_link(link
, flags
);
1363 mutex_unlock(&link
->graph_obj
.mdev
->graph_mutex
);
1367 EXPORT_SYMBOL_GPL(media_entity_setup_link
);
1370 media_entity_find_link(struct media_pad
*source
, struct media_pad
*sink
)
1372 struct media_link
*link
;
1374 for_each_media_entity_data_link(source
->entity
, link
) {
1375 if (link
->source
->entity
== source
->entity
&&
1376 link
->source
->index
== source
->index
&&
1377 link
->sink
->entity
== sink
->entity
&&
1378 link
->sink
->index
== sink
->index
)
1384 EXPORT_SYMBOL_GPL(media_entity_find_link
);
1386 struct media_pad
*media_pad_remote_pad_first(const struct media_pad
*pad
)
1388 struct media_link
*link
;
1390 for_each_media_entity_data_link(pad
->entity
, link
) {
1391 if (!(link
->flags
& MEDIA_LNK_FL_ENABLED
))
1394 if (link
->source
== pad
)
1397 if (link
->sink
== pad
)
1398 return link
->source
;
1404 EXPORT_SYMBOL_GPL(media_pad_remote_pad_first
);
1407 media_entity_remote_pad_unique(const struct media_entity
*entity
,
1410 struct media_pad
*pad
= NULL
;
1411 struct media_link
*link
;
1413 list_for_each_entry(link
, &entity
->links
, list
) {
1414 struct media_pad
*local_pad
;
1415 struct media_pad
*remote_pad
;
1417 if (((link
->flags
& MEDIA_LNK_FL_LINK_TYPE
) !=
1418 MEDIA_LNK_FL_DATA_LINK
) ||
1419 !(link
->flags
& MEDIA_LNK_FL_ENABLED
))
1422 if (type
== MEDIA_PAD_FL_SOURCE
) {
1423 local_pad
= link
->sink
;
1424 remote_pad
= link
->source
;
1426 local_pad
= link
->source
;
1427 remote_pad
= link
->sink
;
1430 if (local_pad
->entity
== entity
) {
1432 return ERR_PTR(-ENOTUNIQ
);
1439 return ERR_PTR(-ENOLINK
);
1443 EXPORT_SYMBOL_GPL(media_entity_remote_pad_unique
);
1445 struct media_pad
*media_pad_remote_pad_unique(const struct media_pad
*pad
)
1447 struct media_pad
*found_pad
= NULL
;
1448 struct media_link
*link
;
1450 list_for_each_entry(link
, &pad
->entity
->links
, list
) {
1451 struct media_pad
*remote_pad
;
1453 if (!(link
->flags
& MEDIA_LNK_FL_ENABLED
))
1456 if (link
->sink
== pad
)
1457 remote_pad
= link
->source
;
1458 else if (link
->source
== pad
)
1459 remote_pad
= link
->sink
;
1464 return ERR_PTR(-ENOTUNIQ
);
1466 found_pad
= remote_pad
;
1470 return ERR_PTR(-ENOLINK
);
1474 EXPORT_SYMBOL_GPL(media_pad_remote_pad_unique
);
1476 int media_entity_get_fwnode_pad(struct media_entity
*entity
,
1477 const struct fwnode_handle
*fwnode
,
1478 unsigned long direction_flags
)
1480 struct fwnode_endpoint endpoint
;
1484 if (!entity
->ops
|| !entity
->ops
->get_fwnode_pad
) {
1485 for (i
= 0; i
< entity
->num_pads
; i
++) {
1486 if (entity
->pads
[i
].flags
& direction_flags
)
1493 ret
= fwnode_graph_parse_endpoint(fwnode
, &endpoint
);
1497 ret
= entity
->ops
->get_fwnode_pad(entity
, &endpoint
);
1501 if (ret
>= entity
->num_pads
)
1504 if (!(entity
->pads
[ret
].flags
& direction_flags
))
1509 EXPORT_SYMBOL_GPL(media_entity_get_fwnode_pad
);
1511 struct media_pipeline
*media_entity_pipeline(struct media_entity
*entity
)
1513 struct media_pad
*pad
;
1515 media_entity_for_each_pad(entity
, pad
) {
1522 EXPORT_SYMBOL_GPL(media_entity_pipeline
);
1524 struct media_pipeline
*media_pad_pipeline(struct media_pad
*pad
)
1528 EXPORT_SYMBOL_GPL(media_pad_pipeline
);
1530 static void media_interface_init(struct media_device
*mdev
,
1531 struct media_interface
*intf
,
1533 u32 intf_type
, u32 flags
)
1535 intf
->type
= intf_type
;
1536 intf
->flags
= flags
;
1537 INIT_LIST_HEAD(&intf
->links
);
1539 media_gobj_create(mdev
, gobj_type
, &intf
->graph_obj
);
1542 /* Functions related to the media interface via device nodes */
1544 struct media_intf_devnode
*media_devnode_create(struct media_device
*mdev
,
1545 u32 type
, u32 flags
,
1546 u32 major
, u32 minor
)
1548 struct media_intf_devnode
*devnode
;
1550 devnode
= kzalloc(sizeof(*devnode
), GFP_KERNEL
);
1554 devnode
->major
= major
;
1555 devnode
->minor
= minor
;
1557 media_interface_init(mdev
, &devnode
->intf
, MEDIA_GRAPH_INTF_DEVNODE
,
1562 EXPORT_SYMBOL_GPL(media_devnode_create
);
1564 void media_devnode_remove(struct media_intf_devnode
*devnode
)
1566 media_remove_intf_links(&devnode
->intf
);
1567 media_gobj_destroy(&devnode
->intf
.graph_obj
);
1570 EXPORT_SYMBOL_GPL(media_devnode_remove
);
1572 struct media_link
*media_create_intf_link(struct media_entity
*entity
,
1573 struct media_interface
*intf
,
1576 struct media_link
*link
;
1578 link
= media_add_link(&intf
->links
);
1583 link
->entity
= entity
;
1584 link
->flags
= flags
| MEDIA_LNK_FL_INTERFACE_LINK
;
1586 /* Initialize graph object embedded at the new link */
1587 media_gobj_create(intf
->graph_obj
.mdev
, MEDIA_GRAPH_LINK
,
1592 EXPORT_SYMBOL_GPL(media_create_intf_link
);
1594 void __media_remove_intf_link(struct media_link
*link
)
1596 list_del(&link
->list
);
1597 media_gobj_destroy(&link
->graph_obj
);
1600 EXPORT_SYMBOL_GPL(__media_remove_intf_link
);
1602 void media_remove_intf_link(struct media_link
*link
)
1604 struct media_device
*mdev
= link
->graph_obj
.mdev
;
1606 /* Do nothing if the intf is not registered. */
1610 mutex_lock(&mdev
->graph_mutex
);
1611 __media_remove_intf_link(link
);
1612 mutex_unlock(&mdev
->graph_mutex
);
1614 EXPORT_SYMBOL_GPL(media_remove_intf_link
);
1616 void __media_remove_intf_links(struct media_interface
*intf
)
1618 struct media_link
*link
, *tmp
;
1620 list_for_each_entry_safe(link
, tmp
, &intf
->links
, list
)
1621 __media_remove_intf_link(link
);
1624 EXPORT_SYMBOL_GPL(__media_remove_intf_links
);
1626 void media_remove_intf_links(struct media_interface
*intf
)
1628 struct media_device
*mdev
= intf
->graph_obj
.mdev
;
1630 /* Do nothing if the intf is not registered. */
1634 mutex_lock(&mdev
->graph_mutex
);
1635 __media_remove_intf_links(intf
);
1636 mutex_unlock(&mdev
->graph_mutex
);
1638 EXPORT_SYMBOL_GPL(media_remove_intf_links
);
1640 struct media_link
*media_create_ancillary_link(struct media_entity
*primary
,
1641 struct media_entity
*ancillary
)
1643 struct media_link
*link
;
1645 link
= media_add_link(&primary
->links
);
1647 return ERR_PTR(-ENOMEM
);
1649 link
->gobj0
= &primary
->graph_obj
;
1650 link
->gobj1
= &ancillary
->graph_obj
;
1651 link
->flags
= MEDIA_LNK_FL_IMMUTABLE
| MEDIA_LNK_FL_ENABLED
|
1652 MEDIA_LNK_FL_ANCILLARY_LINK
;
1654 /* Initialize graph object embedded in the new link */
1655 media_gobj_create(primary
->graph_obj
.mdev
, MEDIA_GRAPH_LINK
,
1660 EXPORT_SYMBOL_GPL(media_create_ancillary_link
);
1662 struct media_link
*__media_entity_next_link(struct media_entity
*entity
,
1663 struct media_link
*link
,
1664 unsigned long link_type
)
1666 link
= link
? list_next_entry(link
, list
)
1667 : list_first_entry(&entity
->links
, typeof(*link
), list
);
1669 list_for_each_entry_from(link
, &entity
->links
, list
)
1670 if ((link
->flags
& MEDIA_LNK_FL_LINK_TYPE
) == link_type
)
1675 EXPORT_SYMBOL_GPL(__media_entity_next_link
);