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