diff --git a/drivers/input/sensors/lsensor/Kconfig b/drivers/input/sensors/lsensor/Kconfig index 8ea493862dd3..57aef5dbb788 100644 --- a/drivers/input/sensors/lsensor/Kconfig +++ b/drivers/input/sensors/lsensor/Kconfig @@ -11,27 +11,27 @@ if LIGHT_DEVICE config LS_CM3217 tristate "light sensor cm3217" default n - + config LS_CM3218 tristate "light sensor cm3218" default n - + config LS_CM3232 tristate "light sensor cm3232" default n - + config LS_AL3006 tristate "light sensor al3006" default n config LS_STK3171 tristate "light sensor stk3171" - default n + default n config LS_ISL29023 tristate "light sensor isl29023" - default n - + default n + config LS_AP321XX tristate "light sensor ap321xx" default n @@ -40,6 +40,9 @@ config LS_US5152 tristate "light sensor us5152" default n +config LS_STK3332 + tristate "light sensor stk3332" + config LS_STK3410 tristate "light sensor stk3410" default n diff --git a/drivers/input/sensors/lsensor/Makefile b/drivers/input/sensors/lsensor/Makefile index aa8bf78f440c..e85dc1491f4f 100644 --- a/drivers/input/sensors/lsensor/Makefile +++ b/drivers/input/sensors/lsensor/Makefile @@ -9,5 +9,6 @@ obj-$(CONFIG_LS_STK3171) += ls_stk3171.o obj-$(CONFIG_LS_ISL29023) += isl29023.o obj-$(CONFIG_LS_AP321XX) += ls_ap321xx.o obj-$(CONFIG_LS_US5152) += ls_us5152.o +obj-$(CONFIG_LS_STK3332) += ls_stk3332.o obj-$(CONFIG_LS_STK3410) += ls_stk3410.o obj-$(CONFIG_LS_EM3071X) += ls_em3071x.o diff --git a/drivers/input/sensors/lsensor/ls_stk3332.c b/drivers/input/sensors/lsensor/ls_stk3332.c new file mode 100644 index 000000000000..dd006e108bba --- /dev/null +++ b/drivers/input/sensors/lsensor/ls_stk3332.c @@ -0,0 +1,372 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021 Rockchip Electronics Co. Ltd. + * + * Author: Kay Guo + */ +#include +#include +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define STK_STATE 0x00 +#define PS_CTRL 0x01 +#define ALS_CTRL1 0x02 +#define LED_CTRL 0x03 +#define INT_CTRL1 0x04 +#define STK_WAIT 0x05 +#define THDH1_PS 0x06 +#define THDH2_PS 0x07 +#define THDL1_PS 0x08 +#define THDL2_PS 0x09 +#define THDH1_ALS 0x0A +#define THDH2_ALS 0x0B +#define THDL1_ALS 0x0C +#define THDL2_ALS 0x0D +#define STK_FLAG 0x10 +#define DATA1_PS 0x11 +#define DATA2_PS 0x12 +#define DATA1_ALS 0x13 +#define DATA2_ALS 0x14 +#define DATA1_C 0x1B +#define DATA2_C 0x1C +#define DATA1_PS_OFFSET 0x1D +#define DATA2_PS_OFFSET 0x1E +#define DATA_CTRL1 0x20 +#define DATA_CTRL2 0x21 +#define DATA_CTRL3 0x22 +#define DATA_CTRL4 0x23 +#define STKPDT_ID 0x3E +#define STK_RESERVED 0x3F +#define ALS_CTRL2 0x4E +#define INTELLI_WAIT 0x4F +#define SOFT_RESET 0x80 +#define PSPD_CTRL 0xA1 +#define INT_CTRL2 0xA5 + +/* STK_STATE 0x00 */ +#define PS_DISABLE (0 << 0) +#define PS_ENABLE (1 << 0) +#define ALS_DISABLE (0 << 1) +#define ALS_ENABLE (1 << 1) +#define WAIT_DISABLE (0 << 2) +#define WAIT_ENABLE (1 << 2) +#define INTELLI_DISABLE (0 << 3) +#define INTELLI_ENABLE (1 << 3) +#define CTAUTOK_DISABLE (0 << 4) +#define CTAUTOK_ENABLE (1 << 4) + +/* PS/GS_CTRL 0x01 */ +#define PS_IT_96US (0 << 0) +#define PS_IT_192US (1 << 0) +#define PS_IT_384US (2 << 0) +#define PS_IT_768US (3 << 0) +#define PS_IT_1MS54 (4 << 0) +#define PS_IT_3MS07 (5 << 0) +#define PS_IT_6MS14 (6 << 0) + +#define PS_GAIN_1G (0 << 4) +#define PS_GAIN_2G (1 << 4) +#define PS_GAIN_4G (2 << 4) +#define PS_GAIN_8G (3 << 4) +#define PS_PRST_1T (0 << 6) +#define PS_PRST_2T (1 << 6) +#define PS_PRST_4T (2 << 6) +#define PS_PRST_16T (3 << 6) + +/* ALS_CTRL1 0x02 */ +#define ALS_REFT_MS (1 << 0)/* [3:0] 25 ms, default value is 50ms */ +#define ALS_GAIN_1G (0 << 4) +#define ALS_GAIN_4G (1 << 4) +#define ALS_GAIN_16G (2 << 4) +#define ALS_GAIN_64G (3 << 4) +#define ALS_PRST_1T (0 << 6) +#define ALS_PRST_2T (1 << 6) +#define ALS_PRST_4T (2 << 6) +#define ALS_PRST_8T (3 << 6) + +/* LED_CTRL 0x03 */ +#define LED_REFT_US 0x03 /* [5:0] 2.89us , default value is 0.185ms */ +#define CTIR_DISABLE (0 << 0) +#define CTIR_ENABLE (1 << 0) +#define CTIRFC_DISABLE (0 << 1) +#define CTIRFC_ENABLE (1 << 1) +#define LED_CUR_12MA (2 << 5) +#define LED_CUR_25MA (3 << 5) +#define LED_CUR_50MA (4 << 5) +#define LED_CUR_100MA (5 << 5) +#define LED_CUR_150MA (6 << 5) + +/* INT 0x04 */ +#define PS_INT_DISABLE (0 << 0) +#define PS_INT_ENABLE (1 << 0) +#define PS_INT_ENABLE_FLGNFH (2 << 0) +#define PS_INT_ENABLE_FLGNFL (3 << 0) +#define PS_INT_MODE_ENABLE (4 << 0) +#define PS_INT_ENABLE_THL (5 << 0) +#define PS_INT_ENABLE_THH (6 << 0) +#define PS_INT_ENABLE_THHL (7 << 0) +#define ALS_INT_DISABLE (0 << 3) +#define ALS_INT_ENABLE (1 << 3) +#define INT_CTRL_PS_OR_LS (0 << 7) +#define INT_CTRL_PS_AND_LS (1 << 7) + +/* FLAG 0x10 */ +#define STK_FLAG_NF (1 << 0) +#define STK_FLAG_INPS_INT (1 << 1) +#define STK_FLAG_ALS_STATE (1 << 2) +#define STK_FLAG_PS_INT (1 << 4) +#define STK_FLAG_ALS_INT (1 << 5) +#define STK_FLAG_PSDR (1 << 6) +#define STK_FLAG_ALSDR (1 << 7) + +static int sensor_active(struct i2c_client *client, int enable, int rate) +{ + struct sensor_private_data *sensor = + (struct sensor_private_data *)i2c_get_clientdata(client); + int result = 0; + int status = 0; + + sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg); + if (!enable) { + status = ~ALS_ENABLE; + sensor->ops->ctrl_data &= status; + } else { + status |= ALS_ENABLE; + sensor->ops->ctrl_data |= status; + } + + dev_dbg(&client->dev, "reg=0x%x, reg_ctrl=0x%x, enable=%d\n", + sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable); + + result = sensor_write_reg(client, sensor->ops->ctrl_reg, + sensor->ops->ctrl_data); + if (result) + dev_err(&client->dev, "%s:fail to active sensor\n", __func__); + + return result; +} + +static int sensor_init(struct i2c_client *client) +{ + struct sensor_private_data *sensor = + (struct sensor_private_data *)i2c_get_clientdata(client); + struct device_node *np = client->dev.of_node; + int als_val = 0; + int val = 0; + int ret = 0; + + ret = sensor->ops->active(client, 0, 0); + if (ret) { + dev_err(&client->dev, "%s:sensor active fail\n", __func__); + return ret; + } + sensor->status_cur = SENSOR_OFF; + + ret = of_property_read_u32(np, "als_threshold_low", &als_val); + if (ret) + dev_err(&client->dev, "%s:Unable to read als_threshold_low\n", + __func__); + ret = sensor_write_reg(client, THDL1_ALS, + (unsigned char)(als_val >> 8)); + if (ret) { + dev_err(&client->dev, "%s:write THDL1_ALS fail\n", __func__); + return ret; + } + + ret = sensor_write_reg(client, THDL2_ALS, (unsigned char)als_val); + if (ret) { + dev_err(&client->dev, "%s:write THDL1_ALS fail\n", __func__); + return ret; + } + + ret = of_property_read_u32(np, "als_threshold_high", &als_val); + if (ret) + dev_err(&client->dev, "%s:Unable to read als_threshold_high\n", + __func__); + + ret = sensor_write_reg(client, THDH1_ALS, + (unsigned char)(als_val >> 8)); + if (ret) { + dev_err(&client->dev, "%s:write THDH1_ALS fail\n", __func__); + return ret; + } + + ret = sensor_write_reg(client, THDH2_ALS, (unsigned char)als_val); + if (ret) { + dev_err(&client->dev, "%s:write THDH1_ALS fail\n", __func__); + return ret; + } + + ret = of_property_read_u32(np, "als_ctrl_gain", &als_val); + if (ret) + dev_err(&client->dev, "%s:Unable to read als_ctrl_gain\n", + __func__); + + ret = sensor_write_reg(client, ALS_CTRL1, + (unsigned char)((als_val << 4) | ALS_REFT_MS)); + if (ret) { + dev_err(&client->dev, "%s:write ALS_CTRL fail\n", __func__); + return ret; + } + + val = sensor_read_reg(client, INT_CTRL1); + val &= ~INT_CTRL_PS_AND_LS; + if (sensor->pdata->irq_enable) + val |= ALS_INT_ENABLE; + else + val &= ~ALS_INT_ENABLE; + ret = sensor_write_reg(client, INT_CTRL1, val); + if (ret) { + dev_err(&client->dev, "%s:write INT_CTRL1 fail\n", __func__); + return ret; + } + + return ret; +} + +static int light_report_value(struct input_dev *input, int data) +{ + unsigned char index = 0; + + if (data <= 100) { + index = 0; + goto report; + } else if (data <= 1600) { + index = 1; + goto report; + } else if (data <= 2250) { + index = 2; + goto report; + } else if (data <= 3200) { + index = 3; + goto report; + } else if (data <= 6400) { + index = 4; + goto report; + } else if (data <= 12800) { + index = 5; + goto report; + } else if (data <= 26000) { + index = 6; + goto report; + } else { + index = 7; + goto report; + } + +report: + input_report_abs(input, ABS_MISC, index); + input_sync(input); + return index; +} + +static int sensor_report_value(struct i2c_client *client) +{ + struct sensor_private_data *sensor = + (struct sensor_private_data *)i2c_get_clientdata(client); + int result = 0; + int value = 0; + int index = 0; + char buffer[2] = { 0 }; + + if (sensor->ops->read_len < 2) { + dev_err(&client->dev, "%s:length is error, len=%d\n", __func__, + sensor->ops->read_len); + return -EINVAL; + } + + buffer[0] = sensor->ops->read_reg; + result = sensor_rx_data(client, buffer, sensor->ops->read_len); + if (result) { + dev_err(&client->dev, "%s:sensor read data fail\n", __func__); + return result; + } + value = (buffer[0] << 8) | buffer[1]; + index = light_report_value(sensor->input_dev, value); + dev_dbg(&client->dev, "%s result=0x%x, index=%d\n", + sensor->ops->name, value, index); + + if (sensor->pdata->irq_enable && sensor->ops->int_status_reg) { + value = sensor_read_reg(client, sensor->ops->int_status_reg); + if (value & STK_FLAG_ALS_INT) { + value &= ~STK_FLAG_ALS_INT; + result = sensor_write_reg(client, + sensor->ops->int_status_reg, + value); + if (result) { + dev_err(&client->dev, "write status reg error\n"); + return result; + } + } + } + + return result; +} + +struct sensor_operate light_stk3332_ops = { + .name = "ls_stk3332", + .type = SENSOR_TYPE_LIGHT, + .id_i2c = LIGHT_ID_STK3332, + .read_reg = DATA1_ALS, + .read_len = 2, + .id_reg = SENSOR_UNKNOW_DATA, + .id_data = SENSOR_UNKNOW_DATA, + .precision = 16, + .ctrl_reg = STK_STATE, + .int_status_reg = STK_FLAG, + .range = { 100, 65535 }, + .brightness = { 10, 255 }, + .trig = IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED, + .active = sensor_active, + .init = sensor_init, + .report = sensor_report_value, +}; + +static int light_stk3332_probe(struct i2c_client *client, + const struct i2c_device_id *devid) +{ + return sensor_register_device(client, NULL, devid, &light_stk3332_ops); +} + +static int light_stk3332_remove(struct i2c_client *client) +{ + return sensor_unregister_device(client, NULL, &light_stk3332_ops); +} + +static const struct i2c_device_id light_stk3332_id[] = { + { "ls_stk3332", LIGHT_ID_STK3332 }, + {} +}; + +static struct i2c_driver light_stk3332_driver = { + .probe = light_stk3332_probe, + .remove = light_stk3332_remove, + .shutdown = sensor_shutdown, + .id_table = light_stk3332_id, + .driver = { + .name = "light_stk3332", +#ifdef CONFIG_PM + .pm = &sensor_pm_ops, +#endif + }, +}; + +module_i2c_driver(light_stk3332_driver); + +MODULE_AUTHOR("Kay Guo "); +MODULE_DESCRIPTION("stk3332 light driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/sensors/psensor/Kconfig b/drivers/input/sensors/psensor/Kconfig index c7d32f51e7d0..7b1ba342a626 100644 --- a/drivers/input/sensors/psensor/Kconfig +++ b/drivers/input/sensors/psensor/Kconfig @@ -5,7 +5,7 @@ menuconfig PROXIMITY_DEVICE tristate "proximity sensor device support" - default n + default n if PROXIMITY_DEVICE @@ -21,6 +21,9 @@ config PS_AP321XX tristate "psensor ap321xx" default n +config PS_STK3332 + tristate "proximity sensor stk3332" + config PS_STK3410 tristate "proximity sensor stk3410" default n diff --git a/drivers/input/sensors/psensor/Makefile b/drivers/input/sensors/psensor/Makefile index 49210d0e71cc..5ff2354a7bc6 100644 --- a/drivers/input/sensors/psensor/Makefile +++ b/drivers/input/sensors/psensor/Makefile @@ -4,5 +4,6 @@ obj-$(CONFIG_PS_AL3006) += ps_al3006.o obj-$(CONFIG_PS_STK3171) += ps_stk3171.o obj-$(CONFIG_PS_AP321XX) += ps_ap321xx.o +obj-$(CONFIG_PS_STK3332) += ps_stk3332.o obj-$(CONFIG_PS_STK3410) += ps_stk3410.o obj-$(CONFIG_PS_EM3071X) += ps_em3071x.o diff --git a/drivers/input/sensors/psensor/ps_stk3332.c b/drivers/input/sensors/psensor/ps_stk3332.c new file mode 100644 index 000000000000..a59747e83b5b --- /dev/null +++ b/drivers/input/sensors/psensor/ps_stk3332.c @@ -0,0 +1,383 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021 Rockchip Electronics Co. Ltd. + * + * Author: Kay Guo + */ +#include +#include +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define STK_STATE 0x00 +#define PS_CTRL 0x01 +#define ALS_CTRL1 0x02 +#define LED_CTRL 0x03 +#define INT_CTRL1 0x04 +#define STK_WAIT 0x05 +#define THDH1_PS 0x06 +#define THDH2_PS 0x07 +#define THDL1_PS 0x08 +#define THDL2_PS 0x09 +#define THDH1_ALS 0x0A +#define THDH2_ALS 0x0B +#define THDL1_ALS 0x0C +#define THDL2_ALS 0x0D +#define STK_FLAG 0x10 +#define DATA1_PS 0x11 +#define DATA2_PS 0x12 +#define DATA1_ALS 0x13 +#define DATA2_ALS 0x14 +#define DATA1_C 0x1B +#define DATA2_C 0x1C +#define DATA1_PS_OFFSET 0x1D +#define DATA2_PS_OFFSET 0x1E +#define DATA_CTRL1 0x20 +#define DATA_CTRL2 0x21 +#define DATA_CTRL3 0x22 +#define DATA_CTRL4 0x23 +#define STKPDT_ID 0x3E +#define STK_RESERVED 0x3F +#define ALS_CTRL2 0x4E +#define INTELLI_WAIT 0x4F +#define SOFT_RESET 0x80 +#define PSPD_CTRL 0xA1 +#define INT_CTRL2 0xA5 + +/* STK_STATE 0x00 */ +#define PS_DISABLE (0 << 0) +#define PS_ENABLE (1 << 0) +#define ALS_DISABLE (0 << 1) +#define ALS_ENABLE (1 << 1) +#define WAIT_DISABLE (0 << 2) +#define WAIT_ENABLE (1 << 2) +#define INTELLI_DISABLE (0 << 3) +#define INTELLI_ENABLE (1 << 3) +#define CTAUTOK_DISABLE (0 << 4) +#define CTAUTOK_ENABLE (1 << 4) + +/* PS/GS_CTRL 0x01 */ +#define PS_IT_96US (0 << 0) +#define PS_IT_192US (1 << 0) +#define PS_IT_384US (2 << 0) +#define PS_IT_768US (3 << 0) +#define PS_IT_1MS54 (4 << 0) +#define PS_IT_3MS07 (5 << 0) +#define PS_IT_6MS14 (6 << 0) + +#define PS_GAIN_1G (0 << 4) +#define PS_GAIN_2G (1 << 4) +#define PS_GAIN_4G (2 << 4) +#define PS_GAIN_8G (3 << 4) +#define PS_PRST_1T (0 << 6) +#define PS_PRST_2T (1 << 6) +#define PS_PRST_4T (2 << 6) +#define PS_PRST_16T (3 << 6) + +/* ALS_CTRL1 0x02 */ +#define ALS_REFT_MS (1 << 0)/* [3:0] 25 ms, default value is 50ms */ +#define ALS_GAIN_1G (0 << 4) +#define ALS_GAIN_4G (1 << 4) +#define ALS_GAIN_16G (2 << 4) +#define ALS_GAIN_64G (3 << 4) +#define ALS_PRST_1T (0 << 6) +#define ALS_PRST_2T (1 << 6) +#define ALS_PRST_4T (2 << 6) +#define ALS_PRST_8T (3 << 6) + +/* LED_CTRL 0x03 */ +#define LED_CTIR_EN 0x03 /* [5:0] 2.89us , default value is 0.185ms */ +#define CTIR_DISABLE (0 << 0) +#define CTIR_ENABLE (1 << 0) +#define CTIRFC_DISABLE (0 << 1) +#define CTIRFC_ENABLE (1 << 1) +#define LED_CUR_12MA (2 << 5) +#define LED_CUR_25MA (3 << 5) +#define LED_CUR_50MA (4 << 5) +#define LED_CUR_100MA (5 << 5) +#define LED_CUR_150MA (6 << 5) + +/* INT 0x04 */ +#define PS_INT_DISABLE (0 << 0) +#define PS_INT_ENABLE (1 << 0) +#define PS_INT_ENABLE_FLGNFH (2 << 0) +#define PS_INT_ENABLE_FLGNFL (3 << 0) +#define PS_INT_MODE_ENABLE (4 << 0) +#define PS_INT_ENABLE_THL (5 << 0) +#define PS_INT_ENABLE_THH (6 << 0) +#define PS_INT_ENABLE_THHL (7 << 0) +#define ALS_INT_DISABLE (0 << 3) +#define ALS_INT_ENABLE (1 << 3) +#define INT_CTRL_PS_OR_LS (0 << 7) +#define INT_CTRL_PS_AND_LS (1 << 7) + +/* FLAG 0x10 */ +#define STK_FLAG_NF (1 << 0) +#define STK_FLAG_INPS_INT (1 << 1) +#define STK_FLAG_ALS_STATE (1 << 2) +#define STK_FLAG_PS_INT (1 << 4) +#define STK_FLAG_ALS_INT (1 << 5) +#define STK_FLAG_PSDR (1 << 6) +#define STK_FLAG_ALSDR (1 << 7) + +static int ps_threshold_low; +static int ps_threshold_high; +static int val_flag; + +static int sensor_active(struct i2c_client *client, int enable, int rate) +{ + struct sensor_private_data *sensor = + (struct sensor_private_data *)i2c_get_clientdata(client); + int result = 0; + int status = 0; + + sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg); + if (!enable) { + status = ~PS_ENABLE; + sensor->ops->ctrl_data &= status; + } else { + status = PS_ENABLE; + sensor->ops->ctrl_data |= status; + } + + dev_dbg(&client->dev, "reg=0x%x, reg_ctrl=0x%x, enable=%d\n", + sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable); + + result = sensor_write_reg(client, sensor->ops->ctrl_reg, + sensor->ops->ctrl_data); + if (result) + dev_err(&client->dev, "%s:fail to active sensor\n", __func__); + + return result; +} + +static int sensor_init(struct i2c_client *client) +{ + struct sensor_private_data *sensor = + (struct sensor_private_data *)i2c_get_clientdata(client); + struct device_node *np = client->dev.of_node; + int ps_val = 0; + int result = 0; + int val = 0; + + result = sensor->ops->active(client, 0, 0); + if (result) { + dev_err(&client->dev, "%s:sensor active fail\n", __func__); + return result; + } + sensor->status_cur = SENSOR_OFF; + + result = of_property_read_u32(np, "ps_threshold_low", &ps_val); + if (result) + dev_err(&client->dev, "%s:Unable to read ps_threshold_low\n", + __func__); + + ps_threshold_low = ps_val; + result = sensor_write_reg(client, THDL1_PS, + (unsigned char)(ps_val >> 8)); + if (result) { + dev_err(&client->dev, "%s:write THDL1_PS fail\n", __func__); + return result; + } + result = sensor_write_reg(client, THDL2_PS, (unsigned char)ps_val); + if (result) { + dev_err(&client->dev, "%s:write THDL1_PS fail\n", __func__); + return result; + } + + result = of_property_read_u32(np, "ps_threshold_high", &ps_val); + if (result) + dev_err(&client->dev, "%s:Unable to read ps_threshold_high\n", + __func__); + + ps_threshold_high = ps_val; + result = sensor_write_reg(client, THDH1_PS, + (unsigned char)(ps_val >> 8)); + if (result) { + dev_err(&client->dev, "%s:write THDH1_PS fail\n", __func__); + return result; + } + + result = sensor_write_reg(client, THDH2_PS, (unsigned char)ps_val); + if (result) { + dev_err(&client->dev, "%s:write THDH1_PS fail\n", __func__); + return result; + } + + result = of_property_read_u32(np, "ps_ctrl_gain", &ps_val); + if (result) + dev_err(&client->dev, "%s:Unable to read ps_ctrl_gain\n", + __func__); + + result = sensor_write_reg(client, PS_CTRL, + (unsigned char)((ps_val << 4) | PS_IT_384US)); + if (result) { + dev_err(&client->dev, "%s:write PS_CTRL fail\n", __func__); + return result; + } + + result = of_property_read_u32(np, "ps_led_current", &ps_val); + if (result) + dev_err(&client->dev, "%s:Unable to read ps_led_current\n", + __func__); + + result = sensor_write_reg(client, LED_CTRL, + (unsigned char)((ps_val << 5) | LED_CTIR_EN)); + if (result) { + dev_err(&client->dev, "%s:write LED_CTRL fail\n", __func__); + return result; + } + + val = sensor_read_reg(client, INT_CTRL1); + val &= ~INT_CTRL_PS_AND_LS; + if (sensor->pdata->irq_enable) + val |= PS_INT_ENABLE_FLGNFL; + else + val &= PS_INT_DISABLE; + result = sensor_write_reg(client, INT_CTRL1, val); + if (result) { + dev_err(&client->dev, "%s:write INT_CTRL fail\n", __func__); + return result; + } + + return result; +} + +static int stk3332_get_ps_value(int ps) +{ + int index = 0; + + if ((ps > ps_threshold_high) && (val_flag == 0)) { + index = 1; + val_flag = 1; + } else if ((ps < ps_threshold_low) && (val_flag == 1)) { + index = 0; + val_flag = 0; + } else { + index = -1; + } + + return index; +} + +static int sensor_report_value(struct i2c_client *client) +{ + struct sensor_private_data *sensor = + (struct sensor_private_data *)i2c_get_clientdata(client); + int result = 0; + int value = 0; + char buffer[2] = { 0 }; + int index = 1; + + if (sensor->ops->read_len < 2) { + dev_err(&client->dev, "%s:length is error, len=%d\n", __func__, + sensor->ops->read_len); + return -EINVAL; + } + + buffer[0] = sensor->ops->read_reg; + result = sensor_rx_data(client, buffer, sensor->ops->read_len); + if (result) { + dev_err(&client->dev, "%s:sensor read data fail\n", __func__); + return result; + } + value = (buffer[0] << 8) | buffer[1]; + + if (sensor->pdata->irq_enable && sensor->ops->int_status_reg) { + value = sensor_read_reg(client, sensor->ops->int_status_reg); + if (value & STK_FLAG_NF) + index = 0; + else + index = 1; + input_report_abs(sensor->input_dev, ABS_DISTANCE, index); + input_sync(sensor->input_dev); + value &= ~STK_FLAG_PS_INT; + result = sensor_write_reg(client, + sensor->ops->int_status_reg, + value); + + dev_dbg(&client->dev, "%s object near = %d", sensor->ops->name, index); + + if (result) { + dev_err(&client->dev, "write status reg error\n"); + return result; + } + } else if (!sensor->pdata->irq_enable) { + index = stk3332_get_ps_value(value); + if (index >= 0) { + input_report_abs(sensor->input_dev, ABS_DISTANCE, index); + input_sync(sensor->input_dev); + dev_dbg(&client->dev, "%s sensor closed=%d\n", + sensor->ops->name, index); + } + } + + return result; +} + +static struct sensor_operate psensor_stk3332_ops = { + .name = "ps_stk3332", + .type = SENSOR_TYPE_PROXIMITY, + .id_i2c = PROXIMITY_ID_STK3332, + .read_reg = DATA1_PS, + .read_len = 2, + .id_reg = SENSOR_UNKNOW_DATA, + .id_data = SENSOR_UNKNOW_DATA, + .precision = 16, + .ctrl_reg = STK_STATE, + .int_status_reg = STK_FLAG, + .range = { 100, 65535 }, + .brightness = { 10, 255 }, + .trig = IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED, + .active = sensor_active, + .init = sensor_init, + .report = sensor_report_value, +}; + +static int proximity_stk3332_probe(struct i2c_client *client, + const struct i2c_device_id *devid) +{ + return sensor_register_device(client, NULL, devid, &psensor_stk3332_ops); +} + +static int proximity_stk3332_remove(struct i2c_client *client) +{ + return sensor_unregister_device(client, NULL, &psensor_stk3332_ops); +} + +static const struct i2c_device_id proximity_stk3332_id[] = { + { "ps_stk3332", PROXIMITY_ID_STK3332 }, + {} +}; + +static struct i2c_driver proximity_stk3332_driver = { + .probe = proximity_stk3332_probe, + .remove = proximity_stk3332_remove, + .shutdown = sensor_shutdown, + .id_table = proximity_stk3332_id, + .driver = { + .name = "proximity_stk3332", +#ifdef CONFIG_PM + .pm = &sensor_pm_ops, +#endif + }, +}; + +module_i2c_driver(proximity_stk3332_driver); + +MODULE_AUTHOR("Kay Guo"); +MODULE_DESCRIPTION("stk3332 proximity driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/sensor-dev.h b/include/linux/sensor-dev.h index 6ae9c16e67a3..d57f4e195f15 100644 --- a/include/linux/sensor-dev.h +++ b/include/linux/sensor-dev.h @@ -103,6 +103,7 @@ enum sensor_id { LIGHT_ID_AP321XX, LIGHT_ID_PHOTORESISTOR, LIGHT_ID_US5152, + LIGHT_ID_STK3332, LIGHT_ID_STK3410, LIGHT_ID_EM3071X, @@ -110,6 +111,7 @@ enum sensor_id { PROXIMITY_ID_AL3006, PROXIMITY_ID_STK3171, PROXIMITY_ID_AP321XX, + PROXIMITY_ID_STK3332, PROXIMITY_ID_STK3410, PROXIMITY_ID_EM3071X,