Documentation/driver-api/media/mc-core.rst GitHub 원문 ↗

Linux 6.18.37 · Driver API

Media Controller devices

Media entity·pad·link graph, pipeline streaming·validation·순회, 공유 media_device 생명주기를 설명하는 전문 번역입니다.

Source pathDocumentation/driver-api/media/mc-core.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약과 해설

mc-core.rst:1-341

Media Controller는 hardware topology를 entity·pad·방향 link graph로 나타냅니다. Driver는 object 생성 순서와 pad flag 불변식을 지키고 `graph_mutex`로 use count와 streaming 상태 검사를 보호해야 합니다.

Pipeline은 중첩 start와 같은 횟수의 stop을 요구하며 streaming 중 link 변경은 기본적으로 `-EBUSY`입니다. 여러 driver가 media device를 공유할 때는 allocator와 kref가 마지막 reference까지 등록 상태를 유지합니다.

문서 구성
원문 줄내용
1-35Kernel 구현 소개와 추상 media graph
36-55`media_device` 생명주기
56-110Entity·interface·pad와 flag
111-143Pad·interface link
144-168Media graph 순회
169-189`use_count`·`graph_mutex`·link 설정
190-239Stream·pipeline 중첩 생명주기
240-254Link validation
255-293Pipeline pad·entity iterator
294-329Shared media device allocator와 kref
330-341Kernel-doc API 정의

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2
3 Media Controller devices
4 ------------------------
5
6 Media Controller
7 ~~~~~~~~~~~~~~~~
8
9 The media controller userspace API is documented in
10 :ref:`the Media Controller uAPI book <media_controller>`. This document focus
11 on the kernel-side implementation of the media framework.
12
13 Abstract media device model
14 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
15
16 Discovering a device internal topology, and configuring it at runtime, is one
17 of the goals of the media framework. To achieve this, hardware devices are
18 modelled as an oriented graph of building blocks called entities connected
19 through pads.
20
21 An entity is a basic media hardware building block. It can correspond to
22 a large variety of logical blocks such as physical hardware devices
23 (CMOS sensor for instance), logical hardware devices (a building block
24 in a System-on-Chip image processing pipeline), DMA channels or physical
25 connectors.
26
27 A pad is a connection endpoint through which an entity can interact with
28 other entities. Data (not restricted to video) produced by an entity
29 flows from the entity's output to one or more entity inputs. Pads should
30 not be confused with physical pins at chip boundaries.
31
32 A link is a point-to-point oriented connection between two pads, either
33 on the same entity or on different entities. Data flows from a source
34 pad to a sink pad.
35
36 Media device
37 ^^^^^^^^^^^^
38
39 A media device is represented by a struct media_device
40 instance, defined in ``include/media/media-device.h``.
41 Allocation of the structure is handled by the media device driver, usually by
42 embedding the :c:type:`media_device` instance in a larger driver-specific
43 structure.
44
45 Drivers initialise media device instances by calling
46 :c:func:`media_device_init()`. After initialising a media device instance, it is
47 registered by calling :c:func:`__media_device_register()` via the macro
48 ``media_device_register()`` and unregistered by calling
49 :c:func:`media_device_unregister()`. An initialised media device must be
50 eventually cleaned up by calling :c:func:`media_device_cleanup()`.
51
52 Note that it is not allowed to unregister a media device instance that was not
53 previously registered, or clean up a media device instance that was not
54 previously initialised.
55
56 Entities
57 ^^^^^^^^
58
59 Entities are represented by a struct media_entity
60 instance, defined in ``include/media/media-entity.h``. The structure is usually
61 embedded into a higher-level structure, such as
62 :c:type:`v4l2_subdev` or :c:type:`video_device`
63 instances, although drivers can allocate entities directly.
64
65 Drivers initialize entity pads by calling
66 :c:func:`media_entity_pads_init()`.
67
68 Drivers register entities with a media device by calling
69 :c:func:`media_device_register_entity()`
70 and unregistered by calling
71 :c:func:`media_device_unregister_entity()`.
72
73 Interfaces
74 ^^^^^^^^^^
75
76 Interfaces are represented by a
77 struct media_interface instance, defined in
78 ``include/media/media-entity.h``. Currently, only one type of interface is
79 defined: a device node. Such interfaces are represented by a
80 struct media_intf_devnode.
81
82 Drivers initialize and create device node interfaces by calling
83 :c:func:`media_devnode_create()`
84 and remove them by calling:
85 :c:func:`media_devnode_remove()`.
86
87 Pads
88 ^^^^
89 Pads are represented by a struct media_pad instance,
90 defined in ``include/media/media-entity.h``. Each entity stores its pads in
91 a pads array managed by the entity driver. Drivers usually embed the array in
92 a driver-specific structure.
93
94 Pads are identified by their entity and their 0-based index in the pads
95 array.
96
97 Both information are stored in the struct media_pad,
98 making the struct media_pad pointer the canonical way
99 to store and pass link references.
100
101 Pads have flags that describe the pad capabilities and state.
102
103 ``MEDIA_PAD_FL_SINK`` indicates that the pad supports sinking data.
104 ``MEDIA_PAD_FL_SOURCE`` indicates that the pad supports sourcing data.
105
106 .. note::
107
108 One and only one of ``MEDIA_PAD_FL_SINK`` or ``MEDIA_PAD_FL_SOURCE`` must
109 be set for each pad.
110
111 Links
112 ^^^^^
113
114 Links are represented by a struct media_link instance,
115 defined in ``include/media/media-entity.h``. There are two types of links:
116
117 **1. pad to pad links**:
118
119 Associate two entities via their PADs. Each entity has a list that points
120 to all links originating at or targeting any of its pads.
121 A given link is thus stored twice, once in the source entity and once in
122 the target entity.
123
124 Drivers create pad to pad links by calling:
125 :c:func:`media_create_pad_link()` and remove with
126 :c:func:`media_entity_remove_links()`.
127
128 **2. interface to entity links**:
129
130 Associate one interface to a Link.
131
132 Drivers create interface to entity links by calling:
133 :c:func:`media_create_intf_link()` and remove with
134 :c:func:`media_remove_intf_links()`.
135
136 .. note::
137
138 Links can only be created after having both ends already created.
139
140 Links have flags that describe the link capabilities and state. The
141 valid values are described at :c:func:`media_create_pad_link()` and
142 :c:func:`media_create_intf_link()`.
143
144 Graph traversal
145 ^^^^^^^^^^^^^^^
146
147 The media framework provides APIs to traverse media graphs, locating connected
148 entities and links.
149
150 To iterate over all entities belonging to a media device, drivers can use
151 the media_device_for_each_entity macro, defined in
152 ``include/media/media-device.h``.
153
154 .. code-block:: c
155
156 struct media_entity *entity;
157
158 media_device_for_each_entity(entity, mdev) {
159 // entity will point to each entity in turn
160 ...
161 }
162
163 Helper functions can be used to find a link between two given pads, or a pad
164 connected to another pad through an enabled link
165 (:c:func:`media_entity_find_link()`, :c:func:`media_pad_remote_pad_first()`,
166 :c:func:`media_entity_remote_source_pad_unique()` and
167 :c:func:`media_pad_remote_pad_unique()`).
168
169 Use count and power handling
170 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
171
172 Due to the wide differences between drivers regarding power management
173 needs, the media controller does not implement power management. However,
174 the struct media_entity includes a ``use_count``
175 field that media drivers
176 can use to track the number of users of every entity for power management
177 needs.
178
179 The :c:type:`media_entity<media_entity>`.\ ``use_count`` field is owned by
180 media drivers and must not be
181 touched by entity drivers. Access to the field must be protected by the
182 :c:type:`media_device`.\ ``graph_mutex`` lock.
183
184 Links setup
185 ^^^^^^^^^^^
186
187 Link properties can be modified at runtime by calling
188 :c:func:`media_entity_setup_link()`.
189
190 Pipelines and media streams
191 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
192
193 A media stream is a stream of pixels or metadata originating from one or more
194 source devices (such as a sensors) and flowing through media entity pads
195 towards the final sinks. The stream can be modified on the route by the
196 devices (e.g. scaling or pixel format conversions), or it can be split into
197 multiple branches, or multiple branches can be merged.
198
199 A media pipeline is a set of media streams which are interdependent. This
200 interdependency can be caused by the hardware (e.g. configuration of a second
201 stream cannot be changed if the first stream has been enabled) or by the driver
202 due to the software design. Most commonly a media pipeline consists of a single
203 stream which does not branch.
204
205 When starting streaming, drivers must notify all entities in the pipeline to
206 prevent link states from being modified during streaming by calling
207 :c:func:`media_pipeline_start()`.
208
209 The function will mark all the pads which are part of the pipeline as streaming.
210
211 The struct media_pipeline instance pointed to by the pipe argument will be
212 stored in every pad in the pipeline. Drivers should embed the struct
213 media_pipeline in higher-level pipeline structures and can then access the
214 pipeline through the struct media_pad pipe field.
215
216 Calls to :c:func:`media_pipeline_start()` can be nested.
217 The pipeline pointer must be identical for all nested calls to the function.
218
219 :c:func:`media_pipeline_start()` may return an error. In that case,
220 it will clean up any of the changes it did by itself.
221
222 When stopping the stream, drivers must notify the entities with
223 :c:func:`media_pipeline_stop()`.
224
225 If multiple calls to :c:func:`media_pipeline_start()` have been
226 made the same number of :c:func:`media_pipeline_stop()` calls
227 are required to stop streaming.
228 The :c:type:`media_entity`.\ ``pipe`` field is reset to ``NULL`` on the last
229 nested stop call.
230
231 Link configuration will fail with ``-EBUSY`` by default if either end of the
232 link is a streaming entity. Links that can be modified while streaming must
233 be marked with the ``MEDIA_LNK_FL_DYNAMIC`` flag.
234
235 If other operations need to be disallowed on streaming entities (such as
236 changing entities configuration parameters) drivers can explicitly check the
237 media_entity stream_count field to find out if an entity is streaming. This
238 operation must be done with the media_device graph_mutex held.
239
240 Link validation
241 ^^^^^^^^^^^^^^^
242
243 Link validation is performed by :c:func:`media_pipeline_start()`
244 for any entity which has sink pads in the pipeline. The
245 :c:type:`media_entity`.\ ``link_validate()`` callback is used for that
246 purpose. In ``link_validate()`` callback, entity driver should check
247 that the properties of the source pad of the connected entity and its own
248 sink pad match. It is up to the type of the entity (and in the end, the
249 properties of the hardware) what matching actually means.
250
251 Subsystems should facilitate link validation by providing subsystem specific
252 helper functions to provide easy access for commonly needed information, and
253 in the end provide a way to use driver-specific callbacks.
254
255 Pipeline traversal
256 ^^^^^^^^^^^^^^^^^^
257
258 Once a pipeline has been constructed with :c:func:`media_pipeline_start()`,
259 drivers can iterate over entities or pads in the pipeline with the
260 :c:macro:´media_pipeline_for_each_entity` and
261 :c:macro:´media_pipeline_for_each_pad` macros. Iterating over pads is
262 straightforward:
263
264 .. code-block:: c
265
266 media_pipeline_pad_iter iter;
267 struct media_pad *pad;
268
269 media_pipeline_for_each_pad(pipe, &iter, pad) {
270 /* 'pad' will point to each pad in turn */
271 ...
272 }
273
274 To iterate over entities, the iterator needs to be initialized and cleaned up
275 as an additional steps:
276
277 .. code-block:: c
278
279 media_pipeline_entity_iter iter;
280 struct media_entity *entity;
281 int ret;
282
283 ret = media_pipeline_entity_iter_init(pipe, &iter);
284 if (ret)
285 ...;
286
287 media_pipeline_for_each_entity(pipe, &iter, entity) {
288 /* 'entity' will point to each entity in turn */
289 ...
290 }
291
292 media_pipeline_entity_iter_cleanup(&iter);
293
294 Media Controller Device Allocator API
295 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
296
297 When the media device belongs to more than one driver, the shared media
298 device is allocated with the shared struct device as the key for look ups.
299
300 The shared media device should stay in registered state until the last
301 driver unregisters it. In addition, the media device should be released when
302 all the references are released. Each driver gets a reference to the media
303 device during probe, when it allocates the media device. If media device is
304 already allocated, the allocate API bumps up the refcount and returns the
305 existing media device. The driver puts the reference back in its disconnect
306 routine when it calls :c:func:`media_device_delete()`.
307
308 The media device is unregistered and cleaned up from the kref put handler to
309 ensure that the media device stays in registered state until the last driver
310 unregisters the media device.
311
312 **Driver Usage**
313
314 Drivers should use the appropriate media-core routines to manage the shared
315 media device life-time handling the two states:
316 1. allocate -> register -> delete
317 2. get reference to already registered device -> delete
318
319 call :c:func:`media_device_delete()` routine to make sure the shared media
320 device delete is handled correctly.
321
322 **driver probe:**
323 Call :c:func:`media_device_usb_allocate()` to allocate or get a reference
324 Call :c:func:`media_device_register()`, if media devnode isn't registered
325
326 **driver disconnect:**
327 Call :c:func:`media_device_delete()` to free the media_device. Freeing is
328 handled by the kref put handler.
329
330 API Definitions
331 ^^^^^^^^^^^^^^^
332
333 .. kernel-doc:: include/media/media-device.h
334
335 .. kernel-doc:: include/media/media-devnode.h
336
337 .. kernel-doc:: include/media/media-entity.h
338
339 .. kernel-doc:: include/media/media-request.h
340
341 .. kernel-doc:: include/media/media-dev-allocator.h
342

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

