drivers/iio/light/cm3605.c

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

File Facts

System
Linux kernel
Corpus path
drivers/iio/light/cm3605.c
Extension
.c
Size
8179 bytes
Lines
328
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 cm3605 {
	struct device *dev;
	struct regulator *vdd;
	struct gpio_desc *aset;
	struct iio_channel *aout;
	s32 als_max;
	enum iio_event_direction dir;
	struct led_trigger *led;
};

static irqreturn_t cm3605_prox_irq(int irq, void *d)
{
	struct iio_dev *indio_dev = d;
	struct cm3605 *cm3605 = iio_priv(indio_dev);
	u64 ev;

	ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, CM3605_PROX_CHANNEL,
				  IIO_EV_TYPE_THRESH, cm3605->dir);
	iio_push_event(indio_dev, ev, iio_get_time_ns(indio_dev));

	/* Invert the edge for each event */
	if (cm3605->dir == IIO_EV_DIR_RISING)
		cm3605->dir = IIO_EV_DIR_FALLING;
	else
		cm3605->dir = IIO_EV_DIR_RISING;

	return IRQ_HANDLED;
}

static int cm3605_get_lux(struct cm3605 *cm3605)
{
	int ret, res;
	s64 lux;

	ret = iio_read_channel_processed(cm3605->aout, &res);
	if (ret < 0)
		return ret;

	dev_dbg(cm3605->dev, "read %d mV from ADC\n", res);

	/*
	 * AOUT has an offset of ~30mV then linear at dark
	 * then goes from 2.54 up to 650 LUX yielding 1.55V
	 * (1550 mV) so scale the returned value to this interval
	 * using simple linear interpolation.
	 */
	if (res < 30)
		return 0;
	if (res > CM3605_AOUT_MAX_MV)
		dev_err(cm3605->dev, "device out of range\n");

	/* Remove bias */
	lux = res - 30;

	/* Linear interpolation between 0 and ALS typ max */
	lux *= cm3605->als_max;
	lux = div64_s64(lux, CM3605_AOUT_TYP_MAX_MV);

	return lux;
}

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

	switch (mask) {
	case IIO_CHAN_INFO_RAW:
		switch (chan->type) {
		case IIO_LIGHT:
			ret = cm3605_get_lux(cm3605);
			if (ret < 0)
				return ret;
			*val = ret;
			return IIO_VAL_INT;
		default:
			return -EINVAL;
		}
	default:
		return -EINVAL;
	}
}

static const struct iio_info cm3605_info = {
	.read_raw = cm3605_read_raw,
};

static const struct iio_event_spec cm3605_events[] = {

Annotation

Implementation Notes