/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "stk3013.h" #define DRIVER_VERSION "3.10.0_ps_only_20150508" /* Driver Settings */ #define STK_INT_PS_MODE 1 /* 1, 2, or 3 */ #undef STK_CHK_REG #define PROX_READ_NUM 40 /* Define Register Map */ #define STK_STATE_REG 0x00 #define STK_PSCTRL_REG 0x01 #define STK_LEDCTRL_REG 0x03 #define STK_INT_REG 0x04 #define STK_WAIT_REG 0x05 #define STK_THDH1_PS_REG 0x06 #define STK_THDH2_PS_REG 0x07 #define STK_THDL1_PS_REG 0x08 #define STK_THDL2_PS_REG 0x09 #define STK_FLAG_REG 0x10 #define STK_DATA1_PS_REG 0x11 #define STK_DATA2_PS_REG 0x12 #define STK_DATA1_OFFSET_REG 0x15 #define STK_DATA2_OFFSET_REG 0x16 #define STK_DATA1_IR_REG 0x17 #define STK_DATA2_IR_REG 0x18 #define STK_PDT_ID_REG 0x3E #define STK_RSRVD_REG 0x3F #define STK_SW_RESET_REG 0x80 #define STK_GSCTRL_REG 0x1A #define STK_FLAG2_REG 0x1C /* Define state reg */ #define STK_STATE_EN_IRS_SHIFT 7 #define STK_STATE_EN_AK_SHIFT 6 #define STK_STATE_EN_ASO_SHIFT 5 #define STK_STATE_EN_IRO_SHIFT 4 #define STK_STATE_EN_WAIT_SHIFT 2 #define STK_STATE_EN_PS_SHIFT 0 #define STK_STATE_EN_IRS_MASK 0x80 #define STK_STATE_EN_AK_MASK 0x40 #define STK_STATE_EN_ASO_MASK 0x20 #define STK_STATE_EN_IRO_MASK 0x10 #define STK_STATE_EN_WAIT_MASK 0x04 #define STK_STATE_EN_PS_MASK 0x01 /* Define PS ctrl reg */ #define STK_PS_PRS_SHIFT 6 #define STK_PS_GAIN_SHIFT 4 #define STK_PS_IT_SHIFT 0 #define STK_PS_PRS_MASK 0xC0 #define STK_PS_GAIN_MASK 0x30 #define STK_PS_IT_MASK 0x0F /* Define LED ctrl reg */ #define STK_LED_IRDR_SHIFT 6 #define STK_LED_DT_SHIFT 0 #define STK_LED_IRDR_MASK 0xC0 #define STK_LED_DT_MASK 0x3F /* Define interrupt reg */ #define STK_INT_CTRL_SHIFT 7 #define STK_INT_OUI_SHIFT 4 #define STK_INT_PS_SHIFT 0 #define STK_INT_CTRL_MASK 0x80 #define STK_INT_OUI_MASK 0x10 #define STK_INT_PS_MASK 0x07 /* Define flag reg */ #define STK_FLG_PSDR_SHIFT 6 #define STK_FLG_PSINT_SHIFT 4 #define STK_FLG_OUI_SHIFT 2 #define STK_FLG_IR_RDY_SHIFT 1 #define STK_FLG_NF_SHIFT 0 #define STK_FLG_PSDR_MASK 0x40 #define STK_FLG_PSINT_MASK 0x10 #define STK_FLG_OUI_MASK 0x04 #define STK_FLG_IR_RDY_MASK 0x02 #define STK_FLG_NF_MASK 0x01 #define VENDOR "SENSORTEK" #define CHIP_ID "STK3013" #define MODULE_NAME "proximity_sensor" #define STK3310SA_PID 0x17 #define STK3311SA_PID 0x1E #define STK3311WV_PID 0x1D #define PROXIMITY_FOR_TEST /* for HW to tune up */ #define PROXIMITY_CALIBRATION #ifdef PROXIMITY_CALIBRATION #define CALIBRATION_FILE_PATH "/efs/FactoryApp/prox_cal" #endif enum { OFF = 0, ON, }; struct stk3013_data { struct i2c_client *client; struct stk3013_platform_data *pdata; int32_t irq; struct work_struct stk_work; struct workqueue_struct *stk_wq; uint16_t ir_code; uint8_t psctrl_reg; uint8_t ledctrl_reg; uint8_t state_reg; int int_pin; uint8_t wait_reg; uint8_t int_reg; uint16_t ps_thd_h; uint16_t ps_thd_l; uint16_t ps_default_thd_h; uint16_t ps_default_thd_l; uint16_t ps_cancel_thd_h; uint16_t ps_cancel_thd_l; uint16_t ps_cal_skip_adc; uint16_t ps_cal_fail_adc; uint16_t ps_default_offset; uint16_t ps_offset; unsigned int cal_result; struct mutex io_lock; struct input_dev *ps_input_dev; int32_t ps_distance_last; bool ps_enabled; bool re_enable_ps; struct wake_lock ps_wakelock; ktime_t ps_poll_delay; bool first_boot; atomic_t recv_reg; uint8_t pid; uint8_t p_wv_r_bd_with_co; struct regulator *vdd; struct regulator *vio; struct device *ps_dev; struct hrtimer prox_timer; ktime_t prox_poll_delay; struct workqueue_struct *prox_wq; struct work_struct work_prox; int avg[3]; }; static int32_t stk3013_enable_ps(struct device *dev, uint8_t enable, uint8_t validate_reg); static int32_t stk3013_set_ps_thd_l(struct stk3013_data *ps_data, uint16_t thd_l); static int32_t stk3013_set_ps_thd_h(struct stk3013_data *ps_data, uint16_t thd_h); static int32_t stk3013_set_ps_offset(struct stk3013_data *ps_data, uint16_t ps_offset); #ifdef PROXIMITY_CALIBRATION static int check_calibration_offset(struct stk3013_data *ps_data); #endif #ifdef STK_CHK_REG static int stk3013_validate_n_handle(struct i2c_client *client); #endif static int stk3013_regulator_onoff(struct device *dev, bool onoff); static int32_t stk3013_init_all_setting(struct i2c_client *client, struct stk3013_platform_data *plat_data); static int stk3013_i2c_read_data(struct i2c_client *client, unsigned char command, int length, unsigned char *values) { uint8_t retry; int ret; struct i2c_msg msgs[] = { { .addr = client->addr, .flags = 0, .len = 1, .buf = &command, }, { .addr = client->addr, .flags = I2C_M_RD, .len = length, .buf = values, }, }; for (retry = 0; retry < 5; retry++) { ret = i2c_transfer(client->adapter, msgs, 2); if (ret == 2) break; } if (retry >= 5) { SENSOR_ERR("i2c read fail, err=%d\n", ret); return -EIO; } return 0; } static int stk3013_i2c_write_data(struct i2c_client *client, unsigned char command, int length, unsigned char *values) { int retry; int ret; unsigned char data[11]; struct i2c_msg msg; int index; if (!client) return -EINVAL; else if (length >= 10) { SENSOR_ERR("length %d exceeds 10\n", length); return -EINVAL; } data[0] = command; for (index = 1; index <= length; index++) data[index] = values[index-1]; msg.addr = client->addr; msg.flags = 0; msg.len = length+1; msg.buf = data; for (retry = 0; retry < 5; retry++) { ret = i2c_transfer(client->adapter, &msg, 1); if (ret == 1) break; } if (retry >= 5) { SENSOR_ERR("i2c write fail, err=%d\n", ret); return -EIO; } return 0; } static int stk3013_i2c_smbus_read_byte_data(struct i2c_client *client, unsigned char command) { unsigned char value; int ret; ret = stk3013_i2c_read_data(client, command, 1, &value); if (ret < 0) return ret; return value; } static int stk3013_i2c_smbus_write_byte_data(struct i2c_client *client, unsigned char command, unsigned char value) { int ret; ret = stk3013_i2c_write_data(client, command, 1, &value); return ret; } static void stk3013_proc_plat_data(struct stk3013_data *ps_data, struct stk3013_platform_data *plat_data) { uint8_t w_reg; ps_data->state_reg = plat_data->state_reg; ps_data->psctrl_reg = plat_data->psctrl_reg; ps_data->ledctrl_reg = plat_data->ledctrl_reg; if (ps_data->pid == STK3310SA_PID || ps_data->pid == STK3311SA_PID) ps_data->ledctrl_reg &= 0x3F; ps_data->wait_reg = plat_data->wait_reg; if (ps_data->wait_reg < 2) { SENSOR_INFO("wait_reg should be larger than 2, force to write 2\n"); ps_data->wait_reg = 2; } else if (ps_data->wait_reg > 0xFF) { SENSOR_INFO("wait_reg should be less than 0xFF, force to write 0xFF\n"); ps_data->wait_reg = 0xFF; } if (ps_data->ps_thd_h == 0 && ps_data->ps_thd_l == 0) { ps_data->ps_thd_h = plat_data->ps_thd_h; ps_data->ps_thd_l = plat_data->ps_thd_l; ps_data->ps_default_thd_h = plat_data->ps_thd_h; ps_data->ps_default_thd_l = plat_data->ps_thd_l; ps_data->ps_cancel_thd_h = plat_data->ps_cancel_thd_h; ps_data->ps_cancel_thd_l = plat_data->ps_cancel_thd_l; ps_data->ps_cal_skip_adc = plat_data->ps_cal_skip_adc; ps_data->ps_cal_fail_adc = plat_data->ps_cal_fail_adc; /*initialize the offset data*/ ps_data->ps_default_offset = plat_data->ps_default_offset; ps_data->ps_offset = ps_data->ps_default_offset; } w_reg = 0; w_reg |= STK_INT_PS_MODE; ps_data->int_reg = w_reg; } static int32_t stk3013_init_all_reg(struct stk3013_data *ps_data) { int32_t ret; ret = stk3013_i2c_smbus_write_byte_data(ps_data->client, STK_STATE_REG, ps_data->state_reg); if (ret < 0) { SENSOR_ERR("write i2c error\n"); return ret; } ret = stk3013_i2c_smbus_write_byte_data(ps_data->client, STK_PSCTRL_REG, ps_data->psctrl_reg); if (ret < 0) { SENSOR_ERR("write i2c error\n"); return ret; } ret = stk3013_i2c_smbus_write_byte_data(ps_data->client, STK_LEDCTRL_REG, ps_data->ledctrl_reg); if (ret < 0) { SENSOR_ERR("write i2c error\n"); return ret; } ret = stk3013_i2c_smbus_write_byte_data(ps_data->client, STK_WAIT_REG, ps_data->wait_reg); if (ret < 0) { SENSOR_ERR("write i2c error\n"); return ret; } stk3013_set_ps_thd_h(ps_data, ps_data->ps_thd_h); stk3013_set_ps_thd_l(ps_data, ps_data->ps_thd_l); stk3013_set_ps_offset(ps_data, ps_data->ps_default_offset); ret = stk3013_i2c_smbus_write_byte_data(ps_data->client, STK_INT_REG, ps_data->int_reg); if (ret < 0) { SENSOR_ERR("write i2c error\n"); return ret; } return 0; } static int32_t stk3013_read_otp25(struct stk3013_data *ps_data) { int32_t ret, otp25; ret = stk3013_i2c_smbus_write_byte_data(ps_data->client, 0x0, 0x2); if (ret < 0) { SENSOR_ERR("write i2c error\n"); return ret; } ret = stk3013_i2c_smbus_write_byte_data(ps_data->client, 0x90, 0x25); if (ret < 0) { SENSOR_ERR("write i2c error\n"); return ret; } ret = stk3013_i2c_smbus_write_byte_data(ps_data->client, 0x92, 0x82); if (ret < 0) { SENSOR_ERR("write i2c error\n"); return ret; } usleep_range(1000, 5000); ret = stk3013_i2c_smbus_read_byte_data(ps_data->client, 0x91); if (ret < 0) { SENSOR_ERR("fail, ret=%d\n", ret); return ret; } otp25 = ret; ret = stk3013_i2c_smbus_write_byte_data(ps_data->client, 0x0, 0x0); if (ret < 0) { SENSOR_ERR("write i2c error\n"); return ret; } SENSOR_INFO("otp25=0x%x\n", otp25); if (otp25 & 0x80) return 1; return 0; } static int32_t stk3013_check_pid(struct stk3013_data *ps_data) { unsigned char value[2], pid_msb; int ret; ps_data->p_wv_r_bd_with_co = 0; ret = stk3013_i2c_read_data(ps_data->client, STK_PDT_ID_REG, 2, &value[0]); if (ret < 0) { SENSOR_ERR("fail, ret=%d\n", ret); return ret; } SENSOR_INFO("PID=0x%x, RID=0x%x\n", value[0], value[1]); ps_data->pid = value[0]; if (value[0] == STK3311WV_PID) ps_data->p_wv_r_bd_with_co |= 0xb100; if (value[1] == 0xC3) ps_data->p_wv_r_bd_with_co |= 0xb010; if (stk3013_read_otp25(ps_data) == 1) ps_data->p_wv_r_bd_with_co |= 0xb001; SENSOR_INFO("p_wv_r_bd_with_co = 0x%x\n", ps_data->p_wv_r_bd_with_co); if (value[0] == 0) { SENSOR_ERR("PID=0x0, please make sure the chip is stk3013!\n"); return -ENXIO; } pid_msb = value[0] & 0xF0; switch (pid_msb) { case 0x10: case 0x20: case 0x30: return 0; default: SENSOR_ERR("invalid PID(%#x)\n", value[0]); return -EPERM; } return 0; } static int32_t stk3013_software_reset(struct stk3013_data *ps_data) { int32_t r; uint8_t w_reg; w_reg = 0x7F; r = stk3013_i2c_smbus_write_byte_data(ps_data->client, STK_WAIT_REG, w_reg); if (r < 0) { SENSOR_ERR("software reset: write i2c error, ret=%d\n", r); return r; } r = stk3013_i2c_smbus_read_byte_data(ps_data->client, STK_WAIT_REG); if (w_reg != r) { SENSOR_ERR("software reset: read-back value is not the same\n"); return -EPERM; } r = stk3013_i2c_smbus_write_byte_data(ps_data->client, STK_SW_RESET_REG, 0); if (r < 0) { SENSOR_ERR("software reset: read error after reset\n"); return r; } usleep_range(13000, 15000); return 0; } static int32_t stk3013_set_ps_thd_l(struct stk3013_data *ps_data, uint16_t thd_l) { unsigned char val[2]; int ret; val[0] = (thd_l & 0xFF00) >> 8; val[1] = thd_l & 0x00FF; ret = stk3013_i2c_write_data(ps_data->client, STK_THDL1_PS_REG, 2, val); if (ret < 0) SENSOR_ERR("fail, ret=%d\n", ret); else ps_data->ps_thd_l = thd_l; SENSOR_INFO("thd_l=%d\n", thd_l); return ret; } static int32_t stk3013_set_ps_thd_h(struct stk3013_data *ps_data, uint16_t thd_h) { unsigned char val[2]; int ret; val[0] = (thd_h & 0xFF00) >> 8; val[1] = thd_h & 0x00FF; ret = stk3013_i2c_write_data(ps_data->client, STK_THDH1_PS_REG, 2, val); if (ret < 0) SENSOR_ERR("fail, ret=%d\n", ret); else ps_data->ps_thd_h = thd_h; SENSOR_INFO("thd_h=%d\n", thd_h); return ret; } static int32_t stk3013_set_ps_offset(struct stk3013_data *ps_data, uint16_t ps_offset) { unsigned char val[2]; int ret; val[0] = (ps_offset & 0xFF00) >> 8; val[1] = ps_offset & 0x00FF; ret = stk3013_i2c_write_data(ps_data->client, STK_DATA1_OFFSET_REG, 2, val); if (ret < 0) SENSOR_ERR("fail, ret=%d\n", ret); return ret; } static uint32_t stk3013_get_ps_reading(struct stk3013_data *ps_data) { unsigned char value[2]; int ret; ret = stk3013_i2c_read_data(ps_data->client, STK_DATA1_PS_REG, 2, &value[0]); if (ret < 0) { SENSOR_ERR("DATA1 fail, ret=%d\n", ret); return ret; } return (value[0]<<8) | value[1]; } static int32_t stk3013_set_flag(struct stk3013_data *ps_data, uint8_t org_flag_reg, uint8_t clr) { uint8_t w_flag; int ret; w_flag = org_flag_reg | (STK_FLG_PSINT_MASK | STK_FLG_OUI_MASK | STK_FLG_IR_RDY_MASK); w_flag &= (~clr); /*SENSOR_INFO(" org_flag_reg=0x%x, w_flag = 0x%x\n", org_flag_reg, w_flag);*/ ret = stk3013_i2c_smbus_write_byte_data(ps_data->client, STK_FLAG_REG, w_flag); if (ret < 0) SENSOR_ERR("fail, ret=%d\n", ret); return ret; } static int32_t stk3013_get_flag(struct stk3013_data *ps_data) { int ret; ret = stk3013_i2c_smbus_read_byte_data(ps_data->client, STK_FLAG_REG); if (ret < 0) SENSOR_ERR("fail, ret=%d\n", ret); return ret; } static int32_t stk3013_set_state(struct stk3013_data *ps_data, uint8_t state) { int ret; ret = stk3013_i2c_smbus_write_byte_data(ps_data->client, STK_STATE_REG, state); if (ret < 0) SENSOR_ERR("fail, ret=%d\n", ret); return ret; } static int32_t stk3013_get_state(struct stk3013_data *ps_data) { int ret; ret = stk3013_i2c_smbus_read_byte_data(ps_data->client, STK_STATE_REG); if (ret < 0) SENSOR_ERR("fail, ret=%d\n", ret); return ret; } static int32_t stk3013_enable_ps(struct device *dev, uint8_t enable, uint8_t validate_reg) { struct stk3013_data *ps_data = dev_get_drvdata(dev); int32_t ret; uint8_t w_state_reg; uint8_t curr_ps_enable; uint32_t read_value; int32_t near_far_state; #ifdef STK_CHK_REG if (validate_reg) { ret = stk3013_validate_n_handle(ps_data->client); if (ret < 0) SENSOR_ERR("stk3013_validate_n_handle fail: %d\n", ret); } #endif /* #ifdef STK_CHK_REG */ curr_ps_enable = ps_data->ps_enabled ? 1 : 0; if (curr_ps_enable == enable) return 0; if (enable) { /*stk3013_regulator_onoff(dev, ON);*/ msleep(20); ret = stk3013_init_all_setting(ps_data->client, ps_data->pdata); if (ret < 0) { SENSOR_ERR("init setting fail, ret=%d\n", ret); return ret; } } if (ps_data->first_boot == true) ps_data->first_boot = false; ret = stk3013_get_state(ps_data); if (ret < 0) return ret; w_state_reg = ret; w_state_reg &= ~(STK_STATE_EN_PS_MASK | STK_STATE_EN_WAIT_MASK | STK_STATE_EN_AK_MASK); if (enable) w_state_reg |= (STK_STATE_EN_PS_MASK | STK_STATE_EN_WAIT_MASK); ret = stk3013_set_state(ps_data, w_state_reg); if (ret < 0) return ret; ps_data->state_reg = w_state_reg; if (enable) { #ifdef PROXIMITY_CALIBRATION check_calibration_offset(ps_data); stk3013_set_ps_offset(ps_data, ps_data->ps_offset); #endif enable_irq(ps_data->irq); ps_data->ps_enabled = true; #ifdef STK_CHK_REG if (!validate_reg) { ps_data->ps_distance_last = 1; input_report_abs(ps_data->ps_input_dev, ABS_DISTANCE, 1); input_sync(ps_data->ps_input_dev); wake_lock_timeout(&ps_data->ps_wakelock, 3 * HZ); read_value = stk3013_get_ps_reading(ps_data); SENSOR_INFO("force report ps input event=1, ps code=%d\n", read_value); } else #endif/* #ifdef STK_CHK_REG */ { usleep_range(4000, 5000); ret = stk3013_get_flag(ps_data); if (ret < 0) return ret; near_far_state = ret & STK_FLG_NF_MASK; ps_data->ps_distance_last = near_far_state; input_report_abs(ps_data->ps_input_dev, ABS_DISTANCE, enable); input_sync(ps_data->ps_input_dev); wake_lock_timeout(&ps_data->ps_wakelock, 3*HZ); read_value = stk3013_get_ps_reading(ps_data); SENSOR_INFO("ps input event=%d, ps code = %d\n", near_far_state, read_value); } } else { disable_irq(ps_data->irq); /*stk3013_regulator_onoff(dev, OFF);*/ ps_data->ps_enabled = false; } return ret; } #ifdef STK_CHK_REG static int stk3013_chk_reg_valid(struct stk3013_data *ps_data) { unsigned char value[9]; int ret; /* uint8_t cnt; for(cnt=0;cnt<9;cnt++) { value[cnt] = stk3013_i2c_smbus_read_byte_data(ps_data->client, (cnt+1)); if (value[cnt] < 0) { SENSOR_ERR("%s fail, ret=%d", value[cnt]); return value[cnt]; } } */ ret = stk3013_i2c_read_data(ps_data->client, STK_PSCTRL_REG, 9, &value[0]); if (ret < 0) { SENSOR_ERR(" fail, ret=%d\n", ret); return ret; } if (value[0] != ps_data->psctrl_reg) { SENSOR_ERR(" invalid reg 0x01=0x%2x\n", value[0]); return 0xFF; } if (value[2] != ps_data->ledctrl_reg) { SENSOR_ERR(" invalid reg 0x03=0x%2x\n", value[2]); return 0xFF; } if (value[3] != ps_data->int_reg) { SENSOR_ERR(" invalid reg 0x04=0x%2x\n", value[3]); return 0xFF; } if (value[4] != ps_data->wait_reg) { SENSOR_ERR(" invalid reg 0x05=0x%2x\n", value[4]); return 0xFF; } if (value[5] != ((ps_data->ps_thd_h & 0xFF00) >> 8)) { SENSOR_ERR(" invalid reg 0x06=0x%2x\n", value[5]); return 0xFF; } if (value[6] != (ps_data->ps_thd_h & 0x00FF)) { SENSOR_ERR(" invalid reg 0x07=0x%2x\n", value[6]); return 0xFF; } if (value[7] != ((ps_data->ps_thd_l & 0xFF00) >> 8)) { SENSOR_ERR(" invalid reg 0x08=0x%2x\n", value[7]); return 0xFF; } if (value[8] != (ps_data->ps_thd_l & 0x00FF)) { SENSOR_ERR(" invalid reg 0x09=0x%2x\n", value[8]); return 0xFF; } return 0; } static int stk3013_validate_n_handle(struct i2c_client *client) { struct stk3013_data *ps_data = i2c_get_clientdata(client); int ret; ret = stk3013_chk_reg_valid(ps_data); if (ret < 0) { SENSOR_ERR("stk3013_chk_reg_valid fail: %d\n", ret); return ret; } if (ret == 0xFF) { SENSOR_ERR("Re-init chip\n"); ret = stk3013_software_reset(ps_data); if (ret < 0) return ret; ret = stk3013_init_all_reg(ps_data); if (ret < 0) return ret; stk3013_set_ps_thd_h(ps_data, ps_data->ps_thd_h); stk3013_set_ps_thd_l(ps_data, ps_data->ps_thd_l); stk3013_set_ps_offset(ps_data, ps_data->ps_default_offset); return 0xFF; } return 0; } #endif /* #ifdef STK_CHK_REG */ #ifdef PROXIMITY_CALIBRATION static int proximity_store_calibration(struct device *dev, bool do_calib) { struct stk3013_data *ps_data = dev_get_drvdata(dev); struct file *cal_filp = NULL; mm_segment_t old_fs; unsigned char value[2]; int ret; uint16_t temp[2]; uint16_t offset_data = 0; SENSOR_INFO("start\n"); if (do_calib) { ret = stk3013_i2c_read_data(ps_data->client, STK_DATA1_PS_REG, 2, &value[0]); if (ret < 0) { SENSOR_ERR("DATA1 fail, ret=%d\n", ret); return ret; } offset_data = ((value[0]<<8) | value[1]); SENSOR_INFO("ps_offset = %d\n", offset_data); if (offset_data < ps_data->ps_cal_skip_adc) { SENSOR_INFO("skip calibration = %d\n", offset_data); ps_data->ps_offset = ps_data->ps_default_offset; ps_data->cal_result = 2; } else if (offset_data <= ps_data->ps_cal_fail_adc/*DO_CAL*/) { SENSOR_INFO("do calibration = %d\n", offset_data); temp[0] = ps_data->ps_default_offset; ps_data->ps_offset = offset_data + ps_data->ps_default_offset; ret = stk3013_set_ps_offset(ps_data, ps_data->ps_offset); if (ret < 0) { SENSOR_ERR("calibration fail\n"); ps_data->ps_default_offset = temp[0]; ps_data->cal_result = 0; } else { stk3013_set_ps_thd_h(ps_data, ps_data->ps_cancel_thd_h); stk3013_set_ps_thd_l(ps_data, ps_data->ps_cancel_thd_l); ps_data->cal_result = 1; } } else { SENSOR_INFO("fail offset calibration = %d\n", offset_data); ps_data->ps_offset = ps_data->ps_default_offset; } } else { /*reset*/ SENSOR_INFO("reset start\n"); temp[0] = ps_data->ps_offset; temp[1] = ps_data->cal_result; ps_data->ps_offset = ps_data->ps_default_offset; ps_data->cal_result = 0; ret = stk3013_set_ps_offset(ps_data, ps_data->ps_offset); if (ret < 0) { SENSOR_ERR("calibration reset fail\n"); ps_data->ps_default_offset = temp[0]; ps_data->cal_result = temp[1]; } SENSOR_INFO("ps_thd_h=%d, ps_thd_l=%d, ps_offset=%d\n", ps_data->ps_thd_h, ps_data->ps_thd_l, ps_data->ps_offset); stk3013_set_ps_thd_h(ps_data, ps_data->ps_default_thd_h); stk3013_set_ps_thd_l(ps_data, ps_data->ps_default_thd_l); } old_fs = get_fs(); set_fs(KERNEL_DS); cal_filp = filp_open(CALIBRATION_FILE_PATH, O_CREAT | O_TRUNC | O_WRONLY | O_SYNC, 0666); if (IS_ERR(cal_filp)) { SENSOR_ERR("Can't open calibration file\n"); set_fs(old_fs); ret = PTR_ERR(cal_filp); return ret; } ret = vfs_write(cal_filp, (char *)&ps_data->ps_offset, sizeof(u16), &cal_filp->f_pos); if (ret != sizeof(u16)) { SENSOR_ERR("Can't write the cancel data to file\n"); ret = -EIO; } filp_close(cal_filp, current->files); set_fs(old_fs); SENSOR_INFO("end\n"); return ret; } static ssize_t proximity_calibration_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { bool do_calib; int err; if (sysfs_streq(buf, "1")) /* calibrate cancelation value */ do_calib = true; else if (sysfs_streq(buf, "0")) /* reset cancelation value */ do_calib = false; else { SENSOR_ERR("invalid value %d\n", *buf); return -EINVAL; } SENSOR_INFO("%d\n", do_calib); err = proximity_store_calibration(dev, do_calib); if (err < 0) { SENSOR_ERR("proximity_store_cancelation() failed\n"); return err; } return size; } static ssize_t proximity_calibration_show(struct device *dev, struct device_attribute *attr, char *buf) { struct stk3013_data *ps_data = dev_get_drvdata(dev); return snprintf(buf, PAGE_SIZE, "%u,%u,%u\n", ps_data->ps_offset, (ps_data->ps_offset != ps_data->ps_default_offset) ? ps_data->ps_cancel_thd_h : ps_data->ps_thd_h, (ps_data->ps_offset != ps_data->ps_default_offset) ? ps_data->ps_cancel_thd_l : ps_data->ps_thd_l); } static ssize_t proximity_calibration_pass_show(struct device *dev, struct device_attribute *attr, char *buf) { struct stk3013_data *ps_data = dev_get_drvdata(dev); SENSOR_INFO("result = %d\n", ps_data->cal_result); return snprintf(buf, PAGE_SIZE, "%u\n", ps_data->cal_result); } #endif static ssize_t proximity_avg_show(struct device *dev, struct device_attribute *attr, char *buf) { struct stk3013_data *ps_data = dev_get_drvdata(dev); return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n", ps_data->avg[0], ps_data->avg[1], ps_data->avg[2]); } static void proximity_get_avg_val(struct stk3013_data *ps_data) { int min = 0, max = 0, avg = 0; int i; uint32_t read_value; for (i = 0; i < PROX_READ_NUM; i++) { msleep(40); read_value = stk3013_get_ps_reading(ps_data); avg += read_value; if (!i) min = read_value; else if (read_value < min) min = read_value; if (read_value > max) max = read_value; } avg /= PROX_READ_NUM; ps_data->avg[0] = min; ps_data->avg[1] = avg; ps_data->avg[2] = max; } static ssize_t proximity_avg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct stk3013_data *ps_data = dev_get_drvdata(dev); bool new_value = false; if (sysfs_streq(buf, "1")) new_value = true; else if (sysfs_streq(buf, "0")) new_value = false; else { SENSOR_ERR("invalid value %d\n", *buf); return -EINVAL; } SENSOR_INFO("average enable = %d\n", new_value); if (new_value) { if ((ps_data->ps_enabled ? 1 : 0) == OFF) { mutex_lock(&ps_data->io_lock); stk3013_enable_ps(dev, new_value, 1); mutex_unlock(&ps_data->io_lock); } hrtimer_start(&ps_data->prox_timer, ps_data->prox_poll_delay, HRTIMER_MODE_REL); } else if (!new_value) { hrtimer_cancel(&ps_data->prox_timer); cancel_work_sync(&ps_data->work_prox); if ((ps_data->ps_enabled ? 1 : 0) == OFF) { mutex_lock(&ps_data->io_lock); stk3013_enable_ps(dev, new_value, 0); mutex_unlock(&ps_data->io_lock); } } return size; } static ssize_t proximity_trim_show(struct device *dev, struct device_attribute *attr, char *buf) { struct stk3013_data *ps_data = dev_get_drvdata(dev); SENSOR_INFO("trim: %d\n", ps_data->ps_default_offset); return snprintf(buf, PAGE_SIZE, "%u\n", ps_data->ps_default_offset); } static void stk3013_work_func_prox(struct work_struct *work) { struct stk3013_data *ps_data = container_of(work, struct stk3013_data, work_prox); proximity_get_avg_val(ps_data); } static enum hrtimer_restart stk3013_prox_timer_func(struct hrtimer *timer) { struct stk3013_data *ps_data = container_of(timer, struct stk3013_data, prox_timer); queue_work(ps_data->prox_wq, &ps_data->work_prox); hrtimer_forward_now(&ps_data->prox_timer, ps_data->prox_poll_delay); return HRTIMER_RESTART; } static ssize_t proximity_thresh_high_show(struct device *dev, struct device_attribute *attr, char *buf) { int32_t ps_thd_h1_reg, ps_thd_h2_reg; struct stk3013_data *ps_data = dev_get_drvdata(dev); ps_thd_h1_reg = stk3013_i2c_smbus_read_byte_data(ps_data->client, STK_THDH1_PS_REG); if (ps_thd_h1_reg < 0) { SENSOR_ERR("fail, err=0x%x", ps_thd_h1_reg); return -EINVAL; } ps_thd_h2_reg = stk3013_i2c_smbus_read_byte_data(ps_data->client, STK_THDH2_PS_REG); if (ps_thd_h2_reg < 0) { SENSOR_ERR("fail, err=0x%x", ps_thd_h2_reg); return -EINVAL; } ps_thd_h1_reg = ps_thd_h1_reg<<8 | ps_thd_h2_reg; SENSOR_INFO("thresh:0x%x", ps_thd_h1_reg); return scnprintf(buf, PAGE_SIZE, "%d\n", ps_thd_h1_reg); } static ssize_t proximity_thresh_high_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct stk3013_data *ps_data = dev_get_drvdata(dev); u16 value = 0; int ret; ret = kstrtou16(buf, 10, &value); if (ret < 0) { SENSOR_ERR("kstrtoul failed, ret=0x%x\n", ret); return ret; } SENSOR_INFO("thresh: %d\n", value); stk3013_set_ps_thd_h(ps_data, value); return size; } static ssize_t proximity_thresh_low_show(struct device *dev, struct device_attribute *attr, char *buf) { int32_t ps_thd_l1_reg, ps_thd_l2_reg; struct stk3013_data *ps_data = dev_get_drvdata(dev); ps_thd_l1_reg = stk3013_i2c_smbus_read_byte_data(ps_data->client, STK_THDL1_PS_REG); if (ps_thd_l1_reg < 0) { SENSOR_ERR("fail, err=0x%x", ps_thd_l1_reg); return -EINVAL; } ps_thd_l2_reg = stk3013_i2c_smbus_read_byte_data(ps_data->client, STK_THDL2_PS_REG); if (ps_thd_l2_reg < 0) { SENSOR_ERR("fail, err=0x%x", ps_thd_l2_reg); return -EINVAL; } ps_thd_l1_reg = ps_thd_l1_reg<<8 | ps_thd_l2_reg; return scnprintf(buf, PAGE_SIZE, "%d\n", ps_thd_l1_reg); } static ssize_t proximity_thresh_low_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct stk3013_data *ps_data = dev_get_drvdata(dev); u16 value = 0; int ret; ret = kstrtou16(buf, 10, &value); if (ret < 0) { SENSOR_ERR("kstrtoul failed, ret=0x%x\n", ret); return ret; } SENSOR_INFO("thresh: %d\n", value); stk3013_set_ps_thd_l(ps_data, value); return size; } static ssize_t proximity_state_show(struct device *dev, struct device_attribute *attr, char *buf) { struct stk3013_data *ps_data = dev_get_drvdata(dev); uint32_t read_value; read_value = stk3013_get_ps_reading(ps_data); return scnprintf(buf, PAGE_SIZE, "%d\n", read_value); } static ssize_t stk3013_vendor_show(struct device *dev, struct device_attribute *attr, char *buf) { return snprintf(buf, PAGE_SIZE, "%s\n", VENDOR); } static ssize_t stk3013_name_show(struct device *dev, struct device_attribute *attr, char *buf) { return snprintf(buf, PAGE_SIZE, "%s\n", CHIP_ID); } #if defined(PROXIMITY_FOR_TEST) static ssize_t proximity_register_write_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { unsigned int regist = 0, val = 0; int ret; struct stk3013_data *data = dev_get_drvdata(dev); if (sscanf(buf, "%2x,%2x", ®ist, &val) != 2) { SENSOR_ERR("The number of data are wrong\n"); return -EINVAL; } ret = stk3013_i2c_write_data(data->client, regist, 1, (unsigned char *)&val); if (ret < 0) SENSOR_ERR("fail, ret=%d\n", ret); else SENSOR_INFO("Register(0x%2x) data(0x%2x)\n", regist, val); return count; } static ssize_t proximity_register_read_show(struct device *dev, struct device_attribute *attr, char *buf) { u8 reg; unsigned char val = 0; int offset = 0; struct stk3013_data *data = dev_get_drvdata(dev); for (reg = STK_STATE_REG; reg <= STK_DATA2_OFFSET_REG; reg++) { stk3013_i2c_read_data(data->client, reg, 1, &val); SENSOR_INFO("Register(0x%2x) data(0x%2x)\n", reg, val); offset += snprintf(buf + offset, PAGE_SIZE - offset, "Reg: 0x%2x, Val: 0x%2x\n", reg, val); } return offset; } #endif #ifdef PROXIMITY_CALIBRATION static DEVICE_ATTR(prox_cal, S_IRUGO | S_IWUSR | S_IWGRP, proximity_calibration_show, proximity_calibration_store); static DEVICE_ATTR(prox_offset_pass, S_IRUGO, proximity_calibration_pass_show, NULL); #endif #if defined(PROXIMITY_FOR_TEST) static DEVICE_ATTR(prox_register, S_IRUGO | S_IWUSR | S_IWGRP, proximity_register_read_show, proximity_register_write_store); #endif static DEVICE_ATTR(prox_avg, S_IRUGO | S_IWUSR | S_IWGRP, proximity_avg_show, proximity_avg_store); static DEVICE_ATTR(prox_trim, S_IRUGO, proximity_trim_show, NULL); static DEVICE_ATTR(thresh_high, S_IRUGO | S_IWUSR | S_IWGRP, proximity_thresh_high_show, proximity_thresh_high_store); static DEVICE_ATTR(thresh_low, S_IRUGO | S_IWUSR | S_IWGRP, proximity_thresh_low_show, proximity_thresh_low_store); static DEVICE_ATTR(state, S_IRUGO, proximity_state_show, NULL); static DEVICE_ATTR(raw_data, S_IRUGO, proximity_state_show, NULL); static DEVICE_ATTR(vendor, S_IRUGO, stk3013_vendor_show, NULL); static DEVICE_ATTR(name, S_IRUGO, stk3013_name_show, NULL); static struct device_attribute *prox_sensor_attrs[] = { #ifdef PROXIMITY_CALIBRATION &dev_attr_prox_cal, &dev_attr_prox_offset_pass, #endif #if defined(PROXIMITY_FOR_TEST) &dev_attr_prox_register, #endif &dev_attr_prox_avg, &dev_attr_prox_trim, &dev_attr_thresh_high, &dev_attr_thresh_low, &dev_attr_state, &dev_attr_raw_data, &dev_attr_vendor, &dev_attr_name, NULL, }; static ssize_t proximity_enable_show(struct device *dev, struct device_attribute *attr, char *buf) { int32_t ret; struct stk3013_data *ps_data = dev_get_drvdata(dev); ret = stk3013_get_state(ps_data); if (ret < 0) return ret; ret = (ret & STK_STATE_EN_PS_MASK) ? 1 : 0; return scnprintf(buf, PAGE_SIZE, "%d\n", ret); } static ssize_t proximity_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct stk3013_data *ps_data = dev_get_drvdata(dev); uint8_t en; if (sysfs_streq(buf, "1")) en = 1; else if (sysfs_streq(buf, "0")) en = 0; else { SENSOR_ERR("invalid value %d\n", *buf); return size; } SENSOR_INFO("Enable PS : %d\n", en); mutex_lock(&ps_data->io_lock); stk3013_enable_ps(dev, en, 1); mutex_unlock(&ps_data->io_lock); return size; } static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR | S_IWGRP, proximity_enable_show, proximity_enable_store); static struct attribute *proximity_sysfs_attrs[] = { &dev_attr_enable.attr, NULL }; static struct attribute_group proximity_attribute_group = { .attrs = proximity_sysfs_attrs, }; static void stk_work_func(struct work_struct *work) { uint32_t read_value; #if ((STK_INT_PS_MODE != 0x03) && (STK_INT_PS_MODE != 0x02)) int32_t ret; uint8_t disable_flag = 0; int32_t org_flag_reg; #endif/* #if ((STK_INT_PS_MODE != 0x03) && (STK_INT_PS_MODE != 0x02)) */ struct stk3013_data *ps_data = container_of(work, struct stk3013_data, stk_work); int32_t near_far_state; #if (STK_INT_PS_MODE == 0x03) near_far_state = gpio_get_value(ps_data->int_pin); #elif (STK_INT_PS_MODE == 0x02) near_far_state = !(gpio_get_value(ps_data->int_pin)); #endif #if ((STK_INT_PS_MODE == 0x03) || (STK_INT_PS_MODE == 0x02)) ps_data->ps_distance_last = near_far_state; input_report_abs(ps_data->ps_input_dev, ABS_DISTANCE, near_far_state); input_sync(ps_data->ps_input_dev); wake_lock_timeout(&ps_data->ps_wakelock, 3 * HZ); read_value = stk3013_get_ps_reading(ps_data); SENSOR_INFO("ps input event %d cm, ps code = %d\n", near_far_state, read_value); #else /* mode 0x01 or 0x04 */ org_flag_reg = stk3013_get_flag(ps_data); if (org_flag_reg < 0) goto err_i2c_rw; if (org_flag_reg & STK_FLG_PSINT_MASK) { disable_flag |= STK_FLG_PSINT_MASK; near_far_state = (org_flag_reg & STK_FLG_NF_MASK) ? 1 : 0; ps_data->ps_distance_last = near_far_state; read_value = stk3013_get_ps_reading(ps_data); #ifdef CONFIG_SEC_FACTORY SENSOR_INFO("FACTORY: near/far=%d, ps code = %d\n", near_far_state, read_value); #else SENSOR_INFO("near/far=%d, ps code = %d\n", near_far_state, read_value); if ((near_far_state == 0 && read_value >= ps_data->ps_thd_h) || (near_far_state == 1 && read_value <= ps_data->ps_thd_l)) #endif { input_report_abs(ps_data->ps_input_dev, ABS_DISTANCE, near_far_state); input_sync(ps_data->ps_input_dev); wake_lock_timeout(&ps_data->ps_wakelock, 3 * HZ); } } if (disable_flag) { ret = stk3013_set_flag(ps_data, org_flag_reg, disable_flag); if (ret < 0) goto err_i2c_rw; } #endif usleep_range(1000, 2000); goto exit; err_i2c_rw: msleep(30); exit: enable_irq(ps_data->irq); } static irqreturn_t stk_oss_irq_handler(int irq, void *data) { struct stk3013_data *pData = data; disable_irq_nosync(irq); queue_work(pData->stk_wq, &pData->stk_work); return IRQ_HANDLED; } static int32_t stk3013_init_all_setting(struct i2c_client *client, struct stk3013_platform_data *plat_data) { int32_t ret; struct stk3013_data *ps_data = i2c_get_clientdata(client); ret = stk3013_software_reset(ps_data); if (ret < 0) return ret; ret = stk3013_check_pid(ps_data); if (ret < 0) return ret; stk3013_proc_plat_data(ps_data, plat_data); ret = stk3013_init_all_reg(ps_data); if (ret < 0) return ret; ps_data->ps_enabled = false; ps_data->re_enable_ps = false; ps_data->ir_code = 0; ps_data->first_boot = true; atomic_set(&ps_data->recv_reg, 0); ps_data->ps_distance_last = 1; return 0; } static int stk3013_setup_irq(struct i2c_client *client) { int irq, ret = -EIO; struct stk3013_data *ps_data = i2c_get_clientdata(client); irq = gpio_to_irq(ps_data->int_pin); SENSOR_INFO("int pin #=%d, irq=%d\n", ps_data->int_pin, irq); if (irq <= 0) { SENSOR_ERR("irq number is not specified, irq=%d, int pin=%d\n", irq, ps_data->int_pin); return irq; } ps_data->irq = irq; ret = gpio_request(ps_data->int_pin, "stk-int"); if (ret < 0) { SENSOR_ERR("gpio_request, err=%d", ret); return ret; } ret = gpio_direction_input(ps_data->int_pin); if (ret < 0) { SENSOR_ERR("gpio_direction_input, err=%d", ret); return ret; } #if ((STK_INT_PS_MODE == 0x03) || (STK_INT_PS_MODE == 0x02)) ret = request_any_context_irq(irq, stk_oss_irq_handler, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "proximity_int", ps_data); #else ret = request_any_context_irq(irq, stk_oss_irq_handler, IRQF_TRIGGER_LOW, "proximity_int", ps_data); #endif if (ret < 0) { SENSOR_WARN("request_any_context_irq(%d) failed for (%d)\n", irq, ret); goto err_request_any_context_irq; } disable_irq(irq); return 0; err_request_any_context_irq: gpio_free(ps_data->int_pin); return ret; } static int stk3013_suspend(struct device *dev) { struct stk3013_data *ps_data = dev_get_drvdata(dev); int ret; struct i2c_client *client = to_i2c_client(dev); SENSOR_INFO("\n"); mutex_lock(&ps_data->io_lock); #ifdef STK_CHK_REG ret = stk3013_validate_n_handle(ps_data->client); if (ret < 0) { SENSOR_ERR("stk3013_validate_n_handle fail: %d\n", ret); } else if (ret == 0xFF) { if (ps_data->ps_enabled) stk3013_enable_ps(ps_data, 1, 0); } #endif /* #ifdef STK_CHK_REG */ if (ps_data->ps_enabled) { if (device_may_wakeup(&client->dev)) { ret = enable_irq_wake(ps_data->irq); if (ret) SENSOR_WARN("set_irq_wake(%d) failed(%d)\n", ps_data->irq, ret); } else { SENSOR_ERR("not support wakeup source"); } } mutex_unlock(&ps_data->io_lock); return 0; } static int stk3013_resume(struct device *dev) { struct stk3013_data *ps_data = dev_get_drvdata(dev); int ret; struct i2c_client *client = to_i2c_client(dev); SENSOR_INFO("\n"); mutex_lock(&ps_data->io_lock); #ifdef STK_CHK_REG ret = stk3013_validate_n_handle(ps_data->client); if (ret < 0) { SENSOR_ERR("stk3013_validate_n_handle fail: %d\n", ret); } else if (ret == 0xFF) { if (ps_data->ps_enabled) stk3013_enable_ps(ps_data, 1, 0); } #endif/* #ifdef STK_CHK_REG */ if (ps_data->ps_enabled) { if (device_may_wakeup(&client->dev)) { ret = disable_irq_wake(ps_data->irq); if (ret) SENSOR_WARN("disable_irq_wake(%d) fail(%d)\n", ps_data->irq, ret); } } mutex_unlock(&ps_data->io_lock); return 0; } static const struct dev_pm_ops stk3013_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(stk3013_suspend, stk3013_resume) }; static int stk3013_regulator_onoff(struct device *dev, bool onoff) { struct stk3013_data *ps_data = dev_get_drvdata(dev); int ret; SENSOR_INFO("%s\n", (onoff) ? "on" : "off"); if (!ps_data->vdd || IS_ERR(ps_data->vdd)) { SENSOR_INFO("VDD get regulator\n"); ps_data->vdd = devm_regulator_get(dev, "stk,vdd"); if (IS_ERR(ps_data->vdd)) { SENSOR_ERR("cannot get vdd\n"); return -ENOMEM; } regulator_set_voltage(ps_data->vdd, 2800000,2800000); } if (!ps_data->vio || IS_ERR(ps_data->vio)) { SENSOR_INFO("VIO get regulator\n"); ps_data->vio = devm_regulator_get(dev, "stk,vio"); if (IS_ERR(ps_data->vio)) { SENSOR_ERR("cannot get vio\n"); devm_regulator_put(ps_data->vdd); return -ENOMEM; } regulator_set_voltage(ps_data->vio, 1800000, 1800000); } if (onoff) { ret = regulator_enable(ps_data->vdd); if (ret) SENSOR_ERR("Failed to enable vdd.\n"); msleep(20); ret = regulator_enable(ps_data->vio); if (ret) SENSOR_ERR("Failed to enable vio.\n"); msleep(20); } else { ret = regulator_disable(ps_data->vdd); if (ret) SENSOR_ERR("Failed to disable vdd.\n"); msleep(20); ret = regulator_disable(ps_data->vio); if (ret) SENSOR_ERR("Failed to disable vio.\n"); msleep(20); } return 0; } static int stk3013_parse_dt(struct device *dev, struct stk3013_platform_data *pdata) { int rc; struct device_node *np = dev->of_node; u32 temp_val; if (!pdata) return -ENOMEM; pdata->int_pin = of_get_named_gpio_flags(np, "stk,irq-gpio", 0, &pdata->int_flags); if (pdata->int_pin < 0) { dev_err(dev, "Unable to read irq-gpio\n"); return pdata->int_pin; } rc = of_property_read_u32(np, "stk,transmittance", &temp_val); if (!rc) pdata->transmittance = temp_val; else { dev_err(dev, "Unable to read transmittance\n"); return rc; } rc = of_property_read_u32(np, "stk,state-reg", &temp_val); if (!rc) pdata->state_reg = temp_val; else { dev_err(dev, "Unable to read state-reg\n"); return rc; } rc = of_property_read_u32(np, "stk,psctrl-reg", &temp_val); if (!rc) pdata->psctrl_reg = (u8)temp_val; else { dev_err(dev, "Unable to read psctrl-reg\n"); return rc; } /* rc = of_property_read_u32(np, "stk,alsctrl-reg", &temp_val); if (!rc) pdata->alsctrl_reg = (u8)temp_val; else { dev_err(dev, "Unable to read alsctrl-reg\n"); return rc; } */ rc = of_property_read_u32(np, "stk,ledctrl-reg", &temp_val); if (!rc) pdata->ledctrl_reg = (u8)temp_val; else { dev_err(dev, "Unable to read ledctrl-reg\n"); return rc; } rc = of_property_read_u32(np, "stk,wait-reg", &temp_val); if (!rc) pdata->wait_reg = (u8)temp_val; else { dev_err(dev, "Unable to read wait-reg\n"); return rc; } rc = of_property_read_u32(np, "stk,ps-thd-h", &temp_val); if (!rc) pdata->ps_thd_h = (u16)temp_val; else { dev_err(dev, "Unable to read ps-thd-h\n"); return rc; } rc = of_property_read_u32(np, "stk,ps-thd-l", &temp_val); if (!rc) pdata->ps_thd_l = (u16)temp_val; else { dev_err(dev, "Unable to read ps-thd-l\n"); return rc; } rc = of_property_read_u32(np, "stk,ps-cancel-thd-h", &temp_val); if (!rc) pdata->ps_cancel_thd_h = (u16)temp_val; else { dev_err(dev, "Unable to read ps-cancel-thd-h\n"); return rc; } rc = of_property_read_u32(np, "stk,ps-cancel-thd-l", &temp_val); if (!rc) pdata->ps_cancel_thd_l = (u16)temp_val; else { dev_err(dev, "Unable to read ps-cancel-thd-l\n"); return rc; } rc = of_property_read_u32(np, "stk,ps-cal-skip-adc", &temp_val); if (!rc) pdata->ps_cal_skip_adc = (u16)temp_val; else { dev_err(dev, "Unable to read ps-cal-skip-adc\n"); return rc; } rc = of_property_read_u32(np, "stk,ps-cal-fail-adc", &temp_val); if (!rc) pdata->ps_cal_fail_adc = (u16)temp_val; else { dev_err(dev, "Unable to read ps-cal-fail-adc\n"); return rc; } rc = of_property_read_u32(np, "stk,ps-default-offset", &temp_val); if (!rc) pdata->ps_default_offset = (u16)temp_val; else { dev_err(dev, "Unable to read ps-default-offset\n"); return rc; } return 0; } #ifdef PROXIMITY_CALIBRATION static int check_calibration_offset(struct stk3013_data *ps_data) { struct file *cal_filp = NULL; mm_segment_t old_fs; uint16_t file_offset_data; int ret; old_fs = get_fs(); set_fs(KERNEL_DS); cal_filp = filp_open(CALIBRATION_FILE_PATH, O_RDONLY, 0); if (IS_ERR(cal_filp)) { ret = PTR_ERR(cal_filp); if (ret != -ENOENT) SENSOR_ERR("Can't open calibration file\n"); set_fs(old_fs); ps_data->ps_offset = ps_data->ps_default_offset; SENSOR_ERR("Can't open calibration file 2(%d) ps_offset =%d\n", ret, ps_data->ps_offset); return ret; } ret = vfs_read(cal_filp, (char *)&file_offset_data, sizeof(u16), &cal_filp->f_pos); if (ret != sizeof(u16)) { SENSOR_ERR("Can't read the cal data from file\n"); ret = -EIO; } if(file_offset_data < ps_data->ps_cal_skip_adc) goto exit; if (file_offset_data != ps_data->ps_offset) ps_data->ps_offset = file_offset_data; if (ps_data->ps_offset != ps_data->ps_default_offset) { stk3013_set_ps_thd_h(ps_data, ps_data->ps_cancel_thd_h); stk3013_set_ps_thd_l(ps_data, ps_data->ps_cancel_thd_l); } exit: SENSOR_INFO("file_offset = %d, ps_offset = %d, default_offset = %d\n", file_offset_data, ps_data->ps_offset, ps_data->ps_default_offset); filp_close(cal_filp, current->files); set_fs(old_fs); return ret; } #endif static int stk3013_set_wq(struct stk3013_data *ps_data) { ps_data->stk_wq = create_singlethread_workqueue("stk_wq"); INIT_WORK(&ps_data->stk_work, stk_work_func); return 0; } static int stk3013_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret = -ENODEV; struct stk3013_data *ps_data; struct stk3013_platform_data *plat_data; SENSOR_INFO("driver version = %s\n", DRIVER_VERSION); if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { SENSOR_ERR("No Support for I2C_FUNC_I2C\n"); return ret; } ps_data = kzalloc(sizeof(struct stk3013_data), GFP_KERNEL); if (!ps_data) { SENSOR_ERR("failed to allocate stk3013_data\n"); return -ENOMEM; } ps_data->client = client; i2c_set_clientdata(client, ps_data); mutex_init(&ps_data->io_lock); wake_lock_init(&ps_data->ps_wakelock, WAKE_LOCK_SUSPEND, "stk_input_wakelock"); if (client->dev.of_node) { SENSOR_INFO("with device tree\n"); plat_data = devm_kzalloc(&client->dev, sizeof(struct stk3013_platform_data), GFP_KERNEL); if (!plat_data) { dev_err(&client->dev, "Failed to allocate memory\n"); ret = -ENOMEM; goto err_als_input_allocate; } ret = stk3013_parse_dt(&client->dev, plat_data); if (ret) { SENSOR_ERR("stk3013_parse_dt ret=%d\n", ret); goto err_als_input_allocate; } } else { SENSOR_INFO("with platform data\n"); plat_data = client->dev.platform_data; } if (!plat_data) { SENSOR_ERR("no stk3013 platform data!\n"); ret = -ENOMEM; goto err_als_input_allocate; } stk3013_regulator_onoff(&client->dev, ON); ps_data->int_pin = plat_data->int_pin; ps_data->pdata = plat_data; stk3013_set_wq(ps_data); ret = stk3013_init_all_setting(client, plat_data); if (ret < 0) goto err_init_all_setting; ps_data->ps_input_dev = input_allocate_device(); if (ps_data->ps_input_dev == NULL) { SENSOR_ERR("could not allocate ps device\n"); ret = -ENOMEM; goto err_input_alloc_device; } ps_data->ps_input_dev->name = MODULE_NAME; set_bit(EV_ABS, ps_data->ps_input_dev->evbit); input_set_capability(ps_data->ps_input_dev, EV_ABS, ABS_DISTANCE); input_set_abs_params(ps_data->ps_input_dev, ABS_DISTANCE, 0, 1, 0, 0); ret = input_register_device(ps_data->ps_input_dev); if (ret < 0) { SENSOR_ERR("can not register ps input device\n"); goto err_input_register_device; } ret = sensors_create_symlink(&ps_data->ps_input_dev->dev.kobj, ps_data->ps_input_dev->name); if (ret < 0) { SENSOR_ERR("create_symlink error\n"); goto err_sensors_create_symlink_prox; } ret = sysfs_create_group(&ps_data->ps_input_dev->dev.kobj, &proximity_attribute_group); if (ret < 0) { SENSOR_ERR("could not create sysfs group for ps\n"); goto err_sysfs_create_group_proximity; } input_set_drvdata(ps_data->ps_input_dev, ps_data); ret = stk3013_setup_irq(client); if (ret < 0) goto err_stk3013_setup_irq; device_init_wakeup(&client->dev, true); hrtimer_init(&ps_data->prox_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ps_data->prox_poll_delay = ns_to_ktime(2000 * NSEC_PER_MSEC);/*2 sec*/ ps_data->prox_timer.function = stk3013_prox_timer_func; /* the timer just fires off a work queue request. we need a thread to read the i2c (can be slow and blocking). */ ps_data->prox_wq = create_singlethread_workqueue("stk3013_prox_wq"); if (!ps_data->prox_wq) { ret = -ENOMEM; SENSOR_ERR("could not create prox workqueue\n"); goto err_create_prox_workqueue; } /* this is the thread function we run on the work queue */ INIT_WORK(&ps_data->work_prox, stk3013_work_func_prox); ret = sensors_register(&ps_data->ps_dev, ps_data, prox_sensor_attrs, MODULE_NAME); if (ret) { SENSOR_ERR("cound not register proximity sensor device(%d)\n", ret); goto prox_sensor_register_failed; } /*stk3013_regulator_onoff(&client->dev, OFF);*/ SENSOR_INFO("success\n"); return 0; /*device_init_wakeup(&client->dev, false);*/ prox_sensor_register_failed: destroy_workqueue(ps_data->prox_wq); err_create_prox_workqueue: err_stk3013_setup_irq: free_irq(ps_data->irq, ps_data); gpio_free(ps_data->int_pin); err_sysfs_create_group_proximity: sensors_remove_symlink(&ps_data->ps_input_dev->dev.kobj, ps_data->ps_input_dev->name); err_sensors_create_symlink_prox: input_unregister_device(ps_data->ps_input_dev); err_input_register_device: err_input_alloc_device: err_init_all_setting: destroy_workqueue(ps_data->stk_wq); /*stk3013_regulator_onoff(&client->dev, OFF);*/ err_als_input_allocate: wake_lock_destroy(&ps_data->ps_wakelock); mutex_destroy(&ps_data->io_lock); kfree(ps_data); return ret; } static int stk3013_remove(struct i2c_client *client) { SENSOR_INFO("\n"); return 0; } static const struct i2c_device_id stk_ps_id[] = { { "stk_ps", 0}, {} }; MODULE_DEVICE_TABLE(i2c, stk_ps_id); static struct of_device_id stk_match_table[] = { { .compatible = "stk,stk3013", }, { }, }; static struct i2c_driver stk_ps_driver = { .driver = { .name = CHIP_ID, .owner = THIS_MODULE, .of_match_table = stk_match_table, .pm = &stk3013_pm_ops, }, .probe = stk3013_probe, .remove = stk3013_remove, .id_table = stk_ps_id, }; static int __init stk3013_init(void) { int ret; ret = i2c_add_driver(&stk_ps_driver); if (ret) i2c_del_driver(&stk_ps_driver); return ret; } static void __exit stk3013_exit(void) { i2c_del_driver(&stk_ps_driver); } module_init(stk3013_init); module_exit(stk3013_exit); MODULE_AUTHOR("Samsung Electronics"); MODULE_DESCRIPTION("Sensortek stk3013 Proximity Sensor driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRIVER_VERSION);