drivers/media/cec/i2c/ch7322.c

Source file repositories/reference/linux-study-clean/drivers/media/cec/i2c/ch7322.c

File Facts

System
Linux kernel
Corpus path
drivers/media/cec/i2c/ch7322.c
Extension
.c
Size
13859 bytes
Lines
603
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 ch7322 {
	struct i2c_client *i2c;
	struct regmap *regmap;
	struct cec_adapter *cec;
	struct mutex mutex;	/* device access mutex */
	u8 tx_flags;
};

static const struct regmap_config ch7322_regmap = {
	.reg_bits = 8,
	.val_bits = 8,
	.max_register = 0x7f,
	.disable_locking = true,
};

static int ch7322_send_message(struct ch7322 *ch7322, const struct cec_msg *msg)
{
	unsigned int val;
	unsigned int len = msg->len;
	int ret;
	int i;

	WARN_ON(!mutex_is_locked(&ch7322->mutex));

	if (len > CH7322_WRBUF_LEN || len < 1)
		return -EINVAL;

	ret = regmap_read(ch7322->regmap, CH7322_WRITE, &val);
	if (ret)
		return ret;

	/* Buffer not ready */
	if (!(val & CH7322_WRITE_MSENT))
		return -EBUSY;

	if (cec_msg_opcode(msg) == -1 &&
	    cec_msg_initiator(msg) == cec_msg_destination(msg)) {
		ch7322->tx_flags = CH7322_TX_FLAG_NACK | CH7322_TX_FLAG_RETRY;
	} else if (cec_msg_is_broadcast(msg)) {
		ch7322->tx_flags = CH7322_TX_FLAG_NACK;
	} else {
		ch7322->tx_flags = CH7322_TX_FLAG_RETRY;
	}

	ret = regmap_write(ch7322->regmap, CH7322_WRITE, len - 1);
	if (ret)
		return ret;

	for (i = 0; i < len; i++) {
		ret = regmap_write(ch7322->regmap,
				   CH7322_WRBUF + i, msg->msg[i]);
		if (ret)
			return ret;
	}

	return 0;
}

static int ch7322_receive_message(struct ch7322 *ch7322, struct cec_msg *msg)
{
	unsigned int val;
	int ret = 0;
	int i;

	WARN_ON(!mutex_is_locked(&ch7322->mutex));

	ret = regmap_read(ch7322->regmap, CH7322_READ, &val);
	if (ret)
		return ret;

	/* Message not ready */
	if (!(val & CH7322_READ_NRDT))
		return -EIO;

	msg->len = (val & CH7322_READ_NMASK) + 1;

	/* Read entire RDBUF to clear state */
	for (i = 0; i < CH7322_RDBUF_LEN; i++) {
		ret = regmap_read(ch7322->regmap, CH7322_RDBUF + i, &val);
		if (ret)
			return ret;
		msg->msg[i] = (u8)val;
	}

	return 0;
}

static void ch7322_tx_done(struct ch7322 *ch7322)
{
	int ret;

Annotation

Implementation Notes