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

Linux 6.18.37 · Driver API

CEC Kernel Support

HDMI CEC adapter의 allocate·register lifecycle, low/high-level callback, transmit status, error injection과 address framework를 설명합니다.

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

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

1. 요약·해설

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

요약과 해설

cec-core.rst:1-502

CEC core는 다양한 HDMI CEC hardware를 `cec_adapter` lifecycle과 `cec_adap_ops`로 통합합니다. Low-level callback은 `adap->lock` 아래 hardware를 제어하고, high-level callback은 lock 없이 protocol policy를 처리합니다.

Driver는 TX completion을 RX보다 먼저 보고하고 hardware를 다음 송신 가능 상태로 만든 뒤 completion API를 호출해야 합니다. Physical address validity가 adapter enable과 logical address claim을 제어하며, error injection·pin·notifier framework가 진단과 별도 hardware 구성을 지원합니다.

2. 영어 원문 전체

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

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2
3 CEC Kernel Support
4 ==================
5
6 The CEC framework provides a unified kernel interface for use with HDMI CEC
7 hardware. It is designed to handle a multiple types of hardware (receivers,
8 transmitters, USB dongles). The framework also gives the option to decide
9 what to do in the kernel driver and what should be handled by userspace
10 applications. In addition it integrates the remote control passthrough
11 feature into the kernel's remote control framework.
12
13
14 The CEC Protocol
15 ----------------
16
17 The CEC protocol enables consumer electronic devices to communicate with each
18 other through the HDMI connection. The protocol uses logical addresses in the
19 communication. The logical address is strictly connected with the functionality
20 provided by the device. The TV acting as the communication hub is always
21 assigned address 0. The physical address is determined by the physical
22 connection between devices.
23
24 The CEC framework described here is up to date with the CEC 2.0 specification.
25 It is documented in the HDMI 1.4 specification with the new 2.0 bits documented
26 in the HDMI 2.0 specification. But for most of the features the freely available
27 HDMI 1.3a specification is sufficient:
28
29 https://www.hdmi.org/spec/index
30
31
32 CEC Adapter Interface
33 ---------------------
34
35 The struct cec_adapter represents the CEC adapter hardware. It is created by
36 calling cec_allocate_adapter() and deleted by calling cec_delete_adapter():
37
38 .. c:function::
39 struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, \
40 void *priv, const char *name, \
41 u32 caps, u8 available_las);
42
43 .. c:function::
44 void cec_delete_adapter(struct cec_adapter *adap);
45
46 To create an adapter you need to pass the following information:
47
48 ops:
49 adapter operations which are called by the CEC framework and that you
50 have to implement.
51
52 priv:
53 will be stored in adap->priv and can be used by the adapter ops.
54 Use cec_get_drvdata(adap) to get the priv pointer.
55
56 name:
57 the name of the CEC adapter. Note: this name will be copied.
58
59 caps:
60 capabilities of the CEC adapter. These capabilities determine the
61 capabilities of the hardware and which parts are to be handled
62 by userspace and which parts are handled by kernelspace. The
63 capabilities are returned by CEC_ADAP_G_CAPS.
64
65 available_las:
66 the number of simultaneous logical addresses that this
67 adapter can handle. Must be 1 <= available_las <= CEC_MAX_LOG_ADDRS.
68
69 To obtain the priv pointer use this helper function:
70
71 .. c:function::
72 void *cec_get_drvdata(const struct cec_adapter *adap);
73
74 To register the /dev/cecX device node and the remote control device (if
75 CEC_CAP_RC is set) you call:
76
77 .. c:function::
78 int cec_register_adapter(struct cec_adapter *adap, \
79 struct device *parent);
80
81 where parent is the parent device.
82
83 To unregister the devices call:
84
85 .. c:function::
86 void cec_unregister_adapter(struct cec_adapter *adap);
87
88 Note: if cec_register_adapter() fails, then call cec_delete_adapter() to
89 clean up. But if cec_register_adapter() succeeded, then only call
90 cec_unregister_adapter() to clean up, never cec_delete_adapter(). The
91 unregister function will delete the adapter automatically once the last user
92 of that /dev/cecX device has closed its file handle.
93
94
95 Implementing the Low-Level CEC Adapter
96 --------------------------------------
97
98 The following low-level adapter operations have to be implemented in
99 your driver:
100
101 .. c:struct:: cec_adap_ops
102
103 .. code-block:: none
104
105 struct cec_adap_ops
106 {
107 /* Low-level callbacks */
108 int (*adap_enable)(struct cec_adapter *adap, bool enable);
109 int (*adap_monitor_all_enable)(struct cec_adapter *adap, bool enable);
110 int (*adap_monitor_pin_enable)(struct cec_adapter *adap, bool enable);
111 int (*adap_log_addr)(struct cec_adapter *adap, u8 logical_addr);
112 void (*adap_unconfigured)(struct cec_adapter *adap);
113 int (*adap_transmit)(struct cec_adapter *adap, u8 attempts,
114 u32 signal_free_time, struct cec_msg *msg);
115 void (*adap_nb_transmit_canceled)(struct cec_adapter *adap,
116 const struct cec_msg *msg);
117 void (*adap_status)(struct cec_adapter *adap, struct seq_file *file);
118 void (*adap_free)(struct cec_adapter *adap);
119
120 /* Error injection callbacks */
121 ...
122
123 /* High-level callback */
124 ...
125 };
126
127 These low-level ops deal with various aspects of controlling the CEC adapter
128 hardware. They are all called with the mutex adap->lock held.
129
130
131 To enable/disable the hardware::
132
133 int (*adap_enable)(struct cec_adapter *adap, bool enable);
134
135 This callback enables or disables the CEC hardware. Enabling the CEC hardware
136 means powering it up in a state where no logical addresses are claimed. The
137 physical address will always be valid if CEC_CAP_NEEDS_HPD is set. If that
138 capability is not set, then the physical address can change while the CEC
139 hardware is enabled. CEC drivers should not set CEC_CAP_NEEDS_HPD unless
140 the hardware design requires that as this will make it impossible to wake
141 up displays that pull the HPD low when in standby mode. The initial
142 state of the CEC adapter after calling cec_allocate_adapter() is disabled.
143
144 Note that adap_enable must return 0 if enable is false.
145
146
147 To enable/disable the 'monitor all' mode::
148
149 int (*adap_monitor_all_enable)(struct cec_adapter *adap, bool enable);
150
151 If enabled, then the adapter should be put in a mode to also monitor messages
152 that are not for us. Not all hardware supports this and this function is only
153 called if the CEC_CAP_MONITOR_ALL capability is set. This callback is optional
154 (some hardware may always be in 'monitor all' mode).
155
156 Note that adap_monitor_all_enable must return 0 if enable is false.
157
158
159 To enable/disable the 'monitor pin' mode::
160
161 int (*adap_monitor_pin_enable)(struct cec_adapter *adap, bool enable);
162
163 If enabled, then the adapter should be put in a mode to also monitor CEC pin
164 changes. Not all hardware supports this and this function is only called if
165 the CEC_CAP_MONITOR_PIN capability is set. This callback is optional
166 (some hardware may always be in 'monitor pin' mode).
167
168 Note that adap_monitor_pin_enable must return 0 if enable is false.
169
170
171 To program a new logical address::
172
173 int (*adap_log_addr)(struct cec_adapter *adap, u8 logical_addr);
174
175 If logical_addr == CEC_LOG_ADDR_INVALID then all programmed logical addresses
176 are to be erased. Otherwise the given logical address should be programmed.
177 If the maximum number of available logical addresses is exceeded, then it
178 should return -ENXIO. Once a logical address is programmed the CEC hardware
179 can receive directed messages to that address.
180
181 Note that adap_log_addr must return 0 if logical_addr is CEC_LOG_ADDR_INVALID.
182
183
184 Called when the adapter is unconfigured::
185
186 void (*adap_unconfigured)(struct cec_adapter *adap);
187
188 The adapter is unconfigured. If the driver has to take specific actions after
189 unconfiguration, then that can be done through this optional callback.
190
191
192 To transmit a new message::
193
194 int (*adap_transmit)(struct cec_adapter *adap, u8 attempts,
195 u32 signal_free_time, struct cec_msg *msg);
196
197 This transmits a new message. The attempts argument is the suggested number of
198 attempts for the transmit.
199
200 The signal_free_time is the number of data bit periods that the adapter should
201 wait when the line is free before attempting to send a message. This value
202 depends on whether this transmit is a retry, a message from a new initiator or
203 a new message for the same initiator. Most hardware will handle this
204 automatically, but in some cases this information is needed.
205
206 The CEC_FREE_TIME_TO_USEC macro can be used to convert signal_free_time to
207 microseconds (one data bit period is 2.4 ms).
208
209
210 To pass on the result of a canceled non-blocking transmit::
211
212 void (*adap_nb_transmit_canceled)(struct cec_adapter *adap,
213 const struct cec_msg *msg);
214
215 This optional callback can be used to obtain the result of a canceled
216 non-blocking transmit with sequence number msg->sequence. This is
217 called if the transmit was aborted, the transmit timed out (i.e. the
218 hardware never signaled that the transmit finished), or the transmit
219 was successful, but the wait for the expected reply was either aborted
220 or it timed out.
221
222
223 To log the current CEC hardware status::
224
225 void (*adap_status)(struct cec_adapter *adap, struct seq_file *file);
226
227 This optional callback can be used to show the status of the CEC hardware.
228 The status is available through debugfs: cat /sys/kernel/debug/cec/cecX/status
229
230 To free any resources when the adapter is deleted::
231
232 void (*adap_free)(struct cec_adapter *adap);
233
234 This optional callback can be used to free any resources that might have been
235 allocated by the driver. It's called from cec_delete_adapter.
236
237
238 Your adapter driver will also have to react to events (typically interrupt
239 driven) by calling into the framework in the following situations:
240
241 When a transmit finished (successfully or otherwise)::
242
243 void cec_transmit_done(struct cec_adapter *adap, u8 status,
244 u8 arb_lost_cnt, u8 nack_cnt, u8 low_drive_cnt,
245 u8 error_cnt);
246
247 or::
248
249 void cec_transmit_attempt_done(struct cec_adapter *adap, u8 status);
250
251 The status can be one of:
252
253 CEC_TX_STATUS_OK:
254 the transmit was successful.
255
256 CEC_TX_STATUS_ARB_LOST:
257 arbitration was lost: another CEC initiator
258 took control of the CEC line and you lost the arbitration.
259
260 CEC_TX_STATUS_NACK:
261 the message was nacked (for a directed message) or
262 acked (for a broadcast message). A retransmission is needed.
263
264 CEC_TX_STATUS_LOW_DRIVE:
265 low drive was detected on the CEC bus. This indicates that
266 a follower detected an error on the bus and requested a
267 retransmission.
268
269 CEC_TX_STATUS_ERROR:
270 some unspecified error occurred: this can be one of ARB_LOST
271 or LOW_DRIVE if the hardware cannot differentiate or something
272 else entirely. Some hardware only supports OK and FAIL as the
273 result of a transmit, i.e. there is no way to differentiate
274 between the different possible errors. In that case map FAIL
275 to CEC_TX_STATUS_NACK and not to CEC_TX_STATUS_ERROR.
276
277 CEC_TX_STATUS_MAX_RETRIES:
278 could not transmit the message after trying multiple times.
279 Should only be set by the driver if it has hardware support for
280 retrying messages. If set, then the framework assumes that it
281 doesn't have to make another attempt to transmit the message
282 since the hardware did that already.
283
284 The hardware must be able to differentiate between OK, NACK and 'something
285 else'.
286
287 The \*_cnt arguments are the number of error conditions that were seen.
288 This may be 0 if no information is available. Drivers that do not support
289 hardware retry can just set the counter corresponding to the transmit error
290 to 1, if the hardware does support retry then either set these counters to
291 0 if the hardware provides no feedback of which errors occurred and how many
292 times, or fill in the correct values as reported by the hardware.
293
294 Be aware that calling these functions can immediately start a new transmit
295 if there is one pending in the queue. So make sure that the hardware is in
296 a state where new transmits can be started *before* calling these functions.
297
298 The cec_transmit_attempt_done() function is a helper for cases where the
299 hardware never retries, so the transmit is always for just a single
300 attempt. It will call cec_transmit_done() in turn, filling in 1 for the
301 count argument corresponding to the status. Or all 0 if the status was OK.
302
303 When a CEC message was received:
304
305 .. c:function::
306 void cec_received_msg(struct cec_adapter *adap, struct cec_msg *msg);
307
308 Speaks for itself.
309
310 Implementing the interrupt handler
311 ----------------------------------
312
313 Typically the CEC hardware provides interrupts that signal when a transmit
314 finished and whether it was successful or not, and it provides and interrupt
315 when a CEC message was received.
316
317 The CEC driver should always process the transmit interrupts first before
318 handling the receive interrupt. The framework expects to see the cec_transmit_done
319 call before the cec_received_msg call, otherwise it can get confused if the
320 received message was in reply to the transmitted message.
321
322 Optional: Implementing Error Injection Support
323 ----------------------------------------------
324
325 If the CEC adapter supports Error Injection functionality, then that can
326 be exposed through the Error Injection callbacks:
327
328 .. code-block:: none
329
330 struct cec_adap_ops {
331 /* Low-level callbacks */
332 ...
333
334 /* Error injection callbacks */
335 int (*error_inj_show)(struct cec_adapter *adap, struct seq_file *sf);
336 bool (*error_inj_parse_line)(struct cec_adapter *adap, char *line);
337
338 /* High-level CEC message callback */
339 ...
340 };
341
342 If both callbacks are set, then an ``error-inj`` file will appear in debugfs.
343 The basic syntax is as follows:
344
345 Leading spaces/tabs are ignored. If the next character is a ``#`` or the end of the
346 line was reached, then the whole line is ignored. Otherwise a command is expected.
347
348 This basic parsing is done in the CEC Framework. It is up to the driver to decide
349 what commands to implement. The only requirement is that the command ``clear`` without
350 any arguments must be implemented and that it will remove all current error injection
351 commands.
352
353 This ensures that you can always do ``echo clear >error-inj`` to clear any error
354 injections without having to know the details of the driver-specific commands.
355
356 Note that the output of ``error-inj`` shall be valid as input to ``error-inj``.
357 So this must work:
358
359 .. code-block:: none
360
361 $ cat error-inj >einj.txt
362 $ cat einj.txt >error-inj
363
364 The first callback is called when this file is read and it should show the
365 current error injection state::
366
367 int (*error_inj_show)(struct cec_adapter *adap, struct seq_file *sf);
368
369 It is recommended that it starts with a comment block with basic usage
370 information. It returns 0 for success and an error otherwise.
371
372 The second callback will parse commands written to the ``error-inj`` file::
373
374 bool (*error_inj_parse_line)(struct cec_adapter *adap, char *line);
375
376 The ``line`` argument points to the start of the command. Any leading
377 spaces or tabs have already been skipped. It is a single line only (so there
378 are no embedded newlines) and it is 0-terminated. The callback is free to
379 modify the contents of the buffer. It is only called for lines containing a
380 command, so this callback is never called for empty lines or comment lines.
381
382 Return true if the command was valid or false if there were syntax errors.
383
384 Implementing the High-Level CEC Adapter
385 ---------------------------------------
386
387 The low-level operations drive the hardware, the high-level operations are
388 CEC protocol driven. The high-level callbacks are called without the adap->lock
389 mutex being held. The following high-level callbacks are available:
390
391 .. code-block:: none
392
393 struct cec_adap_ops {
394 /* Low-level callbacks */
395 ...
396
397 /* Error injection callbacks */
398 ...
399
400 /* High-level CEC message callback */
401 void (*configured)(struct cec_adapter *adap);
402 int (*received)(struct cec_adapter *adap, struct cec_msg *msg);
403 };
404
405 Called when the adapter is configured::
406
407 void (*configured)(struct cec_adapter *adap);
408
409 The adapter is fully configured, i.e. all logical addresses have been
410 successfully claimed. If the driver has to take specific actions after
411 configuration, then that can be done through this optional callback.
412
413
414 The received() callback allows the driver to optionally handle a newly
415 received CEC message::
416
417 int (*received)(struct cec_adapter *adap, struct cec_msg *msg);
418
419 If the driver wants to process a CEC message, then it can implement this
420 callback. If it doesn't want to handle this message, then it should return
421 -ENOMSG, otherwise the CEC framework assumes it processed this message and
422 it will not do anything with it.
423
424
425 CEC framework functions
426 -----------------------
427
428 CEC Adapter drivers can call the following CEC framework functions:
429
430 .. c:function::
431 int cec_transmit_msg(struct cec_adapter *adap, struct cec_msg *msg, \
432 bool block);
433
434 Transmit a CEC message. If block is true, then wait until the message has been
435 transmitted, otherwise just queue it and return.
436
437 .. c:function::
438 void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block);
439
440 Change the physical address. This function will set adap->phys_addr and
441 send an event if it has changed. If cec_s_log_addrs() has been called and
442 the physical address has become valid, then the CEC framework will start
443 claiming the logical addresses. If block is true, then this function won't
444 return until this process has finished.
445
446 When the physical address is set to a valid value the CEC adapter will
447 be enabled (see the adap_enable op). When it is set to CEC_PHYS_ADDR_INVALID,
448 then the CEC adapter will be disabled. If you change a valid physical address
449 to another valid physical address, then this function will first set the
450 address to CEC_PHYS_ADDR_INVALID before enabling the new physical address.
451
452 .. c:function::
453 void cec_s_phys_addr_from_edid(struct cec_adapter *adap, \
454 const struct edid *edid);
455
456 A helper function that extracts the physical address from the edid struct
457 and calls cec_s_phys_addr() with that address, or CEC_PHYS_ADDR_INVALID
458 if the EDID did not contain a physical address or edid was a NULL pointer.
459
460 .. c:function::
461 int cec_s_log_addrs(struct cec_adapter *adap, \
462 struct cec_log_addrs *log_addrs, bool block);
463
464 Claim the CEC logical addresses. Should never be called if CEC_CAP_LOG_ADDRS
465 is set. If block is true, then wait until the logical addresses have been
466 claimed, otherwise just queue it and return. To unconfigure all logical
467 addresses call this function with log_addrs set to NULL or with
468 log_addrs->num_log_addrs set to 0. The block argument is ignored when
469 unconfiguring. This function will just return if the physical address is
470 invalid. Once the physical address becomes valid, then the framework will
471 attempt to claim these logical addresses.
472
473 CEC Pin framework
474 -----------------
475
476 Most CEC hardware operates on full CEC messages where the software provides
477 the message and the hardware handles the low-level CEC protocol. But some
478 hardware only drives the CEC pin and software has to handle the low-level
479 CEC protocol. The CEC pin framework was created to handle such devices.
480
481 Note that due to the close-to-realtime requirements it can never be guaranteed
482 to work 100%. This framework uses highres timers internally, but if a
483 timer goes off too late by more than 300 microseconds wrong results can
484 occur. In reality it appears to be fairly reliable.
485
486 One advantage of this low-level implementation is that it can be used as
487 a cheap CEC analyser, especially if interrupts can be used to detect
488 CEC pin transitions from low to high or vice versa.
489
490 .. kernel-doc:: include/media/cec-pin.h
491
492 CEC Notifier framework
493 ----------------------
494
495 Most drm HDMI implementations have an integrated CEC implementation and no
496 notifier support is needed. But some have independent CEC implementations
497 that have their own driver. This could be an IP block for an SoC or a
498 completely separate chip that deals with the CEC pin. For those cases a
499 drm driver can install a notifier and use the notifier to inform the
500 CEC driver about changes in the physical address.
501
502 .. kernel-doc:: include/media/cec-notifier.h
503

