← Documents Documentation/gpu/komeda-kms.rst GitHub 원문 ↗

Linux 6.18.37 · GPU·DRM

drm/komeda Arm display driver

Arm Komeda pipeline 구성요소와 DRM-KMS·atomic state 매핑을 다루는 전문 번역입니다.

Source pathDocumentation/gpu/komeda-kms.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

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

1. 요약·해설

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

요약·해설

komeda-kms.rst:1-488

Arm D71 이후 Komeda display hardware의 component pipeline과 이를 DRM-KMS Plane·writeback connector·CRTC에 원자적으로 매핑하는 설계를 설명합니다.

문서 핵심
영역핵심
HardwareLayer·Scaler·Compiz·Wb_layer·Improc·Timing controller
PipelineDual display와 master/slave single display mode
KMS mappingPlane·Wb_connector·Crtc가 sub-pipeline 사용
Atomic statedrm_private_obj/state로 component 배타 할당
Driver layerskomeda_dev·komeda_kms_dev·module wrapper

하드웨어 data flow에서 Linux module 경계까지의 구조입니다.

Komeda 설계 한눈에 보기
Memory → Layer/Scaler → CompizCompiz → display 또는 writeback outputPipeline/component → DRM private objectKMS plane/connector/crtc → sub-pipeline 사용자drm_atomic_state → validation·reservation·commit

Pixel 처리와 KMS resource 관리의 두 축입니다.