Media Controller kernel 구현

1-12

이 `GPL-2.0` 문서는 Media Controller 장치와 media framework의 kernel 측 구현을 설명합니다. Media Controller userspace API는 `the Media Controller uAPI book <media_controller>`에 별도로 문서화되어 있습니다.

Media Controller 문서 계층
영역문서
Userspace API`Media Controller uAPI book <media_controller>`
Kernel 구현현재 `mc-core.rst` 문서

.. 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.

추상 media device graph

13-35

Media framework의 목표 가운데 하나는 장치 내부 topology를 발견하고 runtime에 구성하는 것입니다. 이를 위해 hardware device를 entity라는 building block과 이를 잇는 pad로 구성된 방향 graph로 모델링합니다.

Entity는 media hardware의 기본 building block입니다. CMOS sensor 같은 물리 장치, SoC image processing pipeline의 논리 block, DMA channel 또는 물리 connector 등 다양한 논리 단위에 대응할 수 있습니다.

Pad는 entity가 다른 entity와 상호작용하는 연결 endpoint입니다. Video에 한정되지 않는 data는 entity의 output에서 하나 이상의 entity input으로 흐릅니다. Pad는 chip 경계의 물리 pin과 다른 개념입니다.

Link는 같은 entity 또는 서로 다른 entity의 두 pad를 잇는 point-to-point 방향 연결입니다. Data는 source pad에서 sink pad로 흐릅니다.

