Lines Matching +full:proximity +full:- +full:near +full:- +full:level

1 // SPDX-License-Identifier: GPL-2.0-only
3 * vcnl4000.c - Support for Vishay VCNL4000/4010/4020/4040/4200 combined ambient
4 * light and proximity sensor
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)
43 #define VCNL4010_PROX_RATE 0x82 /* Proximity rate */
44 #define VCNL4000_LED_CURRENT 0x83 /* IR LED current for proximity mode */
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 */
53 #define VCNL4000_PS_MOD_ADJ 0x8a /* Proximity modulator timing adjustment */
61 #define VCNL4200_PS_CONF1 0x03 /* Proximity configuration */
62 #define VCNL4200_PS_DATA 0x08 /* Proximity data */
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 */
74 #define VCNL4000_PROX_EN BIT(1) /* start proximity measurement */
75 #define VCNL4000_SELF_TIMED_EN BIT(0) /* start self-timed measurement */
81 #define VCNL4010_INT_PROX_EN BIT(3) /* Enable on proximity data ready */
86 #define VCNL4010_INT_PROXIMITY 3 /* Proximity data ready */
164 ret = i2c_smbus_read_byte_data(data->client, VCNL4000_PROD_REV); in vcnl4000_init()
171 if (data->id != VCNL4000) in vcnl4000_init()
172 dev_warn(&data->client->dev, in vcnl4000_init()
176 if (data->id != VCNL4010) in vcnl4000_init()
177 dev_warn(&data->client->dev, in vcnl4000_init()
181 return -ENODEV; in vcnl4000_init()
184 data->rev = ret & 0xf; in vcnl4000_init()
185 data->al_scale = 250000; in vcnl4000_init()
186 mutex_init(&data->vcnl4000_lock); in vcnl4000_init()
188 return data->chip_spec->set_power_state(data, true); in vcnl4000_init()
196 ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF, val); in vcnl4200_set_power_state()
200 ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1, val); in vcnl4200_set_power_state()
206 data->vcnl4200_al.last_measurement = ktime_get(); in vcnl4200_set_power_state()
207 data->vcnl4200_ps.last_measurement = ktime_get(); in vcnl4200_set_power_state()
217 ret = i2c_smbus_read_word_data(data->client, VCNL4200_DEV_ID); in vcnl4200_init()
224 ret = i2c_smbus_read_word_data(data->client, VCNL4040_DEV_ID); in vcnl4200_init()
231 return -ENODEV; in vcnl4200_init()
234 dev_dbg(&data->client->dev, "device id 0x%x", id); in vcnl4200_init()
236 data->rev = (ret >> 8) & 0xf; in vcnl4200_init()
238 data->vcnl4200_al.reg = VCNL4200_AL_DATA; in vcnl4200_init()
239 data->vcnl4200_ps.reg = VCNL4200_PS_DATA; in vcnl4200_init()
243 data->vcnl4200_al.sampling_rate = ktime_set(0, 60000 * 1000); in vcnl4200_init()
245 data->vcnl4200_ps.sampling_rate = ktime_set(0, 5760 * 1000); in vcnl4200_init()
246 data->al_scale = 24000; in vcnl4200_init()
250 data->vcnl4200_al.sampling_rate = ktime_set(0, 96000 * 1000); in vcnl4200_init()
252 data->vcnl4200_ps.sampling_rate = ktime_set(0, 6000 * 1000); in vcnl4200_init()
253 data->al_scale = 120000; in vcnl4200_init()
256 mutex_init(&data->vcnl4200_al.lock); in vcnl4200_init()
257 mutex_init(&data->vcnl4200_ps.lock); in vcnl4200_init()
259 ret = data->chip_spec->set_power_state(data, true); in vcnl4200_init()
270 ret = i2c_smbus_read_word_swapped(data->client, data_reg); in vcnl4000_read_data()
281 return -ERANGE; in vcnl4000_write_data()
283 return i2c_smbus_write_word_swapped(data->client, data_reg, val); in vcnl4000_write_data()
293 mutex_lock(&data->vcnl4000_lock); in vcnl4000_measure()
295 ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, in vcnl4000_measure()
301 while (tries--) { in vcnl4000_measure()
302 ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND); in vcnl4000_measure()
311 dev_err(&data->client->dev, in vcnl4000_measure()
313 ret = -EIO; in vcnl4000_measure()
321 mutex_unlock(&data->vcnl4000_lock); in vcnl4000_measure()
326 mutex_unlock(&data->vcnl4000_lock); in vcnl4000_measure()
337 mutex_lock(&chan->lock); in vcnl4200_measure()
339 next_measurement = ktime_add(chan->last_measurement, in vcnl4200_measure()
340 chan->sampling_rate); in vcnl4200_measure()
344 chan->last_measurement = ktime_get(); in vcnl4200_measure()
346 mutex_unlock(&chan->lock); in vcnl4200_measure()
348 ret = i2c_smbus_read_word_data(data->client, chan->reg); in vcnl4200_measure()
366 return vcnl4200_measure(data, &data->vcnl4200_al, val); in vcnl4200_measure_light()
378 return vcnl4200_measure(data, &data->vcnl4200_ps, val); in vcnl4200_measure_proximity()
386 ret = i2c_smbus_read_byte_data(data->client, VCNL4010_PROX_RATE); in vcnl4010_read_proxy_samp_freq()
391 return -EINVAL; in vcnl4010_read_proxy_samp_freq()
403 ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND); in vcnl4010_is_in_periodic_mode()
412 struct device *dev = &data->client->dev; in vcnl4000_set_pm_runtime_state()
440 switch (chan->type) { in vcnl4000_read_raw()
442 ret = data->chip_spec->measure_light(data, val); in vcnl4000_read_raw()
447 ret = data->chip_spec->measure_proximity(data, val); in vcnl4000_read_raw()
452 ret = -EINVAL; in vcnl4000_read_raw()
457 if (chan->type != IIO_LIGHT) in vcnl4000_read_raw()
458 return -EINVAL; in vcnl4000_read_raw()
461 *val2 = data->al_scale; in vcnl4000_read_raw()
464 return -EINVAL; in vcnl4000_read_raw()
484 ret = -EBUSY; in vcnl4010_read_raw()
493 switch (chan->type) { in vcnl4010_read_raw()
500 return -EINVAL; in vcnl4010_read_raw()
503 return -EINVAL; in vcnl4010_read_raw()
519 return -EINVAL; in vcnl4010_read_avail()
527 int index = -1; in vcnl4010_write_proxy_samp_freq()
538 return -EINVAL; in vcnl4010_write_proxy_samp_freq()
540 return i2c_smbus_write_byte_data(data->client, VCNL4010_PROX_RATE, in vcnl4010_write_proxy_samp_freq()
557 ret = -EBUSY; in vcnl4010_write_raw()
563 switch (chan->type) { in vcnl4010_write_raw()
568 ret = -EINVAL; in vcnl4010_write_raw()
572 ret = -EINVAL; in vcnl4010_write_raw()
607 return -EINVAL; in vcnl4010_read_event()
610 return -EINVAL; in vcnl4010_read_event()
640 return -EINVAL; in vcnl4010_write_event()
643 return -EINVAL; in vcnl4010_write_event()
651 ret = i2c_smbus_read_byte_data(data->client, VCNL4010_INT_CTRL); in vcnl4010_is_thr_enabled()
665 switch (chan->type) { in vcnl4010_read_event_config()
669 return -EINVAL; in vcnl4010_read_event_config()
685 /* Enable periodic measurement of proximity data. */ in vcnl4010_config_threshold()
689 * Enable interrupts on threshold, for proximity data by in vcnl4010_config_threshold()
701 ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, in vcnl4010_config_threshold()
706 ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, icr); in vcnl4010_config_threshold()
721 switch (chan->type) { in vcnl4010_write_event_config()
725 return -EINVAL; in vcnl4010_write_event_config()
736 return sprintf(buf, "%u\n", data->near_level); in vcnl4000_read_near_level()
779 .scan_index = -1,
869 ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR); in vcnl4010_irq_thread()
896 i2c_smbus_write_byte_data(data->client, VCNL4010_ISR, in vcnl4010_irq_thread()
901 iio_trigger_poll_chained(indio_dev->trig); in vcnl4010_irq_thread()
910 struct iio_dev *indio_dev = pf->indio_dev; in vcnl4010_trigger_handler()
912 const unsigned long *active_scan_mask = indio_dev->active_scan_mask; in vcnl4010_trigger_handler()
913 u16 buffer[8] = {0}; /* 1x16-bit + ts */ in vcnl4010_trigger_handler()
919 ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR); in vcnl4010_trigger_handler()
938 ret = i2c_smbus_write_byte_data(data->client, VCNL4010_ISR, in vcnl4010_trigger_handler()
950 iio_trigger_notify_done(indio_dev->trig); in vcnl4010_trigger_handler()
962 return -EBUSY; in vcnl4010_buffer_postenable()
964 ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, in vcnl4010_buffer_postenable()
970 return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, cmd); in vcnl4010_buffer_postenable()
978 ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, 0); in vcnl4010_buffer_predisable()
982 return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 0); in vcnl4010_buffer_predisable()
997 struct i2c_client *client = data->client; in vcnl4010_probe_trigger()
1000 trigger = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", in vcnl4010_probe_trigger()
1001 indio_dev->name, indio_dev->id); in vcnl4010_probe_trigger()
1003 return -ENOMEM; in vcnl4010_probe_trigger()
1005 trigger->dev.parent = &client->dev; in vcnl4010_probe_trigger()
1006 trigger->ops = &vcnl4010_trigger_ops; in vcnl4010_probe_trigger()
1009 return devm_iio_trigger_register(&client->dev, trigger); in vcnl4010_probe_trigger()
1019 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); in vcnl4000_probe()
1021 return -ENOMEM; in vcnl4000_probe()
1025 data->client = client; in vcnl4000_probe()
1026 data->id = id->driver_data; in vcnl4000_probe()
1027 data->chip_spec = &vcnl4000_chip_spec_cfg[data->id]; in vcnl4000_probe()
1029 ret = data->chip_spec->init(data); in vcnl4000_probe()
1033 dev_dbg(&client->dev, "%s Ambient light/proximity sensor, Rev: %02x\n", in vcnl4000_probe()
1034 data->chip_spec->prod, data->rev); in vcnl4000_probe()
1036 if (device_property_read_u32(&client->dev, "proximity-near-level", in vcnl4000_probe()
1037 &data->near_level)) in vcnl4000_probe()
1038 data->near_level = 0; in vcnl4000_probe()
1040 indio_dev->info = data->chip_spec->info; in vcnl4000_probe()
1041 indio_dev->channels = data->chip_spec->channels; in vcnl4000_probe()
1042 indio_dev->num_channels = data->chip_spec->num_channels; in vcnl4000_probe()
1043 indio_dev->name = VCNL4000_DRV_NAME; in vcnl4000_probe()
1044 indio_dev->modes = INDIO_DIRECT_MODE; in vcnl4000_probe()
1046 if (client->irq && data->chip_spec->irq_support) { in vcnl4000_probe()
1047 ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, in vcnl4000_probe()
1052 dev_err(&client->dev, in vcnl4000_probe()
1057 ret = devm_request_threaded_irq(&client->dev, client->irq, in vcnl4000_probe()
1064 dev_err(&client->dev, "irq request failed\n"); in vcnl4000_probe()
1073 ret = pm_runtime_set_active(&client->dev); in vcnl4000_probe()
1081 pm_runtime_enable(&client->dev); in vcnl4000_probe()
1082 pm_runtime_set_autosuspend_delay(&client->dev, VCNL4000_SLEEP_DELAY_MS); in vcnl4000_probe()
1083 pm_runtime_use_autosuspend(&client->dev); in vcnl4000_probe()
1087 data->chip_spec->set_power_state(data, false); in vcnl4000_probe()
1121 pm_runtime_dont_use_autosuspend(&client->dev); in vcnl4000_remove()
1122 pm_runtime_disable(&client->dev); in vcnl4000_remove()
1124 pm_runtime_set_suspended(&client->dev); in vcnl4000_remove()
1126 return data->chip_spec->set_power_state(data, false); in vcnl4000_remove()
1134 return data->chip_spec->set_power_state(data, false); in vcnl4000_runtime_suspend()
1142 return data->chip_spec->set_power_state(data, true); in vcnl4000_runtime_resume()
1167 MODULE_DESCRIPTION("Vishay VCNL4000 proximity/ambient light sensor driver");