Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * vcnl4000.c - Support for Vishay VCNL4000/4010/4020/4040/4200 combined ambient
   4 * light and proximity sensor
   5 *
   6 * Copyright 2012 Peter Meerwald <pmeerw@pmeerw.net>
   7 * Copyright 2019 Pursim SPC
   8 * Copyright 2020 Mathieu Othacehe <m.othacehe@gmail.com>
   9 *
  10 * IIO driver for:
  11 *   VCNL4000/10/20 (7-bit I2C slave address 0x13)
  12 *   VCNL4040 (7-bit I2C slave address 0x60)
  13 *   VCNL4200 (7-bit I2C slave address 0x51)
  14 *
  15 * TODO:
  16 *   allow to adjust IR current
  17 *   interrupts (VCNL4040, VCNL4200)
  18 */
  19
  20#include <linux/module.h>
  21#include <linux/i2c.h>
  22#include <linux/err.h>
  23#include <linux/delay.h>
  24#include <linux/pm_runtime.h>
  25#include <linux/interrupt.h>
  26
  27#include <linux/iio/buffer.h>
  28#include <linux/iio/events.h>
  29#include <linux/iio/iio.h>
  30#include <linux/iio/sysfs.h>
  31#include <linux/iio/trigger.h>
  32#include <linux/iio/trigger_consumer.h>
  33#include <linux/iio/triggered_buffer.h>
  34
  35#define VCNL4000_DRV_NAME "vcnl4000"
  36#define VCNL4000_PROD_ID	0x01
  37#define VCNL4010_PROD_ID	0x02 /* for VCNL4020, VCNL4010 */
  38#define VCNL4040_PROD_ID	0x86
  39#define VCNL4200_PROD_ID	0x58
  40
  41#define VCNL4000_COMMAND	0x80 /* Command register */
  42#define VCNL4000_PROD_REV	0x81 /* Product ID and Revision ID */
  43#define VCNL4010_PROX_RATE      0x82 /* Proximity rate */
  44#define VCNL4000_LED_CURRENT	0x83 /* IR LED current for proximity mode */
  45#define VCNL4000_AL_PARAM	0x84 /* Ambient light parameter register */
  46#define VCNL4010_ALS_PARAM      0x84 /* ALS rate */
  47#define VCNL4000_AL_RESULT_HI	0x85 /* Ambient light result register, MSB */
  48#define VCNL4000_AL_RESULT_LO	0x86 /* Ambient light result register, LSB */
  49#define VCNL4000_PS_RESULT_HI	0x87 /* Proximity result register, MSB */
  50#define VCNL4000_PS_RESULT_LO	0x88 /* Proximity result register, LSB */
  51#define VCNL4000_PS_MEAS_FREQ	0x89 /* Proximity test signal frequency */
  52#define VCNL4010_INT_CTRL	0x89 /* Interrupt control */
  53#define VCNL4000_PS_MOD_ADJ	0x8a /* Proximity modulator timing adjustment */
  54#define VCNL4010_LOW_THR_HI     0x8a /* Low threshold, MSB */
  55#define VCNL4010_LOW_THR_LO     0x8b /* Low threshold, LSB */
  56#define VCNL4010_HIGH_THR_HI    0x8c /* High threshold, MSB */
  57#define VCNL4010_HIGH_THR_LO    0x8d /* High threshold, LSB */
  58#define VCNL4010_ISR		0x8e /* Interrupt status */
  59
  60#define VCNL4200_AL_CONF	0x00 /* Ambient light configuration */
  61#define VCNL4200_PS_CONF1	0x03 /* Proximity configuration */
  62#define VCNL4200_PS_DATA	0x08 /* Proximity data */
  63#define VCNL4200_AL_DATA	0x09 /* Ambient light data */
  64#define VCNL4200_DEV_ID		0x0e /* Device ID, slave address and version */
  65
  66#define VCNL4040_DEV_ID		0x0c /* Device ID and version */
  67
  68/* Bit masks for COMMAND register */
  69#define VCNL4000_AL_RDY		BIT(6) /* ALS data ready? */
  70#define VCNL4000_PS_RDY		BIT(5) /* proximity data ready? */
  71#define VCNL4000_AL_OD		BIT(4) /* start on-demand ALS measurement */
  72#define VCNL4000_PS_OD		BIT(3) /* start on-demand proximity measurement */
  73#define VCNL4000_ALS_EN		BIT(2) /* start ALS measurement */
  74#define VCNL4000_PROX_EN	BIT(1) /* start proximity measurement */
  75#define VCNL4000_SELF_TIMED_EN	BIT(0) /* start self-timed measurement */
  76
  77/* Bit masks for interrupt registers. */
  78#define VCNL4010_INT_THR_SEL	BIT(0) /* Select threshold interrupt source */
  79#define VCNL4010_INT_THR_EN	BIT(1) /* Threshold interrupt type */
  80#define VCNL4010_INT_ALS_EN	BIT(2) /* Enable on ALS data ready */
  81#define VCNL4010_INT_PROX_EN	BIT(3) /* Enable on proximity data ready */
  82
  83#define VCNL4010_INT_THR_HIGH	0 /* High threshold exceeded */
  84#define VCNL4010_INT_THR_LOW	1 /* Low threshold exceeded */
  85#define VCNL4010_INT_ALS	2 /* ALS data ready */
  86#define VCNL4010_INT_PROXIMITY	3 /* Proximity data ready */
  87
  88#define VCNL4010_INT_THR \
  89	(BIT(VCNL4010_INT_THR_LOW) | BIT(VCNL4010_INT_THR_HIGH))
  90#define VCNL4010_INT_DRDY \
  91	(BIT(VCNL4010_INT_PROXIMITY) | BIT(VCNL4010_INT_ALS))
  92
  93static const int vcnl4010_prox_sampling_frequency[][2] = {
  94	{1, 950000},
  95	{3, 906250},
  96	{7, 812500},
  97	{16, 625000},
  98	{31, 250000},
  99	{62, 500000},
 100	{125, 0},
 101	{250, 0},
 102};
 103
 104#define VCNL4000_SLEEP_DELAY_MS	2000 /* before we enter pm_runtime_suspend */
 105
 106enum vcnl4000_device_ids {
 107	VCNL4000,
 108	VCNL4010,
 109	VCNL4040,
 110	VCNL4200,
 111};
 112
 113struct vcnl4200_channel {
 114	u8 reg;
 115	ktime_t last_measurement;
 116	ktime_t sampling_rate;
 117	struct mutex lock;
 118};
 119
 120struct vcnl4000_data {
 121	struct i2c_client *client;
 122	enum vcnl4000_device_ids id;
 123	int rev;
 124	int al_scale;
 125	const struct vcnl4000_chip_spec *chip_spec;
 126	struct mutex vcnl4000_lock;
 127	struct vcnl4200_channel vcnl4200_al;
 128	struct vcnl4200_channel vcnl4200_ps;
 129	uint32_t near_level;
 130};
 131
 132struct vcnl4000_chip_spec {
 133	const char *prod;
 134	struct iio_chan_spec const *channels;
 135	const int num_channels;
 136	const struct iio_info *info;
 137	bool irq_support;
 138	int (*init)(struct vcnl4000_data *data);
 139	int (*measure_light)(struct vcnl4000_data *data, int *val);
 140	int (*measure_proximity)(struct vcnl4000_data *data, int *val);
 141	int (*set_power_state)(struct vcnl4000_data *data, bool on);
 142};
 143
 144static const struct i2c_device_id vcnl4000_id[] = {
 145	{ "vcnl4000", VCNL4000 },
 146	{ "vcnl4010", VCNL4010 },
 147	{ "vcnl4020", VCNL4010 },
 148	{ "vcnl4040", VCNL4040 },
 149	{ "vcnl4200", VCNL4200 },
 150	{ }
 151};
 152MODULE_DEVICE_TABLE(i2c, vcnl4000_id);
 153
 154static int vcnl4000_set_power_state(struct vcnl4000_data *data, bool on)
 155{
 156	/* no suspend op */
 157	return 0;
 158}
 159
 160static int vcnl4000_init(struct vcnl4000_data *data)
 161{
 162	int ret, prod_id;
 163
 164	ret = i2c_smbus_read_byte_data(data->client, VCNL4000_PROD_REV);
 165	if (ret < 0)
 166		return ret;
 167
 168	prod_id = ret >> 4;
 169	switch (prod_id) {
 170	case VCNL4000_PROD_ID:
 171		if (data->id != VCNL4000)
 172			dev_warn(&data->client->dev,
 173					"wrong device id, use vcnl4000");
 174		break;
 175	case VCNL4010_PROD_ID:
 176		if (data->id != VCNL4010)
 177			dev_warn(&data->client->dev,
 178					"wrong device id, use vcnl4010/4020");
 179		break;
 180	default:
 181		return -ENODEV;
 182	}
 183
 184	data->rev = ret & 0xf;
 185	data->al_scale = 250000;
 186	mutex_init(&data->vcnl4000_lock);
 187
 188	return data->chip_spec->set_power_state(data, true);
 189};
 190
 191static int vcnl4200_set_power_state(struct vcnl4000_data *data, bool on)
 192{
 193	u16 val = on ? 0 /* power on */ : 1 /* shut down */;
 194	int ret;
 195
 196	ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF, val);
 197	if (ret < 0)
 198		return ret;
 199
 200	ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1, val);
 201	if (ret < 0)
 202		return ret;
 203
 204	if (on) {
 205		/* Wait at least one integration cycle before fetching data */
 206		data->vcnl4200_al.last_measurement = ktime_get();
 207		data->vcnl4200_ps.last_measurement = ktime_get();
 208	}
 209
 210	return 0;
 211}
 212
 213static int vcnl4200_init(struct vcnl4000_data *data)
 214{
 215	int ret, id;
 216
 217	ret = i2c_smbus_read_word_data(data->client, VCNL4200_DEV_ID);
 218	if (ret < 0)
 219		return ret;
 220
 221	id = ret & 0xff;
 222
 223	if (id != VCNL4200_PROD_ID) {
 224		ret = i2c_smbus_read_word_data(data->client, VCNL4040_DEV_ID);
 225		if (ret < 0)
 226			return ret;
 227
 228		id = ret & 0xff;
 229
 230		if (id != VCNL4040_PROD_ID)
 231			return -ENODEV;
 232	}
 233
 234	dev_dbg(&data->client->dev, "device id 0x%x", id);
 235
 236	data->rev = (ret >> 8) & 0xf;
 237
 238	data->vcnl4200_al.reg = VCNL4200_AL_DATA;
 239	data->vcnl4200_ps.reg = VCNL4200_PS_DATA;
 240	switch (id) {
 241	case VCNL4200_PROD_ID:
 242		/* Default wait time is 50ms, add 20% tolerance. */
 243		data->vcnl4200_al.sampling_rate = ktime_set(0, 60000 * 1000);
 244		/* Default wait time is 4.8ms, add 20% tolerance. */
 245		data->vcnl4200_ps.sampling_rate = ktime_set(0, 5760 * 1000);
 246		data->al_scale = 24000;
 247		break;
 248	case VCNL4040_PROD_ID:
 249		/* Default wait time is 80ms, add 20% tolerance. */
 250		data->vcnl4200_al.sampling_rate = ktime_set(0, 96000 * 1000);
 251		/* Default wait time is 5ms, add 20% tolerance. */
 252		data->vcnl4200_ps.sampling_rate = ktime_set(0, 6000 * 1000);
 253		data->al_scale = 120000;
 254		break;
 255	}
 256	mutex_init(&data->vcnl4200_al.lock);
 257	mutex_init(&data->vcnl4200_ps.lock);
 258
 259	ret = data->chip_spec->set_power_state(data, true);
 260	if (ret < 0)
 261		return ret;
 262
 263	return 0;
 264};
 265
 266static int vcnl4000_read_data(struct vcnl4000_data *data, u8 data_reg, int *val)
 267{
 268	s32 ret;
 269
 270	ret = i2c_smbus_read_word_swapped(data->client, data_reg);
 271	if (ret < 0)
 272		return ret;
 273
 274	*val = ret;
 275	return 0;
 276}
 277
 278static int vcnl4000_write_data(struct vcnl4000_data *data, u8 data_reg, int val)
 279{
 280	if (val > U16_MAX)
 281		return -ERANGE;
 282
 283	return i2c_smbus_write_word_swapped(data->client, data_reg, val);
 284}
 285
 286
 287static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask,
 288				u8 rdy_mask, u8 data_reg, int *val)
 289{
 290	int tries = 20;
 291	int ret;
 292
 293	mutex_lock(&data->vcnl4000_lock);
 294
 295	ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND,
 296					req_mask);
 297	if (ret < 0)
 298		goto fail;
 299
 300	/* wait for data to become ready */
 301	while (tries--) {
 302		ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND);
 303		if (ret < 0)
 304			goto fail;
 305		if (ret & rdy_mask)
 306			break;
 307		msleep(20); /* measurement takes up to 100 ms */
 308	}
 309
 310	if (tries < 0) {
 311		dev_err(&data->client->dev,
 312			"vcnl4000_measure() failed, data not ready\n");
 313		ret = -EIO;
 314		goto fail;
 315	}
 316
 317	ret = vcnl4000_read_data(data, data_reg, val);
 318	if (ret < 0)
 319		goto fail;
 320
 321	mutex_unlock(&data->vcnl4000_lock);
 322
 323	return 0;
 324
 325fail:
 326	mutex_unlock(&data->vcnl4000_lock);
 327	return ret;
 328}
 329
 330static int vcnl4200_measure(struct vcnl4000_data *data,
 331		struct vcnl4200_channel *chan, int *val)
 332{
 333	int ret;
 334	s64 delta;
 335	ktime_t next_measurement;
 336
 337	mutex_lock(&chan->lock);
 338
 339	next_measurement = ktime_add(chan->last_measurement,
 340			chan->sampling_rate);
 341	delta = ktime_us_delta(next_measurement, ktime_get());
 342	if (delta > 0)
 343		usleep_range(delta, delta + 500);
 344	chan->last_measurement = ktime_get();
 345
 346	mutex_unlock(&chan->lock);
 347
 348	ret = i2c_smbus_read_word_data(data->client, chan->reg);
 349	if (ret < 0)
 350		return ret;
 351
 352	*val = ret;
 353
 354	return 0;
 355}
 356
 357static int vcnl4000_measure_light(struct vcnl4000_data *data, int *val)
 358{
 359	return vcnl4000_measure(data,
 360			VCNL4000_AL_OD, VCNL4000_AL_RDY,
 361			VCNL4000_AL_RESULT_HI, val);
 362}
 363
 364static int vcnl4200_measure_light(struct vcnl4000_data *data, int *val)
 365{
 366	return vcnl4200_measure(data, &data->vcnl4200_al, val);
 367}
 368
 369static int vcnl4000_measure_proximity(struct vcnl4000_data *data, int *val)
 370{
 371	return vcnl4000_measure(data,
 372			VCNL4000_PS_OD, VCNL4000_PS_RDY,
 373			VCNL4000_PS_RESULT_HI, val);
 374}
 375
 376static int vcnl4200_measure_proximity(struct vcnl4000_data *data, int *val)
 377{
 378	return vcnl4200_measure(data, &data->vcnl4200_ps, val);
 379}
 380
 381static int vcnl4010_read_proxy_samp_freq(struct vcnl4000_data *data, int *val,
 382					 int *val2)
 383{
 384	int ret;
 385
 386	ret = i2c_smbus_read_byte_data(data->client, VCNL4010_PROX_RATE);
 387	if (ret < 0)
 388		return ret;
 389
 390	if (ret >= ARRAY_SIZE(vcnl4010_prox_sampling_frequency))
 391		return -EINVAL;
 392
 393	*val = vcnl4010_prox_sampling_frequency[ret][0];
 394	*val2 = vcnl4010_prox_sampling_frequency[ret][1];
 395
 396	return 0;
 397}
 398
 399static bool vcnl4010_is_in_periodic_mode(struct vcnl4000_data *data)
 400{
 401	int ret;
 402
 403	ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND);
 404	if (ret < 0)
 405		return false;
 406
 407	return !!(ret & VCNL4000_SELF_TIMED_EN);
 408}
 409
 410static int vcnl4000_set_pm_runtime_state(struct vcnl4000_data *data, bool on)
 411{
 412	struct device *dev = &data->client->dev;
 413	int ret;
 414
 415	if (on) {
 416		ret = pm_runtime_resume_and_get(dev);
 417	} else {
 418		pm_runtime_mark_last_busy(dev);
 419		ret = pm_runtime_put_autosuspend(dev);
 420	}
 421
 422	return ret;
 423}
 424
 425static int vcnl4000_read_raw(struct iio_dev *indio_dev,
 426				struct iio_chan_spec const *chan,
 427				int *val, int *val2, long mask)
 428{
 429	int ret;
 430	struct vcnl4000_data *data = iio_priv(indio_dev);
 431
 432	switch (mask) {
 433	case IIO_CHAN_INFO_RAW:
 434		ret = vcnl4000_set_pm_runtime_state(data, true);
 435		if  (ret < 0)
 436			return ret;
 437
 438		switch (chan->type) {
 439		case IIO_LIGHT:
 440			ret = data->chip_spec->measure_light(data, val);
 441			if (!ret)
 442				ret = IIO_VAL_INT;
 443			break;
 444		case IIO_PROXIMITY:
 445			ret = data->chip_spec->measure_proximity(data, val);
 446			if (!ret)
 447				ret = IIO_VAL_INT;
 448			break;
 449		default:
 450			ret = -EINVAL;
 451		}
 452		vcnl4000_set_pm_runtime_state(data, false);
 453		return ret;
 454	case IIO_CHAN_INFO_SCALE:
 455		if (chan->type != IIO_LIGHT)
 456			return -EINVAL;
 457
 458		*val = 0;
 459		*val2 = data->al_scale;
 460		return IIO_VAL_INT_PLUS_MICRO;
 461	default:
 462		return -EINVAL;
 463	}
 464}
 465
 466static int vcnl4010_read_raw(struct iio_dev *indio_dev,
 467			     struct iio_chan_spec const *chan,
 468			     int *val, int *val2, long mask)
 469{
 470	int ret;
 471	struct vcnl4000_data *data = iio_priv(indio_dev);
 472
 473	switch (mask) {
 474	case IIO_CHAN_INFO_RAW:
 475	case IIO_CHAN_INFO_SCALE:
 476		ret = iio_device_claim_direct_mode(indio_dev);
 477		if (ret)
 478			return ret;
 479
 480		/* Protect against event capture. */
 481		if (vcnl4010_is_in_periodic_mode(data)) {
 482			ret = -EBUSY;
 483		} else {
 484			ret = vcnl4000_read_raw(indio_dev, chan, val, val2,
 485						mask);
 486		}
 487
 488		iio_device_release_direct_mode(indio_dev);
 489		return ret;
 490	case IIO_CHAN_INFO_SAMP_FREQ:
 491		switch (chan->type) {
 492		case IIO_PROXIMITY:
 493			ret = vcnl4010_read_proxy_samp_freq(data, val, val2);
 494			if (ret < 0)
 495				return ret;
 496			return IIO_VAL_INT_PLUS_MICRO;
 497		default:
 498			return -EINVAL;
 499		}
 500	default:
 501		return -EINVAL;
 502	}
 503}
 504
 505static int vcnl4010_read_avail(struct iio_dev *indio_dev,
 506			       struct iio_chan_spec const *chan,
 507			       const int **vals, int *type, int *length,
 508			       long mask)
 509{
 510	switch (mask) {
 511	case IIO_CHAN_INFO_SAMP_FREQ:
 512		*vals = (int *)vcnl4010_prox_sampling_frequency;
 513		*type = IIO_VAL_INT_PLUS_MICRO;
 514		*length = 2 * ARRAY_SIZE(vcnl4010_prox_sampling_frequency);
 515		return IIO_AVAIL_LIST;
 516	default:
 517		return -EINVAL;
 518	}
 519}
 520
 521static int vcnl4010_write_proxy_samp_freq(struct vcnl4000_data *data, int val,
 522					  int val2)
 523{
 524	unsigned int i;
 525	int index = -1;
 526
 527	for (i = 0; i < ARRAY_SIZE(vcnl4010_prox_sampling_frequency); i++) {
 528		if (val == vcnl4010_prox_sampling_frequency[i][0] &&
 529		    val2 == vcnl4010_prox_sampling_frequency[i][1]) {
 530			index = i;
 531			break;
 532		}
 533	}
 534
 535	if (index < 0)
 536		return -EINVAL;
 537
 538	return i2c_smbus_write_byte_data(data->client, VCNL4010_PROX_RATE,
 539					 index);
 540}
 541
 542static int vcnl4010_write_raw(struct iio_dev *indio_dev,
 543			      struct iio_chan_spec const *chan,
 544			      int val, int val2, long mask)
 545{
 546	int ret;
 547	struct vcnl4000_data *data = iio_priv(indio_dev);
 548
 549	ret = iio_device_claim_direct_mode(indio_dev);
 550	if (ret)
 551		return ret;
 552
 553	/* Protect against event capture. */
 554	if (vcnl4010_is_in_periodic_mode(data)) {
 555		ret = -EBUSY;
 556		goto end;
 557	}
 558
 559	switch (mask) {
 560	case IIO_CHAN_INFO_SAMP_FREQ:
 561		switch (chan->type) {
 562		case IIO_PROXIMITY:
 563			ret = vcnl4010_write_proxy_samp_freq(data, val, val2);
 564			goto end;
 565		default:
 566			ret = -EINVAL;
 567			goto end;
 568		}
 569	default:
 570		ret = -EINVAL;
 571		goto end;
 572	}
 573
 574end:
 575	iio_device_release_direct_mode(indio_dev);
 576	return ret;
 577}
 578
 579static int vcnl4010_read_event(struct iio_dev *indio_dev,
 580			       const struct iio_chan_spec *chan,
 581			       enum iio_event_type type,
 582			       enum iio_event_direction dir,
 583			       enum iio_event_info info,
 584			       int *val, int *val2)
 585{
 586	int ret;
 587	struct vcnl4000_data *data = iio_priv(indio_dev);
 588
 589	switch (info) {
 590	case IIO_EV_INFO_VALUE:
 591		switch (dir) {
 592		case IIO_EV_DIR_RISING:
 593			ret = vcnl4000_read_data(data, VCNL4010_HIGH_THR_HI,
 594						 val);
 595			if (ret < 0)
 596				return ret;
 597			return IIO_VAL_INT;
 598		case IIO_EV_DIR_FALLING:
 599			ret = vcnl4000_read_data(data, VCNL4010_LOW_THR_HI,
 600						 val);
 601			if (ret < 0)
 602				return ret;
 603			return IIO_VAL_INT;
 604		default:
 605			return -EINVAL;
 606		}
 607	default:
 608		return -EINVAL;
 609	}
 610}
 611
 612static int vcnl4010_write_event(struct iio_dev *indio_dev,
 613				const struct iio_chan_spec *chan,
 614				enum iio_event_type type,
 615				enum iio_event_direction dir,
 616				enum iio_event_info info,
 617				int val, int val2)
 618{
 619	int ret;
 620	struct vcnl4000_data *data = iio_priv(indio_dev);
 621
 622	switch (info) {
 623	case IIO_EV_INFO_VALUE:
 624		switch (dir) {
 625		case IIO_EV_DIR_RISING:
 626			ret = vcnl4000_write_data(data, VCNL4010_HIGH_THR_HI,
 627						  val);
 628			if (ret < 0)
 629				return ret;
 630			return IIO_VAL_INT;
 631		case IIO_EV_DIR_FALLING:
 632			ret = vcnl4000_write_data(data, VCNL4010_LOW_THR_HI,
 633						  val);
 634			if (ret < 0)
 635				return ret;
 636			return IIO_VAL_INT;
 637		default:
 638			return -EINVAL;
 639		}
 640	default:
 641		return -EINVAL;
 642	}
 643}
 644
 645static bool vcnl4010_is_thr_enabled(struct vcnl4000_data *data)
 646{
 647	int ret;
 648
 649	ret = i2c_smbus_read_byte_data(data->client, VCNL4010_INT_CTRL);
 650	if (ret < 0)
 651		return false;
 652
 653	return !!(ret & VCNL4010_INT_THR_EN);
 654}
 655
 656static int vcnl4010_read_event_config(struct iio_dev *indio_dev,
 657				      const struct iio_chan_spec *chan,
 658				      enum iio_event_type type,
 659				      enum iio_event_direction dir)
 660{
 661	struct vcnl4000_data *data = iio_priv(indio_dev);
 662
 663	switch (chan->type) {
 664	case IIO_PROXIMITY:
 665		return vcnl4010_is_thr_enabled(data);
 666	default:
 667		return -EINVAL;
 668	}
 669}
 670
 671static int vcnl4010_config_threshold(struct iio_dev *indio_dev, bool state)
 672{
 673	struct vcnl4000_data *data = iio_priv(indio_dev);
 674	int ret;
 675	int icr;
 676	int command;
 677
 678	if (state) {
 679		ret = iio_device_claim_direct_mode(indio_dev);
 680		if (ret)
 681			return ret;
 682
 683		/* Enable periodic measurement of proximity data. */
 684		command = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN;
 685
 686		/*
 687		 * Enable interrupts on threshold, for proximity data by
 688		 * default.
 689		 */
 690		icr = VCNL4010_INT_THR_EN;
 691	} else {
 692		if (!vcnl4010_is_thr_enabled(data))
 693			return 0;
 694
 695		command = 0;
 696		icr = 0;
 697	}
 698
 699	ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND,
 700					command);
 701	if (ret < 0)
 702		goto end;
 703
 704	ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, icr);
 705
 706end:
 707	if (state)
 708		iio_device_release_direct_mode(indio_dev);
 709
 710	return ret;
 711}
 712
 713static int vcnl4010_write_event_config(struct iio_dev *indio_dev,
 714				       const struct iio_chan_spec *chan,
 715				       enum iio_event_type type,
 716				       enum iio_event_direction dir,
 717				       int state)
 718{
 719	switch (chan->type) {
 720	case IIO_PROXIMITY:
 721		return vcnl4010_config_threshold(indio_dev, state);
 722	default:
 723		return -EINVAL;
 724	}
 725}
 726
 727static ssize_t vcnl4000_read_near_level(struct iio_dev *indio_dev,
 728					uintptr_t priv,
 729					const struct iio_chan_spec *chan,
 730					char *buf)
 731{
 732	struct vcnl4000_data *data = iio_priv(indio_dev);
 733
 734	return sprintf(buf, "%u\n", data->near_level);
 735}
 736
 737static const struct iio_chan_spec_ext_info vcnl4000_ext_info[] = {
 738	{
 739		.name = "nearlevel",
 740		.shared = IIO_SEPARATE,
 741		.read = vcnl4000_read_near_level,
 742	},
 743	{ /* sentinel */ }
 744};
 745
 746static const struct iio_event_spec vcnl4000_event_spec[] = {
 747	{
 748		.type = IIO_EV_TYPE_THRESH,
 749		.dir = IIO_EV_DIR_RISING,
 750		.mask_separate = BIT(IIO_EV_INFO_VALUE),
 751	}, {
 752		.type = IIO_EV_TYPE_THRESH,
 753		.dir = IIO_EV_DIR_FALLING,
 754		.mask_separate = BIT(IIO_EV_INFO_VALUE),
 755	}, {
 756		.type = IIO_EV_TYPE_THRESH,
 757		.dir = IIO_EV_DIR_EITHER,
 758		.mask_separate = BIT(IIO_EV_INFO_ENABLE),
 759	}
 760};
 761
 762static const struct iio_chan_spec vcnl4000_channels[] = {
 763	{
 764		.type = IIO_LIGHT,
 765		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 766			BIT(IIO_CHAN_INFO_SCALE),
 767	}, {
 768		.type = IIO_PROXIMITY,
 769		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 770		.ext_info = vcnl4000_ext_info,
 771	}
 772};
 773
 774static const struct iio_chan_spec vcnl4010_channels[] = {
 775	{
 776		.type = IIO_LIGHT,
 777		.scan_index = -1,
 778		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 779			BIT(IIO_CHAN_INFO_SCALE),
 780	}, {
 781		.type = IIO_PROXIMITY,
 782		.scan_index = 0,
 783		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 784			BIT(IIO_CHAN_INFO_SAMP_FREQ),
 785		.info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ),
 786		.event_spec = vcnl4000_event_spec,
 787		.num_event_specs = ARRAY_SIZE(vcnl4000_event_spec),
 788		.ext_info = vcnl4000_ext_info,
 789		.scan_type = {
 790			.sign = 'u',
 791			.realbits = 16,
 792			.storagebits = 16,
 793			.endianness = IIO_CPU,
 794		},
 795	},
 796	IIO_CHAN_SOFT_TIMESTAMP(1),
 797};
 798
 799static const struct iio_info vcnl4000_info = {
 800	.read_raw = vcnl4000_read_raw,
 801};
 802
 803static const struct iio_info vcnl4010_info = {
 804	.read_raw = vcnl4010_read_raw,
 805	.read_avail = vcnl4010_read_avail,
 806	.write_raw = vcnl4010_write_raw,
 807	.read_event_value = vcnl4010_read_event,
 808	.write_event_value = vcnl4010_write_event,
 809	.read_event_config = vcnl4010_read_event_config,
 810	.write_event_config = vcnl4010_write_event_config,
 811};
 812
 813static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = {
 814	[VCNL4000] = {
 815		.prod = "VCNL4000",
 816		.init = vcnl4000_init,
 817		.measure_light = vcnl4000_measure_light,
 818		.measure_proximity = vcnl4000_measure_proximity,
 819		.set_power_state = vcnl4000_set_power_state,
 820		.channels = vcnl4000_channels,
 821		.num_channels = ARRAY_SIZE(vcnl4000_channels),
 822		.info = &vcnl4000_info,
 823		.irq_support = false,
 824	},
 825	[VCNL4010] = {
 826		.prod = "VCNL4010/4020",
 827		.init = vcnl4000_init,
 828		.measure_light = vcnl4000_measure_light,
 829		.measure_proximity = vcnl4000_measure_proximity,
 830		.set_power_state = vcnl4000_set_power_state,
 831		.channels = vcnl4010_channels,
 832		.num_channels = ARRAY_SIZE(vcnl4010_channels),
 833		.info = &vcnl4010_info,
 834		.irq_support = true,
 835	},
 836	[VCNL4040] = {
 837		.prod = "VCNL4040",
 838		.init = vcnl4200_init,
 839		.measure_light = vcnl4200_measure_light,
 840		.measure_proximity = vcnl4200_measure_proximity,
 841		.set_power_state = vcnl4200_set_power_state,
 842		.channels = vcnl4000_channels,
 843		.num_channels = ARRAY_SIZE(vcnl4000_channels),
 844		.info = &vcnl4000_info,
 845		.irq_support = false,
 846	},
 847	[VCNL4200] = {
 848		.prod = "VCNL4200",
 849		.init = vcnl4200_init,
 850		.measure_light = vcnl4200_measure_light,
 851		.measure_proximity = vcnl4200_measure_proximity,
 852		.set_power_state = vcnl4200_set_power_state,
 853		.channels = vcnl4000_channels,
 854		.num_channels = ARRAY_SIZE(vcnl4000_channels),
 855		.info = &vcnl4000_info,
 856		.irq_support = false,
 857	},
 858};
 859
 860static irqreturn_t vcnl4010_irq_thread(int irq, void *p)
 861{
 862	struct iio_dev *indio_dev = p;
 863	struct vcnl4000_data *data = iio_priv(indio_dev);
 864	unsigned long isr;
 865	int ret;
 866
 867	ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR);
 868	if (ret < 0)
 869		goto end;
 870
 871	isr = ret;
 872
 873	if (isr & VCNL4010_INT_THR) {
 874		if (test_bit(VCNL4010_INT_THR_LOW, &isr)) {
 875			iio_push_event(indio_dev,
 876				       IIO_UNMOD_EVENT_CODE(
 877					       IIO_PROXIMITY,
 878					       1,
 879					       IIO_EV_TYPE_THRESH,
 880					       IIO_EV_DIR_FALLING),
 881				       iio_get_time_ns(indio_dev));
 882		}
 883
 884		if (test_bit(VCNL4010_INT_THR_HIGH, &isr)) {
 885			iio_push_event(indio_dev,
 886				       IIO_UNMOD_EVENT_CODE(
 887					       IIO_PROXIMITY,
 888					       1,
 889					       IIO_EV_TYPE_THRESH,
 890					       IIO_EV_DIR_RISING),
 891				       iio_get_time_ns(indio_dev));
 892		}
 893
 894		i2c_smbus_write_byte_data(data->client, VCNL4010_ISR,
 895					  isr & VCNL4010_INT_THR);
 896	}
 897
 898	if (isr & VCNL4010_INT_DRDY && iio_buffer_enabled(indio_dev))
 899		iio_trigger_poll_chained(indio_dev->trig);
 900
 901end:
 902	return IRQ_HANDLED;
 903}
 904
 905static irqreturn_t vcnl4010_trigger_handler(int irq, void *p)
 906{
 907	struct iio_poll_func *pf = p;
 908	struct iio_dev *indio_dev = pf->indio_dev;
 909	struct vcnl4000_data *data = iio_priv(indio_dev);
 910	const unsigned long *active_scan_mask = indio_dev->active_scan_mask;
 911	u16 buffer[8] __aligned(8) = {0}; /* 1x16-bit + naturally aligned ts */
 912	bool data_read = false;
 913	unsigned long isr;
 914	int val = 0;
 915	int ret;
 916
 917	ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR);
 918	if (ret < 0)
 919		goto end;
 920
 921	isr = ret;
 922
 923	if (test_bit(0, active_scan_mask)) {
 924		if (test_bit(VCNL4010_INT_PROXIMITY, &isr)) {
 925			ret = vcnl4000_read_data(data,
 926						 VCNL4000_PS_RESULT_HI,
 927						 &val);
 928			if (ret < 0)
 929				goto end;
 930
 931			buffer[0] = val;
 932			data_read = true;
 933		}
 934	}
 935
 936	ret = i2c_smbus_write_byte_data(data->client, VCNL4010_ISR,
 937					isr & VCNL4010_INT_DRDY);
 938	if (ret < 0)
 939		goto end;
 940
 941	if (!data_read)
 942		goto end;
 943
 944	iio_push_to_buffers_with_timestamp(indio_dev, buffer,
 945					   iio_get_time_ns(indio_dev));
 946
 947end:
 948	iio_trigger_notify_done(indio_dev->trig);
 949	return IRQ_HANDLED;
 950}
 951
 952static int vcnl4010_buffer_postenable(struct iio_dev *indio_dev)
 953{
 954	struct vcnl4000_data *data = iio_priv(indio_dev);
 955	int ret;
 956	int cmd;
 957
 958	/* Do not enable the buffer if we are already capturing events. */
 959	if (vcnl4010_is_in_periodic_mode(data))
 960		return -EBUSY;
 961
 962	ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL,
 963					VCNL4010_INT_PROX_EN);
 964	if (ret < 0)
 965		return ret;
 966
 967	cmd = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN;
 968	return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, cmd);
 969}
 970
 971static int vcnl4010_buffer_predisable(struct iio_dev *indio_dev)
 972{
 973	struct vcnl4000_data *data = iio_priv(indio_dev);
 974	int ret;
 975
 976	ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, 0);
 977	if (ret < 0)
 978		return ret;
 979
 980	return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 0);
 981}
 982
 983static const struct iio_buffer_setup_ops vcnl4010_buffer_ops = {
 984	.postenable = &vcnl4010_buffer_postenable,
 985	.predisable = &vcnl4010_buffer_predisable,
 986};
 987
 988static const struct iio_trigger_ops vcnl4010_trigger_ops = {
 989	.validate_device = iio_trigger_validate_own_device,
 990};
 991
 992static int vcnl4010_probe_trigger(struct iio_dev *indio_dev)
 993{
 994	struct vcnl4000_data *data = iio_priv(indio_dev);
 995	struct i2c_client *client = data->client;
 996	struct iio_trigger *trigger;
 997
 998	trigger = devm_iio_trigger_alloc(&client->dev, "%s-dev%d",
 999					 indio_dev->name,
1000					 iio_device_id(indio_dev));
1001	if (!trigger)
1002		return -ENOMEM;
1003
1004	trigger->ops = &vcnl4010_trigger_ops;
1005	iio_trigger_set_drvdata(trigger, indio_dev);
1006
1007	return devm_iio_trigger_register(&client->dev, trigger);
1008}
1009
1010static int vcnl4000_probe(struct i2c_client *client,
1011			  const struct i2c_device_id *id)
1012{
1013	struct vcnl4000_data *data;
1014	struct iio_dev *indio_dev;
1015	int ret;
1016
1017	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
1018	if (!indio_dev)
1019		return -ENOMEM;
1020
1021	data = iio_priv(indio_dev);
1022	i2c_set_clientdata(client, indio_dev);
1023	data->client = client;
1024	data->id = id->driver_data;
1025	data->chip_spec = &vcnl4000_chip_spec_cfg[data->id];
1026
1027	ret = data->chip_spec->init(data);
1028	if (ret < 0)
1029		return ret;
1030
1031	dev_dbg(&client->dev, "%s Ambient light/proximity sensor, Rev: %02x\n",
1032		data->chip_spec->prod, data->rev);
1033
1034	if (device_property_read_u32(&client->dev, "proximity-near-level",
1035				     &data->near_level))
1036		data->near_level = 0;
1037
1038	indio_dev->info = data->chip_spec->info;
1039	indio_dev->channels = data->chip_spec->channels;
1040	indio_dev->num_channels = data->chip_spec->num_channels;
1041	indio_dev->name = VCNL4000_DRV_NAME;
1042	indio_dev->modes = INDIO_DIRECT_MODE;
1043
1044	if (client->irq && data->chip_spec->irq_support) {
1045		ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,
1046						      NULL,
1047						      vcnl4010_trigger_handler,
1048						      &vcnl4010_buffer_ops);
1049		if (ret < 0) {
1050			dev_err(&client->dev,
1051				"unable to setup iio triggered buffer\n");
1052			return ret;
1053		}
1054
1055		ret = devm_request_threaded_irq(&client->dev, client->irq,
1056						NULL, vcnl4010_irq_thread,
1057						IRQF_TRIGGER_FALLING |
1058						IRQF_ONESHOT,
1059						"vcnl4010_irq",
1060						indio_dev);
1061		if (ret < 0) {
1062			dev_err(&client->dev, "irq request failed\n");
1063			return ret;
1064		}
1065
1066		ret = vcnl4010_probe_trigger(indio_dev);
1067		if (ret < 0)
1068			return ret;
1069	}
1070
1071	ret = pm_runtime_set_active(&client->dev);
1072	if (ret < 0)
1073		goto fail_poweroff;
1074
1075	ret = iio_device_register(indio_dev);
1076	if (ret < 0)
1077		goto fail_poweroff;
1078
1079	pm_runtime_enable(&client->dev);
1080	pm_runtime_set_autosuspend_delay(&client->dev, VCNL4000_SLEEP_DELAY_MS);
1081	pm_runtime_use_autosuspend(&client->dev);
1082
1083	return 0;
1084fail_poweroff:
1085	data->chip_spec->set_power_state(data, false);
1086	return ret;
1087}
1088
1089static const struct of_device_id vcnl_4000_of_match[] = {
1090	{
1091		.compatible = "vishay,vcnl4000",
1092		.data = (void *)VCNL4000,
1093	},
1094	{
1095		.compatible = "vishay,vcnl4010",
1096		.data = (void *)VCNL4010,
1097	},
1098	{
1099		.compatible = "vishay,vcnl4020",
1100		.data = (void *)VCNL4010,
1101	},
1102	{
1103		.compatible = "vishay,vcnl4040",
1104		.data = (void *)VCNL4040,
1105	},
1106	{
1107		.compatible = "vishay,vcnl4200",
1108		.data = (void *)VCNL4200,
1109	},
1110	{},
1111};
1112MODULE_DEVICE_TABLE(of, vcnl_4000_of_match);
1113
1114static int vcnl4000_remove(struct i2c_client *client)
1115{
1116	struct iio_dev *indio_dev = i2c_get_clientdata(client);
1117	struct vcnl4000_data *data = iio_priv(indio_dev);
1118
1119	pm_runtime_dont_use_autosuspend(&client->dev);
1120	pm_runtime_disable(&client->dev);
1121	iio_device_unregister(indio_dev);
1122	pm_runtime_set_suspended(&client->dev);
1123
1124	return data->chip_spec->set_power_state(data, false);
1125}
1126
1127static int __maybe_unused vcnl4000_runtime_suspend(struct device *dev)
1128{
1129	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
1130	struct vcnl4000_data *data = iio_priv(indio_dev);
1131
1132	return data->chip_spec->set_power_state(data, false);
1133}
1134
1135static int __maybe_unused vcnl4000_runtime_resume(struct device *dev)
1136{
1137	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
1138	struct vcnl4000_data *data = iio_priv(indio_dev);
1139
1140	return data->chip_spec->set_power_state(data, true);
1141}
1142
1143static const struct dev_pm_ops vcnl4000_pm_ops = {
1144	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1145				pm_runtime_force_resume)
1146	SET_RUNTIME_PM_OPS(vcnl4000_runtime_suspend,
1147			   vcnl4000_runtime_resume, NULL)
1148};
1149
1150static struct i2c_driver vcnl4000_driver = {
1151	.driver = {
1152		.name   = VCNL4000_DRV_NAME,
1153		.pm	= &vcnl4000_pm_ops,
1154		.of_match_table = vcnl_4000_of_match,
1155	},
1156	.probe  = vcnl4000_probe,
1157	.id_table = vcnl4000_id,
1158	.remove	= vcnl4000_remove,
1159};
1160
1161module_i2c_driver(vcnl4000_driver);
1162
1163MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
1164MODULE_AUTHOR("Mathieu Othacehe <m.othacehe@gmail.com>");
1165MODULE_DESCRIPTION("Vishay VCNL4000 proximity/ambient light sensor driver");
1166MODULE_LICENSE("GPL");