2. 영어 원문 전체

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

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2
3 ==============================
4 drm/komeda Arm display driver
5 ==============================
6
7 The drm/komeda driver supports the Arm display processor D71 and later products,
8 this document gives a brief overview of driver design: how it works and why
9 design it like that.
10
11 Overview of D71 like display IPs
12 ================================
13
14 From D71, Arm display IP begins to adopt a flexible and modularized
15 architecture. A display pipeline is made up of multiple individual and
16 functional pipeline stages called components, and every component has some
17 specific capabilities that can give the flowed pipeline pixel data a
18 particular processing.
19
20 Typical D71 components:
21
22 Layer
23 -----
24 Layer is the first pipeline stage, which prepares the pixel data for the next
25 stage. It fetches the pixel from memory, decodes it if it's AFBC, rotates the
26 source image, unpacks or converts YUV pixels to the device internal RGB pixels,
27 then adjusts the color_space of pixels if needed.
28
29 Scaler
30 ------
31 As its name suggests, scaler takes responsibility for scaling, and D71 also
32 supports image enhancements by scaler.
33 The usage of scaler is very flexible and can be connected to layer output
34 for layer scaling, or connected to compositor and scale the whole display
35 frame and then feed the output data into wb_layer which will then write it
36 into memory.
37
38 Compositor (compiz)
39 -------------------
40 Compositor blends multiple layers or pixel data flows into one single display
41 frame. its output frame can be fed into post image processor for showing it on
42 the monitor or fed into wb_layer and written to memory at the same time.
43 user can also insert a scaler between compositor and wb_layer to down scale
44 the display frame first and then write to memory.
45
46 Writeback Layer (wb_layer)
47 --------------------------
48 Writeback layer does the opposite things of Layer, which connects to compiz
49 and writes the composition result to memory.
50
51 Post image processor (improc)
52 -----------------------------
53 Post image processor adjusts frame data like gamma and color space to fit the
54 requirements of the monitor.
55
56 Timing controller (timing_ctrlr)
57 --------------------------------
58 Final stage of display pipeline, Timing controller is not for the pixel
59 handling, but only for controlling the display timing.
60
61 Merger
62 ------
63 D71 scaler mostly only has the half horizontal input/output capabilities
64 compared with Layer, like if Layer supports 4K input size, the scaler only can
65 support 2K input/output in the same time. To achieve the ful frame scaling, D71
66 introduces Layer Split, which splits the whole image to two half parts and feeds
67 them to two Layers A and B, and does the scaling independently. After scaling
68 the result need to be fed to merger to merge two part images together, and then
69 output merged result to compiz.
70
71 Splitter
72 --------
73 Similar to Layer Split, but Splitter is used for writeback, which splits the
74 compiz result to two parts and then feed them to two scalers.
75
76 Possible D71 Pipeline usage
77 ===========================
78
79 Benefitting from the modularized architecture, D71 pipelines can be easily
80 adjusted to fit different usages. And D71 has two pipelines, which support two
81 types of working mode:
82
83 - Dual display mode
84 Two pipelines work independently and separately to drive two display outputs.
85
86 - Single display mode
87 Two pipelines work together to drive only one display output.
88
89 On this mode, pipeline_B doesn't work independently, but outputs its
90 composition result into pipeline_A, and its pixel timing also derived from
91 pipeline_A.timing_ctrlr. The pipeline_B works just like a "slave" of
92 pipeline_A(master)
93
94 Single pipeline data flow
95 -------------------------
96
97 .. kernel-render:: DOT
98 :alt: Single pipeline digraph
99 :caption: Single pipeline data flow
100
101 digraph single_ppl {
102 rankdir=LR;
103
104 subgraph {
105 "Memory";
106 "Monitor";
107 }
108
109 subgraph cluster_pipeline {
110 style=dashed
111 node [shape=box]
112 {
113 node [bgcolor=grey style=dashed]
114 "Scaler-0";
115 "Scaler-1";
116 "Scaler-0/1"
117 }
118
119 node [bgcolor=grey style=filled]
120 "Layer-0" -> "Scaler-0"
121 "Layer-1" -> "Scaler-0"
122 "Layer-2" -> "Scaler-1"
123 "Layer-3" -> "Scaler-1"
124
125 "Layer-0" -> "Compiz"
126 "Layer-1" -> "Compiz"
127 "Layer-2" -> "Compiz"
128 "Layer-3" -> "Compiz"
129 "Scaler-0" -> "Compiz"
130 "Scaler-1" -> "Compiz"
131
132 "Compiz" -> "Scaler-0/1" -> "Wb_layer"
133 "Compiz" -> "Improc" -> "Timing Controller"
134 }
135
136 "Wb_layer" -> "Memory"
137 "Timing Controller" -> "Monitor"
138 }
139
140 Dual pipeline with Slave enabled
141 --------------------------------
142
143 .. kernel-render:: DOT
144 :alt: Slave pipeline digraph
145 :caption: Slave pipeline enabled data flow
146
147 digraph slave_ppl {
148 rankdir=LR;
149
150 subgraph {
151 "Memory";
152 "Monitor";
153 }
154 node [shape=box]
155 subgraph cluster_pipeline_slave {
156 style=dashed
157 label="Slave Pipeline_B"
158 node [shape=box]
159 {
160 node [bgcolor=grey style=dashed]
161 "Slave.Scaler-0";
162 "Slave.Scaler-1";
163 }
164
165 node [bgcolor=grey style=filled]
166 "Slave.Layer-0" -> "Slave.Scaler-0"
167 "Slave.Layer-1" -> "Slave.Scaler-0"
168 "Slave.Layer-2" -> "Slave.Scaler-1"
169 "Slave.Layer-3" -> "Slave.Scaler-1"
170
171 "Slave.Layer-0" -> "Slave.Compiz"
172 "Slave.Layer-1" -> "Slave.Compiz"
173 "Slave.Layer-2" -> "Slave.Compiz"
174 "Slave.Layer-3" -> "Slave.Compiz"
175 "Slave.Scaler-0" -> "Slave.Compiz"
176 "Slave.Scaler-1" -> "Slave.Compiz"
177 }
178
179 subgraph cluster_pipeline_master {
180 style=dashed
181 label="Master Pipeline_A"
182 node [shape=box]
183 {
184 node [bgcolor=grey style=dashed]
185 "Scaler-0";
186 "Scaler-1";
187 "Scaler-0/1"
188 }
189
190 node [bgcolor=grey style=filled]
191 "Layer-0" -> "Scaler-0"
192 "Layer-1" -> "Scaler-0"
193 "Layer-2" -> "Scaler-1"
194 "Layer-3" -> "Scaler-1"
195
196 "Slave.Compiz" -> "Compiz"
197 "Layer-0" -> "Compiz"
198 "Layer-1" -> "Compiz"
199 "Layer-2" -> "Compiz"
200 "Layer-3" -> "Compiz"
201 "Scaler-0" -> "Compiz"
202 "Scaler-1" -> "Compiz"
203
204 "Compiz" -> "Scaler-0/1" -> "Wb_layer"
205 "Compiz" -> "Improc" -> "Timing Controller"
206 }
207
208 "Wb_layer" -> "Memory"
209 "Timing Controller" -> "Monitor"
210 }
211
212 Sub-pipelines for input and output
213 ----------------------------------
214
215 A complete display pipeline can be easily divided into three sub-pipelines
216 according to the in/out usage.
217
218 Layer(input) pipeline
219 ~~~~~~~~~~~~~~~~~~~~~
220
221 .. kernel-render:: DOT
222 :alt: Layer data digraph
223 :caption: Layer (input) data flow
224
225 digraph layer_data_flow {
226 rankdir=LR;
227 node [shape=box]
228
229 {
230 node [bgcolor=grey style=dashed]
231 "Scaler-n";
232 }
233
234 "Layer-n" -> "Scaler-n" -> "Compiz"
235 }
236
237 .. kernel-render:: DOT
238 :alt: Layer Split digraph
239 :caption: Layer Split pipeline
240
241 digraph layer_data_flow {
242 rankdir=LR;
243 node [shape=box]
244
245 "Layer-0/1" -> "Scaler-0" -> "Merger"
246 "Layer-2/3" -> "Scaler-1" -> "Merger"
247 "Merger" -> "Compiz"
248 }
249
250 Writeback(output) pipeline
251 ~~~~~~~~~~~~~~~~~~~~~~~~~~
252 .. kernel-render:: DOT
253 :alt: writeback digraph
254 :caption: Writeback(output) data flow
255
256 digraph writeback_data_flow {
257 rankdir=LR;
258 node [shape=box]
259
260 {
261 node [bgcolor=grey style=dashed]
262 "Scaler-n";
263 }
264
265 "Compiz" -> "Scaler-n" -> "Wb_layer"
266 }
267
268 .. kernel-render:: DOT
269 :alt: split writeback digraph
270 :caption: Writeback(output) Split data flow
271
272 digraph writeback_data_flow {
273 rankdir=LR;
274 node [shape=box]
275
276 "Compiz" -> "Splitter"
277 "Splitter" -> "Scaler-0" -> "Merger"
278 "Splitter" -> "Scaler-1" -> "Merger"
279 "Merger" -> "Wb_layer"
280 }
281
282 Display output pipeline
283 ~~~~~~~~~~~~~~~~~~~~~~~
284 .. kernel-render:: DOT
285 :alt: display digraph
286 :caption: display output data flow
287
288 digraph single_ppl {
289 rankdir=LR;
290 node [shape=box]
291
292 "Compiz" -> "Improc" -> "Timing Controller"
293 }
294
295 In the following section we'll see these three sub-pipelines will be handled
296 by KMS-plane/wb_conn/crtc respectively.
297
298 Komeda Resource abstraction
299 ===========================
300
301 struct komeda_pipeline/component
302 --------------------------------
303
304 To fully utilize and easily access/configure the HW, the driver side also uses
305 a similar architecture: Pipeline/Component to describe the HW features and
306 capabilities, and a specific component includes two parts:
307
308 - Data flow controlling.
309 - Specific component capabilities and features.
310
311 So the driver defines a common header struct komeda_component to describe the
312 data flow control and all specific components are a subclass of this base
313 structure.
314
315 .. kernel-doc:: drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
316 :internal:
317
318 Resource discovery and initialization
319 =====================================
320
321 Pipeline and component are used to describe how to handle the pixel data. We
322 still need a @struct komeda_dev to describe the whole view of the device, and
323 the control-abilites of device.
324
325 We have &komeda_dev, &komeda_pipeline, &komeda_component. Now fill devices with
326 pipelines. Since komeda is not for D71 only but also intended for later products,
327 of course we’d better share as much as possible between different products. To
328 achieve this, split the komeda device into two layers: CORE and CHIP.
329
330 - CORE: for common features and capabilities handling.
331 - CHIP: for register programming and HW specific feature (limitation) handling.
332
333 CORE can access CHIP by three chip function structures:
334
335 - struct komeda_dev_funcs
336 - struct komeda_pipeline_funcs
337 - struct komeda_component_funcs
338
339 .. kernel-doc:: drivers/gpu/drm/arm/display/komeda/komeda_dev.h
340 :internal:
341
342 Format handling
343 ===============
344
345 .. kernel-doc:: drivers/gpu/drm/arm/display/komeda/komeda_format_caps.h
346 :internal:
347 .. kernel-doc:: drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.h
348 :internal:
349
350 Attach komeda_dev to DRM-KMS
351 ============================
352
353 Komeda abstracts resources by pipeline/component, but DRM-KMS uses
354 crtc/plane/connector. One KMS-obj cannot represent only one single component,
355 since the requirements of a single KMS object cannot simply be achieved by a
356 single component, usually that needs multiple components to fit the requirement.
357 Like set mode, gamma, ctm for KMS all target on CRTC-obj, but komeda needs
358 compiz, improc and timing_ctrlr to work together to fit these requirements.
359 And a KMS-Plane may require multiple komeda resources: layer/scaler/compiz.
360
361 So, one KMS-Obj represents a sub-pipeline of komeda resources.
362
363 - Plane: `Layer(input) pipeline`_
364 - Wb_connector: `Writeback(output) pipeline`_
365 - Crtc: `Display output pipeline`_
366
367 So, for komeda, we treat KMS crtc/plane/connector as users of pipeline and
368 component, and at any one time a pipeline/component only can be used by one
369 user. And pipeline/component will be treated as private object of DRM-KMS; the
370 state will be managed by drm_atomic_state as well.
371
372 How to map plane to Layer(input) pipeline
373 -----------------------------------------
374
375 Komeda has multiple Layer input pipelines, see:
376 - `Single pipeline data flow`_
377 - `Dual pipeline with Slave enabled`_
378
379 The easiest way is binding a plane to a fixed Layer pipeline, but consider the
380 komeda capabilities:
381
382 - Layer Split, See `Layer(input) pipeline`_
383
384 Layer_Split is quite complicated feature, which splits a big image into two
385 parts and handles it by two layers and two scalers individually. But it
386 imports an edge problem or effect in the middle of the image after the split.
387 To avoid such a problem, it needs a complicated Split calculation and some
388 special configurations to the layer and scaler. We'd better hide such HW
389 related complexity to user mode.
390
391 - Slave pipeline, See `Dual pipeline with Slave enabled`_
392
393 Since the compiz component doesn't output alpha value, the slave pipeline
394 only can be used for bottom layers composition. The komeda driver wants to
395 hide this limitation to the user. The way to do this is to pick a suitable
396 Layer according to plane_state->zpos.
397
398 So for komeda, the KMS-plane doesn't represent a fixed komeda layer pipeline,
399 but multiple Layers with same capabilities. Komeda will select one or more
400 Layers to fit the requirement of one KMS-plane.
401
402 Make component/pipeline to be drm_private_obj
403 ---------------------------------------------
404
405 Add :c:type:`drm_private_obj` to :c:type:`komeda_component`, :c:type:`komeda_pipeline`
406
407 .. code-block:: c
408
409 struct komeda_component {
410 struct drm_private_obj obj;
411 ...
412 }
413
414 struct komeda_pipeline {
415 struct drm_private_obj obj;
416 ...
417 }
418
419 Tracking component_state/pipeline_state by drm_atomic_state
420 -----------------------------------------------------------
421
422 Add :c:type:`drm_private_state` and user to :c:type:`komeda_component_state`,
423 :c:type:`komeda_pipeline_state`
424
425 .. code-block:: c
426
427 struct komeda_component_state {
428 struct drm_private_state obj;
429 void *binding_user;
430 ...
431 }
432
433 struct komeda_pipeline_state {
434 struct drm_private_state obj;
435 struct drm_crtc *crtc;
436 ...
437 }
438
439 komeda component validation
440 ---------------------------
441
442 Komeda has multiple types of components, but the process of validation are
443 similar, usually including the following steps:
444
445 .. code-block:: c
446
447 int komeda_xxxx_validate(struct komeda_component_xxx xxx_comp,
448 struct komeda_component_output *input_dflow,
449 struct drm_plane/crtc/connector *user,
450 struct drm_plane/crtc/connector_state, *user_state)
451 {
452 setup 1: check if component is needed, like the scaler is optional depending
453 on the user_state; if unneeded, just return, and the caller will
454 put the data flow into next stage.
455 Setup 2: check user_state with component features and capabilities to see
456 if requirements can be met; if not, return fail.
457 Setup 3: get component_state from drm_atomic_state, and try set to set
458 user to component; fail if component has been assigned to another
459 user already.
460 Setup 3: configure the component_state, like set its input component,
461 convert user_state to component specific state.
462 Setup 4: adjust the input_dflow and prepare it for the next stage.
463 }
464
465 komeda_kms Abstraction
466 ----------------------
467
468 .. kernel-doc:: drivers/gpu/drm/arm/display/komeda/komeda_kms.h
469 :internal:
470
471 komde_kms Functions
472 -------------------
473 .. kernel-doc:: drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
474 :internal:
475 .. kernel-doc:: drivers/gpu/drm/arm/display/komeda/komeda_plane.c
476 :internal:
477
478 Build komeda to be a Linux module driver
479 ========================================
480
481 Now we have two level devices:
482
483 - komeda_dev: describes the real display hardware.
484 - komeda_kms_dev: attaches or connects komeda_dev to DRM-KMS.
485
486 All komeda operations are supplied or operated by komeda_dev or komeda_kms_dev,
487 the module driver is only a simple wrapper to pass the Linux command
488 (probe/remove/pm) into komeda_dev or komeda_kms_dev.
489

