static ssize_t proximity_thresh_diff_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct gp2a_data *gp2a = dev_get_drvdata(dev); struct gp2a_platform_data *pdata = gp2a->pdata; u8 threshold_diff = 0; int err; err = kstrtou8(buf, 10, &threshold_diff); if (err) { pr_err("%s, conversion %s to number.\n", __func__, buf); return err; } if ((threshold_diff > 0) && (threshold_diff < 5)) { /* update diff */ gp2a->thresh_diff = threshold_diff; } else if (threshold_diff == 0) { /* reset to default */ pdata->gp2a_get_threshold(&gp2a->thresh_diff); } else { pr_err("%s: invalid value %d\n", __func__, *buf); return -EINVAL; } gp2a_update_threshold(gp2a, is_gp2a030a() ? gp2a_original_image_030a : gp2a_original_image, (is_gp2a030a() ? gp2a_original_image_030a[3][1] : gp2a_original_image[3][1]), true); return size; }
static int proximity_store_calibration(struct device *dev, bool do_calib) { struct gp2a_data *gp2a = dev_get_drvdata(dev); struct file *cancel_filp = NULL; mm_segment_t old_fs; int err = 0; if (do_calib) { gp2a->cal_data = proximity_adc_read(gp2a); if (is_gp2a030a()) gp2a_original_image_030a[3][1] += gp2a->cal_data; else gp2a_original_image[3][1] += gp2a->cal_data; } else { /* reset */ gp2a->cal_data = 0; if (is_gp2a030a()) gp2a_original_image_030a[3][1] = gp2a->default_threshold; else gp2a_original_image[3][1] = gp2a->default_threshold; } /* Update cal data. */ gp2a_update_threshold(gp2a, is_gp2a030a() ? gp2a_original_image_030a : gp2a_original_image, (is_gp2a030a() ? gp2a_original_image_030a[3][1] : gp2a_original_image[3][1]), true); pr_info("%s: prox_cal = %d, prox_thresh = 0x%x\n", __func__, gp2a->cal_data, (is_gp2a030a() ? gp2a_original_image_030a[3][1] : gp2a_original_image[3][1])); old_fs = get_fs(); set_fs(KERNEL_DS); cancel_filp = filp_open(CALIBRATION_FILE_PATH, O_CREAT | O_TRUNC | O_WRONLY | O_SYNC, 0666); if (IS_ERR(cancel_filp)) { pr_err("%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 *)&gp2a->cal_data, sizeof(u8), &cancel_filp->f_pos); if (err != sizeof(u8)) { 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); return err; }
static int proximity_open_calibration(struct gp2a_data *data) { struct file *cancel_filp = NULL; int err = 0; mm_segment_t old_fs; old_fs = get_fs(); set_fs(KERNEL_DS); cancel_filp = filp_open(CALIBRATION_FILE_PATH, O_RDONLY, 0666); if (IS_ERR(cancel_filp)) { err = PTR_ERR(cancel_filp); if (err != -ENOENT) pr_err("%s: Can't open cancelation file\n", __func__); set_fs(old_fs); return err; } err = cancel_filp->f_op->read(cancel_filp, (char *)&data->cal_data, sizeof(u8), &cancel_filp->f_pos); if (err != sizeof(u8)) { pr_err("%s: Can't read the cancel data from file\n", __func__); err = -EIO; } if (data->cal_data != 0) {/*If there is an offset cal data. */ #if defined(CONFIG_MACH_KONA_SENSOR) if (is_gp2a030a()) { gp2a_original_image_030a[5][1] = data->default_threshold + data->cal_data; gp2a_original_image_030a[3][1] = data->default_threshold + data->cal_data - DEFAULT_THRESHOLD_DIFF; } #else if (is_gp2a030a()) gp2a_original_image_030a[3][1] = data->default_threshold + data->cal_data; #endif else gp2a_original_image[3][1] = data->default_threshold + data->cal_data; pr_info("%s: prox_cal = %d, prox_thresh = 0x%x\n", __func__, data->cal_data, (is_gp2a030a() ? gp2a_original_image_030a[3][1] : gp2a_original_image[3][1])); } filp_close(cancel_filp, current->files); set_fs(old_fs); return err; }
static ssize_t proximity_name_show(struct device *dev, struct device_attribute *attr, char *buf) { return is_gp2a030a() ? sprintf(buf, "%s030\n", CHIP_ID) : sprintf(buf, "%s020\n", CHIP_ID); }
static ssize_t proximity_thresh_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { unsigned long threshold; int err = 0; err = strict_strtoul(buf, 10, &threshold); if (err) { pr_err("%s, conversion %s to number.\n", __func__, buf); return err; } err = gp2a_update_threshold(is_gp2a030a() ? gp2a_original_image_030a : gp2a_original_image, threshold, true); if (err) { pr_err("gp2a threshold(with register) update fail.\n"); return err; } return size; }
static ssize_t proximity_thresh_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct gp2a_data *data = dev_get_drvdata(dev); u8 threshold = 0; int err = 0; err = kstrtou8(buf, 10, &threshold); if (err) { pr_err("%s, conversion %s to number.\n", __func__, buf); return err; } err = gp2a_update_threshold(data, is_gp2a030a() ? gp2a_original_image_030a : gp2a_original_image, threshold, true); if (err) { pr_err("gp2a threshold(with register) update fail.\n"); return err; } return size; }
static void gp2a_work_func_light(struct work_struct *work) { struct sensor_data *data = container_of((struct delayed_work *)work, struct sensor_data, work); int i; int adc = 0; adc = lightsensor_get_adcvalue(); if (is_gp2a030a()) { for (i = 0; ARRAY_SIZE(adc_table_030a); i++) if (adc <= adc_table_030a[i]) break; } else { for (i = 0; ARRAY_SIZE(adc_table); i++) if (adc <= adc_table[i]) break; } if (data->light_buffer == i) { if (data->light_count++ == LIGHT_BUFFER_NUM) { input_report_rel(data->input_dev, REL_MISC, adc); input_sync(data->input_dev); data->light_count = 0; } } else { data->light_buffer = i; data->light_count = 0; } if (data->enabled) queue_delayed_work(data->wq, &data->work, msecs_to_jiffies(data->delay)); }
static ssize_t proximity_cal_show(struct device *dev, struct device_attribute *attr, char *buf) { struct gp2a_data *data = dev_get_drvdata(dev); return sprintf(buf, "%d,%d\n", data->cal_data, (is_gp2a030a() ? gp2a_original_image_030a[3][1] : gp2a_original_image[3][1])); }
static ssize_t proximity_cal_show(struct device *dev, struct device_attribute *attr, char *buf) { struct gp2a_data *data = dev_get_drvdata(dev); #if defined(CONFIG_MACH_KONA_SENSOR) return sprintf(buf, "%d,%d\n", data->cal_data, gp2a_original_image_030a[5][1]); #else return sprintf(buf, "%d,%d\n", data->cal_data, (is_gp2a030a() ? gp2a_original_image_030a[5][1] : gp2a_original_image[5][1])); #endif }
static ssize_t proximity_thresh_show(struct device *dev, struct device_attribute *attr, char *buf) { int i; int threshold = 0; u8 (*selected_image)[2] = (is_gp2a030a() ? gp2a_original_image_030a : gp2a_original_image); for (i = 0; i < COL; i++) { if (selected_image[i][0] == 0x08) /*PS mode LTH(Loff) */ threshold = selected_image[i][1]; else if (selected_image[i][0] == 0x09) /*PS mode LTH(Loff) */ threshold |= selected_image[i][1]<<8; } return sprintf(buf, "prox_threshold = %d\n", threshold); }
static int proximity_onoff(u8 onoff) { u8 value; int i; int err = 0; #ifdef DEBUG gprintk("proximity turn on/off = %d\n", onoff); #endif /* already on light sensor, so must simultaneously turn on light sensor and proximity sensor */ if (onoff) { for (i = 0; i < COL; i++) { if (is_gp2a030a()) err = opt_i2c_write(gp2a_original_image_030a[i][0] , &gp2a_original_image_030a[i][1]); else err = opt_i2c_write(gp2a_original_image[i][0], &gp2a_original_image[i][1]); if (err < 0) printk(KERN_ERR "%s : turnning on error i = %d, err=%d\n", __func__, i, err); lightsensor_mode = 0; } } else { /* light sensor turn on and proximity turn off */ if (lightsensor_mode) value = 0x67; /*resolution :16bit, range: *8(HIGH) */ else value = 0x63; /* resolution :16bit, range: *128(LOW) */ opt_i2c_write(COMMAND2, &value); /* OP3 : 1(operating mode) OP2 :1(coutinuous operating mode) OP1 : 01(ALS mode) */ value = 0xD0; opt_i2c_write(COMMAND1, &value); } return 0; }
static int gp2a_opt_probe(struct platform_device *pdev) { struct gp2a_data *gp2a; struct gp2a_platform_data *pdata = pdev->dev.platform_data; u8 value = 0; int err = 0; gprintk("probe start!\n"); if (!pdata) { pr_err("%s: missing pdata!\n", __func__); return err; } if (!pdata->gp2a_led_on) { pr_err("%s: incomplete pdata!\n", __func__); return err; } /* gp2a power on */ pdata->gp2a_led_on(true); if (pdata->gp2a_get_threshold) { gp2a_update_threshold(is_gp2a030a() ? gp2a_original_image_030a : gp2a_original_image, pdata->gp2a_get_threshold(), false); } /* allocate driver_data */ gp2a = kzalloc(sizeof(struct gp2a_data), GFP_KERNEL); if (!gp2a) { pr_err("kzalloc error\n"); return -ENOMEM; } proximity_enable = 0; proximity_sensor_detection = 0; proximity_avg_on = 0; gp2a->enabled = 0; gp2a->pdata = pdata; /* prox_timer settings. we poll for prox_avg values using a timer. */ hrtimer_init(&gp2a->prox_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); gp2a->prox_poll_delay = ns_to_ktime(2000 * NSEC_PER_MSEC); gp2a->prox_timer.function = gp2a_prox_timer_func; gp2a->prox_wq = create_singlethread_workqueue("gp2a_prox_wq"); if (!gp2a->prox_wq) { err = -ENOMEM; pr_err("%s: could not create prox workqueue\n", __func__); goto err_create_prox_workqueue; } INIT_WORK(&gp2a->work_prox, gp2a_work_func_prox_avg); INIT_WORK(&gp2a->work, gp2a_work_func_prox); err = proximity_input_init(gp2a); if (err < 0) goto error_setup_reg; err = sysfs_create_group(&gp2a->input_dev->dev.kobj, &proximity_attribute_group); if (err < 0) goto err_sysfs_create_group_proximity; /* set platdata */ platform_set_drvdata(pdev, gp2a); /* wake lock init */ wake_lock_init(&gp2a->prx_wake_lock, WAKE_LOCK_SUSPEND, "prx_wake_lock"); /* init i2c */ opt_i2c_init(); if (opt_i2c_client == NULL) { pr_err("opt_probe failed : i2c_client is NULL\n"); goto err_no_device; } else printk(KERN_INFO "opt_i2c_client : (0x%p), address = %x\n", opt_i2c_client, opt_i2c_client->addr); /* GP2A Regs INIT SETTINGS and Check I2C communication */ value = 0x00; /* shutdown mode op[3]=0 */ err = opt_i2c_write((u8) (COMMAND1), &value); if (err < 0) { pr_err("%s failed : threre is no such device.\n", __func__); goto err_no_device; } /* Setup irq */ err = gp2a_setup_irq(gp2a); if (err) { pr_err("%s: could not setup irq\n", __func__); goto err_setup_irq; } /* set sysfs for proximity sensor */ gp2a->proximity_dev = sensors_classdev_register("proximity_sensor"); if (IS_ERR(gp2a->proximity_dev)) { pr_err("%s: could not create proximity_dev\n", __func__); goto err_proximity_device_create; } if (device_create_file(gp2a->proximity_dev, &dev_attr_state) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_state.attr.name); goto err_proximity_device_create_file1; } if (device_create_file(gp2a->proximity_dev, &dev_attr_prox_avg) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_prox_avg.attr.name); goto err_proximity_device_create_file2; } if (device_create_file(gp2a->proximity_dev, &dev_attr_prox_thresh) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_prox_thresh.attr.name); goto err_proximity_device_create_file3; } if (device_create_file(gp2a->proximity_dev, &dev_attr_vendor) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_vendor.attr.name); goto err_proximity_device_create_file4; } if (device_create_file(gp2a->proximity_dev, &dev_attr_name) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_name.attr.name); goto err_proximity_device_create_file5; } if (device_create_file(gp2a->proximity_dev, &dev_attr_raw_data) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_raw_data.attr.name); goto err_proximity_device_create_file6; } #ifdef CONFIG_SLP device_init_wakeup(gp2a->proximity_dev, true); #endif dev_set_drvdata(gp2a->proximity_dev, gp2a); device_init_wakeup(&pdev->dev, 1); gprintk("probe success!\n"); return 0; err_proximity_device_create_file6: device_remove_file(gp2a->proximity_dev, &dev_attr_raw_data); err_proximity_device_create_file5: device_remove_file(gp2a->proximity_dev, &dev_attr_name); err_proximity_device_create_file4: device_remove_file(gp2a->proximity_dev, &dev_attr_vendor); err_proximity_device_create_file3: device_remove_file(gp2a->proximity_dev, &dev_attr_prox_avg); err_proximity_device_create_file2: device_remove_file(gp2a->proximity_dev, &dev_attr_state); err_proximity_device_create_file1: sensors_classdev_unregister(gp2a->proximity_dev); err_proximity_device_create: gpio_free(pdata->p_out); err_setup_irq: err_no_device: sysfs_remove_group(&gp2a->input_dev->dev.kobj, &proximity_attribute_group); wake_lock_destroy(&gp2a->prx_wake_lock); err_sysfs_create_group_proximity: input_unregister_device(gp2a->input_dev); error_setup_reg: destroy_workqueue(gp2a->prox_wq); err_create_prox_workqueue: kfree(gp2a); return err; }
int lightsensor_get_adc(struct sensor_data *data) { unsigned char get_data[4] = { 0, }; int D0_raw_data; int D1_raw_data; int D0_data; int D1_data; int lx = 0; u8 value; int light_alpha; int light_beta; static int lx_prev; int ret = 0; #if defined(CONFIG_MACH_BAFFIN_KOR_SKT) || \ defined(CONFIG_MACH_BAFFIN_KOR_KT) || \ defined(CONFIG_MACH_BAFFIN_KOR_LGT) int d0_boundary = 91; #elif defined(CONFIG_MACH_KONA) int d0_boundary = 93; #else int d0_boundary = 93; #endif mutex_lock(&data->light_mutex); ret = opt_i2c_read(DATA0_LSB, get_data, sizeof(get_data)); mutex_unlock(&data->light_mutex); if (ret < 0) return lx_prev; D0_raw_data = (get_data[1] << 8) | get_data[0]; /* clear */ D1_raw_data = (get_data[3] << 8) | get_data[2]; /* IR */ if (is_gp2a030a()) { #if defined(CONFIG_MACH_GRANDE) if (100 * D1_raw_data <= 41 * D0_raw_data) { light_alpha = 1186; light_beta = 0; } else if (100 * D1_raw_data <= 62 * D0_raw_data) { light_alpha = 2930; light_beta = 4252; } else if (100 * D1_raw_data <= d0_boundary * D0_raw_data) { light_alpha = 924; light_beta = 1015; } else { light_alpha = 0; light_beta = 0; } #elif defined(CONFIG_MACH_BAFFIN_KOR_SKT) || \ defined(CONFIG_MACH_BAFFIN_KOR_KT) || \ defined(CONFIG_MACH_BAFFIN_KOR_LGT) if (100 * D1_raw_data <= 41 * D0_raw_data) { light_alpha = 868; light_beta = 0; } else if (100 * D1_raw_data <= 62 * D0_raw_data) { light_alpha = 2308; light_beta = 3509; } else if (100 * D1_raw_data <= d0_boundary * D0_raw_data) { light_alpha = 404; light_beta = 440; } else { light_alpha = 0; light_beta = 0; } #elif defined(CONFIG_MACH_KONA) if (100 * D1_raw_data <= 40 * D0_raw_data) { light_alpha = 834; light_beta = 0; } else if (100 * D1_raw_data <= 62 * D0_raw_data) { light_alpha = 2050; light_beta = 3036; } else if (100 * D1_raw_data <= d0_boundary * D0_raw_data) { if (D0_raw_data < 3000 && lightsensor_mode == 0) { /* Incandescent Low lux */ light_alpha = 242; light_beta = 257; } else { /* Incandescent High lux */ light_alpha = 497; light_beta = 534; } } else { light_alpha = 0; light_beta = 0; } #else if (100 * D1_raw_data <= 41 * D0_raw_data) { light_alpha = 736; light_beta = 0; } else if (100 * D1_raw_data <= 62 * D0_raw_data) { light_alpha = 1855; light_beta = 2693; } else if (100 * D1_raw_data <= d0_boundary * D0_raw_data) { light_alpha = 544; light_beta = 595; } else { light_alpha = 0; light_beta = 0; } #endif } else { if (lightsensor_mode) { /* HIGH_MODE */ if (100 * D1_raw_data <= 32 * D0_raw_data) { light_alpha = 800; light_beta = 0; } else if (100 * D1_raw_data <= 67 * D0_raw_data) { light_alpha = 2015; light_beta = 2925; } else if (100 * D1_raw_data <= d0_boundary * D0_raw_data) { light_alpha = 56; light_beta = 12; } else { light_alpha = 0; light_beta = 0; } } else { /* LOW_MODE */ if (100 * D1_raw_data <= 32 * D0_raw_data) { light_alpha = 800; light_beta = 0; } else if (100 * D1_raw_data <= 67 * D0_raw_data) { light_alpha = 2015; light_beta = 2925; } else if (100 * D1_raw_data <= d0_boundary * D0_raw_data) { light_alpha = 547; light_beta = 599; } else { light_alpha = 0; light_beta = 0; } } } if (lightsensor_mode) { /* HIGH_MODE */ D0_data = D0_raw_data * 16; D1_data = D1_raw_data * 16; } else { /* LOW_MODE */ D0_data = D0_raw_data; D1_data = D1_raw_data; } if (is_gp2a030a()) { if (D0_data < 3) { lx = 0; #ifdef DEBUG gprintk("lx is 0 : D0=%d, D1=%d\n", D0_raw_data, D1_raw_data); #endif } else if (lightsensor_mode == 0 && (D0_raw_data >= 16000 || D1_raw_data >= 16000) && (D0_raw_data <= 16383 && D1_raw_data <= 16383)) { #ifdef DEBUG gprintk("need to changed HIGH_MODE D0=%d, D1=%d\n", D0_raw_data, D1_raw_data); #endif lx = lx_prev; } else if (100 * D1_data > d0_boundary * D0_data) { lx = lx_prev; #ifdef DEBUG gprintk ("Data range over so ues prev_lx value=%d D0=%d, D1=%d mode=%d\n", lx, D0_data, D1_data, lightsensor_mode); #endif return lx; } else { lx = (int)((light_alpha / 10 * D0_data * 33) - (light_beta / 10 * D1_data * 33)) / 1000; #ifdef DEBUG gprintk ("D0=%d, D1=%d, lx=%d mode=%d a=%d, b=%d prev_lx=%d\n", D0_raw_data, D1_raw_data, lx, lightsensor_mode, light_alpha, light_beta, lx_prev); #endif } } else { if ((D0_data == 0 || D1_data == 0) && (D0_data < 300 && D1_data < 300)) { lx = 0; #ifdef DEBUG gprintk("lx is 0 : D0=%d, D1=%d\n", D0_raw_data, D1_raw_data); #endif } else if ((lightsensor_mode == 0) && (D0_raw_data >= 16000 || D1_raw_data >= 16000) && (D0_raw_data <= 16383 && D1_raw_data <= 16383)) { #ifdef DEBUG gprintk("need to changed HIGH_MODE D0=%d, D1=%d\n", D0_raw_data, D1_raw_data); #endif lx = lx_prev; } else if ((100 * D1_data > d0_boundary * D0_data) || (100 * D1_data < 15 * D0_data)) { lx = lx_prev; #ifdef DEBUG gprintk ("Data range over so ues prev_lx value=%d D0=%d, D1=%d mode=%d\n", lx, D0_data, D1_data, lightsensor_mode); #endif return lx; } else { lx = (int)((light_alpha / 10 * D0_data * 33) - (light_beta / 10 * D1_data * 33)) / 1000; #ifdef DEBUG gprintk ("D0=%d, D1=%d, lx=%d mode=%d a=%d, b=%d prev_lx=%d\n", D0_raw_data, D1_raw_data, lx, lightsensor_mode, light_alpha, light_beta, lx_prev); #endif } } lx_prev = lx; if (lightsensor_mode) { /* HIGH MODE */ if (D0_raw_data < 1000) { #ifdef DEBUG gprintk("change to LOW_MODE detection=%d\n", proximity_sensor_detection); #endif lightsensor_mode = 0; /* change to LOW MODE */ value = 0x0C; opt_i2c_write(COMMAND1, &value); if (proximity_sensor_detection) value = 0x23; else value = 0x63; opt_i2c_write(COMMAND2, &value); if (proximity_enable) value = 0xCC; else value = 0xDC; opt_i2c_write(COMMAND1, &value); } } else { /* LOW MODE */ if (D0_raw_data > 16000 || D1_raw_data > 16000) { #ifdef DEBUG gprintk("change to HIGH_MODE detection=%d\n", proximity_sensor_detection); #endif lightsensor_mode = 1; /* change to HIGH MODE */ value = 0x0C; opt_i2c_write(COMMAND1, &value); if (proximity_sensor_detection) value = 0x27; else value = 0x67; opt_i2c_write(COMMAND2, &value); if (proximity_enable) value = 0xCC; else value = 0xDC; opt_i2c_write(COMMAND1, &value); } } return lx; }
static void gp2a_work_func_light(struct work_struct *work) { struct sensor_data *data = container_of((struct delayed_work *)work, struct sensor_data, work); int i; int adc = 0; #ifdef CONFIG_MACH_BAFFIN int count = 0; #endif #ifdef CONFIG_MACH_BAFFIN while (adc == 0 && count < 5) { adc = lightsensor_get_adcvalue(data); count++; } #else adc = lightsensor_get_adcvalue(data); #endif if (is_gp2a030a()) { for (i = 0; ARRAY_SIZE(adc_table_030a); i++) if (adc <= adc_table_030a[i]) break; } else { for (i = 0; ARRAY_SIZE(adc_table); i++) if (adc <= adc_table[i]) break; } if (data->light_buffer == i) { if (data->light_count++ == LIGHT_BUFFER_NUM) { input_report_rel(data->input_dev, REL_MISC, (adc ? adc : 1)); input_sync(data->input_dev); data->light_count = 0; } } else { data->light_buffer = i; data->light_count = 0; } #if defined(CONFIG_MACH_M3_USA_TMO) if (adc == 0) { if (data->zero_cnt++ > 25) { data->zero_cnt = 0; if (data->reset_cnt++ <= LIMIT_RESET_COUNT) { lightsensor_onoff(0); lightsensor_onoff(1); pr_info("%s : lightsensor reset done.\n", __func__); } else { data->reset_cnt = LIMIT_RESET_COUNT + 1; } } } else { data->reset_cnt = 0; data->zero_cnt = 0; } #endif if (data->enabled) queue_delayed_work(data->wq, &data->work, msecs_to_jiffies(data->delay)); }