Lines Matching +full:port +full:- +full:1
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright 2021-2024 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
7 * Currently this driver does not fully support the serial port of the
8 * Extron, only the USB port is fully supported.
10 * Issues specific to using the serial port instead of the USB since the
11 * serial port doesn't detect if the device is powered off:
13 * - Some periodic ping mechanism is needed to detect when the Extron is
15 * - What to do when it is powered off and the driver is modprobed? Keep
29 #include "extron-da-hd-4k-plus.h"
37 MODULE_PARM_DESC(debug, "debug level (0-1)");
51 MODULE_PARM_DESC(hpd_never_low, "Input HPD will never go low (1), or go low if all output HPDs are …
174 dev_warn(&serio->dev, "unable to write byte after 100 attempts\n"); in extron_send_byte()
175 return err ? -EIO : 0; in extron_send_byte()
188 for (; !err && len; len--) in extron_send_len()
193 static int extron_send_and_wait_len(struct extron *extron, struct extron_port *port, in extron_send_and_wait_len() argument
202 dev_info(extron->dev, "transmit %s (response: %s)\n", in extron_send_and_wait_len()
205 dev_info(extron->dev, "transmit %s\n", cmd); in extron_send_and_wait_len()
208 mutex_lock(&extron->serio_lock); in extron_send_and_wait_len()
209 if (port) { in extron_send_and_wait_len()
210 init_completion(&port->cmd_done); in extron_send_and_wait_len()
211 port->cmd_error = 0; in extron_send_and_wait_len()
212 port->response = response; in extron_send_and_wait_len()
214 init_completion(&extron->cmd_done); in extron_send_and_wait_len()
215 extron->cmd_error = 0; in extron_send_and_wait_len()
216 extron->response = response; in extron_send_and_wait_len()
218 err = extron_send_len(extron->serio, cmd, bin, len); in extron_send_and_wait_len()
221 !wait_for_completion_timeout(port ? &port->cmd_done : &extron->cmd_done, timeout)) { in extron_send_and_wait_len()
222 dev_info(extron->dev, "transmit %s failed with %s (expected: %s)\n", in extron_send_and_wait_len()
223 cmd, extron->reply, response); in extron_send_and_wait_len()
224 err = -ETIMEDOUT; in extron_send_and_wait_len()
227 if (!err && response && (port ? port->cmd_error : extron->cmd_error)) { in extron_send_and_wait_len()
228 dev_info(extron->dev, "transmit %s failed with E%02u (expected: %s)\n", in extron_send_and_wait_len()
229 cmd, port ? port->cmd_error : extron->cmd_error, response); in extron_send_and_wait_len()
230 if (port) in extron_send_and_wait_len()
231 port->cmd_error = 0; in extron_send_and_wait_len()
233 extron->cmd_error = 0; in extron_send_and_wait_len()
234 err = -EPROTO; in extron_send_and_wait_len()
236 if (port) in extron_send_and_wait_len()
237 port->response = NULL; in extron_send_and_wait_len()
239 extron->response = NULL; in extron_send_and_wait_len()
240 mutex_unlock(&extron->serio_lock); in extron_send_and_wait_len()
244 static int extron_send_and_wait(struct extron *extron, struct extron_port *port, in extron_send_and_wait() argument
247 return extron_send_and_wait_len(extron, port, cmd, NULL, 0, response); in extron_send_and_wait()
250 static void extron_parse_edid(struct extron_port *port) in extron_parse_edid() argument
252 const u8 *edid = port->edid; in extron_parse_edid()
256 port->has_4kp30 = false; in extron_parse_edid()
257 port->has_4kp60 = false; in extron_parse_edid()
258 port->has_qy = false; in extron_parse_edid()
259 port->has_qs = false; in extron_parse_edid()
260 /* Store Established Timings 1 and 2 */ in extron_parse_edid()
261 port->est_i = edid[0x23]; in extron_parse_edid()
262 port->est_ii = edid[0x24]; in extron_parse_edid()
271 if (!dtd[0] && !dtd[1]) in extron_parse_edid()
280 pclk = dtd[0] + (dtd[1] << 8); in extron_parse_edid()
284 port->has_4kp30 = true; in extron_parse_edid()
286 port->has_4kp60 = true; in extron_parse_edid()
289 if (port->edid_blocks == 1) in extron_parse_edid()
294 /* Return if not a CTA-861 extension block */ in extron_parse_edid()
295 if (edid[0] != 0x02 || edid[1] != 0x03) in extron_parse_edid()
312 if (i + len + 1 > 0x7f) in extron_parse_edid()
318 if (memchr(edid + i + 1, 97, len)) in extron_parse_edid()
319 port->has_4kp60 = true; in extron_parse_edid()
321 if (memchr(edid + i + 1, 95, len)) in extron_parse_edid()
322 port->has_4kp30 = true; in extron_parse_edid()
326 switch (edid[i + 1]) { in extron_parse_edid()
329 port->has_qy = true; in extron_parse_edid()
331 port->has_qs = true; in extron_parse_edid()
336 i += len + 1; in extron_parse_edid()
349 /* Return if not a CTA-861 extension block */ in get_edid_tag_location()
350 if (size < 256 || edid[0] != 0x02 || edid[1] != 0x03) in get_edid_tag_location()
351 return -ENOENT; in get_edid_tag_location()
356 return -ENOENT; in get_edid_tag_location()
366 i += len + 1; in get_edid_tag_location()
370 if (tag < 7 || (len >= 1 && edid[i + 1] == ext_tag)) in get_edid_tag_location()
372 i += len + 1; in get_edid_tag_location()
374 return -ENOENT; in get_edid_tag_location()
385 edid[127] = 256 - sum; in extron_edid_crc()
389 * Fill in EDID string. As per VESA EDID-1.3, strings are at most 13 chars
406 static void extron_update_edid(struct extron_port *port, unsigned int blocks) in extron_update_edid() argument
411 c1 = ((manufacturer_name[0] - '@') << 2) | in extron_update_edid()
412 (((manufacturer_name[1] - '@') >> 3) & 0x03); in extron_update_edid()
413 c2 = (((manufacturer_name[1] - '@') & 0x07) << 5) | in extron_update_edid()
414 ((manufacturer_name[2] - '@') & 0x1f); in extron_update_edid()
416 port->edid_tmp[8] = c1; in extron_update_edid()
417 port->edid_tmp[9] = c2; in extron_update_edid()
420 port->edid_tmp[0x23] = port->est_i | 0x20; in extron_update_edid()
421 port->edid_tmp[0x24] = port->est_ii; in extron_update_edid()
424 extron_set_edid_string(port->edid_tmp + 0x5f, port->extron->unit_name); in extron_update_edid()
426 extron_set_edid_string(port->edid_tmp + 0x71, port->adap->name); in extron_update_edid()
428 extron_edid_crc(port->edid_tmp); in extron_update_edid()
431 offset = get_edid_tag_location(port->edid_tmp, blocks * 128, 7, 0); in extron_update_edid()
433 port->edid_tmp[offset + 2] &= ~0xc0; in extron_update_edid()
434 if (port->has_qy) in extron_update_edid()
435 port->edid_tmp[offset + 2] |= 0x80; in extron_update_edid()
436 if (port->has_qs) in extron_update_edid()
437 port->edid_tmp[offset + 2] |= 0x40; in extron_update_edid()
440 extron_edid_crc(port->edid_tmp + 128); in extron_update_edid()
443 static int extron_write_edid(struct extron_port *port, in extron_write_edid() argument
446 struct extron *extron = port->extron; in extron_write_edid()
453 if (mutex_lock_interruptible(&extron->edid_lock)) in extron_write_edid()
454 return -EINTR; in extron_write_edid()
456 memcpy(port->edid_tmp, edid, blocks * 128); in extron_write_edid()
459 extron_update_edid(port, blocks); in extron_write_edid()
461 ret = extron_send_and_wait_len(port->extron, port, "W+UF256,in.bin", in extron_write_edid()
462 port->edid_tmp, sizeof(port->edid_tmp), in extron_write_edid()
466 ret = extron_send_and_wait(port->extron, port, "WI1,in.binEDID", in extron_write_edid()
471 port->edid_blocks = blocks; in extron_write_edid()
472 memcpy(port->edid, port->edid_tmp, blocks * 128); in extron_write_edid()
473 port->read_edid = true; in extron_write_edid()
474 mutex_unlock(&extron->edid_lock); in extron_write_edid()
476 cec_s_phys_addr(port->adap, phys_addr, false); in extron_write_edid()
480 mutex_unlock(&extron->edid_lock); in extron_write_edid()
488 struct extron_port *in = extron->ports[extron->num_out_ports]; in update_edid_work()
499 for (out = 0; has_4kp60 && out < extron->num_out_ports; out++) { in update_edid_work()
500 p = extron->ports[out]; in update_edid_work()
501 if (p->read_edid) { in update_edid_work()
502 has_4kp60 = p->has_4kp60; in update_edid_work()
503 est_i &= p->est_i; in update_edid_work()
504 est_ii &= p->est_ii; in update_edid_work()
508 for (out = 0; has_4kp30 && out < extron->num_out_ports; out++) in update_edid_work()
509 if (extron->ports[out]->read_edid) in update_edid_work()
510 has_4kp30 = extron->ports[out]->has_4kp30; in update_edid_work()
512 for (out = 0; has_qy && out < extron->num_out_ports; out++) in update_edid_work()
513 if (extron->ports[out]->read_edid) in update_edid_work()
514 has_qy = extron->ports[out]->has_qy; in update_edid_work()
516 for (out = 0; has_qs && out < extron->num_out_ports; out++) in update_edid_work()
517 if (extron->ports[out]->read_edid) in update_edid_work()
518 has_qs = extron->ports[out]->has_qs; in update_edid_work()
520 /* exit if no output port had an EDID */ in update_edid_work()
525 if (has_4kp60 == in->has_4kp60 && has_4kp30 == in->has_4kp30 && in update_edid_work()
526 has_qy == in->has_qy && has_qs == in->has_qs && in update_edid_work()
527 est_i == in->est_i && est_ii == in->est_ii) in update_edid_work()
530 in->has_4kp60 = has_4kp60; in update_edid_work()
531 in->has_4kp30 = has_4kp30; in update_edid_work()
532 in->has_qy = has_qy; in update_edid_work()
533 in->has_qs = has_qs; in update_edid_work()
534 in->est_i = est_i; in update_edid_work()
535 in->est_ii = est_ii; in update_edid_work()
536 extron_write_edid(extron->ports[extron->num_out_ports], in update_edid_work()
541 static void extron_read_edid(struct extron_port *port) in extron_read_edid() argument
543 struct extron *extron = port->extron; in extron_read_edid()
547 idx = port->port.port + (port->is_input ? 0 : extron->num_in_ports); in extron_read_edid()
550 if (mutex_lock_interruptible(&extron->edid_lock)) in extron_read_edid()
552 if (port->read_edid) in extron_read_edid()
554 extron->edid_bytes_read = 0; in extron_read_edid()
555 extron->edid_port = port; in extron_read_edid()
556 port->edid_blocks = 0; in extron_read_edid()
557 if (!port->has_edid) in extron_read_edid()
560 extron->edid_reading = true; in extron_read_edid()
562 if (!extron_send_and_wait(extron, port, cmd, reply)) in extron_read_edid()
563 wait_for_completion_killable_timeout(&extron->edid_completion, in extron_read_edid()
565 if (port->edid_blocks) { in extron_read_edid()
566 extron_parse_edid(port); in extron_read_edid()
567 port->read_edid = true; in extron_read_edid()
568 if (!port->is_input) in extron_read_edid()
569 v4l2_ctrl_s_ctrl(port->ctrl_tx_edid_present, 1); in extron_read_edid()
572 extron->edid_reading = false; in extron_read_edid()
574 mutex_unlock(&extron->edid_lock); in extron_read_edid()
575 cancel_delayed_work_sync(&extron->work_update_edid); in extron_read_edid()
577 schedule_delayed_work(&extron->work_update_edid, in extron_read_edid()
583 struct extron_port *port = in extron_irq_work_handler() local
585 struct extron *extron = port->extron; in extron_irq_work_handler()
595 spin_lock_irqsave(&port->msg_lock, flags); in extron_irq_work_handler()
596 while (port->rx_msg_num) { in extron_irq_work_handler()
597 spin_unlock_irqrestore(&port->msg_lock, flags); in extron_irq_work_handler()
598 cec_received_msg(port->adap, in extron_irq_work_handler()
599 &port->rx_msg[port->rx_msg_cur_idx]); in extron_irq_work_handler()
600 spin_lock_irqsave(&port->msg_lock, flags); in extron_irq_work_handler()
601 if (port->rx_msg_num) in extron_irq_work_handler()
602 port->rx_msg_num--; in extron_irq_work_handler()
603 port->rx_msg_cur_idx = in extron_irq_work_handler()
604 (port->rx_msg_cur_idx + 1) % NUM_MSGS; in extron_irq_work_handler()
606 update_pa = port->update_phys_addr; in extron_irq_work_handler()
607 pa = port->phys_addr; in extron_irq_work_handler()
608 port->update_phys_addr = false; in extron_irq_work_handler()
609 update_has_signal = port->update_has_signal; in extron_irq_work_handler()
610 has_signal = port->has_signal; in extron_irq_work_handler()
611 port->update_has_signal = false; in extron_irq_work_handler()
612 update_has_edid = port->update_has_edid; in extron_irq_work_handler()
613 has_edid = port->has_edid; in extron_irq_work_handler()
614 port->update_has_edid = false; in extron_irq_work_handler()
615 status = port->tx_done_status; in extron_irq_work_handler()
616 port->tx_done_status = 0; in extron_irq_work_handler()
617 spin_unlock_irqrestore(&port->msg_lock, flags); in extron_irq_work_handler()
620 cec_transmit_done(port->adap, status, 0, 0, 0, 0); in extron_irq_work_handler()
622 if (update_has_signal && port->is_input) in extron_irq_work_handler()
623 v4l2_ctrl_s_ctrl(port->ctrl_rx_power_present, has_signal); in extron_irq_work_handler()
625 if (update_has_edid && !port->is_input) { in extron_irq_work_handler()
626 v4l2_ctrl_s_ctrl(port->ctrl_tx_hotplug, in extron_irq_work_handler()
627 port->has_edid); in extron_irq_work_handler()
628 if (port->has_edid) { in extron_irq_work_handler()
629 port->port.found_sink = true; in extron_irq_work_handler()
630 port->port.lost_sink_ts = ktime_set(0, 0); in extron_irq_work_handler()
632 port->port.lost_sink_ts = ktime_get(); in extron_irq_work_handler()
635 port->edid_blocks = 0; in extron_irq_work_handler()
636 port->read_edid = false; in extron_irq_work_handler()
637 if (extron->edid_reading && !has_edid && in extron_irq_work_handler()
638 extron->edid_port == port) in extron_irq_work_handler()
639 extron->edid_reading = false; in extron_irq_work_handler()
640 v4l2_ctrl_s_ctrl(port->ctrl_tx_edid_present, 0); in extron_irq_work_handler()
641 } else if (!extron->edid_reading || extron->edid_port != port) { in extron_irq_work_handler()
642 extron_read_edid(port); in extron_irq_work_handler()
646 cec_s_phys_addr(port->adap, pa, false); in extron_irq_work_handler()
649 static void extron_process_received(struct extron_port *port, const char *data) in extron_process_received() argument
656 if (!port || port->disconnected) in extron_process_received()
659 if (len < 5 || (len - 2) % 3 || data[len - 2] != '*') in extron_process_received()
663 int v = hex2bin(&msg.msg[msg.len], data + 1, 1); in extron_process_received()
671 spin_lock_irqsave(&port->msg_lock, irq_flags); in extron_process_received()
672 idx = (port->rx_msg_cur_idx + port->rx_msg_num) % in extron_process_received()
674 if (port->rx_msg_num == NUM_MSGS) { in extron_process_received()
675 dev_warn(port->dev, in extron_process_received()
678 spin_unlock_irqrestore(&port->msg_lock, in extron_process_received()
682 port->rx_msg_num++; in extron_process_received()
683 port->rx_msg[idx] = msg; in extron_process_received()
684 spin_unlock_irqrestore(&port->msg_lock, irq_flags); in extron_process_received()
685 if (!port->disconnected) in extron_process_received()
686 schedule_work(&port->irq_work); in extron_process_received()
690 dev_info(port->extron->dev, "malformed msg received: '%s'\n", data); in extron_process_received()
693 static void extron_port_signal_change(struct extron_port *port, bool has_sig) in extron_port_signal_change() argument
698 if (!port) in extron_port_signal_change()
701 spin_lock_irqsave(&port->msg_lock, irq_flags); in extron_port_signal_change()
702 if (!port->update_has_signal && port->has_signal != has_sig) { in extron_port_signal_change()
703 port->update_has_signal = true; in extron_port_signal_change()
706 port->has_signal = has_sig; in extron_port_signal_change()
707 spin_unlock_irqrestore(&port->msg_lock, irq_flags); in extron_port_signal_change()
708 if (update && !port->disconnected) in extron_port_signal_change()
709 schedule_work(&port->irq_work); in extron_port_signal_change()
716 extron_port_signal_change(extron->ports[extron->num_out_ports], in extron_process_signal_change()
717 data[0] == '1'); in extron_process_signal_change()
718 for (i = 0; i < extron->num_out_ports; i++) in extron_process_signal_change()
719 extron_port_signal_change(extron->ports[i], in extron_process_signal_change()
723 static void extron_port_edid_change(struct extron_port *port, bool has_edid) in extron_port_edid_change() argument
728 if (!port) in extron_port_edid_change()
731 spin_lock_irqsave(&port->msg_lock, irq_flags); in extron_port_edid_change()
732 if (!port->update_has_edid && port->has_edid != has_edid) { in extron_port_edid_change()
733 port->update_has_edid = true; in extron_port_edid_change()
736 port->has_edid = has_edid; in extron_port_edid_change()
737 spin_unlock_irqrestore(&port->msg_lock, irq_flags); in extron_port_edid_change()
738 if (update && !port->disconnected) in extron_port_edid_change()
739 schedule_work(&port->irq_work); in extron_port_edid_change()
750 if (!extron->is_ready) in extron_process_edid_change()
753 for (i = 0; i < extron->num_out_ports; i++) in extron_process_edid_change()
754 extron_port_edid_change(extron->ports[i], in extron_process_edid_change()
758 static void extron_phys_addr_change(struct extron_port *port, u16 pa) in extron_phys_addr_change() argument
763 if (!port) in extron_phys_addr_change()
766 spin_lock_irqsave(&port->msg_lock, irq_flags); in extron_phys_addr_change()
767 if (!port->update_phys_addr && port->phys_addr != pa) { in extron_phys_addr_change()
769 port->update_phys_addr = true; in extron_phys_addr_change()
771 port->phys_addr = pa; in extron_phys_addr_change()
772 spin_unlock_irqrestore(&port->msg_lock, irq_flags); in extron_phys_addr_change()
773 if (update && !port->disconnected) in extron_phys_addr_change()
774 schedule_work(&port->irq_work); in extron_phys_addr_change()
777 static void extron_process_tx_done(struct extron_port *port, char status) in extron_process_tx_done() argument
782 if (!port) in extron_process_tx_done()
789 case '1': in extron_process_tx_done()
796 spin_lock_irqsave(&port->msg_lock, irq_flags); in extron_process_tx_done()
797 port->tx_done_status = tx_status; in extron_process_tx_done()
798 spin_unlock_irqrestore(&port->msg_lock, irq_flags); in extron_process_tx_done()
799 if (!port->disconnected) in extron_process_tx_done()
800 schedule_work(&port->irq_work); in extron_process_tx_done()
803 static void extron_add_edid(struct extron_port *port, const char *hex) in extron_add_edid() argument
805 struct extron *extron = port ? port->extron : NULL; in extron_add_edid()
807 if (!port || port != extron->edid_port) in extron_add_edid()
809 while (extron->edid_bytes_read < sizeof(port->edid) && *hex) { in extron_add_edid()
810 int err = hex2bin(&port->edid[extron->edid_bytes_read], hex, 1); in extron_add_edid()
813 extron->edid_reading = false; in extron_add_edid()
814 complete(&extron->edid_completion); in extron_add_edid()
817 extron->edid_bytes_read++; in extron_add_edid()
820 if (extron->edid_bytes_read == 128 && in extron_add_edid()
821 port->edid[126] == 0) { in extron_add_edid()
823 port->edid_blocks = 1; in extron_add_edid()
824 extron->edid_reading = false; in extron_add_edid()
825 complete(&extron->edid_completion); in extron_add_edid()
827 if (extron->edid_bytes_read < sizeof(port->edid)) in extron_add_edid()
830 port->edid_blocks = 2; in extron_add_edid()
831 extron->edid_reading = false; in extron_add_edid()
832 complete(&extron->edid_completion); in extron_add_edid()
839 struct extron_port *port = NULL; in extron_interrupt() local
844 if (extron->idx == 0) in extron_interrupt()
846 memcpy(extron->data, extron->buf, extron->idx); in extron_interrupt()
847 extron->len = extron->idx; in extron_interrupt()
848 extron->data[extron->len] = 0; in extron_interrupt()
850 dev_info(extron->dev, "received %s\n", extron->data); in extron_interrupt()
851 extron->idx = 0; in extron_interrupt()
852 if (!memcmp(extron->data, "Sig", 3) && in extron_interrupt()
853 extron->data[4] == '*') { in extron_interrupt()
854 extron_process_signal_change(extron, extron->data + 3); in extron_interrupt()
855 } else if (!memcmp(extron->data, "Hdcp", 4) && in extron_interrupt()
856 extron->data[5] == '*') { in extron_interrupt()
857 extron_process_edid_change(extron, extron->data + 4); in extron_interrupt()
858 } else if (!memcmp(extron->data, "DcecI", 5) && in extron_interrupt()
859 extron->data[5] >= '1' && in extron_interrupt()
860 extron->data[5] < '1' + extron->num_in_ports) { in extron_interrupt()
861 unsigned int p = extron->data[5] - '1'; in extron_interrupt()
863 p += extron->num_out_ports; in extron_interrupt()
864 extron_process_tx_done(extron->ports[p], in extron_interrupt()
865 extron->data[extron->len - 1]); in extron_interrupt()
866 } else if (!memcmp(extron->data, "Ceci", 4) && in extron_interrupt()
867 extron->data[4] >= '1' && in extron_interrupt()
868 extron->data[4] < '1' + extron->num_in_ports && in extron_interrupt()
869 extron->data[5] == '*') { in extron_interrupt()
870 unsigned int p = extron->data[4] - '1'; in extron_interrupt()
872 p += extron->num_out_ports; in extron_interrupt()
873 extron_process_received(extron->ports[p], in extron_interrupt()
874 extron->data + 6); in extron_interrupt()
875 } else if (!memcmp(extron->data, "DcecO", 5) && in extron_interrupt()
876 extron->data[5] >= '1' && in extron_interrupt()
877 extron->data[5] < '1' + extron->num_out_ports) { in extron_interrupt()
878 unsigned int p = extron->data[5] - '1'; in extron_interrupt()
880 extron_process_tx_done(extron->ports[p], in extron_interrupt()
881 extron->data[extron->len - 1]); in extron_interrupt()
882 } else if (!memcmp(extron->data, "Ceco", 4) && in extron_interrupt()
883 extron->data[4] >= '1' && in extron_interrupt()
884 extron->data[4] < '1' + extron->num_out_ports && in extron_interrupt()
885 extron->data[5] == '*') { in extron_interrupt()
886 unsigned int p = extron->data[4] - '1'; in extron_interrupt()
888 extron_process_received(extron->ports[p], in extron_interrupt()
889 extron->data + 6); in extron_interrupt()
890 } else if (!memcmp(extron->data, "Pceco", 5) && in extron_interrupt()
891 extron->data[5] >= '1' && in extron_interrupt()
892 extron->data[5] < '1' + extron->num_out_ports) { in extron_interrupt()
893 unsigned int p = extron->data[5] - '1'; in extron_interrupt()
896 if (sscanf(extron->data + 7, "%%%02x%%%02x", in extron_interrupt()
897 &tmp_pa[0], &tmp_pa[1]) == 2) in extron_interrupt()
898 extron_phys_addr_change(extron->ports[p], in extron_interrupt()
899 tmp_pa[0] << 8 | tmp_pa[1]); in extron_interrupt()
900 } else if (!memcmp(extron->data, "Pceci", 5) && in extron_interrupt()
901 extron->data[5] >= '1' && in extron_interrupt()
902 extron->data[5] < '1' + extron->num_in_ports) { in extron_interrupt()
903 unsigned int p = extron->data[5] - '1'; in extron_interrupt()
906 p += extron->num_out_ports; in extron_interrupt()
907 if (sscanf(extron->data + 7, "%%%02x%%%02x", in extron_interrupt()
908 &tmp_pa[0], &tmp_pa[1]) == 2) in extron_interrupt()
909 extron_phys_addr_change(extron->ports[p], in extron_interrupt()
910 tmp_pa[0] << 8 | tmp_pa[1]); in extron_interrupt()
911 } else if (!memcmp(extron->data, "EdidR", 5) && in extron_interrupt()
912 extron->data[5] >= '1' && in extron_interrupt()
913 extron->data[5] < '1' + extron->num_ports && in extron_interrupt()
914 extron->data[6] == '*') { in extron_interrupt()
915 unsigned int p = extron->data[5] - '1'; in extron_interrupt()
918 p--; in extron_interrupt()
920 p = extron->num_out_ports; in extron_interrupt()
921 extron_add_edid(extron->ports[p], extron->data + 7); in extron_interrupt()
922 } else if (extron->edid_reading && extron->len == 32 && in extron_interrupt()
923 extron->edid_port) { in extron_interrupt()
924 extron_add_edid(extron->edid_port, extron->data); in extron_interrupt()
928 if (extron->response && in extron_interrupt()
929 !strncmp(extron->response, extron->data, in extron_interrupt()
930 strlen(extron->response))) in extron_interrupt()
933 for (p = 0; !found_response && p < extron->num_ports; p++) { in extron_interrupt()
934 port = extron->ports[p]; in extron_interrupt()
935 if (port && port->response && in extron_interrupt()
936 !strncmp(port->response, extron->data, in extron_interrupt()
937 strlen(port->response))) in extron_interrupt()
941 if (!found_response && extron->response && in extron_interrupt()
942 extron->data[0] == 'E' && in extron_interrupt()
943 isdigit(extron->data[1]) && in extron_interrupt()
944 isdigit(extron->data[2]) && in extron_interrupt()
945 !extron->data[3]) { in extron_interrupt()
946 extron->cmd_error = (extron->data[1] - '0') * 10 + in extron_interrupt()
947 extron->data[2] - '0'; in extron_interrupt()
948 extron->response = NULL; in extron_interrupt()
949 complete(&extron->cmd_done); in extron_interrupt()
955 memcpy(extron->reply, extron->data, extron->len); in extron_interrupt()
956 extron->reply[extron->len] = 0; in extron_interrupt()
957 if (!port) { in extron_interrupt()
958 extron->response = NULL; in extron_interrupt()
959 complete(&extron->cmd_done); in extron_interrupt()
961 port->response = NULL; in extron_interrupt()
962 complete(&port->cmd_done); in extron_interrupt()
967 if (extron->idx >= DATA_SIZE - 1) { in extron_interrupt()
968 dev_info(extron->dev, in extron_interrupt()
969 "throwing away %d bytes of garbage\n", extron->idx); in extron_interrupt()
970 extron->idx = 0; in extron_interrupt()
972 extron->buf[extron->idx++] = (char)data; in extron_interrupt()
978 struct extron_port *port = cec_get_drvdata(adap); in extron_cec_adap_enable() local
980 return (port->disconnected && enable) ? -ENODEV : 0; in extron_cec_adap_enable()
985 struct extron_port *port = cec_get_drvdata(adap); in extron_cec_adap_log_addr() local
991 if (port->disconnected) in extron_cec_adap_log_addr()
992 return -ENODEV; in extron_cec_adap_log_addr()
994 port->direction, port->port.port, la); in extron_cec_adap_log_addr()
996 port->direction, port->port.port, la); in extron_cec_adap_log_addr()
997 err = extron_send_and_wait(port->extron, port, cmd, resp); in extron_cec_adap_log_addr()
1004 struct extron_port *port = cec_get_drvdata(adap); in extron_cec_adap_transmit() local
1005 char buf[CEC_MAX_MSG_SIZE * 3 + 1]; in extron_cec_adap_transmit()
1009 if (port->disconnected) in extron_cec_adap_transmit()
1010 return -ENODEV; in extron_cec_adap_transmit()
1012 for (i = 0; i < msg->len - 1; i++) in extron_cec_adap_transmit()
1013 sprintf(buf + i * 3, "%%%02X", msg->msg[i + 1]); in extron_cec_adap_transmit()
1015 port->direction, port->port.port, in extron_cec_adap_transmit()
1017 return extron_send_and_wait(port->extron, port, cmd, NULL); in extron_cec_adap_transmit()
1022 struct extron_port *port = cec_get_drvdata(adap); in extron_cec_adap_unconfigured() local
1024 if (port->disconnected) in extron_cec_adap_unconfigured()
1027 dev_info(port->extron->dev, "unconfigured port %d (%s)\n", in extron_cec_adap_unconfigured()
1028 port->port.port, in extron_cec_adap_unconfigured()
1029 port->extron->splitter.is_standby ? "Off" : "On"); in extron_cec_adap_unconfigured()
1030 if (!port->is_input) in extron_cec_adap_unconfigured()
1031 cec_splitter_unconfigured_output(&port->port); in extron_cec_adap_unconfigured()
1036 struct extron_port *port = cec_get_drvdata(adap); in extron_cec_configured() local
1038 if (port->disconnected) in extron_cec_configured()
1041 dev_info(port->extron->dev, "configured port %d (%s)\n", in extron_cec_configured()
1042 port->port.port, in extron_cec_configured()
1043 port->extron->splitter.is_standby ? "Off" : "On"); in extron_cec_configured()
1044 if (!port->is_input) in extron_cec_configured()
1045 cec_splitter_configured_output(&port->port); in extron_cec_configured()
1051 struct extron_port *port = cec_get_drvdata(adap); in extron_cec_adap_nb_transmit_canceled() local
1056 if (port->disconnected || port->is_input) in extron_cec_adap_nb_transmit_canceled()
1058 input_adap = port->extron->ports[port->extron->num_out_ports]->adap; in extron_cec_adap_nb_transmit_canceled()
1059 cec_splitter_nb_transmit_canceled_output(&port->port, msg, input_adap); in extron_cec_adap_nb_transmit_canceled()
1064 struct extron_port *port = cec_get_drvdata(adap); in extron_received() local
1067 return -ENOMSG; in extron_received()
1068 if (port->disconnected) in extron_received()
1069 return -ENOMSG; in extron_received()
1070 if (port->is_input) in extron_received()
1071 return cec_splitter_received_input(&port->port, msg); in extron_received()
1072 return cec_splitter_received_output(&port->port, msg, in extron_received()
1073 port->extron->ports[port->extron->num_out_ports]->adap); in extron_received()
1081 pr_info("cec-%s: " fmt, (adap)->name, ## arg); \
1091 static void extron_adap_status_port(struct extron_port *port, struct seq_file *file) in extron_adap_status_port() argument
1093 struct cec_adapter *adap = port->adap; in extron_adap_status_port()
1095 if (port->disconnected) { in extron_adap_status_port()
1097 "\tport %u: disconnected\n", port->port.port); in extron_adap_status_port()
1100 if (port->is_input) in extron_adap_status_port()
1103 port->port.port, in extron_adap_status_port()
1104 port->has_signal ? "has" : "no", in extron_adap_status_port()
1105 port->has_edid ? "has" : "no", in extron_adap_status_port()
1106 port->has_4kp30 ? "has" : "no", in extron_adap_status_port()
1107 port->has_4kp60 ? "has" : "no", in extron_adap_status_port()
1108 port->has_qs ? "" : "no ", in extron_adap_status_port()
1109 port->has_qy ? "" : "no ", in extron_adap_status_port()
1110 !port->port.adap->is_configured ? "not configured" : in extron_adap_status_port()
1111 pwr_state[port->extron->splitter.is_standby]); in extron_adap_status_port()
1115 port->port.port, in extron_adap_status_port()
1116 port->port.found_sink ? "found" : "no", in extron_adap_status_port()
1117 port->has_signal ? "has" : "no", in extron_adap_status_port()
1118 port->has_edid ? "has" : "no", in extron_adap_status_port()
1119 port->has_4kp30 ? "has" : "no", in extron_adap_status_port()
1120 port->has_4kp60 ? "has" : "no", in extron_adap_status_port()
1121 port->has_qs ? "" : "no ", in extron_adap_status_port()
1122 port->has_qy ? "" : "no ", in extron_adap_status_port()
1123 port->port.is_active_source ? "" : "not ", in extron_adap_status_port()
1124 !port->port.adap->is_configured ? "not configured" : in extron_adap_status_port()
1125 pwr_state[port->port.power_status & 3]); in extron_adap_status_port()
1126 if (port->port.out_give_device_power_status_seq) in extron_adap_status_port()
1129 port->port.port, in extron_adap_status_port()
1130 port->port.out_give_device_power_status_seq & ~(1 << 31), in extron_adap_status_port()
1132 port->port.out_give_device_power_status_ts)); in extron_adap_status_port()
1133 if (port->port.out_request_current_latency_seq) in extron_adap_status_port()
1136 port->port.port, in extron_adap_status_port()
1137 port->port.out_request_current_latency_seq & ~(1 << 31), in extron_adap_status_port()
1139 port->port.out_request_current_latency_ts)); in extron_adap_status_port()
1144 struct extron_port *port = cec_get_drvdata(adap); in extron_adap_status() local
1145 struct extron *extron = port->extron; in extron_adap_status()
1149 extron->unit_name, extron->unit_type); in extron_adap_status()
1150 log_printf(adap, file, "model: 60-160%c-01 (1 input, %u outputs)\n", in extron_adap_status()
1151 '6' + extron->num_out_ports / 2, extron->num_out_ports); in extron_adap_status()
1153 extron->unit_fw_version, extron->unit_cec_engine_version); in extron_adap_status()
1154 if (extron->hpd_never_low) in extron_adap_status()
1166 pwr_state[extron->splitter.is_standby]); in extron_adap_status()
1167 log_printf(adap, file, "%s port: %d (%s)\n", in extron_adap_status()
1168 port->is_input ? "input" : "output", in extron_adap_status()
1169 port->port.port, port->name); in extron_adap_status()
1170 log_printf(adap, file, "splitter input port:\n"); in extron_adap_status()
1171 extron_adap_status_port(extron->ports[extron->num_out_ports], file); in extron_adap_status()
1174 for (i = 0; i < extron->num_out_ports; i++) in extron_adap_status()
1175 extron_adap_status_port(extron->ports[i], file); in extron_adap_status()
1177 if (!port->has_edid || !port->read_edid) in extron_adap_status()
1180 for (i = 0; i < port->edid_blocks * 128; i += 16) { in extron_adap_status()
1183 log_printf(adap, file, "EDID: %*ph\n", 16, port->edid + i); in extron_adap_status()
1201 struct extron_port *port = video_drvdata(file); in extron_querycap() local
1203 strscpy(cap->driver, "extron-da-hd-4k-plus-cec", sizeof(cap->driver)); in extron_querycap()
1204 strscpy(cap->card, cap->driver, sizeof(cap->card)); in extron_querycap()
1205 snprintf(cap->bus_info, sizeof(cap->bus_info), "serio:%s", port->name); in extron_querycap()
1211 struct extron_port *port = video_drvdata(file); in extron_enum_input() local
1213 if (inp->index) in extron_enum_input()
1214 return -EINVAL; in extron_enum_input()
1215 inp->type = V4L2_INPUT_TYPE_CAMERA; in extron_enum_input()
1216 snprintf(inp->name, sizeof(inp->name), "HDMI IN %u", port->port.port); in extron_enum_input()
1217 inp->status = v4l2_ctrl_g_ctrl(port->ctrl_rx_power_present) ? in extron_enum_input()
1230 return i ? -EINVAL : 0; in extron_s_input()
1235 struct extron_port *port = video_drvdata(file); in extron_enum_output() local
1237 if (out->index) in extron_enum_output()
1238 return -EINVAL; in extron_enum_output()
1239 out->type = V4L2_OUTPUT_TYPE_ANALOG; in extron_enum_output()
1240 snprintf(out->name, sizeof(out->name), "HDMI OUT %u", port->port.port); in extron_enum_output()
1252 return o ? -EINVAL : 0; in extron_s_output()
1258 struct extron_port *port = video_drvdata(file); in extron_g_edid() local
1260 memset(edid->reserved, 0, sizeof(edid->reserved)); in extron_g_edid()
1261 if (port->disconnected) in extron_g_edid()
1262 return -ENODEV; in extron_g_edid()
1263 if (edid->pad) in extron_g_edid()
1264 return -EINVAL; in extron_g_edid()
1265 if (!port->has_edid) in extron_g_edid()
1266 return -ENODATA; in extron_g_edid()
1267 if (!port->read_edid) in extron_g_edid()
1268 extron_read_edid(port); in extron_g_edid()
1269 if (!port->read_edid) in extron_g_edid()
1270 return -ENODATA; in extron_g_edid()
1271 if (edid->start_block == 0 && edid->blocks == 0) { in extron_g_edid()
1272 edid->blocks = port->edid_blocks; in extron_g_edid()
1275 if (edid->start_block >= port->edid_blocks) in extron_g_edid()
1276 return -EINVAL; in extron_g_edid()
1277 if (edid->blocks > port->edid_blocks - edid->start_block) in extron_g_edid()
1278 edid->blocks = port->edid_blocks - edid->start_block; in extron_g_edid()
1279 memcpy(edid->edid, port->edid + edid->start_block * 128, edid->blocks * 128); in extron_g_edid()
1285 struct extron_port *port = video_drvdata(file); in extron_s_edid() local
1287 memset(edid->reserved, 0, sizeof(edid->reserved)); in extron_s_edid()
1288 if (port->disconnected) in extron_s_edid()
1289 return -ENODEV; in extron_s_edid()
1290 if (edid->pad) in extron_s_edid()
1291 return -EINVAL; in extron_s_edid()
1294 if (edid->blocks == 0) in extron_s_edid()
1295 return -EINVAL; in extron_s_edid()
1297 if (edid->blocks > MAX_EDID_BLOCKS) { in extron_s_edid()
1298 edid->blocks = MAX_EDID_BLOCKS; in extron_s_edid()
1299 return -E2BIG; in extron_s_edid()
1302 if (cec_get_edid_spa_location(edid->edid, edid->blocks * 128)) in extron_s_edid()
1303 v4l2_set_edid_phys_addr(edid->edid, edid->blocks * 128, 0); in extron_s_edid()
1304 extron_parse_edid(port); in extron_s_edid()
1305 return extron_write_edid(port, edid->edid, edid->blocks); in extron_s_edid()
1310 struct extron_port *port = video_drvdata(file); in extron_log_status() local
1312 extron_adap_status(port->adap, NULL); in extron_log_status()
1340 .name = "extron-da-hd-4k-plus-cec",
1344 .minor = -1,
1353 kthread_stop(extron->kthread_setup); in extron_disconnect()
1355 for (p = 0; p < extron->num_ports; p++) { in extron_disconnect()
1356 struct extron_port *port = extron->ports[p]; in extron_disconnect() local
1358 if (!port) in extron_disconnect()
1360 port->disconnected = true; in extron_disconnect()
1361 cancel_work_sync(&port->irq_work); in extron_disconnect()
1363 cancel_delayed_work_sync(&extron->work_update_edid); in extron_disconnect()
1364 for (p = 0; p < extron->num_ports; p++) { in extron_disconnect()
1365 struct extron_port *port = extron->ports[p]; in extron_disconnect() local
1367 if (!port) in extron_disconnect()
1370 if (port->cec_was_registered) { in extron_disconnect()
1371 if (cec_is_registered(port->adap)) in extron_disconnect()
1372 cec_unregister_adapter(port->adap); in extron_disconnect()
1379 cec_put_device(port->adap); in extron_disconnect()
1381 cec_delete_adapter(port->adap); in extron_disconnect()
1383 video_unregister_device(&port->vdev); in extron_disconnect()
1386 complete(&extron->edid_completion); in extron_disconnect()
1388 for (p = 0; p < extron->num_ports; p++) { in extron_disconnect()
1389 struct extron_port *port = extron->ports[p]; in extron_disconnect() local
1391 if (!port) in extron_disconnect()
1393 v4l2_ctrl_handler_free(&port->hdl); in extron_disconnect()
1394 mutex_destroy(&port->video_lock); in extron_disconnect()
1395 kfree(port); in extron_disconnect()
1397 mutex_destroy(&extron->edid_lock); in extron_disconnect()
1398 mutex_destroy(&extron->serio_lock); in extron_disconnect()
1399 extron->serio = NULL; in extron_disconnect()
1406 struct serio *serio = extron->serio; in extron_setup()
1407 struct extron_port *port; in extron_setup() local
1408 u8 *reply = extron->reply; in extron_setup()
1415 * from interfering with the other serial port traffic. in extron_setup()
1424 dev_info(extron->dev, "Unit part number: %s\n", reply + 3); in extron_setup()
1425 if (strcmp(reply + 3, "60-1607-01") && in extron_setup()
1426 strcmp(reply + 3, "60-1608-01") && in extron_setup()
1427 strcmp(reply + 3, "60-1609-01")) { in extron_setup()
1428 dev_err(extron->dev, "Unsupported model\n"); in extron_setup()
1429 return -ENODEV; in extron_setup()
1431 /* Up to 6 output ports and one input port */ in extron_setup()
1432 extron->num_out_ports = 2 * (reply[9] - '6'); in extron_setup()
1433 extron->splitter.num_out_ports = extron->num_out_ports; in extron_setup()
1434 extron->splitter.ports = extron->splitter_ports; in extron_setup()
1435 extron->splitter.dev = extron->dev; in extron_setup()
1436 extron->num_in_ports = 1; in extron_setup()
1437 extron->num_ports = extron->num_out_ports + extron->num_in_ports; in extron_setup()
1438 dev_info(extron->dev, "Unit output ports: %d\n", extron->num_out_ports); in extron_setup()
1439 dev_info(extron->dev, "Unit input ports: %d\n", extron->num_in_ports); in extron_setup()
1444 dev_info(extron->dev, "Unit name: %s\n", reply + 4); in extron_setup()
1445 strscpy(extron->unit_name, reply + 4, sizeof(extron->unit_name)); in extron_setup()
1450 dev_info(extron->dev, "Unit FW Version: %s\n", reply + 3); in extron_setup()
1451 strscpy(extron->unit_fw_version, reply + 3, in extron_setup()
1452 sizeof(extron->unit_fw_version)); in extron_setup()
1454 major < 1 || minor < 2) { in extron_setup()
1455 dev_err(extron->dev, in extron_setup()
1457 return -ENODEV; in extron_setup()
1463 dev_info(extron->dev, "Unit Type: %s\n", reply + 6); in extron_setup()
1464 strscpy(extron->unit_type, reply + 6, sizeof(extron->unit_type)); in extron_setup()
1469 dev_info(extron->dev, "CEC Engine Version: %s\n", reply + 6); in extron_setup()
1470 strscpy(extron->unit_cec_engine_version, reply + 6, in extron_setup()
1471 sizeof(extron->unit_cec_engine_version)); in extron_setup()
1481 extron->hpd_never_low = hpd_never_low; in extron_setup()
1483 /* Pull input port HPD low if all output ports also have a low HPD */ in extron_setup()
1485 dev_info(extron->dev, "Always keep input HPD high\n"); in extron_setup()
1487 dev_info(extron->dev, "Pull input HPD low if all output HPDs are low\n"); in extron_setup()
1491 for (p = 0; p < extron->num_ports; p++) { in extron_setup()
1496 port = kzalloc(sizeof(*port), GFP_KERNEL); in extron_setup()
1497 if (!port) in extron_setup()
1498 return -ENOMEM; in extron_setup()
1500 INIT_WORK(&port->irq_work, extron_irq_work_handler); in extron_setup()
1501 spin_lock_init(&port->msg_lock); in extron_setup()
1502 mutex_init(&port->video_lock); in extron_setup()
1503 port->extron = extron; in extron_setup()
1504 port->is_input = p >= extron->num_out_ports; in extron_setup()
1505 port->direction = port->is_input ? 'I' : 'O'; in extron_setup()
1506 port->port.port = 1 + (port->is_input ? p - extron->num_out_ports : p); in extron_setup()
1507 port->port.splitter = &extron->splitter; in extron_setup()
1508 port->phys_addr = CEC_PHYS_ADDR_INVALID; in extron_setup()
1509 snprintf(port->name, sizeof(port->name), "%s-%s-%u", in extron_setup()
1510 dev_name(&serio->dev), port->is_input ? "in" : "out", in extron_setup()
1511 port->port.port); in extron_setup()
1513 port->dev = extron->dev; in extron_setup()
1514 port->adap = cec_allocate_adapter(&extron_cec_adap_ops, port, in extron_setup()
1515 port->name, caps, 1); in extron_setup()
1516 err = PTR_ERR_OR_ZERO(port->adap); in extron_setup()
1518 kfree(port); in extron_setup()
1522 port->adap->xfer_timeout_ms = EXTRON_TIMEOUT_SECS * 1000; in extron_setup()
1523 port->port.adap = port->adap; in extron_setup()
1524 port->vdev = extron_videodev; in extron_setup()
1525 port->vdev.lock = &port->video_lock; in extron_setup()
1526 port->vdev.v4l2_dev = &extron->v4l2_dev; in extron_setup()
1527 port->vdev.ctrl_handler = &port->hdl; in extron_setup()
1528 port->vdev.device_caps = V4L2_CAP_EDID; in extron_setup()
1529 video_set_drvdata(&port->vdev, port); in extron_setup()
1531 v4l2_ctrl_handler_init(&port->hdl, 2); in extron_setup()
1533 if (port->is_input) { in extron_setup()
1534 port->vdev.vfl_dir = VFL_DIR_RX; in extron_setup()
1535 port->ctrl_rx_power_present = in extron_setup()
1536 v4l2_ctrl_new_std(&port->hdl, NULL, in extron_setup()
1538 0, 1, 0, 0); in extron_setup()
1539 port->has_edid = true; in extron_setup()
1541 port->vdev.vfl_dir = VFL_DIR_TX; in extron_setup()
1542 port->ctrl_tx_hotplug = in extron_setup()
1543 v4l2_ctrl_new_std(&port->hdl, NULL, in extron_setup()
1545 0, 1, 0, 0); in extron_setup()
1546 port->ctrl_tx_edid_present = in extron_setup()
1547 v4l2_ctrl_new_std(&port->hdl, NULL, in extron_setup()
1549 0, 1, 0, 0); in extron_setup()
1552 err = port->hdl.error; in extron_setup()
1554 cec_delete_adapter(port->adap); in extron_setup()
1555 kfree(port); in extron_setup()
1558 extron->ports[p] = port; in extron_setup()
1559 extron->splitter_ports[p] = &port->port; in extron_setup()
1560 if (port->is_input && manufacturer_name[0]) in extron_setup()
1561 extron_write_edid(port, hdmi_edid, 2); in extron_setup()
1578 for (p = 0; p < extron->num_out_ports; p++) { in extron_setup()
1582 snprintf(cmd, sizeof(cmd), "WO%u*15LCEC", p + 1); in extron_setup()
1583 snprintf(resp, sizeof(resp), "LcecO%u*15", p + 1); in extron_setup()
1584 err = extron_send_and_wait(extron, extron->ports[p], cmd, resp); in extron_setup()
1593 extron->is_ready = true; in extron_setup()
1606 struct extron_port *port; in extron_setup_thread() local
1612 while (1) { in extron_setup_thread()
1621 ssleep(1); in extron_setup_thread()
1626 * powered up and while the serial port is working, the firmware is in extron_setup_thread()
1639 for (p = 0; p < extron->num_ports; p++) { in extron_setup_thread()
1642 port = extron->ports[p]; in extron_setup_thread()
1643 if (port->is_input && manufacturer_name[0]) in extron_setup_thread()
1644 v4l2_disable_ioctl(&port->vdev, VIDIOC_S_EDID); in extron_setup_thread()
1645 err = video_register_device(&port->vdev, VFL_TYPE_VIDEO, -1); in extron_setup_thread()
1647 v4l2_err(&extron->v4l2_dev, "Failed to register video device\n"); in extron_setup_thread()
1651 err = cec_register_adapter(port->adap, extron->dev); in extron_setup_thread()
1654 port->dev = &port->adap->devnode.dev; in extron_setup_thread()
1655 port->cec_was_registered = true; in extron_setup_thread()
1673 cec_get_device(port->adap); in extron_setup_thread()
1685 log_addrs.num_log_addrs = 1; in extron_setup_thread()
1687 if (port->is_input) { in extron_setup_thread()
1695 "Splitter Out%u", port->port.port); in extron_setup_thread()
1700 err = cec_s_log_addrs(port->adap, &log_addrs, false); in extron_setup_thread()
1706 port = extron->ports[extron->num_out_ports]; in extron_setup_thread()
1708 ssleep(1); in extron_setup_thread()
1709 if (hpd_never_low != extron->hpd_never_low) { in extron_setup_thread()
1711 * Keep input port HPD high at all times, or pull it low in extron_setup_thread()
1715 dev_info(extron->dev, "Always keep input HPD high\n"); in extron_setup_thread()
1718 dev_info(extron->dev, "Pull input HPD low if all output HPDs are low\n"); in extron_setup_thread()
1721 extron->hpd_never_low = hpd_never_low; in extron_setup_thread()
1724 cec_splitter_poll(&extron->splitter, port->adap, debug) && in extron_setup_thread()
1730 cancel_delayed_work_sync(&extron->work_update_edid); in extron_setup_thread()
1731 schedule_delayed_work(&extron->work_update_edid, in extron_setup_thread()
1738 extron->is_ready = false; in extron_setup_thread()
1739 for (p = 0; p < extron->num_ports; p++) { in extron_setup_thread()
1740 struct extron_port *port = extron->ports[p]; in extron_setup_thread() local
1742 if (!port) in extron_setup_thread()
1744 port->disconnected = true; in extron_setup_thread()
1745 cancel_work_sync(&port->irq_work); in extron_setup_thread()
1746 video_unregister_device(&port->vdev); in extron_setup_thread()
1747 if (port->cec_was_registered) in extron_setup_thread()
1748 cec_unregister_adapter(port->adap); in extron_setup_thread()
1750 cancel_delayed_work_sync(&extron->work_update_edid); in extron_setup_thread()
1751 complete(&extron->edid_completion); in extron_setup_thread()
1752 dev_err(extron->dev, "Setup failed with error %d\n", err); in extron_setup_thread()
1754 ssleep(1); in extron_setup_thread()
1761 int err = -ENOMEM; in extron_connect()
1765 !isupper(manufacturer_name[1]) || in extron_connect()
1767 dev_warn(&serio->dev, "ignoring invalid manufacturer name\n"); in extron_connect()
1774 return -ENOMEM; in extron_connect()
1776 extron->serio = serio; in extron_connect()
1777 extron->dev = &serio->dev; in extron_connect()
1778 mutex_init(&extron->serio_lock); in extron_connect()
1779 mutex_init(&extron->edid_lock); in extron_connect()
1780 INIT_DELAYED_WORK(&extron->work_update_edid, update_edid_work); in extron_connect()
1782 err = v4l2_device_register(extron->dev, &extron->v4l2_dev); in extron_connect()
1791 init_completion(&extron->edid_completion); in extron_connect()
1793 extron->kthread_setup = kthread_run(extron_setup_thread, extron, in extron_connect()
1794 "extron-da-hd-4k-plus-cec-%s", dev_name(&serio->dev)); in extron_connect()
1795 if (!IS_ERR(extron->kthread_setup)) in extron_connect()
1798 dev_err(extron->dev, "kthread_run() failed\n"); in extron_connect()
1799 err = PTR_ERR(extron->kthread_setup); in extron_connect()
1801 extron->serio = NULL; in extron_connect()
1805 v4l2_device_unregister(&extron->v4l2_dev); in extron_connect()
1807 mutex_destroy(&extron->edid_lock); in extron_connect()
1808 mutex_destroy(&extron->serio_lock); in extron_connect()
1827 .name = "extron-da-hd-4k-plus-cec",