3. 한국어 전문 번역

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

D71 계열 표시 IP와 구성요소

1-75

`drm/komeda` 드라이버는 Arm D71 표시 프로세서와 그 이후 제품을 지원합니다. 이 문서는 드라이버가 어떻게 동작하며, 왜 현재와 같은 구조로 설계되었는지를 개괄합니다. 원문의 SPDX 라이선스는 `GPL-2.0`입니다.

D71부터 Arm 표시 IP는 유연하고 모듈화된 구조를 채택합니다. 하나의 display pipeline은 component라고 부르는 독립적인 기능 단계 여러 개로 이루어지며, 각 component는 흐르는 pixel data에 특정 처리를 적용하는 고유 기능과 한계를 가집니다.

`Layer`는 첫 단계입니다. 메모리에서 pixel을 가져오고, AFBC이면 decode하며, source image를 회전하고, YUV pixel을 unpack하거나 장치 내부 RGB 형식으로 변환합니다. 필요하면 pixel의 `color_space`도 조정해 다음 단계가 사용할 데이터를 준비합니다.

`Scaler`는 크기 조절을 담당하고 D71에서는 image enhancement도 수행합니다. Layer 출력 뒤에 연결해 개별 layer를 확대·축소할 수 있고, compositor 뒤에 연결해 전체 display frame을 조절한 다음 `wb_layer`로 보내 메모리에 기록할 수도 있습니다.

`Compositor (compiz)`는 여러 layer 또는 pixel data flow를 하나의 display frame으로 합성합니다. 출력은 monitor 표시를 위해 `improc`로 보낼 수 있고, 동시에 `wb_layer`로 보내 메모리에 기록할 수도 있습니다. Compositor와 writeback 사이에 scaler를 넣으면 전체 frame을 축소한 뒤 기록할 수 있습니다.

