drivers/media/test-drivers/vivid/vivid-cec.c

Source file repositories/reference/linux-study-clean/drivers/media/test-drivers/vivid/vivid-cec.c

File Facts

System
Linux kernel
Corpus path
drivers/media/test-drivers/vivid/vivid-cec.c
Extension
.c
Size
12142 bytes
Lines
416
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

struct xfer_on_bus {
	struct cec_adapter	*adap;
	u8			status;
};

static bool find_dest_adap(struct vivid_dev *dev,
			   struct cec_adapter *adap, u8 dest)
{
	unsigned int i, j;

	if (dest >= 0xf)
		return false;

	if (adap != dev->cec_rx_adap && dev->cec_rx_adap &&
	    dev->cec_rx_adap->is_configured &&
	    cec_has_log_addr(dev->cec_rx_adap, dest))
		return true;

	for (i = 0, j = 0; i < dev->num_inputs; i++) {
		unsigned int menu_idx =
			dev->input_is_connected_to_output[i];

		if (dev->input_type[i] != HDMI)
			continue;
		j++;
		if (menu_idx < FIXED_MENU_ITEMS)
			continue;

		struct vivid_dev *dev_tx = vivid_ctrl_hdmi_to_output_instance[menu_idx];
		unsigned int output = vivid_ctrl_hdmi_to_output_index[menu_idx];

		if (!dev_tx)
			continue;

		unsigned int hdmi_output = dev_tx->output_to_iface_index[output];

		if (adap == dev_tx->cec_tx_adap[hdmi_output])
			continue;
		if (!dev_tx->cec_tx_adap[hdmi_output]->is_configured)
			continue;
		if (cec_has_log_addr(dev_tx->cec_tx_adap[hdmi_output], dest))
			return true;
	}
	return false;
}

static bool xfer_ready(struct vivid_dev *dev)
{
	unsigned int i;
	bool ready = false;

	spin_lock(&dev->cec_xfers_slock);
	for (i = 0; i < ARRAY_SIZE(dev->xfers); i++) {
		if (dev->xfers[i].sft &&
		    dev->xfers[i].sft <= dev->cec_sft) {
			ready = true;
			break;
		}
	}
	spin_unlock(&dev->cec_xfers_slock);

	return ready;
}

/*
 * If an adapter tries to send successive messages, it must wait for the
 * longest signal-free time between its transmissions. But, if another
 * adapter sends a message in the interim, then the wait can be reduced
 * because the messages are no longer successive. Make these adjustments
 * if necessary. Should be called holding cec_xfers_slock.
 */
static void adjust_sfts(struct vivid_dev *dev)
{
	unsigned int i;
	u8 initiator;

	for (i = 0; i < ARRAY_SIZE(dev->xfers); i++) {
		if (dev->xfers[i].sft <= CEC_SIGNAL_FREE_TIME_RETRY)
			continue;
		initiator = dev->xfers[i].msg[0] >> 4;
		if (initiator == dev->last_initiator)
			dev->xfers[i].sft = CEC_SIGNAL_FREE_TIME_NEXT_XFER;
		else
			dev->xfers[i].sft = CEC_SIGNAL_FREE_TIME_NEW_INITIATOR;
	}
}

/*
 * The main emulation of the bus on which CEC adapters attempt to send
 * messages to each other. The bus keeps track of how long it has been

Annotation

Implementation Notes