3. 한국어 전문 번역

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

CEC Kernel Support 개요

1-13

이 문서는 GPL-2.0 SPDX license를 사용합니다. CEC framework는 HDMI CEC hardware를 위한 통합 kernel interface를 제공합니다.

Receiver, transmitter, USB dongle 등 여러 hardware type을 다루며, 어떤 처리를 kernel driver에 두고 무엇을 userspace application에 맡길지 선택할 수 있습니다. Remote-control passthrough도 kernel remote-control framework와 통합합니다.

CEC framework boundary
Receiver / transmitter / USB dongleCEC adapter low-level driverCEC kernel frameworkKernel protocol handling 또는 userspace applicationRemote-control framework passthrough

다양한 CEC hardware를 공통 kernel API와 userspace policy에 연결합니다.

CEC protocol과 address

14-31

CEC protocol은 HDMI connection을 통해 consumer electronic device들이 서로 통신하게 합니다. 통신에는 logical address를 사용하며, 이 address는 device가 제공하는 기능과 엄격히 연결됩니다. Communication hub 역할을 하는 TV는 항상 address 0입니다.

Physical address는 device 사이의 물리적 연결로 결정됩니다. 이 CEC framework는 CEC 2.0 specification에 맞춰져 있으며, HDMI 1.4 specification과 HDMI 2.0의 새 2.0 bit에 문서화되어 있습니다. 대부분의 기능에는 무료 HDMI 1.3a specification으로 충분하며 문서는 `https://www.hdmi.org/spec/index`를 안내합니다.

