1 // SPDX-License-Identifier: GPL-2.0-only 2 3 /* 4 * Copyright 2021-2024 Cisco Systems, Inc. and/or its affiliates. All rights reserved. 5 */ 6 7 #include <media/cec.h> 8 9 #include "cec-splitter.h" 10 11 /* 12 * Helper function to reply to a received message with a Feature Abort 13 * message. 14 */ 15 static int cec_feature_abort_reason(struct cec_adapter *adap, 16 struct cec_msg *msg, u8 reason) 17 { 18 struct cec_msg tx_msg = { }; 19 20 /* 21 * Don't reply with CEC_MSG_FEATURE_ABORT to a CEC_MSG_FEATURE_ABORT 22 * message! 23 */ 24 if (msg->msg[1] == CEC_MSG_FEATURE_ABORT) 25 return 0; 26 /* Don't Feature Abort messages from 'Unregistered' */ 27 if (cec_msg_initiator(msg) == CEC_LOG_ADDR_UNREGISTERED) 28 return 0; 29 cec_msg_set_reply_to(&tx_msg, msg); 30 cec_msg_feature_abort(&tx_msg, msg->msg[1], reason); 31 return cec_transmit_msg(adap, &tx_msg, false); 32 } 33 34 /* Transmit an Active Source message from this output port to a sink */ 35 static void cec_port_out_active_source(struct cec_splitter_port *p) 36 { 37 struct cec_adapter *adap = p->adap; 38 struct cec_msg msg; 39 40 if (!adap->is_configured) 41 return; 42 p->is_active_source = true; 43 cec_msg_init(&msg, adap->log_addrs.log_addr[0], 0); 44 cec_msg_active_source(&msg, adap->phys_addr); 45 cec_transmit_msg(adap, &msg, false); 46 } 47 48 /* Transmit Active Source messages from all output ports to the sinks */ 49 static void cec_out_active_source(struct cec_splitter *splitter) 50 { 51 unsigned int i; 52 53 for (i = 0; i < splitter->num_out_ports; i++) 54 cec_port_out_active_source(splitter->ports[i]); 55 } 56 57 /* Transmit a Standby message from this output port to a sink */ 58 static void cec_port_out_standby(struct cec_splitter_port *p) 59 { 60 struct cec_adapter *adap = p->adap; 61 struct cec_msg msg; 62 63 if (!adap->is_configured) 64 return; 65 cec_msg_init(&msg, adap->log_addrs.log_addr[0], 0); 66 cec_msg_standby(&msg); 67 cec_transmit_msg(adap, &msg, false); 68 } 69 70 /* Transmit Standby messages from all output ports to the sinks */ 71 static void cec_out_standby(struct cec_splitter *splitter) 72 { 73 unsigned int i; 74 75 for (i = 0; i < splitter->num_out_ports; i++) 76 cec_port_out_standby(splitter->ports[i]); 77 } 78 79 /* Transmit an Image/Text View On message from this output port to a sink */ 80 static void cec_port_out_wakeup(struct cec_splitter_port *p, u8 opcode) 81 { 82 struct cec_adapter *adap = p->adap; 83 u8 la = adap->log_addrs.log_addr[0]; 84 struct cec_msg msg; 85 86 if (la == CEC_LOG_ADDR_INVALID) 87 la = CEC_LOG_ADDR_UNREGISTERED; 88 cec_msg_init(&msg, la, 0); 89 msg.len = 2; 90 msg.msg[1] = opcode; 91 cec_transmit_msg(adap, &msg, false); 92 } 93 94 /* Transmit Image/Text View On messages from all output ports to the sinks */ 95 static void cec_out_wakeup(struct cec_splitter *splitter, u8 opcode) 96 { 97 unsigned int i; 98 99 for (i = 0; i < splitter->num_out_ports; i++) 100 cec_port_out_wakeup(splitter->ports[i], opcode); 101 } 102 103 /* 104 * Update the power state of the unconfigured CEC device to either 105 * Off or On depending on the current state of the splitter. 106 * This keeps the outputs in a consistent state. 107 */ 108 void cec_splitter_unconfigured_output(struct cec_splitter_port *p) 109 { 110 p->video_latency = 1; 111 p->power_status = p->splitter->is_standby ? 112 CEC_OP_POWER_STATUS_TO_STANDBY : CEC_OP_POWER_STATUS_TO_ON; 113 114 /* The adapter was unconfigured, so clear the sequence and ts values */ 115 p->out_give_device_power_status_seq = 0; 116 p->out_give_device_power_status_ts = ktime_set(0, 0); 117 p->out_request_current_latency_seq = 0; 118 p->out_request_current_latency_ts = ktime_set(0, 0); 119 } 120 121 /* 122 * Update the power state of the newly configured CEC device to either 123 * Off or On depending on the current state of the splitter. 124 * This keeps the outputs in a consistent state. 125 */ 126 void cec_splitter_configured_output(struct cec_splitter_port *p) 127 { 128 p->video_latency = 1; 129 p->power_status = p->splitter->is_standby ? 130 CEC_OP_POWER_STATUS_TO_STANDBY : CEC_OP_POWER_STATUS_TO_ON; 131 132 if (p->splitter->is_standby) { 133 /* 134 * Some sinks only obey Standby if it comes from the 135 * active source. 136 */ 137 cec_port_out_active_source(p); 138 cec_port_out_standby(p); 139 } else { 140 cec_port_out_wakeup(p, CEC_MSG_IMAGE_VIEW_ON); 141 } 142 } 143 144 /* Pass the in_msg on to all output ports */ 145 static void cec_out_passthrough(struct cec_splitter *splitter, 146 const struct cec_msg *in_msg) 147 { 148 unsigned int i; 149 150 for (i = 0; i < splitter->num_out_ports; i++) { 151 struct cec_splitter_port *p = splitter->ports[i]; 152 struct cec_adapter *adap = p->adap; 153 struct cec_msg msg; 154 155 if (!adap->is_configured) 156 continue; 157 cec_msg_init(&msg, adap->log_addrs.log_addr[0], 0); 158 msg.len = in_msg->len; 159 memcpy(msg.msg + 1, in_msg->msg + 1, msg.len - 1); 160 cec_transmit_msg(adap, &msg, false); 161 } 162 } 163 164 /* 165 * See if all output ports received the Report Current Latency message, 166 * and if so, transmit the result from the input port to the video source. 167 */ 168 static void cec_out_report_current_latency(struct cec_splitter *splitter, 169 struct cec_adapter *input_adap) 170 { 171 struct cec_msg reply = {}; 172 unsigned int reply_lat = 0; 173 unsigned int cnt = 0; 174 unsigned int i; 175 176 for (i = 0; i < splitter->num_out_ports; i++) { 177 struct cec_splitter_port *p = splitter->ports[i]; 178 struct cec_adapter *adap = p->adap; 179 180 /* Skip unconfigured ports */ 181 if (!adap->is_configured) 182 continue; 183 /* Return if a port is still waiting for a reply */ 184 if (p->out_request_current_latency_seq) 185 return; 186 reply_lat += p->video_latency - 1; 187 cnt++; 188 } 189 190 /* 191 * All ports that can reply, replied, so clear the sequence 192 * and timestamp values. 193 */ 194 for (i = 0; i < splitter->num_out_ports; i++) { 195 struct cec_splitter_port *p = splitter->ports[i]; 196 197 p->out_request_current_latency_seq = 0; 198 p->out_request_current_latency_ts = ktime_set(0, 0); 199 } 200 201 /* 202 * Return if there were no replies or the input port is no longer 203 * configured. 204 */ 205 if (!cnt || !input_adap->is_configured) 206 return; 207 208 /* Reply with the average latency */ 209 reply_lat = 1 + reply_lat / cnt; 210 cec_msg_init(&reply, input_adap->log_addrs.log_addr[0], 211 splitter->request_current_latency_dest); 212 cec_msg_report_current_latency(&reply, input_adap->phys_addr, 213 reply_lat, 1, 1, 1); 214 cec_transmit_msg(input_adap, &reply, false); 215 } 216 217 /* Transmit Request Current Latency to all output ports */ 218 static int cec_out_request_current_latency(struct cec_splitter *splitter) 219 { 220 ktime_t now = ktime_get(); 221 bool error = true; 222 unsigned int i; 223 224 for (i = 0; i < splitter->num_out_ports; i++) { 225 struct cec_splitter_port *p = splitter->ports[i]; 226 struct cec_adapter *adap = p->adap; 227 228 if (!adap->is_configured) { 229 /* Clear if not configured */ 230 p->out_request_current_latency_seq = 0; 231 p->out_request_current_latency_ts = ktime_set(0, 0); 232 } else if (!p->out_request_current_latency_seq) { 233 /* 234 * Keep the old ts if an earlier request is still 235 * pending. This ensures that the request will 236 * eventually time out based on the timestamp of 237 * the first request if the sink is unresponsive. 238 */ 239 p->out_request_current_latency_ts = now; 240 } 241 } 242 243 for (i = 0; i < splitter->num_out_ports; i++) { 244 struct cec_splitter_port *p = splitter->ports[i]; 245 struct cec_adapter *adap = p->adap; 246 struct cec_msg msg; 247 248 if (!adap->is_configured) 249 continue; 250 cec_msg_init(&msg, adap->log_addrs.log_addr[0], 0); 251 cec_msg_request_current_latency(&msg, true, adap->phys_addr); 252 if (cec_transmit_msg(adap, &msg, false)) 253 continue; 254 p->out_request_current_latency_seq = msg.sequence | (1U << 31); 255 error = false; 256 } 257 return error ? -ENODEV : 0; 258 } 259 260 /* 261 * See if all output ports received the Report Power Status message, 262 * and if so, transmit the result from the input port to the video source. 263 */ 264 static void cec_out_report_power_status(struct cec_splitter *splitter, 265 struct cec_adapter *input_adap) 266 { 267 struct cec_msg reply = {}; 268 /* The target power status of the splitter itself */ 269 u8 splitter_pwr = splitter->is_standby ? 270 CEC_OP_POWER_STATUS_STANDBY : CEC_OP_POWER_STATUS_ON; 271 /* 272 * The transient power status of the splitter, used if not all 273 * output report the target power status. 274 */ 275 u8 splitter_transient_pwr = splitter->is_standby ? 276 CEC_OP_POWER_STATUS_TO_STANDBY : CEC_OP_POWER_STATUS_TO_ON; 277 u8 reply_pwr = splitter_pwr; 278 unsigned int i; 279 280 for (i = 0; i < splitter->num_out_ports; i++) { 281 struct cec_splitter_port *p = splitter->ports[i]; 282 283 /* Skip if no sink was found (HPD was low for more than 5s) */ 284 if (!p->found_sink) 285 continue; 286 287 /* Return if a port is still waiting for a reply */ 288 if (p->out_give_device_power_status_seq) 289 return; 290 if (p->power_status != splitter_pwr) 291 reply_pwr = splitter_transient_pwr; 292 } 293 294 /* 295 * All ports that can reply, replied, so clear the sequence 296 * and timestamp values. 297 */ 298 for (i = 0; i < splitter->num_out_ports; i++) { 299 struct cec_splitter_port *p = splitter->ports[i]; 300 301 p->out_give_device_power_status_seq = 0; 302 p->out_give_device_power_status_ts = ktime_set(0, 0); 303 } 304 305 /* Return if the input port is no longer configured. */ 306 if (!input_adap->is_configured) 307 return; 308 309 /* Reply with the new power status */ 310 cec_msg_init(&reply, input_adap->log_addrs.log_addr[0], 311 splitter->give_device_power_status_dest); 312 cec_msg_report_power_status(&reply, reply_pwr); 313 cec_transmit_msg(input_adap, &reply, false); 314 } 315 316 /* Transmit Give Device Power Status to all output ports */ 317 static int cec_out_give_device_power_status(struct cec_splitter *splitter) 318 { 319 ktime_t now = ktime_get(); 320 bool error = true; 321 unsigned int i; 322 323 for (i = 0; i < splitter->num_out_ports; i++) { 324 struct cec_splitter_port *p = splitter->ports[i]; 325 struct cec_adapter *adap = p->adap; 326 327 /* 328 * Keep the old ts if an earlier request is still 329 * pending. This ensures that the request will 330 * eventually time out based on the timestamp of 331 * the first request if the sink is unresponsive. 332 */ 333 if (adap->is_configured && !p->out_give_device_power_status_seq) 334 p->out_give_device_power_status_ts = now; 335 } 336 337 for (i = 0; i < splitter->num_out_ports; i++) { 338 struct cec_splitter_port *p = splitter->ports[i]; 339 struct cec_adapter *adap = p->adap; 340 struct cec_msg msg; 341 342 if (!adap->is_configured) 343 continue; 344 345 cec_msg_init(&msg, adap->log_addrs.log_addr[0], 0); 346 cec_msg_give_device_power_status(&msg, true); 347 if (cec_transmit_msg(adap, &msg, false)) 348 continue; 349 p->out_give_device_power_status_seq = msg.sequence | (1U << 31); 350 error = false; 351 } 352 return error ? -ENODEV : 0; 353 } 354 355 /* 356 * CEC messages received on the HDMI input of the splitter are 357 * forwarded (if relevant) to the HDMI outputs of the splitter. 358 */ 359 int cec_splitter_received_input(struct cec_splitter_port *p, struct cec_msg *msg) 360 { 361 if (!cec_msg_status_is_ok(msg)) 362 return 0; 363 364 if (msg->len < 2) 365 return -ENOMSG; 366 367 switch (msg->msg[1]) { 368 case CEC_MSG_DEVICE_VENDOR_ID: 369 case CEC_MSG_REPORT_POWER_STATUS: 370 case CEC_MSG_SET_STREAM_PATH: 371 case CEC_MSG_ROUTING_CHANGE: 372 case CEC_MSG_REQUEST_ACTIVE_SOURCE: 373 case CEC_MSG_SYSTEM_AUDIO_MODE_STATUS: 374 return 0; 375 376 case CEC_MSG_STANDBY: 377 p->splitter->is_standby = true; 378 cec_out_standby(p->splitter); 379 return 0; 380 381 case CEC_MSG_IMAGE_VIEW_ON: 382 case CEC_MSG_TEXT_VIEW_ON: 383 p->splitter->is_standby = false; 384 cec_out_wakeup(p->splitter, msg->msg[1]); 385 return 0; 386 387 case CEC_MSG_ACTIVE_SOURCE: 388 cec_out_active_source(p->splitter); 389 return 0; 390 391 case CEC_MSG_SET_SYSTEM_AUDIO_MODE: 392 cec_out_passthrough(p->splitter, msg); 393 return 0; 394 395 case CEC_MSG_GIVE_DEVICE_POWER_STATUS: 396 p->splitter->give_device_power_status_dest = 397 cec_msg_initiator(msg); 398 if (cec_out_give_device_power_status(p->splitter)) 399 cec_feature_abort_reason(p->adap, msg, 400 CEC_OP_ABORT_INCORRECT_MODE); 401 return 0; 402 403 case CEC_MSG_REQUEST_CURRENT_LATENCY: { 404 u16 pa; 405 406 p->splitter->request_current_latency_dest = 407 cec_msg_initiator(msg); 408 cec_ops_request_current_latency(msg, &pa); 409 if (pa == p->adap->phys_addr && 410 cec_out_request_current_latency(p->splitter)) 411 cec_feature_abort_reason(p->adap, msg, 412 CEC_OP_ABORT_INCORRECT_MODE); 413 return 0; 414 } 415 416 default: 417 return -ENOMSG; 418 } 419 return -ENOMSG; 420 } 421 422 void cec_splitter_nb_transmit_canceled_output(struct cec_splitter_port *p, 423 const struct cec_msg *msg, 424 struct cec_adapter *input_adap) 425 { 426 struct cec_splitter *splitter = p->splitter; 427 u32 seq = msg->sequence | (1U << 31); 428 429 /* 430 * If this is the result of a failed non-blocking transmit, or it is 431 * the result of the failed reply to a non-blocking transmit, then 432 * check if the original transmit was to get the current power status 433 * or latency and, if so, assume that the remove device is for one 434 * reason or another unavailable and assume that it is in the same 435 * power status as the splitter, or has no video latency. 436 */ 437 if ((cec_msg_recv_is_tx_result(msg) && !(msg->tx_status & CEC_TX_STATUS_OK)) || 438 (cec_msg_recv_is_rx_result(msg) && !(msg->rx_status & CEC_RX_STATUS_OK))) { 439 u8 tx_op = msg->msg[1]; 440 441 if (msg->len < 2) 442 return; 443 if (cec_msg_recv_is_rx_result(msg) && 444 (msg->rx_status & CEC_RX_STATUS_FEATURE_ABORT)) 445 tx_op = msg->msg[2]; 446 switch (tx_op) { 447 case CEC_MSG_GIVE_DEVICE_POWER_STATUS: 448 if (p->out_give_device_power_status_seq != seq) 449 break; 450 p->out_give_device_power_status_seq = 0; 451 p->out_give_device_power_status_ts = ktime_set(0, 0); 452 p->power_status = splitter->is_standby ? 453 CEC_OP_POWER_STATUS_STANDBY : 454 CEC_OP_POWER_STATUS_ON; 455 cec_out_report_power_status(splitter, input_adap); 456 break; 457 case CEC_MSG_REQUEST_CURRENT_LATENCY: 458 if (p->out_request_current_latency_seq != seq) 459 break; 460 p->video_latency = 1; 461 p->out_request_current_latency_seq = 0; 462 p->out_request_current_latency_ts = ktime_set(0, 0); 463 cec_out_report_current_latency(splitter, input_adap); 464 break; 465 } 466 return; 467 } 468 469 if (cec_msg_recv_is_tx_result(msg)) { 470 if (p->out_request_current_latency_seq != seq) 471 return; 472 p->out_request_current_latency_ts = ns_to_ktime(msg->tx_ts); 473 return; 474 } 475 } 476 477 /* 478 * CEC messages received on an HDMI output of the splitter 479 * are processed here. 480 */ 481 int cec_splitter_received_output(struct cec_splitter_port *p, struct cec_msg *msg, 482 struct cec_adapter *input_adap) 483 { 484 struct cec_adapter *adap = p->adap; 485 struct cec_splitter *splitter = p->splitter; 486 u32 seq = msg->sequence | (1U << 31); 487 struct cec_msg reply = {}; 488 u16 pa; 489 490 if (!adap->is_configured || msg->len < 2) 491 return -ENOMSG; 492 493 switch (msg->msg[1]) { 494 case CEC_MSG_REPORT_POWER_STATUS: { 495 u8 pwr; 496 497 cec_ops_report_power_status(msg, &pwr); 498 if (pwr > CEC_OP_POWER_STATUS_TO_STANDBY) 499 pwr = splitter->is_standby ? 500 CEC_OP_POWER_STATUS_TO_STANDBY : 501 CEC_OP_POWER_STATUS_TO_ON; 502 p->power_status = pwr; 503 if (p->out_give_device_power_status_seq == seq) { 504 p->out_give_device_power_status_seq = 0; 505 p->out_give_device_power_status_ts = ktime_set(0, 0); 506 } 507 cec_out_report_power_status(splitter, input_adap); 508 return 0; 509 } 510 511 case CEC_MSG_REPORT_CURRENT_LATENCY: { 512 u8 video_lat; 513 u8 low_lat_mode; 514 u8 audio_out_comp; 515 u8 audio_out_delay; 516 517 cec_ops_report_current_latency(msg, &pa, 518 &video_lat, &low_lat_mode, 519 &audio_out_comp, &audio_out_delay); 520 if (!video_lat || video_lat >= 252) 521 video_lat = 1; 522 p->video_latency = video_lat; 523 if (p->out_request_current_latency_seq == seq) { 524 p->out_request_current_latency_seq = 0; 525 p->out_request_current_latency_ts = ktime_set(0, 0); 526 } 527 cec_out_report_current_latency(splitter, input_adap); 528 return 0; 529 } 530 531 case CEC_MSG_STANDBY: 532 case CEC_MSG_ROUTING_CHANGE: 533 case CEC_MSG_GIVE_SYSTEM_AUDIO_MODE_STATUS: 534 return 0; 535 536 case CEC_MSG_ACTIVE_SOURCE: 537 cec_ops_active_source(msg, &pa); 538 if (pa == 0) 539 p->is_active_source = false; 540 return 0; 541 542 case CEC_MSG_REQUEST_ACTIVE_SOURCE: 543 if (!p->is_active_source) 544 return 0; 545 cec_msg_set_reply_to(&reply, msg); 546 cec_msg_active_source(&reply, adap->phys_addr); 547 cec_transmit_msg(adap, &reply, false); 548 return 0; 549 550 case CEC_MSG_GIVE_DEVICE_POWER_STATUS: 551 cec_msg_set_reply_to(&reply, msg); 552 cec_msg_report_power_status(&reply, splitter->is_standby ? 553 CEC_OP_POWER_STATUS_STANDBY : 554 CEC_OP_POWER_STATUS_ON); 555 cec_transmit_msg(adap, &reply, false); 556 return 0; 557 558 case CEC_MSG_SET_STREAM_PATH: 559 cec_ops_set_stream_path(msg, &pa); 560 if (pa == adap->phys_addr) { 561 cec_msg_set_reply_to(&reply, msg); 562 cec_msg_active_source(&reply, pa); 563 cec_transmit_msg(adap, &reply, false); 564 } 565 return 0; 566 567 default: 568 return -ENOMSG; 569 } 570 return -ENOMSG; 571 } 572 573 /* 574 * Called every second to check for timed out messages and whether there 575 * still is a video sink connected or not. 576 * 577 * Returns true if sinks were lost. 578 */ 579 bool cec_splitter_poll(struct cec_splitter *splitter, 580 struct cec_adapter *input_adap, bool debug) 581 { 582 ktime_t now = ktime_get(); 583 u8 pwr = splitter->is_standby ? 584 CEC_OP_POWER_STATUS_STANDBY : CEC_OP_POWER_STATUS_ON; 585 unsigned int max_delay_ms = input_adap->xfer_timeout_ms + 2000; 586 unsigned int i; 587 bool res = false; 588 589 for (i = 0; i < splitter->num_out_ports; i++) { 590 struct cec_splitter_port *p = splitter->ports[i]; 591 s64 pwr_delta, lat_delta; 592 bool pwr_timeout, lat_timeout; 593 594 if (!p) 595 continue; 596 597 pwr_delta = ktime_ms_delta(now, p->out_give_device_power_status_ts); 598 pwr_timeout = p->out_give_device_power_status_seq && 599 pwr_delta >= max_delay_ms; 600 lat_delta = ktime_ms_delta(now, p->out_request_current_latency_ts); 601 lat_timeout = p->out_request_current_latency_seq && 602 lat_delta >= max_delay_ms; 603 604 /* 605 * If the HPD is low for more than 5 seconds, then assume no display 606 * is connected. 607 */ 608 if (p->found_sink && ktime_to_ns(p->lost_sink_ts) && 609 ktime_ms_delta(now, p->lost_sink_ts) > 5000) { 610 if (debug) 611 dev_info(splitter->dev, 612 "port %u: HPD low for more than 5s, assume no sink is connected.\n", 613 p->port); 614 p->found_sink = false; 615 p->lost_sink_ts = ktime_set(0, 0); 616 res = true; 617 } 618 619 /* 620 * If the power status request timed out, then set the port's 621 * power status to that of the splitter, ensuring a consistent 622 * power state. 623 */ 624 if (pwr_timeout) { 625 mutex_lock(&p->adap->lock); 626 if (debug) 627 dev_info(splitter->dev, 628 "port %u: give up on power status for seq %u\n", 629 p->port, 630 p->out_give_device_power_status_seq & ~(1 << 31)); 631 p->power_status = pwr; 632 p->out_give_device_power_status_seq = 0; 633 p->out_give_device_power_status_ts = ktime_set(0, 0); 634 mutex_unlock(&p->adap->lock); 635 cec_out_report_power_status(splitter, input_adap); 636 } 637 638 /* 639 * If the current latency request timed out, then set the port's 640 * latency to 1. 641 */ 642 if (lat_timeout) { 643 mutex_lock(&p->adap->lock); 644 if (debug) 645 dev_info(splitter->dev, 646 "port %u: give up on latency for seq %u\n", 647 p->port, 648 p->out_request_current_latency_seq & ~(1 << 31)); 649 p->video_latency = 1; 650 p->out_request_current_latency_seq = 0; 651 p->out_request_current_latency_ts = ktime_set(0, 0); 652 mutex_unlock(&p->adap->lock); 653 cec_out_report_current_latency(splitter, input_adap); 654 } 655 } 656 return res; 657 } 658