static ssize_t poll_delay_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct gp2a_data *gp2a = dev_get_drvdata(dev); int64_t new_delay; int err; err = strict_strtoll(buf, 10, &new_delay); if (err < 0) return err; gp2a_dbgmsg("new delay = %lldns, old delay = %lldns\n", new_delay, ktime_to_ns(gp2a->light_poll_delay)); if (new_delay < DELAY_LOWBOUND) { gp2a_dbgmsg("new delay less than low bound, so set delay " "to %lld\n", (int64_t)DELAY_LOWBOUND); new_delay = DELAY_LOWBOUND; } mutex_lock(&gp2a->power_lock); if (new_delay != ktime_to_ns(gp2a->light_poll_delay)) { gp2a->light_poll_delay = ns_to_ktime(new_delay); if (gp2a->power_state & LIGHT_ENABLED) { gp2a_light_disable(gp2a); gp2a_light_enable(gp2a); } } mutex_unlock(&gp2a->power_lock); return size; }
static int gp2a_setup_irq(struct gp2a_data *gp2a) { int rc = -EIO; struct gp2a_platform_data *pdata = gp2a->pdata; int irq; gp2a_dbgmsg("start\n"); 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; } #ifndef CONFIG_SAMSUNG_FASCINATE rc = gpio_direction_input(pdata->p_out); if (rc < 0) { pr_err("%s: failed to set gpio %d as input (%d)\n", __func__, pdata->p_out, rc); goto err_gpio_direction_input; } irq = gpio_to_irq(pdata->p_out); #else irq = pdata->p_irq; #endif rc = request_threaded_irq(irq, NULL, gp2a_irq_handler, IRQF_TRIGGER_RISING | 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; } /* start with interrupts disabled */ disable_irq(irq); gp2a->irq = irq; /* sync input device with proximity gpio pin default value */ gp2a_irq_handler(gp2a->irq, gp2a); gp2a_dbgmsg("success\n"); goto done; err_request_irq: #ifndef CONFIG_SAMSUNG_FASCINATE err_gpio_direction_input: #endif gpio_free(pdata->p_out); done: return rc; }
static int gp2a_setup_irq(struct gp2a_data *gp2a) { int rc = -EIO; struct gp2a_platform_data *pdata = gp2a->pdata; int irq; gp2a_dbgmsg("start\n"); 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 to set gpio %d as input (%d)\n", __func__, pdata->p_out, rc); goto err_gpio_direction_input; } irq = gpio_to_irq(pdata->p_out); rc = request_threaded_irq(irq, NULL, gp2a_irq_handler, IRQF_TRIGGER_RISING | 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; } /* start with interrupts disabled */ disable_irq(irq); gp2a->irq = irq; gp2a_dbgmsg("success\n"); goto done; err_request_irq: err_gpio_direction_input: gpio_free(pdata->p_out); done: return rc; }
static ssize_t light_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->power_state & LIGHT_ENABLED) ? 1 : 0); if (new_value && !(gp2a->power_state & LIGHT_ENABLED)) { if (!gp2a->power_state) gp2a->pdata->power(true); gp2a->power_state |= LIGHT_ENABLED; gp2a_light_enable(gp2a); } else if (!new_value && (gp2a->power_state & LIGHT_ENABLED)) { gp2a_light_disable(gp2a); gp2a->power_state &= ~LIGHT_ENABLED; if (!gp2a->power_state) gp2a->pdata->power(false); } mutex_unlock(&gp2a->power_lock); return size; }
static void gp2a_light_enable(struct gp2a_data *gp2a) { gp2a_dbgmsg("starting poll timer, delay %lldns\n", ktime_to_ns(gp2a->light_poll_delay)); gp2a->light_buffer = 0; gp2a->light_count = 0; hrtimer_start(&gp2a->timer, gp2a->light_poll_delay, HRTIMER_MODE_REL); }
static void gp2a_light_enable(struct gp2a_data *gp2a) { gp2a_dbgmsg("starting poll timer, delay %lldns\n", ktime_to_ns(gp2a->light_poll_delay)); #ifdef CONFIG_S5PV210_GARNETT_DELTA gp2a->light_count = 0; gp2a->light_buffer = 0; #endif hrtimer_start(&gp2a->timer, gp2a->light_poll_delay, HRTIMER_MODE_REL); }
static void gp2a_work_func_light(struct work_struct *work) { struct gp2a_data *gp2a = container_of(work, struct gp2a_data, work_light); int adc = gp2a->pdata->light_adc_value(); if (adc < 0) { pr_err("adc returned error %d\n", adc); return; } gp2a_dbgmsg("adc returned light value %d\n", adc); input_report_abs(gp2a->light_input_dev, ABS_MISC, adc); input_sync(gp2a->light_input_dev); }
static void gp2a_light_enable(struct gp2a_data *gp2a) { gp2a_dbgmsg("starting poll timer, delay %lldns\n", ktime_to_ns(gp2a->light_poll_delay)); /* * Set far out of range ABS_MISC value, -1024, to enable real value to * go through next. */ input_abs_set_val(gp2a->light_input_dev, ABS_MISC, -gp2a->pdata->light_adc_max); hrtimer_start(&gp2a->timer, ktime_set(0, LIGHT_SENSOR_START_TIME_DELAY), HRTIMER_MODE_REL); }
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 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; }
/* 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; 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; } gp2a_dbgmsg("gp2a: proximity val=%d\n", val); #ifdef CONFIG_TOUCH_WAKE if (!val) { proximity_detected(); } #endif /* 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 int gp2a_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret = -ENODEV; struct input_dev *input_dev; struct gp2a_data *gp2a; struct gp2a_platform_data *pdata = client->dev.platform_data; if (!pdata) { pr_err("%s: missing pdata!\n", __func__); return ret; } if (!pdata->power) { pr_err("%s: incomplete pdata!\n", __func__); return ret; } if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { pr_err("%s: i2c functionality check failed!\n", __func__); return ret; } gp2a = kzalloc(sizeof(struct gp2a_data), GFP_KERNEL); if (!gp2a) { pr_err("%s: failed to alloc memory for module data\n", __func__); return -ENOMEM; } gp2a->pdata = pdata; gp2a->i2c_client = client; i2c_set_clientdata(client, gp2a); wake_lock_init(&gp2a->prx_wake_lock, WAKE_LOCK_SUSPEND, "prx_wake_lock"); mutex_init(&gp2a->power_lock); /* allocate proximity input_device */ input_dev = input_allocate_device(); if (!input_dev) { pr_err("%s: could not allocate input device\n", __func__); goto err_input_allocate_device_proximity; } gp2a->proximity_input_dev = input_dev; input_set_drvdata(input_dev, gp2a); input_dev->name = "proximity"; input_set_capability(input_dev, EV_ABS, ABS_DISTANCE); input_set_abs_params(input_dev, ABS_DISTANCE, 0, 1, 0, 0); ret = gp2a_setup_irq(gp2a); if (ret) { pr_err("%s: could not setup irq\n", __func__); input_free_device(input_dev); goto err_setup_irq; } gp2a_dbgmsg("registering proximity input device\n"); ret = input_register_device(input_dev); if (ret < 0) { pr_err("%s: could not register input device\n", __func__); input_free_device(input_dev); goto err_input_register_device_proximity; } ret = sysfs_create_group(&input_dev->dev.kobj, &proximity_attribute_group); if (ret) { pr_err("%s: could not create sysfs group\n", __func__); goto err_sysfs_create_group_proximity; } /* Disable power of the sensor */ pdata->power(false); gp2a->on = false; /* set initial proximity value as 1 */ input_report_abs(gp2a->proximity_input_dev, ABS_DISTANCE, 1); input_sync(gp2a->proximity_input_dev); goto done; /* error, unwind it all */ err_sysfs_create_group_proximity: input_unregister_device(gp2a->proximity_input_dev); err_input_register_device_proximity: free_irq(gp2a->irq, gp2a); gpio_free(gp2a->pdata->p_out); err_setup_irq: err_input_allocate_device_proximity: mutex_destroy(&gp2a->power_lock); wake_lock_destroy(&gp2a->prx_wake_lock); kfree(gp2a); done: return ret; }
static int gp2a_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret = -ENODEV; struct input_dev *input_dev; struct gp2a_data *gp2a; struct gp2a_platform_data *pdata = client->dev.platform_data; if (!pdata) { pr_err("%s: missing pdata!\n", __func__); return ret; } if (!pdata->power || !pdata->light_adc_value) { pr_err("%s: incomplete pdata!\n", __func__); return ret; } if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { pr_err("%s: i2c functionality check failed!\n", __func__); return ret; } gp2a = kzalloc(sizeof(struct gp2a_data), GFP_KERNEL); if (!gp2a) { pr_err("%s: failed to alloc memory for module data\n", __func__); return -ENOMEM; } gp2a->pdata = pdata; gp2a->i2c_client = client; i2c_set_clientdata(client, gp2a); /* wake lock init */ wake_lock_init(&gp2a->prx_wake_lock, WAKE_LOCK_SUSPEND, "prx_wake_lock"); mutex_init(&gp2a->power_lock); ret = gp2a_setup_irq(gp2a); if (ret) { pr_err("%s: could not setup irq\n", __func__); goto err_setup_irq; } /* allocate proximity input_device */ input_dev = input_allocate_device(); if (!input_dev) { pr_err("%s: could not allocate input device\n", __func__); goto err_input_allocate_device_proximity; } gp2a->proximity_input_dev = input_dev; input_set_drvdata(input_dev, gp2a); input_dev->name = "proximity_sensor"; input_set_capability(input_dev, EV_ABS, ABS_DISTANCE); input_set_abs_params(input_dev, ABS_DISTANCE, 0, 1, 0, 0); gp2a_dbgmsg("registering proximity input device\n"); ret = input_register_device(input_dev); if (ret < 0) { pr_err("%s: could not register input device\n", __func__); input_free_device(input_dev); goto err_input_register_device_proximity; } ret = sysfs_create_group(&input_dev->dev.kobj, &proximity_attribute_group); if (ret) { pr_err("%s: could not create sysfs group\n", __func__); goto err_sysfs_create_group_proximity; } /* hrtimer settings. we poll for light values using a timer. */ hrtimer_init(&gp2a->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); gp2a->light_poll_delay = ns_to_ktime(200 * NSEC_PER_MSEC); gp2a->timer.function = gp2a_timer_func; /* the timer just fires off a work queue request. we need a thread to read the i2c (can be slow and blocking). */ gp2a->wq = create_singlethread_workqueue("gp2a_wq"); if (!gp2a->wq) { ret = -ENOMEM; pr_err("%s: could not create workqueue\n", __func__); goto err_create_workqueue; } /* this is the thread function we run on the work queue */ INIT_WORK(&gp2a->work_light, gp2a_work_func_light); /* allocate lightsensor-level input_device */ input_dev = input_allocate_device(); if (!input_dev) { pr_err("%s: could not allocate input device\n", __func__); ret = -ENOMEM; goto err_input_allocate_device_light; } input_set_drvdata(input_dev, gp2a); input_dev->name = "light_sensor"; input_set_capability(input_dev, EV_ABS, ABS_MISC); input_set_abs_params(input_dev, ABS_MISC, 0, 1, 0, 0); gp2a_dbgmsg("registering lightsensor-level input device\n"); ret = input_register_device(input_dev); if (ret < 0) { pr_err("%s: could not register input device\n", __func__); input_free_device(input_dev); goto err_input_register_device_light; } gp2a->light_input_dev = input_dev; ret = sysfs_create_group(&input_dev->dev.kobj, &light_attribute_group); if (ret) { pr_err("%s: could not create sysfs group\n", __func__); goto err_sysfs_create_group_light; } /* set sysfs for light sensor */ ret = misc_register(&light_device); if (ret) pr_err(KERN_ERR "misc_register failed - light\n"); gp2a->lightsensor_class = class_create(THIS_MODULE, "lightsensor"); if (IS_ERR(gp2a->lightsensor_class)) pr_err("Failed to create class(lightsensor)!\n"); gp2a->switch_cmd_dev = device_create(gp2a->lightsensor_class, NULL, 0, NULL, "switch_cmd"); if (IS_ERR(gp2a->switch_cmd_dev)) pr_err("Failed to create device(switch_cmd_dev)!\n"); if (device_create_file(gp2a->switch_cmd_dev, &dev_attr_lightsensor_file_state) < 0) pr_err("Failed to create device file(%s)!\n", dev_attr_lightsensor_file_state.attr.name); dev_set_drvdata(gp2a->switch_cmd_dev, gp2a); #ifdef CONFIG_ARIES_NTT /* set initial proximity value as 1 */ input_report_abs(gp2a->proximity_input_dev, ABS_DISTANCE, 1); input_sync(gp2a->proximity_input_dev); #endif goto done; /* error, unwind it all */ err_sysfs_create_group_light: input_unregister_device(gp2a->light_input_dev); err_input_register_device_light: err_input_allocate_device_light: destroy_workqueue(gp2a->wq); err_create_workqueue: sysfs_remove_group(&gp2a->proximity_input_dev->dev.kobj, &proximity_attribute_group); err_sysfs_create_group_proximity: input_unregister_device(gp2a->proximity_input_dev); err_input_register_device_proximity: err_input_allocate_device_proximity: free_irq(gp2a->irq, 0); gpio_free(gp2a->pdata->p_out); err_setup_irq: mutex_destroy(&gp2a->power_lock); wake_lock_destroy(&gp2a->prx_wake_lock); kfree(gp2a); done: return ret; }
static int gp2a_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret = -ENODEV; struct input_dev *input_dev; struct gp2a_data *gp2a; struct gp2a_platform_data *pdata = client->dev.platform_data; u8 value; pr_info("[TMP] %s, %d\n", __func__, __LINE__); #if defined(CONFIG_MACH_KYLE) nondetect = PROX_NONDETECT; detect = PROX_DETECT; #else nondetect = PROX_NONDETECT; detect = PROX_DETECT; #endif pr_info("%s: %02x %02x\n", __func__, nondetect, detect); if (!pdata) { pr_err("%s: missing pdata!\n", __func__); return ret; } if (!pdata->power) { pr_err("%s: incomplete pdata!\n", __func__); return ret; } /* power on gp2a */ pdata->power(true); msleep(10); if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { pr_err("%s: i2c functionality check failed!\n", __func__); return ret; } gp2a = kzalloc(sizeof(struct gp2a_data), GFP_KERNEL); if (!gp2a) { pr_err("%s: failed to alloc memory for module data\n", __func__); return -ENOMEM; } gp2a->pdata = pdata; gp2a->i2c_client = client; i2c_set_clientdata(client, gp2a); /* wake lock init */ wake_lock_init(&gp2a->prx_wake_lock, WAKE_LOCK_SUSPEND, "prx_wake_lock"); mutex_init(&gp2a->power_lock); /* allocate proximity input_device */ input_dev = input_allocate_device(); if (!input_dev) { pr_err("%s: could not allocate input device\n", __func__); goto err_input_allocate_device_proximity; } gp2a->proximity_input_dev = input_dev; input_set_drvdata(input_dev, gp2a); input_dev->name = "proximity_sensor"; input_set_capability(input_dev, EV_ABS, ABS_DISTANCE); input_set_abs_params(input_dev, ABS_DISTANCE, 0, 1, 0, 0); ret = input_register_device(input_dev); if (ret < 0) { pr_err("%s: could not register input device\n", __func__); input_free_device(input_dev); goto err_input_allocate_device_proximity; } ret = sysfs_create_group(&input_dev->dev.kobj, &proximity_attribute_group); if (ret) { pr_err("%s: could not create sysfs group\n", __func__); goto err_sysfs_create_group_proximity; } /* the timer just fires off a work queue request. we need a thread to read the i2c (can be slow and blocking). */ INIT_WORK(&gp2a->work_prox, gp2a_prox_work_func); #if 1 ret = gp2a_setup_irq(gp2a); if (ret) { pr_err("%s: could not setup irq\n", __func__); goto err_setup_irq; } #else //=========================================== printk("%s gp2a->i2c_client->irq:%d", __func__,GPIO_PS_VOUT); printk("%s gp2a->i2c_client->irq:%d", __func__,gp2a->i2c_client->irq); //gpio_request(GPIO_PS_VOUT, "gpio_proximity_out"); //gpio_direction_input(GPIO_PS_VOUT); ret= gpio_request(GPIO_PS_VOUT, "gpio_proximity_out"); if (ret < 0) { pr_err("%s: gpio mfp_to_gpio(%d) request failed =>(%d)\n", __func__, GPIO092_GPIO_92, ret); return ret; } ret= gpio_direction_input(GPIO_PS_VOUT); if (ret < 0) { pr_err("%s: failed to set gpio %d as input (%d)\n", __func__, GPIO_PS_VOUT, ret); goto err_setup_irq; } value = 0x18; gp2a_i2c_write(gp2a, REGS_CON, &value); gp2a->irq = gpio_to_irq(GPIO_PS_VOUT); ret= request_irq(gp2a->irq, gp2a_irq_handler, IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, "proximity_int", gp2a); if (ret < 0) { pr_err("%s: request_irq(%d) failed for gpio %d (%d)\n", __func__, GPIO_PS_VOUT, gp2a->irq, ret); goto err_setup_irq; } else{ pr_info("%s: request_irq(%d) success for gpio %d\n", __func__, GPIO_PS_VOUT, gp2a->irq); } /* start with interrupts disabled */ disable_irq(gp2a->irq); gp2a->val_state = 1; gp2a->power_state &= PROXIMITY_ENABLED; gp2a_dbgmsg("success\n"); value = 0x08; 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 = 0x18; gp2a_i2c_write(gp2a, REGS_CON, &value); value = 0x02; gp2a_i2c_write(gp2a, REGS_OPMOD, &value); //============================================== #endif #if 1 //not yet ready ret = sensors_register(&gp2a->proximity_dev, gp2a, proxi_attrs, "proximity_sensor"); if (ret < 0) { pr_info("%s: could not sensors_register\n", __func__); goto exit_gp2a_sensors_register; } #endif /* set initial proximity value as 1 */ input_report_abs(gp2a->proximity_input_dev, ABS_DISTANCE, 1); input_sync(gp2a->proximity_input_dev); pr_info("[TMP] %s, %d\n", __func__, __LINE__); pdata->power(false); goto done; /* error, unwind it all */ exit_gp2a_sensors_register: free_irq(gp2a->irq, gp2a); gpio_free(gp2a->i2c_client->irq); err_setup_irq: pr_info("err_setup_irq\n"); sysfs_remove_group(&gp2a->proximity_input_dev->dev.kobj, &proximity_attribute_group); err_sysfs_create_group_proximity: pr_info("err_sysfs_create_group_proximity\n"); input_unregister_device(gp2a->proximity_input_dev); err_input_allocate_device_proximity: pr_info("err_input_allocate_device_proximity\n"); mutex_destroy(&gp2a->power_lock); wake_lock_destroy(&gp2a->prx_wake_lock); kfree(gp2a); done: pr_info("done\n"); return ret; }
static void gp2a_light_disable(struct gp2a_data *gp2a) { gp2a_dbgmsg("cancelling poll timer\n"); hrtimer_cancel(&gp2a->timer); cancel_work_sync(&gp2a->work_light); }
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; u8 value; int ret; #ifdef GP2AP002X_PROXIMITY_OFFSET int err; #endif 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->power_state & PROXIMITY_ENABLED) ? 1 : 0); #ifdef ALPS_DEBUG pr_info("[TMP] new_value = %d, old state = %d\n", new_value, (gp2a->power_state & PROXIMITY_ENABLED) ? 1 : 0); #endif if (new_value && !(gp2a->power_state & PROXIMITY_ENABLED)) { pr_info("[TMP] %s, %d\n", __func__, __LINE__); #if defined(CONFIG_MACH_AMAZING_CDMA) LED_onoff(1); #endif #ifdef GP2AP002X_PROXIMITY_OFFSET err = gp2a_cal_mode_read_file(&gp2a->cal_mode); if (err < 0 && err != -ENOENT) pr_err("%s: cal_mode file read fail\n", __func__); pr_info("%s: mode = %02x\n", __func__, gp2a->cal_mode); if (gp2a->cal_mode == 2) { nondetect = PROX_NONDETECT_MODE2; detect = PROX_DETECT_MODE2; } else if (gp2a->cal_mode == 1) { nondetect = PROX_NONDETECT_MODE1; detect = PROX_DETECT_MODE1; } else { nondetect = PROX_NONDETECT; detect = PROX_DETECT; } #endif gp2a->val_state = 1; input_report_abs(gp2a->proximity_input_dev, ABS_DISTANCE, gp2a->val_state); input_sync(gp2a->proximity_input_dev); gp2a->power_state |= PROXIMITY_ENABLED; gp2a->pdata->power(true); msleep(20); value = 0x18; gp2a_i2c_write(gp2a, REGS_CON, &value); #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); #if defined(CONFIG_MACH_GEIM) enable_irq_wake(gp2a->irq); #else enable_irq_wake(gp2a->irq); #endif value = 0x03; ret = gp2a_i2c_write(gp2a, REGS_OPMOD, &value); pr_info("%s: ret = %d\n", __func__, ret); enable_irq(gp2a->irq); value = 0x00; ret = gp2a_i2c_write(gp2a, REGS_CON, &value); pr_info("%s: ret = %d\n", __func__, ret); } else if (!new_value && (gp2a->power_state & PROXIMITY_ENABLED)) { pr_info("[TMP] %s, %d\n", __func__, __LINE__); #if defined(CONFIG_MACH_AMAZING_CDMA) LED_onoff(0); #endif #if defined(CONFIG_MACH_GEIM) disable_irq_wake(gp2a->irq); #else disable_irq_wake(gp2a->irq); #endif disable_irq(gp2a->irq); value = 0x02; gp2a_i2c_write(gp2a, REGS_OPMOD, &value); gp2a->power_state &= ~PROXIMITY_ENABLED; gp2a->pdata->power(false); } mutex_unlock(&gp2a->power_lock); return size; }
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; #ifdef GP2A_MODE_B u8 val; #endif 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_mutex); 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)) { gp2a->power_state |= PROXIMITY_ENABLED; #ifdef GP2A_MODE_B val = GP2A_BIT_OPMOD_SSD_OPERATING_MODE | GP2A_BIT_OPMOD_VCON_NORMAL_MODE | GP2A_BIT_OPMOD_ASD_INEFFECTIVE; gp2a_i2c_write(gp2a, REGS_OPMOD, &val); val = GP2A_BIT_CON_OCON_ENABLE_VOUT; gp2a_i2c_write(gp2a, REGS_CON, &val); #else 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]); gp2a->val_state = 1; #endif enable_irq(gp2a->irq); if (gp2a->enable_wakeup) enable_irq_wake(gp2a->irq); } else if (!new_value && (gp2a->power_state & PROXIMITY_ENABLED)) { if (gp2a->enable_wakeup) disable_irq_wake(gp2a->irq); disable_irq(gp2a->irq); #ifdef GP2A_MODE_B val = GP2A_BIT_CON_OCON_FORCE_VOUT_HIGH; gp2a_i2c_write(gp2a, REGS_CON, &val); val = GP2A_BIT_OPMOD_SSD_SHUTDOWN_MODE | GP2A_BIT_OPMOD_VCON_NORMAL_MODE | GP2A_BIT_OPMOD_ASD_INEFFECTIVE; gp2a_i2c_write(gp2a, REGS_OPMOD, &val); #else gp2a_i2c_write(gp2a, REGS_OPMOD, ®_defaults[0]); #endif gp2a->power_state &= ~PROXIMITY_ENABLED; } mutex_unlock(&gp2a->power_mutex); return size; }
static int gp2a_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret = -ENODEV; struct input_dev *input_dev; struct gp2a_data *gp2a; struct gp2a_platform_data *pdata = client->dev.platform_data; pr_info("==============================\n"); pr_info("========= GP2A =======\n"); pr_info("==============================\n"); if (!pdata) { pr_err("%s: missing pdata!\n", __func__); return ret; } if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { pr_err("%s: i2c functionality check failed!\n", __func__); return ret; } gp2a = kzalloc(sizeof(struct gp2a_data), GFP_KERNEL); if (!gp2a) { pr_err("%s: failed to alloc memory for module data\n", __func__); return -ENOMEM; } #if defined(CONFIG_OPTICAL_WAKE_ENABLE) if (system_rev >= 0x03) { pr_info("GP2A Reset GPIO = GPX0(1) (rev%02d)\n", system_rev); gp2a->enable_wakeup = true; } else { pr_info("GP2A Reset GPIO = GPL0(6) (rev%02d)\n", system_rev); gp2a->enable_wakeup = false; } #else gp2a->enable_wakeup = false; #endif gp2a->pdata = pdata; gp2a->i2c_client = client; i2c_set_clientdata(client, gp2a); /* wake lock init */ wake_lock_init(&gp2a->prx_wake_lock, WAKE_LOCK_SUSPEND, "prx_wake_lock"); mutex_init(&gp2a->power_mutex); mutex_init(&gp2a->adc_mutex); ret = gp2a_setup_irq(gp2a); if (ret) { pr_err("%s: could not setup irq\n", __func__); goto err_setup_irq; } /* allocate proximity input_device */ input_dev = input_allocate_device(); if (!input_dev) { pr_err("%s: could not allocate input device\n", __func__); goto err_input_allocate_device_proximity; } gp2a->proximity_input_dev = input_dev; input_set_drvdata(input_dev, gp2a); input_dev->name = "proximity_sensor"; input_set_capability(input_dev, EV_ABS, ABS_DISTANCE); input_set_abs_params(input_dev, ABS_DISTANCE, 0, 1, 0, 0); gp2a_dbgmsg("registering proximity input device\n"); ret = input_register_device(input_dev); if (ret < 0) { pr_err("%s: could not register input device\n", __func__); input_free_device(input_dev); goto err_input_register_device_proximity; } ret = sysfs_create_group(&input_dev->dev.kobj, &proximity_attribute_group); if (ret) { pr_err("%s: could not create sysfs group\n", __func__); goto err_sysfs_create_group_proximity; } /* hrtimer settings. we poll for light values using a timer. */ hrtimer_init(&gp2a->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); gp2a->light_poll_delay = ns_to_ktime(LIGHT_TIMER_PERIOD_MS * NSEC_PER_MSEC); gp2a->timer.function = gp2a_timer_func; /* the timer just fires off a work queue request. we need a thread to read the i2c (can be slow and blocking). */ gp2a->wq = create_singlethread_workqueue("gp2a_wq"); if (!gp2a->wq) { ret = -ENOMEM; pr_err("%s: could not create workqueue\n", __func__); goto err_create_workqueue; } /* this is the thread function we run on the work queue */ INIT_WORK(&gp2a->work_light, gp2a_work_func_light); #ifdef GP2A_MODE_B /* this is the thread function we run on the work queue */ INIT_WORK(&gp2a->work_proximity, gp2a_work_func_proximity); #endif /* allocate lightsensor-level input_device */ input_dev = input_allocate_device(); if (!input_dev) { pr_err("%s: could not allocate input device\n", __func__); ret = -ENOMEM; goto err_input_allocate_device_light; } input_set_drvdata(input_dev, gp2a); input_dev->name = "light_sensor"; input_set_capability(input_dev, EV_REL, REL_MISC); gp2a_dbgmsg("registering lightsensor-level input device\n"); ret = input_register_device(input_dev); if (ret < 0) { pr_err("%s: could not register input device\n", __func__); input_free_device(input_dev); goto err_input_register_device_light; } gp2a->light_input_dev = input_dev; ret = sysfs_create_group(&input_dev->dev.kobj, &light_attribute_group); if (ret) { pr_err("%s: could not create sysfs group\n", __func__); goto err_sysfs_create_group_light; } /* alloc platform device for adc client */ pdev_gp2a_adc = platform_device_alloc("gp2a-adc", -1); if (!pdev_gp2a_adc) { pr_err("%s: could not allocation pdev_gp2a_adc.\n", __func__); ret = -ENOMEM; goto err_platform_allocate_device_adc; } /* Register adc client */ gp2a->padc = s3c_adc_register(pdev_gp2a_adc, NULL, NULL, 0); if (IS_ERR(gp2a->padc)) { dev_err(&pdev_gp2a_adc->dev, "cannot register adc\n"); ret = PTR_ERR(gp2a->padc); goto err_platform_register_device_adc; } /* set sysfs for light sensor */ ret = misc_register(&light_device); if (ret) pr_err(KERN_ERR "misc_register failed - light\n"); gp2a->lightsensor_class = class_create(THIS_MODULE, "lightsensor"); if (IS_ERR(gp2a->lightsensor_class)) pr_err("Failed to create class(lightsensor)!\n"); gp2a->switch_cmd_dev = device_create(gp2a->lightsensor_class, NULL, 0, NULL, "switch_cmd"); if (IS_ERR(gp2a->switch_cmd_dev)) pr_err("Failed to create device(switch_cmd_dev)!\n"); if (device_create_file(gp2a->switch_cmd_dev, &dev_attr_lightsensor_file_illuminance) < 0) pr_err("Failed to create device file(%s)!\n", dev_attr_lightsensor_file_illuminance.attr.name); dev_set_drvdata(gp2a->switch_cmd_dev, gp2a); /* new sysfs */ ret = sensors_register(gp2a->light_dev, gp2a, light_sensor_attrs, "light_sensor"); if (ret) { pr_err("%s: cound not register light sensor device(%d).\n", __func__, ret); goto out_light_sensor_register_failed; } ret = sensors_register(gp2a->proximity_dev, gp2a, proximity_sensor_attrs, "proximity_sensor"); if (ret) { pr_err("%s: cound not register proximity sensor device(%d).\n", __func__, ret); goto out_proximity_sensor_register_failed; } /* set initial proximity value as 1 */ gp2a->prox_value = 1; input_report_abs(gp2a->proximity_input_dev, ABS_DISTANCE, 1); input_sync(gp2a->proximity_input_dev); goto done; /* error, unwind it all */ out_light_sensor_register_failed: sensors_unregister(gp2a->light_dev); out_proximity_sensor_register_failed: sensors_unregister(gp2a->proximity_dev); err_sysfs_create_group_light: input_unregister_device(gp2a->light_input_dev); err_input_register_device_light: err_input_allocate_device_light: destroy_workqueue(gp2a->wq); err_platform_allocate_device_adc: platform_device_unregister(pdev_gp2a_adc); err_platform_register_device_adc: s3c_adc_release(gp2a->padc); err_create_workqueue: sysfs_remove_group(&gp2a->proximity_input_dev->dev.kobj, &proximity_attribute_group); err_sysfs_create_group_proximity: input_unregister_device(gp2a->proximity_input_dev); err_input_register_device_proximity: err_input_allocate_device_proximity: free_irq(gp2a->irq, 0); gpio_free(gp2a->pdata->p_out); err_setup_irq: mutex_destroy(&gp2a->adc_mutex); mutex_destroy(&gp2a->power_mutex); wake_lock_destroy(&gp2a->prx_wake_lock); kfree(gp2a); done: 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; gp2a_dbgmsg("start\n"); 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 to set 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); } /* start with interrupts disabled */ disable_irq(irq); gp2a->irq = irq; gp2a->val_state = 1; gp2a->power_state &= PROXIMITY_ENABLED; gp2a_dbgmsg("success\n"); value = 0x08; 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 = 0x18; gp2a_i2c_write(gp2a, REGS_CON, &value); 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 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; u8 value; #ifdef GP2AP002X_PROXIMITY_OFFSET int err; #endif 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->power_state & PROXIMITY_ENABLED) ? 1 : 0); if (new_value && !(gp2a->power_state & PROXIMITY_ENABLED)) { pr_info("%s, %d\n", __func__, __LINE__); #ifdef GP2AP002X_PROXIMITY_OFFSET pr_info("%s, %d GP2AP002X_PROXIMITY_OFFSET\n", __func__, __LINE__); err = gp2a_cal_mode_read_file(&gp2a->cal_mode); if (err < 0 && err != -ENOENT) pr_err("%s: cal_mode file read fail\n", __func__); pr_info("%s: mode = %02x\n", __func__, gp2a->cal_mode); if (gp2a->cal_mode == 2) { nondetect = PROX_NONDETECT_MODE2; detect = PROX_DETECT_MODE2; } else if (gp2a->cal_mode == 1) { nondetect = PROX_NONDETECT_MODE1; detect = PROX_DETECT_MODE1; } else { nondetect = PROX_NONDETECT; detect = PROX_DETECT; } #endif /* We send 1 for far status, 0 for close status */ gp2a->val_state = 1; input_report_abs(gp2a->proximity_input_dev, ABS_DISTANCE, gp2a->val_state); input_sync(gp2a->proximity_input_dev); gp2a->power_state |= PROXIMITY_ENABLED; msleep(20); value = 0x18; gp2a_i2c_write(gp2a, REGS_CON, &value); value = 0x08; 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); enable_irq_wake(gp2a->irq); value = 0x03; gp2a_i2c_write(gp2a, REGS_OPMOD, &value); enable_irq(gp2a->irq); value = 0x00; gp2a_i2c_write(gp2a, REGS_CON, &value); } else if (!new_value && (gp2a->power_state & PROXIMITY_ENABLED)) { pr_info("%s, %d\n", __func__, __LINE__); disable_irq_wake(gp2a->irq); disable_irq(gp2a->irq); value = 0x02; gp2a_i2c_write(gp2a, REGS_OPMOD, &value); gp2a->power_state &= ~PROXIMITY_ENABLED; } mutex_unlock(&gp2a->power_lock); return size; }