^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * apds9960.c - Support for Avago APDS9960 gesture/RGB/ALS/proximity sensor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2015, 2018
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Matt Ranostay <matt.ranostay@konsulko.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * TODO: gesture + proximity calib offsets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/iio/iio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/iio/buffer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/iio/events.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/iio/kfifo_buf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/iio/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define APDS9960_REGMAP_NAME "apds9960_regmap"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define APDS9960_DRV_NAME "apds9960"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define APDS9960_REG_RAM_START 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define APDS9960_REG_RAM_END 0x7f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define APDS9960_REG_ENABLE 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define APDS9960_REG_ATIME 0x81
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define APDS9960_REG_WTIME 0x83
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define APDS9960_REG_AILTL 0x84
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define APDS9960_REG_AILTH 0x85
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define APDS9960_REG_AIHTL 0x86
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define APDS9960_REG_AIHTH 0x87
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define APDS9960_REG_PILT 0x89
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define APDS9960_REG_PIHT 0x8b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define APDS9960_REG_PERS 0x8c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define APDS9960_REG_CONFIG_1 0x8d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define APDS9960_REG_PPULSE 0x8e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define APDS9960_REG_CONTROL 0x8f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define APDS9960_REG_CONTROL_AGAIN_MASK 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define APDS9960_REG_CONTROL_PGAIN_MASK 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define APDS9960_REG_CONTROL_AGAIN_MASK_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define APDS9960_REG_CONTROL_PGAIN_MASK_SHIFT 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define APDS9960_REG_CONFIG_2 0x90
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define APDS9960_REG_CONFIG_2_GGAIN_MASK 0x60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define APDS9960_REG_CONFIG_2_GGAIN_MASK_SHIFT 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define APDS9960_REG_ID 0x92
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define APDS9960_REG_STATUS 0x93
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define APDS9960_REG_STATUS_PS_INT BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define APDS9960_REG_STATUS_ALS_INT BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define APDS9960_REG_STATUS_GINT BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define APDS9960_REG_PDATA 0x9c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define APDS9960_REG_POFFSET_UR 0x9d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define APDS9960_REG_POFFSET_DL 0x9e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define APDS9960_REG_CONFIG_3 0x9f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define APDS9960_REG_GPENTH 0xa0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define APDS9960_REG_GEXTH 0xa1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define APDS9960_REG_GCONF_1 0xa2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define APDS9960_REG_GCONF_1_GFIFO_THRES_MASK 0xc0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define APDS9960_REG_GCONF_1_GFIFO_THRES_MASK_SHIFT 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define APDS9960_REG_GCONF_2 0xa3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define APDS9960_REG_GOFFSET_U 0xa4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define APDS9960_REG_GOFFSET_D 0xa5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define APDS9960_REG_GPULSE 0xa6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define APDS9960_REG_GOFFSET_L 0xa7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define APDS9960_REG_GOFFSET_R 0xa9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define APDS9960_REG_GCONF_3 0xaa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define APDS9960_REG_GCONF_4 0xab
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define APDS9960_REG_GFLVL 0xae
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define APDS9960_REG_GSTATUS 0xaf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define APDS9960_REG_IFORCE 0xe4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define APDS9960_REG_PICLEAR 0xe5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define APDS9960_REG_CICLEAR 0xe6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define APDS9960_REG_AICLEAR 0xe7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define APDS9960_DEFAULT_PERS 0x33
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define APDS9960_DEFAULT_GPENTH 0x50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define APDS9960_DEFAULT_GEXTH 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define APDS9960_MAX_PXS_THRES_VAL 255
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define APDS9960_MAX_ALS_THRES_VAL 0xffff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define APDS9960_MAX_INT_TIME_IN_US 1000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) enum apds9960_als_channel_idx {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) IDX_ALS_CLEAR, IDX_ALS_RED, IDX_ALS_GREEN, IDX_ALS_BLUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define APDS9960_REG_ALS_BASE 0x94
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define APDS9960_REG_ALS_CHANNEL(_colour) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) (APDS9960_REG_ALS_BASE + (IDX_ALS_##_colour * 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) enum apds9960_gesture_channel_idx {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) IDX_DIR_UP, IDX_DIR_DOWN, IDX_DIR_LEFT, IDX_DIR_RIGHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define APDS9960_REG_GFIFO_BASE 0xfc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define APDS9960_REG_GFIFO_DIR(_dir) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) (APDS9960_REG_GFIFO_BASE + IDX_DIR_##_dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct apds9960_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct iio_dev *indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /* regmap fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct regmap_field *reg_int_als;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct regmap_field *reg_int_ges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct regmap_field *reg_int_pxs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) struct regmap_field *reg_enable_als;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct regmap_field *reg_enable_ges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct regmap_field *reg_enable_pxs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /* state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) int als_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) int pxs_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) int gesture_mode_running;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /* gain values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) int als_gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) int pxs_gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /* integration time value in us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int als_adc_int_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* gesture buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) u8 buffer[4]; /* 4 8-bit channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static const struct reg_default apds9960_reg_defaults[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* Default ALS integration time = 2.48ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) { APDS9960_REG_ATIME, 0xff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static const struct regmap_range apds9960_volatile_ranges[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) regmap_reg_range(APDS9960_REG_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) APDS9960_REG_PDATA),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) regmap_reg_range(APDS9960_REG_GFLVL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) APDS9960_REG_GSTATUS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) regmap_reg_range(APDS9960_REG_GFIFO_DIR(UP),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) APDS9960_REG_GFIFO_DIR(RIGHT)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) regmap_reg_range(APDS9960_REG_IFORCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) APDS9960_REG_AICLEAR),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static const struct regmap_access_table apds9960_volatile_table = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) .yes_ranges = apds9960_volatile_ranges,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) .n_yes_ranges = ARRAY_SIZE(apds9960_volatile_ranges),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static const struct regmap_range apds9960_precious_ranges[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) regmap_reg_range(APDS9960_REG_RAM_START, APDS9960_REG_RAM_END),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static const struct regmap_access_table apds9960_precious_table = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .yes_ranges = apds9960_precious_ranges,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .n_yes_ranges = ARRAY_SIZE(apds9960_precious_ranges),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) static const struct regmap_range apds9960_readable_ranges[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) regmap_reg_range(APDS9960_REG_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) APDS9960_REG_GSTATUS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) regmap_reg_range(APDS9960_REG_GFIFO_DIR(UP),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) APDS9960_REG_GFIFO_DIR(RIGHT)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static const struct regmap_access_table apds9960_readable_table = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) .yes_ranges = apds9960_readable_ranges,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .n_yes_ranges = ARRAY_SIZE(apds9960_readable_ranges),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static const struct regmap_range apds9960_writeable_ranges[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) regmap_reg_range(APDS9960_REG_ENABLE, APDS9960_REG_CONFIG_2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) regmap_reg_range(APDS9960_REG_POFFSET_UR, APDS9960_REG_GCONF_4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) regmap_reg_range(APDS9960_REG_IFORCE, APDS9960_REG_AICLEAR),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static const struct regmap_access_table apds9960_writeable_table = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) .yes_ranges = apds9960_writeable_ranges,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) .n_yes_ranges = ARRAY_SIZE(apds9960_writeable_ranges),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static const struct regmap_config apds9960_regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) .name = APDS9960_REGMAP_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) .use_single_read = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) .use_single_write = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) .volatile_table = &apds9960_volatile_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) .precious_table = &apds9960_precious_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) .rd_table = &apds9960_readable_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .wr_table = &apds9960_writeable_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .reg_defaults = apds9960_reg_defaults,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) .num_reg_defaults = ARRAY_SIZE(apds9960_reg_defaults),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) .max_register = APDS9960_REG_GFIFO_DIR(RIGHT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) .cache_type = REGCACHE_RBTREE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static const struct iio_event_spec apds9960_pxs_event_spec[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) .type = IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) .dir = IIO_EV_DIR_RISING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) .mask_separate = BIT(IIO_EV_INFO_VALUE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) BIT(IIO_EV_INFO_ENABLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) .type = IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) .dir = IIO_EV_DIR_FALLING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) .mask_separate = BIT(IIO_EV_INFO_VALUE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) BIT(IIO_EV_INFO_ENABLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) static const struct iio_event_spec apds9960_als_event_spec[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) .type = IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) .dir = IIO_EV_DIR_RISING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) .mask_separate = BIT(IIO_EV_INFO_VALUE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) BIT(IIO_EV_INFO_ENABLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .type = IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) .dir = IIO_EV_DIR_FALLING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) .mask_separate = BIT(IIO_EV_INFO_VALUE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) BIT(IIO_EV_INFO_ENABLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) #define APDS9960_GESTURE_CHANNEL(_dir, _si) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) .type = IIO_PROXIMITY, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) .channel = _si + 1, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) .scan_index = _si, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) .indexed = 1, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) .scan_type = { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) .sign = 'u', \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) .realbits = 8, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) .storagebits = 8, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) #define APDS9960_INTENSITY_CHANNEL(_colour) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) .type = IIO_INTENSITY, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) BIT(IIO_CHAN_INFO_INT_TIME), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) .channel2 = IIO_MOD_LIGHT_##_colour, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) .address = APDS9960_REG_ALS_CHANNEL(_colour), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) .modified = 1, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) .scan_index = -1, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) static const unsigned long apds9960_scan_masks[] = {0xf, 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static const struct iio_chan_spec apds9960_channels[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) .type = IIO_PROXIMITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) .address = APDS9960_REG_PDATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) .channel = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) .indexed = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) .scan_index = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) .event_spec = apds9960_pxs_event_spec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) .num_event_specs = ARRAY_SIZE(apds9960_pxs_event_spec),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /* Gesture Sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) APDS9960_GESTURE_CHANNEL(UP, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) APDS9960_GESTURE_CHANNEL(DOWN, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) APDS9960_GESTURE_CHANNEL(LEFT, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) APDS9960_GESTURE_CHANNEL(RIGHT, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) /* ALS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) .type = IIO_INTENSITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) BIT(IIO_CHAN_INFO_INT_TIME),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) .channel2 = IIO_MOD_LIGHT_CLEAR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) .address = APDS9960_REG_ALS_CHANNEL(CLEAR),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) .modified = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) .scan_index = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) .event_spec = apds9960_als_event_spec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) .num_event_specs = ARRAY_SIZE(apds9960_als_event_spec),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /* RGB Sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) APDS9960_INTENSITY_CHANNEL(RED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) APDS9960_INTENSITY_CHANNEL(GREEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) APDS9960_INTENSITY_CHANNEL(BLUE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /* integration time in us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static const int apds9960_int_time[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) { 28000, 246},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {100000, 219},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {200000, 182},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {700000, 0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) /* gain mapping */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static const int apds9960_pxs_gain_map[] = {1, 2, 4, 8};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static const int apds9960_als_gain_map[] = {1, 4, 16, 64};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static IIO_CONST_ATTR(proximity_scale_available, "1 2 4 8");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) static IIO_CONST_ATTR(intensity_scale_available, "1 4 16 64");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) static IIO_CONST_ATTR_INT_TIME_AVAIL("0.028 0.1 0.2 0.7");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) static struct attribute *apds9960_attributes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) &iio_const_attr_proximity_scale_available.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) &iio_const_attr_intensity_scale_available.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) &iio_const_attr_integration_time_available.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) static const struct attribute_group apds9960_attribute_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) .attrs = apds9960_attributes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) static const struct reg_field apds9960_reg_field_int_als =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) REG_FIELD(APDS9960_REG_ENABLE, 4, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) static const struct reg_field apds9960_reg_field_int_ges =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) REG_FIELD(APDS9960_REG_GCONF_4, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static const struct reg_field apds9960_reg_field_int_pxs =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) REG_FIELD(APDS9960_REG_ENABLE, 5, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) static const struct reg_field apds9960_reg_field_enable_als =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) REG_FIELD(APDS9960_REG_ENABLE, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) static const struct reg_field apds9960_reg_field_enable_ges =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) REG_FIELD(APDS9960_REG_ENABLE, 6, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static const struct reg_field apds9960_reg_field_enable_pxs =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) REG_FIELD(APDS9960_REG_ENABLE, 2, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) static int apds9960_set_it_time(struct apds9960_data *data, int val2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) for (idx = 0; idx < ARRAY_SIZE(apds9960_int_time); idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (apds9960_int_time[idx][0] == val2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) ret = regmap_write(data->regmap, APDS9960_REG_ATIME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) apds9960_int_time[idx][1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) data->als_adc_int_us = val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) static int apds9960_set_pxs_gain(struct apds9960_data *data, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) for (idx = 0; idx < ARRAY_SIZE(apds9960_pxs_gain_map); idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (apds9960_pxs_gain_map[idx] == val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /* pxs + gesture gains are mirrored */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) ret = regmap_update_bits(data->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) APDS9960_REG_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) APDS9960_REG_CONTROL_PGAIN_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) idx << APDS9960_REG_CONTROL_PGAIN_MASK_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) ret = regmap_update_bits(data->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) APDS9960_REG_CONFIG_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) APDS9960_REG_CONFIG_2_GGAIN_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) idx << APDS9960_REG_CONFIG_2_GGAIN_MASK_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) data->pxs_gain = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static int apds9960_set_als_gain(struct apds9960_data *data, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) for (idx = 0; idx < ARRAY_SIZE(apds9960_als_gain_map); idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (apds9960_als_gain_map[idx] == val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) ret = regmap_update_bits(data->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) APDS9960_REG_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) APDS9960_REG_CONTROL_AGAIN_MASK, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) data->als_gain = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) static int apds9960_set_power_state(struct apds9960_data *data, bool on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) struct device *dev = &data->client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) int suspended;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) suspended = pm_runtime_suspended(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) ret = pm_runtime_get_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) /* Allow one integration cycle before allowing a reading */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (suspended)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) usleep_range(data->als_adc_int_us,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) APDS9960_MAX_INT_TIME_IN_US);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) pm_runtime_mark_last_busy(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) ret = pm_runtime_put_autosuspend(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static int apds9960_set_power_state(struct apds9960_data *data, bool on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) static int apds9960_read_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) struct iio_chan_spec const *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) int *val, int *val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) struct apds9960_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) __le16 buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (data->gesture_mode_running)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) case IIO_CHAN_INFO_RAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) apds9960_set_power_state(data, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) switch (chan->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) case IIO_PROXIMITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) ret = regmap_read(data->regmap, chan->address, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) ret = IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) case IIO_INTENSITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) ret = regmap_bulk_read(data->regmap, chan->address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) &buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) ret = IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) *val = le16_to_cpu(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) apds9960_set_power_state(data, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) case IIO_CHAN_INFO_INT_TIME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) /* RGB + ALS sensors only have integration time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) switch (chan->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) case IIO_INTENSITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) *val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) *val2 = data->als_adc_int_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) ret = IIO_VAL_INT_PLUS_MICRO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) case IIO_CHAN_INFO_SCALE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) switch (chan->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) case IIO_PROXIMITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) *val = apds9960_pxs_gain_map[data->pxs_gain];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) ret = IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) case IIO_INTENSITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) *val = apds9960_als_gain_map[data->als_gain];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) ret = IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) static int apds9960_write_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) struct iio_chan_spec const *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) int val, int val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) struct apds9960_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) case IIO_CHAN_INFO_INT_TIME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) /* RGB + ALS sensors only have int time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) switch (chan->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) case IIO_INTENSITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (val != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return apds9960_set_it_time(data, val2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) case IIO_CHAN_INFO_SCALE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (val2 != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) switch (chan->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) case IIO_PROXIMITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) return apds9960_set_pxs_gain(data, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) case IIO_INTENSITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) return apds9960_set_als_gain(data, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) static inline int apds9960_get_thres_reg(const struct iio_chan_spec *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) enum iio_event_direction dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) u8 *reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) switch (dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) case IIO_EV_DIR_RISING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) switch (chan->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) case IIO_PROXIMITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) *reg = APDS9960_REG_PIHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) case IIO_INTENSITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) *reg = APDS9960_REG_AIHTL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) case IIO_EV_DIR_FALLING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) switch (chan->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) case IIO_PROXIMITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) *reg = APDS9960_REG_PILT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) case IIO_INTENSITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) *reg = APDS9960_REG_AILTL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) static int apds9960_read_event(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) const struct iio_chan_spec *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) enum iio_event_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) enum iio_event_direction dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) enum iio_event_info info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) int *val, int *val2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) __le16 buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) struct apds9960_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (info != IIO_EV_INFO_VALUE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) ret = apds9960_get_thres_reg(chan, dir, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (chan->type == IIO_PROXIMITY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) ret = regmap_read(data->regmap, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) } else if (chan->type == IIO_INTENSITY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) ret = regmap_bulk_read(data->regmap, reg, &buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) *val = le16_to_cpu(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) *val2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) static int apds9960_write_event(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) const struct iio_chan_spec *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) enum iio_event_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) enum iio_event_direction dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) enum iio_event_info info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) int val, int val2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) __le16 buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) struct apds9960_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (info != IIO_EV_INFO_VALUE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) ret = apds9960_get_thres_reg(chan, dir, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) if (chan->type == IIO_PROXIMITY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (val < 0 || val > APDS9960_MAX_PXS_THRES_VAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) ret = regmap_write(data->regmap, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) } else if (chan->type == IIO_INTENSITY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if (val < 0 || val > APDS9960_MAX_ALS_THRES_VAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) buf = cpu_to_le16(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) ret = regmap_bulk_write(data->regmap, reg, &buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) static int apds9960_read_event_config(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) const struct iio_chan_spec *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) enum iio_event_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) enum iio_event_direction dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) struct apds9960_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) switch (chan->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) case IIO_PROXIMITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) return data->pxs_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) case IIO_INTENSITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return data->als_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) static int apds9960_write_event_config(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) const struct iio_chan_spec *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) enum iio_event_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) enum iio_event_direction dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) struct apds9960_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) state = !!state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) switch (chan->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) case IIO_PROXIMITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (data->pxs_int == state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) ret = regmap_field_write(data->reg_int_pxs, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) data->pxs_int = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) apds9960_set_power_state(data, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) case IIO_INTENSITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (data->als_int == state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) ret = regmap_field_write(data->reg_int_als, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) data->als_int = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) apds9960_set_power_state(data, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) static const struct iio_info apds9960_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) .attrs = &apds9960_attribute_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) .read_raw = apds9960_read_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) .write_raw = apds9960_write_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) .read_event_value = apds9960_read_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) .write_event_value = apds9960_write_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) .read_event_config = apds9960_read_event_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) .write_event_config = apds9960_write_event_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) static inline int apds9660_fifo_is_empty(struct apds9960_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) int cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) ret = regmap_read(data->regmap, APDS9960_REG_GFLVL, &cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) return cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) static void apds9960_read_gesture_fifo(struct apds9960_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) int ret, cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) data->gesture_mode_running = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) while (cnt || (cnt = apds9660_fifo_is_empty(data) > 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) ret = regmap_bulk_read(data->regmap, APDS9960_REG_GFIFO_BASE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) &data->buffer, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) goto err_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) iio_push_to_buffers(data->indio_dev, data->buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) cnt--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) err_read:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) data->gesture_mode_running = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) static irqreturn_t apds9960_interrupt_handler(int irq, void *private)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) struct iio_dev *indio_dev = private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) struct apds9960_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) int ret, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) ret = regmap_read(data->regmap, APDS9960_REG_STATUS, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) dev_err(&data->client->dev, "irq status reg read failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if ((status & APDS9960_REG_STATUS_ALS_INT) && data->als_int) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) iio_push_event(indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) IIO_UNMOD_EVENT_CODE(IIO_INTENSITY, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) IIO_EV_DIR_EITHER),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) iio_get_time_ns(indio_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) regmap_write(data->regmap, APDS9960_REG_CICLEAR, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if ((status & APDS9960_REG_STATUS_PS_INT) && data->pxs_int) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) iio_push_event(indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) IIO_EV_DIR_EITHER),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) iio_get_time_ns(indio_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) regmap_write(data->regmap, APDS9960_REG_PICLEAR, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (status & APDS9960_REG_STATUS_GINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) apds9960_read_gesture_fifo(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) static int apds9960_set_powermode(struct apds9960_data *data, bool state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) return regmap_update_bits(data->regmap, APDS9960_REG_ENABLE, 1, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) static int apds9960_buffer_postenable(struct iio_dev *indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) struct apds9960_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) ret = regmap_field_write(data->reg_int_ges, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) ret = regmap_field_write(data->reg_enable_ges, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) pm_runtime_get_sync(&data->client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) static int apds9960_buffer_predisable(struct iio_dev *indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) struct apds9960_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) ret = regmap_field_write(data->reg_enable_ges, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) ret = regmap_field_write(data->reg_int_ges, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) pm_runtime_put_autosuspend(&data->client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) static const struct iio_buffer_setup_ops apds9960_buffer_setup_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) .postenable = apds9960_buffer_postenable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) .predisable = apds9960_buffer_predisable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) static int apds9960_regfield_init(struct apds9960_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) struct device *dev = &data->client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) struct regmap *regmap = data->regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) data->reg_int_als = devm_regmap_field_alloc(dev, regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) apds9960_reg_field_int_als);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (IS_ERR(data->reg_int_als)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) dev_err(dev, "INT ALS reg field init failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) return PTR_ERR(data->reg_int_als);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) data->reg_int_ges = devm_regmap_field_alloc(dev, regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) apds9960_reg_field_int_ges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) if (IS_ERR(data->reg_int_ges)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) dev_err(dev, "INT gesture reg field init failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) return PTR_ERR(data->reg_int_ges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) data->reg_int_pxs = devm_regmap_field_alloc(dev, regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) apds9960_reg_field_int_pxs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) if (IS_ERR(data->reg_int_pxs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) dev_err(dev, "INT pxs reg field init failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) return PTR_ERR(data->reg_int_pxs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) data->reg_enable_als = devm_regmap_field_alloc(dev, regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) apds9960_reg_field_enable_als);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) if (IS_ERR(data->reg_enable_als)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) dev_err(dev, "Enable ALS reg field init failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return PTR_ERR(data->reg_enable_als);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) data->reg_enable_ges = devm_regmap_field_alloc(dev, regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) apds9960_reg_field_enable_ges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) if (IS_ERR(data->reg_enable_ges)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) dev_err(dev, "Enable gesture reg field init failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) return PTR_ERR(data->reg_enable_ges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) data->reg_enable_pxs = devm_regmap_field_alloc(dev, regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) apds9960_reg_field_enable_pxs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) if (IS_ERR(data->reg_enable_pxs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) dev_err(dev, "Enable PXS reg field init failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) return PTR_ERR(data->reg_enable_pxs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) static int apds9960_chip_init(struct apds9960_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) /* Default IT for ALS of 28 ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) ret = apds9960_set_it_time(data, 28000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) /* Ensure gesture interrupt is OFF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) ret = regmap_field_write(data->reg_int_ges, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) /* Disable gesture sensor, since polling is useless from user-space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) ret = regmap_field_write(data->reg_enable_ges, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) /* Ensure proximity interrupt is OFF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) ret = regmap_field_write(data->reg_int_pxs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) /* Enable proximity sensor for polling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) ret = regmap_field_write(data->reg_enable_pxs, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) /* Ensure ALS interrupt is OFF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) ret = regmap_field_write(data->reg_int_als, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) /* Enable ALS sensor for polling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) ret = regmap_field_write(data->reg_enable_als, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) * When enabled trigger an interrupt after 3 readings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) * outside threshold for ALS + PXS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) ret = regmap_write(data->regmap, APDS9960_REG_PERS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) APDS9960_DEFAULT_PERS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) * Wait for 4 event outside gesture threshold to prevent interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) * flooding.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) ret = regmap_update_bits(data->regmap, APDS9960_REG_GCONF_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) APDS9960_REG_GCONF_1_GFIFO_THRES_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) BIT(0) << APDS9960_REG_GCONF_1_GFIFO_THRES_MASK_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) /* Default ENTER and EXIT thresholds for the GESTURE engine. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) ret = regmap_write(data->regmap, APDS9960_REG_GPENTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) APDS9960_DEFAULT_GPENTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) ret = regmap_write(data->regmap, APDS9960_REG_GEXTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) APDS9960_DEFAULT_GEXTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) return apds9960_set_powermode(data, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) static int apds9960_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) struct apds9960_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) struct iio_buffer *buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) struct iio_dev *indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) if (!indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) buffer = devm_iio_kfifo_allocate(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) if (!buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) iio_device_attach_buffer(indio_dev, buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) indio_dev->info = &apds9960_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) indio_dev->name = APDS9960_DRV_NAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) indio_dev->channels = apds9960_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) indio_dev->num_channels = ARRAY_SIZE(apds9960_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) indio_dev->available_scan_masks = apds9960_scan_masks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) indio_dev->setup_ops = &apds9960_buffer_setup_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) i2c_set_clientdata(client, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) data->regmap = devm_regmap_init_i2c(client, &apds9960_regmap_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) if (IS_ERR(data->regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) dev_err(&client->dev, "regmap initialization failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) return PTR_ERR(data->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) data->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) data->indio_dev = indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) mutex_init(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) ret = pm_runtime_set_active(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) goto error_power_down;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) pm_runtime_enable(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) pm_runtime_set_autosuspend_delay(&client->dev, 5000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) pm_runtime_use_autosuspend(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) apds9960_set_power_state(data, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) ret = apds9960_regfield_init(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) goto error_power_down;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) ret = apds9960_chip_init(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) goto error_power_down;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if (client->irq <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) dev_err(&client->dev, "no valid irq defined\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) goto error_power_down;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) ret = devm_request_threaded_irq(&client->dev, client->irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) NULL, apds9960_interrupt_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) "apds9960_event",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) dev_err(&client->dev, "request irq (%d) failed\n", client->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) goto error_power_down;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) ret = iio_device_register(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) goto error_power_down;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) apds9960_set_power_state(data, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) error_power_down:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) apds9960_set_power_state(data, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) static int apds9960_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) struct iio_dev *indio_dev = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) struct apds9960_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) iio_device_unregister(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) pm_runtime_disable(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) pm_runtime_set_suspended(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) apds9960_set_powermode(data, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) static int apds9960_runtime_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) struct apds9960_data *data =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) return apds9960_set_powermode(data, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) static int apds9960_runtime_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) struct apds9960_data *data =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) return apds9960_set_powermode(data, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) static const struct dev_pm_ops apds9960_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) pm_runtime_force_resume)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) SET_RUNTIME_PM_OPS(apds9960_runtime_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) apds9960_runtime_resume, NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) static const struct i2c_device_id apds9960_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) { "apds9960", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) MODULE_DEVICE_TABLE(i2c, apds9960_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) static const struct of_device_id apds9960_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) { .compatible = "avago,apds9960" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) MODULE_DEVICE_TABLE(of, apds9960_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) static struct i2c_driver apds9960_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) .name = APDS9960_DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) .of_match_table = apds9960_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) .pm = &apds9960_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) .probe = apds9960_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) .remove = apds9960_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) .id_table = apds9960_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) module_i2c_driver(apds9960_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) MODULE_DESCRIPTION("APDS9960 Gesture/RGB/ALS/Proximity sensor");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) MODULE_LICENSE("GPL");