/* * Setting GP2AP002S00F proximity sensor operation mode, * enable=1-->Normal Operation Mode * enable=0-->Shutdown Mode */ static int gp2a_prox_mode(int enable) { u8 reg_value; int ret=0; debug("%s called",__func__); if(1==enable) { reg_value = 0x01; if((ret=gp2a_i2c_write(GP2A_REG_OPMOD,®_value))<0) error("gp2a_i2c_write 1 failed"); reg_value = 0x00; if((ret=gp2a_i2c_write(GP2A_REG_CON,®_value))<0) error("gp2a_i2c_write 2 failed"); proximity_enable=1; } else { reg_value = 0x00; if((ret=gp2a_i2c_write(GP2A_REG_OPMOD,®_value))<0) error("gp2a_i2c_write 3 failed"); reg_value = 0x18; if((ret=gp2a_i2c_write(GP2A_REG_CON,®_value))<0) error("gp2a_i2c_write 4 failed"); proximity_enable=0; } return ret; }
static int gp2a_proximity_poweroff(void) { u8 val = 0; int ret = 0; #if defined(CONFIG_GP2A_MODE_B) disable_irq_nosync(gp2a->irq); #else disable_irq(gp2a->irq); #endif #if defined(CONFIG_GP2A_MODE_B) // SSD : Software shutdown function ( 0:shutdown mode, 1:opteration mode ) val = 0x02; // VCON enable, SSD disable ret = gp2a_i2c_write(gp2a->client, GP2A_REG_OPMOD, val); // printk(" %s, %d\n", __func__, __LINE__); #else val = 0x00; ret = gp2a_i2c_write(gp2a->client, GP2A_REG_OPMOD, val); // printk(" %s, %d\n", __func__, __LINE__); #endif proximity_enable = 0; // printk("OXOXOXOXOX %s, %d\n", __func__, __LINE__); return ret; }
static int lightsensor_onoff(u8 onoff, struct gp2a_data *data) { u8 value; pr_debug("%s : light_sensor onoff = %d\n", __func__, onoff); if (onoff) { /*in calling, must turn on proximity sensor */ if (data->proximity_enabled == 0) { value = 0x01; gp2a_i2c_write(data, COMMAND4, &value); value = 0x63; gp2a_i2c_write(data, COMMAND2, &value); /*OP3 : 1(operating mode) OP2 :1 (coutinuous operating mode) OP1 : 01(ALS mode) TYPE=0(auto) */ value = 0xD0; gp2a_i2c_write(data, COMMAND1, &value); /* other setting have defualt value. */ } } else { /*in calling, must turn on proximity sensor */ if (data->proximity_enabled == 0) { value = 0x00; /*shutdown mode */ gp2a_i2c_write(data, (u8) (COMMAND1), &value); } } return 0; }
static int proximity_onoff(u8 onoff, struct gp2a_data *data) { u8 value; int i; int err = 0; pr_info("%s : proximity turn on/off = %d\n", __func__, onoff); /* already on light sensor, so must simultaneously turn on light sensor and proximity sensor */ if (onoff) { for (i = 0; i < COL; i++) { err = gp2a_i2c_write(data, gp2a_reg[i][0], &gp2a_reg[i][1]); if (err < 0) pr_err("%s : turnning on error i = %d, err=%d\n", __func__, i, err); data->lightsensor_mode = 0; } } else { /* light sensor turn on and proximity turn off */ if (data->lightsensor_mode) value = 0x67; /*resolution :16bit, range: *8(HIGH) */ else value = 0x63; /* resolution :16bit, range: *128(LOW) */ gp2a_i2c_write(data, COMMAND2, &value); /* OP3 : 1(operating mode) OP2 :1(coutinuous operating mode) OP1 : 01(ALS mode) */ value = 0xD0; gp2a_i2c_write(data, COMMAND1, &value); } return 0; }
static void gp2a_prox_work_func(struct work_struct *work) { struct gp2a_data *gp2a = container_of(work, struct gp2a_data, work_prox); u8 vo, value; gp2a_i2c_read(gp2a, REGS_PROX, &vo); vo = 0x01 & vo; value = 0x18; gp2a_i2c_write(gp2a, REGS_CON, value); if (!vo) { gp2a->val_state = 0x01; value = gp2a->nondetect; } else { gp2a->val_state = 0x00; value = gp2a->detect; } gp2a_i2c_write(gp2a, REGS_HYS, value); pr_info("%s,%d\n", __func__, gp2a->val_state); input_report_abs(gp2a->input, ABS_DISTANCE, gp2a->val_state); input_sync(gp2a->input); msleep(20); value = 0x00; gp2a_i2c_write(gp2a, REGS_CON, value); }
static int lightsensor_reset(struct gp2a_data *data) { u8 value; int i; pr_info("%s\n", __func__); if (data->light_enabled) { mutex_lock(&data->light_mutex); value = 0x01; gp2a_i2c_write(data, COMMAND4, &value); if (data->lightsensor_mode) value = 0x67; /*resolution :16bit, range: *8(HIGH) */ else value = 0x63; /* resolution :16bit, range: *128(LOW) */ gp2a_i2c_write(data, COMMAND2, &value); value = 0xD0; gp2a_i2c_write(data, COMMAND1, &value); for (i = 0; i < COL; i++) { gp2a_i2c_write(data, gp2a_reg[i][0], &gp2a_reg[i][1]); } mutex_unlock(&data->light_mutex); } return 0; }
static ssize_t proximity_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct gp2a_data *data = dev_get_drvdata(dev); int value = 0; int err = 0; int16_t thrd; u8 reg; err = kstrtoint(buf, 10, &value); if (err) { pr_err("%s, kstrtoint failed.", __func__); goto done; } if (value != 0 && value != 1) goto done; printk(KERN_INFO "[GP2A] proximity_enable_store : value=%d, offset=%d\n", value, data->offset_value); if (data->proximity_enabled && !value) { /* Prox power off */ data->proximity_enabled = value; disable_irq(data->irq); proximity_onoff(0, data); if (data->pdata->led_on) data->pdata->led_on(0); } if (!data->proximity_enabled && value) { /* prox power on */ data->proximity_enabled = value; if (data->pdata->led_on) data->pdata->led_on(1); msleep(5); proximity_onoff(1, data); thrd = gp2a_reg[3][1]+(data->offset_value); THR_REG_LSB(thrd, reg); gp2a_i2c_write(gp2a_reg[3][0], ®); THR_REG_MSB(thrd, reg); gp2a_i2c_write(gp2a_reg[4][0], ®); thrd = gp2a_reg[5][1]+(data->offset_value); THR_REG_LSB(thrd, reg); gp2a_i2c_write(gp2a_reg[5][0], ®); THR_REG_MSB(thrd, reg); gp2a_i2c_write(gp2a_reg[6][0], ®); input_report_abs(data->proximity_input_dev, ABS_DISTANCE, 1); input_sync(data->proximity_input_dev); enable_irq(data->irq); } done: return count; }
static void gp2a_work_func_prox(struct work_struct *work) { struct gp2a_data *data = container_of((struct work_struct *)work, struct gp2a_data, proximity_work); unsigned char value; int ret; ret = gp2a_i2c_read(data, COMMAND1, &value, sizeof(value)); if (ret < 0) { pr_info("%s, read data error\n", __func__); } else { pr_info("%s, read data %d, %d\n", __func__, value & 0x08, !(value & 0x08)); data->proximity_detection = !(value & 0x08); } if (!(value & 0x08)) { if (data->lightsensor_mode == 0) value = 0x63; else value = 0x67; gp2a_i2c_write(data, COMMAND2, &value); } else { if (data->lightsensor_mode == 0) value = 0x23; else value = 0x27; gp2a_i2c_write(data, COMMAND2, &value); } value = 0xCC; gp2a_i2c_write(data, COMMAND1, &value); ret = gp2a_i2c_read(data, COMMAND1, &value, sizeof(value)); if (ret < 0) pr_info("%s, read data error\n", __func__); pr_info("%s, detection=%d, mode=%d, rev=%d\n", __func__, data->proximity_detection, data->lightsensor_mode, system_rev); if (system_rev < 12) { input_report_abs(data->prox_input_dev, ABS_DISTANCE, data->proximity_detection); } else { if (!gpio_get_value(data->con_gpio)) { input_report_abs(data->prox_input_dev, ABS_DISTANCE, data->proximity_detection); } else { if (!data->proximity_detection) { pr_err("%s, Conducntion is Connect\n", __func__); input_report_abs(data->prox_input_dev, ABS_DISTANCE, 1); } else { input_report_abs(data->prox_input_dev, ABS_DISTANCE, data->proximity_detection); } } } input_sync(data->prox_input_dev); }
static void gp2a_prox_work_func(struct work_struct *work) { struct gp2a_data *gp2a = container_of(work, struct gp2a_data, work_prox); u8 vo, value; if (gp2a->irq != 0) { #if defined(CONFIG_MACH_GEIM) disable_irq_wake(gp2a->irq); #else disable_irq_wake(gp2a->irq); #endif disable_irq(gp2a->irq); } else { return ; } gp2a_i2c_read(gp2a, REGS_PROX, &vo); vo = 0x01 & vo; if (vo == gp2a->val_state) { if (!vo) { vo = 0x01; value = nondetect; } else { vo = 0x00; value = detect; } #ifdef ALPS_DEBUG pr_info("%s: %d\n", __func__, gp2a->val_state); #endif gp2a_i2c_write(gp2a, REGS_HYS, &value); gp2a->val_state = vo; } input_report_abs(gp2a->proximity_input_dev, ABS_DISTANCE, gp2a->val_state); input_sync(gp2a->proximity_input_dev); msleep(20); value = 0x18; gp2a_i2c_write(gp2a, REGS_CON, &value); if (gp2a->irq != 0) { enable_irq(gp2a->irq); #if defined(CONFIG_MACH_GEIM) enable_irq_wake(gp2a->irq); #else enable_irq_wake(gp2a->irq); #endif } value = 0x00; gp2a_i2c_write(gp2a, REGS_CON, &value); }
static int gp2a_proximity_poweron(void) { u8 val; int ret = 0; printk(KERN_INFO "[PROXIMITY][%s] start!\n", __func__); #if !defined(CONFIG_GP2A_MODE_B) int i; #endif #if defined(CONFIG_GP2A_MODE_B) // ASD : Select switch for analog sleep function ( 0:ineffective, 1:effective ) // OCON[1:0] : Select switches for enabling/disabling VOUT terminal // ( 00:enable, 11:force to go High, 10:forcr to go Low ) val = 0x18; // 11:force to go High ret = gp2a_i2c_write(gp2a->client, GP2A_REG_CON, val); // printk(" %s, %d\n", __func__, __LINE__); val = 0x40; // HYSD enable ret = gp2a_i2c_write(gp2a->client, GP2A_REG_HYS, val); // printk(" %s, %d\n", __func__, __LINE__); val = 0x03; // VCON enable, SSD enable ret = gp2a_i2c_write(gp2a->client, GP2A_REG_OPMOD, val); // printk(" %s, %d\n", __func__, __LINE__); #else for(i=1;i<5;i++) { //opt_i2c_write((u8)(i),&gp2a_original_image[i]); gp2a_i2c_write(gp2a->client,i, gp2a_original_image[i]); } #endif proximity_enable = 1; enable_irq(gp2a->irq); #if defined(CONFIG_GP2A_MODE_B) val = 0x00; // 00:enable ret = gp2a_i2c_write(gp2a->client, GP2A_REG_CON, val); #endif input_report_abs(gp2a->prox_input, ABS_DISTANCE, 1); input_sync(gp2a->prox_input); printk(KERN_INFO "[PROXIMITY][%s] end!\n", __func__); return ret; }
static int gp2a_prox_manual_offset(struct gp2a_data *data, u8 change_on) { struct file *cal_filp; int err; int16_t thrd; u8 reg; mm_segment_t old_fs; data->offset_value = change_on; /* update threshold */ thrd = gp2a_reg[3][1]+(data->offset_value); THR_REG_LSB(thrd, reg); gp2a_i2c_write(data, gp2a_reg[3][0], ®); THR_REG_MSB(thrd, reg); gp2a_i2c_write(data, gp2a_reg[4][0], ®); thrd = gp2a_reg[5][1]+(data->offset_value); THR_REG_LSB(thrd, reg); gp2a_i2c_write(data, gp2a_reg[5][0], ®); THR_REG_MSB(thrd, reg); gp2a_i2c_write(data, gp2a_reg[6][0], ®); /* calibration result */ data->cal_result = 1; old_fs = get_fs(); set_fs(KERNEL_DS); cal_filp = filp_open(CAL_PATH, 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 void gp2a_prox_work_func(struct work_struct *work) { unsigned char value; unsigned char int_val = GP2A_REG_PROX; unsigned char vout = 0; int ret=0; /* Read VO & INT Clear */ debug("[PROXIMITY] %s : \n",__func__); if((ret=gp2a_i2c_read((u8)(int_val), &value))<0) { error("gp2a_i2c_read failed\n"); gp2a_prox_reset(); if(proximity_enable == 1) gp2a_prox_mode(1); else gp2a_prox_mode(0); return; } vout = value & 0x01; printk(KERN_INFO "[GP2A] vout = %d \n",vout); /* Report proximity information */ proximity_value = vout; input_report_abs(gp2a_data->prox_input_dev, ABS_DISTANCE,((vout == 1)? 0:1)); input_sync(gp2a_data->prox_input_dev); mdelay(1); /* Write HYS Register */ gp2a_prox_offset(vout); /* Forcing vout terminal to go high */ value = 0x18; gp2a_i2c_write((u8)(GP2A_REG_CON),&value); /* enable INT */ enable_irq(gp2a_data->irq); printk(KERN_INFO "[GP2A] enable_irq IRQ_NO:%d\n",gp2a_data->irq); /* enabling VOUT terminal in nomal operation */ value = 0x00; gp2a_i2c_write((u8)(GP2A_REG_CON),&value); }
static long gp2a_opt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret = 0; short data = 0; u8 thrd = 0; u8 reg; switch (cmd) { case PROX_IOC_SET_CALIBRATION: { printk(KERN_INFO "[GP2A] PROX_IOC_SET_CALIBRATION\n"); if (copy_from_user(&data, (void __user *)arg, sizeof(data))) return -EFAULT; ret = proximity_open_calibration(gp2a_opt_data); if (ret < 0 && ret != -ENOENT) { printk(KERN_INFO "[GP2A] proximity_open_offset() failed\n"); }else { thrd = gp2a_reg[3][1]+(gp2a_opt_data->offset_value); THR_REG_LSB(thrd, reg); gp2a_i2c_write(gp2a_reg[3][0], ®); THR_REG_MSB(thrd, reg); gp2a_i2c_write(gp2a_reg[4][0], ®); thrd = gp2a_reg[5][1]+(gp2a_opt_data->offset_value); THR_REG_LSB(thrd, reg); gp2a_i2c_write(gp2a_reg[5][0], ®); THR_REG_MSB(thrd, reg); gp2a_i2c_write(gp2a_reg[6][0], ®); } break; } case PROX_IOC_GET_CALIBRATION: { printk(KERN_INFO "[GP2A] PROX_IOC_GET_CALIBRATION\n"); data = gp2a_opt_data->offset_value; if (copy_to_user((void __user *)arg, &data, sizeof(data))) return -EFAULT; break; } default: printk(KERN_ERR "Unknown IOCTL command"); ret = -ENOTTY; break; } return ret; }
static int gp2a_setup_irq(struct gp2a_data *gp2a) { int rc; struct gp2a_platform_data *pdata = gp2a->pdata; int irq = -1; u8 value; rc = gpio_request(pdata->p_out, "gpio_proximity_out"); if (rc < 0) { pr_err("%s,gpio %d request failed (%d)\n", __func__, pdata->p_out, rc); return rc; } rc = gpio_direction_input(pdata->p_out); if (rc < 0) { pr_err("%s,failed gpio %d as input (%d)\n", __func__, pdata->p_out, rc); goto err_gpio_direction_input; } value = 0x18; gp2a_i2c_write(gp2a, REGS_CON, value); irq = gpio_to_irq(pdata->p_out); rc = request_irq(irq, gp2a_irq_handler, IRQF_TRIGGER_FALLING, "proximity_int", gp2a); if (rc < 0) { pr_err("%s,request_irq(%d) failed for gpio %d (%d)\n", __func__, irq, pdata->p_out, rc); goto err_request_irq; } else{ pr_info("%s,request_irq(%d) success for gpio %d\n", __func__, irq, pdata->p_out); } disable_irq(irq); gp2a->irq = irq; value = 0x02; gp2a_i2c_write(gp2a, REGS_OPMOD, value); goto done; err_request_irq: err_gpio_direction_input: gpio_free(pdata->p_out); done: return rc; }
static ssize_t prox_cal_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct gp2a_data *gp2a = dev_get_drvdata(dev); u8 value; int err; if (sysfs_streq(buf, "1")) { gp2a->cal_mode = 1; nondetect = PROX_NONDETECT_MODE1; detect = PROX_DETECT_MODE1; } else if (sysfs_streq(buf, "2")) { gp2a->cal_mode = 2; nondetect = PROX_NONDETECT_MODE2; detect = PROX_DETECT_MODE2; } else if (sysfs_streq(buf, "0")) { gp2a->cal_mode = 0; nondetect = PROX_NONDETECT; detect = PROX_DETECT; } else { pr_err("%s: invalid value %d\n", __func__, *buf); return -EINVAL; } #if defined(CONFIG_MACH_KYLE) value = 0x00; #else value = 0x08; #endif gp2a_i2c_write(gp2a, REGS_GAIN, &value); value = nondetect; gp2a_i2c_write(gp2a, REGS_HYS, &value); value = 0x04; gp2a_i2c_write(gp2a, REGS_CYCLE, &value); value = 0x03; gp2a_i2c_write(gp2a, REGS_OPMOD, &value); value = 0x00; gp2a_i2c_write(gp2a, REGS_CON, &value); err = gp2a_cal_mode_save_file(gp2a->cal_mode); if (err < 0) { pr_err("%s: prox_cal_write() failed\n", __func__); return err; } return size; }
/* interrupt happened due to transition/change of near/far proximity state */ irqreturn_t gp2a_irq_handler(int irq, void *data) { struct gp2a_data *ip = data; #ifdef GP2A_MODE_B /* GP2A MODE B */ queue_work(ip->wq, &ip->work_proximity); #else /* GP2A MODE A */ u8 setting; int val = gpio_get_value(ip->pdata->p_out); if (val < 0) { pr_err("%s: gpio_get_value error %d\n", __func__, val); return IRQ_HANDLED; } if (val != ip->prox_value) { if (val) setting = VO_0; else setting = VO_1; gp2a_i2c_write(ip, REGS_HYS, &setting); } ip->prox_value = val; pr_err("gp2a: proximity val = %d\n", val); /* 0 is close, 1 is far */ input_report_abs(ip->proximity_input_dev, ABS_DISTANCE, val); input_sync(ip->proximity_input_dev); wake_lock_timeout(&ip->prx_wake_lock, 3*HZ); #endif return IRQ_HANDLED; }
static int gp2a_i2c_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct gp2a_data *gp2a = i2c_get_clientdata(client); u8 value; mutex_lock(&gp2a->light_mutex); if (gp2a->light_enabled) cancel_delayed_work_sync(&gp2a->light_work); mutex_unlock(&gp2a->light_mutex); if (gp2a->proximity_enabled) { /*enable_irq_wake(gp2a->irq); already wake irq enabled */ } else { value = 0x00; /*shutdown mode */ gp2a_i2c_write(gp2a, (u8) (COMMAND1), &value); gpio_free(gp2a->pdata->p_out); sensor_power_on_vdd(gp2a,0); //if (gp2a->pdata->power_on) // gp2a->pdata->power_on(0); } return 0; }
/* interrupt happened due to transition/change of near/far proximity state */ irqreturn_t gp2a_irq_handler(int irq, void *data) { struct gp2a_data *ip = data; u8 setting; int val = gpio_get_value(ip->pdata->p_out); if (val < 0) { pr_err("%s: gpio_get_value error %d\n", __func__, val); return IRQ_HANDLED; } if (val != ip->val_state) { if (val) setting = 0x40; else setting = 0x20; gp2a_i2c_write(ip, REGS_HYS, &setting); } ip->val_state = val; pr_err("gp2a: proximity val = %d\n", val); /* 0 is close, 1 is far */ input_report_abs(ip->proximity_input_dev, ABS_DISTANCE, val); input_sync(ip->proximity_input_dev); wake_lock_timeout(&ip->prx_wake_lock, 3*HZ); return IRQ_HANDLED; }
static void gp2a_work_func_proximity(struct work_struct *work) { int ret; u8 value; u8 vout = 0; struct gp2a_data *gp2a = container_of(work, struct gp2a_data, work_proximity); pr_info("%s : gp2a mode b", __func__); mutex_lock(&gp2a->power_mutex); /* GP2A initialized and powered on => do the job */ ret = gpio_get_value(gp2a->pdata->p_out); if (ret < 0) { pr_info("Failed to get GP2A proximity value " "[errno=%d]; ignored", ret); } else { gp2a->prox_value = ret; if (GP2A_BIT_PROX_VO_DETECTION == gp2a->prox_value) { ret = GP2A_INPUT_RANGE_MIN; pr_info("GP2A_INPUT_RANGE_MIN"); } else { ret = GP2A_INPUT_RANGE_MAX; pr_info("GP2A_INPUT_RANGE_MAX"); } input_report_abs(gp2a->proximity_input_dev, ABS_DISTANCE, ret); input_sync(gp2a->proximity_input_dev); pr_info("input_report_abs proximity_input_dev"); } if (ret) value = VO_0; else value = VO_1; pr_info("value = 0x%x\n", value); gp2a_i2c_write(gp2a, REGS_HYS, &value); /* enabling VOUT terminal in nomal operation */ value = 0x00; gp2a_i2c_write(gp2a, REGS_CON, &value); mutex_unlock(&gp2a->power_mutex); }
static void gp2a_work_func_prox(struct work_struct *work) { struct gp2a_data *gp2a = container_of((struct work_struct *)work, struct gp2a_data, proximity_work); unsigned char value; char result; int ret; /* 0 : proximity, 1 : away */ result = gpio_get_value_cansleep(gp2a->pdata->p_out); gp2a->proximity_detection = !result; input_report_abs(gp2a->proximity_input_dev, ABS_DISTANCE, result); pr_info("%s Proximity values = %d\n", __func__, result); input_sync(gp2a->proximity_input_dev); disable_irq(gp2a->irq); /*Software reset */ value = 0x0C; ret = gp2a_i2c_write(gp2a, COMMAND1, &value); if (result == 0) { /* detection = Falling Edge */ if (gp2a->lightsensor_mode == 0) /* Low mode */ value = 0x23; else /* High mode */ value = 0x27; ret = gp2a_i2c_write(gp2a, COMMAND2, &value); } else { /* none Detection */ if (gp2a->lightsensor_mode == 0) /* Low mode */ value = 0x63; else /* High mode */ value = 0x67; ret = gp2a_i2c_write(gp2a, COMMAND2, &value); } enable_irq(gp2a->irq); value = 0xCC; ret = gp2a_i2c_write(gp2a, COMMAND1, &value); gp2a->prox_data = result; pr_debug("proximity = %d, lightsensor_mode=%d\n", result, gp2a->lightsensor_mode); }
static int gp2a_power_onoff(struct gp2a_data *gp2a, int power) { u8 value; pr_info("%s,status(%d)\n", __func__, power); if (power) { gp2a_leda_onoff(gp2a, power); value = 0x18; gp2a_i2c_write(gp2a, REGS_CON, value); value = 0x08; gp2a_i2c_write(gp2a, REGS_GAIN, value); value = gp2a->nondetect; gp2a_i2c_write(gp2a, REGS_HYS, value); value = 0x04; gp2a_i2c_write(gp2a, REGS_CYCLE, value); value = 0x03; gp2a_i2c_write(gp2a, REGS_OPMOD, value); enable_irq_wake(gp2a->irq); enable_irq(gp2a->irq); value = 0x00; gp2a_i2c_write(gp2a, REGS_CON, value); } else { disable_irq_wake(gp2a->irq); disable_irq(gp2a->irq); value = 0x02; gp2a_i2c_write(gp2a, REGS_OPMOD, value); gp2a_leda_onoff(gp2a, power); } return 0; }
static int gp2a_prox_onoff(u8 onoff, struct gp2a_data *data) { u8 value; pr_info("%s : proximity turn on/off = %d\n", __func__, onoff); /* already on light sensor, so must simultaneously turn on light sensor and proximity sensor */ if (onoff) { int i; #ifndef CONFIG_SEC_BERLUTI_PROJECT gpio_set_value(data->vled_gpio, 1); #endif for (i = 0; i < COL; i++) { int err = gp2a_i2c_write(data, gp2a_reg[i][0], &gp2a_reg[i][1]); if (err < 0) pr_err("%s : turnning on error i = %d, err=%d\n", __func__, i, err); data->lightsensor_mode = 0; } } else { if (data->light_enabled) { if (data->lightsensor_mode) value = 0x67; /*resolution :16bit, range: *8(HIGH) */ else value = 0x63; /* resolution :16bit, range: *128(LOW) */ gp2a_i2c_write(data, COMMAND2, &value); /* OP3 : 1(operating mode) OP2 : 1(coutinuous operating mode) OP1 : 01(ALS mode) */ value = 0xD0; gp2a_i2c_write(data, COMMAND1, &value); } else { value = 0x00; /*shutdown mode */ gp2a_i2c_write(data, (u8) (COMMAND1), &value); } #ifndef CONFIG_SEC_BERLUTI_PROJECT gpio_set_value(data->vled_gpio, 0); #endif } return 0; }
static ssize_t proximity_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct gp2a_data *gp2a = dev_get_drvdata(dev); bool new_value; if (sysfs_streq(buf, "1")) new_value = true; else if (sysfs_streq(buf, "0")) new_value = false; else { pr_err("%s: invalid value %d\n", __func__, *buf); return -EINVAL; } #ifdef CONFIG_TOUCH_WAKE if (!new_value) proximity_off(); #endif mutex_lock(&gp2a->power_lock); gp2a_dbgmsg("new_value = %d, old state = %d\n", new_value, (gp2a->power_state & PROXIMITY_ENABLED) ? 1 : 0); if (new_value && !(gp2a->power_state & PROXIMITY_ENABLED)) { if (!gp2a->power_state) gp2a->pdata->power(true); gp2a->power_state |= PROXIMITY_ENABLED; enable_irq(gp2a->irq); enable_irq_wake(gp2a->irq); gp2a_i2c_write(gp2a, REGS_GAIN, ®_defaults[1]); gp2a_i2c_write(gp2a, REGS_HYS, ®_defaults[2]); gp2a_i2c_write(gp2a, REGS_CYCLE, ®_defaults[3]); gp2a_i2c_write(gp2a, REGS_OPMOD, ®_defaults[4]); } else if (!new_value && (gp2a->power_state & PROXIMITY_ENABLED)) { disable_irq_wake(gp2a->irq); disable_irq(gp2a->irq); gp2a_i2c_write(gp2a, REGS_OPMOD, ®_defaults[0]); gp2a->power_state &= ~PROXIMITY_ENABLED; if (!gp2a->power_state) gp2a->pdata->power(false); } mutex_unlock(&gp2a->power_lock); return size; }
static void gp2a_prox_work_func(struct work_struct *work) { struct gp2a_data *gp2a = container_of(work, struct gp2a_data, work_prox); u8 vo, value; if (gp2a->irq != 0) { disable_irq_wake(gp2a->irq); disable_irq(gp2a->irq); } else { return ; } gp2a_i2c_read(gp2a, REGS_PROX, &vo); vo = 0x01 & vo; if (vo == gp2a->val_state) { if (!vo) { /* close */ vo = 0x01; value = nondetect; } else { /* far */ vo = 0x00; value = detect; } gp2a_i2c_write(gp2a, REGS_HYS, &value); gp2a->val_state = vo; } input_report_abs(gp2a->proximity_input_dev, ABS_DISTANCE, gp2a->val_state); input_sync(gp2a->proximity_input_dev); /* 1 : far, 0 : close */ pr_info("%s: %d(1:far/0:close)\n", __func__, gp2a->val_state); msleep(20); value = 0x18; gp2a_i2c_write(gp2a, REGS_CON, &value); if (gp2a->irq != 0) { enable_irq(gp2a->irq); enable_irq_wake(gp2a->irq); } value = 0x00; gp2a_i2c_write(gp2a, REGS_CON, &value); }
static int gp2a_prox_cal_mode(char mode) { int ret=0; u8 reg_value; if (mode == 1) { nondetect = PROX_NONDETECT_MODE1; detect = PROX_DETECT_MODE1; } else if (mode == 2) { nondetect = PROX_NONDETECT_MODE2; detect = PROX_DETECT_MODE2; } else { nondetect = PROX_NONDETECT; detect = PROX_DETECT; } reg_value = 0x08; if((ret=gp2a_i2c_write(GP2A_REG_GAIN/*0x01*/,®_value))<0) error("gp2a_i2c_write 1 failed\n"); gp2a_prox_offset(0); reg_value = 0x04; if((ret=gp2a_i2c_write(GP2A_REG_CYCLE/*0x03*/,®_value))<0) error("gp2a_i2c_write 3 failed\n"); reg_value = 0x03; if((ret=gp2a_i2c_write(GP2A_REG_OPMOD,®_value))<0) error("gp2a_i2c_write 3 failed"); reg_value = 0x00; if((ret=gp2a_i2c_write(GP2A_REG_CON,®_value))<0) error("gp2a_i2c_write 4 failed"); return ret; }
/* * Operation Mode B * Initiate operation */ static int gp2a_prox_reset(void) { u8 reg_value; int ret=0; debug("[GP2A] %s called\n",__func__); /* Procedure 1: After Power Supply is turned on, setup the following register 01H GAIN - 0x08 02H HYS - 0x40 03H CYCLE - 0x04 04H OPMOD - 0x03 Procedure 2: Permit host's interrupt input Procedure 3 : VOUT terminal changes from "H" to "L" Procedure 4 : Forbit host's interrupt input Procedure 5 : Read VO value through I2C bus interface, VO=0 : no detection, VO=1 : detection Procedure 6 : Write HYS register through I2C bus interface Procedure 7 : Set 06H CON register as follows, forcing VOUT terminal to go H. 06H CON - 0x18 Procedure 8 : Permit host's interrupt input Prodecure 9 : Set 06H CON register as follows, enabling VOUT terminal in normal operation 06H CON - 0x00 Prodecure 10 : Repeat procedures from 3 to 9 */ reg_value = 0x18; if((ret=gp2a_i2c_write(GP2A_REG_CON/*0x06*/,®_value))<0) error("gp2a_i2c_write 4 failed\n"); reg_value = 0x08; if((ret=gp2a_i2c_write(GP2A_REG_GAIN/*0x01*/,®_value))<0) error("gp2a_i2c_write 1 failed\n"); reg_value = 0x40; if((ret=gp2a_i2c_write(GP2A_REG_HYS/*0x02*/,®_value))<0) error("gp2a_i2c_write 2 failed\n"); reg_value = 0x04; if((ret=gp2a_i2c_write(GP2A_REG_CYCLE/*0x03*/,®_value))<0) error("gp2a_i2c_write 3 failed\n"); return ret; }
static int gp2a_prox_mode(int enable) { u8 reg_value; int ret=0; debug("%s called\n",__func__); if(1==enable) { reg_value = 0x18; if((ret=gp2a_i2c_write(GP2A_REG_CON,®_value))<0) error("gp2a_i2c_write 1 failed"); gp2a_prox_offset(0); reg_value = 0x03; if((ret=gp2a_i2c_write(GP2A_REG_OPMOD,®_value))<0) error("gp2a_i2c_write 3 failed"); enable_irq(gp2a_data->irq); reg_value = 0x00; if((ret=gp2a_i2c_write(GP2A_REG_CON,®_value))<0) error("gp2a_i2c_write 4 failed"); proximity_enable=1; } else { disable_irq_nosync(gp2a_data->irq); reg_value = 0x02; if((ret=gp2a_i2c_write(GP2A_REG_OPMOD,®_value))<0) error("gp2a_i2c_write 3 failed"); proximity_enable=0; proximity_value = 0; } return ret; }
static int gp2a_prox_reset(void) { u8 reg_value; int ret=0; debug("[GP2A] %s called\n",__func__); reg_value = 0x18; if((ret=gp2a_i2c_write(GP2A_REG_CON/*0x06*/,®_value))<0) error("gp2a_i2c_write 4 failed\n"); reg_value = 0x08; if((ret=gp2a_i2c_write(GP2A_REG_GAIN/*0x01*/,®_value))<0) error("gp2a_i2c_write 1 failed\n"); gp2a_prox_offset(0); reg_value = 0x04; if((ret=gp2a_i2c_write(GP2A_REG_CYCLE/*0x03*/,®_value))<0) error("gp2a_i2c_write 3 failed\n"); return ret; }
static ssize_t proximity_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct gp2a_data *gp2a = dev_get_drvdata(dev); bool new_value; if (sysfs_streq(buf, "1")) new_value = true; else if (sysfs_streq(buf, "0")) new_value = false; else { pr_err("%s: invalid value %d\n", __func__, *buf); return -EINVAL; } mutex_lock(&gp2a->power_lock); gp2a_dbgmsg("new_value = %d, old state = %d\n", new_value, gp2a->on); if (new_value && !gp2a->on) { gp2a->pdata->power(true); gp2a->on = true; enable_irq(gp2a->irq); enable_irq_wake(gp2a->irq); gp2a_i2c_write(gp2a, REGS_GAIN, ®_defaults[1]); gp2a_i2c_write(gp2a, REGS_HYS, ®_defaults[2]); gp2a_i2c_write(gp2a, REGS_CYCLE, ®_defaults[3]); gp2a_i2c_write(gp2a, REGS_OPMOD, ®_defaults[4]); } else if (!new_value && gp2a->on) { disable_irq_wake(gp2a->irq); disable_irq(gp2a->irq); gp2a_i2c_write(gp2a, REGS_OPMOD, ®_defaults[0]); gp2a->on = false; gp2a->pdata->power(false); } mutex_unlock(&gp2a->power_lock); return size; }
static void gp2a_prox_work_func(struct work_struct *work) { struct gp2a_data *gp2a = container_of(work, struct gp2a_data, work_prox); u8 vo, value; pr_info("%s : irq = %d\n", __func__, gp2a->pdata->irq); gp2a_i2c_read(gp2a, REGS_PROX, &vo); vo = 0x01 & vo; if (vo == gp2a->val_state) { if (!vo) { vo = 0x01; value = nondetect; } else { vo = 0x00; value = detect; } #ifdef ALPS_DEBUG pr_info("%s: %d\n", __func__, gp2a->val_state); #endif gp2a_i2c_write(gp2a, REGS_HYS, &value); gp2a->val_state = vo; } input_report_abs(gp2a->proximity_input_dev, ABS_DISTANCE, gp2a->val_state); input_sync(gp2a->proximity_input_dev); msleep(20); value = 0x18; gp2a_i2c_write(gp2a, REGS_CON, &value); value = 0x00; gp2a_i2c_write(gp2a, REGS_CON, &value); }