Media graph 기본 모델
물리·논리 hardware blockEntity
Entity outputSource pad방향 linkSink pad다른 entity input
DataVideo에 한정되지 않음
PadChip의 물리 pin과 구별

Entity의 source pad와 sink pad를 방향 link로 연결해 data path를 표현합니다.

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 생명주기

36-55

Media device는 `include/media/media-device.h`에 정의된 `struct media_device` instance로 표현합니다. 구조체 할당은 media device driver가 담당하며 일반적으로 더 큰 driver 전용 구조체 안에 `media_device`를 embed합니다.

Driver는 `media_device_init()`로 instance를 초기화합니다. 초기화한 뒤 macro `media_device_register()`를 통해 `__media_device_register()`를 호출해 등록하고, `media_device_unregister()`로 등록을 해제합니다. 초기화한 instance는 마지막에 반드시 `media_device_cleanup()`으로 정리해야 합니다.

이전에 등록하지 않은 media device를 unregister하거나, 이전에 초기화하지 않은 media device를 cleanup하는 것은 허용되지 않습니다.

media_device 생명주기
Driver 전용 구조체에 embed 또는 할당`media_device_init()`
`media_device_register()``__media_device_register()`등록 상태
`media_device_unregister()``media_device_cleanup()`
금지미등록 instance unregister미초기화 instance cleanup

