static int px3215_init_client(struct i2c_client *client) { struct px3215_data *data = i2c_get_clientdata(client); int i; /* read all the registers once to fill the cache. * if one of the reads fails, we consider the init failed */ for (i = 0; i < ARRAY_SIZE(data->reg_cache); i++) { int v = i2c_smbus_read_byte_data(client, px3215_reg[i]); if (v < 0) return -ENODEV; data->reg_cache[i] = v; } /* set defaults */ px3215_set_mode(client, 0); msleep(20); px3215_set_plthres(client, PX_PROX_DEFAULT_THREL); px3215_set_phthres(client, PX_PROX_DEFAULT_THREH); px3215_set_configure(client, 0x79); px3215_set_ledwaiting(client, 0x07); px3215_set_mode(client, 2); msleep(20); return 0; }
static ssize_t px3215_store_phthres(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct input_dev *input = to_input_dev(dev); struct px3215_data *data = input_get_drvdata(input); unsigned long val; int ret; if (strict_strtoul(buf, 10, &val) < 0) return -EINVAL; ret = px3215_set_phthres(data->client, val); if (ret < 0) return ret; return count; }
static int proximity_manual_offset(struct px3215_data *data, u8 change_on) { struct file *cal_filp; int err; mm_segment_t old_fs; data->offset_value = change_on; /* update threshold */ px3215_set_calib(data->client, data->offset_value); px3215_set_plthres(data->client, data->offset_value); px3215_set_phthres(data->client, data->offset_value); /* calibration result */ data->cal_result = 1; old_fs = get_fs(); set_fs(KERNEL_DS); cal_filp = filp_open("/efs/prox_cal", O_CREAT | O_TRUNC | O_WRONLY, S_IRUGO | S_IWUSR | S_IWGRP); if (IS_ERR(cal_filp)) { pr_err("%s: Can't open calibration file\n", __func__); set_fs(old_fs); err = PTR_ERR(cal_filp); goto done; } err = cal_filp->f_op->write(cal_filp, (char *)&data->offset_value, sizeof(int), &cal_filp->f_pos); if (err != sizeof(int)) { pr_err("%s: Can't write the cal data to file\n", __func__); err = -EIO; } filp_close(cal_filp, current->files); done: set_fs(old_fs); return err; }
static ssize_t proximity_thresh_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct px3215_data *data = dev_get_drvdata(dev); long thresh_value = 0; int err = 0; err = strict_strtol(buf, 10, &thresh_value); if (unlikely(err < 0)) { pr_err("%s, kstrtoint failed.", __func__); goto done; } err = px3215_set_phthres(data->client, thresh_value); if (err < 0) { pr_err("%s: thresh_store failed\n", __func__); } done: return size; }
static ssize_t proximity_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct input_dev *input = to_input_dev(dev); struct px3215_data *data = input_get_drvdata(input); int enable = simple_strtoul(buf, NULL,10); int err = 0; if (enable) { err = proximity_open_calibration(data); if (err < 0 && err != -ENOENT) pr_err("%s: proximity_open_offset() failed\n", __func__); else { if (data->cal_result==1) { px3215_set_calib(data->client, data->offset_value); px3215_set_plthres(data->client, PX_PROX_CAL_THREL); px3215_set_phthres(data->client, PX_PROX_CAL_THREH); } } input_report_abs(data->input, ABS_DISTANCE, 1); input_sync(data->input); px3215_set_mode(data->client, 2); enable_irq(data->irq); enable_irq_wake(data->irq); } else { disable_irq_wake(data->irq); disable_irq(data->irq); px3215_set_mode(data->client, 0); } return size; }
static int proximity_do_calibrate(struct px3215_data *data, bool do_calib, bool thresh_set) { struct file *cal_filp; int err; int xtalk_avg = 0; mm_segment_t old_fs; if (do_calib) { if (thresh_set) { /* for proximity_thresh_store */ data->offset_value = data->threshold_high; } else { /* tap offset button */ /* get offset value */ xtalk_avg = proximity_adc_read(data); if (xtalk_avg < PX_PROX_DEFAULT_ADC) { /* do not need calibration */ data->cal_result = 0; err = 0; goto no_cal; } data->offset_value = xtalk_avg;// - PX_PROX_DEFAULT_ADC; } /* update offest */ px3215_set_calib(data->client, data->offset_value); px3215_set_plthres(data->client, PX_PROX_CAL_THREL); px3215_set_phthres(data->client, PX_PROX_CAL_THREH); /* calibration result */ data->cal_result = 1; } else { /* tap reset button */ data->offset_value = 0; /* update offest */ px3215_set_calib(data->client, data->offset_value); px3215_set_plthres(data->client, PX_PROX_DEFAULT_THREL); px3215_set_phthres(data->client, PX_PROX_DEFAULT_THREH); /* calibration result */ data->cal_result = 2; } old_fs = get_fs(); set_fs(KERNEL_DS); cal_filp = filp_open("/efs/prox_cal", O_CREAT | O_TRUNC | O_WRONLY, S_IRUGO | S_IWUSR | S_IWGRP); if (IS_ERR(cal_filp)) { pr_err("%s: Can't open calibration file\n", __func__); set_fs(old_fs); err = PTR_ERR(cal_filp); goto done; } err = cal_filp->f_op->write(cal_filp, (char *)&data->offset_value, sizeof(int), &cal_filp->f_pos); if (err != sizeof(int)) { pr_err("%s: Can't write the cal data to file\n", __func__); err = -EIO; } filp_close(cal_filp, current->files); done: set_fs(old_fs); no_cal: return err; }