mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-26 21:54:11 +08:00
media: cec: add the adap_monitor_pin_enable op
Some devices can monitor the CEC pin using an interrupt, but you only want to enable the interrupt if you actually switch to pin monitoring mode. So add a new op that is called when pin monitoring needs to be switched on or off. Also fix a small bug where the initial CEC pin event was sent again when calling S_MODE twice with the same CEC_MODE_MONITOR_PIN mode. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
This commit is contained in:
parent
cc05c0ba23
commit
48ea2e926b
@ -2053,6 +2053,29 @@ void cec_monitor_all_cnt_dec(struct cec_adapter *adap)
|
||||
WARN_ON(call_op(adap, adap_monitor_all_enable, 0));
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper functions to keep track of the 'monitor pin' use count.
|
||||
*
|
||||
* These functions are called with adap->lock held.
|
||||
*/
|
||||
int cec_monitor_pin_cnt_inc(struct cec_adapter *adap)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (adap->monitor_pin_cnt == 0)
|
||||
ret = call_op(adap, adap_monitor_pin_enable, 1);
|
||||
if (ret == 0)
|
||||
adap->monitor_pin_cnt++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cec_monitor_pin_cnt_dec(struct cec_adapter *adap)
|
||||
{
|
||||
adap->monitor_pin_cnt--;
|
||||
if (adap->monitor_pin_cnt == 0)
|
||||
WARN_ON(call_op(adap, adap_monitor_pin_enable, 0));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
/*
|
||||
* Log the current state of the CEC adapter.
|
||||
|
@ -354,6 +354,7 @@ static long cec_s_mode(struct cec_adapter *adap, struct cec_fh *fh,
|
||||
u32 mode;
|
||||
u8 mode_initiator;
|
||||
u8 mode_follower;
|
||||
bool send_pin_event = false;
|
||||
long err = 0;
|
||||
|
||||
if (copy_from_user(&mode, parg, sizeof(mode)))
|
||||
@ -433,6 +434,19 @@ static long cec_s_mode(struct cec_adapter *adap, struct cec_fh *fh,
|
||||
}
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
bool old_mon_pin = fh->mode_follower == CEC_MODE_MONITOR_PIN;
|
||||
bool new_mon_pin = mode_follower == CEC_MODE_MONITOR_PIN;
|
||||
|
||||
if (old_mon_pin != new_mon_pin) {
|
||||
send_pin_event = new_mon_pin;
|
||||
if (new_mon_pin)
|
||||
err = cec_monitor_pin_cnt_inc(adap);
|
||||
else
|
||||
cec_monitor_pin_cnt_dec(adap);
|
||||
}
|
||||
}
|
||||
|
||||
if (err) {
|
||||
mutex_unlock(&adap->lock);
|
||||
return err;
|
||||
@ -440,11 +454,9 @@ static long cec_s_mode(struct cec_adapter *adap, struct cec_fh *fh,
|
||||
|
||||
if (fh->mode_follower == CEC_MODE_FOLLOWER)
|
||||
adap->follower_cnt--;
|
||||
if (fh->mode_follower == CEC_MODE_MONITOR_PIN)
|
||||
adap->monitor_pin_cnt--;
|
||||
if (mode_follower == CEC_MODE_FOLLOWER)
|
||||
adap->follower_cnt++;
|
||||
if (mode_follower == CEC_MODE_MONITOR_PIN) {
|
||||
if (send_pin_event) {
|
||||
struct cec_event ev = {
|
||||
.flags = CEC_EVENT_FL_INITIAL_STATE,
|
||||
};
|
||||
@ -452,7 +464,6 @@ static long cec_s_mode(struct cec_adapter *adap, struct cec_fh *fh,
|
||||
ev.event = adap->cec_pin_is_high ? CEC_EVENT_PIN_CEC_HIGH :
|
||||
CEC_EVENT_PIN_CEC_LOW;
|
||||
cec_queue_event_fh(fh, &ev, 0);
|
||||
adap->monitor_pin_cnt++;
|
||||
}
|
||||
if (mode_follower == CEC_MODE_EXCL_FOLLOWER ||
|
||||
mode_follower == CEC_MODE_EXCL_FOLLOWER_PASSTHRU) {
|
||||
@ -608,7 +619,7 @@ static int cec_release(struct inode *inode, struct file *filp)
|
||||
if (fh->mode_follower == CEC_MODE_FOLLOWER)
|
||||
adap->follower_cnt--;
|
||||
if (fh->mode_follower == CEC_MODE_MONITOR_PIN)
|
||||
adap->monitor_pin_cnt--;
|
||||
cec_monitor_pin_cnt_dec(adap);
|
||||
if (fh->mode_follower == CEC_MODE_MONITOR_ALL)
|
||||
cec_monitor_all_cnt_dec(adap);
|
||||
mutex_unlock(&adap->lock);
|
||||
|
@ -40,6 +40,8 @@ void cec_put_device(struct cec_devnode *devnode);
|
||||
/* cec-adap.c */
|
||||
int cec_monitor_all_cnt_inc(struct cec_adapter *adap);
|
||||
void cec_monitor_all_cnt_dec(struct cec_adapter *adap);
|
||||
int cec_monitor_pin_cnt_inc(struct cec_adapter *adap);
|
||||
void cec_monitor_pin_cnt_dec(struct cec_adapter *adap);
|
||||
int cec_adap_status(struct seq_file *file, void *priv);
|
||||
int cec_thread_func(void *_adap);
|
||||
void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block);
|
||||
|
@ -122,6 +122,7 @@ struct cec_adap_ops {
|
||||
/* Low-level callbacks */
|
||||
int (*adap_enable)(struct cec_adapter *adap, bool enable);
|
||||
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);
|
||||
int (*adap_transmit)(struct cec_adapter *adap, u8 attempts,
|
||||
u32 signal_free_time, struct cec_msg *msg);
|
||||
|
Loading…
Reference in New Issue
Block a user