^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2013 Samsung Electronics Co., Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * IIO features supported by the driver:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Read-only raw channels:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * - illuminance_clear [lux]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * - illuminance_ir
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * - proximity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Triggered buffer:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * - illuminance_clear
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * - illuminance_ir
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * - proximity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Events:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * - illuminance_clear (rising and falling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * - proximity (rising and falling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * - both falling and rising thresholds for the proximity events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * must be set to the values greater than 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * The driver supports triggered buffers for all the three
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * channels as well as high and low threshold events for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * illuminance_clear and proxmimity channels. Triggers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * can be enabled simultaneously with both illuminance_clear
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * events. Proximity events cannot be enabled simultaneously
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * with any triggers or illuminance events. Enabling/disabling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * one of the proximity events automatically enables/disables
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * the other one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/irq_work.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/mod_devicetable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/regulator/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <linux/iio/buffer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <linux/iio/events.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <linux/iio/iio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <linux/iio/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <linux/iio/trigger.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include <linux/iio/trigger_consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include <linux/iio/triggered_buffer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define GP2A_I2C_NAME "gp2ap020a00f"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define GP2AP020A00F_OP_REG 0x00 /* Basic operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define GP2AP020A00F_ALS_REG 0x01 /* ALS related settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define GP2AP020A00F_PS_REG 0x02 /* PS related settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define GP2AP020A00F_LED_REG 0x03 /* LED reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define GP2AP020A00F_TL_L_REG 0x04 /* ALS: Threshold low LSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define GP2AP020A00F_TL_H_REG 0x05 /* ALS: Threshold low MSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define GP2AP020A00F_TH_L_REG 0x06 /* ALS: Threshold high LSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define GP2AP020A00F_TH_H_REG 0x07 /* ALS: Threshold high MSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define GP2AP020A00F_PL_L_REG 0x08 /* PS: Threshold low LSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define GP2AP020A00F_PL_H_REG 0x09 /* PS: Threshold low MSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define GP2AP020A00F_PH_L_REG 0x0a /* PS: Threshold high LSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define GP2AP020A00F_PH_H_REG 0x0b /* PS: Threshold high MSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define GP2AP020A00F_D0_L_REG 0x0c /* ALS result: Clear/Illuminance LSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define GP2AP020A00F_D0_H_REG 0x0d /* ALS result: Clear/Illuminance MSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define GP2AP020A00F_D1_L_REG 0x0e /* ALS result: IR LSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define GP2AP020A00F_D1_H_REG 0x0f /* ALS result: IR LSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define GP2AP020A00F_D2_L_REG 0x10 /* PS result LSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define GP2AP020A00F_D2_H_REG 0x11 /* PS result MSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define GP2AP020A00F_NUM_REGS 0x12 /* Number of registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* OP_REG bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define GP2AP020A00F_OP3_MASK 0x80 /* Software shutdown */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define GP2AP020A00F_OP3_SHUTDOWN 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define GP2AP020A00F_OP3_OPERATION 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define GP2AP020A00F_OP2_MASK 0x40 /* Auto shutdown/Continuous mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define GP2AP020A00F_OP2_AUTO_SHUTDOWN 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define GP2AP020A00F_OP2_CONT_OPERATION 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define GP2AP020A00F_OP_MASK 0x30 /* Operating mode selection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define GP2AP020A00F_OP_ALS_AND_PS 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define GP2AP020A00F_OP_ALS 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define GP2AP020A00F_OP_PS 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define GP2AP020A00F_OP_DEBUG 0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define GP2AP020A00F_PROX_MASK 0x08 /* PS: detection/non-detection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define GP2AP020A00F_PROX_NON_DETECT 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define GP2AP020A00F_PROX_DETECT 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define GP2AP020A00F_FLAG_P 0x04 /* PS: interrupt result */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define GP2AP020A00F_FLAG_A 0x02 /* ALS: interrupt result */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define GP2AP020A00F_TYPE_MASK 0x01 /* Output data type selection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define GP2AP020A00F_TYPE_MANUAL_CALC 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define GP2AP020A00F_TYPE_AUTO_CALC 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* ALS_REG bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define GP2AP020A00F_PRST_MASK 0xc0 /* Number of measurement cycles */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define GP2AP020A00F_PRST_ONCE 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define GP2AP020A00F_PRST_4_CYCLES 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define GP2AP020A00F_PRST_8_CYCLES 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define GP2AP020A00F_PRST_16_CYCLES 0xc0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define GP2AP020A00F_RES_A_MASK 0x38 /* ALS: Resolution */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define GP2AP020A00F_RES_A_800ms 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define GP2AP020A00F_RES_A_400ms 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define GP2AP020A00F_RES_A_200ms 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define GP2AP020A00F_RES_A_100ms 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define GP2AP020A00F_RES_A_25ms 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define GP2AP020A00F_RES_A_6_25ms 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define GP2AP020A00F_RES_A_1_56ms 0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define GP2AP020A00F_RES_A_0_39ms 0x38
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define GP2AP020A00F_RANGE_A_MASK 0x07 /* ALS: Max measurable range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define GP2AP020A00F_RANGE_A_x1 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define GP2AP020A00F_RANGE_A_x2 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define GP2AP020A00F_RANGE_A_x4 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define GP2AP020A00F_RANGE_A_x8 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define GP2AP020A00F_RANGE_A_x16 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define GP2AP020A00F_RANGE_A_x32 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define GP2AP020A00F_RANGE_A_x64 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #define GP2AP020A00F_RANGE_A_x128 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /* PS_REG bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define GP2AP020A00F_ALC_MASK 0x80 /* Auto light cancel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define GP2AP020A00F_ALC_ON 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define GP2AP020A00F_ALC_OFF 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define GP2AP020A00F_INTTYPE_MASK 0x40 /* Interrupt type setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define GP2AP020A00F_INTTYPE_LEVEL 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define GP2AP020A00F_INTTYPE_PULSE 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define GP2AP020A00F_RES_P_MASK 0x38 /* PS: Resolution */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define GP2AP020A00F_RES_P_800ms_x2 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define GP2AP020A00F_RES_P_400ms_x2 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define GP2AP020A00F_RES_P_200ms_x2 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define GP2AP020A00F_RES_P_100ms_x2 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define GP2AP020A00F_RES_P_25ms_x2 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define GP2AP020A00F_RES_P_6_25ms_x2 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define GP2AP020A00F_RES_P_1_56ms_x2 0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define GP2AP020A00F_RES_P_0_39ms_x2 0x38
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #define GP2AP020A00F_RANGE_P_MASK 0x07 /* PS: Max measurable range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #define GP2AP020A00F_RANGE_P_x1 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #define GP2AP020A00F_RANGE_P_x2 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define GP2AP020A00F_RANGE_P_x4 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define GP2AP020A00F_RANGE_P_x8 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #define GP2AP020A00F_RANGE_P_x16 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define GP2AP020A00F_RANGE_P_x32 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define GP2AP020A00F_RANGE_P_x64 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #define GP2AP020A00F_RANGE_P_x128 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /* LED reg bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define GP2AP020A00F_INTVAL_MASK 0xc0 /* Intermittent operating */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define GP2AP020A00F_INTVAL_0 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #define GP2AP020A00F_INTVAL_4 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #define GP2AP020A00F_INTVAL_8 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define GP2AP020A00F_INTVAL_16 0xc0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #define GP2AP020A00F_IS_MASK 0x30 /* ILED drive peak current */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #define GP2AP020A00F_IS_13_8mA 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #define GP2AP020A00F_IS_27_5mA 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #define GP2AP020A00F_IS_55mA 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #define GP2AP020A00F_IS_110mA 0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #define GP2AP020A00F_PIN_MASK 0x0c /* INT terminal setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #define GP2AP020A00F_PIN_ALS_OR_PS 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #define GP2AP020A00F_PIN_ALS 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #define GP2AP020A00F_PIN_PS 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) #define GP2AP020A00F_PIN_PS_DETECT 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #define GP2AP020A00F_FREQ_MASK 0x02 /* LED modulation frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) #define GP2AP020A00F_FREQ_327_5kHz 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #define GP2AP020A00F_FREQ_81_8kHz 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #define GP2AP020A00F_RST 0x01 /* Software reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #define GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) #define GP2AP020A00F_SCAN_MODE_LIGHT_IR 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #define GP2AP020A00F_SCAN_MODE_PROXIMITY 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #define GP2AP020A00F_CHAN_TIMESTAMP 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) #define GP2AP020A00F_DATA_READY_TIMEOUT msecs_to_jiffies(1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) #define GP2AP020A00F_DATA_REG(chan) (GP2AP020A00F_D0_L_REG + \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) (chan) * 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #define GP2AP020A00F_THRESH_REG(th_val_id) (GP2AP020A00F_TL_L_REG + \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) (th_val_id) * 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #define GP2AP020A00F_THRESH_VAL_ID(reg_addr) ((reg_addr - 4) / 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #define GP2AP020A00F_SUBTRACT_MODE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #define GP2AP020A00F_ADD_MODE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) #define GP2AP020A00F_MAX_CHANNELS 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) enum gp2ap020a00f_opmode {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) GP2AP020A00F_OPMODE_READ_RAW_CLEAR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) GP2AP020A00F_OPMODE_READ_RAW_IR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) GP2AP020A00F_OPMODE_READ_RAW_PROXIMITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) GP2AP020A00F_OPMODE_ALS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) GP2AP020A00F_OPMODE_PS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) GP2AP020A00F_OPMODE_ALS_AND_PS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) GP2AP020A00F_OPMODE_PROX_DETECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) GP2AP020A00F_OPMODE_SHUTDOWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) GP2AP020A00F_NUM_OPMODES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) enum gp2ap020a00f_cmd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) GP2AP020A00F_CMD_READ_RAW_CLEAR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) GP2AP020A00F_CMD_READ_RAW_IR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) GP2AP020A00F_CMD_READ_RAW_PROXIMITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) GP2AP020A00F_CMD_TRIGGER_CLEAR_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) GP2AP020A00F_CMD_TRIGGER_CLEAR_DIS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) GP2AP020A00F_CMD_TRIGGER_IR_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) GP2AP020A00F_CMD_TRIGGER_IR_DIS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) GP2AP020A00F_CMD_TRIGGER_PROX_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) GP2AP020A00F_CMD_TRIGGER_PROX_DIS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) GP2AP020A00F_CMD_ALS_HIGH_EV_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) GP2AP020A00F_CMD_ALS_HIGH_EV_DIS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) GP2AP020A00F_CMD_ALS_LOW_EV_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) GP2AP020A00F_CMD_ALS_LOW_EV_DIS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) GP2AP020A00F_CMD_PROX_HIGH_EV_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) GP2AP020A00F_CMD_PROX_HIGH_EV_DIS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) GP2AP020A00F_CMD_PROX_LOW_EV_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) GP2AP020A00F_CMD_PROX_LOW_EV_DIS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) enum gp2ap020a00f_flags {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) GP2AP020A00F_FLAG_ALS_IR_TRIGGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) GP2AP020A00F_FLAG_PROX_TRIGGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) GP2AP020A00F_FLAG_PROX_RISING_EV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) GP2AP020A00F_FLAG_PROX_FALLING_EV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) GP2AP020A00F_FLAG_ALS_RISING_EV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) GP2AP020A00F_FLAG_ALS_FALLING_EV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) GP2AP020A00F_FLAG_LUX_MODE_HI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) GP2AP020A00F_FLAG_DATA_READY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) enum gp2ap020a00f_thresh_val_id {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) GP2AP020A00F_THRESH_TL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) GP2AP020A00F_THRESH_TH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) GP2AP020A00F_THRESH_PL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) GP2AP020A00F_THRESH_PH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct gp2ap020a00f_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) const struct gp2ap020a00f_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) char *buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) struct regulator *vled_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) enum gp2ap020a00f_opmode cur_opmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct iio_trigger *trig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) unsigned int thresh_val[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) u8 debug_reg_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) struct irq_work work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) wait_queue_head_t data_ready_queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static const u8 gp2ap020a00f_reg_init_tab[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) [GP2AP020A00F_OP_REG] = GP2AP020A00F_OP3_SHUTDOWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) [GP2AP020A00F_ALS_REG] = GP2AP020A00F_RES_A_25ms |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) GP2AP020A00F_RANGE_A_x8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) [GP2AP020A00F_PS_REG] = GP2AP020A00F_ALC_ON |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) GP2AP020A00F_RES_P_1_56ms_x2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) GP2AP020A00F_RANGE_P_x4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) [GP2AP020A00F_LED_REG] = GP2AP020A00F_INTVAL_0 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) GP2AP020A00F_IS_110mA |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) GP2AP020A00F_FREQ_327_5kHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) [GP2AP020A00F_TL_L_REG] = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) [GP2AP020A00F_TL_H_REG] = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) [GP2AP020A00F_TH_L_REG] = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) [GP2AP020A00F_TH_H_REG] = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) [GP2AP020A00F_PL_L_REG] = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) [GP2AP020A00F_PL_H_REG] = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) [GP2AP020A00F_PH_L_REG] = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) [GP2AP020A00F_PH_H_REG] = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) static bool gp2ap020a00f_is_volatile_reg(struct device *dev, unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) switch (reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) case GP2AP020A00F_OP_REG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) case GP2AP020A00F_D0_L_REG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) case GP2AP020A00F_D0_H_REG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) case GP2AP020A00F_D1_L_REG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) case GP2AP020A00F_D1_H_REG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) case GP2AP020A00F_D2_L_REG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) case GP2AP020A00F_D2_H_REG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static const struct regmap_config gp2ap020a00f_regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) .max_register = GP2AP020A00F_D2_H_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) .cache_type = REGCACHE_RBTREE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) .volatile_reg = gp2ap020a00f_is_volatile_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) static const struct gp2ap020a00f_mutable_config_regs {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) u8 op_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) u8 als_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) u8 ps_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) u8 led_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) } opmode_regs_settings[GP2AP020A00F_NUM_OPMODES] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) [GP2AP020A00F_OPMODE_READ_RAW_CLEAR] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) GP2AP020A00F_OP_ALS | GP2AP020A00F_OP2_CONT_OPERATION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) | GP2AP020A00F_OP3_OPERATION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) | GP2AP020A00F_TYPE_AUTO_CALC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) GP2AP020A00F_PRST_ONCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) GP2AP020A00F_INTTYPE_LEVEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) GP2AP020A00F_PIN_ALS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) [GP2AP020A00F_OPMODE_READ_RAW_IR] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) GP2AP020A00F_OP_ALS | GP2AP020A00F_OP2_CONT_OPERATION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) | GP2AP020A00F_OP3_OPERATION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) | GP2AP020A00F_TYPE_MANUAL_CALC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) GP2AP020A00F_PRST_ONCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) GP2AP020A00F_INTTYPE_LEVEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) GP2AP020A00F_PIN_ALS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) [GP2AP020A00F_OPMODE_READ_RAW_PROXIMITY] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) GP2AP020A00F_OP_PS | GP2AP020A00F_OP2_CONT_OPERATION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) | GP2AP020A00F_OP3_OPERATION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) | GP2AP020A00F_TYPE_MANUAL_CALC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) GP2AP020A00F_PRST_ONCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) GP2AP020A00F_INTTYPE_LEVEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) GP2AP020A00F_PIN_PS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) [GP2AP020A00F_OPMODE_PROX_DETECT] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) GP2AP020A00F_OP_PS | GP2AP020A00F_OP2_CONT_OPERATION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) | GP2AP020A00F_OP3_OPERATION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) | GP2AP020A00F_TYPE_MANUAL_CALC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) GP2AP020A00F_PRST_4_CYCLES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) GP2AP020A00F_INTTYPE_PULSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) GP2AP020A00F_PIN_PS_DETECT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) [GP2AP020A00F_OPMODE_ALS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) GP2AP020A00F_OP_ALS | GP2AP020A00F_OP2_CONT_OPERATION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) | GP2AP020A00F_OP3_OPERATION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) | GP2AP020A00F_TYPE_AUTO_CALC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) GP2AP020A00F_PRST_ONCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) GP2AP020A00F_INTTYPE_LEVEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) GP2AP020A00F_PIN_ALS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) [GP2AP020A00F_OPMODE_PS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) GP2AP020A00F_OP_PS | GP2AP020A00F_OP2_CONT_OPERATION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) | GP2AP020A00F_OP3_OPERATION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) | GP2AP020A00F_TYPE_MANUAL_CALC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) GP2AP020A00F_PRST_4_CYCLES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) GP2AP020A00F_INTTYPE_LEVEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) GP2AP020A00F_PIN_PS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) [GP2AP020A00F_OPMODE_ALS_AND_PS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) GP2AP020A00F_OP_ALS_AND_PS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) | GP2AP020A00F_OP2_CONT_OPERATION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) | GP2AP020A00F_OP3_OPERATION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) | GP2AP020A00F_TYPE_AUTO_CALC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) GP2AP020A00F_PRST_4_CYCLES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) GP2AP020A00F_INTTYPE_LEVEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) GP2AP020A00F_PIN_ALS_OR_PS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) [GP2AP020A00F_OPMODE_SHUTDOWN] = { GP2AP020A00F_OP3_SHUTDOWN, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) static int gp2ap020a00f_set_operation_mode(struct gp2ap020a00f_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) enum gp2ap020a00f_opmode op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) unsigned int op_reg_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (op != GP2AP020A00F_OPMODE_SHUTDOWN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) err = regmap_read(data->regmap, GP2AP020A00F_OP_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) &op_reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) * Shutdown the device if the operation being executed entails
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * mode transition.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if ((opmode_regs_settings[op].op_reg & GP2AP020A00F_OP_MASK) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) (op_reg_val & GP2AP020A00F_OP_MASK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) /* set shutdown mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) err = regmap_update_bits(data->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) GP2AP020A00F_OP_REG, GP2AP020A00F_OP3_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) GP2AP020A00F_OP3_SHUTDOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) err = regmap_update_bits(data->regmap, GP2AP020A00F_ALS_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) GP2AP020A00F_PRST_MASK, opmode_regs_settings[op]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) .als_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) err = regmap_update_bits(data->regmap, GP2AP020A00F_PS_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) GP2AP020A00F_INTTYPE_MASK, opmode_regs_settings[op]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) .ps_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) err = regmap_update_bits(data->regmap, GP2AP020A00F_LED_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) GP2AP020A00F_PIN_MASK, opmode_regs_settings[op]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) .led_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return err;
^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) /* Set OP_REG and apply operation mode (power on / off) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) err = regmap_update_bits(data->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) GP2AP020A00F_OP_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) GP2AP020A00F_OP_MASK | GP2AP020A00F_OP2_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) GP2AP020A00F_OP3_MASK | GP2AP020A00F_TYPE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) opmode_regs_settings[op].op_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) data->cur_opmode = op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static bool gp2ap020a00f_als_enabled(struct gp2ap020a00f_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return test_bit(GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, &data->flags) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) test_bit(GP2AP020A00F_FLAG_ALS_IR_TRIGGER, &data->flags) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) static bool gp2ap020a00f_prox_detect_enabled(struct gp2ap020a00f_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) static int gp2ap020a00f_write_event_threshold(struct gp2ap020a00f_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) enum gp2ap020a00f_thresh_val_id th_val_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) __le16 thresh_buf = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) unsigned int thresh_reg_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (!enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) thresh_reg_val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) else if (test_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) th_val_id != GP2AP020A00F_THRESH_PL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) th_val_id != GP2AP020A00F_THRESH_PH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) * For the high lux mode ALS threshold has to be scaled down
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) * to allow for proper comparison with the output value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) thresh_reg_val = data->thresh_val[th_val_id] / 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) thresh_reg_val = data->thresh_val[th_val_id] > 16000 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 16000 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) data->thresh_val[th_val_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) thresh_buf = cpu_to_le16(thresh_reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return regmap_bulk_write(data->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) GP2AP020A00F_THRESH_REG(th_val_id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) (u8 *)&thresh_buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static int gp2ap020a00f_alter_opmode(struct gp2ap020a00f_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) enum gp2ap020a00f_opmode diff_mode, int add_sub)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) enum gp2ap020a00f_opmode new_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (diff_mode != GP2AP020A00F_OPMODE_ALS &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) diff_mode != GP2AP020A00F_OPMODE_PS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) if (add_sub == GP2AP020A00F_ADD_MODE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (data->cur_opmode == GP2AP020A00F_OPMODE_SHUTDOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) new_mode = diff_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) new_mode = GP2AP020A00F_OPMODE_ALS_AND_PS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (data->cur_opmode == GP2AP020A00F_OPMODE_ALS_AND_PS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) new_mode = (diff_mode == GP2AP020A00F_OPMODE_ALS) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) GP2AP020A00F_OPMODE_PS :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) GP2AP020A00F_OPMODE_ALS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) new_mode = GP2AP020A00F_OPMODE_SHUTDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return gp2ap020a00f_set_operation_mode(data, new_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) enum gp2ap020a00f_cmd cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) case GP2AP020A00F_CMD_READ_RAW_CLEAR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (data->cur_opmode != GP2AP020A00F_OPMODE_SHUTDOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) err = gp2ap020a00f_set_operation_mode(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) GP2AP020A00F_OPMODE_READ_RAW_CLEAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) case GP2AP020A00F_CMD_READ_RAW_IR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (data->cur_opmode != GP2AP020A00F_OPMODE_SHUTDOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) err = gp2ap020a00f_set_operation_mode(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) GP2AP020A00F_OPMODE_READ_RAW_IR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) case GP2AP020A00F_CMD_READ_RAW_PROXIMITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (data->cur_opmode != GP2AP020A00F_OPMODE_SHUTDOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) err = gp2ap020a00f_set_operation_mode(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) GP2AP020A00F_OPMODE_READ_RAW_PROXIMITY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) case GP2AP020A00F_CMD_TRIGGER_CLEAR_EN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (!gp2ap020a00f_als_enabled(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) err = gp2ap020a00f_alter_opmode(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) GP2AP020A00F_OPMODE_ALS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) GP2AP020A00F_ADD_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) set_bit(GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) case GP2AP020A00F_CMD_TRIGGER_CLEAR_DIS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) clear_bit(GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) if (gp2ap020a00f_als_enabled(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) err = gp2ap020a00f_alter_opmode(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) GP2AP020A00F_OPMODE_ALS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) GP2AP020A00F_SUBTRACT_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) case GP2AP020A00F_CMD_TRIGGER_IR_EN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (!gp2ap020a00f_als_enabled(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) err = gp2ap020a00f_alter_opmode(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) GP2AP020A00F_OPMODE_ALS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) GP2AP020A00F_ADD_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) set_bit(GP2AP020A00F_FLAG_ALS_IR_TRIGGER, &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) case GP2AP020A00F_CMD_TRIGGER_IR_DIS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) clear_bit(GP2AP020A00F_FLAG_ALS_IR_TRIGGER, &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (gp2ap020a00f_als_enabled(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) err = gp2ap020a00f_alter_opmode(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) GP2AP020A00F_OPMODE_ALS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) GP2AP020A00F_SUBTRACT_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) case GP2AP020A00F_CMD_TRIGGER_PROX_EN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) err = gp2ap020a00f_alter_opmode(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) GP2AP020A00F_OPMODE_PS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) GP2AP020A00F_ADD_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) set_bit(GP2AP020A00F_FLAG_PROX_TRIGGER, &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) case GP2AP020A00F_CMD_TRIGGER_PROX_DIS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) clear_bit(GP2AP020A00F_FLAG_PROX_TRIGGER, &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) err = gp2ap020a00f_alter_opmode(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) GP2AP020A00F_OPMODE_PS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) GP2AP020A00F_SUBTRACT_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) case GP2AP020A00F_CMD_ALS_HIGH_EV_EN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) if (test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (!gp2ap020a00f_als_enabled(data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) err = gp2ap020a00f_alter_opmode(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) GP2AP020A00F_OPMODE_ALS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) GP2AP020A00F_ADD_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) set_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) err = gp2ap020a00f_write_event_threshold(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) GP2AP020A00F_THRESH_TH, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) case GP2AP020A00F_CMD_ALS_HIGH_EV_DIS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) if (!test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) clear_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (!gp2ap020a00f_als_enabled(data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) err = gp2ap020a00f_alter_opmode(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) GP2AP020A00F_OPMODE_ALS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) GP2AP020A00F_SUBTRACT_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) err = gp2ap020a00f_write_event_threshold(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) GP2AP020A00F_THRESH_TH, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) case GP2AP020A00F_CMD_ALS_LOW_EV_EN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (!gp2ap020a00f_als_enabled(data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) err = gp2ap020a00f_alter_opmode(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) GP2AP020A00F_OPMODE_ALS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) GP2AP020A00F_ADD_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) set_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) err = gp2ap020a00f_write_event_threshold(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) GP2AP020A00F_THRESH_TL, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) case GP2AP020A00F_CMD_ALS_LOW_EV_DIS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (!test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) clear_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (!gp2ap020a00f_als_enabled(data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) err = gp2ap020a00f_alter_opmode(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) GP2AP020A00F_OPMODE_ALS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) GP2AP020A00F_SUBTRACT_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) err = gp2ap020a00f_write_event_threshold(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) GP2AP020A00F_THRESH_TL, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) case GP2AP020A00F_CMD_PROX_HIGH_EV_EN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (gp2ap020a00f_als_enabled(data) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) data->cur_opmode == GP2AP020A00F_OPMODE_PS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if (!gp2ap020a00f_prox_detect_enabled(data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) err = gp2ap020a00f_set_operation_mode(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) GP2AP020A00F_OPMODE_PROX_DETECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) set_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) err = gp2ap020a00f_write_event_threshold(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) GP2AP020A00F_THRESH_PH, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) case GP2AP020A00F_CMD_PROX_HIGH_EV_DIS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (!test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) clear_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) err = gp2ap020a00f_set_operation_mode(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) GP2AP020A00F_OPMODE_SHUTDOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) err = gp2ap020a00f_write_event_threshold(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) GP2AP020A00F_THRESH_PH, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) case GP2AP020A00F_CMD_PROX_LOW_EV_EN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) if (test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) if (gp2ap020a00f_als_enabled(data) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) data->cur_opmode == GP2AP020A00F_OPMODE_PS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (!gp2ap020a00f_prox_detect_enabled(data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) err = gp2ap020a00f_set_operation_mode(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) GP2AP020A00F_OPMODE_PROX_DETECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) set_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) err = gp2ap020a00f_write_event_threshold(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) GP2AP020A00F_THRESH_PL, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) case GP2AP020A00F_CMD_PROX_LOW_EV_DIS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if (!test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) clear_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) err = gp2ap020a00f_set_operation_mode(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) GP2AP020A00F_OPMODE_SHUTDOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) err = gp2ap020a00f_write_event_threshold(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) GP2AP020A00F_THRESH_PL, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) static int wait_conversion_complete_irq(struct gp2ap020a00f_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) ret = wait_event_timeout(data->data_ready_queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) test_bit(GP2AP020A00F_FLAG_DATA_READY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) &data->flags),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) GP2AP020A00F_DATA_READY_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) clear_bit(GP2AP020A00F_FLAG_DATA_READY, &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) return ret > 0 ? 0 : -ETIME;
^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 gp2ap020a00f_read_output(struct gp2ap020a00f_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) unsigned int output_reg, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) u8 reg_buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) err = wait_conversion_complete_irq(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) dev_dbg(&data->client->dev, "data ready timeout\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) err = regmap_bulk_read(data->regmap, output_reg, reg_buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) *val = le16_to_cpup((__le16 *)reg_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) static bool gp2ap020a00f_adjust_lux_mode(struct gp2ap020a00f_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) int output_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) u8 new_range = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) if (!test_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (output_val > 16000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) set_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) new_range = GP2AP020A00F_RANGE_A_x128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (output_val < 1000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) clear_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) new_range = GP2AP020A00F_RANGE_A_x8;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (new_range != 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) /* Clear als threshold registers to avoid spurious
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) * events caused by lux mode transition.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) err = gp2ap020a00f_write_event_threshold(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) GP2AP020A00F_THRESH_TH, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) dev_err(&data->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) "Clearing als threshold register failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) return false;
^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) err = gp2ap020a00f_write_event_threshold(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) GP2AP020A00F_THRESH_TL, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) dev_err(&data->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) "Clearing als threshold register failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) /* Change lux mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) err = regmap_update_bits(data->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) GP2AP020A00F_OP_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) GP2AP020A00F_OP3_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) GP2AP020A00F_OP3_SHUTDOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) dev_err(&data->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) "Shutting down the device failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) err = regmap_update_bits(data->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) GP2AP020A00F_ALS_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) GP2AP020A00F_RANGE_A_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) new_range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) dev_err(&data->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) "Adjusting device lux mode failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) return false;
^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 = regmap_update_bits(data->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) GP2AP020A00F_OP_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) GP2AP020A00F_OP3_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) GP2AP020A00F_OP3_OPERATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) dev_err(&data->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) "Powering up the device failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) /* Adjust als threshold register values to the new lux mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) err = gp2ap020a00f_write_event_threshold(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) GP2AP020A00F_THRESH_TH, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) dev_err(&data->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) "Adjusting als threshold value failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) err = gp2ap020a00f_write_event_threshold(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) GP2AP020A00F_THRESH_TL, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) dev_err(&data->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) "Adjusting als threshold value failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) return true;
^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) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) static void gp2ap020a00f_output_to_lux(struct gp2ap020a00f_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) int *output_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (test_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) *output_val *= 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) static void gp2ap020a00f_iio_trigger_work(struct irq_work *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) struct gp2ap020a00f_data *data =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) container_of(work, struct gp2ap020a00f_data, work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) iio_trigger_poll(data->trig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) static irqreturn_t gp2ap020a00f_prox_sensing_handler(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) struct iio_dev *indio_dev = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) struct gp2ap020a00f_data *priv = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) unsigned int op_reg_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) /* Read interrupt flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) ret = regmap_read(priv->regmap, GP2AP020A00F_OP_REG, &op_reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) if (gp2ap020a00f_prox_detect_enabled(priv)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if (op_reg_val & GP2AP020A00F_PROX_DETECT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) iio_push_event(indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) IIO_UNMOD_EVENT_CODE(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) IIO_PROXIMITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) GP2AP020A00F_SCAN_MODE_PROXIMITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) IIO_EV_TYPE_ROC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) IIO_EV_DIR_RISING),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) iio_get_time_ns(indio_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) iio_push_event(indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) IIO_UNMOD_EVENT_CODE(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) IIO_PROXIMITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) GP2AP020A00F_SCAN_MODE_PROXIMITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) IIO_EV_TYPE_ROC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) IIO_EV_DIR_FALLING),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) iio_get_time_ns(indio_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) static irqreturn_t gp2ap020a00f_thresh_event_handler(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) struct iio_dev *indio_dev = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) struct gp2ap020a00f_data *priv = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) u8 op_reg_flags, d0_reg_buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) unsigned int output_val, op_reg_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) int thresh_val_id, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) /* Read interrupt flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) ret = regmap_read(priv->regmap, GP2AP020A00F_OP_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) &op_reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) op_reg_flags = op_reg_val & (GP2AP020A00F_FLAG_A | GP2AP020A00F_FLAG_P
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) | GP2AP020A00F_PROX_DETECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) op_reg_val &= (~GP2AP020A00F_FLAG_A & ~GP2AP020A00F_FLAG_P
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) & ~GP2AP020A00F_PROX_DETECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) /* Clear interrupt flags (if not in INTTYPE_PULSE mode) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if (priv->cur_opmode != GP2AP020A00F_OPMODE_PROX_DETECT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) ret = regmap_write(priv->regmap, GP2AP020A00F_OP_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) op_reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) if (op_reg_flags & GP2AP020A00F_FLAG_A) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) /* Check D0 register to assess if the lux mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) * transition is required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) ret = regmap_bulk_read(priv->regmap, GP2AP020A00F_D0_L_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) d0_reg_buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) output_val = le16_to_cpup((__le16 *)d0_reg_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) if (gp2ap020a00f_adjust_lux_mode(priv, output_val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) gp2ap020a00f_output_to_lux(priv, &output_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) * We need to check output value to distinguish
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) * between high and low ambient light threshold event.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &priv->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) thresh_val_id =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) GP2AP020A00F_THRESH_VAL_ID(GP2AP020A00F_TH_L_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) if (output_val > priv->thresh_val[thresh_val_id])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) iio_push_event(indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) IIO_MOD_EVENT_CODE(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) IIO_LIGHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) IIO_MOD_LIGHT_CLEAR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) IIO_EV_DIR_RISING),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) iio_get_time_ns(indio_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &priv->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) thresh_val_id =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) GP2AP020A00F_THRESH_VAL_ID(GP2AP020A00F_TL_L_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) if (output_val < priv->thresh_val[thresh_val_id])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) iio_push_event(indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) IIO_MOD_EVENT_CODE(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) IIO_LIGHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) IIO_MOD_LIGHT_CLEAR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) IIO_EV_DIR_FALLING),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) iio_get_time_ns(indio_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) if (priv->cur_opmode == GP2AP020A00F_OPMODE_READ_RAW_CLEAR ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) priv->cur_opmode == GP2AP020A00F_OPMODE_READ_RAW_IR ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) priv->cur_opmode == GP2AP020A00F_OPMODE_READ_RAW_PROXIMITY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) set_bit(GP2AP020A00F_FLAG_DATA_READY, &priv->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) wake_up(&priv->data_ready_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) if (test_bit(GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, &priv->flags) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) test_bit(GP2AP020A00F_FLAG_ALS_IR_TRIGGER, &priv->flags) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) test_bit(GP2AP020A00F_FLAG_PROX_TRIGGER, &priv->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) /* This fires off the trigger. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) irq_work_queue(&priv->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) static irqreturn_t gp2ap020a00f_trigger_handler(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) struct iio_poll_func *pf = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) struct iio_dev *indio_dev = pf->indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) struct gp2ap020a00f_data *priv = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) size_t d_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) int i, out_val, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) for_each_set_bit(i, indio_dev->active_scan_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) indio_dev->masklength) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) ret = regmap_bulk_read(priv->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) GP2AP020A00F_DATA_REG(i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) &priv->buffer[d_size], 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) if (i == GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) i == GP2AP020A00F_SCAN_MODE_LIGHT_IR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) out_val = le16_to_cpup((__le16 *)&priv->buffer[d_size]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) gp2ap020a00f_output_to_lux(priv, &out_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) put_unaligned_le32(out_val, &priv->buffer[d_size]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) d_size += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) d_size += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) iio_push_to_buffers_with_timestamp(indio_dev, priv->buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) pf->timestamp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) iio_trigger_notify_done(indio_dev->trig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) static u8 gp2ap020a00f_get_thresh_reg(const struct iio_chan_spec *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) enum iio_event_direction event_dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) switch (chan->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) case IIO_PROXIMITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (event_dir == IIO_EV_DIR_RISING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) return GP2AP020A00F_PH_L_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) return GP2AP020A00F_PL_L_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) case IIO_LIGHT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) if (event_dir == IIO_EV_DIR_RISING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) return GP2AP020A00F_TH_L_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) return GP2AP020A00F_TL_L_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) static int gp2ap020a00f_write_event_val(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) const struct iio_chan_spec *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) enum iio_event_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) enum iio_event_direction dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) enum iio_event_info info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) int val, int val2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) struct gp2ap020a00f_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) bool event_en = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) u8 thresh_val_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) u8 thresh_reg_l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) thresh_reg_l = gp2ap020a00f_get_thresh_reg(chan, dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) thresh_val_id = GP2AP020A00F_THRESH_VAL_ID(thresh_reg_l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) if (thresh_val_id > GP2AP020A00F_THRESH_PH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) goto error_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) switch (thresh_reg_l) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) case GP2AP020A00F_TH_L_REG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) event_en = test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) case GP2AP020A00F_TL_L_REG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) event_en = test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) case GP2AP020A00F_PH_L_REG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) if (val == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) goto error_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) event_en = test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) case GP2AP020A00F_PL_L_REG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) if (val == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) goto error_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) event_en = test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) data->thresh_val[thresh_val_id] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) err = gp2ap020a00f_write_event_threshold(data, thresh_val_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) event_en);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) error_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) static int gp2ap020a00f_read_event_val(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) const struct iio_chan_spec *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) enum iio_event_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) enum iio_event_direction dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) enum iio_event_info info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) int *val, int *val2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) struct gp2ap020a00f_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) u8 thresh_reg_l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) int err = IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) thresh_reg_l = gp2ap020a00f_get_thresh_reg(chan, dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) if (thresh_reg_l > GP2AP020A00F_PH_L_REG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) goto error_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) *val = data->thresh_val[GP2AP020A00F_THRESH_VAL_ID(thresh_reg_l)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) error_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) static int gp2ap020a00f_write_prox_event_config(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) struct gp2ap020a00f_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) enum gp2ap020a00f_cmd cmd_high_ev, cmd_low_ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) cmd_high_ev = state ? GP2AP020A00F_CMD_PROX_HIGH_EV_EN :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) GP2AP020A00F_CMD_PROX_HIGH_EV_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) cmd_low_ev = state ? GP2AP020A00F_CMD_PROX_LOW_EV_EN :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) GP2AP020A00F_CMD_PROX_LOW_EV_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) * In order to enable proximity detection feature in the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) * both high and low threshold registers have to be written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) * with different values, greater than zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) if (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) if (data->thresh_val[GP2AP020A00F_THRESH_PL] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) if (data->thresh_val[GP2AP020A00F_THRESH_PH] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) err = gp2ap020a00f_exec_cmd(data, cmd_high_ev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) err = gp2ap020a00f_exec_cmd(data, cmd_low_ev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) free_irq(data->client->irq, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) if (state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) err = request_threaded_irq(data->client->irq, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) &gp2ap020a00f_prox_sensing_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) IRQF_TRIGGER_RISING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) IRQF_TRIGGER_FALLING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) "gp2ap020a00f_prox_sensing",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) err = request_threaded_irq(data->client->irq, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) &gp2ap020a00f_thresh_event_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) IRQF_TRIGGER_FALLING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) "gp2ap020a00f_thresh_event",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) static int gp2ap020a00f_write_event_config(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) const struct iio_chan_spec *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) enum iio_event_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) enum iio_event_direction dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) struct gp2ap020a00f_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) enum gp2ap020a00f_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) switch (chan->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) case IIO_PROXIMITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) err = gp2ap020a00f_write_prox_event_config(indio_dev, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) case IIO_LIGHT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) if (dir == IIO_EV_DIR_RISING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) cmd = state ? GP2AP020A00F_CMD_ALS_HIGH_EV_EN :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) GP2AP020A00F_CMD_ALS_HIGH_EV_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) err = gp2ap020a00f_exec_cmd(data, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) cmd = state ? GP2AP020A00F_CMD_ALS_LOW_EV_EN :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) GP2AP020A00F_CMD_ALS_LOW_EV_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) err = gp2ap020a00f_exec_cmd(data, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) static int gp2ap020a00f_read_event_config(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) const struct iio_chan_spec *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) enum iio_event_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) enum iio_event_direction dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) struct gp2ap020a00f_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) int event_en = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) switch (chan->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) case IIO_PROXIMITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) if (dir == IIO_EV_DIR_RISING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) event_en = test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) event_en = test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) case IIO_LIGHT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) if (dir == IIO_EV_DIR_RISING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) event_en = test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) event_en = test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) &data->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) event_en = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) return event_en;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) static int gp2ap020a00f_read_channel(struct gp2ap020a00f_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) struct iio_chan_spec const *chan, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) enum gp2ap020a00f_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) switch (chan->scan_index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) case GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) cmd = GP2AP020A00F_CMD_READ_RAW_CLEAR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) case GP2AP020A00F_SCAN_MODE_LIGHT_IR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) cmd = GP2AP020A00F_CMD_READ_RAW_IR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) case GP2AP020A00F_SCAN_MODE_PROXIMITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) cmd = GP2AP020A00F_CMD_READ_RAW_PROXIMITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) err = gp2ap020a00f_exec_cmd(data, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) dev_err(&data->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) "gp2ap020a00f_exec_cmd failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) goto error_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) err = gp2ap020a00f_read_output(data, chan->address, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) dev_err(&data->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) "gp2ap020a00f_read_output failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) err = gp2ap020a00f_set_operation_mode(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) GP2AP020A00F_OPMODE_SHUTDOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) dev_err(&data->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) "Failed to shut down the device.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) if (cmd == GP2AP020A00F_CMD_READ_RAW_CLEAR ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) cmd == GP2AP020A00F_CMD_READ_RAW_IR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) gp2ap020a00f_output_to_lux(data, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) error_ret:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) static int gp2ap020a00f_read_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) struct iio_chan_spec const *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) int *val, int *val2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) struct gp2ap020a00f_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) int err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) if (mask == IIO_CHAN_INFO_RAW) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) err = iio_device_claim_direct_mode(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) err = gp2ap020a00f_read_channel(data, chan, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) iio_device_release_direct_mode(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) return err < 0 ? err : IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) static const struct iio_event_spec gp2ap020a00f_event_spec_light[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) .type = IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) .dir = IIO_EV_DIR_RISING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) .mask_separate = BIT(IIO_EV_INFO_VALUE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) BIT(IIO_EV_INFO_ENABLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) .type = IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) .dir = IIO_EV_DIR_FALLING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) .mask_separate = BIT(IIO_EV_INFO_VALUE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) BIT(IIO_EV_INFO_ENABLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) static const struct iio_event_spec gp2ap020a00f_event_spec_prox[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) .type = IIO_EV_TYPE_ROC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) .dir = IIO_EV_DIR_RISING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) .mask_separate = BIT(IIO_EV_INFO_VALUE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) BIT(IIO_EV_INFO_ENABLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) .type = IIO_EV_TYPE_ROC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) .dir = IIO_EV_DIR_FALLING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) .mask_separate = BIT(IIO_EV_INFO_VALUE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) BIT(IIO_EV_INFO_ENABLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) static const struct iio_chan_spec gp2ap020a00f_channels[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) .type = IIO_LIGHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) .channel2 = IIO_MOD_LIGHT_CLEAR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) .modified = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) .scan_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) .sign = 'u',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) .realbits = 24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) .shift = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) .storagebits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) .endianness = IIO_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) .scan_index = GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) .address = GP2AP020A00F_D0_L_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) .event_spec = gp2ap020a00f_event_spec_light,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) .num_event_specs = ARRAY_SIZE(gp2ap020a00f_event_spec_light),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) .type = IIO_LIGHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) .channel2 = IIO_MOD_LIGHT_IR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) .modified = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) .scan_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) .sign = 'u',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) .realbits = 24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) .shift = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) .storagebits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) .endianness = IIO_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) .scan_index = GP2AP020A00F_SCAN_MODE_LIGHT_IR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) .address = GP2AP020A00F_D1_L_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) .type = IIO_PROXIMITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) .modified = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) .scan_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) .sign = 'u',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) .realbits = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) .shift = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) .storagebits = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) .endianness = IIO_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) .scan_index = GP2AP020A00F_SCAN_MODE_PROXIMITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) .address = GP2AP020A00F_D2_L_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) .event_spec = gp2ap020a00f_event_spec_prox,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) .num_event_specs = ARRAY_SIZE(gp2ap020a00f_event_spec_prox),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) IIO_CHAN_SOFT_TIMESTAMP(GP2AP020A00F_CHAN_TIMESTAMP),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) static const struct iio_info gp2ap020a00f_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) .read_raw = &gp2ap020a00f_read_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) .read_event_value = &gp2ap020a00f_read_event_val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) .read_event_config = &gp2ap020a00f_read_event_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) .write_event_value = &gp2ap020a00f_write_event_val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) .write_event_config = &gp2ap020a00f_write_event_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) static int gp2ap020a00f_buffer_postenable(struct iio_dev *indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) struct gp2ap020a00f_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) int i, err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) * Enable triggers according to the scan_mask. Enabling either
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) * LIGHT_CLEAR or LIGHT_IR scan mode results in enabling ALS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) * module in the device, which generates samples in both D0 (clear)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) * and D1 (ir) registers. As the two registers are bound to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) * two separate IIO channels they are treated in the driver logic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) * as if they were controlled independently.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) for_each_set_bit(i, indio_dev->active_scan_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) indio_dev->masklength) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) switch (i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) case GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) err = gp2ap020a00f_exec_cmd(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) GP2AP020A00F_CMD_TRIGGER_CLEAR_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) case GP2AP020A00F_SCAN_MODE_LIGHT_IR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) err = gp2ap020a00f_exec_cmd(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) GP2AP020A00F_CMD_TRIGGER_IR_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) case GP2AP020A00F_SCAN_MODE_PROXIMITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) err = gp2ap020a00f_exec_cmd(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) GP2AP020A00F_CMD_TRIGGER_PROX_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) goto error_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) data->buffer = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) if (!data->buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) error_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) static int gp2ap020a00f_buffer_predisable(struct iio_dev *indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) struct gp2ap020a00f_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) int i, err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) for_each_set_bit(i, indio_dev->active_scan_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) indio_dev->masklength) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) switch (i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) case GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) err = gp2ap020a00f_exec_cmd(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) GP2AP020A00F_CMD_TRIGGER_CLEAR_DIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) case GP2AP020A00F_SCAN_MODE_LIGHT_IR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) err = gp2ap020a00f_exec_cmd(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) GP2AP020A00F_CMD_TRIGGER_IR_DIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) case GP2AP020A00F_SCAN_MODE_PROXIMITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) err = gp2ap020a00f_exec_cmd(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) GP2AP020A00F_CMD_TRIGGER_PROX_DIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) if (err == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) kfree(data->buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) static const struct iio_buffer_setup_ops gp2ap020a00f_buffer_setup_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) .postenable = &gp2ap020a00f_buffer_postenable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) .predisable = &gp2ap020a00f_buffer_predisable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) static const struct iio_trigger_ops gp2ap020a00f_trigger_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) static int gp2ap020a00f_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) struct gp2ap020a00f_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) struct iio_dev *indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) if (!indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) data->vled_reg = devm_regulator_get(&client->dev, "vled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) if (IS_ERR(data->vled_reg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) return PTR_ERR(data->vled_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) err = regulator_enable(data->vled_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) regmap = devm_regmap_init_i2c(client, &gp2ap020a00f_regmap_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) if (IS_ERR(regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) dev_err(&client->dev, "Regmap initialization failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) err = PTR_ERR(regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) goto error_regulator_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) /* Initialize device registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) err = regmap_bulk_write(regmap, GP2AP020A00F_OP_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) gp2ap020a00f_reg_init_tab,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) ARRAY_SIZE(gp2ap020a00f_reg_init_tab));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) dev_err(&client->dev, "Device initialization failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) goto error_regulator_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) i2c_set_clientdata(client, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) data->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) data->cur_opmode = GP2AP020A00F_OPMODE_SHUTDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) data->regmap = regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) init_waitqueue_head(&data->data_ready_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) mutex_init(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) indio_dev->channels = gp2ap020a00f_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) indio_dev->num_channels = ARRAY_SIZE(gp2ap020a00f_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) indio_dev->info = &gp2ap020a00f_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) indio_dev->name = id->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) indio_dev->modes = INDIO_DIRECT_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) /* Allocate buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) err = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) &gp2ap020a00f_trigger_handler, &gp2ap020a00f_buffer_setup_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) goto error_regulator_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) /* Allocate trigger */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) data->trig = devm_iio_trigger_alloc(&client->dev, "%s-trigger",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) indio_dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) if (data->trig == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) dev_err(&indio_dev->dev, "Failed to allocate iio trigger.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) goto error_uninit_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) /* This needs to be requested here for read_raw calls to work. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) err = request_threaded_irq(client->irq, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) &gp2ap020a00f_thresh_event_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) IRQF_TRIGGER_FALLING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) "gp2ap020a00f_als_event",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) dev_err(&client->dev, "Irq request failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) goto error_uninit_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) data->trig->ops = &gp2ap020a00f_trigger_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) data->trig->dev.parent = &data->client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) init_irq_work(&data->work, gp2ap020a00f_iio_trigger_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) err = iio_trigger_register(data->trig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) dev_err(&client->dev, "Failed to register iio trigger.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) goto error_free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) err = iio_device_register(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) goto error_trigger_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) error_trigger_unregister:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) iio_trigger_unregister(data->trig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) error_free_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) free_irq(client->irq, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) error_uninit_buffer:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) iio_triggered_buffer_cleanup(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) error_regulator_disable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) regulator_disable(data->vled_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) static int gp2ap020a00f_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) struct iio_dev *indio_dev = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) struct gp2ap020a00f_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) err = gp2ap020a00f_set_operation_mode(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) GP2AP020A00F_OPMODE_SHUTDOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) dev_err(&indio_dev->dev, "Failed to power off the device.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) iio_device_unregister(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) iio_trigger_unregister(data->trig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) free_irq(client->irq, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) iio_triggered_buffer_cleanup(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) regulator_disable(data->vled_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) static const struct i2c_device_id gp2ap020a00f_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) { GP2A_I2C_NAME, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) MODULE_DEVICE_TABLE(i2c, gp2ap020a00f_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) static const struct of_device_id gp2ap020a00f_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) { .compatible = "sharp,gp2ap020a00f" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) MODULE_DEVICE_TABLE(of, gp2ap020a00f_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) static struct i2c_driver gp2ap020a00f_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) .name = GP2A_I2C_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) .of_match_table = gp2ap020a00f_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) .probe = gp2ap020a00f_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) .remove = gp2ap020a00f_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) .id_table = gp2ap020a00f_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) module_i2c_driver(gp2ap020a00f_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) MODULE_DESCRIPTION("Sharp GP2AP020A00F Proximity/ALS sensor driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) MODULE_LICENSE("GPL v2");