static void cm36686_work_func_light(struct work_struct *work)
{
	struct cm36686_data *cm36686 = container_of(work, struct cm36686_data,
						work_light);
	mutex_lock(&cm36686->read_lock);
	cm36686_i2c_read_word(cm36686, REG_ALS_DATA, &cm36686->als_data);
	cm36686_i2c_read_word(cm36686, REG_WHITE_DATA, &cm36686->white_data);
	mutex_unlock(&cm36686->read_lock);

	input_report_rel(cm36686->light_input_dev, REL_DIAL, cm36686->als_data + 1);
	input_report_rel(cm36686->light_input_dev, REL_WHEEL, cm36686->white_data + 1);
	input_sync(cm36686->light_input_dev);

	if (cm36686->count_log_time >= LIGHT_LOG_TIME) {
		pr_info("%s, %u,%u\n", __func__,
			cm36686->als_data, cm36686->white_data);
		cm36686->count_log_time = 0;
	} else
		cm36686->count_log_time++;

#ifdef cm36686_DEBUG
	pr_info("%s, %u,%u\n", __func__,
		cm36686->als_data, cm36686->white_data);
#endif
}
/* interrupt happened due to transition/change of near/far proximity state */
irqreturn_t cm36686_irq_thread_fn(int irq, void *data)
{
	struct cm36686_data *cm36686 = data;
	u8 val = 1;
	u16 ps_data = 0;
#ifdef cm36686_DEBUG
	static int count;
	pr_info("%s\n", __func__);
#endif

	val = gpio_get_value(cm36686->pdata->irq);
	cm36686_i2c_read_word(cm36686, REG_PS_DATA, &ps_data);
#ifdef cm36686_DEBUG
	pr_info("[SENSOR] %s: count = %d\n", __func__, count++);
#endif

	if (cm36686->power_state & PROXIMITY_ENABLED) {
		/* 0 is close, 1 is far */
		input_report_abs(cm36686->proximity_input_dev, ABS_DISTANCE, val);
		input_sync(cm36686->proximity_input_dev);
	}

	wake_lock_timeout(&cm36686->prx_wake_lock, 3 * HZ);

	pr_info("%s: val = %u, ps_data = %u (close:0, far:1)\n",
		__func__, val, ps_data);

	return IRQ_HANDLED;
}
static ssize_t proximity_state_show(struct device *dev,
	struct device_attribute *attr, char *buf)
{
	struct cm36686_data *cm36686 = dev_get_drvdata(dev);
	u16 ps_data;

	mutex_lock(&cm36686->power_lock);
	if (!(cm36686->power_state & PROXIMITY_ENABLED)) {
#if defined(CONFIG_SENSORS_CM36686_LEDA_EN_GPIO)
		cm36686_leden_gpio_onoff(cm36686, 1);
#else
	prox_led_onoff(cm36686, 1);
#endif
		cm36686_i2c_write_word(cm36686, REG_PS_CONF1,
			ps_reg_init_setting[PS_CONF1][CMD]);
	}

	mutex_lock(&cm36686->read_lock);
	cm36686_i2c_read_word(cm36686, REG_PS_DATA,
		&ps_data);
	mutex_unlock(&cm36686->read_lock);

	if (!(cm36686->power_state & PROXIMITY_ENABLED)) {
		cm36686_i2c_write_word(cm36686, REG_PS_CONF1,
				0x0001);
#if defined(CONFIG_SENSORS_CM36686_LEDA_EN_GPIO)
		cm36686_leden_gpio_onoff(cm36686, 0);
#else
	prox_led_onoff(cm36686, 0);
#endif
	}
	mutex_unlock(&cm36686->power_lock);

	return sprintf(buf, "%u\n", ps_data);
}
static void proxsensor_get_avg_val(struct cm36686_data *cm36686)
{
	int min = 0, max = 0, avg = 0;
	int i;
	u16 ps_data = 0;

	for (i = 0; i < PROX_READ_NUM; i++) {
		msleep(40);
		cm36686_i2c_read_word(cm36686, REG_PS_DATA,
			&ps_data);
		avg += ps_data;

		if (!i)
			min = ps_data;
		else if (ps_data < min)
			min = ps_data;

		if (ps_data > max)
			max = ps_data;
	}
	avg /= PROX_READ_NUM;

	cm36686->avg[0] = min;
	cm36686->avg[1] = avg;
	cm36686->avg[2] = max;
}
static ssize_t proximity_state_show(struct device *dev,
	struct device_attribute *attr, char *buf)
{
	struct cm36686_data *cm36686 = dev_get_drvdata(dev);
	u16 ps_data;

	mutex_lock(&cm36686->power_lock);
	if (!(cm36686->power_state & PROXIMITY_ENABLED)) {
		if (cm36686->pdata->cm36686_led_on) {
			cm36686->pdata->cm36686_led_on(true);
			msleep(20);
		}
		cm36686_i2c_write_word(cm36686, REG_PS_CONF1,
			ps_reg_init_setting[PS_CONF1][CMD]);
	}

	mutex_lock(&cm36686->read_lock);
	cm36686_i2c_read_word(cm36686, REG_PS_DATA,
		&ps_data);
	mutex_unlock(&cm36686->read_lock);

	if (!(cm36686->power_state & PROXIMITY_ENABLED)) {
		cm36686_i2c_write_word(cm36686, REG_PS_CONF1,
				0x0001);
		if (cm36686->pdata->cm36686_led_on)
			cm36686->pdata->cm36686_led_on(false);
	}
	mutex_unlock(&cm36686->power_lock);

