aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Documentation/driver-api/media/cec-core.rst
diff options
context:
space:
mode:
Diffstat (limited to 'Documentation/driver-api/media/cec-core.rst')
-rw-r--r--Documentation/driver-api/media/cec-core.rst120
1 files changed, 74 insertions, 46 deletions
diff --git a/Documentation/driver-api/media/cec-core.rst b/Documentation/driver-api/media/cec-core.rst
index 3ce26b7c2b2b..f1ffdec388f3 100644
--- a/Documentation/driver-api/media/cec-core.rst
+++ b/Documentation/driver-api/media/cec-core.rst
@@ -26,7 +26,7 @@ It is documented in the HDMI 1.4 specification with the new 2.0 bits documented
in the HDMI 2.0 specification. But for most of the features the freely available
HDMI 1.3a specification is sufficient:
-http://www.microprocessor.org/HDMISpecification13a.pdf
+https://www.hdmi.org/spec/index
CEC Adapter Interface
@@ -36,8 +36,9 @@ The struct cec_adapter represents the CEC adapter hardware. It is created by
calling cec_allocate_adapter() and deleted by calling 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);
+ 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);
@@ -74,7 +75,8 @@ To register the /dev/cecX device node and the remote control device (if
CEC_CAP_RC is set) you call:
.. c:function::
- int cec_register_adapter(struct cec_adapter *adap, struct device *parent);
+ int cec_register_adapter(struct cec_adapter *adap, \
+ struct device *parent);
where parent is the parent device.
@@ -96,7 +98,7 @@ Implementing the Low-Level CEC Adapter
The following low-level adapter operations have to be implemented in
your driver:
-.. c:type:: struct cec_adap_ops
+.. c:struct:: cec_adap_ops
.. code-block:: none
@@ -107,52 +109,55 @@ your driver:
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 callbacks */
+ /* High-level callback */
...
};
-The seven low-level ops deal with various aspects of controlling the CEC adapter
-hardware:
+These low-level ops deal with various aspects of controlling the CEC adapter
+hardware. They are all called with the mutex adap->lock held.
-To enable/disable the hardware:
+To enable/disable the hardware::
-.. c:function::
int (*adap_enable)(struct cec_adapter *adap, bool enable);
This callback enables or disables the CEC hardware. Enabling the CEC hardware
-means powering it up in a state where no logical addresses are claimed. This
-op assumes that the physical address (adap->phys_addr) is valid when enable is
-true and will not change while the CEC adapter remains enabled. The initial
+means powering it up in a state where no logical addresses are claimed. The
+physical address will always be valid if CEC_CAP_NEEDS_HPD is set. If that
+capability is not set, then the physical address can change while the CEC
+hardware is enabled. CEC drivers should not set CEC_CAP_NEEDS_HPD unless
+the hardware design requires that as this will make it impossible to wake
+up displays that pull the HPD low when in standby mode. The initial
state of the CEC adapter after calling cec_allocate_adapter() is disabled.
Note that adap_enable must return 0 if enable is false.
-To enable/disable the 'monitor all' mode:
+To enable/disable the 'monitor all' mode::
-.. c:function::
int (*adap_monitor_all_enable)(struct cec_adapter *adap, bool enable);
If enabled, then the adapter should be put in a mode to also monitor messages
-that not for us. Not all hardware supports this and this function is only
+that are not for us. Not all hardware supports this and this function is only
called if the CEC_CAP_MONITOR_ALL capability is set. This callback is optional
(some hardware may always be in 'monitor all' mode).
Note that adap_monitor_all_enable must return 0 if enable is false.
-To enable/disable the 'monitor pin' mode:
+To enable/disable the 'monitor pin' mode::
-.. c:function::
int (*adap_monitor_pin_enable)(struct cec_adapter *adap, bool enable);
If enabled, then the adapter should be put in a mode to also monitor CEC pin
@@ -163,9 +168,8 @@ the CEC_CAP_MONITOR_PIN capability is set. This callback is optional
Note that adap_monitor_pin_enable must return 0 if enable is false.
-To program a new logical address:
+To program a new logical address::
-.. c:function::
int (*adap_log_addr)(struct cec_adapter *adap, u8 logical_addr);
If logical_addr == CEC_LOG_ADDR_INVALID then all programmed logical addresses
@@ -177,9 +181,16 @@ can receive directed messages to that address.
Note that adap_log_addr must return 0 if logical_addr is CEC_LOG_ADDR_INVALID.
-To transmit a new message:
+Called when the adapter is unconfigured::
+
+ void (*adap_unconfigured)(struct cec_adapter *adap);
+
+The adapter is unconfigured. If the driver has to take specific actions after
+unconfiguration, then that can be done through this optional callback.
+
+
+To transmit a new message::
-.. c:function::
int (*adap_transmit)(struct cec_adapter *adap, u8 attempts,
u32 signal_free_time, struct cec_msg *msg);
@@ -196,17 +207,28 @@ The CEC_FREE_TIME_TO_USEC macro can be used to convert signal_free_time to
microseconds (one data bit period is 2.4 ms).
-To log the current CEC hardware status:
+To pass on the result of a canceled non-blocking transmit::
+
+ void (*adap_nb_transmit_canceled)(struct cec_adapter *adap,
+ const struct cec_msg *msg);
+
+This optional callback can be used to obtain the result of a canceled
+non-blocking transmit with sequence number msg->sequence. This is
+called if the transmit was aborted, the transmit timed out (i.e. the
+hardware never signaled that the transmit finished), or the transmit
+was successful, but the wait for the expected reply was either aborted
+or it timed out.
+
+
+To log the current CEC hardware status::
-.. c:function::
void (*adap_status)(struct cec_adapter *adap, struct seq_file *file);
This optional callback can be used to show the status of the CEC hardware.
The status is available through debugfs: cat /sys/kernel/debug/cec/cecX/status
-To free any resources when the adapter is deleted:
+To free any resources when the adapter is deleted::
-.. c:function::
void (*adap_free)(struct cec_adapter *adap);
This optional callback can be used to free any resources that might have been
@@ -216,15 +238,14 @@ allocated by the driver. It's called from cec_delete_adapter.
Your adapter driver will also have to react to events (typically interrupt
driven) by calling into the framework in the following situations:
-When a transmit finished (successfully or otherwise):
+When a transmit finished (successfully or otherwise)::
-.. c:function::
- void cec_transmit_done(struct cec_adapter *adap, u8 status, u8 arb_lost_cnt,
- u8 nack_cnt, u8 low_drive_cnt, u8 error_cnt);
+ 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:
+or::
-.. c:function::
void cec_transmit_attempt_done(struct cec_adapter *adap, u8 status);
The status can be one of:
@@ -341,17 +362,15 @@ So this must work:
$ cat einj.txt >error-inj
The first callback is called when this file is read and it should show the
-the current error injection state:
+current error injection state::
-.. c:function::
int (*error_inj_show)(struct cec_adapter *adap, struct seq_file *sf);
It is recommended that it starts with a comment block with basic usage
information. It returns 0 for success and an error otherwise.
-The second callback will parse commands written to the ``error-inj`` file:
+The second callback will parse commands written to the ``error-inj`` file::
-.. c:function::
bool (*error_inj_parse_line)(struct cec_adapter *adap, char *line);
The ``line`` argument points to the start of the command. Any leading
@@ -366,7 +385,8 @@ Implementing the High-Level CEC Adapter
---------------------------------------
The low-level operations drive the hardware, the high-level operations are
-CEC protocol driven. The following high-level callbacks are available:
+CEC protocol driven. The high-level callbacks are called without the adap->lock
+mutex being held. The following high-level callbacks are available:
.. code-block:: none
@@ -378,13 +398,22 @@ CEC protocol driven. The following high-level callbacks are available:
...
/* High-level CEC message callback */
+ void (*configured)(struct cec_adapter *adap);
int (*received)(struct cec_adapter *adap, struct cec_msg *msg);
};
+Called when the adapter is configured::
+
+ void (*configured)(struct cec_adapter *adap);
+
+The adapter is fully configured, i.e. all logical addresses have been
+successfully claimed. If the driver has to take specific actions after
+configuration, then that can be done through this optional callback.
+
+
The received() callback allows the driver to optionally handle a newly
-received CEC message
+received CEC message::
-.. c:function::
int (*received)(struct cec_adapter *adap, struct cec_msg *msg);
If the driver wants to process a CEC message, then it can implement this
@@ -399,15 +428,14 @@ CEC framework functions
CEC Adapter drivers can call the following CEC framework functions:
.. c:function::
- int cec_transmit_msg(struct cec_adapter *adap, struct cec_msg *msg,
- bool block);
+ int cec_transmit_msg(struct cec_adapter *adap, struct cec_msg *msg, \
+ bool block);
Transmit a CEC message. If block is true, then wait until the message has been
transmitted, otherwise just queue it and return.
.. c:function::
- void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr,
- bool block);
+ void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block);
Change the physical address. This function will set adap->phys_addr and
send an event if it has changed. If cec_s_log_addrs() has been called and
@@ -422,15 +450,15 @@ to another valid physical address, then this function will first set the
address to CEC_PHYS_ADDR_INVALID before enabling the new physical address.
.. c:function::
- void cec_s_phys_addr_from_edid(struct cec_adapter *adap,
- const struct edid *edid);
+ void cec_s_phys_addr_from_edid(struct cec_adapter *adap, \
+ const struct edid *edid);
A helper function that extracts the physical address from the edid struct
and calls cec_s_phys_addr() with that address, or CEC_PHYS_ADDR_INVALID
if the EDID did not contain a physical address or edid was a NULL pointer.
.. c:function::
- int cec_s_log_addrs(struct cec_adapter *adap,
+ int cec_s_log_addrs(struct cec_adapter *adap, \
struct cec_log_addrs *log_addrs, bool block);
Claim the CEC logical addresses. Should never be called if CEC_CAP_LOG_ADDRS