CEC address 의미
Address결정 기준
LogicalDevice functionalityTV hub는 항상 0
PhysicalHDMI physical connection topologyPort chain에 따라 결정

Logical address와 physical address가 나타내는 바가 다릅니다.

CEC adapter allocate와 parameter

32-68

`struct cec_adapter`는 CEC adapter hardware를 나타냅니다. `cec_allocate_adapter()`로 만들고 `cec_delete_adapter()`로 삭제합니다.

.. c:function::
   struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, \
                                            void *priv, const char *name, \
                                            u32 caps, u8 available_las);

.. c:function::
   void cec_delete_adapter(struct cec_adapter *adap);

`ops`는 CEC framework가 호출하며 driver가 구현해야 하는 adapter operation입니다. `priv`는 `adap->priv`에 저장되어 adapter op에서 사용할 수 있고 `cec_get_drvdata(adap)`로 얻습니다.

`name`은 CEC adapter 이름이며 framework가 복사합니다. `caps`는 hardware capability와 userspace·kernelspace 처리 경계를 결정하며 `CEC_ADAP_G_CAPS`로 반환됩니다.

`available_las`는 adapter가 동시에 처리할 수 있는 logical address 수이며 `1 <= available_las <= CEC_MAX_LOG_ADDRS`여야 합니다.