`Writeback Layer (wb_layer)`는 Layer와 반대 방향으로 동작합니다. `compiz`에 연결하여 합성 결과를 메모리에 씁니다. `Post image processor (improc)`는 gamma와 color space 같은 frame 속성을 monitor 요구사항에 맞게 조정합니다. 마지막 단계인 `Timing controller (timing_ctrlr)`는 pixel 자체를 처리하지 않고 display timing만 제어합니다.

D71의 scaler는 보통 Layer의 절반 수준인 수평 입출력 폭만 처리합니다. 예를 들어 Layer가 4K 입력을 받더라도 scaler는 같은 시점에 2K만 처리할 수 있습니다. 전체 frame을 scale하기 위해 Layer Split이 이미지를 두 절반으로 나누고 Layer A/B와 두 scaler가 각각 처리한 뒤 `Merger`가 다시 결합해 `compiz`로 보냅니다. `Splitter`는 writeback 방향에서 같은 역할을 하며 `compiz` 결과를 둘로 나누어 두 scaler에 공급합니다.

D71 기본 pixel 처리 경로
Memory → Layer: fetch·AFBC decode·rotate·YUV/RGB 변환Layer → optional Scaler: layer scaling·image enhancementLayer/Scaler → Compiz: 여러 data flow 합성Compiz → Improc → Timing Controller → MonitorCompiz → optional Scaler → Wb_layer → Memory

구성요소가 입력 pixel을 표시 또는 메모리 출력으로 전달하는 기본 흐름입니다.

D71 구성요소
구성요소기능
Layer메모리 fetch, AFBC decode, 회전, pixel format·color space 변환
Scaler개별 layer 또는 합성 frame scaling과 image enhancement
Compiz여러 layer·pixel flow를 하나의 display frame으로 합성
Wb_layer합성 결과를 메모리에 기록
ImprocGamma·color space를 monitor 요구사항에 맞게 조정
Timing controller최종 display timing 제어
Merger분할 처리된 두 절반을 다시 결합
SplitterWriteback frame을 두 scaler 경로로 분할

각 component의 주된 책임과 연결 위치입니다.

.. SPDX-License-Identifier: GPL-2.0

==============================
 drm/komeda Arm display driver
==============================

The drm/komeda driver supports the Arm display processor D71 and later products,
this document gives a brief overview of driver design: how it works and why
design it like that.

Overview of D71 like display IPs
================================

From D71, Arm display IP begins to adopt a flexible and modularized
architecture. A display pipeline is made up of multiple individual and
functional pipeline stages called components, and every component has some
specific capabilities that can give the flowed pipeline pixel data a
particular processing.

Typical D71 components:

Layer
-----
Layer is the first pipeline stage, which prepares the pixel data for the next
stage. It fetches the pixel from memory, decodes it if it's AFBC, rotates the
source image, unpacks or converts YUV pixels to the device internal RGB pixels,
then adjusts the color_space of pixels if needed.

Scaler
------
As its name suggests, scaler takes responsibility for scaling, and D71 also
supports image enhancements by scaler.
The usage of scaler is very flexible and can be connected to layer output
for layer scaling, or connected to compositor and scale the whole display
frame and then feed the output data into wb_layer which will then write it
into memory.

Compositor (compiz)
-------------------
Compositor blends multiple layers or pixel data flows into one single display
frame. its output frame can be fed into post image processor for showing it on
the monitor or fed into wb_layer and written to memory at the same time.
user can also insert a scaler between compositor and wb_layer to down scale
the display frame first and then write to memory.

Writeback Layer (wb_layer)
--------------------------
Writeback layer does the opposite things of Layer, which connects to compiz
and writes the composition result to memory.

Post image processor (improc)
-----------------------------
Post image processor adjusts frame data like gamma and color space to fit the
requirements of the monitor.

Timing controller (timing_ctrlr)
--------------------------------
Final stage of display pipeline, Timing controller is not for the pixel
handling, but only for controlling the display timing.

Merger
------
D71 scaler mostly only has the half horizontal input/output capabilities
compared with Layer, like if Layer supports 4K input size, the scaler only can
support 2K input/output in the same time. To achieve the ful frame scaling, D71
introduces Layer Split, which splits the whole image to two half parts and feeds
them to two Layers A and B, and does the scaling independently. After scaling
the result need to be fed to merger to merge two part images together, and then
output merged result to compiz.

Splitter
--------
Similar to Layer Split, but Splitter is used for writeback, which splits the
compiz result to two parts and then feed them to two scalers.

D71 동작 모드와 단일 pipeline 흐름

76-140

모듈화 구조 덕분에 D71 pipeline은 사용 목적에 맞게 쉽게 조합할 수 있습니다. D71에는 두 pipeline이 있으며, 두 display 출력을 각각 구동하는 `Dual display mode`와 두 pipeline이 하나의 display 출력을 함께 구동하는 `Single display mode`를 지원합니다.

Single display mode에서 `pipeline_B`는 독립적으로 동작하지 않습니다. 합성 결과를 `pipeline_A`로 보내며 pixel timing도 `pipeline_A.timing_ctrlr`에서 파생됩니다. 따라서 `pipeline_B`는 master인 `pipeline_A`의 slave처럼 동작합니다.

단일 pipeline DOT 도식에서는 `Layer-0`부터 `Layer-3`까지가 직접 `Compiz`에 들어가거나 선택적으로 `Scaler-0/1`을 거쳐 들어갑니다. `Compiz` 출력은 표시 경로인 `Improc → Timing Controller → Monitor`와 writeback 경로인 `Scaler-0/1 → Wb_layer → Memory`로 나뉩니다. 회색 점선 scaler는 해당 연결이 선택적임을 나타냅니다.

D71의 두 동작 모드
모드pipeline 관계출력
Dual displayA와 B가 독립적으로 동작display output 2개
Single displayB가 A의 slave로 합성·timing을 공유display output 1개

두 pipeline의 독립성과 출력 수를 기준으로 비교합니다.

Single pipeline data flow
Memory → Layer-0/1/2/3Layer-0/1 → optional Scaler-0 → CompizLayer-2/3 → optional Scaler-1 → CompizCompiz → optional Scaler-0/1 → Wb_layer → MemoryCompiz → Improc → Timing Controller → Monitor

원문 DOT의 모든 처리 분기를 구조화한 흐름입니다.

Possible D71 Pipeline usage
===========================

Benefitting from the modularized architecture, D71 pipelines can be easily
adjusted to fit different usages. And D71 has two pipelines, which support two
types of working mode:

-   Dual display mode
    Two pipelines work independently and separately to drive two display outputs.

-   Single display mode
    Two pipelines work together to drive only one display output.

    On this mode, pipeline_B doesn't work independently, but outputs its
    composition result into pipeline_A, and its pixel timing also derived from
    pipeline_A.timing_ctrlr. The pipeline_B works just like a "slave" of
    pipeline_A(master)

