diff options
| author | Bruno Martins <bgcngm@gmail.com> | 2016-12-31 15:14:55 +0000 |
|---|---|---|
| committer | Davide Garberi <dade.garberi@gmail.com> | 2022-07-27 18:59:03 +0200 |
| commit | cccc81038a9a86fc90e2e15d536770307ed6ac6a (patch) | |
| tree | ef6255a4190821f1c40ecb22eedf42ddd7b943d9 | |
| parent | e471ee5a64e05031512bcf19e88ccecf0848f7ed (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.c | 44 |
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; |