cec_allocate_adapter() 인자
인자역할
opsDriver가 구현한 cec_adap_ops
privadap->priv에 저장할 driver data
name복사되는 adapter 이름
capsHardware capability와 kernel/userspace 경계
available_las동시 logical address 수, 1..CEC_MAX_LOG_ADDRS

Adapter 생성에 필요한 정보입니다.

Driver data와 device registration lifecycle

69-94

Private pointer를 얻는 helper는 다음과 같습니다.

.. c:function::
        void *cec_get_drvdata(const struct cec_adapter *adap);

`/dev/cecX` device node와 `CEC_CAP_RC`가 설정된 경우 remote-control device를 등록할 때 `cec_register_adapter()`를 호출하며 `parent`는 parent device입니다.

.. c:function::
        int cec_register_adapter(struct cec_adapter *adap, \
                                 struct device *parent);

Device를 unregister할 때는 `cec_unregister_adapter()`를 호출합니다.

.. c:function::
        void cec_unregister_adapter(struct cec_adapter *adap);

`cec_register_adapter()`가 실패하면 `cec_delete_adapter()`로 정리합니다. 등록에 성공했다면 `cec_delete_adapter()`를 절대 직접 호출하지 말고 `cec_unregister_adapter()`만 호출해야 합니다. 마지막 `/dev/cecX` user가 file handle을 닫으면 unregister function이 adapter를 자동 삭제합니다.

