Lines Matching +full:skip +full:- +full:power +full:- +full:up

1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright 2021-2024 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
9 #include "cec-splitter.h"
24 if (msg->msg[1] == CEC_MSG_FEATURE_ABORT) in cec_feature_abort_reason()
30 cec_msg_feature_abort(&tx_msg, msg->msg[1], reason); in cec_feature_abort_reason()
37 struct cec_adapter *adap = p->adap; in cec_port_out_active_source()
40 if (!adap->is_configured) in cec_port_out_active_source()
42 p->is_active_source = true; in cec_port_out_active_source()
43 cec_msg_init(&msg, adap->log_addrs.log_addr[0], 0); in cec_port_out_active_source()
44 cec_msg_active_source(&msg, adap->phys_addr); in cec_port_out_active_source()
53 for (i = 0; i < splitter->num_out_ports; i++) in cec_out_active_source()
54 cec_port_out_active_source(splitter->ports[i]); in cec_out_active_source()
60 struct cec_adapter *adap = p->adap; in cec_port_out_standby()
63 if (!adap->is_configured) in cec_port_out_standby()
65 cec_msg_init(&msg, adap->log_addrs.log_addr[0], 0); in cec_port_out_standby()
75 for (i = 0; i < splitter->num_out_ports; i++) in cec_out_standby()
76 cec_port_out_standby(splitter->ports[i]); in cec_out_standby()
82 struct cec_adapter *adap = p->adap; in cec_port_out_wakeup()
83 u8 la = adap->log_addrs.log_addr[0]; in cec_port_out_wakeup()
99 for (i = 0; i < splitter->num_out_ports; i++) in cec_out_wakeup()
100 cec_port_out_wakeup(splitter->ports[i], opcode); in cec_out_wakeup()
104 * Update the power state of the unconfigured CEC device to either
110 p->video_latency = 1; in cec_splitter_unconfigured_output()
111 p->power_status = p->splitter->is_standby ? in cec_splitter_unconfigured_output()
115 p->out_give_device_power_status_seq = 0; in cec_splitter_unconfigured_output()
116 p->out_give_device_power_status_ts = ktime_set(0, 0); in cec_splitter_unconfigured_output()
117 p->out_request_current_latency_seq = 0; in cec_splitter_unconfigured_output()
118 p->out_request_current_latency_ts = ktime_set(0, 0); in cec_splitter_unconfigured_output()
122 * Update the power state of the newly configured CEC device to either
128 p->video_latency = 1; in cec_splitter_configured_output()
129 p->power_status = p->splitter->is_standby ? in cec_splitter_configured_output()
132 if (p->splitter->is_standby) { in cec_splitter_configured_output()
150 for (i = 0; i < splitter->num_out_ports; i++) { in cec_out_passthrough()
151 struct cec_splitter_port *p = splitter->ports[i]; in cec_out_passthrough()
152 struct cec_adapter *adap = p->adap; in cec_out_passthrough()
155 if (!adap->is_configured) in cec_out_passthrough()
157 cec_msg_init(&msg, adap->log_addrs.log_addr[0], 0); in cec_out_passthrough()
158 msg.len = in_msg->len; in cec_out_passthrough()
159 memcpy(msg.msg + 1, in_msg->msg + 1, msg.len - 1); in cec_out_passthrough()
176 for (i = 0; i < splitter->num_out_ports; i++) { in cec_out_report_current_latency()
177 struct cec_splitter_port *p = splitter->ports[i]; in cec_out_report_current_latency()
178 struct cec_adapter *adap = p->adap; in cec_out_report_current_latency()
180 /* Skip unconfigured ports */ in cec_out_report_current_latency()
181 if (!adap->is_configured) in cec_out_report_current_latency()
184 if (p->out_request_current_latency_seq) in cec_out_report_current_latency()
186 reply_lat += p->video_latency - 1; in cec_out_report_current_latency()
194 for (i = 0; i < splitter->num_out_ports; i++) { in cec_out_report_current_latency()
195 struct cec_splitter_port *p = splitter->ports[i]; in cec_out_report_current_latency()
197 p->out_request_current_latency_seq = 0; in cec_out_report_current_latency()
198 p->out_request_current_latency_ts = ktime_set(0, 0); in cec_out_report_current_latency()
205 if (!cnt || !input_adap->is_configured) in cec_out_report_current_latency()
210 cec_msg_init(&reply, input_adap->log_addrs.log_addr[0], in cec_out_report_current_latency()
211 splitter->request_current_latency_dest); in cec_out_report_current_latency()
212 cec_msg_report_current_latency(&reply, input_adap->phys_addr, in cec_out_report_current_latency()
224 for (i = 0; i < splitter->num_out_ports; i++) { in cec_out_request_current_latency()
225 struct cec_splitter_port *p = splitter->ports[i]; in cec_out_request_current_latency()
226 struct cec_adapter *adap = p->adap; in cec_out_request_current_latency()
228 if (!adap->is_configured) { in cec_out_request_current_latency()
230 p->out_request_current_latency_seq = 0; in cec_out_request_current_latency()
231 p->out_request_current_latency_ts = ktime_set(0, 0); in cec_out_request_current_latency()
232 } else if (!p->out_request_current_latency_seq) { in cec_out_request_current_latency()
239 p->out_request_current_latency_ts = now; in cec_out_request_current_latency()
243 for (i = 0; i < splitter->num_out_ports; i++) { in cec_out_request_current_latency()
244 struct cec_splitter_port *p = splitter->ports[i]; in cec_out_request_current_latency()
245 struct cec_adapter *adap = p->adap; in cec_out_request_current_latency()
248 if (!adap->is_configured) in cec_out_request_current_latency()
250 cec_msg_init(&msg, adap->log_addrs.log_addr[0], 0); in cec_out_request_current_latency()
251 cec_msg_request_current_latency(&msg, true, adap->phys_addr); in cec_out_request_current_latency()
254 p->out_request_current_latency_seq = msg.sequence | (1U << 31); in cec_out_request_current_latency()
257 return error ? -ENODEV : 0; in cec_out_request_current_latency()
261 * See if all output ports received the Report Power Status message,
268 /* The target power status of the splitter itself */ in cec_out_report_power_status()
269 u8 splitter_pwr = splitter->is_standby ? in cec_out_report_power_status()
272 * The transient power status of the splitter, used if not all in cec_out_report_power_status()
273 * output report the target power status. in cec_out_report_power_status()
275 u8 splitter_transient_pwr = splitter->is_standby ? in cec_out_report_power_status()
280 for (i = 0; i < splitter->num_out_ports; i++) { in cec_out_report_power_status()
281 struct cec_splitter_port *p = splitter->ports[i]; in cec_out_report_power_status()
283 /* Skip if no sink was found (HPD was low for more than 5s) */ in cec_out_report_power_status()
284 if (!p->found_sink) in cec_out_report_power_status()
288 if (p->out_give_device_power_status_seq) in cec_out_report_power_status()
290 if (p->power_status != splitter_pwr) in cec_out_report_power_status()
298 for (i = 0; i < splitter->num_out_ports; i++) { in cec_out_report_power_status()
299 struct cec_splitter_port *p = splitter->ports[i]; in cec_out_report_power_status()
301 p->out_give_device_power_status_seq = 0; in cec_out_report_power_status()
302 p->out_give_device_power_status_ts = ktime_set(0, 0); in cec_out_report_power_status()
306 if (!input_adap->is_configured) in cec_out_report_power_status()
309 /* Reply with the new power status */ in cec_out_report_power_status()
310 cec_msg_init(&reply, input_adap->log_addrs.log_addr[0], in cec_out_report_power_status()
311 splitter->give_device_power_status_dest); in cec_out_report_power_status()
316 /* Transmit Give Device Power Status to all output ports */
323 for (i = 0; i < splitter->num_out_ports; i++) { in cec_out_give_device_power_status()
324 struct cec_splitter_port *p = splitter->ports[i]; in cec_out_give_device_power_status()
325 struct cec_adapter *adap = p->adap; in cec_out_give_device_power_status()
333 if (adap->is_configured && !p->out_give_device_power_status_seq) in cec_out_give_device_power_status()
334 p->out_give_device_power_status_ts = now; in cec_out_give_device_power_status()
337 for (i = 0; i < splitter->num_out_ports; i++) { in cec_out_give_device_power_status()
338 struct cec_splitter_port *p = splitter->ports[i]; in cec_out_give_device_power_status()
339 struct cec_adapter *adap = p->adap; in cec_out_give_device_power_status()
342 if (!adap->is_configured) in cec_out_give_device_power_status()
345 cec_msg_init(&msg, adap->log_addrs.log_addr[0], 0); in cec_out_give_device_power_status()
349 p->out_give_device_power_status_seq = msg.sequence | (1U << 31); in cec_out_give_device_power_status()
352 return error ? -ENODEV : 0; in cec_out_give_device_power_status()
364 if (msg->len < 2) in cec_splitter_received_input()
365 return -ENOMSG; in cec_splitter_received_input()
367 switch (msg->msg[1]) { in cec_splitter_received_input()
377 p->splitter->is_standby = true; in cec_splitter_received_input()
378 cec_out_standby(p->splitter); in cec_splitter_received_input()
383 p->splitter->is_standby = false; in cec_splitter_received_input()
384 cec_out_wakeup(p->splitter, msg->msg[1]); in cec_splitter_received_input()
388 cec_out_active_source(p->splitter); in cec_splitter_received_input()
392 cec_out_passthrough(p->splitter, msg); in cec_splitter_received_input()
396 p->splitter->give_device_power_status_dest = in cec_splitter_received_input()
398 if (cec_out_give_device_power_status(p->splitter)) in cec_splitter_received_input()
399 cec_feature_abort_reason(p->adap, msg, in cec_splitter_received_input()
406 p->splitter->request_current_latency_dest = in cec_splitter_received_input()
409 if (pa == p->adap->phys_addr && in cec_splitter_received_input()
410 cec_out_request_current_latency(p->splitter)) in cec_splitter_received_input()
411 cec_feature_abort_reason(p->adap, msg, in cec_splitter_received_input()
417 return -ENOMSG; in cec_splitter_received_input()
419 return -ENOMSG; in cec_splitter_received_input()
426 struct cec_splitter *splitter = p->splitter; in cec_splitter_nb_transmit_canceled_output()
427 u32 seq = msg->sequence | (1U << 31); in cec_splitter_nb_transmit_canceled_output()
430 * If this is the result of a failed non-blocking transmit, or it is in cec_splitter_nb_transmit_canceled_output()
431 * the result of the failed reply to a non-blocking transmit, then in cec_splitter_nb_transmit_canceled_output()
432 * check if the original transmit was to get the current power status in cec_splitter_nb_transmit_canceled_output()
435 * power status as the splitter, or has no video latency. in cec_splitter_nb_transmit_canceled_output()
437 if ((cec_msg_recv_is_tx_result(msg) && !(msg->tx_status & CEC_TX_STATUS_OK)) || in cec_splitter_nb_transmit_canceled_output()
438 (cec_msg_recv_is_rx_result(msg) && !(msg->rx_status & CEC_RX_STATUS_OK))) { in cec_splitter_nb_transmit_canceled_output()
439 u8 tx_op = msg->msg[1]; in cec_splitter_nb_transmit_canceled_output()
441 if (msg->len < 2) in cec_splitter_nb_transmit_canceled_output()
444 (msg->rx_status & CEC_RX_STATUS_FEATURE_ABORT)) in cec_splitter_nb_transmit_canceled_output()
445 tx_op = msg->msg[2]; in cec_splitter_nb_transmit_canceled_output()
448 if (p->out_give_device_power_status_seq != seq) in cec_splitter_nb_transmit_canceled_output()
450 p->out_give_device_power_status_seq = 0; in cec_splitter_nb_transmit_canceled_output()
451 p->out_give_device_power_status_ts = ktime_set(0, 0); in cec_splitter_nb_transmit_canceled_output()
452 p->power_status = splitter->is_standby ? in cec_splitter_nb_transmit_canceled_output()
458 if (p->out_request_current_latency_seq != seq) in cec_splitter_nb_transmit_canceled_output()
460 p->video_latency = 1; in cec_splitter_nb_transmit_canceled_output()
461 p->out_request_current_latency_seq = 0; in cec_splitter_nb_transmit_canceled_output()
462 p->out_request_current_latency_ts = ktime_set(0, 0); in cec_splitter_nb_transmit_canceled_output()
470 if (p->out_request_current_latency_seq != seq) in cec_splitter_nb_transmit_canceled_output()
472 p->out_request_current_latency_ts = ns_to_ktime(msg->tx_ts); in cec_splitter_nb_transmit_canceled_output()
484 struct cec_adapter *adap = p->adap; in cec_splitter_received_output()
485 struct cec_splitter *splitter = p->splitter; in cec_splitter_received_output()
486 u32 seq = msg->sequence | (1U << 31); in cec_splitter_received_output()
490 if (!adap->is_configured || msg->len < 2) in cec_splitter_received_output()
491 return -ENOMSG; in cec_splitter_received_output()
493 switch (msg->msg[1]) { in cec_splitter_received_output()
499 pwr = splitter->is_standby ? in cec_splitter_received_output()
502 p->power_status = pwr; in cec_splitter_received_output()
503 if (p->out_give_device_power_status_seq == seq) { in cec_splitter_received_output()
504 p->out_give_device_power_status_seq = 0; in cec_splitter_received_output()
505 p->out_give_device_power_status_ts = ktime_set(0, 0); in cec_splitter_received_output()
522 p->video_latency = video_lat; in cec_splitter_received_output()
523 if (p->out_request_current_latency_seq == seq) { in cec_splitter_received_output()
524 p->out_request_current_latency_seq = 0; in cec_splitter_received_output()
525 p->out_request_current_latency_ts = ktime_set(0, 0); in cec_splitter_received_output()
539 p->is_active_source = false; in cec_splitter_received_output()
543 if (!p->is_active_source) in cec_splitter_received_output()
546 cec_msg_active_source(&reply, adap->phys_addr); in cec_splitter_received_output()
552 cec_msg_report_power_status(&reply, splitter->is_standby ? in cec_splitter_received_output()
560 if (pa == adap->phys_addr) { in cec_splitter_received_output()
568 return -ENOMSG; in cec_splitter_received_output()
570 return -ENOMSG; in cec_splitter_received_output()
583 u8 pwr = splitter->is_standby ? in cec_splitter_poll()
585 unsigned int max_delay_ms = input_adap->xfer_timeout_ms + 2000; in cec_splitter_poll()
589 for (i = 0; i < splitter->num_out_ports; i++) { in cec_splitter_poll()
590 struct cec_splitter_port *p = splitter->ports[i]; in cec_splitter_poll()
597 pwr_delta = ktime_ms_delta(now, p->out_give_device_power_status_ts); in cec_splitter_poll()
598 pwr_timeout = p->out_give_device_power_status_seq && in cec_splitter_poll()
600 lat_delta = ktime_ms_delta(now, p->out_request_current_latency_ts); in cec_splitter_poll()
601 lat_timeout = p->out_request_current_latency_seq && in cec_splitter_poll()
608 if (p->found_sink && ktime_to_ns(p->lost_sink_ts) && in cec_splitter_poll()
609 ktime_ms_delta(now, p->lost_sink_ts) > 5000) { in cec_splitter_poll()
611 dev_info(splitter->dev, in cec_splitter_poll()
613 p->port); in cec_splitter_poll()
614 p->found_sink = false; in cec_splitter_poll()
615 p->lost_sink_ts = ktime_set(0, 0); in cec_splitter_poll()
620 * If the power status request timed out, then set the port's in cec_splitter_poll()
621 * power status to that of the splitter, ensuring a consistent in cec_splitter_poll()
622 * power state. in cec_splitter_poll()
625 mutex_lock(&p->adap->lock); in cec_splitter_poll()
627 dev_info(splitter->dev, in cec_splitter_poll()
628 "port %u: give up on power status for seq %u\n", in cec_splitter_poll()
629 p->port, in cec_splitter_poll()
630 p->out_give_device_power_status_seq & ~(1 << 31)); in cec_splitter_poll()
631 p->power_status = pwr; in cec_splitter_poll()
632 p->out_give_device_power_status_seq = 0; in cec_splitter_poll()
633 p->out_give_device_power_status_ts = ktime_set(0, 0); in cec_splitter_poll()
634 mutex_unlock(&p->adap->lock); in cec_splitter_poll()
643 mutex_lock(&p->adap->lock); in cec_splitter_poll()
645 dev_info(splitter->dev, in cec_splitter_poll()
646 "port %u: give up on latency for seq %u\n", in cec_splitter_poll()
647 p->port, in cec_splitter_poll()
648 p->out_request_current_latency_seq & ~(1 << 31)); in cec_splitter_poll()
649 p->video_latency = 1; in cec_splitter_poll()
650 p->out_request_current_latency_seq = 0; in cec_splitter_poll()
651 p->out_request_current_latency_ts = ktime_set(0, 0); in cec_splitter_poll()
652 mutex_unlock(&p->adap->lock); in cec_splitter_poll()