초기화·등록·해제·정리 순서를 지켜야 합니다.

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.

Entity, interface, pad

56-110

Entity는 `include/media/media-entity.h`의 `struct media_entity` instance로 표현합니다. 보통 `v4l2_subdev`나 `video_device` 같은 상위 구조체에 embed하지만 driver가 entity를 직접 할당할 수도 있습니다.

Driver는 `media_entity_pads_init()`로 entity pad를 초기화하고 `media_device_register_entity()`로 media device에 entity를 등록하며 `media_device_unregister_entity()`로 등록을 해제합니다.

Interface는 `include/media/media-entity.h`의 `struct media_interface` instance입니다. 현재 정의된 interface type은 device node 하나뿐이고 `struct media_intf_devnode`로 표현합니다. Driver는 `media_devnode_create()`로 초기화·생성하고 `media_devnode_remove()`로 제거합니다.

Pad는 `include/media/media-entity.h`의 `struct media_pad` instance입니다. 각 entity는 entity driver가 관리하는 pad 배열을 가지며, driver는 보통 이 배열을 전용 구조체에 embed합니다.

Pad는 소속 entity와 pad 배열의 0-based index로 식별합니다. 두 정보가 `struct media_pad`에 저장되므로 `struct media_pad` pointer가 link reference를 저장하고 전달하는 표준 방식입니다.