CEC adapter lifecycle
cec_allocate_adapter()cec_register_adapter()등록 성공?아니오: cec_delete_adapter()예: /dev/cecX 사용cec_unregister_adapter()마지막 file handle closeFramework가 adapter 자동 삭제

Registration 성공 여부에 따라 cleanup API가 달라집니다.

Cleanup 규칙
상태허용 cleanup금지
Register 실패cec_delete_adapter()unregister만으로 정리 기대
Register 성공cec_unregister_adapter()cec_delete_adapter() 직접 호출

Double deletion을 피하기 위한 엄격한 분기입니다.

Low-level cec_adap_ops

95-130

Driver는 다음 low-level adapter operation을 구현해야 합니다.

.. c:struct:: cec_adap_ops

.. code-block:: none

        struct cec_adap_ops
        {
                /* Low-level callbacks */
                int (*adap_enable)(struct cec_adapter *adap, bool enable);
                int (*adap_monitor_all_enable)(struct cec_adapter *adap, bool enable);
                int (*adap_monitor_pin_enable)(struct cec_adapter *adap, bool enable);
                int (*adap_log_addr)(struct cec_adapter *adap, u8 logical_addr);
                void (*adap_unconfigured)(struct cec_adapter *adap);
                int (*adap_transmit)(struct cec_adapter *adap, u8 attempts,
                                      u32 signal_free_time, struct cec_msg *msg);
                void (*adap_nb_transmit_canceled)(struct cec_adapter *adap,
                                                  const struct cec_msg *msg);
                void (*adap_status)(struct cec_adapter *adap, struct seq_file *file);
                void (*adap_free)(struct cec_adapter *adap);

                /* Error injection callbacks */
                ...

                /* High-level callback */
                ...
        };

이 low-level op들은 CEC adapter hardware 제어의 여러 측면을 담당하며 모두 `adap->lock` mutex를 잡은 상태에서 호출됩니다.

Low-level callback group
Callback핵심 역할
adap_enableHardware power·enable
adap_monitor_all_enable다른 destination message도 monitor
adap_monitor_pin_enableCEC pin transition monitor
adap_log_addrLogical address program·erase
adap_unconfiguredUnconfigure 후 driver action
adap_transmitCEC message transmit
adap_nb_transmit_canceled취소된 non-blocking 결과
adap_statusdebugfs hardware status
adap_freeDriver resource free

Hardware control callback과 선택 callback을 분류했습니다.

adap_enable과 HPD capability

131-146

Hardware enable·disable callback signature는 다음과 같습니다.

int (*adap_enable)(struct cec_adapter *adap, bool enable);

Enable은 logical address를 하나도 claim하지 않은 상태로 CEC hardware의 power를 올리는 것을 뜻합니다. `CEC_CAP_NEEDS_HPD`가 있으면 physical address가 항상 valid하고, 없으면 hardware가 enable된 동안에도 physical address가 바뀔 수 있습니다.

Hardware 설계가 요구하지 않는 한 `CEC_CAP_NEEDS_HPD`를 설정하지 않아야 합니다. 이 flag는 standby에서 HPD를 low로 끌어내리는 display를 깨울 수 없게 만들기 때문입니다. `cec_allocate_adapter()` 직후 adapter 초기 상태는 disabled입니다.

`enable`이 false일 때 `adap_enable`은 반드시 0을 반환해야 합니다.

Adapter enable state
Allocation 직후 disabledValid physical address 설정adap_enable(true)Logical address 미claim 상태로 power onCEC_CAP_NEEDS_HPD?예: physical address 항상 valid아니오: enabled 중에도 address 변경 가능Disable 요청은 0 반환

Physical address와 HPD requirement가 enable semantics에 영향을 줍니다.

Monitor-all과 monitor-pin

147-170

`monitor all` mode callback은 다음과 같습니다.

int (*adap_monitor_all_enable)(struct cec_adapter *adap, bool enable);

Enable하면 adapter는 자신에게 온 message뿐 아니라 다른 destination의 message도 monitor해야 합니다. `CEC_CAP_MONITOR_ALL`이 있을 때만 호출되며, hardware가 항상 monitor-all mode라면 callback은 optional입니다. Disable 때는 반드시 0을 반환합니다.

`monitor pin` mode callback은 다음과 같습니다.

int (*adap_monitor_pin_enable)(struct cec_adapter *adap, bool enable);

Enable하면 CEC pin 변화도 monitor합니다. `CEC_CAP_MONITOR_PIN`이 있을 때만 호출되며 hardware가 항상 이 mode라면 optional입니다. Disable 때는 반드시 0을 반환합니다.

Monitor mode capability
ModeCapability관찰 대상Callback
monitor allCEC_CAP_MONITOR_ALL우리 destination이 아닌 messageadap_monitor_all_enable
monitor pinCEC_CAP_MONITOR_PINCEC pin level transitionadap_monitor_pin_enable

