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); }
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; }