summaryrefslogtreecommitdiffstats
path: root/drivers/media/cec/cec-adap.c
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2017-02-10 13:02:31 -0200
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2017-03-22 11:11:17 -0300
commit533a3f7bc7919f8f5462d6b921532cf1d1ccf6cd (patch)
tree4873aeebb01cdfa84504bacd748b47acbe950398 /drivers/media/cec/cec-adap.c
parentb39f93efc698fadc94a5fa273798f9e317089c72 (diff)
downloadop-kernel-dev-533a3f7bc7919f8f5462d6b921532cf1d1ccf6cd.zip
op-kernel-dev-533a3f7bc7919f8f5462d6b921532cf1d1ccf6cd.tar.gz
[media] cec: allow specific messages even when unconfigured
The CEC specifications explicitly allows you to send poll messages and Image/Text View On messages to a TV, even when unconfigured (i.e. there is no hotplug signal detected). Some TVs will pull the HPD low when switching to another input, or when going into standby, but CEC should still be allowed to wake up such a display. Add support for sending messages with initiator 0xf (Unregistered) and destination 0 (TV) when no physical address is present. This also required another change: the CEC adapter has to stay enabled as long as 1) the CEC device is configured or 2) at least one filehandle is open for the CEC device. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/media/cec/cec-adap.c')
-rw-r--r--drivers/media/cec/cec-adap.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c
index 421472b..78a85c4 100644
--- a/drivers/media/cec/cec-adap.c
+++ b/drivers/media/cec/cec-adap.c
@@ -367,7 +367,6 @@ int cec_thread_func(void *_adap)
*/
err = wait_event_interruptible_timeout(adap->kthread_waitq,
kthread_should_stop() ||
- (!adap->is_configured && !adap->is_configuring) ||
(!adap->transmitting &&
!list_empty(&adap->transmit_queue)),
msecs_to_jiffies(CEC_XFER_TIMEOUT_MS));
@@ -382,8 +381,7 @@ int cec_thread_func(void *_adap)
mutex_lock(&adap->lock);
- if ((!adap->is_configured && !adap->is_configuring) ||
- kthread_should_stop()) {
+ if (kthread_should_stop()) {
cec_flush(adap);
goto unlock;
}
@@ -414,6 +412,7 @@ int cec_thread_func(void *_adap)
struct cec_data, list);
list_del_init(&data->list);
adap->transmit_queue_sz--;
+
/* Make this the current transmitting message */
adap->transmitting = data;
@@ -647,7 +646,8 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
cec_msg_initiator(msg));
return -EINVAL;
}
- if (!adap->is_configured && !adap->is_configuring)
+ if (!adap->is_configured && !adap->is_configuring &&
+ (msg->msg[0] != 0xf0 || msg->reply))
return -ENONET;
if (adap->transmit_queue_sz >= CEC_MAX_MSG_TX_QUEUE_SZ)
@@ -696,6 +696,7 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
if (fh)
list_add_tail(&data->xfer_list, &fh->xfer_list);
+
list_add_tail(&data->list, &adap->transmit_queue);
adap->transmit_queue_sz++;
if (!adap->transmitting)
@@ -1121,6 +1122,7 @@ static void cec_adap_unconfigure(struct cec_adapter *adap)
adap->is_configuring = false;
adap->is_configured = false;
memset(adap->phys_addrs, 0xff, sizeof(adap->phys_addrs));
+ cec_flush(adap);
wake_up_interruptible(&adap->kthread_waitq);
cec_post_state_event(adap);
}
@@ -1352,19 +1354,30 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
/* Disabling monitor all mode should always succeed */
if (adap->monitor_all_cnt)
WARN_ON(call_op(adap, adap_monitor_all_enable, false));
- WARN_ON(adap->ops->adap_enable(adap, false));
+ mutex_lock(&adap->devnode.lock);
+ if (list_empty(&adap->devnode.fhs))
+ WARN_ON(adap->ops->adap_enable(adap, false));
+ mutex_unlock(&adap->devnode.lock);
if (phys_addr == CEC_PHYS_ADDR_INVALID)
return;
}
- if (adap->ops->adap_enable(adap, true))
+ mutex_lock(&adap->devnode.lock);
+ if (list_empty(&adap->devnode.fhs) &&
+ adap->ops->adap_enable(adap, true)) {
+ mutex_unlock(&adap->devnode.lock);
return;
+ }
if (adap->monitor_all_cnt &&
call_op(adap, adap_monitor_all_enable, true)) {
- WARN_ON(adap->ops->adap_enable(adap, false));
+ if (list_empty(&adap->devnode.fhs))
+ WARN_ON(adap->ops->adap_enable(adap, false));
+ mutex_unlock(&adap->devnode.lock);
return;
}
+ mutex_unlock(&adap->devnode.lock);
+
adap->phys_addr = phys_addr;
cec_post_state_event(adap);
if (adap->log_addrs.num_log_addrs)
OpenPOWER on IntegriCloud