aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2016-07-20 10:22:41 +0200
committerHans Verkuil <hans.verkuil@cisco.com>2016-07-20 10:22:41 +0200
commit45cfa80c134782d6e229821898637343329eb7e5 (patch)
treea8866999a2c3ac52d0f4a19850012a30aaf087cc
parent009a620848218d521f008141c62f56bf19294dd9 (diff)
cec: add preliminary arc/cdc-hpd supportcec-arc
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
-rw-r--r--Documentation/DocBook/media/v4l/cec-ioc-adap-g-caps.xml10
-rw-r--r--Documentation/DocBook/media/v4l/cec-ioc-g-mode.xml36
-rw-r--r--Documentation/cec.txt75
-rw-r--r--drivers/media/i2c/adv7511.c40
-rw-r--r--drivers/staging/media/cec/cec-adap.c198
-rw-r--r--include/linux/cec.h5
-rw-r--r--include/media/cec.h12
7 files changed, 373 insertions, 3 deletions
diff --git a/Documentation/DocBook/media/v4l/cec-ioc-adap-g-caps.xml b/Documentation/DocBook/media/v4l/cec-ioc-adap-g-caps.xml
index 3523ef2259b1..a4e8a48f8287 100644
--- a/Documentation/DocBook/media/v4l/cec-ioc-adap-g-caps.xml
+++ b/Documentation/DocBook/media/v4l/cec-ioc-adap-g-caps.xml
@@ -140,6 +140,16 @@
<entry>The CEC hardware can monitor all messages, not just directed and
broadcast messages.</entry>
</row>
+ <row>
+ <entry><constant>CEC_CAP_ARC</constant></entry>
+ <entry>0x00000040</entry>
+ <entry>This adapter supports the Audio Return Channel protocol.</entry>
+ </row>
+ <row>
+ <entry><constant>CEC_CAP_CDC_HPD</constant></entry>
+ <entry>0x00000080</entry>
+ <entry>This adapter supports the hotplug detect protocol over CDC.</entry>
+ </row>
</tbody>
</tgroup>
</table>
diff --git a/Documentation/DocBook/media/v4l/cec-ioc-g-mode.xml b/Documentation/DocBook/media/v4l/cec-ioc-g-mode.xml
index 26b4282ad134..72225733165c 100644
--- a/Documentation/DocBook/media/v4l/cec-ioc-g-mode.xml
+++ b/Documentation/DocBook/media/v4l/cec-ioc-g-mode.xml
@@ -197,6 +197,42 @@ The follower can of course always call &CEC-TRANSMIT;.</para>
&cs-def;
<tbody valign="top">
<row>
+ <entry><constant>CEC_MSG_INITIATE_ARC</constant></entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry><constant>CEC_MSG_TERMINATE_ARC</constant></entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry><constant>CEC_MSG_REQUEST_ARC_INITIATION</constant></entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry><constant>CEC_MSG_REQUEST_ARC_TERMINATION</constant></entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry><constant>CEC_MSG_REPORT_ARC_INITIATED</constant></entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry><constant>CEC_MSG_REPORT_ARC_TERMINATED</constant></entry>
+ <entry>If <constant>CEC_CAP_ARC</constant> is not set, then just pass
+ it on to userspace for processing. However, if <constant>CEC_CAP_ARC</constant> is
+ set, then the core framework processes this message and userspace will
+ not see it, not even in passthrough mode.</entry>
+ </row>
+ <row>
+ <entry><constant>CEC_MSG_CDC_MESSAGE</constant></entry>
+ <entry>If <constant>CEC_CAP_CDC_HPD</constant> is not set, then just pass
+ it on to userspace for processing. Do the same if the CDC command is not
+ one of <constant>CEC_MSG_CDC_HPD_REPORT_STATE</constant> or
+ <constant>CEC_MSG_CDC_HPD_SET_STATE</constant>. Else the core framework
+ processes this message and userspace will not see it, not even in passthrough
+ mode.</entry>
+ </row>
+ <row>
<entry><constant>CEC_MSG_GET_CEC_VERSION</constant></entry>
<entry>When in passthrough mode this message has to be handled by userspace,
otherwise the core will return the CEC version that was set with &CEC-ADAP-S-LOG-ADDRS;.</entry>
diff --git a/Documentation/cec.txt b/Documentation/cec.txt
index 75155fe37153..8a618191685d 100644
--- a/Documentation/cec.txt
+++ b/Documentation/cec.txt
@@ -216,6 +216,16 @@ struct cec_adap_ops {
/* High-level CEC message callback */
int (*received)(struct cec_adapter *adap, struct cec_msg *msg);
+
+ /* High-level CDC Hotplug Detect callbacks */
+ u8 (*source_cdc_hpd)(struct cec_adapter *adap, u8 cdc_hpd_state);
+ void (*sink_cdc_hpd)(struct cec_adapter *adap, u8 cdc_hpd_state, u8 cdc_hpd_error);
+
+ /* High-level Audio Return Channel callbacks */
+ int (*sink_initiate_arc)(struct cec_adapter *adap);
+ int (*sink_terminate_arc)(struct cec_adapter *adap);
+ int (*source_arc_initiated)(struct cec_adapter *adap);
+ int (*source_arc_terminated)(struct cec_adapter *adap);
};
The received() callback allows the driver to optionally handle a newly
@@ -228,6 +238,62 @@ callback. If it doesn't want to handle this message, then it should return
-ENOMSG, otherwise the CEC framework assumes it processed this message and
it will not no anything with it.
+The other callbacks deal with two CEC features: CDC Hotplug Detect and
+Audio Return Channel. Here the framework takes care of handling these
+messages and it calls the callbacks to notify the driver when it needs
+to take action.
+
+CDC Hotplug Support
+-------------------
+
+A source received a hotplug state change message:
+
+ u8 (*source_cdc_hpd)(struct cec_adapter *adap, u8 cdc_hpd_state);
+
+A source received a CEC_MSG_CDC_HPD_SET_STATE message. The framework will
+reply with a CEC_MSG_CDC_HPD_REPORT_STATE message and this callback is used
+to fill in the HPD Error Code Operand of the REPORT_STATE message. In addition,
+the driver can act in this callback on the hotplug state change.
+
+Only implement if CEC_CAP_CDC_HPD is set.
+
+A sink received a hotplug report state message:
+
+ void (*sink_cdc_hpd)(struct cec_adapter *adap, u8 cdc_hpd_state, u8 cdc_hpd_error);
+
+A sink received a CEC_MSG_CDC_HPD_REPORT_STATE message. This callback will
+do anything necessary to implement this hotplug change. The two arguments
+are the HPD Error State and HPD Error Code Operands from the CEC_MSG_CDC_HPD_REPORT_STATE
+message.
+
+
+Audio Return Channel Support
+----------------------------
+
+Called if a CEC_MSG_INITIATE_ARC message is received by an HDMI sink.
+This callback should start sending audio over the audio return channel. If
+successful it should return 0.
+
+ int (*sink_initiate_arc)(struct cec_adapter *adap);
+
+Called if a CEC_MSG_TERMINATE_ARC message is received by an HDMI sink.
+This callback should stop sending audio over the audio return channel. If
+successful it should return 0.
+
+ void (*sink_terminate_arc)(struct cec_adapter *adap);
+
+Called if a CEC_MSG_REPORT_ARC_INITIATED message is received by an
+HDMI source. This callback can be used to enable receiving audio from
+the audio return channel.
+
+ void (*source_arc_initiated)(struct cec_adapter *adap);
+
+Called if a CEC_MSG_REPORT_ARC_TERMINATED message is received by an
+HDMI source. This callback can be used to disable receiving audio from
+the audio return channel.
+
+ void (*source_arc_terminated)(struct cec_adapter *adap);
+
CEC framework functions
-----------------------
@@ -265,3 +331,12 @@ log_addrs->num_log_addrs set to 0. The block argument is ignored when
unconfiguring. This function will just return if the physical address is
invalid. Once the physical address becomes valid, then the framework will
attempt to claim these logical addresses.
+
+u8 cec_sink_cdc_hpd(struct cec_adapter *adap, u8 input_port, u8 cdc_hpd_state);
+
+If an HDMI receiver supports hotplug signalling over CDC (CEC_CAP_CDC_HPD is
+set), then the driver should call this function whenever the hotplug state
+changes for an input. This call will send an appropriate CDC message over
+the CEC line. It returns CEC_OP_HPD_ERROR_NONE on success, if the adapter
+is unconfigured it returns CEC_OP_HPD_ERROR_INITIATOR_WRONG_STATE and if
+the cec_transmit fails it returns CEC_OP_HPD_ERROR_OTHER.
diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c
index 6d7cad54a65d..14d33d983c52 100644
--- a/drivers/media/i2c/adv7511.c
+++ b/drivers/media/i2c/adv7511.c
@@ -857,6 +857,38 @@ static int adv7511_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
return 0;
}
+static u8 adv_cec_cdc_hpd(struct cec_adapter *adap, u8 cdc_hpd_state)
+{
+ switch (cdc_hpd_state) {
+ case CEC_OP_HPD_STATE_EDID_DISABLE:
+ case CEC_OP_HPD_STATE_EDID_ENABLE:
+ case CEC_OP_HPD_STATE_EDID_DISABLE_ENABLE:
+ return CEC_OP_HPD_ERROR_NONE;
+ case CEC_OP_HPD_STATE_CP_EDID_DISABLE:
+ case CEC_OP_HPD_STATE_CP_EDID_ENABLE:
+ case CEC_OP_HPD_STATE_CP_EDID_DISABLE_ENABLE:
+ default:
+ return CEC_OP_HPD_ERROR_INITIATOR_WRONG_STATE;
+ }
+}
+
+static int adv_sink_initiate_arc(struct cec_adapter *adap)
+{
+ return 0;
+}
+
+static void adv_sink_terminate_arc(struct cec_adapter *adap)
+{
+}
+
+static void adv_source_arc_initiated(struct cec_adapter *adap)
+{
+}
+
+static void adv_source_arc_terminated(struct cec_adapter *adap)
+{
+}
+
static void adv_cec_tx_raw_status(struct v4l2_subdev *sd, u8 tx_raw_status)
{
struct adv7511_state *state = get_adv7511_state(sd);
@@ -905,6 +937,11 @@ static const struct cec_adap_ops adv7511_cec_adap_ops = {
.adap_enable = adv7511_cec_adap_enable,
.adap_log_addr = adv7511_cec_adap_log_addr,
.adap_transmit = adv7511_cec_adap_transmit,
+ .source_cdc_hpd = adv_cec_cdc_hpd,
+ .sink_initiate_arc = adv_sink_initiate_arc,
+ .sink_terminate_arc = adv_sink_terminate_arc,
+ .source_arc_initiated = adv_source_arc_initiated,
+ .source_arc_terminated = adv_source_arc_terminated,
};
#endif
@@ -1910,7 +1947,8 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id *
#if IS_ENABLED(CONFIG_VIDEO_ADV7511_CEC)
state->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops,
state, dev_name(&client->dev), CEC_CAP_TRANSMIT |
- CEC_CAP_LOG_ADDRS | CEC_CAP_PASSTHROUGH | CEC_CAP_RC,
+ CEC_CAP_LOG_ADDRS | CEC_CAP_PASSTHROUGH | CEC_CAP_RC |
+ CEC_CAP_ARC | CEC_CAP_CDC_HPD,
ADV7511_MAX_ADDRS, &client->dev);
err = PTR_ERR_OR_ZERO(state->cec_adap);
if (err) {
diff --git a/drivers/staging/media/cec/cec-adap.c b/drivers/staging/media/cec/cec-adap.c
index 9fffddb7ac7e..90af9a8cf10f 100644
--- a/drivers/staging/media/cec/cec-adap.c
+++ b/drivers/staging/media/cec/cec-adap.c
@@ -54,6 +54,42 @@ static int cec_report_phys_addr(struct cec_adapter *adap, unsigned int la_idx);
adap->ops->op(adap, ## arg); \
} while (0)
+/*
+ * Two physical addresses are adjacent if they have a direct link.
+ * So 0.0.0.0 and 1.0.0.0 are adjacent, but not 0.0.0.0 and 1.1.0.0.
+ * And 2.3.0.0 and 2.3.1.0 are adjacent, but not 2.3.0.0 and 2.4.0.0.
+ *
+ * In other words, the two addresses share the same prefix, but then
+ * one has a zero and the other has a non-zero value. And the remaining
+ * components are all zero for both.
+ */
+static bool cec_pa_are_adjacent(const struct cec_adapter *adap, u16 pa1, u16 pa2)
+{
+ u16 mask = 0xf000;
+ int i;
+
+ if (pa1 == CEC_PHYS_ADDR_INVALID || pa2 == CEC_PHYS_ADDR_INVALID)
+ return false;
+ for (i = 0; i < 3; i++) {
+ if ((pa1 & mask) != (pa2 & mask))
+ break;
+ mask = (mask >> 4) | 0xf000;
+ }
+ if ((pa1 & ~mask) || (pa2 & ~mask))
+ return false;
+ if (!(pa1 & mask) ^ !(pa2 & mask))
+ return true;
+ return false;
+}
+
+static bool cec_la_are_adjacent(const struct cec_adapter *adap, u8 la1, u8 la2)
+{
+ u16 pa1 = adap->phys_addrs[la1];
+ u16 pa2 = adap->phys_addrs[la2];
+
+ return cec_pa_are_adjacent(adap, pa1, pa2);
+}
+
static int cec_log_addr2idx(const struct cec_adapter *adap, u8 log_addr)
{
int i;
@@ -1400,7 +1436,9 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
int la_idx = cec_log_addr2idx(adap, dest_laddr);
bool is_directed = la_idx >= 0;
bool from_unregistered = init_laddr == 0xf;
+ u16 cdc_phys_addr;
struct cec_msg tx_cec_msg = { };
+ u8 *tx_msg = tx_cec_msg.msg;
dprintk(1, "cec_receive_notify: %*ph\n", msg->len, msg->msg);
@@ -1411,12 +1449,57 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
}
/*
- * REPORT_PHYSICAL_ADDR, CEC_MSG_USER_CONTROL_PRESSED and
+ * ARC, CDC and REPORT_PHYSICAL_ADDR, CEC_MSG_USER_CONTROL_PRESSED and
* CEC_MSG_USER_CONTROL_RELEASED messages always have to be
* handled by the CEC core, even if the passthrough mode is on.
- * The others are just ignored if passthrough mode is on.
+ * ARC and CDC messages will never be seen even if passthrough is
+ * on, but the others are just passed on normally after we processed
+ * them.
*/
switch (msg->msg[1]) {
+ case CEC_MSG_INITIATE_ARC:
+ case CEC_MSG_TERMINATE_ARC:
+ case CEC_MSG_REQUEST_ARC_INITIATION:
+ case CEC_MSG_REQUEST_ARC_TERMINATION:
+ case CEC_MSG_REPORT_ARC_INITIATED:
+ case CEC_MSG_REPORT_ARC_TERMINATED:
+ /* ARC messages are never passed through if CAP_ARC is set */
+
+ /* Abort/ignore if ARC is not supported */
+ if (!(adap->capabilities & CEC_CAP_ARC)) {
+ /* Just abort if nobody is listening */
+ if (is_directed && !is_reply && !adap->cec_follower &&
+ !adap->follower_cnt)
+ return cec_feature_abort(adap, msg);
+ goto skip_processing;
+ }
+ /* Ignore if addressing is wrong */
+ if (is_broadcast || from_unregistered)
+ return 0;
+ break;
+
+ case CEC_MSG_CDC_MESSAGE:
+ switch (msg->msg[4]) {
+ case CEC_MSG_CDC_HPD_REPORT_STATE:
+ case CEC_MSG_CDC_HPD_SET_STATE:
+ /*
+ * CDC_HPD messages are never passed through if
+ * CAP_CDC_HPD is set
+ */
+
+ /* Ignore if CDC_HPD is not supported */
+ if (!(adap->capabilities & CEC_CAP_CDC_HPD))
+ goto skip_processing;
+ /* or the addressing is wrong */
+ if (!is_broadcast)
+ return 0;
+ break;
+ default:
+ /* Other CDC messages are ignored */
+ goto skip_processing;
+ }
+ break;
+
case CEC_MSG_GET_CEC_VERSION:
case CEC_MSG_GIVE_DEVICE_VENDOR_ID:
case CEC_MSG_ABORT:
@@ -1555,6 +1638,97 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
return cec_report_features(adap, la_idx);
return 0;
+ case CEC_MSG_REQUEST_ARC_INITIATION:
+ if (cec_is_sink(adap) ||
+ !cec_la_are_adjacent(adap, dest_laddr, init_laddr))
+ return cec_feature_refused(adap, msg);
+ cec_msg_initiate_arc(&tx_cec_msg, false);
+ return cec_transmit_msg(adap, &tx_cec_msg, false);
+
+ case CEC_MSG_REQUEST_ARC_TERMINATION:
+ if (cec_is_sink(adap) ||
+ !cec_la_are_adjacent(adap, dest_laddr, init_laddr))
+ return cec_feature_refused(adap, msg);
+ cec_msg_terminate_arc(&tx_cec_msg, false);
+ return cec_transmit_msg(adap, &tx_cec_msg, false);
+
+ case CEC_MSG_INITIATE_ARC:
+ if (!cec_is_sink(adap) ||
+ !cec_la_are_adjacent(adap, dest_laddr, init_laddr))
+ return cec_feature_refused(adap, msg);
+ if (call_op(adap, sink_initiate_arc))
+ return 0;
+ cec_msg_report_arc_initiated(&tx_cec_msg);
+ return cec_transmit_msg(adap, &tx_cec_msg, false);
+
+ case CEC_MSG_TERMINATE_ARC:
+ if (!cec_is_sink(adap) ||
+ !cec_la_are_adjacent(adap, dest_laddr, init_laddr))
+ return cec_feature_refused(adap, msg);
+ call_void_op(adap, sink_terminate_arc);
+ cec_msg_report_arc_terminated(&tx_cec_msg);
+ return cec_transmit_msg(adap, &tx_cec_msg, false);
+
+ case CEC_MSG_REPORT_ARC_INITIATED:
+ if (cec_is_sink(adap) ||
+ !cec_la_are_adjacent(adap, dest_laddr, init_laddr))
+ return cec_feature_refused(adap, msg);
+ call_void_op(adap, source_arc_initiated);
+ return 0;
+
+ case CEC_MSG_REPORT_ARC_TERMINATED:
+ if (cec_is_sink(adap) ||
+ !cec_la_are_adjacent(adap, dest_laddr, init_laddr))
+ return cec_feature_refused(adap, msg);
+ call_void_op(adap, source_arc_terminated);
+ return 0;
+
+ case CEC_MSG_CDC_MESSAGE: {
+ unsigned int shift;
+ unsigned int input_port;
+
+ cdc_phys_addr = (msg->msg[2] << 8) | msg->msg[3];
+ if (!cec_pa_are_adjacent(adap, cdc_phys_addr, adap->phys_addr))
+ return 0;
+
+ switch (msg->msg[4]) {
+ case CEC_MSG_CDC_HPD_REPORT_STATE:
+ /*
+ * Ignore if we're not a sink or the message comes from
+ * an upstream device.
+ */
+ if (!cec_is_sink(adap) || cdc_phys_addr <= adap->phys_addr)
+ return 0;
+ adap->ops->sink_cdc_hpd(adap, msg->msg[5] >> 4, msg->msg[5] & 0xf);
+ return 0;
+ case CEC_MSG_CDC_HPD_SET_STATE:
+ /* Ignore if we're not a source */
+ if (cec_is_sink(adap))
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+
+ input_port = msg->msg[5] >> 4;
+ for (shift = 0; shift < 16; shift += 4) {
+ if (cdc_phys_addr & (0xf000 >> shift))
+ continue;
+ cdc_phys_addr |= input_port << (12 - shift);
+ break;
+ }
+ if (cdc_phys_addr != adap->phys_addr)
+ return 0;
+
+ tx_cec_msg.len = 6;
+ /* broadcast reply */
+ tx_msg[0] = (adap->log_addrs.log_addr[0] << 4) | 0xf;
+ cec_msg_cdc_hpd_report_state(&tx_cec_msg,
+ msg->msg[5] & 0xf,
+ adap->ops->source_cdc_hpd(adap, msg->msg[5] & 0xf));
+ return cec_transmit_msg(adap, &tx_cec_msg, false);
+ }
+
default:
/*
* Unprocessed messages are aborted if userspace isn't doing
@@ -1605,6 +1779,26 @@ void cec_monitor_all_cnt_dec(struct cec_adapter *adap)
WARN_ON(call_op(adap, adap_monitor_all_enable, 0));
}
+/*
+ * Called by drivers to update the CDC HPD state of an input port.
+ */
+u8 cec_sink_cdc_hpd(struct cec_adapter *adap, u8 input_port, u8 cdc_hpd_state)
+{
+ struct cec_msg msg = { };
+ int err;
+
+ if (!adap->is_configured)
+ return CEC_OP_HPD_ERROR_INITIATOR_WRONG_STATE;
+
+ msg.msg[0] = (adap->log_addrs.log_addr[0] << 4) | 0xf;
+ cec_msg_cdc_hpd_set_state(&msg, input_port, cdc_hpd_state);
+ err = cec_transmit_msg(adap, &msg, false);
+ if (err)
+ return CEC_OP_HPD_ERROR_OTHER;
+ return CEC_OP_HPD_ERROR_NONE;
+}
+EXPORT_SYMBOL_GPL(cec_sink_cdc_hpd);
+
#ifdef CONFIG_MEDIA_CEC_DEBUG
/*
* Log the current state of the CEC adapter.
diff --git a/include/linux/cec.h b/include/linux/cec.h
index b3e22893a002..eea48a66a448 100644
--- a/include/linux/cec.h
+++ b/include/linux/cec.h
@@ -332,12 +332,17 @@ static inline bool cec_is_unconfigured(__u16 log_addr_mask)
#define CEC_CAP_TRANSMIT (1 << 2)
/*
* Passthrough all messages instead of processing them.
+ * Note: ARC and CDC messages are always processed.
*/
#define CEC_CAP_PASSTHROUGH (1 << 3)
/* Supports remote control */
#define CEC_CAP_RC (1 << 4)
/* Hardware can monitor all messages, not just directed and broadcast. */
#define CEC_CAP_MONITOR_ALL (1 << 5)
+/* Supports ARC */
+#define CEC_CAP_ARC (1 << 6)
+/* Supports CDC HPD */
+#define CEC_CAP_CDC_HPD (1 << 7)
/**
* struct cec_caps - CEC capabilities structure.
diff --git a/include/media/cec.h b/include/media/cec.h
index dc7854b855f3..133c59360137 100644
--- a/include/media/cec.h
+++ b/include/media/cec.h
@@ -119,6 +119,17 @@ struct cec_adap_ops {
/* High-level CEC message callback */
int (*received)(struct cec_adapter *adap, struct cec_msg *msg);
+
+ /* High-level CDC Hotplug Detect callbacks */
+ u8 (*source_cdc_hpd)(struct cec_adapter *adap, u8 cdc_hpd_state);
+ void (*sink_cdc_hpd)(struct cec_adapter *adap, u8 cdc_hpd_state,
+ u8 cdc_hpd_error);
+
+ /* High-level Audio Return Channel callbacks */
+ int (*sink_initiate_arc)(struct cec_adapter *adap);
+ void (*sink_terminate_arc)(struct cec_adapter *adap);
+ void (*source_arc_initiated)(struct cec_adapter *adap);
+ void (*source_arc_terminated)(struct cec_adapter *adap);
};
/*
@@ -210,6 +221,7 @@ void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr,
bool block);
int cec_transmit_msg(struct cec_adapter *adap, struct cec_msg *msg,
bool block);
+u8 cec_sink_cdc_hpd(struct cec_adapter *adap, u8 input_port, u8 cdc_hpd_state);
/* Called by the adapter */
void cec_transmit_done(struct cec_adapter *adap, u8 status, u8 arb_lost_cnt,

Privacy Policy