`MEDIA_PAD_FL_SINK`는 data를 받는 pad를, `MEDIA_PAD_FL_SOURCE`는 data를 내보내는 pad를 뜻합니다. 모든 pad에는 두 flag 가운데 정확히 하나만 설정해야 합니다.

Media graph object
Object구조체·header생성·등록 규칙
Entity`struct media_entity`, `media-entity.h``media_entity_pads_init()` 후 register/unregister
Device node interface`struct media_intf_devnode``media_devnode_create()` / `media_devnode_remove()`
Pad`struct media_pad`, entity + 0-based index`MEDIA_PAD_FL_SINK` 또는 `MEDIA_PAD_FL_SOURCE` 정확히 하나

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.

Media graph 순회

144-168

Media framework는 media graph를 순회하면서 연결된 entity와 link를 찾는 API를 제공합니다.

한 media device의 모든 entity를 반복하려면 `include/media/media-device.h`에 정의된 `media_device_for_each_entity` macro를 사용합니다. 예제에서 `entity`는 반복할 때마다 다음 entity를 가리킵니다.

`media_entity_find_link()`는 지정한 두 pad 사이의 link를 찾습니다. `media_pad_remote_pad_first()`, `media_entity_remote_source_pad_unique()`, `media_pad_remote_pad_unique()`는 enabled link를 통해 연결된 pad를 찾을 때 사용합니다.

