18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/** 38c2ecf20Sopenharmony_ci * Sensortek STK3310/STK3311 Ambient Light and Proximity Sensor 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2015, Intel Corporation. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * IIO driver for STK3310/STK3311. 7-bit I2C address: 0x48. 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/acpi.h> 118c2ecf20Sopenharmony_ci#include <linux/i2c.h> 128c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 138c2ecf20Sopenharmony_ci#include <linux/kernel.h> 148c2ecf20Sopenharmony_ci#include <linux/module.h> 158c2ecf20Sopenharmony_ci#include <linux/regmap.h> 168c2ecf20Sopenharmony_ci#include <linux/iio/events.h> 178c2ecf20Sopenharmony_ci#include <linux/iio/iio.h> 188c2ecf20Sopenharmony_ci#include <linux/iio/sysfs.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#define STK3310_REG_STATE 0x00 218c2ecf20Sopenharmony_ci#define STK3310_REG_PSCTRL 0x01 228c2ecf20Sopenharmony_ci#define STK3310_REG_ALSCTRL 0x02 238c2ecf20Sopenharmony_ci#define STK3310_REG_INT 0x04 248c2ecf20Sopenharmony_ci#define STK3310_REG_THDH_PS 0x06 258c2ecf20Sopenharmony_ci#define STK3310_REG_THDL_PS 0x08 268c2ecf20Sopenharmony_ci#define STK3310_REG_FLAG 0x10 278c2ecf20Sopenharmony_ci#define STK3310_REG_PS_DATA_MSB 0x11 288c2ecf20Sopenharmony_ci#define STK3310_REG_PS_DATA_LSB 0x12 298c2ecf20Sopenharmony_ci#define STK3310_REG_ALS_DATA_MSB 0x13 308c2ecf20Sopenharmony_ci#define STK3310_REG_ALS_DATA_LSB 0x14 318c2ecf20Sopenharmony_ci#define STK3310_REG_ID 0x3E 328c2ecf20Sopenharmony_ci#define STK3310_MAX_REG 0x80 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define STK3310_STATE_EN_PS BIT(0) 358c2ecf20Sopenharmony_ci#define STK3310_STATE_EN_ALS BIT(1) 368c2ecf20Sopenharmony_ci#define STK3310_STATE_STANDBY 0x00 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#define STK3310_CHIP_ID_VAL 0x13 398c2ecf20Sopenharmony_ci#define STK3311_CHIP_ID_VAL 0x1D 408c2ecf20Sopenharmony_ci#define STK3311X_CHIP_ID_VAL 0x12 418c2ecf20Sopenharmony_ci#define STK3335_CHIP_ID_VAL 0x51 428c2ecf20Sopenharmony_ci#define STK3310_PSINT_EN 0x01 438c2ecf20Sopenharmony_ci#define STK3310_PS_MAX_VAL 0xFFFF 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#define STK3310_DRIVER_NAME "stk3310" 468c2ecf20Sopenharmony_ci#define STK3310_REGMAP_NAME "stk3310_regmap" 478c2ecf20Sopenharmony_ci#define STK3310_EVENT "stk3310_event" 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci#define STK3310_SCALE_AVAILABLE "6.4 1.6 0.4 0.1" 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci#define STK3310_IT_AVAILABLE \ 528c2ecf20Sopenharmony_ci "0.000185 0.000370 0.000741 0.001480 0.002960 0.005920 0.011840 " \ 538c2ecf20Sopenharmony_ci "0.023680 0.047360 0.094720 0.189440 0.378880 0.757760 1.515520 " \ 548c2ecf20Sopenharmony_ci "3.031040 6.062080" 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci#define STK3310_REGFIELD(name) \ 578c2ecf20Sopenharmony_ci do { \ 588c2ecf20Sopenharmony_ci data->reg_##name = \ 598c2ecf20Sopenharmony_ci devm_regmap_field_alloc(&client->dev, regmap, \ 608c2ecf20Sopenharmony_ci stk3310_reg_field_##name); \ 618c2ecf20Sopenharmony_ci if (IS_ERR(data->reg_##name)) { \ 628c2ecf20Sopenharmony_ci dev_err(&client->dev, "reg field alloc failed.\n"); \ 638c2ecf20Sopenharmony_ci return PTR_ERR(data->reg_##name); \ 648c2ecf20Sopenharmony_ci } \ 658c2ecf20Sopenharmony_ci } while (0) 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic const struct reg_field stk3310_reg_field_state = 688c2ecf20Sopenharmony_ci REG_FIELD(STK3310_REG_STATE, 0, 2); 698c2ecf20Sopenharmony_cistatic const struct reg_field stk3310_reg_field_als_gain = 708c2ecf20Sopenharmony_ci REG_FIELD(STK3310_REG_ALSCTRL, 4, 5); 718c2ecf20Sopenharmony_cistatic const struct reg_field stk3310_reg_field_ps_gain = 728c2ecf20Sopenharmony_ci REG_FIELD(STK3310_REG_PSCTRL, 4, 5); 738c2ecf20Sopenharmony_cistatic const struct reg_field stk3310_reg_field_als_it = 748c2ecf20Sopenharmony_ci REG_FIELD(STK3310_REG_ALSCTRL, 0, 3); 758c2ecf20Sopenharmony_cistatic const struct reg_field stk3310_reg_field_ps_it = 768c2ecf20Sopenharmony_ci REG_FIELD(STK3310_REG_PSCTRL, 0, 3); 778c2ecf20Sopenharmony_cistatic const struct reg_field stk3310_reg_field_int_ps = 788c2ecf20Sopenharmony_ci REG_FIELD(STK3310_REG_INT, 0, 2); 798c2ecf20Sopenharmony_cistatic const struct reg_field stk3310_reg_field_flag_psint = 808c2ecf20Sopenharmony_ci REG_FIELD(STK3310_REG_FLAG, 4, 4); 818c2ecf20Sopenharmony_cistatic const struct reg_field stk3310_reg_field_flag_nf = 828c2ecf20Sopenharmony_ci REG_FIELD(STK3310_REG_FLAG, 0, 0); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci/* Estimate maximum proximity values with regard to measurement scale. */ 858c2ecf20Sopenharmony_cistatic const int stk3310_ps_max[4] = { 868c2ecf20Sopenharmony_ci STK3310_PS_MAX_VAL / 640, 878c2ecf20Sopenharmony_ci STK3310_PS_MAX_VAL / 160, 888c2ecf20Sopenharmony_ci STK3310_PS_MAX_VAL / 40, 898c2ecf20Sopenharmony_ci STK3310_PS_MAX_VAL / 10 908c2ecf20Sopenharmony_ci}; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic const int stk3310_scale_table[][2] = { 938c2ecf20Sopenharmony_ci {6, 400000}, {1, 600000}, {0, 400000}, {0, 100000} 948c2ecf20Sopenharmony_ci}; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci/* Integration time in seconds, microseconds */ 978c2ecf20Sopenharmony_cistatic const int stk3310_it_table[][2] = { 988c2ecf20Sopenharmony_ci {0, 185}, {0, 370}, {0, 741}, {0, 1480}, 998c2ecf20Sopenharmony_ci {0, 2960}, {0, 5920}, {0, 11840}, {0, 23680}, 1008c2ecf20Sopenharmony_ci {0, 47360}, {0, 94720}, {0, 189440}, {0, 378880}, 1018c2ecf20Sopenharmony_ci {0, 757760}, {1, 515520}, {3, 31040}, {6, 62080}, 1028c2ecf20Sopenharmony_ci}; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cistruct stk3310_data { 1058c2ecf20Sopenharmony_ci struct i2c_client *client; 1068c2ecf20Sopenharmony_ci struct mutex lock; 1078c2ecf20Sopenharmony_ci bool als_enabled; 1088c2ecf20Sopenharmony_ci bool ps_enabled; 1098c2ecf20Sopenharmony_ci u64 timestamp; 1108c2ecf20Sopenharmony_ci struct regmap *regmap; 1118c2ecf20Sopenharmony_ci struct regmap_field *reg_state; 1128c2ecf20Sopenharmony_ci struct regmap_field *reg_als_gain; 1138c2ecf20Sopenharmony_ci struct regmap_field *reg_ps_gain; 1148c2ecf20Sopenharmony_ci struct regmap_field *reg_als_it; 1158c2ecf20Sopenharmony_ci struct regmap_field *reg_ps_it; 1168c2ecf20Sopenharmony_ci struct regmap_field *reg_int_ps; 1178c2ecf20Sopenharmony_ci struct regmap_field *reg_flag_psint; 1188c2ecf20Sopenharmony_ci struct regmap_field *reg_flag_nf; 1198c2ecf20Sopenharmony_ci}; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cistatic const struct iio_event_spec stk3310_events[] = { 1228c2ecf20Sopenharmony_ci /* Proximity event */ 1238c2ecf20Sopenharmony_ci { 1248c2ecf20Sopenharmony_ci .type = IIO_EV_TYPE_THRESH, 1258c2ecf20Sopenharmony_ci .dir = IIO_EV_DIR_RISING, 1268c2ecf20Sopenharmony_ci .mask_separate = BIT(IIO_EV_INFO_VALUE) | 1278c2ecf20Sopenharmony_ci BIT(IIO_EV_INFO_ENABLE), 1288c2ecf20Sopenharmony_ci }, 1298c2ecf20Sopenharmony_ci /* Out-of-proximity event */ 1308c2ecf20Sopenharmony_ci { 1318c2ecf20Sopenharmony_ci .type = IIO_EV_TYPE_THRESH, 1328c2ecf20Sopenharmony_ci .dir = IIO_EV_DIR_FALLING, 1338c2ecf20Sopenharmony_ci .mask_separate = BIT(IIO_EV_INFO_VALUE) | 1348c2ecf20Sopenharmony_ci BIT(IIO_EV_INFO_ENABLE), 1358c2ecf20Sopenharmony_ci }, 1368c2ecf20Sopenharmony_ci}; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistatic const struct iio_chan_spec stk3310_channels[] = { 1398c2ecf20Sopenharmony_ci { 1408c2ecf20Sopenharmony_ci .type = IIO_LIGHT, 1418c2ecf20Sopenharmony_ci .info_mask_separate = 1428c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_RAW) | 1438c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE) | 1448c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_INT_TIME), 1458c2ecf20Sopenharmony_ci }, 1468c2ecf20Sopenharmony_ci { 1478c2ecf20Sopenharmony_ci .type = IIO_PROXIMITY, 1488c2ecf20Sopenharmony_ci .info_mask_separate = 1498c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_RAW) | 1508c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE) | 1518c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_INT_TIME), 1528c2ecf20Sopenharmony_ci .event_spec = stk3310_events, 1538c2ecf20Sopenharmony_ci .num_event_specs = ARRAY_SIZE(stk3310_events), 1548c2ecf20Sopenharmony_ci } 1558c2ecf20Sopenharmony_ci}; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistatic IIO_CONST_ATTR(in_illuminance_scale_available, STK3310_SCALE_AVAILABLE); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_cistatic IIO_CONST_ATTR(in_proximity_scale_available, STK3310_SCALE_AVAILABLE); 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cistatic IIO_CONST_ATTR(in_illuminance_integration_time_available, 1628c2ecf20Sopenharmony_ci STK3310_IT_AVAILABLE); 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistatic IIO_CONST_ATTR(in_proximity_integration_time_available, 1658c2ecf20Sopenharmony_ci STK3310_IT_AVAILABLE); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_cistatic struct attribute *stk3310_attributes[] = { 1688c2ecf20Sopenharmony_ci &iio_const_attr_in_illuminance_scale_available.dev_attr.attr, 1698c2ecf20Sopenharmony_ci &iio_const_attr_in_proximity_scale_available.dev_attr.attr, 1708c2ecf20Sopenharmony_ci &iio_const_attr_in_illuminance_integration_time_available.dev_attr.attr, 1718c2ecf20Sopenharmony_ci &iio_const_attr_in_proximity_integration_time_available.dev_attr.attr, 1728c2ecf20Sopenharmony_ci NULL, 1738c2ecf20Sopenharmony_ci}; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_cistatic const struct attribute_group stk3310_attribute_group = { 1768c2ecf20Sopenharmony_ci .attrs = stk3310_attributes 1778c2ecf20Sopenharmony_ci}; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_cistatic int stk3310_get_index(const int table[][2], int table_size, 1808c2ecf20Sopenharmony_ci int val, int val2) 1818c2ecf20Sopenharmony_ci{ 1828c2ecf20Sopenharmony_ci int i; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci for (i = 0; i < table_size; i++) { 1858c2ecf20Sopenharmony_ci if (val == table[i][0] && val2 == table[i][1]) 1868c2ecf20Sopenharmony_ci return i; 1878c2ecf20Sopenharmony_ci } 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci return -EINVAL; 1908c2ecf20Sopenharmony_ci} 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_cistatic int stk3310_read_event(struct iio_dev *indio_dev, 1938c2ecf20Sopenharmony_ci const struct iio_chan_spec *chan, 1948c2ecf20Sopenharmony_ci enum iio_event_type type, 1958c2ecf20Sopenharmony_ci enum iio_event_direction dir, 1968c2ecf20Sopenharmony_ci enum iio_event_info info, 1978c2ecf20Sopenharmony_ci int *val, int *val2) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci u8 reg; 2008c2ecf20Sopenharmony_ci __be16 buf; 2018c2ecf20Sopenharmony_ci int ret; 2028c2ecf20Sopenharmony_ci struct stk3310_data *data = iio_priv(indio_dev); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci if (info != IIO_EV_INFO_VALUE) 2058c2ecf20Sopenharmony_ci return -EINVAL; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci /* Only proximity interrupts are implemented at the moment. */ 2088c2ecf20Sopenharmony_ci if (dir == IIO_EV_DIR_RISING) 2098c2ecf20Sopenharmony_ci reg = STK3310_REG_THDH_PS; 2108c2ecf20Sopenharmony_ci else if (dir == IIO_EV_DIR_FALLING) 2118c2ecf20Sopenharmony_ci reg = STK3310_REG_THDL_PS; 2128c2ecf20Sopenharmony_ci else 2138c2ecf20Sopenharmony_ci return -EINVAL; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci mutex_lock(&data->lock); 2168c2ecf20Sopenharmony_ci ret = regmap_bulk_read(data->regmap, reg, &buf, 2); 2178c2ecf20Sopenharmony_ci mutex_unlock(&data->lock); 2188c2ecf20Sopenharmony_ci if (ret < 0) { 2198c2ecf20Sopenharmony_ci dev_err(&data->client->dev, "register read failed\n"); 2208c2ecf20Sopenharmony_ci return ret; 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci *val = be16_to_cpu(buf); 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci return IIO_VAL_INT; 2258c2ecf20Sopenharmony_ci} 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_cistatic int stk3310_write_event(struct iio_dev *indio_dev, 2288c2ecf20Sopenharmony_ci const struct iio_chan_spec *chan, 2298c2ecf20Sopenharmony_ci enum iio_event_type type, 2308c2ecf20Sopenharmony_ci enum iio_event_direction dir, 2318c2ecf20Sopenharmony_ci enum iio_event_info info, 2328c2ecf20Sopenharmony_ci int val, int val2) 2338c2ecf20Sopenharmony_ci{ 2348c2ecf20Sopenharmony_ci u8 reg; 2358c2ecf20Sopenharmony_ci __be16 buf; 2368c2ecf20Sopenharmony_ci int ret; 2378c2ecf20Sopenharmony_ci unsigned int index; 2388c2ecf20Sopenharmony_ci struct stk3310_data *data = iio_priv(indio_dev); 2398c2ecf20Sopenharmony_ci struct i2c_client *client = data->client; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci ret = regmap_field_read(data->reg_ps_gain, &index); 2428c2ecf20Sopenharmony_ci if (ret < 0) 2438c2ecf20Sopenharmony_ci return ret; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci if (val < 0 || val > stk3310_ps_max[index]) 2468c2ecf20Sopenharmony_ci return -EINVAL; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci if (dir == IIO_EV_DIR_RISING) 2498c2ecf20Sopenharmony_ci reg = STK3310_REG_THDH_PS; 2508c2ecf20Sopenharmony_ci else if (dir == IIO_EV_DIR_FALLING) 2518c2ecf20Sopenharmony_ci reg = STK3310_REG_THDL_PS; 2528c2ecf20Sopenharmony_ci else 2538c2ecf20Sopenharmony_ci return -EINVAL; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci buf = cpu_to_be16(val); 2568c2ecf20Sopenharmony_ci ret = regmap_bulk_write(data->regmap, reg, &buf, 2); 2578c2ecf20Sopenharmony_ci if (ret < 0) 2588c2ecf20Sopenharmony_ci dev_err(&client->dev, "failed to set PS threshold!\n"); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci return ret; 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_cistatic int stk3310_read_event_config(struct iio_dev *indio_dev, 2648c2ecf20Sopenharmony_ci const struct iio_chan_spec *chan, 2658c2ecf20Sopenharmony_ci enum iio_event_type type, 2668c2ecf20Sopenharmony_ci enum iio_event_direction dir) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci unsigned int event_val; 2698c2ecf20Sopenharmony_ci int ret; 2708c2ecf20Sopenharmony_ci struct stk3310_data *data = iio_priv(indio_dev); 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci ret = regmap_field_read(data->reg_int_ps, &event_val); 2738c2ecf20Sopenharmony_ci if (ret < 0) 2748c2ecf20Sopenharmony_ci return ret; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci return event_val; 2778c2ecf20Sopenharmony_ci} 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_cistatic int stk3310_write_event_config(struct iio_dev *indio_dev, 2808c2ecf20Sopenharmony_ci const struct iio_chan_spec *chan, 2818c2ecf20Sopenharmony_ci enum iio_event_type type, 2828c2ecf20Sopenharmony_ci enum iio_event_direction dir, 2838c2ecf20Sopenharmony_ci int state) 2848c2ecf20Sopenharmony_ci{ 2858c2ecf20Sopenharmony_ci int ret; 2868c2ecf20Sopenharmony_ci struct stk3310_data *data = iio_priv(indio_dev); 2878c2ecf20Sopenharmony_ci struct i2c_client *client = data->client; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci if (state < 0 || state > 7) 2908c2ecf20Sopenharmony_ci return -EINVAL; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci /* Set INT_PS value */ 2938c2ecf20Sopenharmony_ci mutex_lock(&data->lock); 2948c2ecf20Sopenharmony_ci ret = regmap_field_write(data->reg_int_ps, state); 2958c2ecf20Sopenharmony_ci if (ret < 0) 2968c2ecf20Sopenharmony_ci dev_err(&client->dev, "failed to set interrupt mode\n"); 2978c2ecf20Sopenharmony_ci mutex_unlock(&data->lock); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci return ret; 3008c2ecf20Sopenharmony_ci} 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistatic int stk3310_read_raw(struct iio_dev *indio_dev, 3038c2ecf20Sopenharmony_ci struct iio_chan_spec const *chan, 3048c2ecf20Sopenharmony_ci int *val, int *val2, long mask) 3058c2ecf20Sopenharmony_ci{ 3068c2ecf20Sopenharmony_ci u8 reg; 3078c2ecf20Sopenharmony_ci __be16 buf; 3088c2ecf20Sopenharmony_ci int ret; 3098c2ecf20Sopenharmony_ci unsigned int index; 3108c2ecf20Sopenharmony_ci struct stk3310_data *data = iio_priv(indio_dev); 3118c2ecf20Sopenharmony_ci struct i2c_client *client = data->client; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci if (chan->type != IIO_LIGHT && chan->type != IIO_PROXIMITY) 3148c2ecf20Sopenharmony_ci return -EINVAL; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci switch (mask) { 3178c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_RAW: 3188c2ecf20Sopenharmony_ci if (chan->type == IIO_LIGHT) 3198c2ecf20Sopenharmony_ci reg = STK3310_REG_ALS_DATA_MSB; 3208c2ecf20Sopenharmony_ci else 3218c2ecf20Sopenharmony_ci reg = STK3310_REG_PS_DATA_MSB; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci mutex_lock(&data->lock); 3248c2ecf20Sopenharmony_ci ret = regmap_bulk_read(data->regmap, reg, &buf, 2); 3258c2ecf20Sopenharmony_ci if (ret < 0) { 3268c2ecf20Sopenharmony_ci dev_err(&client->dev, "register read failed\n"); 3278c2ecf20Sopenharmony_ci mutex_unlock(&data->lock); 3288c2ecf20Sopenharmony_ci return ret; 3298c2ecf20Sopenharmony_ci } 3308c2ecf20Sopenharmony_ci *val = be16_to_cpu(buf); 3318c2ecf20Sopenharmony_ci mutex_unlock(&data->lock); 3328c2ecf20Sopenharmony_ci return IIO_VAL_INT; 3338c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_INT_TIME: 3348c2ecf20Sopenharmony_ci if (chan->type == IIO_LIGHT) 3358c2ecf20Sopenharmony_ci ret = regmap_field_read(data->reg_als_it, &index); 3368c2ecf20Sopenharmony_ci else 3378c2ecf20Sopenharmony_ci ret = regmap_field_read(data->reg_ps_it, &index); 3388c2ecf20Sopenharmony_ci if (ret < 0) 3398c2ecf20Sopenharmony_ci return ret; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci *val = stk3310_it_table[index][0]; 3428c2ecf20Sopenharmony_ci *val2 = stk3310_it_table[index][1]; 3438c2ecf20Sopenharmony_ci return IIO_VAL_INT_PLUS_MICRO; 3448c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 3458c2ecf20Sopenharmony_ci if (chan->type == IIO_LIGHT) 3468c2ecf20Sopenharmony_ci ret = regmap_field_read(data->reg_als_gain, &index); 3478c2ecf20Sopenharmony_ci else 3488c2ecf20Sopenharmony_ci ret = regmap_field_read(data->reg_ps_gain, &index); 3498c2ecf20Sopenharmony_ci if (ret < 0) 3508c2ecf20Sopenharmony_ci return ret; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci *val = stk3310_scale_table[index][0]; 3538c2ecf20Sopenharmony_ci *val2 = stk3310_scale_table[index][1]; 3548c2ecf20Sopenharmony_ci return IIO_VAL_INT_PLUS_MICRO; 3558c2ecf20Sopenharmony_ci } 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci return -EINVAL; 3588c2ecf20Sopenharmony_ci} 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_cistatic int stk3310_write_raw(struct iio_dev *indio_dev, 3618c2ecf20Sopenharmony_ci struct iio_chan_spec const *chan, 3628c2ecf20Sopenharmony_ci int val, int val2, long mask) 3638c2ecf20Sopenharmony_ci{ 3648c2ecf20Sopenharmony_ci int ret; 3658c2ecf20Sopenharmony_ci int index; 3668c2ecf20Sopenharmony_ci struct stk3310_data *data = iio_priv(indio_dev); 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci if (chan->type != IIO_LIGHT && chan->type != IIO_PROXIMITY) 3698c2ecf20Sopenharmony_ci return -EINVAL; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci switch (mask) { 3728c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_INT_TIME: 3738c2ecf20Sopenharmony_ci index = stk3310_get_index(stk3310_it_table, 3748c2ecf20Sopenharmony_ci ARRAY_SIZE(stk3310_it_table), 3758c2ecf20Sopenharmony_ci val, val2); 3768c2ecf20Sopenharmony_ci if (index < 0) 3778c2ecf20Sopenharmony_ci return -EINVAL; 3788c2ecf20Sopenharmony_ci mutex_lock(&data->lock); 3798c2ecf20Sopenharmony_ci if (chan->type == IIO_LIGHT) 3808c2ecf20Sopenharmony_ci ret = regmap_field_write(data->reg_als_it, index); 3818c2ecf20Sopenharmony_ci else 3828c2ecf20Sopenharmony_ci ret = regmap_field_write(data->reg_ps_it, index); 3838c2ecf20Sopenharmony_ci if (ret < 0) 3848c2ecf20Sopenharmony_ci dev_err(&data->client->dev, 3858c2ecf20Sopenharmony_ci "sensor configuration failed\n"); 3868c2ecf20Sopenharmony_ci mutex_unlock(&data->lock); 3878c2ecf20Sopenharmony_ci return ret; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 3908c2ecf20Sopenharmony_ci index = stk3310_get_index(stk3310_scale_table, 3918c2ecf20Sopenharmony_ci ARRAY_SIZE(stk3310_scale_table), 3928c2ecf20Sopenharmony_ci val, val2); 3938c2ecf20Sopenharmony_ci if (index < 0) 3948c2ecf20Sopenharmony_ci return -EINVAL; 3958c2ecf20Sopenharmony_ci mutex_lock(&data->lock); 3968c2ecf20Sopenharmony_ci if (chan->type == IIO_LIGHT) 3978c2ecf20Sopenharmony_ci ret = regmap_field_write(data->reg_als_gain, index); 3988c2ecf20Sopenharmony_ci else 3998c2ecf20Sopenharmony_ci ret = regmap_field_write(data->reg_ps_gain, index); 4008c2ecf20Sopenharmony_ci if (ret < 0) 4018c2ecf20Sopenharmony_ci dev_err(&data->client->dev, 4028c2ecf20Sopenharmony_ci "sensor configuration failed\n"); 4038c2ecf20Sopenharmony_ci mutex_unlock(&data->lock); 4048c2ecf20Sopenharmony_ci return ret; 4058c2ecf20Sopenharmony_ci } 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci return -EINVAL; 4088c2ecf20Sopenharmony_ci} 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_cistatic const struct iio_info stk3310_info = { 4118c2ecf20Sopenharmony_ci .read_raw = stk3310_read_raw, 4128c2ecf20Sopenharmony_ci .write_raw = stk3310_write_raw, 4138c2ecf20Sopenharmony_ci .attrs = &stk3310_attribute_group, 4148c2ecf20Sopenharmony_ci .read_event_value = stk3310_read_event, 4158c2ecf20Sopenharmony_ci .write_event_value = stk3310_write_event, 4168c2ecf20Sopenharmony_ci .read_event_config = stk3310_read_event_config, 4178c2ecf20Sopenharmony_ci .write_event_config = stk3310_write_event_config, 4188c2ecf20Sopenharmony_ci}; 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_cistatic int stk3310_set_state(struct stk3310_data *data, u8 state) 4218c2ecf20Sopenharmony_ci{ 4228c2ecf20Sopenharmony_ci int ret; 4238c2ecf20Sopenharmony_ci struct i2c_client *client = data->client; 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci /* 3-bit state; 0b100 is not supported. */ 4268c2ecf20Sopenharmony_ci if (state > 7 || state == 4) 4278c2ecf20Sopenharmony_ci return -EINVAL; 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci mutex_lock(&data->lock); 4308c2ecf20Sopenharmony_ci ret = regmap_field_write(data->reg_state, state); 4318c2ecf20Sopenharmony_ci if (ret < 0) { 4328c2ecf20Sopenharmony_ci dev_err(&client->dev, "failed to change sensor state\n"); 4338c2ecf20Sopenharmony_ci } else if (state != STK3310_STATE_STANDBY) { 4348c2ecf20Sopenharmony_ci /* Don't reset the 'enabled' flags if we're going in standby */ 4358c2ecf20Sopenharmony_ci data->ps_enabled = !!(state & STK3310_STATE_EN_PS); 4368c2ecf20Sopenharmony_ci data->als_enabled = !!(state & STK3310_STATE_EN_ALS); 4378c2ecf20Sopenharmony_ci } 4388c2ecf20Sopenharmony_ci mutex_unlock(&data->lock); 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci return ret; 4418c2ecf20Sopenharmony_ci} 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_cistatic int stk3310_init(struct iio_dev *indio_dev) 4448c2ecf20Sopenharmony_ci{ 4458c2ecf20Sopenharmony_ci int ret; 4468c2ecf20Sopenharmony_ci int chipid; 4478c2ecf20Sopenharmony_ci u8 state; 4488c2ecf20Sopenharmony_ci struct stk3310_data *data = iio_priv(indio_dev); 4498c2ecf20Sopenharmony_ci struct i2c_client *client = data->client; 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci ret = regmap_read(data->regmap, STK3310_REG_ID, &chipid); 4528c2ecf20Sopenharmony_ci if (ret < 0) 4538c2ecf20Sopenharmony_ci return ret; 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci if (chipid != STK3310_CHIP_ID_VAL && 4568c2ecf20Sopenharmony_ci chipid != STK3311_CHIP_ID_VAL && 4578c2ecf20Sopenharmony_ci chipid != STK3311X_CHIP_ID_VAL && 4588c2ecf20Sopenharmony_ci chipid != STK3335_CHIP_ID_VAL) { 4598c2ecf20Sopenharmony_ci dev_err(&client->dev, "invalid chip id: 0x%x\n", chipid); 4608c2ecf20Sopenharmony_ci return -ENODEV; 4618c2ecf20Sopenharmony_ci } 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci state = STK3310_STATE_EN_ALS | STK3310_STATE_EN_PS; 4648c2ecf20Sopenharmony_ci ret = stk3310_set_state(data, state); 4658c2ecf20Sopenharmony_ci if (ret < 0) { 4668c2ecf20Sopenharmony_ci dev_err(&client->dev, "failed to enable sensor"); 4678c2ecf20Sopenharmony_ci return ret; 4688c2ecf20Sopenharmony_ci } 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci /* Enable PS interrupts */ 4718c2ecf20Sopenharmony_ci ret = regmap_field_write(data->reg_int_ps, STK3310_PSINT_EN); 4728c2ecf20Sopenharmony_ci if (ret < 0) 4738c2ecf20Sopenharmony_ci dev_err(&client->dev, "failed to enable interrupts!\n"); 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci return ret; 4768c2ecf20Sopenharmony_ci} 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_cistatic bool stk3310_is_volatile_reg(struct device *dev, unsigned int reg) 4798c2ecf20Sopenharmony_ci{ 4808c2ecf20Sopenharmony_ci switch (reg) { 4818c2ecf20Sopenharmony_ci case STK3310_REG_ALS_DATA_MSB: 4828c2ecf20Sopenharmony_ci case STK3310_REG_ALS_DATA_LSB: 4838c2ecf20Sopenharmony_ci case STK3310_REG_PS_DATA_LSB: 4848c2ecf20Sopenharmony_ci case STK3310_REG_PS_DATA_MSB: 4858c2ecf20Sopenharmony_ci case STK3310_REG_FLAG: 4868c2ecf20Sopenharmony_ci return true; 4878c2ecf20Sopenharmony_ci default: 4888c2ecf20Sopenharmony_ci return false; 4898c2ecf20Sopenharmony_ci } 4908c2ecf20Sopenharmony_ci} 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_cistatic const struct regmap_config stk3310_regmap_config = { 4938c2ecf20Sopenharmony_ci .name = STK3310_REGMAP_NAME, 4948c2ecf20Sopenharmony_ci .reg_bits = 8, 4958c2ecf20Sopenharmony_ci .val_bits = 8, 4968c2ecf20Sopenharmony_ci .max_register = STK3310_MAX_REG, 4978c2ecf20Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 4988c2ecf20Sopenharmony_ci .volatile_reg = stk3310_is_volatile_reg, 4998c2ecf20Sopenharmony_ci}; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_cistatic int stk3310_regmap_init(struct stk3310_data *data) 5028c2ecf20Sopenharmony_ci{ 5038c2ecf20Sopenharmony_ci struct regmap *regmap; 5048c2ecf20Sopenharmony_ci struct i2c_client *client; 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci client = data->client; 5078c2ecf20Sopenharmony_ci regmap = devm_regmap_init_i2c(client, &stk3310_regmap_config); 5088c2ecf20Sopenharmony_ci if (IS_ERR(regmap)) { 5098c2ecf20Sopenharmony_ci dev_err(&client->dev, "regmap initialization failed.\n"); 5108c2ecf20Sopenharmony_ci return PTR_ERR(regmap); 5118c2ecf20Sopenharmony_ci } 5128c2ecf20Sopenharmony_ci data->regmap = regmap; 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci STK3310_REGFIELD(state); 5158c2ecf20Sopenharmony_ci STK3310_REGFIELD(als_gain); 5168c2ecf20Sopenharmony_ci STK3310_REGFIELD(ps_gain); 5178c2ecf20Sopenharmony_ci STK3310_REGFIELD(als_it); 5188c2ecf20Sopenharmony_ci STK3310_REGFIELD(ps_it); 5198c2ecf20Sopenharmony_ci STK3310_REGFIELD(int_ps); 5208c2ecf20Sopenharmony_ci STK3310_REGFIELD(flag_psint); 5218c2ecf20Sopenharmony_ci STK3310_REGFIELD(flag_nf); 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci return 0; 5248c2ecf20Sopenharmony_ci} 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_cistatic irqreturn_t stk3310_irq_handler(int irq, void *private) 5278c2ecf20Sopenharmony_ci{ 5288c2ecf20Sopenharmony_ci struct iio_dev *indio_dev = private; 5298c2ecf20Sopenharmony_ci struct stk3310_data *data = iio_priv(indio_dev); 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci data->timestamp = iio_get_time_ns(indio_dev); 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci return IRQ_WAKE_THREAD; 5348c2ecf20Sopenharmony_ci} 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_cistatic irqreturn_t stk3310_irq_event_handler(int irq, void *private) 5378c2ecf20Sopenharmony_ci{ 5388c2ecf20Sopenharmony_ci int ret; 5398c2ecf20Sopenharmony_ci unsigned int dir; 5408c2ecf20Sopenharmony_ci u64 event; 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci struct iio_dev *indio_dev = private; 5438c2ecf20Sopenharmony_ci struct stk3310_data *data = iio_priv(indio_dev); 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci /* Read FLAG_NF to figure out what threshold has been met. */ 5468c2ecf20Sopenharmony_ci mutex_lock(&data->lock); 5478c2ecf20Sopenharmony_ci ret = regmap_field_read(data->reg_flag_nf, &dir); 5488c2ecf20Sopenharmony_ci if (ret < 0) { 5498c2ecf20Sopenharmony_ci dev_err(&data->client->dev, "register read failed: %d\n", ret); 5508c2ecf20Sopenharmony_ci goto out; 5518c2ecf20Sopenharmony_ci } 5528c2ecf20Sopenharmony_ci event = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 1, 5538c2ecf20Sopenharmony_ci IIO_EV_TYPE_THRESH, 5548c2ecf20Sopenharmony_ci (dir ? IIO_EV_DIR_FALLING : 5558c2ecf20Sopenharmony_ci IIO_EV_DIR_RISING)); 5568c2ecf20Sopenharmony_ci iio_push_event(indio_dev, event, data->timestamp); 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci /* Reset the interrupt flag */ 5598c2ecf20Sopenharmony_ci ret = regmap_field_write(data->reg_flag_psint, 0); 5608c2ecf20Sopenharmony_ci if (ret < 0) 5618c2ecf20Sopenharmony_ci dev_err(&data->client->dev, "failed to reset interrupts\n"); 5628c2ecf20Sopenharmony_ciout: 5638c2ecf20Sopenharmony_ci mutex_unlock(&data->lock); 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci return IRQ_HANDLED; 5668c2ecf20Sopenharmony_ci} 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_cistatic int stk3310_probe(struct i2c_client *client, 5698c2ecf20Sopenharmony_ci const struct i2c_device_id *id) 5708c2ecf20Sopenharmony_ci{ 5718c2ecf20Sopenharmony_ci int ret; 5728c2ecf20Sopenharmony_ci struct iio_dev *indio_dev; 5738c2ecf20Sopenharmony_ci struct stk3310_data *data; 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 5768c2ecf20Sopenharmony_ci if (!indio_dev) { 5778c2ecf20Sopenharmony_ci dev_err(&client->dev, "iio allocation failed!\n"); 5788c2ecf20Sopenharmony_ci return -ENOMEM; 5798c2ecf20Sopenharmony_ci } 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci data = iio_priv(indio_dev); 5828c2ecf20Sopenharmony_ci data->client = client; 5838c2ecf20Sopenharmony_ci i2c_set_clientdata(client, indio_dev); 5848c2ecf20Sopenharmony_ci mutex_init(&data->lock); 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci ret = stk3310_regmap_init(data); 5878c2ecf20Sopenharmony_ci if (ret < 0) 5888c2ecf20Sopenharmony_ci return ret; 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci indio_dev->info = &stk3310_info; 5918c2ecf20Sopenharmony_ci indio_dev->name = STK3310_DRIVER_NAME; 5928c2ecf20Sopenharmony_ci indio_dev->modes = INDIO_DIRECT_MODE; 5938c2ecf20Sopenharmony_ci indio_dev->channels = stk3310_channels; 5948c2ecf20Sopenharmony_ci indio_dev->num_channels = ARRAY_SIZE(stk3310_channels); 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci ret = stk3310_init(indio_dev); 5978c2ecf20Sopenharmony_ci if (ret < 0) 5988c2ecf20Sopenharmony_ci return ret; 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci if (client->irq > 0) { 6018c2ecf20Sopenharmony_ci ret = devm_request_threaded_irq(&client->dev, client->irq, 6028c2ecf20Sopenharmony_ci stk3310_irq_handler, 6038c2ecf20Sopenharmony_ci stk3310_irq_event_handler, 6048c2ecf20Sopenharmony_ci IRQF_TRIGGER_FALLING | 6058c2ecf20Sopenharmony_ci IRQF_ONESHOT, 6068c2ecf20Sopenharmony_ci STK3310_EVENT, indio_dev); 6078c2ecf20Sopenharmony_ci if (ret < 0) { 6088c2ecf20Sopenharmony_ci dev_err(&client->dev, "request irq %d failed\n", 6098c2ecf20Sopenharmony_ci client->irq); 6108c2ecf20Sopenharmony_ci goto err_standby; 6118c2ecf20Sopenharmony_ci } 6128c2ecf20Sopenharmony_ci } 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci ret = iio_device_register(indio_dev); 6158c2ecf20Sopenharmony_ci if (ret < 0) { 6168c2ecf20Sopenharmony_ci dev_err(&client->dev, "device_register failed\n"); 6178c2ecf20Sopenharmony_ci goto err_standby; 6188c2ecf20Sopenharmony_ci } 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci return 0; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_cierr_standby: 6238c2ecf20Sopenharmony_ci stk3310_set_state(data, STK3310_STATE_STANDBY); 6248c2ecf20Sopenharmony_ci return ret; 6258c2ecf20Sopenharmony_ci} 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_cistatic int stk3310_remove(struct i2c_client *client) 6288c2ecf20Sopenharmony_ci{ 6298c2ecf20Sopenharmony_ci struct iio_dev *indio_dev = i2c_get_clientdata(client); 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci iio_device_unregister(indio_dev); 6328c2ecf20Sopenharmony_ci return stk3310_set_state(iio_priv(indio_dev), STK3310_STATE_STANDBY); 6338c2ecf20Sopenharmony_ci} 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 6368c2ecf20Sopenharmony_cistatic int stk3310_suspend(struct device *dev) 6378c2ecf20Sopenharmony_ci{ 6388c2ecf20Sopenharmony_ci struct stk3310_data *data; 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci return stk3310_set_state(data, STK3310_STATE_STANDBY); 6438c2ecf20Sopenharmony_ci} 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_cistatic int stk3310_resume(struct device *dev) 6468c2ecf20Sopenharmony_ci{ 6478c2ecf20Sopenharmony_ci u8 state = 0; 6488c2ecf20Sopenharmony_ci struct stk3310_data *data; 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); 6518c2ecf20Sopenharmony_ci if (data->ps_enabled) 6528c2ecf20Sopenharmony_ci state |= STK3310_STATE_EN_PS; 6538c2ecf20Sopenharmony_ci if (data->als_enabled) 6548c2ecf20Sopenharmony_ci state |= STK3310_STATE_EN_ALS; 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci return stk3310_set_state(data, state); 6578c2ecf20Sopenharmony_ci} 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(stk3310_pm_ops, stk3310_suspend, stk3310_resume); 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci#define STK3310_PM_OPS (&stk3310_pm_ops) 6628c2ecf20Sopenharmony_ci#else 6638c2ecf20Sopenharmony_ci#define STK3310_PM_OPS NULL 6648c2ecf20Sopenharmony_ci#endif 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_cistatic const struct i2c_device_id stk3310_i2c_id[] = { 6678c2ecf20Sopenharmony_ci {"STK3310", 0}, 6688c2ecf20Sopenharmony_ci {"STK3311", 0}, 6698c2ecf20Sopenharmony_ci {"STK3335", 0}, 6708c2ecf20Sopenharmony_ci {} 6718c2ecf20Sopenharmony_ci}; 6728c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, stk3310_i2c_id); 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_cistatic const struct acpi_device_id stk3310_acpi_id[] = { 6758c2ecf20Sopenharmony_ci {"STK3310", 0}, 6768c2ecf20Sopenharmony_ci {"STK3311", 0}, 6778c2ecf20Sopenharmony_ci {"STK3335", 0}, 6788c2ecf20Sopenharmony_ci {} 6798c2ecf20Sopenharmony_ci}; 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, stk3310_acpi_id); 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_cistatic const struct of_device_id stk3310_of_match[] = { 6848c2ecf20Sopenharmony_ci { .compatible = "sensortek,stk3310", }, 6858c2ecf20Sopenharmony_ci { .compatible = "sensortek,stk3311", }, 6868c2ecf20Sopenharmony_ci { .compatible = "sensortek,stk3335", }, 6878c2ecf20Sopenharmony_ci {} 6888c2ecf20Sopenharmony_ci}; 6898c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, stk3310_of_match); 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_cistatic struct i2c_driver stk3310_driver = { 6928c2ecf20Sopenharmony_ci .driver = { 6938c2ecf20Sopenharmony_ci .name = "stk3310", 6948c2ecf20Sopenharmony_ci .of_match_table = stk3310_of_match, 6958c2ecf20Sopenharmony_ci .pm = STK3310_PM_OPS, 6968c2ecf20Sopenharmony_ci .acpi_match_table = ACPI_PTR(stk3310_acpi_id), 6978c2ecf20Sopenharmony_ci }, 6988c2ecf20Sopenharmony_ci .probe = stk3310_probe, 6998c2ecf20Sopenharmony_ci .remove = stk3310_remove, 7008c2ecf20Sopenharmony_ci .id_table = stk3310_i2c_id, 7018c2ecf20Sopenharmony_ci}; 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_cimodule_i2c_driver(stk3310_driver); 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ciMODULE_AUTHOR("Tiberiu Breana <tiberiu.a.breana@intel.com>"); 7068c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("STK3310 Ambient Light and Proximity Sensor driver"); 7078c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 708