Lines Matching +full:wait +full:- +full:pin
1 // SPDX-License-Identifier: GPL-2.0-only
3 * cec-api.c - HDMI Consumer Electronics Control framework - API
21 #include <media/cec-pin.h>
22 #include "cec-priv.h"
23 #include "cec-pin-priv.h"
27 struct cec_fh *fh = filp->private_data; in cec_devnode_data()
29 return &fh->adap->devnode; in cec_devnode_data()
37 struct cec_fh *fh = filp->private_data; in cec_poll()
38 struct cec_adapter *adap = fh->adap; in cec_poll()
41 poll_wait(filp, &fh->wait, poll); in cec_poll()
44 mutex_lock(&adap->lock); in cec_poll()
45 if (adap->is_configured && in cec_poll()
46 adap->transmit_queue_sz < CEC_MAX_MSG_TX_QUEUE_SZ) in cec_poll()
48 if (fh->queued_msgs) in cec_poll()
50 if (fh->total_queued_events) in cec_poll()
52 mutex_unlock(&adap->lock); in cec_poll()
59 bool valid_initiator = adap->cec_initiator && adap->cec_initiator == fh; in cec_is_busy()
60 bool valid_follower = adap->cec_follower && adap->cec_follower == fh; in cec_is_busy()
71 return adap->cec_initiator || in cec_is_busy()
72 fh->mode_initiator == CEC_MODE_NO_INITIATOR; in cec_is_busy()
80 strscpy(caps.driver, adap->devnode.dev.parent->driver->name, in cec_adap_g_caps()
82 strscpy(caps.name, adap->name, sizeof(caps.name)); in cec_adap_g_caps()
83 caps.available_log_addrs = adap->available_log_addrs; in cec_adap_g_caps()
84 caps.capabilities = adap->capabilities; in cec_adap_g_caps()
87 return -EFAULT; in cec_adap_g_caps()
96 mutex_lock(&adap->lock); in cec_adap_g_phys_addr()
97 phys_addr = adap->phys_addr; in cec_adap_g_phys_addr()
98 mutex_unlock(&adap->lock); in cec_adap_g_phys_addr()
100 return -EFAULT; in cec_adap_g_phys_addr()
117 return -EINVAL; in cec_validate_phys_addr()
127 if (!(adap->capabilities & CEC_CAP_PHYS_ADDR)) in cec_adap_s_phys_addr()
128 return -ENOTTY; in cec_adap_s_phys_addr()
130 return -EFAULT; in cec_adap_s_phys_addr()
135 mutex_lock(&adap->lock); in cec_adap_s_phys_addr()
137 err = -EBUSY; in cec_adap_s_phys_addr()
140 mutex_unlock(&adap->lock); in cec_adap_s_phys_addr()
149 mutex_lock(&adap->lock); in cec_adap_g_log_addrs()
156 memcpy(&log_addrs, &adap->log_addrs, sizeof(log_addrs)); in cec_adap_g_log_addrs()
157 if (!adap->is_configured) in cec_adap_g_log_addrs()
160 mutex_unlock(&adap->lock); in cec_adap_g_log_addrs()
163 return -EFAULT; in cec_adap_g_log_addrs()
171 long err = -EBUSY; in cec_adap_s_log_addrs()
173 if (!(adap->capabilities & CEC_CAP_LOG_ADDRS)) in cec_adap_s_log_addrs()
174 return -ENOTTY; in cec_adap_s_log_addrs()
176 return -EFAULT; in cec_adap_s_log_addrs()
180 mutex_lock(&adap->lock); in cec_adap_s_log_addrs()
181 if (!adap->is_configuring && in cec_adap_s_log_addrs()
182 (!log_addrs.num_log_addrs || !adap->is_configured) && in cec_adap_s_log_addrs()
186 log_addrs = adap->log_addrs; in cec_adap_s_log_addrs()
188 mutex_unlock(&adap->lock); in cec_adap_s_log_addrs()
192 return -EFAULT; in cec_adap_s_log_addrs()
201 if (!(adap->capabilities & CEC_CAP_CONNECTOR_INFO)) in cec_adap_g_connector_info()
202 return -ENOTTY; in cec_adap_g_connector_info()
204 mutex_lock(&adap->lock); in cec_adap_g_connector_info()
205 if (copy_to_user(parg, &adap->conn_info, sizeof(adap->conn_info))) in cec_adap_g_connector_info()
206 ret = -EFAULT; in cec_adap_g_connector_info()
207 mutex_unlock(&adap->lock); in cec_adap_g_connector_info()
217 if (!(adap->capabilities & CEC_CAP_TRANSMIT)) in cec_transmit()
218 return -ENOTTY; in cec_transmit()
220 return -EFAULT; in cec_transmit()
222 mutex_lock(&adap->lock); in cec_transmit()
223 if (adap->log_addrs.num_log_addrs == 0) in cec_transmit()
224 err = -EPERM; in cec_transmit()
225 else if (adap->is_configuring) in cec_transmit()
226 err = -ENONET; in cec_transmit()
228 err = -EBUSY; in cec_transmit()
231 mutex_unlock(&adap->lock); in cec_transmit()
235 return -EFAULT; in cec_transmit()
239 /* Called by CEC_RECEIVE: wait for a message to arrive */
242 u32 timeout = msg->timeout; in cec_receive_msg()
246 mutex_lock(&fh->lock); in cec_receive_msg()
248 if (fh->queued_msgs) { in cec_receive_msg()
251 list_first_entry(&fh->msgs, in cec_receive_msg()
254 list_del(&entry->list); in cec_receive_msg()
255 *msg = entry->msg; in cec_receive_msg()
257 fh->queued_msgs--; in cec_receive_msg()
258 mutex_unlock(&fh->lock); in cec_receive_msg()
260 msg->timeout = timeout; in cec_receive_msg()
264 /* No, return EAGAIN in non-blocking mode or wait */ in cec_receive_msg()
265 mutex_unlock(&fh->lock); in cec_receive_msg()
267 /* Return when in non-blocking mode */ in cec_receive_msg()
269 return -EAGAIN; in cec_receive_msg()
271 if (msg->timeout) { in cec_receive_msg()
273 res = wait_event_interruptible_timeout(fh->wait, in cec_receive_msg()
274 fh->queued_msgs, in cec_receive_msg()
275 msecs_to_jiffies(msg->timeout)); in cec_receive_msg()
277 res = -ETIMEDOUT; in cec_receive_msg()
281 /* Wait indefinitely */ in cec_receive_msg()
282 res = wait_event_interruptible(fh->wait, in cec_receive_msg()
283 fh->queued_msgs); in cec_receive_msg()
297 return -EFAULT; in cec_receive()
304 return -EFAULT; in cec_receive()
317 mutex_lock(&fh->lock); in cec_dqevent()
318 while (!fh->total_queued_events && block) { in cec_dqevent()
319 mutex_unlock(&fh->lock); in cec_dqevent()
320 err = wait_event_interruptible(fh->wait, in cec_dqevent()
321 fh->total_queued_events); in cec_dqevent()
324 mutex_lock(&fh->lock); in cec_dqevent()
330 list_first_entry_or_null(&fh->events[i], in cec_dqevent()
333 if (entry && entry->ev.ts <= ts) { in cec_dqevent()
336 ts = ev->ev.ts; in cec_dqevent()
341 err = -EAGAIN; in cec_dqevent()
344 list_del(&ev->list); in cec_dqevent()
346 if (copy_to_user(parg, &ev->ev, sizeof(ev->ev))) in cec_dqevent()
347 err = -EFAULT; in cec_dqevent()
350 fh->queued_events[ev_idx]--; in cec_dqevent()
351 fh->total_queued_events--; in cec_dqevent()
354 mutex_unlock(&fh->lock); in cec_dqevent()
361 u32 mode = fh->mode_initiator | fh->mode_follower; in cec_g_mode()
364 return -EFAULT; in cec_g_mode()
378 return -EFAULT; in cec_s_mode()
381 return -EINVAL; in cec_s_mode()
390 return -EINVAL; in cec_s_mode()
394 !(adap->capabilities & CEC_CAP_MONITOR_ALL)) { in cec_s_mode()
396 return -EINVAL; in cec_s_mode()
400 !(adap->capabilities & CEC_CAP_MONITOR_PIN)) { in cec_s_mode()
402 return -EINVAL; in cec_s_mode()
407 !(adap->capabilities & CEC_CAP_TRANSMIT)) && in cec_s_mode()
411 return -EINVAL; in cec_s_mode()
418 return -EINVAL; in cec_s_mode()
423 return -EPERM; in cec_s_mode()
425 mutex_lock(&adap->lock); in cec_s_mode()
432 adap->cec_follower && adap->cec_follower != fh) in cec_s_mode()
433 err = -EBUSY; in cec_s_mode()
439 adap->cec_initiator && adap->cec_initiator != fh) in cec_s_mode()
440 err = -EBUSY; in cec_s_mode()
443 bool old_mon_all = fh->mode_follower == CEC_MODE_MONITOR_ALL; in cec_s_mode()
455 bool old_mon_pin = fh->mode_follower == CEC_MODE_MONITOR_PIN; in cec_s_mode()
468 mutex_unlock(&adap->lock); in cec_s_mode()
472 if (fh->mode_follower == CEC_MODE_FOLLOWER) in cec_s_mode()
473 adap->follower_cnt--; in cec_s_mode()
475 adap->follower_cnt++; in cec_s_mode()
481 ev.event = adap->cec_pin_is_high ? CEC_EVENT_PIN_CEC_HIGH : in cec_s_mode()
487 adap->passthrough = in cec_s_mode()
489 adap->cec_follower = fh; in cec_s_mode()
490 } else if (adap->cec_follower == fh) { in cec_s_mode()
491 adap->passthrough = false; in cec_s_mode()
492 adap->cec_follower = NULL; in cec_s_mode()
495 adap->cec_initiator = fh; in cec_s_mode()
496 else if (adap->cec_initiator == fh) in cec_s_mode()
497 adap->cec_initiator = NULL; in cec_s_mode()
498 fh->mode_initiator = mode_initiator; in cec_s_mode()
499 fh->mode_follower = mode_follower; in cec_s_mode()
500 mutex_unlock(&adap->lock); in cec_s_mode()
506 struct cec_fh *fh = filp->private_data; in cec_ioctl()
507 struct cec_adapter *adap = fh->adap; in cec_ioctl()
508 bool block = !(filp->f_flags & O_NONBLOCK); in cec_ioctl()
512 return -ENODEV; in cec_ioctl()
549 return -ENOTTY; in cec_ioctl()
556 container_of(inode->i_cdev, struct cec_devnode, cdev); in cec_open()
571 return -ENOMEM; in cec_open()
573 INIT_LIST_HEAD(&fh->msgs); in cec_open()
574 INIT_LIST_HEAD(&fh->xfer_list); in cec_open()
576 INIT_LIST_HEAD(&fh->events[i]); in cec_open()
577 mutex_init(&fh->lock); in cec_open()
578 init_waitqueue_head(&fh->wait); in cec_open()
580 fh->mode_initiator = CEC_MODE_INITIATOR; in cec_open()
581 fh->adap = adap; in cec_open()
589 filp->private_data = fh; in cec_open()
592 ev.state_change.phys_addr = adap->phys_addr; in cec_open()
593 ev.state_change.log_addr_mask = adap->log_addrs.log_addr_mask; in cec_open()
595 adap->conn_info.type != CEC_CONNECTOR_TYPE_NO_CONNECTOR; in cec_open()
598 if (adap->pin && adap->pin->ops->read_hpd && in cec_open()
599 !adap->devnode.unregistered) { in cec_open()
600 err = adap->pin->ops->read_hpd(adap); in cec_open()
607 if (adap->pin && adap->pin->ops->read_5v && in cec_open()
608 !adap->devnode.unregistered) { in cec_open()
609 err = adap->pin->ops->read_5v(adap); in cec_open()
618 mutex_lock(&devnode->lock); in cec_open()
619 mutex_lock(&devnode->lock_fhs); in cec_open()
620 list_add(&fh->list, &devnode->fhs); in cec_open()
621 mutex_unlock(&devnode->lock_fhs); in cec_open()
622 mutex_unlock(&devnode->lock); in cec_open()
632 struct cec_fh *fh = filp->private_data; in cec_release()
635 mutex_lock(&adap->lock); in cec_release()
636 if (adap->cec_initiator == fh) in cec_release()
637 adap->cec_initiator = NULL; in cec_release()
638 if (adap->cec_follower == fh) { in cec_release()
639 adap->cec_follower = NULL; in cec_release()
640 adap->passthrough = false; in cec_release()
642 if (fh->mode_follower == CEC_MODE_FOLLOWER) in cec_release()
643 adap->follower_cnt--; in cec_release()
644 if (fh->mode_follower == CEC_MODE_MONITOR_PIN) in cec_release()
646 if (fh->mode_follower == CEC_MODE_MONITOR_ALL) in cec_release()
648 mutex_unlock(&adap->lock); in cec_release()
650 mutex_lock(&devnode->lock); in cec_release()
651 mutex_lock(&devnode->lock_fhs); in cec_release()
652 list_del(&fh->list); in cec_release()
653 mutex_unlock(&devnode->lock_fhs); in cec_release()
654 mutex_unlock(&devnode->lock); in cec_release()
657 mutex_lock(&adap->lock); in cec_release()
658 while (!list_empty(&fh->xfer_list)) { in cec_release()
660 list_first_entry(&fh->xfer_list, struct cec_data, xfer_list); in cec_release()
662 data->blocking = false; in cec_release()
663 data->fh = NULL; in cec_release()
664 list_del_init(&data->xfer_list); in cec_release()
666 mutex_unlock(&adap->lock); in cec_release()
667 while (!list_empty(&fh->msgs)) { in cec_release()
669 list_first_entry(&fh->msgs, struct cec_msg_entry, list); in cec_release()
671 list_del(&entry->list); in cec_release()
675 while (!list_empty(&fh->events[i])) { in cec_release()
677 list_first_entry(&fh->events[i], in cec_release()
680 list_del(&entry->list); in cec_release()
687 filp->private_data = NULL; in cec_release()