drivers/media/pci/saa7134/saa7134-i2c.c

Source file repositories/reference/linux-study-clean/drivers/media/pci/saa7134/saa7134-i2c.c

File Facts

System
Linux kernel
Corpus path
drivers/media/pci/saa7134/saa7134-i2c.c
Extension
.c
Size
11407 bytes
Lines
457
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 (!(msgs[i].flags & I2C_M_NOSTART) || 0 == i) {
			/* send address */
			saa7134_i2c_dbg(2, "send address\n");
			addr  = msgs[i].addr << 1;
			if (msgs[i].flags & I2C_M_RD)
				addr |= 1;
			if (i > 0 && msgs[i].flags &
			    I2C_M_RD && msgs[i].addr != 0x40 &&
			    msgs[i].addr != 0x41 &&
			    msgs[i].addr != 0x19) {
				/* workaround for a saa7134 i2c bug
				 * needed to talk to the mt352 demux
				 * thanks to pinnacle for the hint */
				int quirk = 0xfe;
				i2c_cont(1, " [%02x quirk]", quirk);
				i2c_send_byte(dev,START,quirk);
				i2c_recv_byte(dev);
			}
			i2c_cont(1, " < %02x", addr);
			rc = i2c_send_byte(dev,START,addr);
			if (rc < 0)
				 goto err;
		}
		if (msgs[i].flags & I2C_M_RD) {
			/* read bytes */
			saa7134_i2c_dbg(2, "read bytes\n");
			for (byte = 0; byte < msgs[i].len; byte++) {
				i2c_cont(1, " =");
				rc = i2c_recv_byte(dev);
				if (rc < 0)
					goto err;
				i2c_cont(1, "%02x", rc);
				msgs[i].buf[byte] = rc;
			}
			/* discard mysterious extra byte when reading
			   from Samsung S5H1411.  i2c bus gets error
			   if we do not. */
			if (0x19 == msgs[i].addr) {
				i2c_cont(1, " ?");
				rc = i2c_recv_byte(dev);
				if (rc < 0)
					goto err;
				i2c_cont(1, "%02x", rc);
			}
		} else {
			/* write bytes */
			saa7134_i2c_dbg(2, "write bytes\n");
			for (byte = 0; byte < msgs[i].len; byte++) {
				data = msgs[i].buf[byte];
				i2c_cont(1, " %02x", data);
				rc = i2c_send_byte(dev,CONTINUE,data);
				if (rc < 0)
					goto err;
			}
		}
	}
	saa7134_i2c_dbg(2, "xfer done\n");
	i2c_cont(1, " >");
	i2c_set_attr(dev,STOP);
	rc = -EIO;
	if (!i2c_is_busy_wait(dev))
		goto err;
	status = i2c_get_status(dev);
	if (i2c_is_error(status))
		goto err;
	/* ensure that the bus is idle for at least one bit slot */
	msleep(1);

	i2c_cont(1, "\n");
	return num;
 err:
	if (1 == i2c_debug) {
		status = i2c_get_status(dev);
		i2c_cont(1, " ERROR: %s\n", str_i2c_status[status]);
	}
	return rc;
}

/* ----------------------------------------------------------- */

static u32 functionality(struct i2c_adapter *adap)
{
	return I2C_FUNC_SMBUS_EMUL;
}

static const struct i2c_algorithm saa7134_algo = {
	.master_xfer   = saa7134_i2c_xfer,
	.functionality = functionality,
};

Annotation

Implementation Notes