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: Hans Verkuil <hans.verkuil@cisco.com> Reviewed-by: Maxime Ripard <maxime.ripard@free-electrons.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
This commit is contained in:

committed by
Mauro Carvalho Chehab

parent
fdb8c88e92
commit
b8d62f50b1
@@ -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,
|
|||||||
!(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,
|
|||||||
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,
|
|||||||
|
|
||||||
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)
|
|||||||
}
|
}
|
||||||
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 {
|
|||||||
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,
|
|||||||
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
|
||||||
*
|
*
|
||||||
|
Reference in New Issue
Block a user