2 * Copyright (C) 2011 Sony Ericsson Mobile Communications Inc.
4 * Author: Courtney Cavin <courtney.cavin@sonyericsson.com>
5 * Prepared for up-stream by: Oskar Andero <oskar.andero@sonyericsson.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2, as
9 * published by the Free Software Foundation.
12 #include <linux/i2c.h>
13 #include <linux/irq.h>
15 #include <linux/uaccess.h>
16 #include <linux/slab.h>
17 #include <linux/input.h>
18 #include <linux/module.h>
19 #include <linux/interrupt.h>
20 #include <linux/gpio.h>
21 #include <linux/delay.h>
22 #include <linux/gp2ap002a00f.h>
23 #include <linux/sensors_core.h>
25 static struct device *proximity_sensor_device = NULL;
27 #define OFFSET_FILE_PATH "/efs/prox_cal"
30 #define PROX_NONDETECT 0x2F
31 #define PROX_DETECT 0x0C
33 #define PROX_NONDETECT_MODE1 0x43
34 #define PROX_DETECT_MODE1 0x28
36 #define PROX_NONDETECT_MODE2 0x48
37 #define PROX_DETECT_MODE2 0x42
40 struct input_dev *input;
41 const struct gp2a_platform_data *pdata;
42 struct i2c_client *i2c_client;
43 int proximity_enabled;
59 GP2A_ADDR_CYCLE = 0x3,
60 GP2A_ADDR_OPMOD = 0x4,
65 /* Software Shutdown control: 0 = shutdown, 1 = normal operation */
69 static int gp2a_report(struct gp2a_data *dt)
71 int vo = gpio_get_value(dt->pdata->vout_gpio);
75 input_report_switch(dt->input, SW_FRONT_PROXIMITY, vo);
76 input_sync(dt->input);
81 static irqreturn_t gp2a_irq(int irq, void *handle)
83 struct gp2a_data *dt = handle;
85 printk(KERN_EMERG"Proximity Interrupts ::%d\n",irq);
92 static int gp2a_enable(struct gp2a_data *dt)
94 return i2c_smbus_write_byte_data(dt->i2c_client, GP2A_ADDR_OPMOD,
98 static int gp2a_disable(struct gp2a_data *dt)
100 return i2c_smbus_write_byte_data(dt->i2c_client, GP2A_ADDR_OPMOD,
105 /*Only One Read Only register, so word address need not be specified (from Data Sheet)*/
106 static int gp2a_i2c_read(u8 reg, u8 *value,struct gp2a_data *gp2a_cal_data)
111 struct i2c_msg msg[1];
115 /*first byte read(buf[0]) is dummy read*/
116 msg[0].addr = gp2a_cal_data->i2c_client->addr;
117 msg[0].flags = I2C_M_RD;
120 count = i2c_transfer(gp2a_cal_data->i2c_client->adapter, msg, 1);
128 *value = buf[0] << 8 | buf[1];
134 static int gp2a_i2c_write( u8 reg, u8 *value,struct gp2a_data *gp2a_cal_data)
138 struct i2c_msg msg[1];
141 printk(KERN_INFO "[GP2A] %s : start \n", __func__);
143 if( (gp2a_cal_data->i2c_client == NULL) || (!gp2a_cal_data->i2c_client->adapter) ){
150 msg[0].addr = gp2a_cal_data->i2c_client->addr;
154 count = i2c_transfer(gp2a_cal_data->i2c_client->adapter,msg,1);
160 printk(KERN_INFO "[GP2A] %s : stop \n", __func__);
165 static ssize_t proximity_enable_show(struct device *dev,
166 struct device_attribute *attr, char *buf)
168 struct gp2a_data *dt = dev_get_drvdata(dev);
170 pr_info("%s, %d \n", __func__, __LINE__);
171 return snprintf(buf, PAGE_SIZE, "%d\n", dt->proximity_enabled);
174 static ssize_t proximity_value_show(struct device *dev,
175 struct device_attribute *attr, char *buf)
177 struct gp2a_data *dt = dev_get_drvdata(dev);
179 pr_info("%s, %d \n", __func__, __LINE__);
181 return snprintf(buf, PAGE_SIZE, "%d\n", dt->value);
184 static ssize_t proximity_enable_store(struct device *dev,
185 struct device_attribute *attr, const char *buf, size_t count)
187 struct gp2a_data *dt = dev_get_drvdata(dev);
189 unsigned long value = 0;
192 err = strict_strtoul(buf, 10, &value);
194 pr_err("%s, kstrtoint failed.", __func__);
196 if (value != 0 && value != 1)
199 printk(KERN_ALERT"%s :: Request for State(%d->%d)\n",__func__,dt->proximity_enabled,value);
201 //check for multiple times disable and enable sensor
202 if (dt->proximity_enabled && !value) { /* Prox power off */
204 disable_irq(dt->irq);
208 if (dt->pdata->hw_pwr)
209 dt->pdata->hw_pwr(false);
211 dt->proximity_enabled = 0;
213 if (!dt->proximity_enabled && value) { /* prox power on */
215 if (dt->pdata->hw_pwr)
216 dt->pdata->hw_pwr(true);
223 dt->proximity_enabled = 1;
231 static int __init gp2a_initialize(struct gp2a_data *dt)
235 error = i2c_smbus_write_byte_data(dt->i2c_client, GP2A_ADDR_GAIN,
240 error = i2c_smbus_write_byte_data(dt->i2c_client, GP2A_ADDR_HYS,
245 error = i2c_smbus_write_byte_data(dt->i2c_client, GP2A_ADDR_CYCLE,
250 error = gp2a_disable(dt);
255 static int gp2a_prox_offset(unsigned char vout,struct gp2a_data *gp2a_cal_data)
260 printk(KERN_INFO "[GP2A] %s called\n", __func__);
262 /* Write HYS Register */
264 reg_value = nondetect;
268 if((ret=gp2a_i2c_write(GP2A_ADDR_HYS/*0x02*/,®_value,gp2a_cal_data))<0)
269 printk(KERN_INFO "[GP2A]gp2a_i2c_write 2 failed\n", __func__);
274 static int gp2a_prox_cal_mode(char mode,struct gp2a_data *gp2a_cal_data)
279 printk(KERN_INFO "[GP2A] %s : start \n", __func__);
283 nondetect = PROX_NONDETECT_MODE1;
284 detect = PROX_DETECT_MODE1;
288 nondetect = PROX_NONDETECT_MODE2;
289 detect = PROX_DETECT_MODE2;
293 nondetect = PROX_NONDETECT;
294 detect = PROX_DETECT;
299 if((ret=gp2a_i2c_write(GP2A_ADDR_GAIN/*0x01*/,®_value,gp2a_cal_data))<0)
300 printk(KERN_INFO "[GP2A]gp2a_i2c_write 1 failed\n", __func__);
302 gp2a_prox_offset(0,gp2a_cal_data);
305 if((ret=gp2a_i2c_write(GP2A_ADDR_CYCLE/*0x03*/,®_value,gp2a_cal_data))<0)
306 printk(KERN_INFO "[GP2A]gp2a_i2c_write 2 failed\n", __func__);
309 if((ret=gp2a_i2c_write(GP2A_ADDR_OPMOD,®_value,gp2a_cal_data))<0)
310 printk(KERN_INFO "[GP2A]gp2a_i2c_write 3 failed\n", __func__);
313 if((ret=gp2a_i2c_write(GP2A_ADDR_CON,®_value,gp2a_cal_data))<0)
314 printk(KERN_INFO "[GP2A]gp2a_i2c_write 4 failed\n", __func__);
316 printk(KERN_INFO "[GP2A] %s : stop \n", __func__);
322 static int gp2a_cal_mode_read_file(char *mode,struct gp2a_data *gp2a_cal_data)
326 struct file *cal_mode_filp = NULL;
331 cal_mode_filp = filp_open(OFFSET_FILE_PATH, O_RDONLY, 0666);
332 if (IS_ERR(cal_mode_filp)) {
333 printk(KERN_INFO "[GP2A] %s: no cal_mode file\n", __func__);
334 err = PTR_ERR(cal_mode_filp);
336 pr_err("[GP2A] %s: Can't open cal_mode file\n", __func__);
340 err = cal_mode_filp->f_op->read(cal_mode_filp, mode, sizeof(u8), &cal_mode_filp->f_pos);
342 if (err != sizeof(u8)) {
343 pr_err("%s: Can't read the cal_mode from file\n", __func__);
344 filp_close(cal_mode_filp, current->files);
349 filp_close(cal_mode_filp, current->files);
355 static int gp2a_cal_mode_save_file(char mode,struct gp2a_data *gp2a_cal_data)
357 struct file *cal_mode_filp = NULL;
361 printk(KERN_INFO "[GP2A] %s : start \n", __func__);
363 gp2a_prox_cal_mode(mode,gp2a_cal_data);
368 cal_mode_filp = filp_open(OFFSET_FILE_PATH, O_CREAT | O_TRUNC | O_WRONLY | O_SYNC, 0666);
369 if (IS_ERR(cal_mode_filp))
371 pr_err("%s: Can't open cal_mode file\n", __func__);
373 err = PTR_ERR(cal_mode_filp);
374 pr_err("%s: err = %d\n", __func__, err);
378 err = cal_mode_filp->f_op->write(cal_mode_filp, (char *)&mode, sizeof(u8), &cal_mode_filp->f_pos);
379 if (err != sizeof(u8)) {
380 pr_err("%s: Can't read the cal_mode from file\n", __func__);
383 printk(KERN_INFO "[GP2A] %s : stop \n", __func__);
385 filp_close(cal_mode_filp, current->files);
390 static ssize_t proximity_cal_show(struct device *dev, struct device_attribute *attr, char *buf)
394 struct gp2a_data *gp2a_cal_data=dev_get_drvdata(dev);
397 result = gp2a_cal_data->cal_mode;
398 printk(KERN_INFO "[GP2A] prox_cal_read = %d\n", result);
400 return sprintf(buf, "%d\n", result);
403 static ssize_t proximity_cal_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
405 struct gp2a_data *gp2a_cal_data=dev_get_drvdata(dev);
407 if (sysfs_streq(buf, "1"))
408 gp2a_cal_data->cal_mode = 1;
409 else if (sysfs_streq(buf, "2"))
410 gp2a_cal_data->cal_mode = 2;
411 else if (sysfs_streq(buf, "0"))
412 gp2a_cal_data->cal_mode = 0;
414 pr_err("[GP2A] %s: invalid value %d\n", __func__, *buf);
418 printk(KERN_INFO "[GP2A] prox_cal_write =%d\n", gp2a_cal_data->cal_mode);
420 gp2a_cal_mode_save_file(gp2a_cal_data->cal_mode,gp2a_cal_data);
426 static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR,
427 proximity_enable_show, proximity_enable_store);
429 static DEVICE_ATTR(value, S_IRUGO | S_IWUSR | S_IWGRP,
430 proximity_value_show, NULL);
432 static DEVICE_ATTR(prox_cal, S_IRUGO | S_IWUSR |S_IWGRP|S_IWOTH, proximity_cal_show, proximity_cal_store);
434 static struct attribute *gp2a_attrs[] = {
435 &dev_attr_enable.attr,
439 static struct attribute_group gp2a_attribute_group = {
443 static struct device_attribute *proximity_sensor_attr[] = {
452 static int __init gp2a_probe(struct i2c_client *client,
453 const struct i2c_device_id *id)
455 const struct gp2a_platform_data *pdata = client->dev.platform_data;
456 struct gp2a_data *dt;
462 if (pdata->hw_setup) {
463 error = pdata->hw_setup(client);
468 error = gpio_request_one(pdata->vout_gpio, GPIOF_IN, GP2A_I2C_NAME);
470 goto err_hw_shutdown;
472 dt = kzalloc(sizeof(struct gp2a_data), GFP_KERNEL);
479 dt->i2c_client = client;
481 error = gp2a_initialize(dt);
485 dt->input = input_allocate_device();
491 input_set_drvdata(dt->input, dt);
493 // dt->input->open = gp2a_device_open;
494 // dt->input->close = gp2a_device_close;
495 dt->input->name = GP2A_I2C_NAME;
496 dt->input->id.bustype = BUS_I2C;
497 dt->input->dev.parent = &client->dev;
498 dt->proximity_enabled = 0;
499 dt->irq = client->irq;
502 input_set_capability(dt->input, EV_SW, SW_FRONT_PROXIMITY);
504 error = request_threaded_irq(client->irq, NULL, gp2a_irq,
505 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
506 IRQF_ONESHOT | IRQF_NO_SUSPEND ,
509 dev_err(&client->dev, "irq request failed\n");
510 goto err_free_input_dev;
513 error = input_register_device(dt->input);
515 dev_err(&client->dev, "device registration failed\n");
519 error = sysfs_create_group(&dt->input->dev.kobj, &gp2a_attribute_group);
521 dev_err(&client->dev, "sysfs create failed\n");
522 goto err_unregister_input;
525 device_init_wakeup(&client->dev, pdata->wakeup);
526 i2c_set_clientdata(client, dt);
527 dev_set_drvdata(&client->dev, dt);
529 error = sensors_register(&proximity_sensor_device, dt,proximity_sensor_attr, "proximity_sensor");
533 pr_err("%s: could not register""proximity sensor device(%d).\n",__func__, error);
534 goto err_unregister_input;
536 disable_irq(client->irq);
538 if (dt->pdata->hw_pwr)
540 dt->pdata->hw_pwr(false);
541 printk(KERN_ALERT"%s :: chip power down\n",__func__);
545 err_unregister_input:
546 input_unregister_device(dt->input);
548 free_irq(client->irq, dt);
550 input_free_device(dt->input);
554 gpio_free(pdata->vout_gpio);
556 if (pdata->hw_shutdown)
557 pdata->hw_shutdown(client);
559 pdata->hw_pwr(false);
563 static int __exit gp2a_remove(struct i2c_client *client)
565 struct gp2a_data *dt = i2c_get_clientdata(client);
566 const struct gp2a_platform_data *pdata = dt->pdata;
568 device_init_wakeup(&client->dev, false);
570 free_irq(client->irq, dt);
572 sensors_unregister(proximity_sensor_device, proximity_sensor_attr);
573 input_unregister_device(dt->input);
576 gpio_free(pdata->vout_gpio);
578 if (pdata->hw_shutdown)
579 pdata->hw_shutdown(client);
582 pdata->hw_pwr(false);
587 #ifdef CONFIG_PM_SLEEP
588 static int gp2a_suspend(struct device *dev)
590 struct i2c_client *client = to_i2c_client(dev);
591 struct gp2a_data *dt = i2c_get_clientdata(client);
593 printk(KERN_ALERT"%s\n",__func__);
594 if (device_may_wakeup(&client->dev)) {
595 enable_irq_wake(client->irq);
597 mutex_lock(&dt->input->mutex);
598 if (dt->input->users)
599 retval = gp2a_disable(dt);
600 mutex_unlock(&dt->input->mutex);
606 static int gp2a_resume(struct device *dev)
608 struct i2c_client *client = to_i2c_client(dev);
609 struct gp2a_data *dt = i2c_get_clientdata(client);
611 printk(KERN_ALERT"%s\n",__func__);
612 if (device_may_wakeup(&client->dev)) {
613 disable_irq_wake(client->irq);
615 mutex_lock(&dt->input->mutex);
616 if (dt->input->users)
617 retval = gp2a_enable(dt);
618 mutex_unlock(&dt->input->mutex);
625 static SIMPLE_DEV_PM_OPS(gp2a_pm, gp2a_suspend, gp2a_resume);
627 static const struct i2c_device_id gp2a_i2c_id[] = {
628 { GP2A_I2C_NAME, 0 },
632 static struct i2c_driver gp2a_i2c_driver = {
634 .name = GP2A_I2C_NAME,
635 .owner = THIS_MODULE,
639 .remove = gp2a_remove,
640 .id_table = gp2a_i2c_id,
643 module_i2c_driver(gp2a_i2c_driver);
645 MODULE_AUTHOR("Courtney Cavin <courtney.cavin@sonyericsson.com>");
646 MODULE_DESCRIPTION("Sharp GP2AP002A00F I2C Proximity/Opto sensor driver");
647 MODULE_LICENSE("GPL v2");