From 3dc6b43363b218e7d41787d9e9f28037ef5f2eb2 Mon Sep 17 00:00:00 2001 From: lyx Date: Wed, 2 Mar 2011 03:25:50 -0800 Subject: [PATCH] update l/p sensor isl29028 driver for phonesdk --- arch/arm/configs/rk29_phonesdk_defconfig | 2 +- arch/arm/mach-rk29/board-rk29-phonesdk.c | 2 +- drivers/input/misc/Kconfig | 4 +- drivers/input/misc/Makefile | 2 +- drivers/input/misc/isl29028.c | 577 ++++++++++++++--------- drivers/input/misc/isl29028.h | 14 +- 6 files changed, 373 insertions(+), 228 deletions(-) diff --git a/arch/arm/configs/rk29_phonesdk_defconfig b/arch/arm/configs/rk29_phonesdk_defconfig index 845152b37a8e..7e119811ff7c 100755 --- a/arch/arm/configs/rk29_phonesdk_defconfig +++ b/arch/arm/configs/rk29_phonesdk_defconfig @@ -810,7 +810,7 @@ CONFIG_EETI_EGALAX_MAX_Y=800 # CONFIG_EETI_EGALAX_DEBUG is not set # CONFIG_TOUCHSCREEN_IT7260 is not set CONFIG_INPUT_MISC=y -CONFIG_INPUT_PSENSOR_ISL29028=y +CONFIG_INPUT_LPSENSOR_ISL29028=y # CONFIG_INPUT_LPSENSOR_CM3602 is not set # CONFIG_INPUT_ATI_REMOTE is not set # CONFIG_INPUT_ATI_REMOTE2 is not set diff --git a/arch/arm/mach-rk29/board-rk29-phonesdk.c b/arch/arm/mach-rk29/board-rk29-phonesdk.c index 78f3d67b9c05..f83130c8f5c4 100755 --- a/arch/arm/mach-rk29/board-rk29-phonesdk.c +++ b/arch/arm/mach-rk29/board-rk29-phonesdk.c @@ -1342,7 +1342,7 @@ static struct i2c_board_info __initdata board_i2c0_devices[] = { .irq = RK29_PIN0_PA4, }, #endif -#if defined (CONFIG_INPUT_PSENSOR_ISL29028) +#if defined (CONFIG_INPUT_LPSENSOR_ISL29028) { .type = "isl29028", .addr = 0x44, diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index cb9da9f4fb02..4c5c7c04c014 100755 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -12,8 +12,8 @@ menuconfig INPUT_MISC if INPUT_MISC -config INPUT_PSENSOR_ISL29028 - tristate "isl29028 psensor input support" +config INPUT_LPSENSOR_ISL29028 + tristate "isl29028 l/p sensor input support" config INPUT_LPSENSOR_CM3602 tristate "l/p sensor input support" diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 6be5646544f3..9f40a5d77457 100755 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -5,7 +5,7 @@ # Each configuration option enables a list of files. obj-$(CONFIG_INPUT_LPSENSOR_CM3602) += capella_cm3602.o -obj-$(CONFIG_INPUT_PSENSOR_ISL29028) += isl29028.o +obj-$(CONFIG_INPUT_LPSENSOR_ISL29028) += isl29028.o obj-$(CONFIG_INPUT_APANEL) += apanel.o obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o diff --git a/drivers/input/misc/isl29028.c b/drivers/input/misc/isl29028.c index eed094dfe765..c0ea3c1492fc 100755 --- a/drivers/input/misc/isl29028.c +++ b/drivers/input/misc/isl29028.c @@ -56,6 +56,7 @@ #define ISL_REG_INT (0x02) #define PROX_FLAG_MASK ~(1 << 7) +#define LS_FLAG_MASK ~(1 << 3) #define PROX_PRST(x) (x << 5) #define ALS_PRST(x) (x << 1) #define INT_AND (1 << 0) @@ -67,15 +68,15 @@ #define PROX_HT (0xf0) #define ISL_REG_PROX_DATA (0x08) +#define ISL_REG_ALSIR_LDATA (0x09) +#define ISL_REG_ALSIR_HDATA (0x0a) struct isl29028_data { - struct input_dev *input_dev; + struct input_dev *psensor_input_dev; + struct input_dev *lsensor_input_dev; struct i2c_client *client; - struct workqueue_struct *wq; - struct work_struct work; - struct delayed_work d_work; - //struct completion completion; - //wait_queue_head_t wait; + struct delayed_work p_work; //for psensor + struct delayed_work l_work; //for light sensor int enabled; int irq; @@ -84,12 +85,6 @@ struct isl29028_data { #ifdef CONFIG_HAS_EARLYSUSPEND static struct early_suspend isl29028_early_suspend; #endif -static struct miscdevice isl29028_misc; - -static int misc_opened; -static int isl29028_open(struct inode *inode, struct file *file); -static int isl29028_release(struct inode *inode, struct file *file); -static long isl29028_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static int isl29028_read_reg(struct i2c_client *client, char reg, char *value) { @@ -142,21 +137,41 @@ static int isl29028_write_reg(struct i2c_client *client, char reg, char value) return 1; } -static irqreturn_t isl29028_irq_handler(int irq, void *data) +static void isl29028_psensor_work_handler(struct work_struct *work) +{ + struct isl29028_data *isl = (struct isl29028_data *)container_of(work, struct isl29028_data, p_work.work); + char reg, value, int_flag; + + reg = ISL_REG_INT; + isl29028_read_reg(isl->client, reg, (char *)&int_flag); + + if (!(int_flag >> 7)) { + input_report_abs(isl->psensor_input_dev, ABS_DISTANCE, 1); + input_sync(isl->psensor_input_dev); + } + + reg = ISL_REG_PROX_DATA; + isl29028_read_reg(isl->client, reg, (char *)&value); + //D("%s: int is %#x\n", __FUNCTION__, int_flag); + D("%s: prox_int is %d\n", __FUNCTION__, (int_flag >> 7 )); + D("%s: prox_data is %#x\n", __FUNCTION__, value); + + enable_irq(isl->irq); +} + +static irqreturn_t isl29028_psensor_irq_handler(int irq, void *data) { struct isl29028_data *isl = (struct isl29028_data *)data; - input_report_abs(isl->input_dev, ABS_DISTANCE, 0); - input_sync(isl->input_dev); + input_report_abs(isl->psensor_input_dev, ABS_DISTANCE, 0); + input_sync(isl->psensor_input_dev); disable_irq_nosync(isl->irq); - //queue_work(isl->wq, &isl->work); - schedule_delayed_work(&isl->d_work, msecs_to_jiffies(420)); - //wake_up_interruptible(&isl->wait); + schedule_delayed_work(&isl->p_work, msecs_to_jiffies(420)); return IRQ_HANDLED; } -static int isl29028_enable(struct i2c_client *client) +static int isl29028_psensor_enable(struct i2c_client *client) { char reg, value; int ret; @@ -165,26 +180,28 @@ static int isl29028_enable(struct i2c_client *client) reg = ISL_REG_CONFIG; ret = isl29028_read_reg(client, reg, &value); value |= PROX_EN; - value |= ALS_EN; /* ZMF */ ret = isl29028_write_reg(client, reg, value); - //schedule_delayed_work(&isl->d_work, msecs_to_jiffies(420)); - //enable_irq(isl->irq); #ifdef ISL_DBG ret = isl29028_read_reg(client, reg, &value); D("%s: configure reg value %#x ...\n", __FUNCTION__, value); #endif + + enable_irq(isl->irq); + return ret; } -static int isl29028_disable(struct i2c_client *client) +static int isl29028_psensor_disable(struct i2c_client *client) { char ret, reg, reg2, value, value2; struct isl29028_data *isl = (struct isl29028_data *)i2c_get_clientdata(client); + disable_irq(isl->irq); + cancel_delayed_work_sync(&isl->p_work); + reg = ISL_REG_CONFIG; ret = isl29028_read_reg(client, reg, &value); value &= ~PROX_EN; - value &= ~ALS_EN; /* ZMF */ ret = isl29028_write_reg(client, reg, value); reg2 = ISL_REG_INT; @@ -192,206 +209,298 @@ static int isl29028_disable(struct i2c_client *client) value2 &= PROX_FLAG_MASK; ret = isl29028_write_reg(client, reg2, value2); - disable_irq(isl->irq); - if (cancel_delayed_work_sync(&isl->d_work)) { - enable_irq(isl->irq); - } - enable_irq(isl->irq); - #ifdef ISL_DBG ret = isl29028_read_reg(client, reg, &value); ret = isl29028_read_reg(client, reg2, &value2); D("%s: configure reg value %#x ...\n", __FUNCTION__, value); D("%s: interrupt reg value %#x ...\n", __FUNCTION__, value2); #endif - //disable_irq(isl->irq); - //cancel_delayed_work_sync(&isl->d_work); return ret; } -#ifdef CONFIG_HAS_EARLYSUSPEND -static void isl29028_suspend(struct early_suspend *h) -{ - struct i2c_client *client = container_of(isl29028_misc.parent, struct i2c_client, dev); - D("isl29028 early suspend ========================= \n"); - isl29028_disable(client); -} +static int isl29028_psensor_open(struct inode *inode, struct file *file); +static int isl29028_psensor_release(struct inode *inode, struct file *file); +static long isl29028_psensor_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -static void isl29028_resume(struct early_suspend *h) -{ - struct i2c_client *client = container_of(isl29028_misc.parent, struct i2c_client, dev); - D("isl29028 early resume ======================== \n"); - isl29028_enable(client); +static int misc_ps_opened; +static struct file_operations isl29028_psensor_fops = { + .owner = THIS_MODULE, + .open = isl29028_psensor_open, + .release = isl29028_psensor_release, + .unlocked_ioctl = isl29028_psensor_ioctl +}; +static struct miscdevice isl29028_psensor_misc = { + .minor = MISC_DYNAMIC_MINOR, + .name = "psensor", + .fops = &isl29028_psensor_fops +}; + +static int isl29028_psensor_open(struct inode *inode, struct file *file) +{ + struct i2c_client *client = + container_of (isl29028_psensor_misc.parent, struct i2c_client, dev); + D("%s\n", __func__); + if (misc_ps_opened) + return -EBUSY; + misc_ps_opened = 1; + + return isl29028_psensor_enable(client); } -#else -#define isl29028_suspend NULL -#define isl29028_resume NULL -#endif +static int isl29028_psensor_release(struct inode *inode, struct file *file) +{ + struct i2c_client *client = + container_of (isl29028_psensor_misc.parent, struct i2c_client, dev); + D("%s\n", __func__); + misc_ps_opened = 0; + return isl29028_psensor_disable(client); +} -#if 0 -static void isl29028_work_handler(struct work_struct *work) +static long isl29028_psensor_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct isl29028_data *isl = container_of(work, struct isl29028_data, work); - char reg, value, int_flag; - //int als_data; - reg = ISL_REG_INT; - isl29028_read_reg(isl->client, reg, (char *)&int_flag); - - if (int_flag & (1 << 7)) { - reg = ISL_REG_PROX_DATA; - isl29028_read_reg(isl->client, reg, (char *)&value); - - D("\n%s: isl29028 prox_data is %#x\n", __FUNCTION__, value); - D("%s: isl29028 int_data is %#x\n", __FUNCTION__, int_flag); - - //input_report_abs(isl->input_dev, ABS_DISTANCE, 0); - //input_sync(isl->input_dev); - } - - if (!(int_flag & (1 << 7))) { - - reg = ISL_REG_PROX_DATA; - isl29028_read_reg(isl->client, reg, (char *)&value); - D("\n%s: isl29028 ................prox_data is %#x\n", __FUNCTION__, value); - D("%s: isl29028 ................int_data is %#x\n", __FUNCTION__, int_flag); - //input_report_abs(isl->input_dev, ABS_DISTANCE, 0); - //input_sync(isl->input_dev); - } - enable_irq(isl->irq); + char reg, val, enabled; + struct i2c_client *client = + container_of (isl29028_psensor_misc.parent, struct i2c_client, dev); + + D("%s cmd %d\n", __func__, _IOC_NR(cmd)); + switch (cmd) { + case PSENSOR_IOCTL_ENABLE: + if (get_user(val, (unsigned long __user *)arg)) + return -EFAULT; + if (val) + return isl29028_psensor_enable(client); + else + return isl29028_psensor_disable(client); + break; + case PSENSOR_IOCTL_GET_ENABLED: + reg = ISL_REG_CONFIG; + isl29028_read_reg(client, reg, &val); + enabled = (val & (1 << 7)) ? 1 : 0; + return put_user(enabled, (unsigned long __user *)arg); + break; + default: + pr_err("%s: invalid cmd %d\n", __func__, _IOC_NR(cmd)); + return -EINVAL; + } } -#endif -static void isl29028_dwork_handler(struct work_struct *work) +static int register_psensor_device(struct i2c_client *client, struct isl29028_data *isl) { - struct isl29028_data *isl = (struct isl29028_data *)container_of(work, struct isl29028_data, d_work.work); - char reg, value, int_flag; + struct input_dev *input_dev; + int rc; - reg = ISL_REG_INT; - isl29028_read_reg(isl->client, reg, (char *)&int_flag); + D("%s: allocating input device\n", __func__); + input_dev = input_allocate_device(); + if (!input_dev) { + dev_err(&client->dev,"%s: could not allocate input device for psensor\n", __FUNCTION__); + rc = -ENOMEM; + goto done; + } + + isl->psensor_input_dev = input_dev; + input_set_drvdata(input_dev, isl); - if (!(int_flag >> 7)) { - input_report_abs(isl->input_dev, ABS_DISTANCE, 1); - input_sync(isl->input_dev); + input_dev->name = "proximity"; + + set_bit(EV_ABS, input_dev->evbit); + input_set_abs_params(input_dev, ABS_DISTANCE, 0, 1, 0, 0); + + D("%s: registering input device\n", __func__); + rc = input_register_device(input_dev); + if (rc < 0) { + pr_err("%s: could not register input device for psensor\n", __func__); + goto err_free_input_device; } - reg = ISL_REG_PROX_DATA; - isl29028_read_reg(isl->client, reg, (char *)&value); - //D("%s: int is %#x\n", __FUNCTION__, int_flag); - D("%s: prox_int is %d\n", __FUNCTION__, (int_flag >> 7 )); - D("%s: prox_data is %#x\n", __FUNCTION__, value); + D("%s: registering misc device for psensor\n", __func__); + rc = misc_register(&isl29028_psensor_misc); + if (rc < 0) { + pr_err("%s: could not register misc device\n", __func__); + goto err_unregister_input_device; + } + + isl29028_psensor_misc.parent = &client->dev; + //misc_deregister(&isl29028_psensor_misc); + + INIT_DELAYED_WORK(&isl->p_work, isl29028_psensor_work_handler); - enable_irq(isl->irq); + rc = gpio_request(client->irq, "isl29028 irq"); + if (rc) { + pr_err("%s: request gpio %d failed \n", __func__, client->irq); + goto err_unregister_misc; + } + rc = gpio_direction_input(client->irq); + if (rc) { + pr_err("%s: failed set gpio input\n", __FUNCTION__); + } + + gpio_pull_updown(client->irq, GPIOPullUp); + isl->irq = gpio_to_irq(client->irq); + //mdelay(1); + rc = request_irq(isl->irq, isl29028_psensor_irq_handler, + IRQ_TYPE_LEVEL_LOW, client->name, (void *)isl); + if (rc < 0) { + dev_err(&client->dev,"request_irq failed for gpio %d (%d)\n", client->irq, rc); + goto err_free_gpio; + } + +err_free_gpio: + gpio_free(client->irq); +err_unregister_misc: + misc_deregister(&isl29028_psensor_misc); +err_unregister_input_device: + input_unregister_device(input_dev); +err_free_input_device: + input_free_device(input_dev); +done: + return rc; } -#if 0 -static int isl29028_thread(void *data) +static void unregister_psensor_device(struct i2c_client *client, struct isl29028_data *isl) { - char value, int_flag; - int als_data; - struct isl29028_data *isl = data; - DECLARE_WAITQUEUE(wait, current); - __add_wait_queue(&isl->wait, &wait); - __set_current_state(TASK_INTERRUPTIBLE); - complete(&isl->completion); - while (1) { + misc_deregister(&isl29028_psensor_misc); + input_unregister_device(isl->psensor_input_dev); + input_free_device(isl->psensor_input_dev); +} - schedule(); +#define LSENSOR_POLL_PROMESHUTOK 120 - if (signal_pending(current)) { - continue; - } +static int isl29028_lsensor_enable(struct i2c_client *client) +{ + char reg, value; + int ret; + struct isl29028_data *isl = (struct isl29028_data *)i2c_get_clientdata(client); - isl29028_read_reg(isl->client, 0x02, (char *)&int_flag); + reg = ISL_REG_CONFIG; + ret = isl29028_read_reg(client, reg, &value); + value |= ALS_EN; + ret = isl29028_write_reg(client, reg, value); + +#ifdef ISL_DBG + ret = isl29028_read_reg(client, reg, &value); + D("%s: configure reg value %#x ...\n", __FUNCTION__, value); +#endif - if (int_flag & (1 << 7)) { - isl29028_read_reg(isl->client, 0x08, (char *)&value); + schedule_delayed_work(&(isl->l_work), msecs_to_jiffies(LSENSOR_POLL_PROMESHUTOK)); - printk("%s: isl29028 prox_data is %#x\n", __FUNCTION__, value); + return ret; +} - //input_report_abs(isl->input_dev, ABS_DISTANCE, 0); - //input_sync(isl->input_dev); - } - if (int_flag & (1 << 3)) { - isl29028_read_reg(isl->client, 0x09, (char *)&value); - als_data = value; +static int isl29028_lsensor_disable(struct i2c_client *client) +{ + char ret, reg, reg2, value, value2; + struct isl29028_data *isl = (struct isl29028_data *)i2c_get_clientdata(client); - isl29028_read_reg(isl->client, 0x0a, (char *)&value); - als_data |= value << 8; + cancel_delayed_work_sync(&(isl->l_work)); - D("%s: isl29028 als_data is %#x\n", __FUNCTION__, als_data); - int_flag &= ~(1 << 3); - isl29028_write_reg(isl->client, 0x02, int_flag); - } + reg = ISL_REG_CONFIG; + ret = isl29028_read_reg(client, reg, &value); + value &= ~ALS_EN; + ret = isl29028_write_reg(client, reg, value); - enable_irq(isl->irq); - } + reg2 = ISL_REG_INT; + ret = isl29028_read_reg(client, reg2, &value2); + value2 &= LS_FLAG_MASK; + ret = isl29028_write_reg(client, reg2, value2); - remove_wait_queue(&isl->wait, &wait); - __set_current_state(TASK_RUNNING); +#ifdef ISL_DBG + ret = isl29028_read_reg(client, reg, &value); + ret = isl29028_read_reg(client, reg2, &value2); + D("%s: configure reg value %#x ...\n", __FUNCTION__, value); + D("%s: interrupt reg value %#x ...\n", __FUNCTION__, value2); +#endif - return 0; + return ret; } + +static void isl29028_lsensor_work_handler(struct work_struct *work) +{ + struct isl29028_data *isl = (struct isl29028_data *)container_of(work, struct isl29028_data, l_work.work); + char reg, l_value, h_value; + unsigned int als_value; + + reg = ISL_REG_ALSIR_LDATA; + isl29028_read_reg(isl->client, reg, (char *)&l_value); + + reg = ISL_REG_ALSIR_HDATA; + isl29028_read_reg(isl->client, reg, (char *)&h_value); + + als_value = h_value; + als_value = (als_value << 8) | l_value; + +#ifdef ISL_DBG + D("%s: als_data is %#x\n", __FUNCTION__, als_value); #endif + + input_report_abs(isl->lsensor_input_dev, ABS_MISC, als_value); + input_sync(isl->lsensor_input_dev); + + schedule_delayed_work(&(isl->l_work), msecs_to_jiffies(LSENSOR_POLL_PROMESHUTOK)); +} +static int isl29028_lsensor_open(struct inode *inode, struct file *file); +static int isl29028_lsensor_release(struct inode *inode, struct file *file); +static long isl29028_lsensor_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -static struct file_operations isl29028_fops = { +static int misc_ls_opened; +static struct file_operations isl29028_lsensor_fops = { .owner = THIS_MODULE, - .open = isl29028_open, - .release = isl29028_release, - .unlocked_ioctl = isl29028_ioctl + .open = isl29028_lsensor_open, + .release = isl29028_lsensor_release, + .unlocked_ioctl = isl29028_lsensor_ioctl }; -static struct miscdevice isl29028_misc = { +static struct miscdevice isl29028_lsensor_misc = { .minor = MISC_DYNAMIC_MINOR, - .name = "psensor", - .fops = &isl29028_fops + .name = "lightsensor", + .fops = &isl29028_lsensor_fops }; -static int isl29028_open(struct inode *inode, struct file *file) +static int isl29028_lsensor_open(struct inode *inode, struct file *file) { struct i2c_client *client = - container_of (isl29028_misc.parent, struct i2c_client, dev); + container_of (isl29028_lsensor_misc.parent, struct i2c_client, dev); D("%s\n", __func__); - if (misc_opened) + if (misc_ls_opened) return -EBUSY; - misc_opened = 1; + misc_ls_opened = 1; - return isl29028_enable(client); + return isl29028_lsensor_enable(client); } -static int isl29028_release(struct inode *inode, struct file *file) +static int isl29028_lsensor_release(struct inode *inode, struct file *file) { struct i2c_client *client = - container_of (isl29028_misc.parent, struct i2c_client, dev); + container_of (isl29028_lsensor_misc.parent, struct i2c_client, dev); D("%s\n", __func__); - misc_opened = 0; - return isl29028_disable(client); + misc_ls_opened = 0; + + return isl29028_lsensor_disable(client); } -static long isl29028_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long isl29028_lsensor_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { char reg, val, enabled; struct i2c_client *client = - container_of (isl29028_misc.parent, struct i2c_client, dev); + container_of (isl29028_lsensor_misc.parent, struct i2c_client, dev); D("%s cmd %d\n", __func__, _IOC_NR(cmd)); switch (cmd) { - case ISL29028_IOCTL_ENABLE: + case LIGHTSENSOR_IOCTL_ENABLE: if (get_user(val, (unsigned long __user *)arg)) return -EFAULT; if (val) - return isl29028_enable(client); + return isl29028_lsensor_enable(client); else - return isl29028_disable(client); + return isl29028_lsensor_disable(client); break; - case ISL29028_IOCTL_GET_ENABLED: + case LIGHTSENSOR_IOCTL_GET_ENABLED: reg = ISL_REG_CONFIG; isl29028_read_reg(client, reg, &val); - enabled = (val & ~(1 << 7)) ? 1 : 0; + enabled = (val & (1 << 2)) ? 1 : 0; return put_user(enabled, (unsigned long __user *)arg); break; default: @@ -400,7 +509,63 @@ static long isl29028_ioctl(struct file *file, unsigned int cmd, unsigned long ar } } -static void isl29028_config(struct i2c_client *client) +static int register_lsensor_device(struct i2c_client *client, struct isl29028_data *isl) +{ + struct input_dev *input_dev; + int rc; + + D("%s: allocating input device\n", __func__); + input_dev = input_allocate_device(); + if (!input_dev) { + dev_err(&client->dev,"%s: could not allocate input device forlsensor\n", __FUNCTION__); + rc = -ENOMEM; + goto done; + } + + isl->lsensor_input_dev = input_dev; + input_set_drvdata(input_dev, isl); + + input_dev->name = "lightsensor-level"; + + set_bit(EV_ABS, input_dev->evbit); + input_set_abs_params(input_dev, ABS_MISC, 0, 10, 0, 0); + + D("%s: registering input device\n", __func__); + rc = input_register_device(input_dev); + if (rc < 0) { + pr_err("%s: could not register input device for lsensor\n", __func__); + goto err_free_input_device; + } + + D("%s: registering misc device for lsensor\n", __func__); + rc = misc_register(&isl29028_lsensor_misc); + if (rc < 0) { + pr_err("%s: could not register misc device\n", __func__); + goto err_unregister_input_device; + } + + isl29028_lsensor_misc.parent = &client->dev; + + INIT_DELAYED_WORK(&isl->l_work, isl29028_lsensor_work_handler); + + return 0; + +err_unregister_input_device: + input_unregister_device(input_dev); +err_free_input_device: + input_free_device(input_dev); +done: + return rc; +} + +static void unregister_lsensor_device(struct i2c_client *client, struct isl29028_data *isl) +{ + misc_deregister(&isl29028_lsensor_misc); + input_unregister_device(isl->lsensor_input_dev); + input_free_device(isl->lsensor_input_dev); +} + +static int isl29028_config(struct i2c_client *client) { int ret; char value, buf[2]; @@ -425,8 +590,13 @@ static void isl29028_config(struct i2c_client *client) if ((ret = i2c_master_send(client, buf, 2)) < 2) { printk("%s: config isl29028 register %#x err %d\n", __FUNCTION__, buf[0], ret); } + + if (ret < 2) + return -1; + mdelay(2); - /*************************************************/ + + /***********************config**************************/ buf[0] = ISL_REG_CONFIG; buf[1] = /*PROX_EN | */PROX_SLP(4) | PROX_DR_220 /*| ALS_EN | ALS_RANGE_L*/; @@ -467,13 +637,34 @@ static void isl29028_config(struct i2c_client *client) isl29028_read_reg(client, 0x04, &value); printk("%s: config isl29028 PROX_HT(0x04) reg %#x \n", __FUNCTION__, value); #endif + + return 0; +} + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void isl29028_suspend(struct early_suspend *h) +{ + struct i2c_client *client = container_of(isl29028_psensor_misc.parent, struct i2c_client, dev); + D("isl29028 early suspend ========================= \n"); + isl29028_psensor_disable(client); + isl29028_lsensor_disable(client); } +static void isl29028_resume(struct early_suspend *h) +{ + struct i2c_client *client = container_of(isl29028_psensor_misc.parent, struct i2c_client, dev); + D("isl29028 early resume ======================== \n"); + isl29028_psensor_enable(client); + isl29028_lsensor_enable(client); +} +#else +#define isl29028_suspend NULL +#define isl29028_resume NULL +#endif static int isl29028_probe(struct i2c_client *client, const struct i2c_device_id *id) { int rc = -EIO; - struct input_dev *input_dev; struct isl29028_data *isl; D("\n%s: isl29028 i2c client probe\n\n", __func__); @@ -488,69 +679,20 @@ static int isl29028_probe(struct i2c_client *client, const struct i2c_device_id isl->client = client; i2c_set_clientdata(client, isl); - - D("%s: allocating input device\n", __func__); - input_dev = input_allocate_device(); - if (!input_dev) { - dev_err(&client->dev,"%s: could not allocate input device\n", __FUNCTION__); - rc = -ENOMEM; - goto done; - } - isl->input_dev = input_dev; - input_set_drvdata(input_dev, isl); - - input_dev->name = "proximity"; - - set_bit(EV_ABS, input_dev->evbit); - input_set_abs_params(input_dev, ABS_DISTANCE, 0, 1, 0, 0); - - D("%s: registering input device\n", __func__); - rc = input_register_device(input_dev); - if (rc < 0) { - pr_err("%s: could not register input device\n", __func__); - goto err_free_input_device; - } - - D("%s: registering misc device\n", __func__); - rc = misc_register(&isl29028_misc); - if (rc < 0) { - pr_err("%s: could not register misc device\n", __func__); - goto err_unregister_input_device; - } - - isl29028_misc.parent = &client->dev; - misc_deregister(&isl29028_misc); - - //isl->wq = create_freezeable_workqueue("isl29028_wq"); - //INIT_WORK(&isl->work, isl29028_work_handler); - INIT_DELAYED_WORK(&isl->d_work, isl29028_dwork_handler); - - rc = gpio_request(client->irq, "isl29028 irq"); + rc = register_psensor_device(client, isl); if (rc) { - pr_err("%s: request gpio %d failed \n", __func__, client->irq); - return rc; + goto err_free_mem; } - rc = gpio_direction_input(client->irq); + rc = register_lsensor_device(client, isl); if (rc) { - pr_err("%s: failed set gpio input\n", __FUNCTION__); + goto unregister_device1; } - gpio_pull_updown(client->irq, GPIOPullUp); - isl->irq = gpio_to_irq(client->irq); - mdelay(1); - rc = request_irq(isl->irq, isl29028_irq_handler, - IRQ_TYPE_LEVEL_LOW, client->name, (void *)isl); - if (rc < 0) { - dev_err(&client->dev,"request_irq failed for gpio %d (%d)\n", client->irq, rc); - goto err_unregister_input_device; + rc = isl29028_config(client); + if (rc) { + goto unregister_device2; } - //init_completion(&isl->completion); - //init_waitqueue_head(&isl->wait); - //kernel_thread(isl29028_thread, (void*)isl, CLONE_FILES | CLONE_SIGHAND | CLONE_FS); - //wait_for_completion(&isl->completion); - isl29028_config(client); - #ifdef CONFIG_HAS_EARLYSUSPEND isl29028_early_suspend.suspend = isl29028_suspend; isl29028_early_suspend.resume = isl29028_resume; @@ -558,11 +700,12 @@ static int isl29028_probe(struct i2c_client *client, const struct i2c_device_id register_early_suspend(&isl29028_early_suspend); #endif -err_unregister_input_device: - input_unregister_device(input_dev); - goto done; -err_free_input_device: - input_free_device(input_dev); +unregister_device2: + unregister_lsensor_device(client, isl); +unregister_device1: + unregister_psensor_device(client, isl); +err_free_mem: + kfree(isl); done: return rc; } @@ -571,10 +714,8 @@ static int isl29028_remove(struct i2c_client *client) { struct isl29028_data *isl29028 = i2c_get_clientdata(client); - misc_deregister(&isl29028_misc); - input_unregister_device(isl29028->input_dev); - input_free_device(isl29028->input_dev); - free_irq(client->irq, isl29028); + unregister_lsensor_device(client, isl29028); + unregister_psensor_device(client, isl29028); kfree(isl29028); #ifdef CONFIG_HAS_EARLYSUSPEND unregister_early_suspend(&isl29028_early_suspend); diff --git a/drivers/input/misc/isl29028.h b/drivers/input/misc/isl29028.h index 236379353fd7..58f64120b1f4 100755 --- a/drivers/input/misc/isl29028.h +++ b/drivers/input/misc/isl29028.h @@ -20,10 +20,14 @@ #include #include -#define ISL29028_IOCTL_MAGIC 'c' -#define ISL29028_IOCTL_GET_ENABLED \ - _IOR(ISL29028_IOCTL_MAGIC, 1, int *) -#define ISL29028_IOCTL_ENABLE \ - _IOW(ISL29028_IOCTL_MAGIC, 2, int *) +#define PSENSOR_IOCTL_MAGIC 'c' +#define PSENSOR_IOCTL_GET_ENABLED \ + _IOR(PSENSOR_IOCTL_MAGIC, 1, int *) +#define PSENSOR_IOCTL_ENABLE \ + _IOW(PSENSOR_IOCTL_MAGIC, 2, int *) + +#define LIGHTSENSOR_IOCTL_MAGIC 'l' +#define LIGHTSENSOR_IOCTL_GET_ENABLED _IOR(LIGHTSENSOR_IOCTL_MAGIC, 1, int *) +#define LIGHTSENSOR_IOCTL_ENABLE _IOW(LIGHTSENSOR_IOCTL_MAGIC, 2, int *) #endif -- 2.34.1