drivers/iio/light/isl29125.c

Source file repositories/reference/linux-study-clean/drivers/iio/light/isl29125.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/light/isl29125.c
Extension
.c
Size
8472 bytes
Lines
347
Domain
Driver Families
Bucket
drivers/iio
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 isl29125_data {
	struct i2c_client *client;
	u8 conf1;
};

#define ISL29125_CHANNEL(_color, _si) { \
	.type = IIO_INTENSITY, \
	.modified = 1, \
	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
	.channel2 = IIO_MOD_LIGHT_##_color, \
	.scan_index = _si, \
	.scan_type = { \
		.sign = 'u', \
		.realbits = 16, \
		.storagebits = 16, \
		.endianness = IIO_CPU, \
	}, \
}

static const struct iio_chan_spec isl29125_channels[] = {
	ISL29125_CHANNEL(GREEN, 0),
	ISL29125_CHANNEL(RED, 1),
	ISL29125_CHANNEL(BLUE, 2),
	IIO_CHAN_SOFT_TIMESTAMP(3),
};

static const struct {
	u8 mode, data;
} isl29125_regs[] = {
	{ISL29125_MODE_G, ISL29125_GREEN_DATA},
	{ISL29125_MODE_R, ISL29125_RED_DATA},
	{ISL29125_MODE_B, ISL29125_BLUE_DATA},
};

static int isl29125_read_data(struct isl29125_data *data, int si)
{
	int tries = 5;
	int ret;

	ret = i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
		data->conf1 | isl29125_regs[si].mode);
	if (ret < 0)
		return ret;

	msleep(101);

	while (tries--) {
		ret = i2c_smbus_read_byte_data(data->client, ISL29125_STATUS);
		if (ret < 0)
			goto fail;
		if (ret & ISL29125_STATUS_CONV)
			break;
		msleep(20);
	}

	if (tries < 0) {
		dev_err(&data->client->dev, "data not ready\n");
		ret = -EIO;
		goto fail;
	}

	ret = i2c_smbus_read_word_data(data->client, isl29125_regs[si].data);

fail:
	i2c_smbus_write_byte_data(data->client, ISL29125_CONF1, data->conf1);
	return ret;
}

static int isl29125_read_raw(struct iio_dev *indio_dev,
			   struct iio_chan_spec const *chan,
			   int *val, int *val2, long mask)
{
	struct isl29125_data *data = iio_priv(indio_dev);
	int ret;

	switch (mask) {
	case IIO_CHAN_INFO_RAW:
		if (!iio_device_claim_direct(indio_dev))
			return -EBUSY;
		ret = isl29125_read_data(data, chan->scan_index);
		iio_device_release_direct(indio_dev);
		if (ret < 0)
			return ret;
		*val = ret;
		return IIO_VAL_INT;
	case IIO_CHAN_INFO_SCALE:
		*val = 0;
		if (data->conf1 & ISL29125_MODE_RANGE)
			*val2 = ISL29125_SENSING_RANGE_1; /*10k lux full range*/

Annotation

Implementation Notes