drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c
Extension
.c
Size
10149 bytes
Lines
354
Domain
Driver Families
Bucket
drivers/gpu
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 (!(cnt & 0x80)) {
			struct cec_msg msg = {};
			unsigned int i;

			/* then read the message */
			msg.len = cnt & 0xf;
			if (msg.len > CEC_MAX_MSG_SIZE - 2)
				msg.len = CEC_MAX_MSG_SIZE - 2;
			msg.msg[0] = hdmi_read_reg(core->base,
						   HDMI_CEC_RX_CMD_HEADER);
			msg.msg[1] = hdmi_read_reg(core->base,
						   HDMI_CEC_RX_COMMAND);
			for (i = 0; i < msg.len; i++) {
				unsigned int reg = HDMI_CEC_RX_OPERAND + i * 4;

				msg.msg[2 + i] =
					hdmi_read_reg(core->base, reg);
			}
			msg.len += 2;
			cec_received_msg(core->adap, &msg);
		}
		/* Clear the current frame from the FIFO */
		hdmi_write_reg(core->base, HDMI_CEC_RX_CONTROL, 1);
		/* Wait until the current frame is cleared */
		while (hdmi_read_reg(core->base, HDMI_CEC_RX_CONTROL) & 1)
			udelay(1);
		/*
		 * Re-read the count register and loop to see if there are
		 * more messages in the FIFO.
		 */
		cnt = hdmi_read_reg(core->base, HDMI_CEC_RX_COUNT) & 0xff;
	}
}

void hdmi4_cec_irq(struct hdmi_core_data *core)
{
	u32 stat0 = hdmi_read_reg(core->base, HDMI_CEC_INT_STATUS_0);
	u32 stat1 = hdmi_read_reg(core->base, HDMI_CEC_INT_STATUS_1);

	hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_0, stat0);
	hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_1, stat1);

	if (stat0 & 0x20) {
		cec_transmit_done(core->adap, CEC_TX_STATUS_OK,
				  0, 0, 0, 0);
		REG_FLD_MOD(core->base, HDMI_CEC_DBG_3, 0x1, 7, 7);
	} else if (stat1 & 0x02) {
		u32 dbg3 = hdmi_read_reg(core->base, HDMI_CEC_DBG_3);

		cec_transmit_done(core->adap,
				  CEC_TX_STATUS_NACK |
				  CEC_TX_STATUS_MAX_RETRIES,
				  0, (dbg3 >> 4) & 7, 0, 0);
		REG_FLD_MOD(core->base, HDMI_CEC_DBG_3, 0x1, 7, 7);
	}
	if (stat0 & 0x02)
		hdmi_cec_received_msg(core);
}

static bool hdmi_cec_clear_tx_fifo(struct cec_adapter *adap)
{
	struct hdmi_core_data *core = cec_get_drvdata(adap);
	int retry = HDMI_CORE_CEC_RETRY;
	int temp;

	REG_FLD_MOD(core->base, HDMI_CEC_DBG_3, 0x1, 7, 7);
	while (retry) {
		temp = hdmi_read_reg(core->base, HDMI_CEC_DBG_3);
		if (FLD_GET(temp, 7, 7) == 0)
			break;
		retry--;
	}
	return retry != 0;
}

static bool hdmi_cec_clear_rx_fifo(struct cec_adapter *adap)
{
	struct hdmi_core_data *core = cec_get_drvdata(adap);
	int retry = HDMI_CORE_CEC_RETRY;
	int temp;

	hdmi_write_reg(core->base, HDMI_CEC_RX_CONTROL, 0x3);
	retry = HDMI_CORE_CEC_RETRY;
	while (retry) {
		temp = hdmi_read_reg(core->base, HDMI_CEC_RX_CONTROL);
		if (FLD_GET(temp, 1, 0) == 0)
			break;
		retry--;
	}
	return retry != 0;

Annotation

Implementation Notes