Capability gate와 관찰 대상입니다.

Logical address와 unconfigured callback

171-191

새 logical address를 program하는 callback은 다음과 같습니다.

int (*adap_log_addr)(struct cec_adapter *adap, u8 logical_addr);

`logical_addr == CEC_LOG_ADDR_INVALID`이면 program된 모든 logical address를 지웁니다. 그 외에는 지정 address를 program합니다. 최대 available logical address 수를 넘으면 `-ENXIO`를 반환해야 합니다. Address가 program되면 hardware가 그 destination으로 온 directed message를 받을 수 있습니다.

`CEC_LOG_ADDR_INVALID`를 전달했을 때 `adap_log_addr`는 반드시 0을 반환해야 합니다.

Adapter unconfiguration callback은 다음과 같습니다.

void (*adap_unconfigured)(struct cec_adapter *adap);

Unconfigure 뒤 driver가 특별한 작업을 해야 할 때 사용하는 optional callback입니다.

Logical address programming
adap_log_addr(logical_addr)CEC_LOG_ADDR_INVALID?예: 모든 logical address erase, return 0아니오: available_las 초과?예: -ENXIO아니오: address programDirected message receive 가능

Invalid sentinel은 모든 address를 지우는 명령입니다.

Message transmit와 canceled non-blocking 결과

192-221

새 message transmit callback은 다음과 같습니다.

int (*adap_transmit)(struct cec_adapter *adap, u8 attempts,
                     u32 signal_free_time, struct cec_msg *msg);

`attempts`는 권장 transmit 시도 횟수입니다. `signal_free_time`은 line이 free가 된 뒤 송신하기 전에 기다릴 data bit period 수입니다. Retry인지, 새 initiator의 message인지, 같은 initiator의 새 message인지에 따라 값이 달라집니다.

대부분 hardware가 이를 자동 처리하지만 일부는 이 정보가 필요합니다. `CEC_FREE_TIME_TO_USEC` macro로 microsecond로 바꿀 수 있고 data bit period 하나는 2.4 ms입니다.

Canceled non-blocking transmit 결과 callback은 다음과 같습니다.

void (*adap_nb_transmit_canceled)(struct cec_adapter *adap,
                                  const struct cec_msg *msg);

이 optional callback은 `msg->sequence`인 non-blocking transmit이 abort되었거나 timeout되었거나, transmit은 성공했지만 expected reply wait가 abort 또는 timeout된 경우 결과를 얻는 데 사용합니다.

adap_transmit() 입력
인자의미
attempts권장 transmit 시도 횟수
signal_free_timeFree line 뒤 기다릴 data bit period
msg송신할 struct cec_msg
CEC_FREE_TIME_TO_USECPeriod를 microsecond로 변환
1 data bit period2.4 ms

Hardware가 송신 timing과 retry를 수행하는 데 필요한 값입니다.

Non-blocking cancel callback 조건
상황adap_nb_transmit_canceled 호출
Transmit abort
Transmit hardware timeout
Transmit 성공, reply wait abort
Transmit 성공, reply wait timeout

Transmit 또는 reply wait가 끝나지 못한 경로입니다.

Debug status와 adapter resource free

222-237

현재 CEC hardware status를 출력하는 optional callback은 다음과 같습니다.

void (*adap_status)(struct cec_adapter *adap, struct seq_file *file);

Status는 debugfs의 `cat /sys/kernel/debug/cec/cecX/status`로 확인할 수 있습니다.

Adapter 삭제 때 resource를 free하는 optional callback은 다음과 같습니다.

void (*adap_free)(struct cec_adapter *adap);

Driver가 allocate한 resource를 해제하는 데 사용하며 `cec_delete_adapter()`에서 호출됩니다.

Diagnostic·cleanup callback
CallbackTrigger결과
adap_statusdebugfs status readseq_file에 hardware 상태 출력
adap_freecec_delete_adapterDriver allocation resource 해제

두 optional callback의 호출 지점입니다.

Transmit completion, status와 receive event

238-309

Adapter driver는 보통 interrupt event에 반응해 framework function을 호출해야 합니다. Transmit이 성공 또는 실패로 끝났을 때는 다음 둘 중 하나를 사용합니다.

        void cec_transmit_done(struct cec_adapter *adap, u8 status,
                               u8 arb_lost_cnt,  u8 nack_cnt, u8 low_drive_cnt,
                               u8 error_cnt);

or::

        void cec_transmit_attempt_done(struct cec_adapter *adap, u8 status);

`CEC_TX_STATUS_OK`는 성공, `CEC_TX_STATUS_ARB_LOST`는 다른 initiator가 line control을 가져가 arbitration에서 진 상태입니다. `CEC_TX_STATUS_NACK`은 directed message가 NACK되었거나 broadcast message가 ACK되어 retransmission이 필요함을 뜻합니다.

`CEC_TX_STATUS_LOW_DRIVE`는 follower가 bus error를 감지해 retransmission을 요청했음을 뜻합니다. `CEC_TX_STATUS_ERROR`는 hardware가 구분하지 못하는 ARB_LOST·LOW_DRIVE 또는 다른 unspecified error입니다. Hardware가 OK와 FAIL만 제공하면 FAIL은 `CEC_TX_STATUS_ERROR`가 아니라 `CEC_TX_STATUS_NACK`으로 mapping해야 합니다.

`CEC_TX_STATUS_MAX_RETRIES`는 여러 번 시도했지만 전송하지 못한 상태입니다. Hardware retry support가 있을 때만 driver가 설정하며 framework는 hardware가 이미 retry했다고 보고 추가 시도를 하지 않습니다. Hardware는 최소한 OK, NACK, 그 밖의 상태를 구분할 수 있어야 합니다.

