예제 #1
0
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;
}
예제 #2
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;
}
예제 #3
0
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;
}
예제 #5
0
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;
}
예제 #6
0
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;
}