Media graph 탐색 API
Media device`media_device_for_each_entity`모든 entity 순회
두 pad`media_entity_find_link()`Link 찾기
한 pad`media_pad_remote_pad_first()`첫 remote pad
유일 연결 요구`media_entity_remote_source_pad_unique()``media_pad_remote_pad_unique()`

전체 entity 순회와 pad·link의 직접 탐색 helper를 구분합니다.

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()`).

Media stream과 pipeline 생명주기

190-239

Media stream은 하나 이상의 sensor 같은 source device에서 시작하여 media entity pad를 지나 최종 sink로 흐르는 pixel 또는 metadata stream입니다. 경로의 장치는 scaling이나 pixel format 변환으로 stream을 수정할 수 있고, 여러 branch로 나누거나 여러 branch를 합칠 수도 있습니다.

Media pipeline은 서로 의존하는 media stream의 집합입니다. 두 번째 stream의 설정을 첫 번째 stream이 enabled인 동안 바꿀 수 없는 hardware 제약이나 driver software 설계 때문에 의존성이 생깁니다. 가장 흔한 pipeline은 branch가 없는 단일 stream입니다.

Streaming을 시작할 때 driver는 `media_pipeline_start()`를 호출하여 pipeline의 모든 entity에 알리고 streaming 중 link state가 바뀌지 않게 해야 합니다. 이 함수는 pipeline에 속한 모든 pad를 streaming 상태로 표시합니다.

`pipe` 인자가 가리키는 `struct media_pipeline` instance는 pipeline의 모든 pad에 저장됩니다. Driver는 이를 상위 pipeline 구조체에 embed하고 `struct media_pad`의 `pipe` 필드로 접근할 수 있습니다.

`media_pipeline_start()`는 중첩 호출할 수 있지만 모든 중첩 호출에서 pipeline pointer가 같아야 합니다. 함수가 오류를 반환하면 자신이 적용한 변경을 스스로 정리합니다.

Stream을 멈출 때는 `media_pipeline_stop()`으로 entity에 알려야 합니다. `start()`를 여러 번 호출했다면 streaming을 끝내기 위해 같은 횟수의 `stop()`을 호출해야 하며 마지막 nested stop에서 `media_entity.pipe`가 `NULL`로 reset됩니다.

기본적으로 link의 어느 한쪽 entity가 streaming 중이면 link 구성 변경은 `-EBUSY`로 실패합니다. Streaming 중 바꿀 수 있는 link는 `MEDIA_LNK_FL_DYNAMIC` flag로 표시해야 합니다.

Streaming entity에서 설정 parameter 변경 같은 다른 동작을 금지하려면 driver가 `media_entity.stream_count`를 명시적으로 확인할 수 있습니다. 이 검사는 `media_device.graph_mutex`를 잡은 상태에서 수행해야 합니다.

Media pipeline 시작·중첩·정지
`media_pipeline_start(pipe)`모든 pipeline pad를 streaming으로 표시각 pad에 동일 `pipe` 저장
Nested start항상 동일 pipeline pointer오류 시 자체 rollback
Streaming link 변경기본 `-EBUSY``MEDIA_LNK_FL_DYNAMIC`이면 허용
`stream_count` 검사`graph_mutex` 보유
동일 횟수 `media_pipeline_stop()`마지막 stop`pipe = NULL`

Start와 stop 횟수가 대칭이어야 하며 streaming 중 graph 변경은 기본적으로 차단됩니다.

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.

Pipeline link validation

240-254

`media_pipeline_start()`는 pipeline 안에서 sink pad를 가진 모든 entity에 대해 link validation을 수행합니다. 이때 `media_entity.link_validate()` callback을 사용합니다.

Entity driver의 `link_validate()`는 연결된 entity의 source pad 속성과 자기 sink pad 속성이 맞는지 검사해야 합니다. 무엇을 일치로 볼지는 entity type과 최종적으로 hardware 속성에 달려 있습니다.

Subsystem은 자주 필요한 정보에 쉽게 접근할 수 있는 전용 helper를 제공하고 마지막에는 driver 전용 callback을 사용할 방법을 제공하여 link validation을 지원해야 합니다.

Link validation 흐름
`media_pipeline_start()`Sink pad가 있는 각 entity
`media_entity.link_validate()`Remote source pad 속성 ↔ local sink pad 속성
Subsystem helper공통 정보 제공
Driver callbackHardware 전용 일치 조건

Pipeline start 시 source와 sink의 subsystem별 속성 호환성을 확인합니다.

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 entity와 pad 순회

255-293

`media_pipeline_start()`로 pipeline을 구성한 뒤에는 `media_pipeline_for_each_entity`와 `media_pipeline_for_each_pad` macro로 pipeline 안의 entity 또는 pad를 순회할 수 있습니다.

Pad 순회는 `media_pipeline_pad_iter`와 `struct media_pad *`를 선언한 뒤 `media_pipeline_for_each_pad(pipe, &iter, pad)`를 사용하면 됩니다. 반복할 때마다 `pad`가 다음 pad를 가리킵니다.

Entity 순회는 추가 초기화와 정리가 필요합니다. `media_pipeline_entity_iter_init(pipe, &iter)`의 반환값을 확인하고, 성공하면 `media_pipeline_for_each_entity()`로 순회한 뒤 `media_pipeline_entity_iter_cleanup(&iter)`를 호출합니다.

Pipeline iterator 비교
대상Iterator순회 macro추가 생명주기
Pad`media_pipeline_pad_iter``media_pipeline_for_each_pad`별도 init·cleanup 없음
Entity`media_pipeline_entity_iter``media_pipeline_for_each_entity``init()` 오류 확인 후 `cleanup()`

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

294-329

Media device가 둘 이상의 driver에 속하면 공유 `struct device`를 lookup key로 사용하여 shared media device를 할당합니다.

공유 media device는 마지막 driver가 unregister할 때까지 등록 상태를 유지하고 모든 reference가 해제되었을 때 release되어야 합니다. 각 driver는 probe 중 media device를 할당하면서 reference를 얻습니다. 이미 할당되어 있으면 allocate API가 refcount를 증가시키고 기존 media device를 반환합니다.

Driver는 disconnect routine에서 `media_device_delete()`를 호출해 reference를 돌려놓습니다. kref put handler가 unregister와 cleanup을 수행하므로 마지막 driver가 unregister할 때까지 media device의 등록 상태가 유지됩니다.

Driver가 처리할 생명주기는 새 장치의 `allocate → register → delete`와 이미 등록된 장치의 `reference 획득 → delete` 두 가지입니다. 공유 장치 삭제를 정확히 처리하려면 반드시 `media_device_delete()`를 사용해야 합니다.

Driver probe에서는 `media_device_usb_allocate()`로 새 장치를 할당하거나 reference를 얻고 media devnode가 등록되지 않았다면 `media_device_register()`를 호출합니다. Driver disconnect에서는 `media_device_delete()`를 호출하며 실제 free는 kref put handler가 처리합니다.

Shared media_device reference 생명주기
Driver probe`media_device_usb_allocate()`
새 장치AllocateDevnode 미등록 시 `media_device_register()`
기존 장치Refcount 증가등록된 instance 반환
각 driver disconnect`media_device_delete()`Reference 반환
마지막 kref putUnregisterCleanup·free

여러 driver가 공유하는 장치는 마지막 reference가 사라질 때 unregister·cleanup됩니다.

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.

Media Controller API 정의

330-341

Media Controller의 API 정의는 media device, devnode, entity, request, shared device allocator header의 kernel-doc에서 가져옵니다.

Media Controller kernel-doc source
Source path내용
`include/media/media-device.h`Media device
`include/media/media-devnode.h`Media device node
`include/media/media-entity.h`Entity·pad·link·interface
`include/media/media-request.h`Media request
`include/media/media-dev-allocator.h`Shared device allocator

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