drivers/media/cec/usb/extron-da-hd-4k-plus/cec-splitter.c

Source file repositories/reference/linux-study-clean/drivers/media/cec/usb/extron-da-hd-4k-plus/cec-splitter.c

File Facts

System
Linux kernel
Corpus path
drivers/media/cec/usb/extron-da-hd-4k-plus/cec-splitter.c
Extension
.c
Size
18916 bytes
Lines
658
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!adap->is_configured) {
			/* Clear if not configured */
			p->out_request_current_latency_seq = 0;
			p->out_request_current_latency_ts = ktime_set(0, 0);
		} else if (!p->out_request_current_latency_seq) {
			/*
			 * Keep the old ts if an earlier request is still
			 * pending. This ensures that the request will
			 * eventually time out based on the timestamp of
			 * the first request if the sink is unresponsive.
			 */
			p->out_request_current_latency_ts = now;
		}
	}

	for (i = 0; i < splitter->num_out_ports; i++) {
		struct cec_splitter_port *p = splitter->ports[i];
		struct cec_adapter *adap = p->adap;
		struct cec_msg msg;

		if (!adap->is_configured)
			continue;
		cec_msg_init(&msg, adap->log_addrs.log_addr[0], 0);
		cec_msg_request_current_latency(&msg, true, adap->phys_addr);
		if (cec_transmit_msg(adap, &msg, false))
			continue;
		p->out_request_current_latency_seq = msg.sequence | (1U << 31);
		error = false;
	}
	return error ? -ENODEV : 0;
}

/*
 * See if all output ports received the Report Power Status message,
 * and if so, transmit the result from the input port to the video source.
 */
static void cec_out_report_power_status(struct cec_splitter *splitter,
					struct cec_adapter *input_adap)
{
	struct cec_msg reply = {};
	/* The target power status of the splitter itself */
	u8 splitter_pwr = splitter->is_standby ?
		CEC_OP_POWER_STATUS_STANDBY : CEC_OP_POWER_STATUS_ON;
	/*
	 * The transient power status of the splitter, used if not all
	 * output report the target power status.
	 */
	u8 splitter_transient_pwr = splitter->is_standby ?
		CEC_OP_POWER_STATUS_TO_STANDBY : CEC_OP_POWER_STATUS_TO_ON;
	u8 reply_pwr = splitter_pwr;
	unsigned int i;

	for (i = 0; i < splitter->num_out_ports; i++) {
		struct cec_splitter_port *p = splitter->ports[i];

		/* Skip if no sink was found (HPD was low for more than 5s) */
		if (!p->found_sink)
			continue;

		/* Return if a port is still waiting for a reply */
		if (p->out_give_device_power_status_seq)
			return;
		if (p->power_status != splitter_pwr)
			reply_pwr = splitter_transient_pwr;
	}

	/*
	 * All ports that can reply, replied, so clear the sequence
	 * and timestamp values.
	 */
	for (i = 0; i < splitter->num_out_ports; i++) {
		struct cec_splitter_port *p = splitter->ports[i];

		p->out_give_device_power_status_seq = 0;
		p->out_give_device_power_status_ts = ktime_set(0, 0);
	}

	/* Return if the input port is no longer configured. */
	if (!input_adap->is_configured)
		return;

	/* Reply with the new power status */
	cec_msg_init(&reply, input_adap->log_addrs.log_addr[0],
		     splitter->give_device_power_status_dest);
	cec_msg_report_power_status(&reply, reply_pwr);
	cec_transmit_msg(input_adap, &reply, false);
}

/* Transmit Give Device Power Status to all output ports */
static int cec_out_give_device_power_status(struct cec_splitter *splitter)

Annotation

Implementation Notes