Single pipeline data flow
-------------------------

.. kernel-render:: DOT
   :alt: Single pipeline digraph
   :caption: Single pipeline data flow

   digraph single_ppl {
      rankdir=LR;

      subgraph {
         "Memory";
         "Monitor";
      }

      subgraph cluster_pipeline {
          style=dashed
          node [shape=box]
          {
              node [bgcolor=grey style=dashed]
              "Scaler-0";
              "Scaler-1";
              "Scaler-0/1"
          }

         node [bgcolor=grey style=filled]
         "Layer-0" -> "Scaler-0"
         "Layer-1" -> "Scaler-0"
         "Layer-2" -> "Scaler-1"
         "Layer-3" -> "Scaler-1"

         "Layer-0" -> "Compiz"
         "Layer-1" -> "Compiz"
         "Layer-2" -> "Compiz"
         "Layer-3" -> "Compiz"
         "Scaler-0" -> "Compiz"
         "Scaler-1" -> "Compiz"

         "Compiz" -> "Scaler-0/1" -> "Wb_layer"
         "Compiz" -> "Improc" -> "Timing Controller"
      }

      "Wb_layer" -> "Memory"
      "Timing Controller" -> "Monitor"
   }

Dual pipeline with Slave enabled

Slave가 활성화된 이중 pipeline

141-212

Slave pipeline 도식은 `Slave Pipeline_B`와 `Master Pipeline_A`를 함께 보여 줍니다. Slave 쪽의 `Slave.Layer-0`부터 `Slave.Layer-3`까지는 직접 또는 `Slave.Scaler-0/1`을 거쳐 `Slave.Compiz`에 합성됩니다.

`Slave.Compiz` 결과는 Master의 `Compiz` 입력으로 들어갑니다. Master의 자체 Layer와 Scaler 출력도 같은 `Compiz`에 들어가므로, 최종 합성은 pipeline_A에서 이루어집니다. 이후 writeback은 `Scaler-0/1 → Wb_layer → Memory`, 표시는 `Improc → Timing Controller → Monitor` 경로를 따릅니다.

이 구조에서 pipeline_B는 별도 monitor를 구동하지 않고 하위 합성 결과만 master에 제공합니다. 최종 timing과 출력은 pipeline_A가 담당하므로, 두 pipeline을 사용하더라도 KMS 관점에서는 하나의 display output으로 보입니다.

Slave Pipeline_B → Master Pipeline_A
Slave Layer-0/1/2/3 → optional Slave Scaler-0/1Slave Layer/Scaler outputs → Slave.CompizSlave.Compiz → Master CompizMaster Layer-0/1/2/3·Scaler-0/1 → Master CompizMaster Compiz → writeback path 또는 display path

두 pipeline을 하나의 출력으로 결합하는 원문 DOT 흐름입니다.

Master·slave 책임
pipeline책임
pipeline_B (slave)자체 layer 처리와 하위 합성 결과 생성
pipeline_A (master)Slave 결과와 자체 layer의 최종 합성
pipeline_A timing_ctrlr최종 pixel timing과 monitor 출력 제어

Single display mode에서 각 pipeline이 맡는 범위입니다.

--------------------------------

.. kernel-render:: DOT
   :alt: Slave pipeline digraph
   :caption: Slave pipeline enabled data flow

   digraph slave_ppl {
      rankdir=LR;

      subgraph {
         "Memory";
         "Monitor";
      }
      node [shape=box]
      subgraph cluster_pipeline_slave {
          style=dashed
          label="Slave Pipeline_B"
          node [shape=box]
          {
              node [bgcolor=grey style=dashed]
              "Slave.Scaler-0";
              "Slave.Scaler-1";
          }

         node [bgcolor=grey style=filled]
         "Slave.Layer-0" -> "Slave.Scaler-0"
         "Slave.Layer-1" -> "Slave.Scaler-0"
         "Slave.Layer-2" -> "Slave.Scaler-1"
         "Slave.Layer-3" -> "Slave.Scaler-1"

         "Slave.Layer-0" -> "Slave.Compiz"
         "Slave.Layer-1" -> "Slave.Compiz"
         "Slave.Layer-2" -> "Slave.Compiz"
         "Slave.Layer-3" -> "Slave.Compiz"
         "Slave.Scaler-0" -> "Slave.Compiz"
         "Slave.Scaler-1" -> "Slave.Compiz"
      }

      subgraph cluster_pipeline_master {
          style=dashed
          label="Master Pipeline_A"
          node [shape=box]
          {
              node [bgcolor=grey style=dashed]
              "Scaler-0";
              "Scaler-1";
              "Scaler-0/1"
          }

         node [bgcolor=grey style=filled]
         "Layer-0" -> "Scaler-0"
         "Layer-1" -> "Scaler-0"
         "Layer-2" -> "Scaler-1"
         "Layer-3" -> "Scaler-1"

         "Slave.Compiz" -> "Compiz"
         "Layer-0" -> "Compiz"
         "Layer-1" -> "Compiz"
         "Layer-2" -> "Compiz"
         "Layer-3" -> "Compiz"
         "Scaler-0" -> "Compiz"
         "Scaler-1" -> "Compiz"

         "Compiz" -> "Scaler-0/1" -> "Wb_layer"
         "Compiz" -> "Improc" -> "Timing Controller"
      }

      "Wb_layer" -> "Memory"
      "Timing Controller" -> "Monitor"
   }

Sub-pipelines for input and output

입력·writeback·display 출력 sub-pipeline

213-297

완전한 display pipeline은 입출력 용도에 따라 세 sub-pipeline으로 나눌 수 있습니다. 뒤의 KMS 연결에서는 이 세 경로를 각각 KMS plane, writeback connector(`wb_conn`), CRTC가 담당합니다.

`Layer(input) pipeline`의 일반 경로는 `Layer-n → optional Scaler-n → Compiz`입니다. 큰 이미지를 분할하는 경로에서는 `Layer-0/1 → Scaler-0`과 `Layer-2/3 → Scaler-1`이 병렬로 처리되고, 두 결과가 `Merger → Compiz` 순서로 합쳐집니다.

`Writeback(output) pipeline`의 일반 경로는 `Compiz → optional Scaler-n → Wb_layer`입니다. 분할 writeback에서는 `Compiz → Splitter` 뒤에 `Scaler-0`과 `Scaler-1`이 병렬로 놓이고, `Merger`가 두 결과를 합쳐 `Wb_layer`로 보냅니다.

`Display output pipeline`은 `Compiz → Improc → Timing Controller`로 이어집니다. Improc가 화면 특성에 맞게 frame을 보정하고 Timing Controller가 출력 timing을 생성합니다.

