Merge tag 'drm-intel-gt-next-2022-08-24' of git://anongit.freedesktop.org/drm/drm...
[linux-2.6-microblaze.git] / drivers / media / mc / mc-entity.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Media entity
4  *
5  * Copyright (C) 2010 Nokia Corporation
6  *
7  * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
8  *           Sakari Ailus <sakari.ailus@iki.fi>
9  */
10
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>
17
18 static inline const char *intf_type(struct media_interface *intf)
19 {
20         switch (intf->type) {
21         case MEDIA_INTF_T_DVB_FE:
22                 return "dvb-frontend";
23         case MEDIA_INTF_T_DVB_DEMUX:
24                 return "dvb-demux";
25         case MEDIA_INTF_T_DVB_DVR:
26                 return "dvb-dvr";
27         case MEDIA_INTF_T_DVB_CA:
28                 return  "dvb-ca";
29         case MEDIA_INTF_T_DVB_NET:
30                 return "dvb-net";
31         case MEDIA_INTF_T_V4L_VIDEO:
32                 return "v4l-video";
33         case MEDIA_INTF_T_V4L_VBI:
34                 return "v4l-vbi";
35         case MEDIA_INTF_T_V4L_RADIO:
36                 return "v4l-radio";
37         case MEDIA_INTF_T_V4L_SUBDEV:
38                 return "v4l-subdev";
39         case MEDIA_INTF_T_V4L_SWRADIO:
40                 return "v4l-swradio";
41         case MEDIA_INTF_T_V4L_TOUCH:
42                 return "v4l-touch";
43         default:
44                 return "unknown-intf";
45         }
46 };
47
48 static inline const char *link_type_name(struct media_link *link)
49 {
50         switch (link->flags & MEDIA_LNK_FL_LINK_TYPE) {
51         case MEDIA_LNK_FL_DATA_LINK:
52                 return "data";
53         case MEDIA_LNK_FL_INTERFACE_LINK:
54                 return "interface";
55         case MEDIA_LNK_FL_ANCILLARY_LINK:
56                 return "ancillary";
57         default:
58                 return "unknown";
59         }
60 }
61
62 __must_check int __media_entity_enum_init(struct media_entity_enum *ent_enum,
63                                           int idx_max)
64 {
65         idx_max = ALIGN(idx_max, BITS_PER_LONG);
66         ent_enum->bmap = bitmap_zalloc(idx_max, GFP_KERNEL);
67         if (!ent_enum->bmap)
68                 return -ENOMEM;
69
70         ent_enum->idx_max = idx_max;
71
72         return 0;
73 }
74 EXPORT_SYMBOL_GPL(__media_entity_enum_init);
75
76 void media_entity_enum_cleanup(struct media_entity_enum *ent_enum)
77 {
78         bitmap_free(ent_enum->bmap);
79 }
80 EXPORT_SYMBOL_GPL(media_entity_enum_cleanup);
81
82 /**
83  *  dev_dbg_obj - Prints in debug mode a change on some object
84  *
85  * @event_name: Name of the event to report. Could be __func__
86  * @gobj:       Pointer to the object
87  *
88  * Enabled only if DEBUG or CONFIG_DYNAMIC_DEBUG. Otherwise, it
89  * won't produce any code.
90  */
91 static void dev_dbg_obj(const char *event_name,  struct media_gobj *gobj)
92 {
93 #if defined(DEBUG) || defined (CONFIG_DYNAMIC_DEBUG)
94         switch (media_type(gobj)) {
95         case MEDIA_GRAPH_ENTITY:
96                 dev_dbg(gobj->mdev->dev,
97                         "%s id %u: entity '%s'\n",
98                         event_name, media_id(gobj),
99                         gobj_to_entity(gobj)->name);
100                 break;
101         case MEDIA_GRAPH_LINK:
102         {
103                 struct media_link *link = gobj_to_link(gobj);
104
105                 dev_dbg(gobj->mdev->dev,
106                         "%s id %u: %s link id %u ==> id %u\n",
107                         event_name, media_id(gobj), link_type_name(link),
108                         media_id(link->gobj0),
109                         media_id(link->gobj1));
110                 break;
111         }
112         case MEDIA_GRAPH_PAD:
113         {
114                 struct media_pad *pad = gobj_to_pad(gobj);
115
116                 dev_dbg(gobj->mdev->dev,
117                         "%s id %u: %s%spad '%s':%d\n",
118                         event_name, media_id(gobj),
119                         pad->flags & MEDIA_PAD_FL_SINK   ? "sink " : "",
120                         pad->flags & MEDIA_PAD_FL_SOURCE ? "source " : "",
121                         pad->entity->name, pad->index);
122                 break;
123         }
124         case MEDIA_GRAPH_INTF_DEVNODE:
125         {
126                 struct media_interface *intf = gobj_to_intf(gobj);
127                 struct media_intf_devnode *devnode = intf_to_devnode(intf);
128
129                 dev_dbg(gobj->mdev->dev,
130                         "%s id %u: intf_devnode %s - major: %d, minor: %d\n",
131                         event_name, media_id(gobj),
132                         intf_type(intf),
133                         devnode->major, devnode->minor);
134                 break;
135         }
136         }
137 #endif
138 }
139
140 void media_gobj_create(struct media_device *mdev,
141                            enum media_gobj_type type,
142                            struct media_gobj *gobj)
143 {
144         BUG_ON(!mdev);
145
146         gobj->mdev = mdev;
147
148         /* Create a per-type unique object ID */
149         gobj->id = media_gobj_gen_id(type, ++mdev->id);
150
151         switch (type) {
152         case MEDIA_GRAPH_ENTITY:
153                 list_add_tail(&gobj->list, &mdev->entities);
154                 break;
155         case MEDIA_GRAPH_PAD:
156                 list_add_tail(&gobj->list, &mdev->pads);
157                 break;
158         case MEDIA_GRAPH_LINK:
159                 list_add_tail(&gobj->list, &mdev->links);
160                 break;
161         case MEDIA_GRAPH_INTF_DEVNODE:
162                 list_add_tail(&gobj->list, &mdev->interfaces);
163                 break;
164         }
165
166         mdev->topology_version++;
167
168         dev_dbg_obj(__func__, gobj);
169 }
170
171 void media_gobj_destroy(struct media_gobj *gobj)
172 {
173         /* Do nothing if the object is not linked. */
174         if (gobj->mdev == NULL)
175                 return;
176
177         dev_dbg_obj(__func__, gobj);
178
179         gobj->mdev->topology_version++;
180
181         /* Remove the object from mdev list */
182         list_del(&gobj->list);
183
184         gobj->mdev = NULL;
185 }
186
187 /*
188  * TODO: Get rid of this.
189  */
190 #define MEDIA_ENTITY_MAX_PADS           512
191
192 int media_entity_pads_init(struct media_entity *entity, u16 num_pads,
193                            struct media_pad *pads)
194 {
195         struct media_device *mdev = entity->graph_obj.mdev;
196         unsigned int i;
197
198         if (num_pads >= MEDIA_ENTITY_MAX_PADS)
199                 return -E2BIG;
200
201         entity->num_pads = num_pads;
202         entity->pads = pads;
203
204         if (mdev)
205                 mutex_lock(&mdev->graph_mutex);
206
207         for (i = 0; i < num_pads; i++) {
208                 pads[i].entity = entity;
209                 pads[i].index = i;
210                 if (mdev)
211                         media_gobj_create(mdev, MEDIA_GRAPH_PAD,
212                                         &entity->pads[i].graph_obj);
213         }
214
215         if (mdev)
216                 mutex_unlock(&mdev->graph_mutex);
217
218         return 0;
219 }
220 EXPORT_SYMBOL_GPL(media_entity_pads_init);
221
222 /* -----------------------------------------------------------------------------
223  * Graph traversal
224  */
225
226 static struct media_entity *
227 media_entity_other(struct media_entity *entity, struct media_link *link)
228 {
229         if (link->source->entity == entity)
230                 return link->sink->entity;
231         else
232                 return link->source->entity;
233 }
234
235 /* push an entity to traversal stack */
236 static void stack_push(struct media_graph *graph,
237                        struct media_entity *entity)
238 {
239         if (graph->top == MEDIA_ENTITY_ENUM_MAX_DEPTH - 1) {
240                 WARN_ON(1);
241                 return;
242         }
243         graph->top++;
244         graph->stack[graph->top].link = entity->links.next;
245         graph->stack[graph->top].entity = entity;
246 }
247
248 static struct media_entity *stack_pop(struct media_graph *graph)
249 {
250         struct media_entity *entity;
251
252         entity = graph->stack[graph->top].entity;
253         graph->top--;
254
255         return entity;
256 }
257
258 #define link_top(en)    ((en)->stack[(en)->top].link)
259 #define stack_top(en)   ((en)->stack[(en)->top].entity)
260
261 /**
262  * media_graph_walk_init - Allocate resources for graph walk
263  * @graph: Media graph structure that will be used to walk the graph
264  * @mdev: Media device
265  *
266  * Reserve resources for graph walk in media device's current
267  * state. The memory must be released using
268  * media_graph_walk_free().
269  *
270  * Returns error on failure, zero on success.
271  */
272 __must_check int media_graph_walk_init(
273         struct media_graph *graph, struct media_device *mdev)
274 {
275         return media_entity_enum_init(&graph->ent_enum, mdev);
276 }
277 EXPORT_SYMBOL_GPL(media_graph_walk_init);
278
279 /**
280  * media_graph_walk_cleanup - Release resources related to graph walking
281  * @graph: Media graph structure that was used to walk the graph
282  */
283 void media_graph_walk_cleanup(struct media_graph *graph)
284 {
285         media_entity_enum_cleanup(&graph->ent_enum);
286 }
287 EXPORT_SYMBOL_GPL(media_graph_walk_cleanup);
288
289 void media_graph_walk_start(struct media_graph *graph,
290                             struct media_entity *entity)
291 {
292         media_entity_enum_zero(&graph->ent_enum);
293         media_entity_enum_set(&graph->ent_enum, entity);
294
295         graph->top = 0;
296         graph->stack[graph->top].entity = NULL;
297         stack_push(graph, entity);
298         dev_dbg(entity->graph_obj.mdev->dev,
299                 "begin graph walk at '%s'\n", entity->name);
300 }
301 EXPORT_SYMBOL_GPL(media_graph_walk_start);
302
303 static void media_graph_walk_iter(struct media_graph *graph)
304 {
305         struct media_entity *entity = stack_top(graph);
306         struct media_link *link;
307         struct media_entity *next;
308
309         link = list_entry(link_top(graph), typeof(*link), list);
310
311         /* If the link is not a data link, don't follow it */
312         if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) != MEDIA_LNK_FL_DATA_LINK) {
313                 link_top(graph) = link_top(graph)->next;
314                 return;
315         }
316
317         /* The link is not enabled so we do not follow. */
318         if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
319                 link_top(graph) = link_top(graph)->next;
320                 dev_dbg(entity->graph_obj.mdev->dev,
321                         "walk: skipping disabled link '%s':%u -> '%s':%u\n",
322                         link->source->entity->name, link->source->index,
323                         link->sink->entity->name, link->sink->index);
324                 return;
325         }
326
327         /* Get the entity at the other end of the link. */
328         next = media_entity_other(entity, link);
329
330         /* Has the entity already been visited? */
331         if (media_entity_enum_test_and_set(&graph->ent_enum, next)) {
332                 link_top(graph) = link_top(graph)->next;
333                 dev_dbg(entity->graph_obj.mdev->dev,
334                         "walk: skipping entity '%s' (already seen)\n",
335                         next->name);
336                 return;
337         }
338
339         /* Push the new entity to stack and start over. */
340         link_top(graph) = link_top(graph)->next;
341         stack_push(graph, next);
342         dev_dbg(entity->graph_obj.mdev->dev, "walk: pushing '%s' on stack\n",
343                 next->name);
344         lockdep_assert_held(&entity->graph_obj.mdev->graph_mutex);
345 }
346
347 struct media_entity *media_graph_walk_next(struct media_graph *graph)
348 {
349         struct media_entity *entity;
350
351         if (stack_top(graph) == NULL)
352                 return NULL;
353
354         /*
355          * Depth first search. Push entity to stack and continue from
356          * top of the stack until no more entities on the level can be
357          * found.
358          */
359         while (link_top(graph) != &stack_top(graph)->links)
360                 media_graph_walk_iter(graph);
361
362         entity = stack_pop(graph);
363         dev_dbg(entity->graph_obj.mdev->dev,
364                 "walk: returning entity '%s'\n", entity->name);
365
366         return entity;
367 }
368 EXPORT_SYMBOL_GPL(media_graph_walk_next);
369
370 int media_entity_get_fwnode_pad(struct media_entity *entity,
371                                 struct fwnode_handle *fwnode,
372                                 unsigned long direction_flags)
373 {
374         struct fwnode_endpoint endpoint;
375         unsigned int i;
376         int ret;
377
378         if (!entity->ops || !entity->ops->get_fwnode_pad) {
379                 for (i = 0; i < entity->num_pads; i++) {
380                         if (entity->pads[i].flags & direction_flags)
381                                 return i;
382                 }
383
384                 return -ENXIO;
385         }
386
387         ret = fwnode_graph_parse_endpoint(fwnode, &endpoint);
388         if (ret)
389                 return ret;
390
391         ret = entity->ops->get_fwnode_pad(entity, &endpoint);
392         if (ret < 0)
393                 return ret;
394
395         if (ret >= entity->num_pads)
396                 return -ENXIO;
397
398         if (!(entity->pads[ret].flags & direction_flags))
399                 return -ENXIO;
400
401         return ret;
402 }
403 EXPORT_SYMBOL_GPL(media_entity_get_fwnode_pad);
404
405 /* -----------------------------------------------------------------------------
406  * Pipeline management
407  */
408
409 __must_check int __media_pipeline_start(struct media_entity *entity,
410                                         struct media_pipeline *pipe)
411 {
412         struct media_device *mdev = entity->graph_obj.mdev;
413         struct media_graph *graph = &pipe->graph;
414         struct media_entity *entity_err = entity;
415         struct media_link *link;
416         int ret;
417
418         if (pipe->streaming_count) {
419                 pipe->streaming_count++;
420                 return 0;
421         }
422
423         ret = media_graph_walk_init(&pipe->graph, mdev);
424         if (ret)
425                 return ret;
426
427         media_graph_walk_start(&pipe->graph, entity);
428
429         while ((entity = media_graph_walk_next(graph))) {
430                 DECLARE_BITMAP(active, MEDIA_ENTITY_MAX_PADS);
431                 DECLARE_BITMAP(has_no_links, MEDIA_ENTITY_MAX_PADS);
432
433                 if (entity->pipe && entity->pipe != pipe) {
434                         pr_err("Pipe active for %s. Can't start for %s\n",
435                                 entity->name,
436                                 entity_err->name);
437                         ret = -EBUSY;
438                         goto error;
439                 }
440
441                 /* Already streaming --- no need to check. */
442                 if (entity->pipe)
443                         continue;
444
445                 entity->pipe = pipe;
446
447                 if (!entity->ops || !entity->ops->link_validate)
448                         continue;
449
450                 bitmap_zero(active, entity->num_pads);
451                 bitmap_fill(has_no_links, entity->num_pads);
452
453                 for_each_media_entity_data_link(entity, link) {
454                         struct media_pad *pad = link->sink->entity == entity
455                                                 ? link->sink : link->source;
456
457                         /* Mark that a pad is connected by a link. */
458                         bitmap_clear(has_no_links, pad->index, 1);
459
460                         /*
461                          * Pads that either do not need to connect or
462                          * are connected through an enabled link are
463                          * fine.
464                          */
465                         if (!(pad->flags & MEDIA_PAD_FL_MUST_CONNECT) ||
466                             link->flags & MEDIA_LNK_FL_ENABLED)
467                                 bitmap_set(active, pad->index, 1);
468
469                         /*
470                          * Link validation will only take place for
471                          * sink ends of the link that are enabled.
472                          */
473                         if (link->sink != pad ||
474                             !(link->flags & MEDIA_LNK_FL_ENABLED))
475                                 continue;
476
477                         ret = entity->ops->link_validate(link);
478                         if (ret < 0 && ret != -ENOIOCTLCMD) {
479                                 dev_dbg(entity->graph_obj.mdev->dev,
480                                         "link validation failed for '%s':%u -> '%s':%u, error %d\n",
481                                         link->source->entity->name,
482                                         link->source->index,
483                                         entity->name, link->sink->index, ret);
484                                 goto error;
485                         }
486                 }
487
488                 /* Either no links or validated links are fine. */
489                 bitmap_or(active, active, has_no_links, entity->num_pads);
490
491                 if (!bitmap_full(active, entity->num_pads)) {
492                         ret = -ENOLINK;
493                         dev_dbg(entity->graph_obj.mdev->dev,
494                                 "'%s':%u must be connected by an enabled link\n",
495                                 entity->name,
496                                 (unsigned)find_first_zero_bit(
497                                         active, entity->num_pads));
498                         goto error;
499                 }
500         }
501
502         pipe->streaming_count++;
503
504         return 0;
505
506 error:
507         /*
508          * Link validation on graph failed. We revert what we did and
509          * return the error.
510          */
511         media_graph_walk_start(graph, entity_err);
512
513         while ((entity_err = media_graph_walk_next(graph))) {
514                 entity_err->pipe = NULL;
515
516                 /*
517                  * We haven't started entities further than this so we quit
518                  * here.
519                  */
520                 if (entity_err == entity)
521                         break;
522         }
523
524         media_graph_walk_cleanup(graph);
525
526         return ret;
527 }
528 EXPORT_SYMBOL_GPL(__media_pipeline_start);
529
530 __must_check int media_pipeline_start(struct media_entity *entity,
531                                       struct media_pipeline *pipe)
532 {
533         struct media_device *mdev = entity->graph_obj.mdev;
534         int ret;
535
536         mutex_lock(&mdev->graph_mutex);
537         ret = __media_pipeline_start(entity, pipe);
538         mutex_unlock(&mdev->graph_mutex);
539         return ret;
540 }
541 EXPORT_SYMBOL_GPL(media_pipeline_start);
542
543 void __media_pipeline_stop(struct media_entity *entity)
544 {
545         struct media_graph *graph = &entity->pipe->graph;
546         struct media_pipeline *pipe = entity->pipe;
547
548         /*
549          * If the following check fails, the driver has performed an
550          * unbalanced call to media_pipeline_stop()
551          */
552         if (WARN_ON(!pipe))
553                 return;
554
555         if (--pipe->streaming_count)
556                 return;
557
558         media_graph_walk_start(graph, entity);
559
560         while ((entity = media_graph_walk_next(graph)))
561                 entity->pipe = NULL;
562
563         media_graph_walk_cleanup(graph);
564
565 }
566 EXPORT_SYMBOL_GPL(__media_pipeline_stop);
567
568 void media_pipeline_stop(struct media_entity *entity)
569 {
570         struct media_device *mdev = entity->graph_obj.mdev;
571
572         mutex_lock(&mdev->graph_mutex);
573         __media_pipeline_stop(entity);
574         mutex_unlock(&mdev->graph_mutex);
575 }
576 EXPORT_SYMBOL_GPL(media_pipeline_stop);
577
578 /* -----------------------------------------------------------------------------
579  * Links management
580  */
581
582 static struct media_link *media_add_link(struct list_head *head)
583 {
584         struct media_link *link;
585
586         link = kzalloc(sizeof(*link), GFP_KERNEL);
587         if (link == NULL)
588                 return NULL;
589
590         list_add_tail(&link->list, head);
591
592         return link;
593 }
594
595 static void __media_entity_remove_link(struct media_entity *entity,
596                                        struct media_link *link)
597 {
598         struct media_link *rlink, *tmp;
599         struct media_entity *remote;
600
601         /* Remove the reverse links for a data link. */
602         if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) == MEDIA_LNK_FL_DATA_LINK) {
603                 if (link->source->entity == entity)
604                         remote = link->sink->entity;
605                 else
606                         remote = link->source->entity;
607
608                 list_for_each_entry_safe(rlink, tmp, &remote->links, list) {
609                         if (rlink != link->reverse)
610                                 continue;
611
612                         if (link->source->entity == entity)
613                                 remote->num_backlinks--;
614
615                         /* Remove the remote link */
616                         list_del(&rlink->list);
617                         media_gobj_destroy(&rlink->graph_obj);
618                         kfree(rlink);
619
620                         if (--remote->num_links == 0)
621                                 break;
622                 }
623         }
624
625         list_del(&link->list);
626         media_gobj_destroy(&link->graph_obj);
627         kfree(link);
628 }
629
630 int media_get_pad_index(struct media_entity *entity, bool is_sink,
631                         enum media_pad_signal_type sig_type)
632 {
633         int i;
634         bool pad_is_sink;
635
636         if (!entity)
637                 return -EINVAL;
638
639         for (i = 0; i < entity->num_pads; i++) {
640                 if (entity->pads[i].flags & MEDIA_PAD_FL_SINK)
641                         pad_is_sink = true;
642                 else if (entity->pads[i].flags & MEDIA_PAD_FL_SOURCE)
643                         pad_is_sink = false;
644                 else
645                         continue;       /* This is an error! */
646
647                 if (pad_is_sink != is_sink)
648                         continue;
649                 if (entity->pads[i].sig_type == sig_type)
650                         return i;
651         }
652         return -EINVAL;
653 }
654 EXPORT_SYMBOL_GPL(media_get_pad_index);
655
656 int
657 media_create_pad_link(struct media_entity *source, u16 source_pad,
658                          struct media_entity *sink, u16 sink_pad, u32 flags)
659 {
660         struct media_link *link;
661         struct media_link *backlink;
662
663         if (WARN_ON(!source || !sink) ||
664             WARN_ON(source_pad >= source->num_pads) ||
665             WARN_ON(sink_pad >= sink->num_pads))
666                 return -EINVAL;
667         if (WARN_ON(!(source->pads[source_pad].flags & MEDIA_PAD_FL_SOURCE)))
668                 return -EINVAL;
669         if (WARN_ON(!(sink->pads[sink_pad].flags & MEDIA_PAD_FL_SINK)))
670                 return -EINVAL;
671
672         link = media_add_link(&source->links);
673         if (link == NULL)
674                 return -ENOMEM;
675
676         link->source = &source->pads[source_pad];
677         link->sink = &sink->pads[sink_pad];
678         link->flags = flags & ~MEDIA_LNK_FL_INTERFACE_LINK;
679
680         /* Initialize graph object embedded at the new link */
681         media_gobj_create(source->graph_obj.mdev, MEDIA_GRAPH_LINK,
682                         &link->graph_obj);
683
684         /* Create the backlink. Backlinks are used to help graph traversal and
685          * are not reported to userspace.
686          */
687         backlink = media_add_link(&sink->links);
688         if (backlink == NULL) {
689                 __media_entity_remove_link(source, link);
690                 return -ENOMEM;
691         }
692
693         backlink->source = &source->pads[source_pad];
694         backlink->sink = &sink->pads[sink_pad];
695         backlink->flags = flags;
696         backlink->is_backlink = true;
697
698         /* Initialize graph object embedded at the new link */
699         media_gobj_create(sink->graph_obj.mdev, MEDIA_GRAPH_LINK,
700                         &backlink->graph_obj);
701
702         link->reverse = backlink;
703         backlink->reverse = link;
704
705         sink->num_backlinks++;
706         sink->num_links++;
707         source->num_links++;
708
709         return 0;
710 }
711 EXPORT_SYMBOL_GPL(media_create_pad_link);
712
713 int media_create_pad_links(const struct media_device *mdev,
714                            const u32 source_function,
715                            struct media_entity *source,
716                            const u16 source_pad,
717                            const u32 sink_function,
718                            struct media_entity *sink,
719                            const u16 sink_pad,
720                            u32 flags,
721                            const bool allow_both_undefined)
722 {
723         struct media_entity *entity;
724         unsigned function;
725         int ret;
726
727         /* Trivial case: 1:1 relation */
728         if (source && sink)
729                 return media_create_pad_link(source, source_pad,
730                                              sink, sink_pad, flags);
731
732         /* Worse case scenario: n:n relation */
733         if (!source && !sink) {
734                 if (!allow_both_undefined)
735                         return 0;
736                 media_device_for_each_entity(source, mdev) {
737                         if (source->function != source_function)
738                                 continue;
739                         media_device_for_each_entity(sink, mdev) {
740                                 if (sink->function != sink_function)
741                                         continue;
742                                 ret = media_create_pad_link(source, source_pad,
743                                                             sink, sink_pad,
744                                                             flags);
745                                 if (ret)
746                                         return ret;
747                                 flags &= ~(MEDIA_LNK_FL_ENABLED |
748                                            MEDIA_LNK_FL_IMMUTABLE);
749                         }
750                 }
751                 return 0;
752         }
753
754         /* Handle 1:n and n:1 cases */
755         if (source)
756                 function = sink_function;
757         else
758                 function = source_function;
759
760         media_device_for_each_entity(entity, mdev) {
761                 if (entity->function != function)
762                         continue;
763
764                 if (source)
765                         ret = media_create_pad_link(source, source_pad,
766                                                     entity, sink_pad, flags);
767                 else
768                         ret = media_create_pad_link(entity, source_pad,
769                                                     sink, sink_pad, flags);
770                 if (ret)
771                         return ret;
772                 flags &= ~(MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
773         }
774         return 0;
775 }
776 EXPORT_SYMBOL_GPL(media_create_pad_links);
777
778 void __media_entity_remove_links(struct media_entity *entity)
779 {
780         struct media_link *link, *tmp;
781
782         list_for_each_entry_safe(link, tmp, &entity->links, list)
783                 __media_entity_remove_link(entity, link);
784
785         entity->num_links = 0;
786         entity->num_backlinks = 0;
787 }
788 EXPORT_SYMBOL_GPL(__media_entity_remove_links);
789
790 void media_entity_remove_links(struct media_entity *entity)
791 {
792         struct media_device *mdev = entity->graph_obj.mdev;
793
794         /* Do nothing if the entity is not registered. */
795         if (mdev == NULL)
796                 return;
797
798         mutex_lock(&mdev->graph_mutex);
799         __media_entity_remove_links(entity);
800         mutex_unlock(&mdev->graph_mutex);
801 }
802 EXPORT_SYMBOL_GPL(media_entity_remove_links);
803
804 static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
805 {
806         int ret;
807
808         /* Notify both entities. */
809         ret = media_entity_call(link->source->entity, link_setup,
810                                 link->source, link->sink, flags);
811         if (ret < 0 && ret != -ENOIOCTLCMD)
812                 return ret;
813
814         ret = media_entity_call(link->sink->entity, link_setup,
815                                 link->sink, link->source, flags);
816         if (ret < 0 && ret != -ENOIOCTLCMD) {
817                 media_entity_call(link->source->entity, link_setup,
818                                   link->source, link->sink, link->flags);
819                 return ret;
820         }
821
822         link->flags = flags;
823         link->reverse->flags = link->flags;
824
825         return 0;
826 }
827
828 int __media_entity_setup_link(struct media_link *link, u32 flags)
829 {
830         const u32 mask = MEDIA_LNK_FL_ENABLED;
831         struct media_device *mdev;
832         struct media_entity *source, *sink;
833         int ret = -EBUSY;
834
835         if (link == NULL)
836                 return -EINVAL;
837
838         /* The non-modifiable link flags must not be modified. */
839         if ((link->flags & ~mask) != (flags & ~mask))
840                 return -EINVAL;
841
842         if (link->flags & MEDIA_LNK_FL_IMMUTABLE)
843                 return link->flags == flags ? 0 : -EINVAL;
844
845         if (link->flags == flags)
846                 return 0;
847
848         source = link->source->entity;
849         sink = link->sink->entity;
850
851         if (!(link->flags & MEDIA_LNK_FL_DYNAMIC) &&
852             (media_entity_is_streaming(source) ||
853              media_entity_is_streaming(sink)))
854                 return -EBUSY;
855
856         mdev = source->graph_obj.mdev;
857
858         if (mdev->ops && mdev->ops->link_notify) {
859                 ret = mdev->ops->link_notify(link, flags,
860                                              MEDIA_DEV_NOTIFY_PRE_LINK_CH);
861                 if (ret < 0)
862                         return ret;
863         }
864
865         ret = __media_entity_setup_link_notify(link, flags);
866
867         if (mdev->ops && mdev->ops->link_notify)
868                 mdev->ops->link_notify(link, flags,
869                                        MEDIA_DEV_NOTIFY_POST_LINK_CH);
870
871         return ret;
872 }
873 EXPORT_SYMBOL_GPL(__media_entity_setup_link);
874
875 int media_entity_setup_link(struct media_link *link, u32 flags)
876 {
877         int ret;
878
879         mutex_lock(&link->graph_obj.mdev->graph_mutex);
880         ret = __media_entity_setup_link(link, flags);
881         mutex_unlock(&link->graph_obj.mdev->graph_mutex);
882
883         return ret;
884 }
885 EXPORT_SYMBOL_GPL(media_entity_setup_link);
886
887 struct media_link *
888 media_entity_find_link(struct media_pad *source, struct media_pad *sink)
889 {
890         struct media_link *link;
891
892         for_each_media_entity_data_link(source->entity, link) {
893                 if (link->source->entity == source->entity &&
894                     link->source->index == source->index &&
895                     link->sink->entity == sink->entity &&
896                     link->sink->index == sink->index)
897                         return link;
898         }
899
900         return NULL;
901 }
902 EXPORT_SYMBOL_GPL(media_entity_find_link);
903
904 struct media_pad *media_pad_remote_pad_first(const struct media_pad *pad)
905 {
906         struct media_link *link;
907
908         for_each_media_entity_data_link(pad->entity, link) {
909                 if (!(link->flags & MEDIA_LNK_FL_ENABLED))
910                         continue;
911
912                 if (link->source == pad)
913                         return link->sink;
914
915                 if (link->sink == pad)
916                         return link->source;
917         }
918
919         return NULL;
920
921 }
922 EXPORT_SYMBOL_GPL(media_pad_remote_pad_first);
923
924 struct media_pad *
925 media_entity_remote_pad_unique(const struct media_entity *entity,
926                                unsigned int type)
927 {
928         struct media_pad *pad = NULL;
929         struct media_link *link;
930
931         list_for_each_entry(link, &entity->links, list) {
932                 struct media_pad *local_pad;
933                 struct media_pad *remote_pad;
934
935                 if (((link->flags & MEDIA_LNK_FL_LINK_TYPE) !=
936                      MEDIA_LNK_FL_DATA_LINK) ||
937                     !(link->flags & MEDIA_LNK_FL_ENABLED))
938                         continue;
939
940                 if (type == MEDIA_PAD_FL_SOURCE) {
941                         local_pad = link->sink;
942                         remote_pad = link->source;
943                 } else {
944                         local_pad = link->source;
945                         remote_pad = link->sink;
946                 }
947
948                 if (local_pad->entity == entity) {
949                         if (pad)
950                                 return ERR_PTR(-ENOTUNIQ);
951
952                         pad = remote_pad;
953                 }
954         }
955
956         if (!pad)
957                 return ERR_PTR(-ENOLINK);
958
959         return pad;
960 }
961 EXPORT_SYMBOL_GPL(media_entity_remote_pad_unique);
962
963 struct media_pad *media_pad_remote_pad_unique(const struct media_pad *pad)
964 {
965         struct media_pad *found_pad = NULL;
966         struct media_link *link;
967
968         list_for_each_entry(link, &pad->entity->links, list) {
969                 struct media_pad *remote_pad;
970
971                 if (!(link->flags & MEDIA_LNK_FL_ENABLED))
972                         continue;
973
974                 if (link->sink == pad)
975                         remote_pad = link->source;
976                 else if (link->source == pad)
977                         remote_pad = link->sink;
978                 else
979                         continue;
980
981                 if (found_pad)
982                         return ERR_PTR(-ENOTUNIQ);
983
984                 found_pad = remote_pad;
985         }
986
987         if (!found_pad)
988                 return ERR_PTR(-ENOLINK);
989
990         return found_pad;
991 }
992 EXPORT_SYMBOL_GPL(media_pad_remote_pad_unique);
993
994 static void media_interface_init(struct media_device *mdev,
995                                  struct media_interface *intf,
996                                  u32 gobj_type,
997                                  u32 intf_type, u32 flags)
998 {
999         intf->type = intf_type;
1000         intf->flags = flags;
1001         INIT_LIST_HEAD(&intf->links);
1002
1003         media_gobj_create(mdev, gobj_type, &intf->graph_obj);
1004 }
1005
1006 /* Functions related to the media interface via device nodes */
1007
1008 struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
1009                                                 u32 type, u32 flags,
1010                                                 u32 major, u32 minor)
1011 {
1012         struct media_intf_devnode *devnode;
1013
1014         devnode = kzalloc(sizeof(*devnode), GFP_KERNEL);
1015         if (!devnode)
1016                 return NULL;
1017
1018         devnode->major = major;
1019         devnode->minor = minor;
1020
1021         media_interface_init(mdev, &devnode->intf, MEDIA_GRAPH_INTF_DEVNODE,
1022                              type, flags);
1023
1024         return devnode;
1025 }
1026 EXPORT_SYMBOL_GPL(media_devnode_create);
1027
1028 void media_devnode_remove(struct media_intf_devnode *devnode)
1029 {
1030         media_remove_intf_links(&devnode->intf);
1031         media_gobj_destroy(&devnode->intf.graph_obj);
1032         kfree(devnode);
1033 }
1034 EXPORT_SYMBOL_GPL(media_devnode_remove);
1035
1036 struct media_link *media_create_intf_link(struct media_entity *entity,
1037                                             struct media_interface *intf,
1038                                             u32 flags)
1039 {
1040         struct media_link *link;
1041
1042         link = media_add_link(&intf->links);
1043         if (link == NULL)
1044                 return NULL;
1045
1046         link->intf = intf;
1047         link->entity = entity;
1048         link->flags = flags | MEDIA_LNK_FL_INTERFACE_LINK;
1049
1050         /* Initialize graph object embedded at the new link */
1051         media_gobj_create(intf->graph_obj.mdev, MEDIA_GRAPH_LINK,
1052                         &link->graph_obj);
1053
1054         return link;
1055 }
1056 EXPORT_SYMBOL_GPL(media_create_intf_link);
1057
1058 void __media_remove_intf_link(struct media_link *link)
1059 {
1060         list_del(&link->list);
1061         media_gobj_destroy(&link->graph_obj);
1062         kfree(link);
1063 }
1064 EXPORT_SYMBOL_GPL(__media_remove_intf_link);
1065
1066 void media_remove_intf_link(struct media_link *link)
1067 {
1068         struct media_device *mdev = link->graph_obj.mdev;
1069
1070         /* Do nothing if the intf is not registered. */
1071         if (mdev == NULL)
1072                 return;
1073
1074         mutex_lock(&mdev->graph_mutex);
1075         __media_remove_intf_link(link);
1076         mutex_unlock(&mdev->graph_mutex);
1077 }
1078 EXPORT_SYMBOL_GPL(media_remove_intf_link);
1079
1080 void __media_remove_intf_links(struct media_interface *intf)
1081 {
1082         struct media_link *link, *tmp;
1083
1084         list_for_each_entry_safe(link, tmp, &intf->links, list)
1085                 __media_remove_intf_link(link);
1086
1087 }
1088 EXPORT_SYMBOL_GPL(__media_remove_intf_links);
1089
1090 void media_remove_intf_links(struct media_interface *intf)
1091 {
1092         struct media_device *mdev = intf->graph_obj.mdev;
1093
1094         /* Do nothing if the intf is not registered. */
1095         if (mdev == NULL)
1096                 return;
1097
1098         mutex_lock(&mdev->graph_mutex);
1099         __media_remove_intf_links(intf);
1100         mutex_unlock(&mdev->graph_mutex);
1101 }
1102 EXPORT_SYMBOL_GPL(media_remove_intf_links);
1103
1104 struct media_link *media_create_ancillary_link(struct media_entity *primary,
1105                                                struct media_entity *ancillary)
1106 {
1107         struct media_link *link;
1108
1109         link = media_add_link(&primary->links);
1110         if (!link)
1111                 return ERR_PTR(-ENOMEM);
1112
1113         link->gobj0 = &primary->graph_obj;
1114         link->gobj1 = &ancillary->graph_obj;
1115         link->flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED |
1116                       MEDIA_LNK_FL_ANCILLARY_LINK;
1117
1118         /* Initialize graph object embedded in the new link */
1119         media_gobj_create(primary->graph_obj.mdev, MEDIA_GRAPH_LINK,
1120                           &link->graph_obj);
1121
1122         return link;
1123 }
1124 EXPORT_SYMBOL_GPL(media_create_ancillary_link);
1125
1126 struct media_link *__media_entity_next_link(struct media_entity *entity,
1127                                             struct media_link *link,
1128                                             unsigned long link_type)
1129 {
1130         link = link ? list_next_entry(link, list)
1131                     : list_first_entry(&entity->links, typeof(*link), list);
1132
1133         list_for_each_entry_from(link, &entity->links, list)
1134                 if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) == link_type)
1135                         return link;
1136
1137         return NULL;
1138 }
1139 EXPORT_SYMBOL_GPL(__media_entity_next_link);