drivers/media/cec/platform/seco/seco-cec.c

Source file repositories/reference/linux-study-clean/drivers/media/cec/platform/seco/seco-cec.c

File Facts

System
Linux kernel
Corpus path
drivers/media/cec/platform/seco/seco-cec.c
Extension
.c
Size
17752 bytes
Lines
793
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 secocec_data {
	struct device *dev;
	struct platform_device *pdev;
	struct cec_adapter *cec_adap;
	struct cec_notifier *notifier;
	struct rc_dev *ir;
	char ir_input_phys[32];
	int irq;
};

#define smb_wr16(cmd, data) smb_word_op(SECOCEC_MICRO_ADDRESS, \
					cmd, data, SMBUS_WRITE, NULL)
#define smb_rd16(cmd, res) smb_word_op(SECOCEC_MICRO_ADDRESS, \
				       cmd, 0, SMBUS_READ, res)

static int smb_word_op(u16 slave_addr, u8 cmd, u16 data,
		       u8 operation, u16 *result)
{
	unsigned int count;
	int status = 0;

	/* Active wait until ready */
	for (count = 0; count <= SMBTIMEOUT; ++count) {
		if (!(inb(HSTS) & BRA_INUSE_STS))
			break;
		udelay(SMB_POLL_UDELAY);
	}

	if (count > SMBTIMEOUT)
		/* Reset the lock instead of failing */
		outb(0xff, HSTS);

	outb(0x00, HCNT);
	outb((u8)(slave_addr & 0xfe) | operation, XMIT_SLVA);
	outb(cmd, HCMD);
	inb(HCNT);

	if (operation == SMBUS_WRITE) {
		outb((u8)data, HDAT0);
		outb((u8)(data >> 8), HDAT1);
	}

	outb(BRA_START + BRA_SMB_CMD_WORD_DATA, HCNT);

	for (count = 0; count <= SMBTIMEOUT; count++) {
		if (!(inb(HSTS) & BRA_HOST_BUSY))
			break;
		udelay(SMB_POLL_UDELAY);
	}

	if (count > SMBTIMEOUT) {
		status = -EBUSY;
		goto err;
	}

	if (inb(HSTS) & BRA_HSTS_ERR_MASK) {
		status = -EIO;
		goto err;
	}

	if (operation == SMBUS_READ)
		*result = ((inb(HDAT0) & 0xff) + ((inb(HDAT1) & 0xff) << 8));

err:
	outb(0xff, HSTS);
	return status;
}

static int secocec_adap_enable(struct cec_adapter *adap, bool enable)
{
	struct secocec_data *cec = cec_get_drvdata(adap);
	struct device *dev = cec->dev;
	u16 val = 0;
	int status;

	if (enable) {
		/* Clear the status register */
		status = smb_rd16(SECOCEC_STATUS_REG_1, &val);
		if (status)
			goto err;

		status = smb_wr16(SECOCEC_STATUS_REG_1, val);
		if (status)
			goto err;

		/* Enable the interrupts */
		status = smb_rd16(SECOCEC_ENABLE_REG_1, &val);
		if (status)
			goto err;

Annotation

Implementation Notes