From 85d67b7c203f1351c42797cd6ca54b08d1cb63b0 Mon Sep 17 00:00:00 2001 From: Chris Lahaye Date: Tue, 10 Nov 2020 15:06:44 +0300 Subject: [PATCH] pocket: Introduce pocket judge This driver maintains a sysfs interface used by the pocket bridge system service. It enables and disables interrupts based on pocket state to optimize battery consumption in-pocket. Ticket: NOUGAT-49 Change-Id: I75e8cbb38d780c77767e21667092a94c70df5cbf Signed-off-by: Chris Lahaye --- drivers/input/Makefile | 2 +- drivers/input/fingerprint/fpc/fpc1020_tee.c | 54 +++++++++-- drivers/input/fingerprint/fpc/fpc1020_tee.h | 6 ++ drivers/input/pocket-judge.c | 96 +++++++++++++++++++ .../touchscreen/synaptics_driver_s3320.c | 12 +++ .../touchscreen/synaptics_driver_s3320.h | 17 ++++ 6 files changed, 179 insertions(+), 8 deletions(-) create mode 100644 drivers/input/fingerprint/fpc/fpc1020_tee.h create mode 100644 drivers/input/pocket-judge.c create mode 100644 drivers/input/touchscreen/synaptics_driver_s3320.h diff --git a/drivers/input/Makefile b/drivers/input/Makefile index 0e81f77ea1a5..79a961ed1310 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile @@ -4,7 +4,7 @@ # Each configuration option enables a list of files. -obj-$(CONFIG_INPUT) += input-core.o +obj-$(CONFIG_INPUT) += input-core.o pocket-judge.o input-core-y := input.o input-compat.o input-mt.o ff-core.o obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o diff --git a/drivers/input/fingerprint/fpc/fpc1020_tee.c b/drivers/input/fingerprint/fpc/fpc1020_tee.c index 675c5bc446e5..b15691a92aee 100644 --- a/drivers/input/fingerprint/fpc/fpc1020_tee.c +++ b/drivers/input/fingerprint/fpc/fpc1020_tee.c @@ -29,7 +29,7 @@ * modify it under the terms of the GNU General Public License Version 2 * as published by the Free Software Foundation. */ - +#include "fpc1020_tee.h" #include #include #include @@ -72,9 +72,11 @@ struct fpc1020_data { struct device *dev; struct wake_lock ttw_wl; int irq_gpio; + atomic_t irq_enable; int rst_gpio; int irq_num; struct mutex lock; + spinlock_t spinlock; bool prepared; struct pinctrl *ts_pinctrl; @@ -101,6 +103,8 @@ struct fpc1020_data { struct completion irq_sent; }; +static struct fpc1020_data *fpc1020_g = NULL; + static int fpc1020_request_named_gpio(struct fpc1020_data *fpc1020, const char *label, int *gpio) { @@ -553,6 +557,26 @@ static irqreturn_t fpc1020_irq_handler(int irq, void *handle) return IRQ_HANDLED; } +static void fpc1020_enable(struct fpc1020_data *fpc1020) +{ + if(0 == atomic_read(&fpc1020->irq_enable)) + { + if(fpc1020->irq_gpio) + enable_irq(gpio_to_irq(fpc1020->irq_gpio)); + atomic_set(&fpc1020->irq_enable,1); + } +} + +static void fpc1020_disable(struct fpc1020_data *fpc1020) +{ + if(1 == atomic_read(&fpc1020->irq_enable)) + { + if(fpc1020->irq_gpio) + disable_irq_nosync(gpio_to_irq(fpc1020->irq_gpio)); + atomic_set(&fpc1020->irq_enable,0); + } +} + static int fpc1020_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -597,7 +621,7 @@ static int fpc1020_probe(struct platform_device *pdev) goto exit; rc = gpio_direction_input(fpc1020->irq_gpio); - + if (rc) { dev_err(fpc1020->dev, "gpio_direction_input (irq) failed.\n"); @@ -625,7 +649,7 @@ static int fpc1020_probe(struct platform_device *pdev) rc = fpc1020_pinctrl_select(fpc1020, true); if (rc) goto exit; - + #endif rc = fpc1020_input_init(fpc1020); if (rc) @@ -655,6 +679,7 @@ static int fpc1020_probe(struct platform_device *pdev) gpio_to_irq(fpc1020->irq_gpio)); goto exit; } + atomic_set(&fpc1020->irq_enable,1); dev_info(dev, "requested irq %d\n", gpio_to_irq(fpc1020->irq_gpio)); /* Request that the interrupt should not be wakeable */ @@ -669,7 +694,7 @@ static int fpc1020_probe(struct platform_device *pdev) dev_err(dev, "could not create sysfs\n"); goto exit; } - + #if 0 //changhua remove HW reset here,move to HAL,after spi cs pin become high rc = gpio_direction_output(fpc1020->rst_gpio, 1); @@ -681,10 +706,10 @@ static int fpc1020_probe(struct platform_device *pdev) gpio_set_value(fpc1020->rst_gpio, 1); udelay(FPC1020_RESET_HIGH1_US); - + gpio_set_value(fpc1020->rst_gpio, 0); udelay(FPC1020_RESET_LOW_US); - + gpio_set_value(fpc1020->rst_gpio, 1); udelay(FPC1020_RESET_HIGH2_US); #endif @@ -702,13 +727,28 @@ static int fpc1020_probe(struct platform_device *pdev) *fingerchip/ * qtech 0 1 0 * Goodix 1 0 1 - * + * */ + fpc1020_g = fpc1020; dev_info(dev, "%s: ok\n", __func__); exit: return rc; } +void fpc1020_enable_global(bool enabled) +{ + if (fpc1020_g == NULL) + return; + + spin_lock(&fpc1020_g->spinlock); + + if (enabled) + fpc1020_enable(fpc1020_g); + else + fpc1020_disable(fpc1020_g); + + spin_unlock(&fpc1020_g->spinlock); +} static struct of_device_id fpc1020_of_match[] = { { .compatible = "fpc,fpc1020", }, diff --git a/drivers/input/fingerprint/fpc/fpc1020_tee.h b/drivers/input/fingerprint/fpc/fpc1020_tee.h new file mode 100644 index 000000000000..299b59992868 --- /dev/null +++ b/drivers/input/fingerprint/fpc/fpc1020_tee.h @@ -0,0 +1,6 @@ +#ifndef _FPC1020_TEE_H +#define _FPC1020_TEE_H + +void fpc1020_enable_global(_Bool enabled); + +#endif diff --git a/drivers/input/pocket-judge.c b/drivers/input/pocket-judge.c new file mode 100644 index 000000000000..3677b055dbc0 --- /dev/null +++ b/drivers/input/pocket-judge.c @@ -0,0 +1,96 @@ +/* + * Copyright 2017 Paranoid Android + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#include +#include +#include +#include +#include + +#include "touchscreen/synaptics_driver_s3320.h" +#include "fingerprint/fpc/fpc1020_tee.h" + +/** + * This driver maintains a sysfs interface used by the pocket bridge system + * service. It enables and disables interrupts based on pocket state to + * optimize battery consumption in-pocket. + * + * @author Chris Lahaye + * @hide + */ + +static bool pocket_judge_inpocket = false; +EXPORT_SYMBOL(pocket_judge_inpocket); + +static void pocket_judge_update(void) +{ + synaptics_s3320_enable_global(!pocket_judge_inpocket); + fpc1020_enable_global(!pocket_judge_inpocket); +} + +static ssize_t inpocket_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%u\n", pocket_judge_inpocket); +} + +static ssize_t inpocket_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + bool state; + ssize_t ret; + + ret = strtobool(buf, &state); + if (ret) + return size; + + if (pocket_judge_inpocket != state) { + pocket_judge_inpocket = state; + pocket_judge_update(); + } + + return size; +} + +static DEVICE_ATTR_RW(inpocket); + +static struct attribute *pocket_judge_class_attrs[] = { + &dev_attr_inpocket.attr, + NULL, +}; + +static const struct attribute_group pocket_judge_attr_group = { + .attrs = pocket_judge_class_attrs, +}; + +static struct kobject *pocket_judge_kobj; + +static int __init pocket_judge_init(void) +{ + ssize_t ret; + + pocket_judge_kobj = kobject_create_and_add("pocket_judge", kernel_kobj); + if (!pocket_judge_kobj) + return -ENOMEM; + + ret = sysfs_create_group(pocket_judge_kobj, &pocket_judge_attr_group); + if (ret) + kobject_put(pocket_judge_kobj); + + return ret; +} + +static void __exit pocket_judge_exit (void) +{ + kobject_put(pocket_judge_kobj); +} + +module_init(pocket_judge_init); +module_exit(pocket_judge_exit); diff --git a/drivers/input/touchscreen/synaptics_driver_s3320.c b/drivers/input/touchscreen/synaptics_driver_s3320.c index e293e86c17f4..8d3dd0f3377d 100644 --- a/drivers/input/touchscreen/synaptics_driver_s3320.c +++ b/drivers/input/touchscreen/synaptics_driver_s3320.c @@ -13,6 +13,7 @@ ** ** bean.wu@BSP.TP modified for oem 2017-09-01 8998_O tp_driver ****************************************************************************/ +#include "synaptics_driver_s3320.h" #include #include #include @@ -5152,6 +5153,17 @@ static int fb_notifier_callback(struct notifier_block *self, unsigned long event } #endif +void synaptics_s3320_enable_global(bool enabled) +{ + if (ts_g == NULL) + return; + + if (enabled) + touch_enable(ts_g); + else + touch_disable(ts_g); +} + static int __init tpd_driver_init(void) { TPD_ERR("%s enter\n", __func__); diff --git a/drivers/input/touchscreen/synaptics_driver_s3320.h b/drivers/input/touchscreen/synaptics_driver_s3320.h new file mode 100644 index 000000000000..f4e3062e86b8 --- /dev/null +++ b/drivers/input/touchscreen/synaptics_driver_s3320.h @@ -0,0 +1,17 @@ +/* + * Copyright 2017 Paranoid Android + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#ifndef _SYNAPTICS_DRIVER_S3320_H +#define _SYNAPTICS_DRIVER_S3320_H + +void synaptics_s3320_enable_global(_Bool enabled); + +#endif