linux/drivers/media/media-entity.c
<<
>>
Prefs
   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 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  21 */
  22
  23#include <linux/bitmap.h>
  24#include <linux/module.h>
  25#include <linux/slab.h>
  26#include <media/media-entity.h>
  27#include <media/media-device.h>
  28
  29/**
  30 * media_entity_init - Initialize a media entity
  31 *
  32 * @num_pads: Total number of sink and source pads.
  33 * @extra_links: Initial estimate of the number of extra links.
  34 * @pads: Array of 'num_pads' pads.
  35 *
  36 * The total number of pads is an intrinsic property of entities known by the
  37 * entity driver, while the total number of links depends on hardware design
  38 * and is an extrinsic property unknown to the entity driver. However, in most
  39 * use cases the entity driver can guess the number of links which can safely
  40 * be assumed to be equal to or larger than the number of pads.
  41 *
  42 * For those reasons the links array can be preallocated based on the entity
  43 * driver guess and will be reallocated later if extra links need to be
  44 * created.
  45 *
  46 * This function allocates a links array with enough space to hold at least
  47 * 'num_pads' + 'extra_links' elements. The media_entity::max_links field will
  48 * be set to the number of allocated elements.
  49 *
  50 * The pads array is managed by the entity driver and passed to
  51 * media_entity_init() where its pointer will be stored in the entity structure.
  52 */
  53int
  54media_entity_init(struct media_entity *entity, u16 num_pads,
  55                  struct media_pad *pads, u16 extra_links)
  56{
  57        struct media_link *links;
  58        unsigned int max_links = num_pads + extra_links;
  59        unsigned int i;
  60
  61        links = kzalloc(max_links * sizeof(links[0]), GFP_KERNEL);
  62        if (links == NULL)
  63                return -ENOMEM;
  64
  65        entity->group_id = 0;
  66        entity->max_links = max_links;
  67        entity->num_links = 0;
  68        entity->num_backlinks = 0;
  69        entity->num_pads = num_pads;
  70        entity->pads = pads;
  71        entity->links = links;
  72
  73        for (i = 0; i < num_pads; i++) {
  74                pads[i].entity = entity;
  75                pads[i].index = i;
  76        }
  77
  78        return 0;
  79}
  80EXPORT_SYMBOL_GPL(media_entity_init);
  81
  82void
  83media_entity_cleanup(struct media_entity *entity)
  84{
  85        kfree(entity->links);
  86}
  87EXPORT_SYMBOL_GPL(media_entity_cleanup);
  88
  89/* -----------------------------------------------------------------------------
  90 * Graph traversal
  91 */
  92
  93static struct media_entity *
  94media_entity_other(struct media_entity *entity, struct media_link *link)
  95{
  96        if (link->source->entity == entity)
  97                return link->sink->entity;
  98        else
  99                return link->source->entity;
 100}
 101
 102/* push an entity to traversal stack */
 103static void stack_push(struct media_entity_graph *graph,
 104                       struct media_entity *entity)
 105{
 106        if (graph->top == MEDIA_ENTITY_ENUM_MAX_DEPTH - 1) {
 107                WARN_ON(1);
 108                return;
 109        }
 110        graph->top++;
 111        graph->stack[graph->top].link = 0;
 112        graph->stack[graph->top].entity = entity;
 113}
 114
 115static struct media_entity *stack_pop(struct media_entity_graph *graph)
 116{
 117        struct media_entity *entity;
 118
 119        entity = graph->stack[graph->top].entity;
 120        graph->top--;
 121
 122        return entity;
 123}
 124
 125#define link_top(en)    ((en)->stack[(en)->top].link)
 126#define stack_top(en)   ((en)->stack[(en)->top].entity)
 127
 128/**
 129 * media_entity_graph_walk_start - Start walking the media graph at a given entity
 130 * @graph: Media graph structure that will be used to walk the graph
 131 * @entity: Starting entity
 132 *
 133 * This function initializes the graph traversal structure to walk the entities
 134 * graph starting at the given entity. The traversal structure must not be
 135 * modified by the caller during graph traversal. When done the structure can
 136 * safely be freed.
 137 */
 138void media_entity_graph_walk_start(struct media_entity_graph *graph,
 139                                   struct media_entity *entity)
 140{
 141        graph->top = 0;
 142        graph->stack[graph->top].entity = NULL;
 143        bitmap_zero(graph->entities, MEDIA_ENTITY_ENUM_MAX_ID);
 144
 145        if (WARN_ON(entity->id >= MEDIA_ENTITY_ENUM_MAX_ID))
 146                return;
 147
 148        __set_bit(entity->id, graph->entities);
 149        stack_push(graph, entity);
 150}
 151EXPORT_SYMBOL_GPL(media_entity_graph_walk_start);
 152
 153/**
 154 * media_entity_graph_walk_next - Get the next entity in the graph
 155 * @graph: Media graph structure
 156 *
 157 * Perform a depth-first traversal of the given media entities graph.
 158 *
 159 * The graph structure must have been previously initialized with a call to
 160 * media_entity_graph_walk_start().
 161 *
 162 * Return the next entity in the graph or NULL if the whole graph have been
 163 * traversed.
 164 */
 165struct media_entity *
 166media_entity_graph_walk_next(struct media_entity_graph *graph)
 167{
 168        if (stack_top(graph) == NULL)
 169                return NULL;
 170
 171        /*
 172         * Depth first search. Push entity to stack and continue from
 173         * top of the stack until no more entities on the level can be
 174         * found.
 175         */
 176        while (link_top(graph) < stack_top(graph)->num_links) {
 177                struct media_entity *entity = stack_top(graph);
 178                struct media_link *link = &entity->links[link_top(graph)];
 179                struct media_entity *next;
 180
 181                /* The link is not enabled so we do not follow. */
 182                if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
 183                        link_top(graph)++;
 184                        continue;
 185                }
 186
 187                /* Get the entity in the other end of the link . */
 188                next = media_entity_other(entity, link);
 189                if (WARN_ON(next->id >= MEDIA_ENTITY_ENUM_MAX_ID))
 190                        return NULL;
 191
 192                /* Has the entity already been visited? */
 193                if (__test_and_set_bit(next->id, graph->entities)) {
 194                        link_top(graph)++;
 195                        continue;
 196                }
 197
 198                /* Push the new entity to stack and start over. */
 199                link_top(graph)++;
 200                stack_push(graph, next);
 201        }
 202
 203        return stack_pop(graph);
 204}
 205EXPORT_SYMBOL_GPL(media_entity_graph_walk_next);
 206
 207/* -----------------------------------------------------------------------------
 208 * Pipeline management
 209 */
 210
 211/**
 212 * media_entity_pipeline_start - Mark a pipeline as streaming
 213 * @entity: Starting entity
 214 * @pipe: Media pipeline to be assigned to all entities in the pipeline.
 215 *
 216 * Mark all entities connected to a given entity through enabled links, either
 217 * directly or indirectly, as streaming. The given pipeline object is assigned to
 218 * every entity in the pipeline and stored in the media_entity pipe field.
 219 *
 220 * Calls to this function can be nested, in which case the same number of
 221 * media_entity_pipeline_stop() calls will be required to stop streaming. The
 222 * pipeline pointer must be identical for all nested calls to
 223 * media_entity_pipeline_start().
 224 */
 225__must_check int media_entity_pipeline_start(struct media_entity *entity,
 226                                             struct media_pipeline *pipe)
 227{
 228        struct media_device *mdev = entity->parent;
 229        struct media_entity_graph graph;
 230        struct media_entity *entity_err = entity;
 231        int ret;
 232
 233        mutex_lock(&mdev->graph_mutex);
 234
 235        media_entity_graph_walk_start(&graph, entity);
 236
 237        while ((entity = media_entity_graph_walk_next(&graph))) {
 238                DECLARE_BITMAP(active, entity->num_pads);
 239                DECLARE_BITMAP(has_no_links, entity->num_pads);
 240                unsigned int i;
 241
 242                entity->stream_count++;
 243                WARN_ON(entity->pipe && entity->pipe != pipe);
 244                entity->pipe = pipe;
 245
 246                /* Already streaming --- no need to check. */
 247                if (entity->stream_count > 1)
 248                        continue;
 249
 250                if (!entity->ops || !entity->ops->link_validate)
 251                        continue;
 252
 253                bitmap_zero(active, entity->num_pads);
 254                bitmap_fill(has_no_links, entity->num_pads);
 255
 256                for (i = 0; i < entity->num_links; i++) {
 257                        struct media_link *link = &entity->links[i];
 258                        struct media_pad *pad = link->sink->entity == entity
 259                                                ? link->sink : link->source;
 260
 261                        /* Mark that a pad is connected by a link. */
 262                        bitmap_clear(has_no_links, pad->index, 1);
 263
 264                        /*
 265                         * Pads that either do not need to connect or
 266                         * are connected through an enabled link are
 267                         * fine.
 268                         */
 269                        if (!(pad->flags & MEDIA_PAD_FL_MUST_CONNECT) ||
 270                            link->flags & MEDIA_LNK_FL_ENABLED)
 271                                bitmap_set(active, pad->index, 1);
 272
 273                        /*
 274                         * Link validation will only take place for
 275                         * sink ends of the link that are enabled.
 276                         */
 277                        if (link->sink != pad ||
 278                            !(link->flags & MEDIA_LNK_FL_ENABLED))
 279                                continue;
 280
 281                        ret = entity->ops->link_validate(link);
 282                        if (ret < 0 && ret != -ENOIOCTLCMD) {
 283                                dev_dbg(entity->parent->dev,
 284                                        "link validation failed for \"%s\":%u -> \"%s\":%u, error %d\n",
 285                                        entity->name, link->source->index,
 286                                        link->sink->entity->name,
 287                                        link->sink->index, ret);
 288                                goto error;
 289                        }
 290                }
 291
 292                /* Either no links or validated links are fine. */
 293                bitmap_or(active, active, has_no_links, entity->num_pads);
 294
 295                if (!bitmap_full(active, entity->num_pads)) {
 296                        ret = -EPIPE;
 297                        dev_dbg(entity->parent->dev,
 298                                "\"%s\":%u must be connected by an enabled link\n",
 299                                entity->name,
 300                                (unsigned)find_first_zero_bit(
 301                                        active, entity->num_pads));
 302                        goto error;
 303                }
 304        }
 305
 306        mutex_unlock(&mdev->graph_mutex);
 307
 308        return 0;
 309
 310error:
 311        /*
 312         * Link validation on graph failed. We revert what we did and
 313         * return the error.
 314         */
 315        media_entity_graph_walk_start(&graph, entity_err);
 316
 317        while ((entity_err = media_entity_graph_walk_next(&graph))) {
 318                entity_err->stream_count--;
 319                if (entity_err->stream_count == 0)
 320                        entity_err->pipe = NULL;
 321
 322                /*
 323                 * We haven't increased stream_count further than this
 324                 * so we quit here.
 325                 */
 326                if (entity_err == entity)
 327                        break;
 328        }
 329
 330        mutex_unlock(&mdev->graph_mutex);
 331
 332        return ret;
 333}
 334EXPORT_SYMBOL_GPL(media_entity_pipeline_start);
 335
 336/**
 337 * media_entity_pipeline_stop - Mark a pipeline as not streaming
 338 * @entity: Starting entity
 339 *
 340 * Mark all entities connected to a given entity through enabled links, either
 341 * directly or indirectly, as not streaming. The media_entity pipe field is
 342 * reset to NULL.
 343 *
 344 * If multiple calls to media_entity_pipeline_start() have been made, the same
 345 * number of calls to this function are required to mark the pipeline as not
 346 * streaming.
 347 */
 348void media_entity_pipeline_stop(struct media_entity *entity)
 349{
 350        struct media_device *mdev = entity->parent;
 351        struct media_entity_graph graph;
 352
 353        mutex_lock(&mdev->graph_mutex);
 354
 355        media_entity_graph_walk_start(&graph, entity);
 356
 357        while ((entity = media_entity_graph_walk_next(&graph))) {
 358                entity->stream_count--;
 359                if (entity->stream_count == 0)
 360                        entity->pipe = NULL;
 361        }
 362
 363        mutex_unlock(&mdev->graph_mutex);
 364}
 365EXPORT_SYMBOL_GPL(media_entity_pipeline_stop);
 366
 367/* -----------------------------------------------------------------------------
 368 * Module use count
 369 */
 370
 371/*
 372 * media_entity_get - Get a reference to the parent module
 373 * @entity: The entity
 374 *
 375 * Get a reference to the parent media device module.
 376 *
 377 * The function will return immediately if @entity is NULL.
 378 *
 379 * Return a pointer to the entity on success or NULL on failure.
 380 */
 381struct media_entity *media_entity_get(struct media_entity *entity)
 382{
 383        if (entity == NULL)
 384                return NULL;
 385
 386        if (entity->parent->dev &&
 387            !try_module_get(entity->parent->dev->driver->owner))
 388                return NULL;
 389
 390        return entity;
 391}
 392EXPORT_SYMBOL_GPL(media_entity_get);
 393
 394/*
 395 * media_entity_put - Release the reference to the parent module
 396 * @entity: The entity
 397 *
 398 * Release the reference count acquired by media_entity_get().
 399 *
 400 * The function will return immediately if @entity is NULL.
 401 */
 402void media_entity_put(struct media_entity *entity)
 403{
 404        if (entity == NULL)
 405                return;
 406
 407        if (entity->parent->dev)
 408                module_put(entity->parent->dev->driver->owner);
 409}
 410EXPORT_SYMBOL_GPL(media_entity_put);
 411
 412/* -----------------------------------------------------------------------------
 413 * Links management
 414 */
 415
 416static struct media_link *media_entity_add_link(struct media_entity *entity)
 417{
 418        if (entity->num_links >= entity->max_links) {
 419                struct media_link *links = entity->links;
 420                unsigned int max_links = entity->max_links + 2;
 421                unsigned int i;
 422
 423                links = krealloc(links, max_links * sizeof(*links), GFP_KERNEL);
 424                if (links == NULL)
 425                        return NULL;
 426
 427                for (i = 0; i < entity->num_links; i++)
 428                        links[i].reverse->reverse = &links[i];
 429
 430                entity->max_links = max_links;
 431                entity->links = links;
 432        }
 433
 434        return &entity->links[entity->num_links++];
 435}
 436
 437int
 438media_entity_create_link(struct media_entity *source, u16 source_pad,
 439                         struct media_entity *sink, u16 sink_pad, u32 flags)
 440{
 441        struct media_link *link;
 442        struct media_link *backlink;
 443
 444        BUG_ON(source == NULL || sink == NULL);
 445        BUG_ON(source_pad >= source->num_pads);
 446        BUG_ON(sink_pad >= sink->num_pads);
 447
 448        link = media_entity_add_link(source);
 449        if (link == NULL)
 450                return -ENOMEM;
 451
 452        link->source = &source->pads[source_pad];
 453        link->sink = &sink->pads[sink_pad];
 454        link->flags = flags;
 455
 456        /* Create the backlink. Backlinks are used to help graph traversal and
 457         * are not reported to userspace.
 458         */
 459        backlink = media_entity_add_link(sink);
 460        if (backlink == NULL) {
 461                source->num_links--;
 462                return -ENOMEM;
 463        }
 464
 465        backlink->source = &source->pads[source_pad];
 466        backlink->sink = &sink->pads[sink_pad];
 467        backlink->flags = flags;
 468
 469        link->reverse = backlink;
 470        backlink->reverse = link;
 471
 472        sink->num_backlinks++;
 473
 474        return 0;
 475}
 476EXPORT_SYMBOL_GPL(media_entity_create_link);
 477
 478void __media_entity_remove_links(struct media_entity *entity)
 479{
 480        unsigned int i;
 481
 482        for (i = 0; i < entity->num_links; i++) {
 483                struct media_link *link = &entity->links[i];
 484                struct media_entity *remote;
 485                unsigned int r = 0;
 486
 487                if (link->source->entity == entity)
 488                        remote = link->sink->entity;
 489                else
 490                        remote = link->source->entity;
 491
 492                while (r < remote->num_links) {
 493                        struct media_link *rlink = &remote->links[r];
 494
 495                        if (rlink != link->reverse) {
 496                                r++;
 497                                continue;
 498                        }
 499
 500                        if (link->source->entity == entity)
 501                                remote->num_backlinks--;
 502
 503                        if (--remote->num_links == 0)
 504                                break;
 505
 506                        /* Insert last entry in place of the dropped link. */
 507                        *rlink = remote->links[remote->num_links];
 508                }
 509        }
 510
 511        entity->num_links = 0;
 512        entity->num_backlinks = 0;
 513}
 514EXPORT_SYMBOL_GPL(__media_entity_remove_links);
 515
 516void media_entity_remove_links(struct media_entity *entity)
 517{
 518        /* Do nothing if the entity is not registered. */
 519        if (entity->parent == NULL)
 520                return;
 521
 522        mutex_lock(&entity->parent->graph_mutex);
 523        __media_entity_remove_links(entity);
 524        mutex_unlock(&entity->parent->graph_mutex);
 525}
 526EXPORT_SYMBOL_GPL(media_entity_remove_links);
 527
 528static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
 529{
 530        int ret;
 531
 532        /* Notify both entities. */
 533        ret = media_entity_call(link->source->entity, link_setup,
 534                                link->source, link->sink, flags);
 535        if (ret < 0 && ret != -ENOIOCTLCMD)
 536                return ret;
 537
 538        ret = media_entity_call(link->sink->entity, link_setup,
 539                                link->sink, link->source, flags);
 540        if (ret < 0 && ret != -ENOIOCTLCMD) {
 541                media_entity_call(link->source->entity, link_setup,
 542                                  link->source, link->sink, link->flags);
 543                return ret;
 544        }
 545
 546        link->flags = flags;
 547        link->reverse->flags = link->flags;
 548
 549        return 0;
 550}
 551
 552/**
 553 * __media_entity_setup_link - Configure a media link
 554 * @link: The link being configured
 555 * @flags: Link configuration flags
 556 *
 557 * The bulk of link setup is handled by the two entities connected through the
 558 * link. This function notifies both entities of the link configuration change.
 559 *
 560 * If the link is immutable or if the current and new configuration are
 561 * identical, return immediately.
 562 *
 563 * The user is expected to hold link->source->parent->mutex. If not,
 564 * media_entity_setup_link() should be used instead.
 565 */
 566int __media_entity_setup_link(struct media_link *link, u32 flags)
 567{
 568        const u32 mask = MEDIA_LNK_FL_ENABLED;
 569        struct media_device *mdev;
 570        struct media_entity *source, *sink;
 571        int ret = -EBUSY;
 572
 573        if (link == NULL)
 574                return -EINVAL;
 575
 576        /* The non-modifiable link flags must not be modified. */
 577        if ((link->flags & ~mask) != (flags & ~mask))
 578                return -EINVAL;
 579
 580        if (link->flags & MEDIA_LNK_FL_IMMUTABLE)
 581                return link->flags == flags ? 0 : -EINVAL;
 582
 583        if (link->flags == flags)
 584                return 0;
 585
 586        source = link->source->entity;
 587        sink = link->sink->entity;
 588
 589        if (!(link->flags & MEDIA_LNK_FL_DYNAMIC) &&
 590            (source->stream_count || sink->stream_count))
 591                return -EBUSY;
 592
 593        mdev = source->parent;
 594
 595        if (mdev->link_notify) {
 596                ret = mdev->link_notify(link, flags,
 597                                        MEDIA_DEV_NOTIFY_PRE_LINK_CH);
 598                if (ret < 0)
 599                        return ret;
 600        }
 601
 602        ret = __media_entity_setup_link_notify(link, flags);
 603
 604        if (mdev->link_notify)
 605                mdev->link_notify(link, flags, MEDIA_DEV_NOTIFY_POST_LINK_CH);
 606
 607        return ret;
 608}
 609
 610int media_entity_setup_link(struct media_link *link, u32 flags)
 611{
 612        int ret;
 613
 614        mutex_lock(&link->source->entity->parent->graph_mutex);
 615        ret = __media_entity_setup_link(link, flags);
 616        mutex_unlock(&link->source->entity->parent->graph_mutex);
 617
 618        return ret;
 619}
 620EXPORT_SYMBOL_GPL(media_entity_setup_link);
 621
 622/**
 623 * media_entity_find_link - Find a link between two pads
 624 * @source: Source pad
 625 * @sink: Sink pad
 626 *
 627 * Return a pointer to the link between the two entities. If no such link
 628 * exists, return NULL.
 629 */
 630struct media_link *
 631media_entity_find_link(struct media_pad *source, struct media_pad *sink)
 632{
 633        struct media_link *link;
 634        unsigned int i;
 635
 636        for (i = 0; i < source->entity->num_links; ++i) {
 637                link = &source->entity->links[i];
 638
 639                if (link->source->entity == source->entity &&
 640                    link->source->index == source->index &&
 641                    link->sink->entity == sink->entity &&
 642                    link->sink->index == sink->index)
 643                        return link;
 644        }
 645
 646        return NULL;
 647}
 648EXPORT_SYMBOL_GPL(media_entity_find_link);
 649
 650/**
 651 * media_entity_remote_pad - Find the pad at the remote end of a link
 652 * @pad: Pad at the local end of the link
 653 *
 654 * Search for a remote pad connected to the given pad by iterating over all
 655 * links originating or terminating at that pad until an enabled link is found.
 656 *
 657 * Return a pointer to the pad at the remote end of the first found enabled
 658 * link, or NULL if no enabled link has been found.
 659 */
 660struct media_pad *media_entity_remote_pad(struct media_pad *pad)
 661{
 662        unsigned int i;
 663
 664        for (i = 0; i < pad->entity->num_links; i++) {
 665                struct media_link *link = &pad->entity->links[i];
 666
 667                if (!(link->flags & MEDIA_LNK_FL_ENABLED))
 668                        continue;
 669
 670                if (link->source == pad)
 671                        return link->sink;
 672
 673                if (link->sink == pad)
 674                        return link->source;
 675        }
 676
 677        return NULL;
 678
 679}
 680EXPORT_SYMBOL_GPL(media_entity_remote_pad);
 681