`*_cnt` 인자는 관찰한 각 error condition 횟수입니다. 정보가 없으면 0일 수 있습니다. Hardware retry가 없으면 해당 error counter를 1로 설정할 수 있습니다. Retry가 있으면 feedback이 없을 때 모두 0, feedback이 있으면 hardware 보고값을 채웁니다.

Completion function 호출은 queue에 pending transmit이 있으면 즉시 다음 transmit을 시작할 수 있습니다. 따라서 호출 전에 hardware가 새 transmit을 시작할 수 있는 상태여야 합니다.

`cec_transmit_attempt_done()`은 hardware가 절대 retry하지 않아 항상 single attempt인 경우의 helper입니다. 내부에서 `cec_transmit_done()`을 호출하고 해당 status counter를 1로, OK라면 모든 counter를 0으로 채웁니다.

CEC message를 받았을 때 호출하는 API는 다음과 같습니다.

.. c:function::
        void cec_received_msg(struct cec_adapter *adap, struct cec_msg *msg);
CEC transmit status
Status의미처리
CEC_TX_STATUS_OKTransmit 성공완료
CEC_TX_STATUS_ARB_LOST다른 initiator에 arbitration 패배Retry 가능
CEC_TX_STATUS_NACKDirected NACK 또는 broadcast ACKRetransmission 필요
CEC_TX_STATUS_LOW_DRIVEFollower가 bus error signalRetransmission 필요
CEC_TX_STATUS_ERROR구분 불가 또는 기타 errorHardware 한계 반영
CEC_TX_STATUS_MAX_RETRIESHardware retry 모두 실패Framework 추가 retry 안 함

Framework에 보고할 status와 의미입니다.

TX completion callback 안전 순서
Hardware TX 완료 interruptHardware를 다음 TX 가능 상태로 정리cec_transmit_done 또는 attempt_doneFramework가 status·counter 기록Pending TX 존재?예: 즉시 다음 adap_transmit 호출 가능RX message면 cec_received_msg

Callback이 다음 queued transmit을 즉시 시작할 수 있습니다.

Interrupt handler ordering

310-321

일반적인 CEC hardware는 transmit 완료와 성공 여부, CEC message 수신을 interrupt로 알립니다.

CEC driver는 receive interrupt보다 transmit interrupt를 항상 먼저 처리해야 합니다. Framework는 `cec_received_msg()`보다 `cec_transmit_done()`을 먼저 볼 것으로 기대합니다. 순서가 바뀌면 받은 message가 방금 송신한 message의 reply인 경우 framework가 혼동할 수 있습니다.

CEC interrupt 처리 순서
IRQ 발생TX complete status 확인cec_transmit_done()그 다음 RX 확인cec_received_msg()Reply correlation 정상 유지

동시에 TX와 RX가 pending일 때 TX completion을 먼저 보고합니다.

Error injection interface와 syntax

322-363

CEC adapter가 Error Injection 기능을 지원하면 다음 callback으로 노출할 수 있습니다.

.. code-block:: none

        struct cec_adap_ops {
                /* Low-level callbacks */
                ...

                /* Error injection callbacks */
                int (*error_inj_show)(struct cec_adapter *adap, struct seq_file *sf);
                bool (*error_inj_parse_line)(struct cec_adapter *adap, char *line);

                /* High-level CEC message callback */
                ...
        };

두 callback이 모두 설정되면 debugfs에 `error-inj` file이 생깁니다. Leading space와 tab은 무시하며 다음 character가 `#`이거나 line 끝이면 전체 line을 무시하고, 그렇지 않으면 command를 기대합니다. 이 기본 parsing은 CEC framework가 수행하고 driver가 구현할 command를 정합니다.

인자 없는 `clear` command는 반드시 구현하여 현재 error injection command를 모두 제거해야 합니다. 따라서 driver-specific syntax를 몰라도 `echo clear >error-inj`로 항상 정리할 수 있습니다.

`error-inj` output은 그대로 input으로 유효해야 하므로 다음 round trip이 동작해야 합니다.

.. code-block:: none

        $ cat error-inj >einj.txt
        $ cat einj.txt >error-inj
error-inj parsing
error-inj에 line writeLeading space/tab skip빈 line 또는 # comment?예: ignore아니오: driver error_inj_parse_lineclear는 반드시 모든 injection 제거Read output은 재입력 가능한 syntax

Framework의 공통 syntax 처리 뒤 driver parser가 command를 검증합니다.

Error injection callback 동작

364-383

File read 때 현재 error injection state를 출력하는 callback은 다음과 같습니다.

int (*error_inj_show)(struct cec_adapter *adap, struct seq_file *sf);

기본 사용법을 담은 comment block으로 시작하는 것이 권장되며 성공 시 0, 실패 시 error를 반환합니다.

`error-inj`에 쓴 command를 parse하는 callback은 다음과 같습니다.

bool (*error_inj_parse_line)(struct cec_adapter *adap, char *line);

`line`은 leading space·tab을 이미 건너뛴 command 시작을 가리킵니다. Embedded newline이 없는 single line이고 NUL-terminated이며 callback이 buffer 내용을 수정해도 됩니다. Empty line이나 comment line에는 호출되지 않습니다. Command가 valid하면 true, syntax error면 false를 반환합니다.

High-level CEC adapter callback

384-424

Low-level operation은 hardware를 구동하고 high-level operation은 CEC protocol에 따라 동작합니다. High-level callback은 `adap->lock` mutex를 잡지 않은 상태에서 호출됩니다.

.. code-block:: none

        struct cec_adap_ops {
                /* Low-level callbacks */
                ...

                /* Error injection callbacks */
                ...

                /* High-level CEC message callback */
                void (*configured)(struct cec_adapter *adap);
                int (*received)(struct cec_adapter *adap, struct cec_msg *msg);
        };

Adapter가 완전히 configured되어 모든 logical address를 성공적으로 claim했을 때 호출하는 optional callback은 다음과 같습니다.

void (*configured)(struct cec_adapter *adap);

