Commit b8d62f50 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

media: cec: add core support for low-level CEC pin monitoring

Add support for the new MONITOR_PIN mode.

Add the cec_pin_event function that the CEC pin code will call to queue pin
change events.
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Reviewed-by: default avatarMaxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent fdb8c88e
...@@ -153,6 +153,22 @@ static void cec_queue_event(struct cec_adapter *adap, ...@@ -153,6 +153,22 @@ static void cec_queue_event(struct cec_adapter *adap,
mutex_unlock(&adap->devnode.lock); mutex_unlock(&adap->devnode.lock);
} }
/* Notify userspace that the CEC pin changed state at the given time. */
void cec_queue_pin_event(struct cec_adapter *adap, bool is_high, ktime_t ts)
{
struct cec_event ev = {
.event = is_high ? CEC_EVENT_PIN_HIGH : CEC_EVENT_PIN_LOW,
};
struct cec_fh *fh;
mutex_lock(&adap->devnode.lock);
list_for_each_entry(fh, &adap->devnode.fhs, list)
if (fh->mode_follower == CEC_MODE_MONITOR_PIN)
cec_queue_event_fh(fh, &ev, ktime_to_ns(ts));
mutex_unlock(&adap->devnode.lock);
}
EXPORT_SYMBOL_GPL(cec_queue_pin_event);
/* /*
* Queue a new message for this filehandle. * Queue a new message for this filehandle.
* *
......
...@@ -370,6 +370,10 @@ static long cec_s_mode(struct cec_adapter *adap, struct cec_fh *fh, ...@@ -370,6 +370,10 @@ static long cec_s_mode(struct cec_adapter *adap, struct cec_fh *fh,
!(adap->capabilities & CEC_CAP_MONITOR_ALL)) !(adap->capabilities & CEC_CAP_MONITOR_ALL))
return -EINVAL; return -EINVAL;
if (mode_follower == CEC_MODE_MONITOR_PIN &&
!(adap->capabilities & CEC_CAP_MONITOR_PIN))
return -EINVAL;
/* Follower modes should always be able to send CEC messages */ /* Follower modes should always be able to send CEC messages */
if ((mode_initiator == CEC_MODE_NO_INITIATOR || if ((mode_initiator == CEC_MODE_NO_INITIATOR ||
!(adap->capabilities & CEC_CAP_TRANSMIT)) && !(adap->capabilities & CEC_CAP_TRANSMIT)) &&
...@@ -378,11 +382,11 @@ static long cec_s_mode(struct cec_adapter *adap, struct cec_fh *fh, ...@@ -378,11 +382,11 @@ static long cec_s_mode(struct cec_adapter *adap, struct cec_fh *fh,
return -EINVAL; return -EINVAL;
/* Monitor modes require CEC_MODE_NO_INITIATOR */ /* Monitor modes require CEC_MODE_NO_INITIATOR */
if (mode_initiator && mode_follower >= CEC_MODE_MONITOR) if (mode_initiator && mode_follower >= CEC_MODE_MONITOR_PIN)
return -EINVAL; return -EINVAL;
/* Monitor modes require CAP_NET_ADMIN */ /* Monitor modes require CAP_NET_ADMIN */
if (mode_follower >= CEC_MODE_MONITOR && !capable(CAP_NET_ADMIN)) if (mode_follower >= CEC_MODE_MONITOR_PIN && !capable(CAP_NET_ADMIN))
return -EPERM; return -EPERM;
mutex_lock(&adap->lock); mutex_lock(&adap->lock);
...@@ -421,8 +425,13 @@ static long cec_s_mode(struct cec_adapter *adap, struct cec_fh *fh, ...@@ -421,8 +425,13 @@ static long cec_s_mode(struct cec_adapter *adap, struct cec_fh *fh,
if (fh->mode_follower == CEC_MODE_FOLLOWER) if (fh->mode_follower == CEC_MODE_FOLLOWER)
adap->follower_cnt--; adap->follower_cnt--;
if (fh->mode_follower == CEC_MODE_MONITOR_PIN)
adap->monitor_pin_cnt--;
if (mode_follower == CEC_MODE_FOLLOWER) if (mode_follower == CEC_MODE_FOLLOWER)
adap->follower_cnt++; adap->follower_cnt++;
if (mode_follower == CEC_MODE_MONITOR_PIN) {
adap->monitor_pin_cnt++;
}
if (mode_follower == CEC_MODE_EXCL_FOLLOWER || if (mode_follower == CEC_MODE_EXCL_FOLLOWER ||
mode_follower == CEC_MODE_EXCL_FOLLOWER_PASSTHRU) { mode_follower == CEC_MODE_EXCL_FOLLOWER_PASSTHRU) {
adap->passthrough = adap->passthrough =
...@@ -566,6 +575,8 @@ static int cec_release(struct inode *inode, struct file *filp) ...@@ -566,6 +575,8 @@ static int cec_release(struct inode *inode, struct file *filp)
} }
if (fh->mode_follower == CEC_MODE_FOLLOWER) if (fh->mode_follower == CEC_MODE_FOLLOWER)
adap->follower_cnt--; adap->follower_cnt--;
if (fh->mode_follower == CEC_MODE_MONITOR_PIN)
adap->monitor_pin_cnt--;
if (fh->mode_follower == CEC_MODE_MONITOR_ALL) if (fh->mode_follower == CEC_MODE_MONITOR_ALL)
cec_monitor_all_cnt_dec(adap); cec_monitor_all_cnt_dec(adap);
mutex_unlock(&adap->lock); mutex_unlock(&adap->lock);
......
...@@ -177,6 +177,7 @@ struct cec_adapter { ...@@ -177,6 +177,7 @@ struct cec_adapter {
bool is_configuring; bool is_configuring;
bool is_configured; bool is_configured;
u32 monitor_all_cnt; u32 monitor_all_cnt;
u32 monitor_pin_cnt;
u32 follower_cnt; u32 follower_cnt;
struct cec_fh *cec_follower; struct cec_fh *cec_follower;
struct cec_fh *cec_initiator; struct cec_fh *cec_initiator;
...@@ -271,6 +272,16 @@ static inline void cec_received_msg(struct cec_adapter *adap, ...@@ -271,6 +272,16 @@ static inline void cec_received_msg(struct cec_adapter *adap,
cec_received_msg_ts(adap, msg, ktime_get()); cec_received_msg_ts(adap, msg, ktime_get());
} }
/**
* cec_queue_pin_event() - queue a pin event with a given timestamp.
*
* @adap: pointer to the cec adapter
* @is_high: when true the pin is high, otherwise it is low
* @ts: the timestamp for this event
*
*/
void cec_queue_pin_event(struct cec_adapter *adap, bool is_high, ktime_t ts);
/** /**
* cec_get_edid_phys_addr() - find and return the physical address * cec_get_edid_phys_addr() - find and return the physical address
* *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment