From 1a26c920717a24272e15b79b1455f3e99969a3ce Mon Sep 17 00:00:00 2001 From: Robin van der Gracht Date: Mon, 25 Nov 2019 12:40:47 -0800 Subject: [PATCH 1/7] Input: snvs_pwrkey - send key events for i.MX6 S, DL and Q The first generation i.MX6 processors does not send an interrupt when the power key is pressed. It sends a power down request interrupt if the key is released before a hard shutdown (5 second press). This should allow software to bring down the SoC safely. For this driver to work as a regular power key with the older SoCs, we need to send a keypress AND release when we get the power down request irq. Signed-off-by: Robin van der Gracht Link: https://lore.kernel.org/r/20191125161210.8275-1-robin@protonic.nl Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 2 +- drivers/input/keyboard/snvs_pwrkey.c | 44 +++++++++++++++++++++------- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 61f4eb63eec1..4706ff09f0e8 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -450,7 +450,7 @@ config KEYBOARD_SNVS_PWRKEY depends on OF help This is the snvs powerkey driver for the Freescale i.MX application - processors that are newer than i.MX6 SX. + processors. To compile this driver as a module, choose M here; the module will be called snvs_pwrkey. diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c index e76b7a400a1c..fd6f244f403d 100644 --- a/drivers/input/keyboard/snvs_pwrkey.c +++ b/drivers/input/keyboard/snvs_pwrkey.c @@ -19,15 +19,16 @@ #include #include -#define SNVS_LPSR_REG 0x4C /* LP Status Register */ -#define SNVS_LPCR_REG 0x38 /* LP Control Register */ -#define SNVS_HPSR_REG 0x14 -#define SNVS_HPSR_BTN BIT(6) -#define SNVS_LPSR_SPO BIT(18) -#define SNVS_LPCR_DEP_EN BIT(5) +#define SNVS_HPVIDR1_REG 0xF8 +#define SNVS_LPSR_REG 0x4C /* LP Status Register */ +#define SNVS_LPCR_REG 0x38 /* LP Control Register */ +#define SNVS_HPSR_REG 0x14 +#define SNVS_HPSR_BTN BIT(6) +#define SNVS_LPSR_SPO BIT(18) +#define SNVS_LPCR_DEP_EN BIT(5) -#define DEBOUNCE_TIME 30 -#define REPEAT_INTERVAL 60 +#define DEBOUNCE_TIME 30 +#define REPEAT_INTERVAL 60 struct pwrkey_drv_data { struct regmap *snvs; @@ -37,6 +38,7 @@ struct pwrkey_drv_data { int wakeup; struct timer_list check_timer; struct input_dev *input; + u8 minor_rev; }; static void imx_imx_snvs_check_for_events(struct timer_list *t) @@ -67,13 +69,29 @@ static irqreturn_t imx_snvs_pwrkey_interrupt(int irq, void *dev_id) { struct platform_device *pdev = dev_id; struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev); + struct input_dev *input = pdata->input; u32 lp_status; - pm_wakeup_event(pdata->input->dev.parent, 0); + pm_wakeup_event(input->dev.parent, 0); regmap_read(pdata->snvs, SNVS_LPSR_REG, &lp_status); - if (lp_status & SNVS_LPSR_SPO) - mod_timer(&pdata->check_timer, jiffies + msecs_to_jiffies(DEBOUNCE_TIME)); + if (lp_status & SNVS_LPSR_SPO) { + if (pdata->minor_rev == 0) { + /* + * The first generation i.MX6 SoCs only sends an + * interrupt on button release. To mimic power-key + * usage, we'll prepend a press event. + */ + input_report_key(input, pdata->keycode, 1); + input_sync(input); + input_report_key(input, pdata->keycode, 0); + input_sync(input); + pm_relax(input->dev.parent); + } else { + mod_timer(&pdata->check_timer, + jiffies + msecs_to_jiffies(DEBOUNCE_TIME)); + } + } /* clear SPO status */ regmap_write(pdata->snvs, SNVS_LPSR_REG, SNVS_LPSR_SPO); @@ -94,6 +112,7 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev) struct input_dev *input = NULL; struct device_node *np; int error; + u32 vid; /* Get SNVS register Page */ np = pdev->dev.of_node; @@ -121,6 +140,9 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev) if (pdata->irq < 0) return -EINVAL; + regmap_read(pdata->snvs, SNVS_HPVIDR1_REG, &vid); + pdata->minor_rev = vid & 0xff; + regmap_update_bits(pdata->snvs, SNVS_LPCR_REG, SNVS_LPCR_DEP_EN, SNVS_LPCR_DEP_EN); /* clear the unexpected interrupt before driver ready */ From 1e55c176f8f503c7dccba6e2b237f26a065ff79c Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 4 Dec 2019 17:56:24 -0800 Subject: [PATCH 2/7] Input: snvs_pwrkey - remove gratuitous NULL initializers Gratuitous NULL initializers rarely help and often prevent compiler from warning about using uninitialized variable. Let's remove them. Reviewed-by: Anson Huang Link: https://lore.kernel.org/r/20191125211407.GA97812@dtor-ws Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/snvs_pwrkey.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c index fd6f244f403d..2f5e3ab5ed63 100644 --- a/drivers/input/keyboard/snvs_pwrkey.c +++ b/drivers/input/keyboard/snvs_pwrkey.c @@ -108,8 +108,8 @@ static void imx_snvs_pwrkey_act(void *pdata) static int imx_snvs_pwrkey_probe(struct platform_device *pdev) { - struct pwrkey_drv_data *pdata = NULL; - struct input_dev *input = NULL; + struct pwrkey_drv_data *pdata; + struct input_dev *input; struct device_node *np; int error; u32 vid; From d4b675e1b5272149d4c6fac6870df6ebdbd8be82 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 4 Dec 2019 17:27:16 -0800 Subject: [PATCH 3/7] Input: uinput - fix returning EPOLLOUT from uinput_poll Always return EPOLLOUT from uinput_poll to allow polling /dev/uinput for writable state. Signed-off-by: Marcel Holtmann Link: https://lore.kernel.org/r/20191204025014.5189-1-marcel@holtmann.org Signed-off-by: Dmitry Torokhov --- drivers/input/misc/uinput.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 84051f20b18a..fd253781be71 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -695,7 +695,7 @@ static __poll_t uinput_poll(struct file *file, poll_table *wait) if (udev->head != udev->tail) return EPOLLIN | EPOLLRDNORM; - return 0; + return EPOLLOUT | EPOLLWRNORM; } static int uinput_release(struct inode *inode, struct file *file) From 25b2f1b77a92b4d850d40eca50d446dd25c09934 Mon Sep 17 00:00:00 2001 From: Mathew King Date: Wed, 4 Dec 2019 17:27:47 -0800 Subject: [PATCH 4/7] Input: add privacy screen toggle keycode Add keycode for toggling electronic privacy screen to the keycodes definition. Some new laptops have a privacy screen which can be toggled with a key on the keyboard. Signed-off-by: Mathew King Link: https://lore.kernel.org/r/20191017163208.235518-1-mathewk@chromium.org Signed-off-by: Dmitry Torokhov --- include/uapi/linux/input-event-codes.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h index 85387c76c24f..05d8b4f4f82f 100644 --- a/include/uapi/linux/input-event-codes.h +++ b/include/uapi/linux/input-event-codes.h @@ -649,6 +649,8 @@ */ #define KEY_DATA 0x277 #define KEY_ONSCREEN_KEYBOARD 0x278 +/* Electronic privacy screen control */ +#define KEY_PRIVACY_SCREEN_TOGGLE 0x279 #define BTN_TRIGGER_HAPPY 0x2c0 #define BTN_TRIGGER_HAPPY1 0x2c0 From df5b5e555b356662a5e4a23c6774fdfce8547d54 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 2 Dec 2019 09:36:15 -0800 Subject: [PATCH 5/7] Input: goodix - add upside-down quirk for Teclast X89 tablet The touchscreen on the Teclast X89 is mounted upside down in relation to the display orientation (the touchscreen itself is mounted upright, but the display is mounted upside-down). Add a quirk for this so that we send coordinates which match the display orientation. Signed-off-by: Hans de Goede Reviewed-by: Bastien Nocera Link: https://lore.kernel.org/r/20191202085636.6650-1-hdegoede@redhat.com Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/goodix.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index fb43aa708660..0403102e807e 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -128,6 +128,15 @@ static const unsigned long goodix_irq_flags[] = { */ static const struct dmi_system_id rotated_screen[] = { #if defined(CONFIG_DMI) && defined(CONFIG_X86) + { + .ident = "Teclast X89", + .matches = { + /* tPAD is too generic, also match on bios date */ + DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"), + DMI_MATCH(DMI_BOARD_NAME, "tPAD"), + DMI_MATCH(DMI_BIOS_DATE, "12/19/2014"), + }, + }, { .ident = "WinBook TW100", .matches = { From 86bcd3a12999447faad60ec59c2d64d18d8e61ac Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Mon, 2 Dec 2019 09:37:00 -0800 Subject: [PATCH 6/7] Input: synaptics-rmi4 - re-enable IRQs in f34v7_do_reflash F34 is a bit special as it reinitializes the device and related driver structs during the firmware update. This clears the fn_irq_mask which will then prevent F34 from receiving further interrupts, leading to timeouts during the firmware update. Make sure to reinitialize the IRQ enables at the appropriate times. The issue is in F34 code, but the commit in the fixes tag exposed the issue, as before this commit things would work by accident. Fixes: 363c53875aef (Input: synaptics-rmi4 - avoid processing unknown IRQs) Signed-off-by: Lucas Stach Link: https://lore.kernel.org/r/20191129133514.23224-1-l.stach@pengutronix.de Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/rmi4/rmi_f34v7.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/input/rmi4/rmi_f34v7.c b/drivers/input/rmi4/rmi_f34v7.c index a4cabf52740c..74f7c6f214ff 100644 --- a/drivers/input/rmi4/rmi_f34v7.c +++ b/drivers/input/rmi4/rmi_f34v7.c @@ -1189,6 +1189,9 @@ int rmi_f34v7_do_reflash(struct f34_data *f34, const struct firmware *fw) { int ret; + f34->fn->rmi_dev->driver->set_irq_bits(f34->fn->rmi_dev, + f34->fn->irq_mask); + rmi_f34v7_read_queries_bl_version(f34); f34->v7.image = fw->data; From a284e11c371e446371675668d8c8120a27227339 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 2 Dec 2019 10:08:12 -0800 Subject: [PATCH 7/7] Input: synaptics-rmi4 - don't increment rmiaddr for SMBus transfers This increment of rmi_smbus in rmi_smb_read/write_block() causes garbage to be read/written. The first read of SMB_MAX_COUNT bytes is fine, but after that it is nonsense. Trial-and-error showed that by dropping the increment of rmiaddr everything is fine and the F54 function properly works. I tried a hack with rmi_smb_write_block() as well (writing to the same F54 touchpad data area, then reading it back), and that suggests that there too the rmiaddr increment has to be dropped. It makes sense that if it has to be dropped for read, then it has to be dropped for write as well. It looks like the initial work with F54 was done using i2c, not smbus, and it seems nobody ever tested F54 with smbus. The other functions all read/write less than SMB_MAX_COUNT as far as I can tell, so this issue was never noticed with non-F54 functions. With this change I can read out the touchpad data correctly on my Lenovo X1 Carbon 6th Gen laptop. Signed-off-by: Hans Verkuil Link: https://lore.kernel.org/r/8dd22e21-4933-8e9c-a696-d281872c8de7@xs4all.nl Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/rmi4/rmi_smbus.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/input/rmi4/rmi_smbus.c b/drivers/input/rmi4/rmi_smbus.c index 2407ea43de59..b313c579914f 100644 --- a/drivers/input/rmi4/rmi_smbus.c +++ b/drivers/input/rmi4/rmi_smbus.c @@ -163,7 +163,6 @@ static int rmi_smb_write_block(struct rmi_transport_dev *xport, u16 rmiaddr, /* prepare to write next block of bytes */ cur_len -= SMB_MAX_COUNT; databuff += SMB_MAX_COUNT; - rmiaddr += SMB_MAX_COUNT; } exit: mutex_unlock(&rmi_smb->page_mutex); @@ -215,7 +214,6 @@ static int rmi_smb_read_block(struct rmi_transport_dev *xport, u16 rmiaddr, /* prepare to read next block of bytes */ cur_len -= SMB_MAX_COUNT; databuff += SMB_MAX_COUNT; - rmiaddr += SMB_MAX_COUNT; } retval = 0;