summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Martins <bgcngm@gmail.com>2016-12-31 15:14:55 +0000
committerDavide Garberi <dade.garberi@gmail.com>2022-07-27 18:59:03 +0200
commitcccc81038a9a86fc90e2e15d536770307ed6ac6a (patch)
treeef6255a4190821f1c40ecb22eedf42ddd7b943d9
parente471ee5a64e05031512bcf19e88ccecf0848f7ed (diff)
fpc1020: Honor proximity state
* Implement a poor man's pocket mode: Receive proximity state from userspace Disable IRQ while proximity state is near * Based on fluxi's original idea (https://review.lineageos.org/#/c/152043/), but adapted to work along with ZUK's fingerprint wake up implementation. * Adapted to Zuk Z2 Plus and Pro by DD3Boh Change-Id: Ie9f92d5fba6f26beebcc208e9b9b6c989d9b90be Signed-off-by: Davide Garberi <dade.garberi@gmail.com>
-rw-r--r--drivers/fingerprint/fpc1020_ree.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/fingerprint/fpc1020_ree.c b/drivers/fingerprint/fpc1020_ree.c
index 8fcadaf0d8b4..8f7afe9eb379 100644
--- a/drivers/fingerprint/fpc1020_ree.c
+++ b/drivers/fingerprint/fpc1020_ree.c
@@ -45,6 +45,7 @@ struct fpc1020_data {
int reset_gpio;
int irq_gpio;
int irq;
+ bool irq_enabled;
struct notifier_block fb_notif;
/*Input device*/
struct input_dev *input_dev;
@@ -53,8 +54,26 @@ struct fpc1020_data {
struct workqueue_struct *fpc1020_wq;
u8 report_key;
int screen_on;
+ int proximity_state; /* 0:far 1:near */
};
+static void config_irq(struct fpc1020_data *fpc1020, bool enabled)
+{
+ if (enabled != fpc1020->irq_enabled) {
+ if (enabled)
+ enable_irq(gpio_to_irq(fpc1020->irq_gpio));
+ else
+ disable_irq(gpio_to_irq(fpc1020->irq_gpio));
+
+ dev_info(fpc1020->dev, "%s: %s fpc irq ---\n", __func__,
+ enabled ? "enable" : "disable");
+ fpc1020->irq_enabled = enabled;
+ } else {
+ dev_info(fpc1020->dev, "%s: dual config irq status: %s\n", __func__,
+ enabled ? "true" : "false");
+ }
+}
+
/* From drivers/input/keyboard/gpio_keys.c */
extern bool home_button_pressed(void);
extern void reset_home_button(void);
@@ -137,9 +156,32 @@ static ssize_t set_key(struct device *device,
static DEVICE_ATTR(key, S_IRUSR | S_IWUSR, get_key, set_key);
+static ssize_t proximity_state_set(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct fpc1020_data *fpc1020 = dev_get_drvdata(dev);
+ int rc, val;
+ rc = kstrtoint(buf, 10, &val);
+ if (rc)
+ return -EINVAL;
+ fpc1020->proximity_state = !!val;
+ if (!fpc1020->screen_on) {
+ if (fpc1020->proximity_state == 1) {
+ /* Disable IRQ when screen is off and proximity sensor is covered */
+ config_irq(fpc1020, false);
+ } else if (fpc1020->proximity_state == 0) {
+ /* Enable IRQ when screen is off and proximity sensor is uncovered */
+ config_irq(fpc1020, true);
+ }
+ }
+ return count;
+}
+static DEVICE_ATTR(proximity_state, S_IWUSR, NULL, proximity_state_set);
+
static struct attribute *attributes[] = {
&dev_attr_irq.attr,
&dev_attr_key.attr,
+ &dev_attr_proximity_state.attr,
NULL
};
@@ -345,6 +387,8 @@ static int fb_notifier_callback(struct notifier_block *self,
pr_err("ScreenOn\n");
fpc1020->screen_on = 1;
queue_work(fpc1020->fpc1020_wq, &fpc1020->pm_work);
+ /* Unconditionally enable IRQ when screen turns on */
+ config_irq(fpc1020, true);
} else if (*blank == FB_BLANK_POWERDOWN) {
pr_err("ScreenOff\n");
fpc1020->screen_on = 0;