세 sub-pipeline과 KMS 객체
sub-pipeline경로KMS 사용자
Layer inputLayer → optional Scaler → CompizPlane
Layer Split input두 Layer·Scaler → Merger → CompizPlane
Writeback outputCompiz → optional Scaler → Wb_layerWb_connector
Split writebackCompiz → Splitter → 두 Scaler → Merger → Wb_layerWb_connector
Display outputCompiz → Improc → Timing ControllerCrtc

Komeda data flow를 KMS 객체 역할에 대응시킵니다.

Layer input data flow
Layer-noptional Scaler-nCompiz

일반 입력 경로입니다.

Layer Split pipeline
Layer-0/1 → Scaler-0Layer-2/3 → Scaler-1두 scaler output → Merger → Compiz

수평 폭 한계를 넘는 입력의 병렬 처리 경로입니다.

Writeback output data flow
Compizoptional Scaler-nWb_layer → Memory

일반 writeback 경로입니다.

Split writeback data flow
Compiz → SplitterSplitter → Scaler-0 및 Scaler-1두 scaler output → Merger → Wb_layer

두 scaler를 사용하는 writeback 경로입니다.

Display output data flow
CompizImprocTiming Controller → Monitor

Monitor 출력으로 이어지는 최종 경로입니다.

----------------------------------

A complete display pipeline can be easily divided into three sub-pipelines
according to the in/out usage.

Layer(input) pipeline
~~~~~~~~~~~~~~~~~~~~~

.. kernel-render:: DOT
   :alt: Layer data digraph
   :caption: Layer (input) data flow

   digraph layer_data_flow {
      rankdir=LR;
      node [shape=box]

      {
         node [bgcolor=grey style=dashed]
           "Scaler-n";
      }

      "Layer-n" -> "Scaler-n" -> "Compiz"
   }

.. kernel-render:: DOT
   :alt: Layer Split digraph
   :caption: Layer Split pipeline

   digraph layer_data_flow {
      rankdir=LR;
      node [shape=box]

      "Layer-0/1" -> "Scaler-0" -> "Merger"
      "Layer-2/3" -> "Scaler-1" -> "Merger"
      "Merger" -> "Compiz"
   }

Writeback(output) pipeline
~~~~~~~~~~~~~~~~~~~~~~~~~~
.. kernel-render:: DOT
   :alt: writeback digraph
   :caption: Writeback(output) data flow

   digraph writeback_data_flow {
      rankdir=LR;
      node [shape=box]

      {
         node [bgcolor=grey style=dashed]
           "Scaler-n";
      }

      "Compiz" -> "Scaler-n" -> "Wb_layer"
   }

.. kernel-render:: DOT
   :alt: split writeback digraph
   :caption: Writeback(output) Split data flow

   digraph writeback_data_flow {
      rankdir=LR;
      node [shape=box]

      "Compiz" -> "Splitter"
      "Splitter" -> "Scaler-0" -> "Merger"
      "Splitter" -> "Scaler-1" -> "Merger"
      "Merger" -> "Wb_layer"
   }

Display output pipeline
~~~~~~~~~~~~~~~~~~~~~~~
.. kernel-render:: DOT
   :alt: display digraph
   :caption: display output data flow

   digraph single_ppl {
      rankdir=LR;
      node [shape=box]

      "Compiz" -> "Improc" -> "Timing Controller"
   }

In the following section we'll see these three sub-pipelines will be handled
by KMS-plane/wb_conn/crtc respectively.

Komeda 리소스 추상화·발견·format 처리

298-350

하드웨어를 충분히 활용하고 쉽게 접근·설정하기 위해 드라이버도 하드웨어와 같은 `Pipeline/Component` 구조를 사용합니다. 각 component는 data flow 제어와 해당 component 고유의 capability·feature라는 두 부분을 포함합니다.

공통 header 구조체 `struct komeda_component`가 data flow 제어를 기술하고, 구체적인 component는 이 base structure의 subclass가 됩니다. 내부 API 문서는 `drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h`에서 생성합니다.

Pipeline과 component가 pixel data 처리 방법을 나타낸다면, `struct komeda_dev`는 장치 전체 모습과 장치 수준의 제어 능력을 나타냅니다. `komeda_dev`에 pipeline을 채우되 D71 이후 제품 간 코드를 최대한 공유하도록 장치를 `CORE`와 `CHIP` 두 계층으로 나눕니다.

`CORE`는 공통 feature와 capability 처리를 맡고, `CHIP`은 register programming과 하드웨어별 feature·limitation을 처리합니다. CORE는 `struct komeda_dev_funcs`, `struct komeda_pipeline_funcs`, `struct komeda_component_funcs`라는 세 chip function structure를 통해 CHIP에 접근합니다. 장치 내부 API는 `komeda_dev.h`에서 생성합니다.

Format capability와 framebuffer 처리는 각각 `drivers/gpu/drm/arm/display/komeda/komeda_format_caps.h`와 `drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.h`의 내부 `kernel-doc`에서 가져옵니다.

Komeda 리소스 추상화
komeda_dev: 장치 전체 view·control capabilitykomeda_pipeline: pixel data 처리 경로komeda_component base: 공통 data flow control구체 component subclass: 고유 capability·featureCORE function tables → CHIP register·limitation 구현

하드웨어 구성요소에서 제품별 구현으로 내려가는 계층입니다.

CORE와 CHIP 경계
계층책임접점
CORE공통 feature·capability 처리dev/pipeline/component funcs 호출
CHIPRegister programming, HW별 feature·limitation세 chip function structure 구현
FormatFormat capability와 framebufferkomeda_format_caps.h·komeda_framebuffer.h

공통 정책과 제품별 프로그래밍의 분리입니다.

Komeda Resource abstraction
===========================

struct komeda_pipeline/component
--------------------------------

To fully utilize and easily access/configure the HW, the driver side also uses
a similar architecture: Pipeline/Component to describe the HW features and
capabilities, and a specific component includes two parts:

-  Data flow controlling.
-  Specific component capabilities and features.

So the driver defines a common header struct komeda_component to describe the
data flow control and all specific components are a subclass of this base
structure.

.. kernel-doc:: drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
   :internal:

Resource discovery and initialization
=====================================

Pipeline and component are used to describe how to handle the pixel data. We
still need a @struct komeda_dev to describe the whole view of the device, and
the control-abilites of device.

We have &komeda_dev, &komeda_pipeline, &komeda_component. Now fill devices with
pipelines. Since komeda is not for D71 only but also intended for later products,
of course we’d better share as much as possible between different products. To
achieve this, split the komeda device into two layers: CORE and CHIP.

