| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- .. SPDX-License-Identifier: GPL-2.0
- Media Controller devices
- ------------------------
- Media Controller
- ~~~~~~~~~~~~~~~~
- The media controller userspace API is documented in
- :ref:`the Media Controller uAPI book <media_controller>`. This document focus
- on the kernel-side implementation of the media framework.
- Abstract media device model
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Discovering a device internal topology, and configuring it at runtime, is one
- of the goals of the media framework. To achieve this, hardware devices are
- modelled as an oriented graph of building blocks called entities connected
- through pads.
- An entity is a basic media hardware building block. It can correspond to
- a large variety of logical blocks such as physical hardware devices
- (CMOS sensor for instance), logical hardware devices (a building block
- in a System-on-Chip image processing pipeline), DMA channels or physical
- connectors.
- A pad is a connection endpoint through which an entity can interact with
- other entities. Data (not restricted to video) produced by an entity
- flows from the entity's output to one or more entity inputs. Pads should
- not be confused with physical pins at chip boundaries.
- A link is a point-to-point oriented connection between two pads, either
- on the same entity or on different entities. Data flows from a source
- pad to a sink pad.
- Media device
- ^^^^^^^^^^^^
- A media device is represented by a struct media_device
- instance, defined in ``include/media/media-device.h``.
- Allocation of the structure is handled by the media device driver, usually by
- embedding the :c:type:`media_device` instance in a larger driver-specific
- structure.
- Drivers initialise media device instances by calling
- :c:func:`media_device_init()`. After initialising a media device instance, it is
- registered by calling :c:func:`__media_device_register()` via the macro
- ``media_device_register()`` and unregistered by calling
- :c:func:`media_device_unregister()`. An initialised media device must be
- eventually cleaned up by calling :c:func:`media_device_cleanup()`.
- Note that it is not allowed to unregister a media device instance that was not
- previously registered, or clean up a media device instance that was not
- previously initialised.
- Entities
- ^^^^^^^^
- Entities are represented by a struct media_entity
- instance, defined in ``include/media/media-entity.h``. The structure is usually
- embedded into a higher-level structure, such as
- :c:type:`v4l2_subdev` or :c:type:`video_device`
- instances, although drivers can allocate entities directly.
- Drivers initialize entity pads by calling
- :c:func:`media_entity_pads_init()`.
- Drivers register entities with a media device by calling
- :c:func:`media_device_register_entity()`
- and unregistered by calling
- :c:func:`media_device_unregister_entity()`.
- Interfaces
- ^^^^^^^^^^
- Interfaces are represented by a
- struct media_interface instance, defined in
- ``include/media/media-entity.h``. Currently, only one type of interface is
- defined: a device node. Such interfaces are represented by a
- struct media_intf_devnode.
- Drivers initialize and create device node interfaces by calling
- :c:func:`media_devnode_create()`
- and remove them by calling:
- :c:func:`media_devnode_remove()`.
- Pads
- ^^^^
- Pads are represented by a struct media_pad instance,
- defined in ``include/media/media-entity.h``. Each entity stores its pads in
- a pads array managed by the entity driver. Drivers usually embed the array in
- a driver-specific structure.
- Pads are identified by their entity and their 0-based index in the pads
- array.
- Both information are stored in the struct media_pad,
- making the struct media_pad pointer the canonical way
- to store and pass link references.
- Pads have flags that describe the pad capabilities and state.
- ``MEDIA_PAD_FL_SINK`` indicates that the pad supports sinking data.
- ``MEDIA_PAD_FL_SOURCE`` indicates that the pad supports sourcing data.
- .. note::
- One and only one of ``MEDIA_PAD_FL_SINK`` or ``MEDIA_PAD_FL_SOURCE`` must
- be set for each pad.
- Links
- ^^^^^
- Links are represented by a struct media_link instance,
- defined in ``include/media/media-entity.h``. There are two types of links:
- **1. pad to pad links**:
- Associate two entities via their PADs. Each entity has a list that points
- to all links originating at or targeting any of its pads.
- A given link is thus stored twice, once in the source entity and once in
- the target entity.
- Drivers create pad to pad links by calling:
- :c:func:`media_create_pad_link()` and remove with
- :c:func:`media_entity_remove_links()`.
- **2. interface to entity links**:
- Associate one interface to a Link.
- Drivers create interface to entity links by calling:
- :c:func:`media_create_intf_link()` and remove with
- :c:func:`media_remove_intf_links()`.
- .. note::
- Links can only be created after having both ends already created.
- Links have flags that describe the link capabilities and state. The
- valid values are described at :c:func:`media_create_pad_link()` and
- :c:func:`media_create_intf_link()`.
- Graph traversal
- ^^^^^^^^^^^^^^^
- The media framework provides APIs to traverse media graphs, locating connected
- entities and links.
- To iterate over all entities belonging to a media device, drivers can use
- the media_device_for_each_entity macro, defined in
- ``include/media/media-device.h``.
- .. code-block:: c
- struct media_entity *entity;
- media_device_for_each_entity(entity, mdev) {
- // entity will point to each entity in turn
- ...
- }
- Helper functions can be used to find a link between two given pads, or a pad
- connected to another pad through an enabled link
- (:c:func:`media_entity_find_link()`, :c:func:`media_pad_remote_pad_first()`,
- :c:func:`media_entity_remote_source_pad_unique()` and
- :c:func:`media_pad_remote_pad_unique()`).
- Use count and power handling
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Due to the wide differences between drivers regarding power management
- needs, the media controller does not implement power management. However,
- the struct media_entity includes a ``use_count``
- field that media drivers
- can use to track the number of users of every entity for power management
- needs.
- The :c:type:`media_entity<media_entity>`.\ ``use_count`` field is owned by
- media drivers and must not be
- touched by entity drivers. Access to the field must be protected by the
- :c:type:`media_device`.\ ``graph_mutex`` lock.
- Links setup
- ^^^^^^^^^^^
- Link properties can be modified at runtime by calling
- :c:func:`media_entity_setup_link()`.
- Pipelines and media streams
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- A media stream is a stream of pixels or metadata originating from one or more
- source devices (such as a sensors) and flowing through media entity pads
- towards the final sinks. The stream can be modified on the route by the
- devices (e.g. scaling or pixel format conversions), or it can be split into
- multiple branches, or multiple branches can be merged.
- A media pipeline is a set of media streams which are interdependent. This
- interdependency can be caused by the hardware (e.g. configuration of a second
- stream cannot be changed if the first stream has been enabled) or by the driver
- due to the software design. Most commonly a media pipeline consists of a single
- stream which does not branch.
- When starting streaming, drivers must notify all entities in the pipeline to
- prevent link states from being modified during streaming by calling
- :c:func:`media_pipeline_start()`.
- The function will mark all the pads which are part of the pipeline as streaming.
- The struct media_pipeline instance pointed to by the pipe argument will be
- stored in every pad in the pipeline. Drivers should embed the struct
- media_pipeline in higher-level pipeline structures and can then access the
- pipeline through the struct media_pad pipe field.
- Calls to :c:func:`media_pipeline_start()` can be nested.
- The pipeline pointer must be identical for all nested calls to the function.
- :c:func:`media_pipeline_start()` may return an error. In that case,
- it will clean up any of the changes it did by itself.
- When stopping the stream, drivers must notify the entities with
- :c:func:`media_pipeline_stop()`.
- If multiple calls to :c:func:`media_pipeline_start()` have been
- made the same number of :c:func:`media_pipeline_stop()` calls
- are required to stop streaming.
- The :c:type:`media_entity`.\ ``pipe`` field is reset to ``NULL`` on the last
- nested stop call.
- Link configuration will fail with ``-EBUSY`` by default if either end of the
- link is a streaming entity. Links that can be modified while streaming must
- be marked with the ``MEDIA_LNK_FL_DYNAMIC`` flag.
- If other operations need to be disallowed on streaming entities (such as
- changing entities configuration parameters) drivers can explicitly check the
- media_entity stream_count field to find out if an entity is streaming. This
- operation must be done with the media_device graph_mutex held.
- Link validation
- ^^^^^^^^^^^^^^^
- Link validation is performed by :c:func:`media_pipeline_start()`
- for any entity which has sink pads in the pipeline. The
- :c:type:`media_entity`.\ ``link_validate()`` callback is used for that
- purpose. In ``link_validate()`` callback, entity driver should check
- that the properties of the source pad of the connected entity and its own
- sink pad match. It is up to the type of the entity (and in the end, the
- properties of the hardware) what matching actually means.
- Subsystems should facilitate link validation by providing subsystem specific
- helper functions to provide easy access for commonly needed information, and
- in the end provide a way to use driver-specific callbacks.
- Pipeline traversal
- ^^^^^^^^^^^^^^^^^^
- Once a pipeline has been constructed with :c:func:`media_pipeline_start()`,
- drivers can iterate over entities or pads in the pipeline with the
- :c:macro:´media_pipeline_for_each_entity` and
- :c:macro:´media_pipeline_for_each_pad` macros. Iterating over pads is
- straightforward:
- .. code-block:: c
- media_pipeline_pad_iter iter;
- struct media_pad *pad;
- media_pipeline_for_each_pad(pipe, &iter, pad) {
- /* 'pad' will point to each pad in turn */
- ...
- }
- To iterate over entities, the iterator needs to be initialized and cleaned up
- as an additional steps:
- .. code-block:: c
- media_pipeline_entity_iter iter;
- struct media_entity *entity;
- int ret;
- ret = media_pipeline_entity_iter_init(pipe, &iter);
- if (ret)
- ...;
- media_pipeline_for_each_entity(pipe, &iter, entity) {
- /* 'entity' will point to each entity in turn */
- ...
- }
- media_pipeline_entity_iter_cleanup(&iter);
- Media Controller Device Allocator API
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- When the media device belongs to more than one driver, the shared media
- device is allocated with the shared struct device as the key for look ups.
- The shared media device should stay in registered state until the last
- driver unregisters it. In addition, the media device should be released when
- all the references are released. Each driver gets a reference to the media
- device during probe, when it allocates the media device. If media device is
- already allocated, the allocate API bumps up the refcount and returns the
- existing media device. The driver puts the reference back in its disconnect
- routine when it calls :c:func:`media_device_delete()`.
- The media device is unregistered and cleaned up from the kref put handler to
- ensure that the media device stays in registered state until the last driver
- unregisters the media device.
- **Driver Usage**
- Drivers should use the appropriate media-core routines to manage the shared
- media device life-time handling the two states:
- 1. allocate -> register -> delete
- 2. get reference to already registered device -> delete
- call :c:func:`media_device_delete()` routine to make sure the shared media
- device delete is handled correctly.
- **driver probe:**
- Call :c:func:`media_device_usb_allocate()` to allocate or get a reference
- Call :c:func:`media_device_register()`, if media devnode isn't registered
- **driver disconnect:**
- Call :c:func:`media_device_delete()` to free the media_device. Freeing is
- handled by the kref put handler.
- API Definitions
- ^^^^^^^^^^^^^^^
- .. kernel-doc:: include/media/media-device.h
- .. kernel-doc:: include/media/media-devnode.h
- .. kernel-doc:: include/media/media-entity.h
- .. kernel-doc:: include/media/media-request.h
- .. kernel-doc:: include/media/media-dev-allocator.h
|