brintos

brintos / linux-shallow public Read only

0
0
Text · 51.9 KiB · 4e3641f Raw
2123 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * vcnl4000.c - Support for Vishay VCNL4000/4010/4020/4040/4200 combined ambient4 * light and proximity sensor5 *6 * Copyright 2012 Peter Meerwald <pmeerw@pmeerw.net>7 * Copyright 2019 Pursim SPC8 * 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 current17 *   interrupts (VCNL4040, VCNL4200)18 */19 20#include <linux/bitfield.h>21#include <linux/module.h>22#include <linux/i2c.h>23#include <linux/err.h>24#include <linux/delay.h>25#include <linux/pm_runtime.h>26#include <linux/interrupt.h>27#include <linux/units.h>28 29#include <linux/iio/buffer.h>30#include <linux/iio/events.h>31#include <linux/iio/iio.h>32#include <linux/iio/sysfs.h>33#include <linux/iio/trigger.h>34#include <linux/iio/trigger_consumer.h>35#include <linux/iio/triggered_buffer.h>36 37#define VCNL4000_DRV_NAME "vcnl4000"38#define VCNL4000_PROD_ID	0x0139#define VCNL4010_PROD_ID	0x02 /* for VCNL4020, VCNL4010 */40#define VCNL4040_PROD_ID	0x8641#define VCNL4200_PROD_ID	0x5842 43#define VCNL4000_COMMAND	0x80 /* Command register */44#define VCNL4000_PROD_REV	0x81 /* Product ID and Revision ID */45#define VCNL4010_PROX_RATE      0x82 /* Proximity rate */46#define VCNL4000_LED_CURRENT	0x83 /* IR LED current for proximity mode */47#define VCNL4000_AL_PARAM	0x84 /* Ambient light parameter register */48#define VCNL4010_ALS_PARAM      0x84 /* ALS rate */49#define VCNL4000_AL_RESULT_HI	0x85 /* Ambient light result register, MSB */50#define VCNL4000_AL_RESULT_LO	0x86 /* Ambient light result register, LSB */51#define VCNL4000_PS_RESULT_HI	0x87 /* Proximity result register, MSB */52#define VCNL4000_PS_RESULT_LO	0x88 /* Proximity result register, LSB */53#define VCNL4000_PS_MEAS_FREQ	0x89 /* Proximity test signal frequency */54#define VCNL4010_INT_CTRL	0x89 /* Interrupt control */55#define VCNL4000_PS_MOD_ADJ	0x8a /* Proximity modulator timing adjustment */56#define VCNL4010_LOW_THR_HI     0x8a /* Low threshold, MSB */57#define VCNL4010_LOW_THR_LO     0x8b /* Low threshold, LSB */58#define VCNL4010_HIGH_THR_HI    0x8c /* High threshold, MSB */59#define VCNL4010_HIGH_THR_LO    0x8d /* High threshold, LSB */60#define VCNL4010_ISR		0x8e /* Interrupt status */61 62#define VCNL4200_AL_CONF	0x00 /* Ambient light configuration */63#define VCNL4200_PS_CONF1	0x03 /* Proximity configuration */64#define VCNL4200_PS_CONF3	0x04 /* Proximity configuration */65#define VCNL4040_PS_THDL_LM	0x06 /* Proximity threshold low */66#define VCNL4040_PS_THDH_LM	0x07 /* Proximity threshold high */67#define VCNL4040_ALS_THDL_LM	0x02 /* Ambient light threshold low */68#define VCNL4040_ALS_THDH_LM	0x01 /* Ambient light threshold high */69#define VCNL4200_PS_DATA	0x08 /* Proximity data */70#define VCNL4200_AL_DATA	0x09 /* Ambient light data */71#define VCNL4040_INT_FLAGS	0x0b /* Interrupt register */72#define VCNL4200_INT_FLAGS	0x0d /* Interrupt register */73#define VCNL4200_DEV_ID		0x0e /* Device ID, slave address and version */74 75#define VCNL4040_DEV_ID		0x0c /* Device ID and version */76 77/* Bit masks for COMMAND register */78#define VCNL4000_AL_RDY		BIT(6) /* ALS data ready? */79#define VCNL4000_PS_RDY		BIT(5) /* proximity data ready? */80#define VCNL4000_AL_OD		BIT(4) /* start on-demand ALS measurement */81#define VCNL4000_PS_OD		BIT(3) /* start on-demand proximity measurement */82#define VCNL4000_ALS_EN		BIT(2) /* start ALS measurement */83#define VCNL4000_PROX_EN	BIT(1) /* start proximity measurement */84#define VCNL4000_SELF_TIMED_EN	BIT(0) /* start self-timed measurement */85 86#define VCNL4040_ALS_CONF_ALS_SHUTDOWN	BIT(0)87#define VCNL4040_ALS_CONF_IT		GENMASK(7, 6) /* Ambient integration time */88#define VCNL4040_ALS_CONF_INT_EN	BIT(1) /* Ambient light Interrupt enable */89#define VCNL4040_ALS_CONF_PERS	GENMASK(3, 2) /* Ambient interrupt persistence setting */90#define VCNL4040_PS_CONF1_PS_SHUTDOWN	BIT(0)91#define VCNL4040_PS_CONF2_PS_IT	GENMASK(3, 1) /* Proximity integration time */92#define VCNL4040_CONF1_PS_PERS	GENMASK(5, 4) /* Proximity interrupt persistence setting */93#define VCNL4040_PS_CONF2_PS_HD		BIT(11)	/* Proximity high definition */94#define VCNL4040_PS_CONF2_PS_INT	GENMASK(9, 8) /* Proximity interrupt mode */95#define VCNL4040_PS_CONF3_MPS		GENMASK(6, 5) /* Proximity multi pulse number */96#define VCNL4040_PS_MS_LED_I		GENMASK(10, 8) /* Proximity current */97#define VCNL4040_PS_IF_AWAY		BIT(8) /* Proximity event cross low threshold */98#define VCNL4040_PS_IF_CLOSE		BIT(9) /* Proximity event cross high threshold */99#define VCNL4040_ALS_RISING		BIT(12) /* Ambient Light cross high threshold */100#define VCNL4040_ALS_FALLING		BIT(13) /* Ambient Light cross low threshold */101 102/* Bit masks for interrupt registers. */103#define VCNL4010_INT_THR_SEL	BIT(0) /* Select threshold interrupt source */104#define VCNL4010_INT_THR_EN	BIT(1) /* Threshold interrupt type */105#define VCNL4010_INT_ALS_EN	BIT(2) /* Enable on ALS data ready */106#define VCNL4010_INT_PROX_EN	BIT(3) /* Enable on proximity data ready */107 108#define VCNL4010_INT_THR_HIGH	0 /* High threshold exceeded */109#define VCNL4010_INT_THR_LOW	1 /* Low threshold exceeded */110#define VCNL4010_INT_ALS	2 /* ALS data ready */111#define VCNL4010_INT_PROXIMITY	3 /* Proximity data ready */112 113#define VCNL4010_INT_THR \114	(BIT(VCNL4010_INT_THR_LOW) | BIT(VCNL4010_INT_THR_HIGH))115#define VCNL4010_INT_DRDY \116	(BIT(VCNL4010_INT_PROXIMITY) | BIT(VCNL4010_INT_ALS))117 118#define VCNL4040_CONF3_PS_MPS_16BITS	3	/* 8 multi pulses */119#define VCNL4040_CONF3_PS_LED_I_16BITS	3	/* 120 mA */120 121#define VCNL4040_CONF3_PS_SAMPLE_16BITS \122	(FIELD_PREP(VCNL4040_PS_CONF3_MPS, VCNL4040_CONF3_PS_MPS_16BITS) | \123	 FIELD_PREP(VCNL4040_PS_MS_LED_I, VCNL4040_CONF3_PS_LED_I_16BITS))124 125static const int vcnl4010_prox_sampling_frequency[][2] = {126	{1, 950000},127	{3, 906250},128	{7, 812500},129	{16, 625000},130	{31, 250000},131	{62, 500000},132	{125, 0},133	{250, 0},134};135 136static const int vcnl4040_ps_it_times[][2] = {137	{0, 100},138	{0, 150},139	{0, 200},140	{0, 250},141	{0, 300},142	{0, 350},143	{0, 400},144	{0, 800},145};146 147static const int vcnl4200_ps_it_times[][2] = {148	{0, 96},149	{0, 144},150	{0, 192},151	{0, 384},152	{0, 768},153	{0, 864},154};155 156static const int vcnl4040_als_it_times[][2] = {157	{0, 80000},158	{0, 160000},159	{0, 320000},160	{0, 640000},161};162 163static const int vcnl4200_als_it_times[][2] = {164	{0, 50000},165	{0, 100000},166	{0, 200000},167	{0, 400000},168};169 170static const int vcnl4040_ps_calibbias_ua[][2] = {171	{0, 50000},172	{0, 75000},173	{0, 100000},174	{0, 120000},175	{0, 140000},176	{0, 160000},177	{0, 180000},178	{0, 200000},179};180 181static const int vcnl4040_als_persistence[] = {1, 2, 4, 8};182static const int vcnl4040_ps_persistence[] = {1, 2, 3, 4};183static const int vcnl4040_ps_oversampling_ratio[] = {1, 2, 4, 8};184 185#define VCNL4000_SLEEP_DELAY_MS	2000 /* before we enter pm_runtime_suspend */186 187enum vcnl4000_device_ids {188	VCNL4000,189	VCNL4010,190	VCNL4040,191	VCNL4200,192};193 194struct vcnl4200_channel {195	u8 reg;196	ktime_t last_measurement;197	ktime_t sampling_rate;198	struct mutex lock;199};200 201struct vcnl4000_data {202	struct i2c_client *client;203	enum vcnl4000_device_ids id;204	int rev;205	int al_scale;206	int ps_scale;207	u8 ps_int;		/* proximity interrupt mode */208	u8 als_int;		/* ambient light interrupt mode*/209	const struct vcnl4000_chip_spec *chip_spec;210	struct mutex vcnl4000_lock;211	struct vcnl4200_channel vcnl4200_al;212	struct vcnl4200_channel vcnl4200_ps;213	uint32_t near_level;214};215 216struct vcnl4000_chip_spec {217	const char *prod;218	struct iio_chan_spec const *channels;219	const int num_channels;220	const struct iio_info *info;221	const struct iio_buffer_setup_ops *buffer_setup_ops;222	int (*init)(struct vcnl4000_data *data);223	int (*measure_light)(struct vcnl4000_data *data, int *val);224	int (*measure_proximity)(struct vcnl4000_data *data, int *val);225	int (*set_power_state)(struct vcnl4000_data *data, bool on);226	irqreturn_t (*irq_thread)(int irq, void *priv);227	irqreturn_t (*trig_buffer_func)(int irq, void *priv);228 229	u8 int_reg;230	const int(*ps_it_times)[][2];231	const int num_ps_it_times;232	const int(*als_it_times)[][2];233	const int num_als_it_times;234	const unsigned int ulux_step;235};236 237static const struct i2c_device_id vcnl4000_id[] = {238	{ "vcnl4000", VCNL4000 },239	{ "vcnl4010", VCNL4010 },240	{ "vcnl4020", VCNL4010 },241	{ "vcnl4040", VCNL4040 },242	{ "vcnl4200", VCNL4200 },243	{ }244};245MODULE_DEVICE_TABLE(i2c, vcnl4000_id);246 247static int vcnl4000_set_power_state(struct vcnl4000_data *data, bool on)248{249	/* no suspend op */250	return 0;251}252 253static int vcnl4000_init(struct vcnl4000_data *data)254{255	int ret, prod_id;256 257	ret = i2c_smbus_read_byte_data(data->client, VCNL4000_PROD_REV);258	if (ret < 0)259		return ret;260 261	prod_id = ret >> 4;262	switch (prod_id) {263	case VCNL4000_PROD_ID:264		if (data->id != VCNL4000)265			dev_warn(&data->client->dev,266					"wrong device id, use vcnl4000");267		break;268	case VCNL4010_PROD_ID:269		if (data->id != VCNL4010)270			dev_warn(&data->client->dev,271					"wrong device id, use vcnl4010/4020");272		break;273	default:274		return -ENODEV;275	}276 277	data->rev = ret & 0xf;278	data->al_scale = 250000;279 280	return data->chip_spec->set_power_state(data, true);281};282 283static ssize_t vcnl4000_write_als_enable(struct vcnl4000_data *data, bool en)284{285	int ret;286 287	mutex_lock(&data->vcnl4000_lock);288 289	ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);290	if (ret < 0)291		goto out;292 293	if (en)294		ret &= ~VCNL4040_ALS_CONF_ALS_SHUTDOWN;295	else296		ret |= VCNL4040_ALS_CONF_ALS_SHUTDOWN;297 298	ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF, ret);299 300out:301	mutex_unlock(&data->vcnl4000_lock);302 303	return ret;304}305 306static ssize_t vcnl4000_write_ps_enable(struct vcnl4000_data *data, bool en)307{308	int ret;309 310	mutex_lock(&data->vcnl4000_lock);311 312	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);313	if (ret < 0)314		goto out;315 316	if (en)317		ret &= ~VCNL4040_PS_CONF1_PS_SHUTDOWN;318	else319		ret |= VCNL4040_PS_CONF1_PS_SHUTDOWN;320 321	ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1, ret);322 323out:324	mutex_unlock(&data->vcnl4000_lock);325 326	return ret;327}328 329static int vcnl4200_set_power_state(struct vcnl4000_data *data, bool on)330{331	int ret;332 333	/* Do not power down if interrupts are enabled */334	if (!on && (data->ps_int || data->als_int))335		return 0;336 337	ret = vcnl4000_write_als_enable(data, on);338	if (ret < 0)339		return ret;340 341	ret = vcnl4000_write_ps_enable(data, on);342	if (ret < 0)343		return ret;344 345	if (on) {346		/* Wait at least one integration cycle before fetching data */347		data->vcnl4200_al.last_measurement = ktime_get();348		data->vcnl4200_ps.last_measurement = ktime_get();349	}350 351	return 0;352}353 354static int vcnl4200_init(struct vcnl4000_data *data)355{356	int ret, id;357	u16 regval;358 359	ret = i2c_smbus_read_word_data(data->client, VCNL4200_DEV_ID);360	if (ret < 0)361		return ret;362 363	id = ret & 0xff;364 365	if (id != VCNL4200_PROD_ID) {366		ret = i2c_smbus_read_word_data(data->client, VCNL4040_DEV_ID);367		if (ret < 0)368			return ret;369 370		id = ret & 0xff;371 372		if (id != VCNL4040_PROD_ID)373			return -ENODEV;374	}375 376	dev_dbg(&data->client->dev, "device id 0x%x", id);377 378	data->rev = (ret >> 8) & 0xf;379	data->ps_int = 0;380	data->als_int = 0;381 382	data->vcnl4200_al.reg = VCNL4200_AL_DATA;383	data->vcnl4200_ps.reg = VCNL4200_PS_DATA;384	switch (id) {385	case VCNL4200_PROD_ID:386		/* Default wait time is 50ms, add 20% tolerance. */387		data->vcnl4200_al.sampling_rate = ktime_set(0, 60000 * 1000);388		/* Default wait time is 4.8ms, add 20% tolerance. */389		data->vcnl4200_ps.sampling_rate = ktime_set(0, 5760 * 1000);390		break;391	case VCNL4040_PROD_ID:392		/* Default wait time is 80ms, add 20% tolerance. */393		data->vcnl4200_al.sampling_rate = ktime_set(0, 96000 * 1000);394		/* Default wait time is 5ms, add 20% tolerance. */395		data->vcnl4200_ps.sampling_rate = ktime_set(0, 6000 * 1000);396		break;397	}398	data->al_scale = data->chip_spec->ulux_step;399	data->ps_scale = 16;400	mutex_init(&data->vcnl4200_al.lock);401	mutex_init(&data->vcnl4200_ps.lock);402 403	/* Use 16 bits proximity sensor readings */404	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);405	if (ret < 0)406		return ret;407 408	regval = ret | VCNL4040_PS_CONF2_PS_HD;409	ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1,410					regval);411	if (ret < 0)412		return ret;413 414	/* Align proximity sensor sample rate to 16 bits data width */415	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);416	if (ret < 0)417		return ret;418 419	regval = ret | VCNL4040_CONF3_PS_SAMPLE_16BITS;420	ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3,421					regval);422	if (ret < 0)423		return ret;424 425	ret = data->chip_spec->set_power_state(data, true);426	if (ret < 0)427		return ret;428 429	return 0;430};431 432static int vcnl4000_read_data(struct vcnl4000_data *data, u8 data_reg, int *val)433{434	s32 ret;435 436	ret = i2c_smbus_read_word_swapped(data->client, data_reg);437	if (ret < 0)438		return ret;439 440	*val = ret;441	return 0;442}443 444static int vcnl4000_write_data(struct vcnl4000_data *data, u8 data_reg, int val)445{446	if (val > U16_MAX)447		return -ERANGE;448 449	return i2c_smbus_write_word_swapped(data->client, data_reg, val);450}451 452 453static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask,454				u8 rdy_mask, u8 data_reg, int *val)455{456	int tries = 20;457	int ret;458 459	mutex_lock(&data->vcnl4000_lock);460 461	ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND,462					req_mask);463	if (ret < 0)464		goto fail;465 466	/* wait for data to become ready */467	while (tries--) {468		ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND);469		if (ret < 0)470			goto fail;471		if (ret & rdy_mask)472			break;473		msleep(20); /* measurement takes up to 100 ms */474	}475 476	if (tries < 0) {477		dev_err(&data->client->dev,478			"vcnl4000_measure() failed, data not ready\n");479		ret = -EIO;480		goto fail;481	}482 483	ret = vcnl4000_read_data(data, data_reg, val);484	if (ret < 0)485		goto fail;486 487	mutex_unlock(&data->vcnl4000_lock);488 489	return 0;490 491fail:492	mutex_unlock(&data->vcnl4000_lock);493	return ret;494}495 496static int vcnl4200_measure(struct vcnl4000_data *data,497		struct vcnl4200_channel *chan, int *val)498{499	int ret;500	s64 delta;501	ktime_t next_measurement;502 503	mutex_lock(&chan->lock);504 505	next_measurement = ktime_add(chan->last_measurement,506			chan->sampling_rate);507	delta = ktime_us_delta(next_measurement, ktime_get());508	if (delta > 0)509		usleep_range(delta, delta + 500);510	chan->last_measurement = ktime_get();511 512	mutex_unlock(&chan->lock);513 514	ret = i2c_smbus_read_word_data(data->client, chan->reg);515	if (ret < 0)516		return ret;517 518	*val = ret;519 520	return 0;521}522 523static int vcnl4000_measure_light(struct vcnl4000_data *data, int *val)524{525	return vcnl4000_measure(data,526			VCNL4000_AL_OD, VCNL4000_AL_RDY,527			VCNL4000_AL_RESULT_HI, val);528}529 530static int vcnl4200_measure_light(struct vcnl4000_data *data, int *val)531{532	return vcnl4200_measure(data, &data->vcnl4200_al, val);533}534 535static int vcnl4000_measure_proximity(struct vcnl4000_data *data, int *val)536{537	return vcnl4000_measure(data,538			VCNL4000_PS_OD, VCNL4000_PS_RDY,539			VCNL4000_PS_RESULT_HI, val);540}541 542static int vcnl4200_measure_proximity(struct vcnl4000_data *data, int *val)543{544	return vcnl4200_measure(data, &data->vcnl4200_ps, val);545}546 547static int vcnl4010_read_proxy_samp_freq(struct vcnl4000_data *data, int *val,548					 int *val2)549{550	int ret;551 552	ret = i2c_smbus_read_byte_data(data->client, VCNL4010_PROX_RATE);553	if (ret < 0)554		return ret;555 556	if (ret >= ARRAY_SIZE(vcnl4010_prox_sampling_frequency))557		return -EINVAL;558 559	*val = vcnl4010_prox_sampling_frequency[ret][0];560	*val2 = vcnl4010_prox_sampling_frequency[ret][1];561 562	return 0;563}564 565static bool vcnl4010_is_in_periodic_mode(struct vcnl4000_data *data)566{567	int ret;568 569	ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND);570	if (ret < 0)571		return false;572 573	return !!(ret & VCNL4000_SELF_TIMED_EN);574}575 576static int vcnl4000_set_pm_runtime_state(struct vcnl4000_data *data, bool on)577{578	struct device *dev = &data->client->dev;579	int ret;580 581	if (on) {582		ret = pm_runtime_resume_and_get(dev);583	} else {584		pm_runtime_mark_last_busy(dev);585		ret = pm_runtime_put_autosuspend(dev);586	}587 588	return ret;589}590 591static int vcnl4040_read_als_it(struct vcnl4000_data *data, int *val, int *val2)592{593	int ret;594 595	ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);596	if (ret < 0)597		return ret;598 599	ret = FIELD_GET(VCNL4040_ALS_CONF_IT, ret);600	if (ret >= data->chip_spec->num_als_it_times)601		return -EINVAL;602 603	*val = (*data->chip_spec->als_it_times)[ret][0];604	*val2 = (*data->chip_spec->als_it_times)[ret][1];605 606	return 0;607}608 609static ssize_t vcnl4040_write_als_it(struct vcnl4000_data *data, int val)610{611	unsigned int i;612	int ret;613	u16 regval;614 615	for (i = 0; i < data->chip_spec->num_als_it_times; i++) {616		if (val == (*data->chip_spec->als_it_times)[i][1])617			break;618	}619 620	if (i == data->chip_spec->num_als_it_times)621		return -EINVAL;622 623	data->vcnl4200_al.sampling_rate = ktime_set(0, val * 1200);624	data->al_scale = div_u64(mul_u32_u32(data->chip_spec->ulux_step,625			 (*data->chip_spec->als_it_times)[0][1]),626			 val);627 628	mutex_lock(&data->vcnl4000_lock);629 630	ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);631	if (ret < 0)632		goto out_unlock;633 634	regval = FIELD_PREP(VCNL4040_ALS_CONF_IT, i);635	regval |= (ret & ~VCNL4040_ALS_CONF_IT);636	ret = i2c_smbus_write_word_data(data->client,637					VCNL4200_AL_CONF,638					regval);639 640out_unlock:641	mutex_unlock(&data->vcnl4000_lock);642	return ret;643}644 645static int vcnl4040_read_ps_it(struct vcnl4000_data *data, int *val, int *val2)646{647	int ret;648 649	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);650	if (ret < 0)651		return ret;652 653	ret = FIELD_GET(VCNL4040_PS_CONF2_PS_IT, ret);654 655	if (ret >= data->chip_spec->num_ps_it_times)656		return -EINVAL;657 658	*val = (*data->chip_spec->ps_it_times)[ret][0];659	*val2 = (*data->chip_spec->ps_it_times)[ret][1];660 661	return 0;662}663 664static ssize_t vcnl4040_write_ps_it(struct vcnl4000_data *data, int val)665{666	unsigned int i;667	int ret, index = -1;668	u16 regval;669 670	for (i = 0; i < data->chip_spec->num_ps_it_times; i++) {671		if (val == (*data->chip_spec->ps_it_times)[i][1]) {672			index = i;673			break;674		}675	}676 677	if (index < 0)678		return -EINVAL;679 680	data->vcnl4200_ps.sampling_rate = ktime_set(0, val * 60 * NSEC_PER_USEC);681 682	mutex_lock(&data->vcnl4000_lock);683 684	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);685	if (ret < 0)686		goto out;687 688	regval = (ret & ~VCNL4040_PS_CONF2_PS_IT) |689	    FIELD_PREP(VCNL4040_PS_CONF2_PS_IT, index);690	ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1,691					regval);692 693out:694	mutex_unlock(&data->vcnl4000_lock);695	return ret;696}697 698static ssize_t vcnl4040_read_als_period(struct vcnl4000_data *data, int *val, int *val2)699{700	int ret, ret_pers, it;701	int64_t val_c;702 703	ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);704	if (ret < 0)705		return ret;706 707	ret_pers = FIELD_GET(VCNL4040_ALS_CONF_PERS, ret);708	if (ret_pers >= ARRAY_SIZE(vcnl4040_als_persistence))709		return -EINVAL;710 711	it = FIELD_GET(VCNL4040_ALS_CONF_IT, ret);712	if (it >= data->chip_spec->num_als_it_times)713		return -EINVAL;714 715	val_c = mul_u32_u32((*data->chip_spec->als_it_times)[it][1],716			    vcnl4040_als_persistence[ret_pers]);717	*val = div_u64_rem(val_c, MICRO, val2);718 719	return IIO_VAL_INT_PLUS_MICRO;720}721 722static ssize_t vcnl4040_write_als_period(struct vcnl4000_data *data, int val, int val2)723{724	unsigned int i;725	int ret, it;726	u16 regval;727	u64 val_n = mul_u32_u32(val, MICRO) + val2;728 729	ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);730	if (ret < 0)731		return ret;732 733	it = FIELD_GET(VCNL4040_ALS_CONF_IT, ret);734	if (it >= data->chip_spec->num_als_it_times)735		return -EINVAL;736 737	for (i = 0; i < ARRAY_SIZE(vcnl4040_als_persistence) - 1; i++) {738		if (val_n < mul_u32_u32(vcnl4040_als_persistence[i],739					(*data->chip_spec->als_it_times)[it][1]))740			break;741	}742 743	mutex_lock(&data->vcnl4000_lock);744 745	ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);746	if (ret < 0)747		goto out_unlock;748 749	regval = FIELD_PREP(VCNL4040_ALS_CONF_PERS, i);750	regval |= (ret & ~VCNL4040_ALS_CONF_PERS);751	ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF,752					regval);753 754out_unlock:755	mutex_unlock(&data->vcnl4000_lock);756	return ret;757}758 759static ssize_t vcnl4040_read_ps_period(struct vcnl4000_data *data, int *val, int *val2)760{761	int ret, ret_pers, it;762 763	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);764	if (ret < 0)765		return ret;766 767	ret_pers = FIELD_GET(VCNL4040_CONF1_PS_PERS, ret);768	if (ret_pers >= ARRAY_SIZE(vcnl4040_ps_persistence))769		return -EINVAL;770 771	it = FIELD_GET(VCNL4040_PS_CONF2_PS_IT, ret);772	if (it >= data->chip_spec->num_ps_it_times)773		return -EINVAL;774 775	*val = (*data->chip_spec->ps_it_times)[it][0];776	*val2 = (*data->chip_spec->ps_it_times)[it][1] *777		vcnl4040_ps_persistence[ret_pers];778 779	return IIO_VAL_INT_PLUS_MICRO;780}781 782static ssize_t vcnl4040_write_ps_period(struct vcnl4000_data *data, int val, int val2)783{784	int ret, it, i;785	u16 regval;786 787	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);788	if (ret < 0)789		return ret;790 791	it = FIELD_GET(VCNL4040_PS_CONF2_PS_IT, ret);792	if (it >= data->chip_spec->num_ps_it_times)793		return -EINVAL;794 795	if (val > 0)796		i = ARRAY_SIZE(vcnl4040_ps_persistence) - 1;797	else {798		for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_persistence) - 1; i++) {799			if (val2 <= vcnl4040_ps_persistence[i] *800					(*data->chip_spec->ps_it_times)[it][1])801				break;802		}803	}804 805	mutex_lock(&data->vcnl4000_lock);806 807	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);808	if (ret < 0)809		goto out_unlock;810 811	regval = FIELD_PREP(VCNL4040_CONF1_PS_PERS, i);812	regval |= (ret & ~VCNL4040_CONF1_PS_PERS);813	ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1,814					regval);815 816out_unlock:817	mutex_unlock(&data->vcnl4000_lock);818	return ret;819}820 821static ssize_t vcnl4040_read_ps_oversampling_ratio(struct vcnl4000_data *data, int *val)822{823	int ret;824 825	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);826	if (ret < 0)827		return ret;828 829	ret = FIELD_GET(VCNL4040_PS_CONF3_MPS, ret);830	if (ret >= ARRAY_SIZE(vcnl4040_ps_oversampling_ratio))831		return -EINVAL;832 833	*val = vcnl4040_ps_oversampling_ratio[ret];834 835	return ret;836}837 838static ssize_t vcnl4040_write_ps_oversampling_ratio(struct vcnl4000_data *data, int val)839{840	unsigned int i;841	int ret;842	u16 regval;843 844	for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_oversampling_ratio); i++) {845		if (val == vcnl4040_ps_oversampling_ratio[i])846			break;847	}848 849	if (i >= ARRAY_SIZE(vcnl4040_ps_oversampling_ratio))850		return -EINVAL;851 852	mutex_lock(&data->vcnl4000_lock);853 854	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);855	if (ret < 0)856		goto out_unlock;857 858	regval = FIELD_PREP(VCNL4040_PS_CONF3_MPS, i);859	regval |= (ret & ~VCNL4040_PS_CONF3_MPS);860	ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3,861					regval);862 863out_unlock:864	mutex_unlock(&data->vcnl4000_lock);865	return ret;866}867 868static ssize_t vcnl4040_read_ps_calibbias(struct vcnl4000_data *data, int *val, int *val2)869{870	int ret;871 872	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);873	if (ret < 0)874		return ret;875 876	ret = FIELD_GET(VCNL4040_PS_MS_LED_I, ret);877	if (ret >= ARRAY_SIZE(vcnl4040_ps_calibbias_ua))878		return -EINVAL;879 880	*val = vcnl4040_ps_calibbias_ua[ret][0];881	*val2 = vcnl4040_ps_calibbias_ua[ret][1];882 883	return ret;884}885 886static ssize_t vcnl4040_write_ps_calibbias(struct vcnl4000_data *data, int val)887{888	unsigned int i;889	int ret;890	u16 regval;891 892	for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_calibbias_ua); i++) {893		if (val == vcnl4040_ps_calibbias_ua[i][1])894			break;895	}896 897	if (i >= ARRAY_SIZE(vcnl4040_ps_calibbias_ua))898		return -EINVAL;899 900	mutex_lock(&data->vcnl4000_lock);901 902	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);903	if (ret < 0)904		goto out_unlock;905 906	regval = (ret & ~VCNL4040_PS_MS_LED_I);907	regval |= FIELD_PREP(VCNL4040_PS_MS_LED_I, i);908	ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3,909					regval);910 911out_unlock:912	mutex_unlock(&data->vcnl4000_lock);913	return ret;914}915 916static int vcnl4000_read_raw(struct iio_dev *indio_dev,917				struct iio_chan_spec const *chan,918				int *val, int *val2, long mask)919{920	int ret;921	struct vcnl4000_data *data = iio_priv(indio_dev);922 923	switch (mask) {924	case IIO_CHAN_INFO_RAW:925		ret = vcnl4000_set_pm_runtime_state(data, true);926		if  (ret < 0)927			return ret;928 929		switch (chan->type) {930		case IIO_LIGHT:931			ret = data->chip_spec->measure_light(data, val);932			if (!ret)933				ret = IIO_VAL_INT;934			break;935		case IIO_PROXIMITY:936			ret = data->chip_spec->measure_proximity(data, val);937			*val2 = data->ps_scale;938			if (!ret)939				ret = IIO_VAL_FRACTIONAL;940			break;941		default:942			ret = -EINVAL;943		}944		vcnl4000_set_pm_runtime_state(data, false);945		return ret;946	case IIO_CHAN_INFO_SCALE:947		if (chan->type != IIO_LIGHT)948			return -EINVAL;949 950		*val = 0;951		*val2 = data->al_scale;952		return IIO_VAL_INT_PLUS_MICRO;953	case IIO_CHAN_INFO_INT_TIME:954		switch (chan->type) {955		case IIO_LIGHT:956			ret = vcnl4040_read_als_it(data, val, val2);957			break;958		case IIO_PROXIMITY:959			ret = vcnl4040_read_ps_it(data, val, val2);960			break;961		default:962			return -EINVAL;963		}964		if (ret < 0)965			return ret;966		return IIO_VAL_INT_PLUS_MICRO;967	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:968		switch (chan->type) {969		case IIO_PROXIMITY:970			ret = vcnl4040_read_ps_oversampling_ratio(data, val);971			if (ret < 0)972				return ret;973			return IIO_VAL_INT;974		default:975			return -EINVAL;976		}977	case IIO_CHAN_INFO_CALIBBIAS:978		switch (chan->type) {979		case IIO_PROXIMITY:980			ret = vcnl4040_read_ps_calibbias(data, val, val2);981			if (ret < 0)982				return ret;983			return IIO_VAL_INT_PLUS_MICRO;984		default:985			return -EINVAL;986		}987	default:988		return -EINVAL;989	}990}991 992static int vcnl4040_write_raw(struct iio_dev *indio_dev,993			      struct iio_chan_spec const *chan,994			      int val, int val2, long mask)995{996	struct vcnl4000_data *data = iio_priv(indio_dev);997 998	switch (mask) {999	case IIO_CHAN_INFO_INT_TIME:1000		if (val != 0)1001			return -EINVAL;1002		switch (chan->type) {1003		case IIO_LIGHT:1004			return vcnl4040_write_als_it(data, val2);1005		case IIO_PROXIMITY:1006			return vcnl4040_write_ps_it(data, val2);1007		default:1008			return -EINVAL;1009		}1010	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:1011		switch (chan->type) {1012		case IIO_PROXIMITY:1013			return vcnl4040_write_ps_oversampling_ratio(data, val);1014		default:1015			return -EINVAL;1016		}1017	case IIO_CHAN_INFO_CALIBBIAS:1018		switch (chan->type) {1019		case IIO_PROXIMITY:1020			return vcnl4040_write_ps_calibbias(data, val2);1021		default:1022			return -EINVAL;1023		}1024	default:1025		return -EINVAL;1026	}1027}1028 1029static int vcnl4040_read_avail(struct iio_dev *indio_dev,1030			       struct iio_chan_spec const *chan,1031			       const int **vals, int *type, int *length,1032			       long mask)1033{1034	struct vcnl4000_data *data = iio_priv(indio_dev);1035 1036	switch (mask) {1037	case IIO_CHAN_INFO_INT_TIME:1038		switch (chan->type) {1039		case IIO_LIGHT:1040			*vals = (int *)(*data->chip_spec->als_it_times);1041			*length = 2 * data->chip_spec->num_als_it_times;1042			break;1043		case IIO_PROXIMITY:1044			*vals = (int *)(*data->chip_spec->ps_it_times);1045			*length = 2 * data->chip_spec->num_ps_it_times;1046			break;1047		default:1048			return -EINVAL;1049		}1050		*type = IIO_VAL_INT_PLUS_MICRO;1051		return IIO_AVAIL_LIST;1052	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:1053		switch (chan->type) {1054		case IIO_PROXIMITY:1055			*vals = (int *)vcnl4040_ps_oversampling_ratio;1056			*length = ARRAY_SIZE(vcnl4040_ps_oversampling_ratio);1057			*type = IIO_VAL_INT;1058			return IIO_AVAIL_LIST;1059		default:1060			return -EINVAL;1061		}1062	case IIO_CHAN_INFO_CALIBBIAS:1063		switch (chan->type) {1064		case IIO_PROXIMITY:1065			*vals = (int *)vcnl4040_ps_calibbias_ua;1066			*length = 2 * ARRAY_SIZE(vcnl4040_ps_calibbias_ua);1067			*type = IIO_VAL_INT_PLUS_MICRO;1068			return IIO_AVAIL_LIST;1069		default:1070			return -EINVAL;1071		}1072	default:1073		return -EINVAL;1074	}1075}1076 1077static int vcnl4010_read_raw(struct iio_dev *indio_dev,1078			     struct iio_chan_spec const *chan,1079			     int *val, int *val2, long mask)1080{1081	int ret;1082	struct vcnl4000_data *data = iio_priv(indio_dev);1083 1084	switch (mask) {1085	case IIO_CHAN_INFO_RAW:1086	case IIO_CHAN_INFO_SCALE:1087		ret = iio_device_claim_direct_mode(indio_dev);1088		if (ret)1089			return ret;1090 1091		/* Protect against event capture. */1092		if (vcnl4010_is_in_periodic_mode(data)) {1093			ret = -EBUSY;1094		} else {1095			ret = vcnl4000_read_raw(indio_dev, chan, val, val2,1096						mask);1097		}1098 1099		iio_device_release_direct_mode(indio_dev);1100		return ret;1101	case IIO_CHAN_INFO_SAMP_FREQ:1102		switch (chan->type) {1103		case IIO_PROXIMITY:1104			ret = vcnl4010_read_proxy_samp_freq(data, val, val2);1105			if (ret < 0)1106				return ret;1107			return IIO_VAL_INT_PLUS_MICRO;1108		default:1109			return -EINVAL;1110		}1111	default:1112		return -EINVAL;1113	}1114}1115 1116static int vcnl4010_read_avail(struct iio_dev *indio_dev,1117			       struct iio_chan_spec const *chan,1118			       const int **vals, int *type, int *length,1119			       long mask)1120{1121	switch (mask) {1122	case IIO_CHAN_INFO_SAMP_FREQ:1123		*vals = (int *)vcnl4010_prox_sampling_frequency;1124		*type = IIO_VAL_INT_PLUS_MICRO;1125		*length = 2 * ARRAY_SIZE(vcnl4010_prox_sampling_frequency);1126		return IIO_AVAIL_LIST;1127	default:1128		return -EINVAL;1129	}1130}1131 1132static int vcnl4010_write_proxy_samp_freq(struct vcnl4000_data *data, int val,1133					  int val2)1134{1135	unsigned int i;1136	int index = -1;1137 1138	for (i = 0; i < ARRAY_SIZE(vcnl4010_prox_sampling_frequency); i++) {1139		if (val == vcnl4010_prox_sampling_frequency[i][0] &&1140		    val2 == vcnl4010_prox_sampling_frequency[i][1]) {1141			index = i;1142			break;1143		}1144	}1145 1146	if (index < 0)1147		return -EINVAL;1148 1149	return i2c_smbus_write_byte_data(data->client, VCNL4010_PROX_RATE,1150					 index);1151}1152 1153static int vcnl4010_write_raw(struct iio_dev *indio_dev,1154			      struct iio_chan_spec const *chan,1155			      int val, int val2, long mask)1156{1157	int ret;1158	struct vcnl4000_data *data = iio_priv(indio_dev);1159 1160	ret = iio_device_claim_direct_mode(indio_dev);1161	if (ret)1162		return ret;1163 1164	/* Protect against event capture. */1165	if (vcnl4010_is_in_periodic_mode(data)) {1166		ret = -EBUSY;1167		goto end;1168	}1169 1170	switch (mask) {1171	case IIO_CHAN_INFO_SAMP_FREQ:1172		switch (chan->type) {1173		case IIO_PROXIMITY:1174			ret = vcnl4010_write_proxy_samp_freq(data, val, val2);1175			goto end;1176		default:1177			ret = -EINVAL;1178			goto end;1179		}1180	default:1181		ret = -EINVAL;1182		goto end;1183	}1184 1185end:1186	iio_device_release_direct_mode(indio_dev);1187	return ret;1188}1189 1190static int vcnl4010_read_event(struct iio_dev *indio_dev,1191			       const struct iio_chan_spec *chan,1192			       enum iio_event_type type,1193			       enum iio_event_direction dir,1194			       enum iio_event_info info,1195			       int *val, int *val2)1196{1197	int ret;1198	struct vcnl4000_data *data = iio_priv(indio_dev);1199 1200	switch (info) {1201	case IIO_EV_INFO_VALUE:1202		switch (dir) {1203		case IIO_EV_DIR_RISING:1204			ret = vcnl4000_read_data(data, VCNL4010_HIGH_THR_HI,1205						 val);1206			if (ret < 0)1207				return ret;1208			return IIO_VAL_INT;1209		case IIO_EV_DIR_FALLING:1210			ret = vcnl4000_read_data(data, VCNL4010_LOW_THR_HI,1211						 val);1212			if (ret < 0)1213				return ret;1214			return IIO_VAL_INT;1215		default:1216			return -EINVAL;1217		}1218	default:1219		return -EINVAL;1220	}1221}1222 1223static int vcnl4010_write_event(struct iio_dev *indio_dev,1224				const struct iio_chan_spec *chan,1225				enum iio_event_type type,1226				enum iio_event_direction dir,1227				enum iio_event_info info,1228				int val, int val2)1229{1230	int ret;1231	struct vcnl4000_data *data = iio_priv(indio_dev);1232 1233	switch (info) {1234	case IIO_EV_INFO_VALUE:1235		switch (dir) {1236		case IIO_EV_DIR_RISING:1237			ret = vcnl4000_write_data(data, VCNL4010_HIGH_THR_HI,1238						  val);1239			if (ret < 0)1240				return ret;1241			return IIO_VAL_INT;1242		case IIO_EV_DIR_FALLING:1243			ret = vcnl4000_write_data(data, VCNL4010_LOW_THR_HI,1244						  val);1245			if (ret < 0)1246				return ret;1247			return IIO_VAL_INT;1248		default:1249			return -EINVAL;1250		}1251	default:1252		return -EINVAL;1253	}1254}1255 1256static int vcnl4040_read_event(struct iio_dev *indio_dev,1257			       const struct iio_chan_spec *chan,1258			       enum iio_event_type type,1259			       enum iio_event_direction dir,1260			       enum iio_event_info info,1261			       int *val, int *val2)1262{1263	int ret;1264	struct vcnl4000_data *data = iio_priv(indio_dev);1265 1266	switch (chan->type) {1267	case IIO_LIGHT:1268		switch (info) {1269		case IIO_EV_INFO_PERIOD:1270			return vcnl4040_read_als_period(data, val, val2);1271		case IIO_EV_INFO_VALUE:1272			switch (dir) {1273			case IIO_EV_DIR_RISING:1274				ret = i2c_smbus_read_word_data(data->client,1275							       VCNL4040_ALS_THDH_LM);1276				break;1277			case IIO_EV_DIR_FALLING:1278				ret = i2c_smbus_read_word_data(data->client,1279							       VCNL4040_ALS_THDL_LM);1280				break;1281			default:1282				return -EINVAL;1283			}1284			break;1285		default:1286			return -EINVAL;1287		}1288		break;1289	case IIO_PROXIMITY:1290		switch (info) {1291		case IIO_EV_INFO_PERIOD:1292			return vcnl4040_read_ps_period(data, val, val2);1293		case IIO_EV_INFO_VALUE:1294			switch (dir) {1295			case IIO_EV_DIR_RISING:1296				ret = i2c_smbus_read_word_data(data->client,1297							       VCNL4040_PS_THDH_LM);1298				break;1299			case IIO_EV_DIR_FALLING:1300				ret = i2c_smbus_read_word_data(data->client,1301							       VCNL4040_PS_THDL_LM);1302				break;1303			default:1304				return -EINVAL;1305			}1306			break;1307		default:1308			return -EINVAL;1309		}1310		break;1311	default:1312		return -EINVAL;1313	}1314	if (ret < 0)1315		return ret;1316	*val = ret;1317	return IIO_VAL_INT;1318}1319 1320static int vcnl4040_write_event(struct iio_dev *indio_dev,1321				const struct iio_chan_spec *chan,1322				enum iio_event_type type,1323				enum iio_event_direction dir,1324				enum iio_event_info info,1325				int val, int val2)1326{1327	int ret;1328	struct vcnl4000_data *data = iio_priv(indio_dev);1329 1330	switch (chan->type) {1331	case IIO_LIGHT:1332		switch (info) {1333		case IIO_EV_INFO_PERIOD:1334			return vcnl4040_write_als_period(data, val, val2);1335		case IIO_EV_INFO_VALUE:1336			switch (dir) {1337			case IIO_EV_DIR_RISING:1338				ret = i2c_smbus_write_word_data(data->client,1339								VCNL4040_ALS_THDH_LM,1340								val);1341				break;1342			case IIO_EV_DIR_FALLING:1343				ret = i2c_smbus_write_word_data(data->client,1344								VCNL4040_ALS_THDL_LM,1345								val);1346				break;1347			default:1348				return -EINVAL;1349			}1350			break;1351		default:1352			return -EINVAL;1353		}1354		break;1355	case IIO_PROXIMITY:1356		switch (info) {1357		case IIO_EV_INFO_PERIOD:1358			return vcnl4040_write_ps_period(data, val, val2);1359		case IIO_EV_INFO_VALUE:1360			switch (dir) {1361			case IIO_EV_DIR_RISING:1362				ret = i2c_smbus_write_word_data(data->client,1363								VCNL4040_PS_THDH_LM,1364								val);1365				break;1366			case IIO_EV_DIR_FALLING:1367				ret = i2c_smbus_write_word_data(data->client,1368								VCNL4040_PS_THDL_LM,1369								val);1370				break;1371			default:1372				return -EINVAL;1373			}1374			break;1375		default:1376			return -EINVAL;1377		}1378		break;1379	default:1380		return -EINVAL;1381	}1382	if (ret < 0)1383		return ret;1384	return IIO_VAL_INT;1385}1386 1387static bool vcnl4010_is_thr_enabled(struct vcnl4000_data *data)1388{1389	int ret;1390 1391	ret = i2c_smbus_read_byte_data(data->client, VCNL4010_INT_CTRL);1392	if (ret < 0)1393		return false;1394 1395	return !!(ret & VCNL4010_INT_THR_EN);1396}1397 1398static int vcnl4010_read_event_config(struct iio_dev *indio_dev,1399				      const struct iio_chan_spec *chan,1400				      enum iio_event_type type,1401				      enum iio_event_direction dir)1402{1403	struct vcnl4000_data *data = iio_priv(indio_dev);1404 1405	switch (chan->type) {1406	case IIO_PROXIMITY:1407		return vcnl4010_is_thr_enabled(data);1408	default:1409		return -EINVAL;1410	}1411}1412 1413static int vcnl4010_config_threshold(struct iio_dev *indio_dev, bool state)1414{1415	struct vcnl4000_data *data = iio_priv(indio_dev);1416	int ret;1417	int icr;1418	int command;1419 1420	if (state) {1421		ret = iio_device_claim_direct_mode(indio_dev);1422		if (ret)1423			return ret;1424 1425		/* Enable periodic measurement of proximity data. */1426		command = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN;1427 1428		/*1429		 * Enable interrupts on threshold, for proximity data by1430		 * default.1431		 */1432		icr = VCNL4010_INT_THR_EN;1433	} else {1434		if (!vcnl4010_is_thr_enabled(data))1435			return 0;1436 1437		command = 0;1438		icr = 0;1439	}1440 1441	ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND,1442					command);1443	if (ret < 0)1444		goto end;1445 1446	ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, icr);1447 1448end:1449	if (state)1450		iio_device_release_direct_mode(indio_dev);1451 1452	return ret;1453}1454 1455static int vcnl4010_write_event_config(struct iio_dev *indio_dev,1456				       const struct iio_chan_spec *chan,1457				       enum iio_event_type type,1458				       enum iio_event_direction dir,1459				       int state)1460{1461	switch (chan->type) {1462	case IIO_PROXIMITY:1463		return vcnl4010_config_threshold(indio_dev, state);1464	default:1465		return -EINVAL;1466	}1467}1468 1469static int vcnl4040_read_event_config(struct iio_dev *indio_dev,1470				      const struct iio_chan_spec *chan,1471				      enum iio_event_type type,1472				      enum iio_event_direction dir)1473{1474	int ret;1475	struct vcnl4000_data *data = iio_priv(indio_dev);1476 1477	switch (chan->type) {1478	case IIO_LIGHT:1479		ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);1480		if (ret < 0)1481			return ret;1482 1483		data->als_int = FIELD_GET(VCNL4040_ALS_CONF_INT_EN, ret);1484 1485		return data->als_int;1486	case IIO_PROXIMITY:1487		ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);1488		if (ret < 0)1489			return ret;1490 1491		data->ps_int = FIELD_GET(VCNL4040_PS_CONF2_PS_INT, ret);1492 1493		return (dir == IIO_EV_DIR_RISING) ?1494			FIELD_GET(VCNL4040_PS_IF_AWAY, ret) :1495			FIELD_GET(VCNL4040_PS_IF_CLOSE, ret);1496	default:1497		return -EINVAL;1498	}1499}1500 1501static int vcnl4040_write_event_config(struct iio_dev *indio_dev,1502				       const struct iio_chan_spec *chan,1503				       enum iio_event_type type,1504				       enum iio_event_direction dir, int state)1505{1506	int ret = -EINVAL;1507	u16 val, mask;1508	struct vcnl4000_data *data = iio_priv(indio_dev);1509 1510	mutex_lock(&data->vcnl4000_lock);1511 1512	switch (chan->type) {1513	case IIO_LIGHT:1514		ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);1515		if (ret < 0)1516			goto out;1517 1518		mask = VCNL4040_ALS_CONF_INT_EN;1519		if (state)1520			val = (ret | mask);1521		else1522			val = (ret & ~mask);1523 1524		data->als_int = FIELD_GET(VCNL4040_ALS_CONF_INT_EN, val);1525		ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF,1526						val);1527		break;1528	case IIO_PROXIMITY:1529		ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);1530		if (ret < 0)1531			goto out;1532 1533		if (dir == IIO_EV_DIR_RISING)1534			mask = VCNL4040_PS_IF_AWAY;1535		else1536			mask = VCNL4040_PS_IF_CLOSE;1537 1538		val = state ? (ret | mask) : (ret & ~mask);1539 1540		data->ps_int = FIELD_GET(VCNL4040_PS_CONF2_PS_INT, val);1541		ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1,1542						val);1543		break;1544	default:1545		break;1546	}1547 1548out:1549	mutex_unlock(&data->vcnl4000_lock);1550 1551	return ret;1552}1553 1554static irqreturn_t vcnl4040_irq_thread(int irq, void *p)1555{1556	struct iio_dev *indio_dev = p;1557	struct vcnl4000_data *data = iio_priv(indio_dev);1558	int ret;1559 1560	ret = i2c_smbus_read_word_data(data->client, data->chip_spec->int_reg);1561	if (ret < 0)1562		return IRQ_HANDLED;1563 1564	if (ret & VCNL4040_PS_IF_CLOSE) {1565		iio_push_event(indio_dev,1566			       IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0,1567						    IIO_EV_TYPE_THRESH,1568						    IIO_EV_DIR_RISING),1569			       iio_get_time_ns(indio_dev));1570	}1571 1572	if (ret & VCNL4040_PS_IF_AWAY) {1573		iio_push_event(indio_dev,1574			       IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0,1575						    IIO_EV_TYPE_THRESH,1576						    IIO_EV_DIR_FALLING),1577			       iio_get_time_ns(indio_dev));1578	}1579 1580	if (ret & VCNL4040_ALS_FALLING) {1581		iio_push_event(indio_dev,1582			       IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,1583						    IIO_EV_TYPE_THRESH,1584						    IIO_EV_DIR_FALLING),1585			       iio_get_time_ns(indio_dev));1586	}1587 1588	if (ret & VCNL4040_ALS_RISING) {1589		iio_push_event(indio_dev,1590			       IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,1591						    IIO_EV_TYPE_THRESH,1592						    IIO_EV_DIR_RISING),1593			       iio_get_time_ns(indio_dev));1594	}1595 1596	return IRQ_HANDLED;1597}1598 1599static ssize_t vcnl4000_read_near_level(struct iio_dev *indio_dev,1600					uintptr_t priv,1601					const struct iio_chan_spec *chan,1602					char *buf)1603{1604	struct vcnl4000_data *data = iio_priv(indio_dev);1605 1606	return sprintf(buf, "%u\n", data->near_level);1607}1608 1609static irqreturn_t vcnl4010_irq_thread(int irq, void *p)1610{1611	struct iio_dev *indio_dev = p;1612	struct vcnl4000_data *data = iio_priv(indio_dev);1613	unsigned long isr;1614	int ret;1615 1616	ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR);1617	if (ret < 0)1618		goto end;1619 1620	isr = ret;1621 1622	if (isr & VCNL4010_INT_THR) {1623		if (test_bit(VCNL4010_INT_THR_LOW, &isr)) {1624			iio_push_event(indio_dev,1625				       IIO_UNMOD_EVENT_CODE(1626					       IIO_PROXIMITY,1627					       1,1628					       IIO_EV_TYPE_THRESH,1629					       IIO_EV_DIR_FALLING),1630				       iio_get_time_ns(indio_dev));1631		}1632 1633		if (test_bit(VCNL4010_INT_THR_HIGH, &isr)) {1634			iio_push_event(indio_dev,1635				       IIO_UNMOD_EVENT_CODE(1636					       IIO_PROXIMITY,1637					       1,1638					       IIO_EV_TYPE_THRESH,1639					       IIO_EV_DIR_RISING),1640				       iio_get_time_ns(indio_dev));1641		}1642 1643		i2c_smbus_write_byte_data(data->client, VCNL4010_ISR,1644					  isr & VCNL4010_INT_THR);1645	}1646 1647	if (isr & VCNL4010_INT_DRDY && iio_buffer_enabled(indio_dev))1648		iio_trigger_poll_nested(indio_dev->trig);1649 1650end:1651	return IRQ_HANDLED;1652}1653 1654static irqreturn_t vcnl4010_trigger_handler(int irq, void *p)1655{1656	struct iio_poll_func *pf = p;1657	struct iio_dev *indio_dev = pf->indio_dev;1658	struct vcnl4000_data *data = iio_priv(indio_dev);1659	const unsigned long *active_scan_mask = indio_dev->active_scan_mask;1660	u16 buffer[8] __aligned(8) = {0}; /* 1x16-bit + naturally aligned ts */1661	bool data_read = false;1662	unsigned long isr;1663	int val = 0;1664	int ret;1665 1666	ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR);1667	if (ret < 0)1668		goto end;1669 1670	isr = ret;1671 1672	if (test_bit(0, active_scan_mask)) {1673		if (test_bit(VCNL4010_INT_PROXIMITY, &isr)) {1674			ret = vcnl4000_read_data(data,1675						 VCNL4000_PS_RESULT_HI,1676						 &val);1677			if (ret < 0)1678				goto end;1679 1680			buffer[0] = val;1681			data_read = true;1682		}1683	}1684 1685	ret = i2c_smbus_write_byte_data(data->client, VCNL4010_ISR,1686					isr & VCNL4010_INT_DRDY);1687	if (ret < 0)1688		goto end;1689 1690	if (!data_read)1691		goto end;1692 1693	iio_push_to_buffers_with_timestamp(indio_dev, buffer,1694					   iio_get_time_ns(indio_dev));1695 1696end:1697	iio_trigger_notify_done(indio_dev->trig);1698	return IRQ_HANDLED;1699}1700 1701static int vcnl4010_buffer_postenable(struct iio_dev *indio_dev)1702{1703	struct vcnl4000_data *data = iio_priv(indio_dev);1704	int ret;1705	int cmd;1706 1707	/* Do not enable the buffer if we are already capturing events. */1708	if (vcnl4010_is_in_periodic_mode(data))1709		return -EBUSY;1710 1711	ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL,1712					VCNL4010_INT_PROX_EN);1713	if (ret < 0)1714		return ret;1715 1716	cmd = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN;1717	return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, cmd);1718}1719 1720static int vcnl4010_buffer_predisable(struct iio_dev *indio_dev)1721{1722	struct vcnl4000_data *data = iio_priv(indio_dev);1723	int ret;1724 1725	ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, 0);1726	if (ret < 0)1727		return ret;1728 1729	return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 0);1730}1731 1732static const struct iio_buffer_setup_ops vcnl4010_buffer_ops = {1733	.postenable = &vcnl4010_buffer_postenable,1734	.predisable = &vcnl4010_buffer_predisable,1735};1736 1737static const struct iio_chan_spec_ext_info vcnl4000_ext_info[] = {1738	{1739		.name = "nearlevel",1740		.shared = IIO_SEPARATE,1741		.read = vcnl4000_read_near_level,1742	},1743	{ /* sentinel */ }1744};1745 1746static const struct iio_event_spec vcnl4000_event_spec[] = {1747	{1748		.type = IIO_EV_TYPE_THRESH,1749		.dir = IIO_EV_DIR_RISING,1750		.mask_separate = BIT(IIO_EV_INFO_VALUE),1751	}, {1752		.type = IIO_EV_TYPE_THRESH,1753		.dir = IIO_EV_DIR_FALLING,1754		.mask_separate = BIT(IIO_EV_INFO_VALUE),1755	}, {1756		.type = IIO_EV_TYPE_THRESH,1757		.dir = IIO_EV_DIR_EITHER,1758		.mask_separate = BIT(IIO_EV_INFO_ENABLE),1759	}1760};1761 1762static const struct iio_event_spec vcnl4040_als_event_spec[] = {1763	{1764		.type = IIO_EV_TYPE_THRESH,1765		.dir = IIO_EV_DIR_RISING,1766		.mask_separate = BIT(IIO_EV_INFO_VALUE),1767	}, {1768		.type = IIO_EV_TYPE_THRESH,1769		.dir = IIO_EV_DIR_FALLING,1770		.mask_separate = BIT(IIO_EV_INFO_VALUE),1771	}, {1772		.type = IIO_EV_TYPE_THRESH,1773		.dir = IIO_EV_DIR_EITHER,1774		.mask_separate = BIT(IIO_EV_INFO_ENABLE) | BIT(IIO_EV_INFO_PERIOD),1775	},1776};1777 1778static const struct iio_event_spec vcnl4040_event_spec[] = {1779	{1780		.type = IIO_EV_TYPE_THRESH,1781		.dir = IIO_EV_DIR_RISING,1782		.mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE),1783	}, {1784		.type = IIO_EV_TYPE_THRESH,1785		.dir = IIO_EV_DIR_FALLING,1786		.mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE),1787	}, {1788		.type = IIO_EV_TYPE_THRESH,1789		.dir = IIO_EV_DIR_EITHER,1790		.mask_separate = BIT(IIO_EV_INFO_PERIOD),1791	},1792};1793 1794static const struct iio_chan_spec vcnl4000_channels[] = {1795	{1796		.type = IIO_LIGHT,1797		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |1798			BIT(IIO_CHAN_INFO_SCALE),1799	}, {1800		.type = IIO_PROXIMITY,1801		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),1802		.ext_info = vcnl4000_ext_info,1803	}1804};1805 1806static const struct iio_chan_spec vcnl4010_channels[] = {1807	{1808		.type = IIO_LIGHT,1809		.scan_index = -1,1810		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |1811			BIT(IIO_CHAN_INFO_SCALE),1812	}, {1813		.type = IIO_PROXIMITY,1814		.scan_index = 0,1815		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |1816			BIT(IIO_CHAN_INFO_SAMP_FREQ),1817		.info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ),1818		.event_spec = vcnl4000_event_spec,1819		.num_event_specs = ARRAY_SIZE(vcnl4000_event_spec),1820		.ext_info = vcnl4000_ext_info,1821		.scan_type = {1822			.sign = 'u',1823			.realbits = 16,1824			.storagebits = 16,1825			.endianness = IIO_CPU,1826		},1827	},1828	IIO_CHAN_SOFT_TIMESTAMP(1),1829};1830 1831static const struct iio_chan_spec vcnl4040_channels[] = {1832	{1833		.type = IIO_LIGHT,1834		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |1835			BIT(IIO_CHAN_INFO_SCALE) |1836			BIT(IIO_CHAN_INFO_INT_TIME),1837		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME),1838		.event_spec = vcnl4040_als_event_spec,1839		.num_event_specs = ARRAY_SIZE(vcnl4040_als_event_spec),1840	}, {1841		.type = IIO_PROXIMITY,1842		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |1843			BIT(IIO_CHAN_INFO_INT_TIME) |1844			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) |1845			BIT(IIO_CHAN_INFO_CALIBBIAS),1846		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME) |1847			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) |1848			BIT(IIO_CHAN_INFO_CALIBBIAS),1849		.ext_info = vcnl4000_ext_info,1850		.event_spec = vcnl4040_event_spec,1851		.num_event_specs = ARRAY_SIZE(vcnl4040_event_spec),1852	}1853};1854 1855static const struct iio_info vcnl4000_info = {1856	.read_raw = vcnl4000_read_raw,1857};1858 1859static const struct iio_info vcnl4010_info = {1860	.read_raw = vcnl4010_read_raw,1861	.read_avail = vcnl4010_read_avail,1862	.write_raw = vcnl4010_write_raw,1863	.read_event_value = vcnl4010_read_event,1864	.write_event_value = vcnl4010_write_event,1865	.read_event_config = vcnl4010_read_event_config,1866	.write_event_config = vcnl4010_write_event_config,1867};1868 1869static const struct iio_info vcnl4040_info = {1870	.read_raw = vcnl4000_read_raw,1871	.write_raw = vcnl4040_write_raw,1872	.read_event_value = vcnl4040_read_event,1873	.write_event_value = vcnl4040_write_event,1874	.read_event_config = vcnl4040_read_event_config,1875	.write_event_config = vcnl4040_write_event_config,1876	.read_avail = vcnl4040_read_avail,1877};1878 1879static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = {1880	[VCNL4000] = {1881		.prod = "VCNL4000",1882		.init = vcnl4000_init,1883		.measure_light = vcnl4000_measure_light,1884		.measure_proximity = vcnl4000_measure_proximity,1885		.set_power_state = vcnl4000_set_power_state,1886		.channels = vcnl4000_channels,1887		.num_channels = ARRAY_SIZE(vcnl4000_channels),1888		.info = &vcnl4000_info,1889	},1890	[VCNL4010] = {1891		.prod = "VCNL4010/4020",1892		.init = vcnl4000_init,1893		.measure_light = vcnl4000_measure_light,1894		.measure_proximity = vcnl4000_measure_proximity,1895		.set_power_state = vcnl4000_set_power_state,1896		.channels = vcnl4010_channels,1897		.num_channels = ARRAY_SIZE(vcnl4010_channels),1898		.info = &vcnl4010_info,1899		.irq_thread = vcnl4010_irq_thread,1900		.trig_buffer_func = vcnl4010_trigger_handler,1901		.buffer_setup_ops = &vcnl4010_buffer_ops,1902	},1903	[VCNL4040] = {1904		.prod = "VCNL4040",1905		.init = vcnl4200_init,1906		.measure_light = vcnl4200_measure_light,1907		.measure_proximity = vcnl4200_measure_proximity,1908		.set_power_state = vcnl4200_set_power_state,1909		.channels = vcnl4040_channels,1910		.num_channels = ARRAY_SIZE(vcnl4040_channels),1911		.info = &vcnl4040_info,1912		.irq_thread = vcnl4040_irq_thread,1913		.int_reg = VCNL4040_INT_FLAGS,1914		.ps_it_times = &vcnl4040_ps_it_times,1915		.num_ps_it_times = ARRAY_SIZE(vcnl4040_ps_it_times),1916		.als_it_times = &vcnl4040_als_it_times,1917		.num_als_it_times = ARRAY_SIZE(vcnl4040_als_it_times),1918		.ulux_step = 100000,1919	},1920	[VCNL4200] = {1921		.prod = "VCNL4200",1922		.init = vcnl4200_init,1923		.measure_light = vcnl4200_measure_light,1924		.measure_proximity = vcnl4200_measure_proximity,1925		.set_power_state = vcnl4200_set_power_state,1926		.channels = vcnl4040_channels,1927		.num_channels = ARRAY_SIZE(vcnl4000_channels),1928		.info = &vcnl4040_info,1929		.irq_thread = vcnl4040_irq_thread,1930		.int_reg = VCNL4200_INT_FLAGS,1931		.ps_it_times = &vcnl4200_ps_it_times,1932		.num_ps_it_times = ARRAY_SIZE(vcnl4200_ps_it_times),1933		.als_it_times = &vcnl4200_als_it_times,1934		.num_als_it_times = ARRAY_SIZE(vcnl4200_als_it_times),1935		.ulux_step = 24000,1936	},1937};1938 1939static const struct iio_trigger_ops vcnl4010_trigger_ops = {1940	.validate_device = iio_trigger_validate_own_device,1941};1942 1943static int vcnl4010_probe_trigger(struct iio_dev *indio_dev)1944{1945	struct vcnl4000_data *data = iio_priv(indio_dev);1946	struct i2c_client *client = data->client;1947	struct iio_trigger *trigger;1948 1949	trigger = devm_iio_trigger_alloc(&client->dev, "%s-dev%d",1950					 indio_dev->name,1951					 iio_device_id(indio_dev));1952	if (!trigger)1953		return -ENOMEM;1954 1955	trigger->ops = &vcnl4010_trigger_ops;1956	iio_trigger_set_drvdata(trigger, indio_dev);1957 1958	return devm_iio_trigger_register(&client->dev, trigger);1959}1960 1961static int vcnl4000_probe(struct i2c_client *client)1962{1963	const struct i2c_device_id *id = i2c_client_get_device_id(client);1964	struct vcnl4000_data *data;1965	struct iio_dev *indio_dev;1966	int ret;1967 1968	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));1969	if (!indio_dev)1970		return -ENOMEM;1971 1972	data = iio_priv(indio_dev);1973	i2c_set_clientdata(client, indio_dev);1974	data->client = client;1975	data->id = id->driver_data;1976	data->chip_spec = &vcnl4000_chip_spec_cfg[data->id];1977 1978	mutex_init(&data->vcnl4000_lock);1979 1980	ret = data->chip_spec->init(data);1981	if (ret < 0)1982		return ret;1983 1984	dev_dbg(&client->dev, "%s Ambient light/proximity sensor, Rev: %02x\n",1985		data->chip_spec->prod, data->rev);1986 1987	if (device_property_read_u32(&client->dev, "proximity-near-level",1988				     &data->near_level))1989		data->near_level = 0;1990 1991	indio_dev->info = data->chip_spec->info;1992	indio_dev->channels = data->chip_spec->channels;1993	indio_dev->num_channels = data->chip_spec->num_channels;1994	indio_dev->name = VCNL4000_DRV_NAME;1995	indio_dev->modes = INDIO_DIRECT_MODE;1996 1997	if (data->chip_spec->trig_buffer_func &&1998	    data->chip_spec->buffer_setup_ops) {1999		ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,2000						      NULL,2001						      data->chip_spec->trig_buffer_func,2002						      data->chip_spec->buffer_setup_ops);2003		if (ret < 0) {2004			dev_err(&client->dev,2005				"unable to setup iio triggered buffer\n");2006			return ret;2007		}2008	}2009 2010	if (client->irq && data->chip_spec->irq_thread) {2011		ret = devm_request_threaded_irq(&client->dev, client->irq,2012						NULL, data->chip_spec->irq_thread,2013						IRQF_TRIGGER_FALLING |2014						IRQF_ONESHOT,2015						"vcnl4000_irq",2016						indio_dev);2017		if (ret < 0) {2018			dev_err(&client->dev, "irq request failed\n");2019			return ret;2020		}2021 2022		ret = vcnl4010_probe_trigger(indio_dev);2023		if (ret < 0)2024			return ret;2025	}2026 2027	ret = pm_runtime_set_active(&client->dev);2028	if (ret < 0)2029		goto fail_poweroff;2030 2031	ret = iio_device_register(indio_dev);2032	if (ret < 0)2033		goto fail_poweroff;2034 2035	pm_runtime_enable(&client->dev);2036	pm_runtime_set_autosuspend_delay(&client->dev, VCNL4000_SLEEP_DELAY_MS);2037	pm_runtime_use_autosuspend(&client->dev);2038 2039	return 0;2040fail_poweroff:2041	data->chip_spec->set_power_state(data, false);2042	return ret;2043}2044 2045static const struct of_device_id vcnl_4000_of_match[] = {2046	{2047		.compatible = "vishay,vcnl4000",2048		.data = (void *)VCNL4000,2049	},2050	{2051		.compatible = "vishay,vcnl4010",2052		.data = (void *)VCNL4010,2053	},2054	{2055		.compatible = "vishay,vcnl4020",2056		.data = (void *)VCNL4010,2057	},2058	{2059		.compatible = "vishay,vcnl4040",2060		.data = (void *)VCNL4040,2061	},2062	{2063		.compatible = "vishay,vcnl4200",2064		.data = (void *)VCNL4200,2065	},2066	{},2067};2068MODULE_DEVICE_TABLE(of, vcnl_4000_of_match);2069 2070static void vcnl4000_remove(struct i2c_client *client)2071{2072	struct iio_dev *indio_dev = i2c_get_clientdata(client);2073	struct vcnl4000_data *data = iio_priv(indio_dev);2074	int ret;2075 2076	pm_runtime_dont_use_autosuspend(&client->dev);2077	pm_runtime_disable(&client->dev);2078	iio_device_unregister(indio_dev);2079	pm_runtime_set_suspended(&client->dev);2080 2081	ret = data->chip_spec->set_power_state(data, false);2082	if (ret)2083		dev_warn(&client->dev, "Failed to power down (%pe)\n",2084			 ERR_PTR(ret));2085}2086 2087static int vcnl4000_runtime_suspend(struct device *dev)2088{2089	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));2090	struct vcnl4000_data *data = iio_priv(indio_dev);2091 2092	return data->chip_spec->set_power_state(data, false);2093}2094 2095static int vcnl4000_runtime_resume(struct device *dev)2096{2097	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));2098	struct vcnl4000_data *data = iio_priv(indio_dev);2099 2100	return data->chip_spec->set_power_state(data, true);2101}2102 2103static DEFINE_RUNTIME_DEV_PM_OPS(vcnl4000_pm_ops, vcnl4000_runtime_suspend,2104				 vcnl4000_runtime_resume, NULL);2105 2106static struct i2c_driver vcnl4000_driver = {2107	.driver = {2108		.name   = VCNL4000_DRV_NAME,2109		.pm	= pm_ptr(&vcnl4000_pm_ops),2110		.of_match_table = vcnl_4000_of_match,2111	},2112	.probe = vcnl4000_probe,2113	.id_table = vcnl4000_id,2114	.remove	= vcnl4000_remove,2115};2116 2117module_i2c_driver(vcnl4000_driver);2118 2119MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");2120MODULE_AUTHOR("Mathieu Othacehe <m.othacehe@gmail.com>");2121MODULE_DESCRIPTION("Vishay VCNL4000 proximity/ambient light sensor driver");2122MODULE_LICENSE("GPL");2123