-   CORE: for common features and capabilities handling.
-   CHIP: for register programming and HW specific feature (limitation) handling.

CORE can access CHIP by three chip function structures:

-   struct komeda_dev_funcs
-   struct komeda_pipeline_funcs
-   struct komeda_component_funcs

.. kernel-doc:: drivers/gpu/drm/arm/display/komeda/komeda_dev.h
   :internal:

Format handling
===============

.. kernel-doc:: drivers/gpu/drm/arm/display/komeda/komeda_format_caps.h
   :internal:
.. kernel-doc:: drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.h
   :internal:

Attach komeda_dev to DRM-KMS

komeda_dev를 DRM-KMS에 연결

351-401

Komeda는 리소스를 pipeline/component로 추상화하지만 DRM-KMS는 `crtc/plane/connector` 객체를 사용합니다. KMS 객체 하나의 요구사항은 component 하나만으로 충족되지 않는 경우가 많습니다. 예를 들어 CRTC의 mode, gamma, CTM 설정에는 `compiz`, `improc`, `timing_ctrlr`가 함께 필요하고, KMS Plane도 `layer/scaler/compiz` 여러 리소스를 요구할 수 있습니다.

따라서 KMS 객체 하나는 Komeda 리소스의 sub-pipeline 하나를 나타냅니다. Plane은 `Layer(input) pipeline`, `Wb_connector`는 `Writeback(output) pipeline`, Crtc는 `Display output pipeline`의 사용자입니다.

Komeda는 KMS `crtc/plane/connector`를 pipeline과 component의 사용자로 취급합니다. 한 시점에 pipeline/component는 사용자 하나에게만 할당할 수 있습니다. 이 리소스들을 DRM-KMS의 private object로 취급하고, 상태도 `drm_atomic_state`가 함께 관리합니다.

Plane을 고정 Layer pipeline에 묶는 방식은 단순하지만 Layer Split과 slave pipeline의 제약을 userspace에 노출합니다. Layer Split은 큰 이미지를 두 Layer와 두 scaler로 처리하면서 중앙 경계 artifact를 피하기 위한 복잡한 split 계산과 특수 설정이 필요하므로 드라이버가 숨겨야 합니다.

또한 `compiz`가 alpha 값을 출력하지 않으므로 slave pipeline은 bottom layer 합성에만 사용할 수 있습니다. 드라이버는 `plane_state->zpos`에 따라 적절한 Layer를 선택하여 이 한계를 userspace에서 감춥니다.

결국 KMS Plane은 고정된 Komeda layer pipeline 하나가 아니라 같은 capability를 가진 여러 Layer를 대표합니다. Komeda는 Plane 하나의 요구사항을 충족하도록 실행 시점에 Layer 하나 이상을 선택합니다.

KMS 객체와 Komeda sub-pipeline
KMS 객체Komeda 경로대표 component
PlaneLayer input pipelineLayer·Scaler·Compiz
Wb_connectorWriteback output pipelineCompiz·Scaler·Wb_layer
CrtcDisplay output pipelineCompiz·Improc·Timing_ctrlr

하나의 KMS 객체가 여러 component 조합을 대표합니다.

Plane의 동적 Layer 선택
KMS plane_state 요구사항과 zpos 확인Layer Split 필요성과 중앙 경계 보정 계산Slave pipeline은 bottom layer에만 후보로 사용동일 capability를 가진 Layer 하나 이상 선택선택한 component를 해당 KMS 사용자에게 원자적으로 예약

하드웨어 제약을 userspace에 노출하지 않는 매핑 절차입니다.

============================

Komeda abstracts resources by pipeline/component, but DRM-KMS uses
crtc/plane/connector. One KMS-obj cannot represent only one single component,
since the requirements of a single KMS object cannot simply be achieved by a
single component, usually that needs multiple components to fit the requirement.
Like set mode, gamma, ctm for KMS all target on CRTC-obj, but komeda needs
compiz, improc and timing_ctrlr to work together to fit these requirements.
And a KMS-Plane may require multiple komeda resources: layer/scaler/compiz.

So, one KMS-Obj represents a sub-pipeline of komeda resources.

-   Plane: `Layer(input) pipeline`_
-   Wb_connector: `Writeback(output) pipeline`_
-   Crtc: `Display output pipeline`_

So, for komeda, we treat KMS crtc/plane/connector as users of pipeline and
component, and at any one time a pipeline/component only can be used by one
user. And pipeline/component will be treated as private object of DRM-KMS; the
state will be managed by drm_atomic_state as well.

How to map plane to Layer(input) pipeline
-----------------------------------------

Komeda has multiple Layer input pipelines, see:
-   `Single pipeline data flow`_
-   `Dual pipeline with Slave enabled`_

The easiest way is binding a plane to a fixed Layer pipeline, but consider the
komeda capabilities:

-   Layer Split, See `Layer(input) pipeline`_

    Layer_Split is quite complicated feature, which splits a big image into two
    parts and handles it by two layers and two scalers individually. But it
    imports an edge problem or effect in the middle of the image after the split.
    To avoid such a problem, it needs a complicated Split calculation and some
    special configurations to the layer and scaler. We'd better hide such HW
    related complexity to user mode.

-   Slave pipeline, See `Dual pipeline with Slave enabled`_

    Since the compiz component doesn't output alpha value, the slave pipeline
    only can be used for bottom layers composition. The komeda driver wants to
    hide this limitation to the user. The way to do this is to pick a suitable
    Layer according to plane_state->zpos.

So for komeda, the KMS-plane doesn't represent a fixed komeda layer pipeline,
but multiple Layers with same capabilities. Komeda will select one or more
Layers to fit the requirement of one KMS-plane.

DRM private object와 atomic state 추적

402-438

Component와 pipeline을 DRM atomic state에 포함하기 위해 `komeda_component`와 `komeda_pipeline`에 `struct drm_private_obj obj`를 추가합니다. 이 객체는 일반 KMS 객체 밖에 있는 driver-private 리소스도 atomic transaction의 일부로 관리하게 합니다.

상태 구조체에는 `struct drm_private_state obj`와 사용자를 기록합니다. `komeda_component_state`의 `void *binding_user`는 component를 현재 점유한 사용자를 나타내고, `komeda_pipeline_state`의 `struct drm_crtc *crtc`는 pipeline이 연결된 CRTC를 나타냅니다.

원문의 두 C 코드 블록은 구조체 배치를 그대로 제시합니다. `drm_private_obj`와 `drm_private_state`를 통해 component/pipeline 상태의 duplicate·swap·rollback이 `drm_atomic_state` 수명 주기와 함께 이루어집니다.