	return sprintf(buf, "%u\n", ps_data);
}
示例#6
0
static int cm36686_setup_reg(struct cm36686_data *cm36686)
{
	int err = 0, i = 0;
	u16 tmp = 0;

	/* ALS initialization */
	err = cm36686_i2c_write_word(cm36686,
			als_reg_setting[0][0],
			als_reg_setting[0][1]);
	if (err < 0) {
		pr_err("%s: cm36686_als_reg is failed. %d\n", __func__,
			err);
		return err;
	}
	/* PS initialization */

	if (cm36686->pdata != NULL) {
		ps_reg_init_setting[PS_THD_LOW][CMD] =
			cm36686->pdata->default_low_thd;
		ps_reg_init_setting[PS_THD_HIGH][CMD] =
			cm36686->pdata->default_hi_thd;
		pr_info("%s - THD_LOW = %u, THD_HIGH = %u\n", __func__,
			ps_reg_init_setting[PS_THD_LOW][CMD],
			ps_reg_init_setting[PS_THD_HIGH][CMD]);
	}
	for (i = 0; i < PS_REG_NUM; i++) {
		err = cm36686_i2c_write_word(cm36686,
			ps_reg_init_setting[i][REG_ADDR],
			ps_reg_init_setting[i][CMD]);
		if (err < 0) {
			pr_err("%s: cm36686_ps_reg is failed. %d\n", __func__,
				err);
			return err;
		}
	}

	/* printing the inital proximity value with no contact */
	msleep(50);
	mutex_lock(&cm36686->read_lock);
	err = cm36686_i2c_read_word(cm36686, REG_PS_DATA, &tmp);
	mutex_unlock(&cm36686->read_lock);
	if (err < 0) {
		pr_err("%s: read ps_data failed\n", __func__);
		err = -EIO;
	}
	pr_err("%s: initial proximity value = %d\n",
		__func__, tmp);

	/* turn off */
	cm36686_i2c_write_word(cm36686, REG_CS_CONF1, 0x0001);
	cm36686_i2c_write_word(cm36686, REG_PS_CONF1, 0x0001);
	cm36686_i2c_write_word(cm36686, REG_PS_CONF3, 0x0000);

	pr_info("%s is success.", __func__);
	return err;
}
static int proximity_store_cancelation(struct device *dev, bool do_calib)
{
	struct cm36686_data *cm36686 = dev_get_drvdata(dev);
	struct file *cancel_filp = NULL;
	mm_segment_t old_fs;
	int err = 0;
	u16 ps_data = 0;

	if (do_calib) {
		mutex_lock(&cm36686->read_lock);
		cm36686_i2c_read_word(cm36686,
			REG_PS_DATA, &ps_data);
		ps_reg_init_setting[PS_CANCEL][CMD] = ps_data;
		mutex_unlock(&cm36686->read_lock);

		err = get_proximity_threshold(cm36686);
		if(err != ERROR) {
			if (cm36686->pdata->cancel_hi_thd) {
				ps_reg_init_setting[PS_THD_HIGH][CMD] =
					cm36686->pdata->cancel_hi_thd;
			} else
				ps_reg_init_setting[PS_THD_HIGH][CMD] = CANCEL_HI_THD;

			if (cm36686->pdata->cancel_low_thd) {
				ps_reg_init_setting[PS_THD_LOW][CMD] =
					cm36686->pdata->cancel_low_thd;
			} else
				ps_reg_init_setting[PS_THD_LOW][CMD] = DEFUALT_LOW_THD;
		} else {
			set_default_proximity_threshold(cm36686);
		}
	} else { /* reset */
		ps_reg_init_setting[PS_CANCEL][CMD] = 0;
		set_default_proximity_threshold(cm36686);
	}

	err = cm36686_i2c_write_word(cm36686, REG_PS_CANC,
		ps_reg_init_setting[PS_CANCEL][CMD]);
	if (err < 0)
		pr_err("%s: cm36686_ps_canc_reg is failed. %d\n", __func__,
			err);
	err = cm36686_i2c_write_word(cm36686, REG_PS_THD_HIGH,
		ps_reg_init_setting[PS_THD_HIGH][CMD]);
	if (err < 0)
		pr_err("%s: cm36686_ps_high_reg is failed. %d\n", __func__,
			err);
	err = cm36686_i2c_write_word(cm36686, REG_PS_THD_LOW,
		ps_reg_init_setting[PS_THD_LOW][CMD]);
	if (err < 0)
		pr_err("%s: cm36686_ps_low_reg is failed. %d\n", __func__,
			err);

	pr_info("%s: prox_cal = 0x%x, ps_high_thresh = 0x%x, ps_low_thresh = 0x%x\n",
		__func__, ps_reg_init_setting[PS_CANCEL][CMD],
		ps_reg_init_setting[PS_THD_HIGH][CMD], ps_reg_init_setting[PS_THD_LOW][CMD]);

	old_fs = get_fs();
	set_fs(KERNEL_DS);

	cancel_filp = filp_open(CANCELATION_FILE_PATH,
			O_CREAT | O_TRUNC | O_WRONLY | O_SYNC, 0666);
	if (IS_ERR(cancel_filp)) {
		pr_err("[SENSOR] %s: Can't open cancelation file\n", __func__);
		set_fs(old_fs);
		err = PTR_ERR(cancel_filp);
		return err;
	}

	err = cancel_filp->f_op->write(cancel_filp,
		(char *)&ps_reg_init_setting[PS_CANCEL][CMD],
		sizeof(u16), &cancel_filp->f_pos);
	if (err != sizeof(u16)) {
		pr_err("%s: Can't write the cancel data to file\n", __func__);
		err = -EIO;
	}

	filp_close(cancel_filp, current->files);
	set_fs(old_fs);

	if (!do_calib) /* delay for clearing */
		msleep(150);

	return err;
}