From 06ca994c43eb409e8e7e02986601e5b6161cd10a Mon Sep 17 00:00:00 2001 From: zhaoyuan Date: Mon, 21 Dec 2015 11:14:05 +0800 Subject: [PATCH] input: synaptics: defer touch resume to workqueue During device resume, the touch resume function is called after display resume. Touch resume function will take about >200ms. Defer the touch resume function to a workqueue to reduce the total device resume time. An optional DT property is added to enable this on targets that need this feature. Change-Id: Ia9b055144c5a7f29f0f0d57428cccbe15a7d7a87 Signed-off-by: zhaoyuan --- .../input/touchscreen/synaptics_dsx_i2c.txt | 1 + .../synaptics_dsx/synaptics_dsx_core.c | 44 ++++++++++++++----- .../synaptics_dsx/synaptics_dsx_core.h | 3 +- .../synaptics_dsx/synaptics_dsx_i2c.c | 5 ++- include/linux/input/synaptics_dsx_v2.h | 3 +- 5 files changed, 43 insertions(+), 13 deletions(-) mode change 100755 => 100644 drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c mode change 100755 => 100644 include/linux/input/synaptics_dsx_v2.h diff --git a/Documentation/devicetree/bindings/input/touchscreen/synaptics_dsx_i2c.txt b/Documentation/devicetree/bindings/input/touchscreen/synaptics_dsx_i2c.txt index 833eb7a3eff2..19b78133bd60 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/synaptics_dsx_i2c.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/synaptics_dsx_i2c.txt @@ -67,6 +67,7 @@ These properties are defined only when synaptics,detect-device property is defin - synaptics,bypass-sensor-coords-check : Bypass the comparison of sensor coordinates range read from DT and touch controller. Used when some touch panels in the field are unprogrammed and misprogrammed. + - synaptics,resume-in-workqueue : specifiy whether to defer the resume to workqueue. Example: i2c@f9927000 { diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c index 7e7140641646..0ea6c6a23ee4 100644 --- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c +++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c @@ -115,6 +115,7 @@ static ssize_t synaptics_rmi4_full_pm_cycle_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); #if defined(CONFIG_FB) +static void fb_notify_resume_work(struct work_struct *work); static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data); #elif defined(CONFIG_HAS_EARLYSUSPEND) @@ -3669,6 +3670,7 @@ static int synaptics_rmi4_probe(struct platform_device *pdev) } #ifdef CONFIG_FB + INIT_WORK(&rmi4_data->fb_notify_work, fb_notify_resume_work); rmi4_data->fb_notif.notifier_call = fb_notifier_callback; retval = fb_register_client(&rmi4_data->fb_notif); @@ -3911,6 +3913,13 @@ static int synaptics_rmi4_remove(struct platform_device *pdev) } #if defined(CONFIG_FB) +static void fb_notify_resume_work(struct work_struct *work) +{ + struct synaptics_rmi4_data *rmi4_data = + container_of(work, struct synaptics_rmi4_data, fb_notify_work); + synaptics_rmi4_resume(&(rmi4_data->input_dev->dev)); +} + static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data) { @@ -3920,16 +3929,31 @@ static int fb_notifier_callback(struct notifier_block *self, container_of(self, struct synaptics_rmi4_data, fb_notif); if (evdata && evdata->data && rmi4_data) { - if (event == FB_EARLY_EVENT_BLANK) - synaptics_secure_touch_stop(rmi4_data, 0); - else if (event == FB_EVENT_BLANK) { - blank = evdata->data; - if (*blank == FB_BLANK_UNBLANK) - synaptics_rmi4_resume( - &(rmi4_data->input_dev->dev)); - else if (*blank == FB_BLANK_POWERDOWN) - synaptics_rmi4_suspend( - &(rmi4_data->input_dev->dev)); + blank = evdata->data; + if (rmi4_data->hw_if->board_data->resume_in_workqueue) { + if (event == FB_EARLY_EVENT_BLANK) { + synaptics_secure_touch_stop(rmi4_data, 0); + if (*blank == FB_BLANK_UNBLANK) + schedule_work( + &(rmi4_data->fb_notify_work)); + } else if (event == FB_EVENT_BLANK && + *blank == FB_BLANK_POWERDOWN) { + flush_work( + &(rmi4_data->fb_notify_work)); + synaptics_rmi4_suspend( + &(rmi4_data->input_dev->dev)); + } + } else { + if (event == FB_EARLY_EVENT_BLANK) { + synaptics_secure_touch_stop(rmi4_data, 0); + } else if (event == FB_EVENT_BLANK) { + if (*blank == FB_BLANK_UNBLANK) + synaptics_rmi4_resume( + &(rmi4_data->input_dev->dev)); + else if (*blank == FB_BLANK_POWERDOWN) + synaptics_rmi4_suspend( + &(rmi4_data->input_dev->dev)); + } } } diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.h b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.h index 0483fa4f6dd1..97802e9fe895 100644 --- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.h +++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.h @@ -5,7 +5,7 @@ * * Copyright (C) 2012 Alexandra Chin * Copyright (C) 2012 Scott Lin - * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * Copyright (c) 2014, 2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -248,6 +248,7 @@ struct synaptics_rmi4_data { struct mutex rmi4_reset_mutex; struct mutex rmi4_io_ctrl_mutex; #if defined(CONFIG_FB) + struct work_struct fb_notify_work; struct notifier_block fb_notif; #elif defined(CONFIG_HAS_EARLYSUSPEND) struct early_suspend early_suspend; diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c old mode 100755 new mode 100644 index 5f357965e9f1..0b3fbaf9f462 --- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c +++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c @@ -1,7 +1,7 @@ /* * Synaptics DSX touchscreen driver * - * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. * * Linux foundation chooses to take subject only to the GPLv2 license terms, * and distributes only under these terms. @@ -320,6 +320,9 @@ static int synaptics_dsx_parse_dt(struct device *dev, rmi4_pdata->bypass_packrat_id_check = of_property_read_bool(np, "synaptics,bypass-packrat-id-check"); + rmi4_pdata->resume_in_workqueue = of_property_read_bool(np, + "synaptics,resume-in-workqueue"); + rmi4_pdata->reset_delay_ms = RESET_DELAY; rc = of_property_read_u32(np, "synaptics,reset-delay-ms", &temp_val); if (!rc) diff --git a/include/linux/input/synaptics_dsx_v2.h b/include/linux/input/synaptics_dsx_v2.h old mode 100755 new mode 100644 index 13e8ae3df62e..9df212c3cdfe --- a/include/linux/input/synaptics_dsx_v2.h +++ b/include/linux/input/synaptics_dsx_v2.h @@ -5,7 +5,7 @@ * * Copyright (C) 2012 Alexandra Chin * Copyright (C) 2012 Scott Lin - * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -101,6 +101,7 @@ struct synaptics_dsx_board_data { bool disable_gpios; bool detect_device; bool bypass_packrat_id_check; + bool resume_in_workqueue; const char *fw_name; };