Configuration 뒤 driver-specific action이 필요하면 `configured()`에서 수행합니다.

새로 받은 CEC message를 driver가 선택적으로 처리하는 callback은 다음과 같습니다.

int (*received)(struct cec_adapter *adap, struct cec_msg *msg);

Driver가 message를 처리하지 않으려면 `-ENOMSG`를 반환해야 합니다. 그 외 return이면 framework는 driver가 처리했다고 가정하고 추가 동작을 하지 않습니다.

Low-level과 high-level callback
계층Lock context책임
Low-leveladap->lock heldadap_transmit, adap_log_addrHardware control
High-leveladap->lock not heldconfigured, receivedCEC protocol-driven policy

Lock context와 책임이 다릅니다.

Framework transmit과 physical address

425-451

Adapter driver가 CEC message를 보내는 framework function은 다음과 같습니다.

.. c:function::
   int cec_transmit_msg(struct cec_adapter *adap, struct cec_msg *msg, \
                        bool block);

`block`이 true면 transmit 완료까지 기다리고, false면 queue에 넣고 즉시 반환합니다.

Physical address 변경 API는 다음과 같습니다.

.. c:function::
   void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block);

이 function은 `adap->phys_addr`를 설정하고 값이 바뀌면 event를 보냅니다. `cec_s_log_addrs()`가 이미 호출되었고 physical address가 valid가 되면 framework가 logical address claim을 시작합니다. `block`이 true면 이 과정이 끝날 때까지 반환하지 않습니다.

Physical address를 valid value로 설정하면 `adap_enable`로 adapter를 enable하고 `CEC_PHYS_ADDR_INVALID`로 설정하면 disable합니다. Valid address에서 다른 valid address로 바꿀 때는 먼저 invalid로 설정한 뒤 새 address로 enable합니다.

Physical address state transition
현재 physical address새 address가 invalid?예: adap_enable(false)새 address가 valid기존도 valid?예: 먼저 CEC_PHYS_ADDR_INVALIDadap_enable(true)Pending logical address claim 시작block이면 완료까지 wait

Valid address 전환은 항상 invalid 중간 상태를 거칩니다.

EDID helper와 logical address claim

452-472

EDID에서 physical address를 추출하는 helper는 다음과 같습니다.

.. c:function::
   void cec_s_phys_addr_from_edid(struct cec_adapter *adap, \
                                  const struct edid *edid);

EDID에 physical address가 없거나 `edid`가 NULL이면 `CEC_PHYS_ADDR_INVALID`, 있으면 추출한 address로 `cec_s_phys_addr()`를 호출합니다.

CEC logical address를 claim하는 API는 다음과 같습니다.

.. c:function::
        int cec_s_log_addrs(struct cec_adapter *adap, \
                            struct cec_log_addrs *log_addrs, bool block);

`CEC_CAP_LOG_ADDRS`가 설정된 경우에는 절대 호출하면 안 됩니다. `block`이 true면 claim 완료까지 기다리고 false면 queue 후 반환합니다.

모든 logical address를 unconfigure하려면 `log_addrs`를 NULL로 전달하거나 `log_addrs->num_log_addrs`를 0으로 설정합니다. Unconfigure 때는 `block`을 무시합니다. Physical address가 invalid면 function은 바로 반환하지만, 나중에 valid가 되면 framework가 이 logical address들을 claim합니다.

Logical address claim gating
cec_s_log_addrs(log_addrs)CEC_CAP_LOG_ADDRS 설정?예: 호출 금지Unconfigure 요청?예: NULL 또는 num_log_addrs=0Physical address valid?아니오: 요청 보류나중에 valid eventFramework가 logical address claimblock이면 완료까지 wait

Physical address 유효성이 claim 실행 시점을 결정합니다.

CEC Pin framework

473-491

대부분 CEC hardware는 full CEC message를 받고 low-level protocol을 hardware가 처리합니다. 일부 hardware는 CEC pin만 구동해 software가 low-level CEC protocol을 처리해야 하며, 이를 위해 CEC pin framework가 만들어졌습니다.

Close-to-realtime requirement 때문에 100% 동작을 보장할 수 없습니다. 내부적으로 high-resolution timer를 사용하지만 timer가 300 microseconds보다 더 늦게 실행되면 잘못된 결과가 생길 수 있습니다. 실제로는 상당히 신뢰할 만한 것으로 보입니다.

이 low-level 구현은 값싼 CEC analyser로 사용할 수 있다는 장점이 있습니다. 특히 interrupt로 CEC pin의 low-to-high 또는 high-to-low transition을 감지할 수 있으면 유용합니다. API는 다음 kernel-doc에서 가져옵니다.

.. kernel-doc:: include/media/cec-pin.h
CEC pin framework 특성
항목내용
대상 hardwareFull message engine 없이 CEC pin만 구동
Protocol 처리Software
TimerHigh-resolution timer
위험 threshold300 microseconds 초과 지연
장점Low-cost CEC analyser
유용한 IRQPin low↔high transition

Software protocol 처리의 장점과 timing 위험입니다.

CEC Notifier framework

492-502

대부분 DRM HDMI 구현은 CEC가 통합되어 notifier가 필요 없습니다. 하지만 SoC IP block이나 CEC pin 전용 별도 chip처럼 독립 CEC 구현과 자체 driver를 가진 경우가 있습니다.

이 경우 DRM driver는 notifier를 설치해 physical address 변경을 CEC driver에 알릴 수 있습니다. API는 다음 kernel-doc에서 가져옵니다.

.. kernel-doc:: include/media/cec-notifier.h
Independent CEC notifier path
DRM HDMI driverHDMI topology·physical address 변경CEC notifier독립 SoC CEC IP 또는 external CEC chip driverCEC adapter physical address 갱신

DRM HDMI와 별도 CEC driver 사이에 physical address를 전달합니다.