Private object/state 필드
구조체필드의미
komeda_componentstruct drm_private_obj objComponent를 DRM private object로 등록
komeda_pipelinestruct drm_private_obj objPipeline을 DRM private object로 등록
komeda_component_statestruct drm_private_state objComponent atomic state
komeda_component_statevoid *binding_user현재 component 사용자
komeda_pipeline_statestruct drm_crtc *crtcPipeline을 사용하는 CRTC

리소스와 transaction 상태의 연결점입니다.

Atomic state 관리
drm_atomic_state에서 private state 획득component/pipeline의 기존 binding 확인새 KMS 사용자에게 임시 할당전체 validation 성공 시 state commit실패 시 private state를 포함해 rollback

KMS 사용자와 Komeda private resource를 한 transaction으로 묶습니다.

Make component/pipeline to be drm_private_obj
---------------------------------------------

Add :c:type:`drm_private_obj` to :c:type:`komeda_component`, :c:type:`komeda_pipeline`

.. code-block:: c

    struct komeda_component {
        struct drm_private_obj obj;
        ...
    }

    struct komeda_pipeline {
        struct drm_private_obj obj;
        ...
    }

Tracking component_state/pipeline_state by drm_atomic_state
-----------------------------------------------------------

Add :c:type:`drm_private_state` and user to :c:type:`komeda_component_state`,
:c:type:`komeda_pipeline_state`

.. code-block:: c

    struct komeda_component_state {
        struct drm_private_state obj;
        void *binding_user;
        ...
    }

    struct komeda_pipeline_state {
        struct drm_private_state obj;
        struct drm_crtc *crtc;
        ...
    }

Component validation과 komeda_kms API

439-477

Komeda에는 여러 종류의 component가 있지만 validation 절차는 공통적입니다. 예시 `komeda_xxxx_validate()`는 component, 입력 data flow, `drm_plane/crtc/connector` 사용자와 해당 user state를 받습니다.

먼저 component가 필요한지 확인합니다. Scaler처럼 user state에 따라 선택적인 component가 필요 없으면 즉시 반환하고 caller가 data flow를 다음 단계로 전달합니다. 필요하다면 user state 요구사항을 component feature·capability와 비교하여 충족할 수 없는 경우 실패합니다.

그다음 `drm_atomic_state`에서 component state를 가져와 사용자를 할당합니다. 이미 다른 사용자가 점유했다면 실패합니다. 할당에 성공하면 입력 component를 기록하고 user state를 component 고유 state로 변환한 뒤, `input_dflow`를 다음 단계가 사용할 형태로 조정합니다.

원문 pseudocode에는 `Setup 3` 번호가 두 번 등장하지만 의미상 첫 번째는 사용자 예약, 두 번째는 component state 설정입니다. 원문의 번호와 코드는 변경하지 않고 보존합니다.

Komeda KMS 추상화의 내부 문서는 `drivers/gpu/drm/arm/display/komeda/komeda_kms.h`에서, CRTC와 Plane 함수 문서는 각각 `komeda_crtc.c`, `komeda_plane.c`에서 생성합니다. 원문 제목의 `komde_kms Functions` 철자도 source block에 그대로 보존됩니다.

komeda component validation
1. Component 필요 여부 확인; 불필요하면 다음 stage로 bypass2. User state와 component feature·capability 비교3. drm_atomic_state에서 component_state 획득4. 다른 binding_user가 없는지 확인하고 사용자 예약5. Input component·component-specific state 설정6. input_dflow를 다음 stage용으로 조정

원문 pseudocode의 검증·예약·설정 순서입니다.

Komeda KMS 내부 문서
경로범위
drivers/gpu/drm/arm/display/komeda/komeda_kms.hkomeda_kms abstraction
drivers/gpu/drm/arm/display/komeda/komeda_crtc.cCRTC functions
drivers/gpu/drm/arm/display/komeda/komeda_plane.cPlane functions

kernel-doc이 추출하는 abstraction과 함수 구현입니다.

komeda component validation
---------------------------

Komeda has multiple types of components, but the process of validation are
similar, usually including the following steps:

.. code-block:: c

    int komeda_xxxx_validate(struct komeda_component_xxx xxx_comp,
                struct komeda_component_output *input_dflow,
                struct drm_plane/crtc/connector *user,
                struct drm_plane/crtc/connector_state, *user_state)
    {
         setup 1: check if component is needed, like the scaler is optional depending
                  on the user_state; if unneeded, just return, and the caller will
                  put the data flow into next stage.
         Setup 2: check user_state with component features and capabilities to see
                  if requirements can be met; if not, return fail.
         Setup 3: get component_state from drm_atomic_state, and try set to set
                  user to component; fail if component has been assigned to another
                  user already.
         Setup 3: configure the component_state, like set its input component,
                  convert user_state to component specific state.
         Setup 4: adjust the input_dflow and prepare it for the next stage.
    }

komeda_kms Abstraction
----------------------

.. kernel-doc:: drivers/gpu/drm/arm/display/komeda/komeda_kms.h
   :internal:

komde_kms Functions
-------------------
.. kernel-doc:: drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
   :internal:
.. kernel-doc:: drivers/gpu/drm/arm/display/komeda/komeda_plane.c
   :internal:

Linux module driver 계층

478-488

최종 구조에는 두 수준의 device가 있습니다. `komeda_dev`는 실제 display hardware를 기술하고, `komeda_kms_dev`는 `komeda_dev`를 DRM-KMS에 연결합니다.

모든 Komeda 동작은 `komeda_dev` 또는 `komeda_kms_dev`가 제공하거나 수행합니다. Linux module driver 자체는 `probe/remove/pm` 명령을 두 device 계층으로 전달하는 단순한 wrapper입니다.

Linux 명령 전달 경로
Linux driver core: probe·remove·pmKomeda module wrapperkomeda_kms_dev: DRM-KMS 연결과 KMS 객체 관리komeda_dev: 실제 display hardware 제어

Module wrapper와 두 device abstraction의 역할 분리입니다.

두 device 수준
device책임
komeda_dev실제 display hardware와 pipeline/component 제어
komeda_kms_devkomeda_dev를 DRM-KMS crtc/plane/connector에 연결
module driverLinux probe/remove/pm 명령 전달

하드웨어 표현과 KMS 연결을 분리합니다.

Build komeda to be a Linux module driver
========================================

Now we have two level devices:

-   komeda_dev: describes the real display hardware.
-   komeda_kms_dev: attaches or connects komeda_dev to DRM-KMS.

All komeda operations are supplied or operated by komeda_dev or komeda_kms_dev,
the module driver is only a simple wrapper to pass the Linux command
(probe/remove/pm) into komeda_dev or komeda_kms_dev.