| /* |
| * Copyright (C) 2018 Samsung Electronics Co., Ltd. All rights reserved. |
| * |
| * This software is licensed under the terms of the GNU General Public |
| * License, as published by the Free Software Foundation, and |
| * may be copied, distributed, and modified under those terms. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| /*! \file |
| * \brief Device driver for monitoring ambient light intensity in (lux) |
| * proximity detection (prox), and Beam functionality within the |
| * AMS TMX49xx family of devices. |
| */ |
| |
| #ifndef __AMS_TCS3407_H |
| #define __AMS_TCS3407_H |
| |
| #include <linux/delay.h> |
| #include <linux/i2c.h> |
| #include <linux/irq.h> |
| #include <linux/input.h> |
| #include <linux/init.h> |
| #include <linux/kernel.h> |
| #include <linux/module.h> |
| #include <linux/moduleparam.h> |
| #include <linux/interrupt.h> |
| #include <linux/leds.h> |
| #include <linux/miscdevice.h> |
| #include <linux/platform_device.h> |
| #include <linux/regulator/consumer.h> |
| #include <linux/slab.h> |
| #include <linux/types.h> |
| #include <linux/uaccess.h> |
| #include <linux/workqueue.h> |
| #include <linux/spinlock.h> |
| #include <linux/gpio.h> |
| #include <linux/kthread.h> |
| #include <linux/sched.h> |
| #include <linux/time.h> |
| #include <linux/timer.h> |
| #include <linux/file.h> |
| #include <linux/syscalls.h> |
| #include <linux/pinctrl/consumer.h> |
| #include <linux/pm_qos.h> |
| #ifdef CONFIG_OF |
| #include <linux/of_gpio.h> |
| #include <linux/of_device.h> |
| #endif |
| |
| #define HEADER_VERSION "17" |
| |
| #define CONFIG_AMS_ALS_CRGBW |
| #ifndef CONFIG_AMS_OPTICAL_SENSOR_FIFO |
| #define CONFIG_AMS_OPTICAL_SENSOR_ALS |
| #endif |
| #define CONFIG_AMS_OPTICAL_SENSOR_ALS_CCB |
| #define CONFIG_AMS_OPTICAL_SENSOR_FLICKER |
| #define CONFIG_AMS_OPTICAL_SENSOR_3407 |
| |
| #define HIGH 0xFF |
| #define LOW 0x00 |
| |
| #if !defined(CONFIG_ALS_CAL_TARGET) |
| #define CONFIG_ALS_CAL_TARGET 300 /* lux */ |
| #endif |
| #if !defined(CONFIG_ALS_CAL_TARGET_TOLERANCE) |
| #define CONFIG_ALS_CAL_TARGET_TOLERANCE 15 /* lux */ |
| #endif |
| |
| #define AMS_LUX_AVERAGE_COUNT 8 |
| |
| typedef enum _amsAlsAdaptive { |
| ADAPTIVE_ALS_NO_REQUEST, |
| ADAPTIVE_ALS_TIME_INC_REQUEST, |
| ADAPTIVE_ALS_TIME_DEC_REQUEST, |
| ADAPTIVE_ALS_GAIN_INC_REQUEST, |
| ADAPTIVE_ALS_GAIN_DEC_REQUEST |
| } amsAlsAdaptive_t; |
| |
| typedef enum _amsAlsStatus { |
| ALS_STATUS_IRQ = (1 << 0), |
| ALS_STATUS_RDY = (1 << 1), |
| ALS_STATUS_OVFL = (1 << 2) |
| } amsAlsStatus_t; |
| |
| typedef struct _alsData { |
| uint16_t clearADC; |
| uint16_t redADC; |
| uint16_t greenADC; |
| uint16_t blueADC; |
| uint16_t widebandADC; |
| } alsData_t; |
| |
| typedef struct _amsAlsCalibration { |
| uint32_t Time_base; /* in uSec */ |
| uint32_t adcMaxCount; |
| uint16_t calibrationFactor; /* default 1000 */ |
| uint8_t thresholdLow; |
| uint8_t thresholdHigh; |
| int32_t Wbc; |
| } amsAlsCalibration_t; |
| |
| typedef struct _amsAlsInitData { |
| bool adaptive; |
| bool irRejection; |
| uint32_t time_us; |
| uint32_t gain; |
| amsAlsCalibration_t calibration; |
| } amsAlsInitData_t; |
| |
| typedef struct _amsALSConf { |
| uint32_t time_us; |
| uint32_t gain; |
| uint8_t thresholdLow; |
| uint8_t thresholdHigh; |
| } amsAlsConf_t; |
| |
| typedef struct _amsAlsDataSet { |
| alsData_t *datasetArray; |
| uint64_t timeStamp; |
| uint8_t status; |
| } amsAlsDataSet_t; |
| |
| typedef struct _amsAlsResult { |
| uint32_t irrClear; |
| uint32_t irrRed; |
| uint32_t irrGreen; |
| uint32_t irrBlue; |
| uint32_t IR; |
| uint32_t irrWideband; |
| uint32_t mLux; |
| uint32_t mMaxLux; |
| uint32_t mLux_ave; |
| uint32_t CCT; |
| amsAlsAdaptive_t adaptive; |
| uint32_t rawClear; |
| uint32_t rawRed; |
| uint32_t rawGreen; |
| uint32_t rawBlue; |
| uint32_t rawWideband; |
| } amsAlsResult_t; |
| |
| typedef struct _amsAlsContext { |
| uint64_t lastTimeStamp; |
| uint32_t ave_lux[AMS_LUX_AVERAGE_COUNT]; |
| uint32_t ave_lux_index; |
| uint32_t cpl; |
| uint32_t uvir_cpl; |
| uint32_t time_us; |
| amsAlsCalibration_t calibration; |
| amsAlsResult_t results; |
| bool adaptive; |
| uint16_t saturation; |
| uint32_t gain; |
| uint32_t previousGain; |
| uint32_t previousLux; |
| bool notStableMeasurement; |
| } amsAlsContext_t; |
| |
| typedef struct _amsAlsAlgInfo { |
| char *algName; |
| uint16_t contextMemSize; |
| uint16_t scratchMemSize; |
| amsAlsCalibration_t calibrationData; |
| int (*initAlg)(amsAlsContext_t *ctx, amsAlsInitData_t *initData); |
| int (*processData)(amsAlsContext_t *ctx, amsAlsDataSet_t *inputData); |
| int (*getResult)(amsAlsContext_t *ctx, amsAlsResult_t *outData); |
| int (*setConfig)(amsAlsContext_t *ctx, amsAlsConf_t *inputData); |
| int (*getConfig)(amsAlsContext_t *ctx, amsAlsConf_t *outputData); |
| } amsAlsAlgoInfo_t; |
| |
| typedef struct { |
| uint32_t calibrationFactor; |
| uint32_t Time_base; /* in uSec */ |
| uint32_t adcMaxCount; |
| uint8_t thresholdLow; |
| uint8_t thresholdHigh; |
| int32_t Wbc; |
| } ams_ccb_als_calibration_t; |
| |
| typedef struct { |
| uint32_t uSecTime; |
| uint32_t gain; |
| uint8_t threshold; |
| } ams_ccb_als_config_t; |
| |
| typedef struct { |
| bool calibrate; |
| bool autoGain; |
| uint8_t hysteresis; |
| uint16_t sampleRate; |
| ams_ccb_als_config_t configData; |
| ams_ccb_als_calibration_t calibrationData; |
| } ams_ccb_als_init_t; |
| |
| typedef enum { |
| AMS_CCB_ALS_INIT, |
| AMS_CCB_ALS_RGB, |
| AMS_CCB_ALS_AUTOGAIN, |
| AMS_CCB_ALS_CALIBRATION_INIT, |
| AMS_CCB_ALS_CALIBRATION_COLLECT_DATA, |
| AMS_CCB_ALS_CALIBRATION_CHECK, |
| AMS_CCB_ALS_LAST_STATE |
| } ams_ccb_als_state_t; |
| |
| typedef struct { |
| char *algName; |
| uint16_t contextMemSize; |
| uint16_t scratchMemSize; |
| ams_ccb_als_calibration_t defaultCalibrationData; |
| } ams_ccb_als_info_t; |
| |
| typedef struct { |
| ams_ccb_als_state_t state; |
| amsAlsContext_t ctxAlgAls; |
| ams_ccb_als_init_t initData; |
| uint16_t bufferCounter; |
| uint16_t shadowAiltReg; |
| uint16_t shadowAihtReg; |
| } ams_ccb_als_ctx_t; |
| |
| typedef struct { |
| uint8_t statusReg; |
| } ams_ccb_als_dataSet_t; |
| |
| typedef struct { |
| uint32_t ir; |
| uint32_t red; |
| uint32_t green; |
| uint32_t blue; |
| uint32_t clear; |
| uint32_t wideband; |
| uint32_t rawClear; |
| uint32_t rawRed; |
| uint32_t rawGreen; |
| uint32_t rawBlue; |
| uint32_t rawWideband; |
| uint32_t time_us; |
| uint32_t gain; |
| } ams_ccb_als_result_t; |
| |
| #define PWR_ON 1 |
| #define PWR_OFF 0 |
| #define PM_RESUME 1 |
| #define PM_SUSPEND 0 |
| #define NAME_LEN 32 |
| |
| #define CONFIG_AMS_LITTLE_ENDIAN 1 |
| #ifdef CONFIG_AMS_LITTLE_ENDIAN |
| #define AMS_ENDIAN_1 0 |
| #define AMS_ENDIAN_2 8 |
| #else |
| #define AMS_ENDIAN_2 0 |
| #define AMS_ENDIAN_1 8 |
| #endif |
| |
| #define AMS_PORT_portHndl struct i2c_client |
| |
| typedef struct { |
| bool nearBy; |
| uint16_t proximity; |
| } ams_apiPrx_t; |
| |
| typedef enum { |
| NOT_VALID, |
| PRESENT, |
| ABSENT |
| } ternary; |
| |
| typedef struct { |
| ternary freq100Hz; |
| ternary freq120Hz; |
| uint32_t mHz; |
| } ams_apiAlsFlicker_t; |
| |
| typedef struct { |
| uint32_t ir; |
| uint32_t red; |
| uint32_t green; |
| uint32_t blue; |
| uint32_t clear; |
| uint32_t wideband; |
| uint32_t rawClear; |
| uint32_t rawRed; |
| uint32_t rawGreen; |
| uint32_t rawBlue; |
| uint32_t rawWideband; |
| uint32_t time_us; |
| uint32_t gain; |
| } ams_apiAls_t; |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #define AMS_USEC_PER_TICK (2780) |
| #define ACTUAL_USEC(x) (((x + AMS_USEC_PER_TICK / 2) / AMS_USEC_PER_TICK) * AMS_USEC_PER_TICK) |
| #define AMS_ALS_USEC_TO_REG(x) (256 - (x / AMS_USEC_PER_TICK)) |
| #define AMS_DEFAULT_REPORTTIME_US (1000000) /* Max 8 seconds */ |
| #define AMS_PRX_PGLD_TO_REG(x) ((x-4)/8) |
| |
| #ifndef UINT_MAX_VALUE |
| #define UINT_MAX_VALUE (-1) |
| #endif |
| |
| #define AMS_CALIBRATION_DONE (-1) |
| #define AMS_CALIBRATION_DONE_BUT_FAILED (-2) |
| |
| typedef enum _deviceIdentifier_e { |
| AMS_UNKNOWN_DEVICE, |
| AMS_TCS3407, |
| AMS_TCS3407_UNTRIM, |
| AMS_TCS3408, |
| AMS_TCS3408_UNTRIM, |
| AMS_LAST_DEVICE |
| } ams_deviceIdentifier_e; |
| |
| /*TCS3407 */ |
| /*0x92 ID(0x18), 0x91 REVID(0x51)*/ |
| #define AMS_DEVICE_ID 0x18 |
| #define AMS_DEVICE_ID_MASK 0xFF |
| #define AMS_REV_ID 0x51 |
| #define AMS_REV_ID_UNTRIM 0x01 |
| #define AMS_REV_ID_MASK 0xFF |
| |
| |
| /*TCS3408 */ |
| /*0x92 ID(0x18), 0x91 REVID(0x53)*/ |
| #define AMS_DEVICE_ID2 0x18 |
| #define AMS_DEVICE_ID2_MASK 0xFF |
| #define AMS_REV_ID2 0x53 |
| #define AMS_REV_ID2_UNTRIM 0x03 |
| #define AMS_REV_ID2_MASK 0xFF |
| |
| |
| /*NOT USED*/ |
| #define AMS_DEVICE_ID3 0xEC |
| #define AMS_DEVICE_ID3_MASK 0xFC |
| #define AMS_REV_ID3 0x00 |
| #define AMS_REV_ID3_MASK 0x07 |
| |
| |
| |
| #define AMS_PRX_PERS_TO_REG(x) (x << 4) |
| #define AMS_PRX_REG_TO_PERS(x) (x >> 4) |
| #define AMS_PRX_CURRENT_TO_REG(mA) ((((mA) > 257) ? 127 : (((mA) - 4) >> 1)) << 0) |
| #define AMS_ALS_PERS_TO_REG(x) (x << 0) |
| #define AMS_ALS_REG_TO_PERS(x) (x >> 0) |
| |
| typedef enum _deviceRegisters { |
| DEVREG_RAM_START, |
| DEVREG_SMUX13_PRX_TO_FLICKER, |
| |
| DEVREG_ENABLE, |
| DEVREG_ATIME, |
| DEVREG_PTIME, |
| DEVREG_WTIME, |
| DEVREG_AILTL, |
| DEVREG_AILTH, |
| DEVREG_AIHTL, |
| DEVREG_AIHTH, |
| DEVREG_AUXID, |
| DEVREG_REVID, |
| DEVREG_ID, |
| DEVREG_STATUS, |
| DEVREG_ASTATUS, |
| DEVREG_ADATA0L, |
| DEVREG_ADATA0H, |
| DEVREG_ADATA1L, |
| DEVREG_ADATA1H, |
| DEVREG_ADATA2L, |
| DEVREG_ADATA2H, |
| DEVREG_ADATA3L, |
| DEVREG_ADATA3H, |
| DEVREG_ADATA4L, |
| DEVREG_ADATA4H, |
| DEVREG_ADATA5L, |
| DEVREG_ADATA5H, |
| DEVREG_STATUS2, |
| DEVREG_STATUS3, |
| DEVREG_STATUS5, |
| DEVREG_STATUS4, |
| DEVREG_CFG0, |
| DEVREG_CFG1, |
| DEVREG_CFG3, |
| DEVREG_CFG4, |
| DEVREG_CFG6, |
| DEVREG_CFG8, |
| DEVREG_CFG9, |
| DEVREG_CFG10, |
| DEVREG_CFG11, |
| DEVREG_CFG12, |
| DEVREG_PERS, |
| DEVREG_GPIO, |
| DEVREG_ASTEPL, |
| DEVREG_ASTEPH, |
| DEVREG_AGC_GAIN_MAX, |
| DEVREG_AZ_CONFIG, |
| DEVREG_FD_CFG0, |
| DEVREG_FD_CFG1, |
| DEVREG_FD_CFG2, |
| DEVREG_FD_CFG3, |
| DEVREG_FD_STATUS, |
| DEVREG_INTENAB, |
| DEVREG_CONTROL, |
| DEVREG_FIFO_MAP, |
| DEVREG_FIFO_STATUS, |
| DEVREG_FDATAL, |
| DEVREG_FDATAH, |
| DEVREG_FLKR_WA_RAMLOC_1, |
| DEVREG_FLKR_WA_RAMLOC_2, |
| DEVREG_SOFT_RESET, /* 0xF3 */ |
| |
| DEVREG_REG_MAX |
| } ams_deviceRegister_t; |
| |
| typedef enum _3407_regOptions { |
| PON = 0x01, /* register 0x80 */ |
| AEN = 0x02, |
| PEN = 0x04, |
| WEN = 0x08, |
| SMUXEN = 0x10, |
| /* reserved: 0x20 */ |
| FDEN = 0x40, |
| IBEN = 0x80, |
| |
| /* STATUS REG: Interrupts. All but FIFOINT are cleared by writing |
| * back a '1' bit. FIFOINT only clearable by emptying the FIFO. |
| */ |
| SINT = 0x01, /* register 0x93 */ |
| CINT = 0x02, |
| FIFOINT = 0x04, |
| AINT = 0x08, |
| PINT0 = 0x10, |
| PINT1 = 0x20, |
| PSAT = 0x40, |
| ASAT_FDSAT = 0x80, |
| ALS_INT_ALL = (AINT + ASAT_FDSAT), |
| PROX_INT_ALL_0 = (CINT + PINT0), |
| PROX_INT_ALL_1 = (CINT + PINT1), |
| PROX_INT_ALL_0_1 = (CINT + PINT0 + PINT1), |
| /*PROX_INT_ALL = (CINT + PINT0),*/ |
| FLICKER_INT_ALL = (SINT + FIFOINT + ASAT_FDSAT), |
| IRBEAM_INT = SINT, |
| |
| FDSAT_DIGITAL = 0x01, /* register 0xA3 */ |
| FDSAT_ANALOG = 0x02, |
| ASAT_ANALOG = 0x08, |
| ASAT_DIGITAL = 0x10, |
| AVALID = 0x40, |
| PVALID0 = 0x80, |
| |
| PSAT_AMB = 0x01, /* register 0xA4 */ |
| PSAT_REFL = 0x02, |
| PSAT_ADC = 0x04, |
| |
| PINT0_PILT = 0x01, /* register 0xA5 */ |
| PINT0_PIHT = 0x02, |
| PINT1_PILT = 0x04, |
| PINT1_PIHT = 0x08, |
| |
| /* ambient, prox threshold/hysteresis bits in 0xA4-A5: not used (yet?) */ |
| |
| IBUSY = 0x01, /* register 0xA6 */ |
| SINT_IRBEAM = 0x02, |
| SINT_SMUX = 0x04, |
| SINT_FD = 0x08, |
| SINT_ALS_MAN_AZ = 0x10, |
| SINT_AUX = 0x20, |
| |
| INIT_BUSY = 0x01, /* register 0xA7 */ |
| |
| RAM_BANK_0 = 0x00, /* register 0xA9 */ |
| RAM_BANK_1 = 0x01, |
| RAM_BANK_2 = 0x02, |
| RAM_BANK_3 = 0x03, |
| ALS_TRIG_LONG = 0x04, |
| PRX_TRIG_LONG = 0x08, |
| REG_BANK = 0x10, |
| LOWPWR_IDLE = 0x20, |
| PRX_OFFSET2X = 0x40, |
| PGOFF_HIRES = 0x80, |
| |
| AGAIN_1_HALF = 0x00, /* register 0xAA */ |
| AGAIN_1 = 0x01, |
| AGAIN_2 = 0x02, |
| AGAIN_4 = 0x03, |
| AGAIN_8 = 0x04, |
| AGAIN_16 = 0x05, |
| AGAIN_32 = 0x06, |
| AGAIN_64 = 0x07, |
| AGAIN_128 = 0x08, |
| AGAIN_256 = 0x09, |
| ALS_TRIG_FAST = 0x40, |
| S4S_MODE = 0x80, |
| |
| HXTALK_MODE1 = 0x20, /* register 0xAC */ |
| |
| SMUX_CMD_ROM_INIT = 0x00, /* register 0xAF */ |
| SMUX_CMD_READ = 0x08, |
| SMUX_CMD_WRITE = 0x10, |
| SMUX_CMD_ARRAY_MODE = 0x18, |
| |
| SWAP_PROX_ALS5 = 0x01, /* register 0xB1 */ |
| ALS_AGC_ENABLE = 0x04, |
| FD_AGC_ENABLE = 0x08, |
| PROX_BEFORE_EACH_ALS = 0x10, |
| |
| SIEN_AUX = 0x08, /* register 0xB2 */ |
| SIEN_SMUX = 0x10, |
| SIEN_ALS_MAN_AZ = 0x20, |
| SIEN_FD = 0x40, |
| SIEN_IRBEAM = 0x80, |
| |
| FD_PERS_ALWAYS = 0x00, /* register 0xB3 */ |
| FD_PERS_1 = 0x01, |
| FD_PERS_2 = 0x02, |
| FD_PERS_4 = 0x03, |
| FD_PERS_8 = 0x04, |
| FD_PERS_16 = 0x05, |
| FD_PERS_32 = 0x06, |
| FD_PERS_64 = 0x07, |
| |
| TRIGGER_APF_ALIGN = 0x10, /* register 0xB4 */ |
| PRX_TRIGGER_FAST = 0x20, |
| PINT_DIRECT = 0x40, |
| AINT_DIRECT = 0x80, |
| |
| PROX_FILTER_1 = 0x00, /* register 0xB8 */ |
| PROX_FILTER_2 = 0x01, |
| PROX_FILTER_4 = 0x02, |
| PROX_FILTER_8 = 0x03, |
| HXTALK_MODE2 = 0x80, |
| |
| PGAIN_1 = 0x00, /* register 0xBB */ |
| PGAIN_2 = 0x01, |
| PGAIN_4 = 0x02, |
| PGAIN_8 = 0x03, |
| |
| PPLEN_4uS = 0x00, /* register 0xBC */ |
| PPLEN_8uS = 0x01, |
| PPLEN_16uS = 0x02, |
| PPLEN_32uS = 0x03, |
| |
| FD_COMPARE_32_32NDS = 0x00, /* register 0xD7 */ |
| FD_COMPARE_24_32NDS = 0x01, |
| FD_COMPARE_16_32NDS = 0x02, |
| FD_COMPARE_12_32NDS = 0x03, |
| FD_COMPARE_8_32NDS = 0x04, |
| FD_COMPARE_6_32NDS = 0x05, |
| FD_COMPARE_4_32NDS = 0x06, |
| FD_COMPARE_3_32NDS = 0x07, |
| FD_SAMPLES_8 = 0x00, |
| FD_SAMPLES_16 = 0x08, |
| FD_SAMPLES_32 = 0x10, |
| FD_SAMPLES_64 = 0x18, |
| FD_SAMPLES_128 = 0x20, |
| FD_SAMPLES_256 = 0x28, |
| FD_SAMPLES_512 = 0x30, |
| FD_SAMPLES_1024 = 0x38, |
| |
| FD_GAIN_1_HALF = 0x00, /* register 0xDA */ |
| FD_GAIN_1 = 0x08, |
| FD_GAIN_2 = 0x10, |
| FD_GAIN_4 = 0x18, |
| FD_GAIN_8 = 0x20, |
| FD_GAIN_16 = 0x28, |
| FD_GAIN_32 = 0x30, |
| FD_GAIN_64 = 0x38, |
| FD_GAIN_128 = 0x40, |
| FD_GAIN_256 = 0x48, |
| |
| FD_100HZ_FLICKER = 0x01, /* register 0xDB */ |
| FD_120HZ_FLICKER = 0x02, |
| FD_100HZ_VALID = 0x04, |
| FD_120HZ_VALID = 0x08, |
| FD_SAT_DETECTED = 0x10, |
| FD_MEAS_VALID = 0x20, |
| |
| ISTART_MOBEAM = 0x01, /* register 0xE8 */ |
| ISTART_REMCON = 0x02, |
| |
| START_OFFSET_CALIB = 0x01, /* register 0xEA */ |
| |
| DCAVG_AUTO_BSLN = 0x80, /* register 0xEB */ |
| DCAVG_AUTO_OFFSET_ADJUST = 0x40, |
| BINSRCH_SKIP = 0x08, |
| |
| BASELINE_ADJUSTED = 0x04, /* register 0xEE */ |
| OFFSET_ADJUSTED = 0x02, |
| CALIB_FINISHED = 0x01, |
| |
| SIEN = 0x01, /* register 0xF9 */ |
| CIEN = 0x02, |
| FIEN = 0x04, |
| AIEN = 0x08, |
| PIEN0 = 0x10, |
| PIEN1 = 0x20, |
| PSIEN = 0x40, |
| ASIEN_FDSIEN = 0x80, |
| AMS_ALL_IENS = (AIEN+PIEN0+PIEN1+FIEN+CIEN), |
| LAST_IN_ENUM_LIST |
| } ams_regOptions_t; |
| |
| typedef enum _3407_regMasks { |
| MASK_PON = 0x01, /* register 0x80 */ |
| MASK_AEN = 0x02, |
| MASK_PEN = 0x04, |
| MASK_WEN = 0x08, |
| MASK_SMUXEN = 0x10, |
| MASK_FDEN = 0x40, |
| MASK_IBEN = 0x80, |
| |
| MASK_ATIME = 0xFF, /* register 0x81 */ |
| |
| MASK_PTIME = 0xFF, /* register 0x82 */ |
| |
| MASK_WTIME = 0xFF, /* register 0x83 */ |
| |
| MASK_AILT = 0xFFFF, /* register 0x84 */ |
| MASK_AILH = 0xFFFF, /* register 0x86 */ |
| |
| MASK_PILT = 0xFFFF, /* register 0x88 */ |
| MASK_PILH = 0xFFFF, /* register 0x8A */ |
| |
| MASK_AUXID = 0x0F, /* register 0x90 */ |
| |
| MASK_REV_ID = 0x07, /* register 0x91 */ |
| |
| MASK_ID = 0xFC, /* register 0x92 */ |
| |
| MASK_SINT = 0x01, /* register 0x93 */ |
| MASK_CINT = 0x02, |
| MASK_FINT = 0x04, |
| MASK_AINT = 0x08, |
| MASK_PINT0 = 0x10, |
| MASK_PINT1 = 0x20, |
| MASK_PSAT = 0x40, |
| MASK_ASAT_FDSAT = 0x80, |
| MASK_ALS_INT_ALL = MASK_AINT, |
| MASK_PROX_INT_ALL_0 = (MASK_PINT0 | MASK_PSAT), |
| MASK_PROX_INT_ALL_1 = (MASK_PINT1 | MASK_PSAT), |
| MASK_PROX_INT_ALL_0_1 = (MASK_PINT0 | MASK_PINT1 | MASK_PSAT), |
| /*MASK_PROX_INT_ALL = (MASK_PINT0),*/ |
| MASK_INT_ALL = (0xFF), |
| |
| MASK_ADATA = 0xFFFF, /* registers 0x95-0xA0 */ |
| |
| MASK_ASAT_ANALOG = 0x08, /* register 0xA3 */ |
| MASK_ASAT_DIGITAL = 0x10, |
| MASK_AVALID = 0x40, |
| MASK_PVALID0 = 0x80, |
| |
| MASK_PSAT_AMB = 0x01, /* register 0xA4 */ |
| MASK_PSAT_REFL = 0x02, |
| MASK_PSAT_ADC = 0x04, |
| |
| MASK_RAM_BANK = 0x03, /* register 0xA9 */ |
| |
| MASK_AGAIN = 0x1F, /* register 0xAA */ |
| |
| MASK_HXTALK_MODE1 = 0x20, /* register 0xAC */ |
| |
| MASK_SMUX_CMD = 0x18, /* register 0xAF */ |
| |
| MASK_AUTOGAIN = 0x04, /* register 0xB1 */ |
| MASK_PROX_BEFORE_EACH_ALS = 0x10, |
| |
| MASK_SIEN_FD = 0x40, /* register 0xB2 */ |
| MASK_SIEN_IRBEAM = 0x80, |
| |
| MASK_FD_PERS = 0x07, /* register 0xB3 */ |
| MASK_AGC_HYST_LOW = 0x30, |
| MASK_AGC_HYST_HIGH = 0xC0, |
| |
| MASK_PRX_TRIGGER_FAST = 0x20, /* register 0xB4 */ |
| MASK_PINT_DIRECT = 0x40, |
| MASK_AINT_DIRECT = 0x80, |
| |
| MASK_PROX_FILTER = 0x03, /* register 0xB8 */ |
| MASK_HXTALK_MODE2 = 0x80, |
| |
| MASK_PLDRIVE0 = 0x7f, /* register 0xB9 */ |
| |
| MASK_APERS = 0x0F, /* register 0xBD */ |
| MASK_PPERS = 0xF0, |
| |
| MASK_PPULSE = 0x3F, /* register 0xBC */ |
| MASK_PPLEN = 0xC0, |
| |
| MASK_PGAIN = 0x03, /* register 0xBB */ |
| |
| MASK_PLDRIVE = 0x7F, /* Registers 0xB9, 0xBA */ |
| |
| MASK_FD_TIME_MSBits = 0x07, /* Register 0xDA */ |
| |
| MASK_100HZ_FLICKER = 0x05, /* Register 0xDB */ |
| MASK_120HZ_FLICKER = 0x0A, |
| MASK_CLEAR_FLICKER_STATUS = 0x3C, |
| MASK_FLICKER_VALID = 0x2C, |
| |
| MASK_SLEW = 0x10, /* register E0 */ |
| MASK_ISQZT = 0x07, |
| |
| MASK_OFFSET_CALIB = 0x01, /* register 0xEA */ |
| |
| MASK_DCAVG_AUTO_BSLN = 0x80, /* register 0xEB */ |
| MASK_BINSRCH_SKIP = 0x08, |
| |
| MASK_PROX_AUTO_OFFSET_ADJUST = 0x40, /* register 0xEC */ |
| MASK_PXAVG_AUTO_BSLN = 0x08, /* register 0xEC */ |
| |
| MASK_BINSRCH_TARGET = 0xE0, /* register 0xED */ |
| |
| MASK_SIEN = 0x01, /* register 0xF9 */ |
| MASK_CIEN = 0x02, |
| MASK_FIEN = 0x04, |
| MASK_AIEN = 0x08, |
| MASK_PIEN0 = 0x10, |
| MASK_PIEN1 = 0x20, |
| MASK_PSIEN = 0x40, |
| MASK_ASIEN_FDSIEN = 0x80, |
| |
| MASK_AGC_HYST = 0x30, |
| MASK_AGC_LOW_HYST = 0x30, |
| MASK_AGC_HIGH_HYST = 0xC0, |
| |
| MASK_SOFT_RESET = 0x04, /* register 0xF3 */ |
| |
| MASK_LAST_IN_ENUMLIST |
| } ams_regMask_t; |
| |
| |
| #define AMS_ENABLE_ALS_EX() {ctx->shadowEnableReg |= (AEN); \ |
| ams_setByte(ctx->portHndl, DEVREG_ENABLE, ctx->shadowEnableReg); \ |
| ams_setField(ctx->portHndl, DEVREG_INTENAB, HIGH, (MASK_AIEN | MASK_ASIEN_FDSIEN));\ |
| } |
| #define AMS_DISABLE_ALS_EX() {ctx->shadowEnableReg &= ~(AEN); \ |
| ams_setByte(ctx->portHndl, DEVREG_ENABLE, ctx->shadowEnableReg); \ |
| ams_setField(ctx->portHndl, DEVREG_INTENAB, LOW, (MASK_AIEN | MASK_ASIEN_FDSIEN));\ |
| } |
| |
| typedef struct _deviceRegisterTable { |
| uint8_t address; |
| uint8_t resetValue; |
| } deviceRegisterTable_t; |
| |
| typedef enum _3407_config_options { |
| AMS_CONFIG_ENABLE, |
| AMS_CONFIG_THRESHOLD, |
| AMS_CONFIG_OPTION_LAST |
| } deviceConfigOptions_t; |
| |
| typedef enum _3407_mode { |
| MODE_OFF = (0), |
| MODE_ALS_LUX = (1 << 0), |
| MODE_ALS_RGB = (1 << 1), |
| MODE_ALS_CT = (1 << 2), |
| MODE_ALS_WIDEBAND = (1 << 3), |
| MODE_ALS_ALL = (MODE_ALS_LUX | MODE_ALS_RGB | MODE_ALS_CT | MODE_ALS_WIDEBAND), |
| MODE_FLICKER = (1 << 4), /* is independent of ALS in this model */ |
| MODE_PROX = (1 << 5), |
| MODE_IRBEAM = (1 << 6), |
| MODE_UNKNOWN /* must be in last position */ |
| } ams_mode_t; |
| |
| typedef enum _3407_configureFeature { |
| AMS_CONFIG_PROX, |
| AMS_CONFIG_ALS_LUX, |
| AMS_CONFIG_ALS_RGB, |
| AMS_CONFIG_ALS_CT, |
| AMS_CONFIG_ALS_WIDEBAND, |
| AMS_CONFIG_FLICKER, |
| AMS_CONFIG_MOBEAM, |
| AMS_CONFIG_REMCON, |
| AMS_CONFIG_FEATURE_LAST |
| } ams_configureFeature_t; |
| |
| typedef struct _calibrationData { |
| uint32_t timeBase_us; |
| uint32_t adcMaxCount; |
| uint8_t alsThresholdHigh; /* in % */ |
| uint8_t alsThresholdLow; /* in % */ |
| uint16_t alsCalibrationFactor; /* multiplicative factor default 1000 */ |
| char deviceName[8]; |
| int32_t alsCoefC; |
| int32_t alsCoefR; |
| int32_t alsCoefG; |
| int32_t alsCoefB; |
| int16_t alsDfg; |
| uint16_t alsCctOffset; |
| uint16_t alsCctCoef; |
| int32_t Wbc; |
| } ams_calibrationData_t; |
| |
| typedef struct _flickerParams { |
| uint32_t samplePeriod_us; |
| uint16_t gain; |
| uint8_t compare; |
| uint8_t statusReg; |
| ams_apiAlsFlicker_t lastValid; |
| } ams_flicker_ctx_t; |
| |
| typedef struct _3407Context { |
| ams_deviceIdentifier_e deviceId; |
| uint64_t timeStamp; |
| AMS_PORT_portHndl *portHndl; |
| ams_mode_t mode; |
| #ifdef AMS_PHY_SUPPORT_SHADOW |
| uint8_t shadow[DEVREG_REG_MAX]; |
| #endif |
| // ams_ccb_proximity_ctx_t ccbProxCtx; |
| ams_ccb_als_ctx_t ccbAlsCtx; |
| // ams_ccb_irBeam_ctx_t ccbIrBeamCtx; |
| ams_flicker_ctx_t flickerCtx; |
| ams_calibrationData_t *systemCalibrationData; |
| |
| bool alwaysReadAls; /* read ADATA every ams_deviceEventHandler call regardless of xINT bits */ |
| bool alwaysReadProx; /* ditto PDATA */ |
| bool alwaysReadFlicker; |
| |
| uint32_t updateAvailable; |
| uint8_t shadowEnableReg; |
| uint8_t shadowIntenabReg; |
| uint8_t shadowStatus1Reg; |
| uint8_t shadowStatus2Reg; |
| } ams_deviceCtx_t; |
| |
| typedef enum _sensorType { |
| AMS_NO_SENSOR_AVAILABLE, |
| AMS_AMBIENT_SENSOR, |
| AMS_FLICKER_SENSOR, |
| AMS_PROXIMITY_SENSOR, |
| AMS_WIDEBAND_ALS_SENSOR, |
| AMS_LAST_SENSOR, |
| AMS_ALS_RGB_GAIN_CHANGED |
| } ams_sensorType_t; |
| |
| typedef struct _sensorInfo { |
| uint32_t standbyCurrent_uA; |
| uint32_t activeCurrent_uA; |
| uint32_t rangeMin; |
| uint32_t rangeMax; |
| char *driverName; |
| uint8_t maxPolRate; |
| uint8_t adcBits; |
| } ams_SensorInfo_t; |
| |
| typedef struct _deviceInfo { |
| uint32_t memorySize; |
| ams_calibrationData_t defaultCalibrationData; |
| ams_SensorInfo_t proxSensor; |
| ams_SensorInfo_t alsSensor; |
| ams_SensorInfo_t mobeamSensor; |
| ams_SensorInfo_t remconSensor; |
| ams_sensorType_t tableSubSensors[10]; |
| uint8_t numberOfSubSensors; |
| char *driverVersion; |
| char *deviceModel; |
| char *deviceName; |
| } ams_deviceInfo_t; |
| |
| |
| /* #define ALS_DBG */ |
| /* #define ALS_INFO */ |
| |
| #ifndef ALS_dbg |
| #ifdef ALS_DBG |
| #define ALS_dbg(format, arg...) \ |
| printk(KERN_DEBUG "ALS_dbg : "format, ##arg) |
| #define ALS_err(format, arg...) \ |
| printk(KERN_DEBUG "ALS_err : "format, ##arg) |
| #else |
| #define ALS_dbg(format, arg...) {if (als_debug)\ |
| printk(KERN_DEBUG "ALS_dbg : "format, ##arg);\ |
| } |
| #define ALS_err(format, arg...) {if (als_debug)\ |
| printk(KERN_DEBUG "ALS_err : "format, ##arg);\ |
| } |
| #endif |
| #endif |
| |
| #ifndef ALS_info |
| #ifdef ALS_INFO |
| #define ALS_info(format, arg...) \ |
| printk(KERN_INFO "ALS_info : "format, ##arg) |
| #else |
| #define ALS_info(format, arg...) {if (als_info)\ |
| printk(KERN_INFO "ALS_info : "format, ##arg);\ |
| } |
| #endif |
| #endif |
| |
| enum { |
| DEBUG_REG_STATUS = 1, |
| DEBUG_VAR, |
| }; |
| |
| struct mode_count { |
| s32 hrm_cnt; |
| s32 amb_cnt; |
| s32 prox_cnt; |
| s32 sdk_cnt; |
| s32 cgm_cnt; |
| s32 unkn_cnt; |
| }; |
| |
| enum platform_pwr_state { |
| POWER_ON, |
| POWER_OFF, |
| POWER_STANDBY, |
| }; |
| |
| struct tcs3407_parameters { |
| /* Common */ |
| u8 persist; |
| /* ALS / Color */ |
| u8 als_gain; |
| u8 als_auto_gain; |
| u16 als_deltaP; |
| u8 als_time; |
| }; |
| |
| // Must match definition in ../arch file |
| struct amsdriver_i2c_platform_data { |
| /* The following callback for power events received and handled by the driver. |
| * Currently only for SUSPEND and RESUME |
| */ |
| int (*platform_power)(struct device *dev, enum platform_pwr_state state); |
| int (*platform_init)(void); |
| void (*platform_teardown)(struct device *dev); |
| bool haveCalibrationData; |
| char const *als_name; |
| struct tcs3407_parameters parameters; |
| #ifdef CONFIG_OF |
| struct device_node *of_node; |
| #endif |
| }; |
| |
| #ifdef CONFIG_AMS_OPTICAL_SENSOR_EOL_MODE |
| enum { |
| EOL_STATE_INIT = -1, |
| EOL_STATE_100, |
| EOL_STATE_120, |
| EOL_STATE_DONE |
| }; |
| #endif |
| |
| struct tcs3407_device_data { |
| struct i2c_client *client; |
| struct amsdriver_i2c_platform_data *pdata; |
| int in_suspend; |
| int wake_irq; |
| int irq_pending; |
| bool unpowered; |
| u8 device_index; |
| void *deviceCtx; |
| |
| struct device *dev; |
| struct input_dev *als_input_dev; |
| struct mutex i2clock; |
| struct mutex activelock; |
| struct mutex suspendlock; |
| struct mutex flickerdatalock; |
| struct miscdevice miscdev; |
| struct pinctrl *als_pinctrl; |
| struct pinctrl_state *pins_sleep; |
| struct pinctrl_state *pins_idle; |
| char *vdd_1p8; |
| char *i2c_1p8; |
| u8 enabled; |
| u32 sampling_period_ns; |
| u8 regulator_state; |
| s32 pin_als_int; |
| s32 pin_als_en; |
| s32 dev_irq; |
| u8 irq_state; |
| u32 reg_read_buf; |
| u32 debug_mode; |
| struct mode_count mode_cnt; |
| #ifdef CONFIG_ARCH_QCOM |
| struct pm_qos_request pm_qos_req_fpm; |
| #endif |
| bool pm_state; |
| int isTrimmed; |
| |
| u8 part_type; |
| u32 i2c_err_cnt; |
| u32 user_ir_data; |
| u32 user_flicker_data; |
| #ifdef CONFIG_AMS_OPTICAL_SENSOR_EOL_MODE |
| char *eol_result; |
| u8 eol_enable; |
| u8 eol_result_status; |
| s16 eol_state; |
| u32 eol_count; |
| u32 eol_awb; |
| u32 eol_clear; |
| u32 eol_flicker; |
| u8 eol_flicker_count; |
| u32 eol_flicker_awb[6][3]; |
| u32 eol_pulse_duty[2]; |
| u32 eol_pulse_count; |
| u32 eol_ir_spec[4]; |
| u32 eol_clear_spec[4]; |
| u32 eol_icratio_spec[4]; |
| s32 pin_led_en; |
| struct pinctrl_state *pinctrl_pwm; |
| struct pinctrl_state *pinctrl_out; |
| struct pwm_device *pwm; |
| #endif |
| |
| #ifdef CONFIG_AMS_OPTICAL_SENSOR_FIFO |
| u16 awb_sample_cnt; |
| int *flicker_data; |
| int flicker_data_cnt; |
| u8 fifodata[256]; |
| #endif |
| }; |
| |
| #define AMSDRIVER_ALS_ENABLE 1 |
| #define AMSDRIVER_ALS_DISABLE 0 |
| #define AMSDRIVER_FLICKER_ENABLE 1 |
| #define AMSDRIVER_FLICKER_DISABLE 0 |
| |
| |
| #ifdef CONFIG_ARCH_QCOM |
| extern int sensors_create_symlink(struct kobject *target, const char *name); |
| extern void sensors_remove_symlink(struct kobject *target, const char *name); |
| extern int sensors_register(struct device **dev, void *drvdata, |
| struct device_attribute *attributes[], char *name); |
| #else |
| extern int sensors_create_symlink(struct input_dev *inputdev); |
| extern void sensors_remove_symlink(struct input_dev *inputdev); |
| extern int sensors_register(struct device *dev, void *drvdata, |
| struct device_attribute *attributes[], char *name); |
| #endif |
| extern void sensors_unregister(struct device *dev, |
| struct device_attribute *attributes[]); |
| |
| extern unsigned int lpcharge; |
| |
| #endif /* __AMS_TCS3407_H */ |