summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTai Kuo <taikuo@google.com>2019-04-11 15:29:43 +0800
committerDavid Chen <davidycchen@google.com>2020-03-05 02:09:20 +0000
commit583f2cd822d679f6d70a3ff7e100833721a00ebc (patch)
treef904b3e1b6210ce479cb1c1b3ccb6ef89ca99fbb
parent62e5f8fd1d78a53358eaa76c26eb7e27056ef0e0 (diff)
downloadfts_touch-583f2cd822d679f6d70a3ff7e100833721a00ebc.tar.gz
input: touchscreen: stm: pinctrl feature on resume/suspend
pinctrl implementation for touch driver resume and suspend Bug: 129371541 Change-Id: Ife05efc7d9dfa2d82e0d1ce87260e0397504cc85 Signed-off-by: Tai Kuo <taikuo@google.com>
-rw-r--r--fts.c112
-rw-r--r--fts.h9
2 files changed, 121 insertions, 0 deletions
diff --git a/fts.c b/fts.c
index 99d4058..1feea7f 100644
--- a/fts.c
+++ b/fts.c
@@ -134,6 +134,7 @@ static u8 key_mask; /* /< store the last update of the key mask
static int fts_init_sensing(struct fts_ts_info *info);
static int fts_mode_handler(struct fts_ts_info *info, int force);
+static void fts_pinctrl_setup(struct fts_ts_info *info, bool active);
static int fts_chip_initialization(struct fts_ts_info *info, int init_type);
@@ -4841,6 +4842,8 @@ static void fts_resume_work(struct work_struct *work)
fts_set_switch_gpio(info, FTS_SWITCH_GPIO_VALUE_AP_MASTER);
+ fts_pinctrl_setup(info, true);
+
__pm_wakeup_event(&info->wakesrc, jiffies_to_msecs(HZ));
info->resume_bit = 1;
@@ -4892,6 +4895,8 @@ static void fts_suspend_work(struct work_struct *work)
fts_system_reset();
flushFIFO();
+ fts_pinctrl_setup(info, false);
+
fts_set_switch_gpio(info, FTS_SWITCH_GPIO_VALUE_SLPI_MASTER);
#ifdef CONFIG_TOUCHSCREEN_TBN
@@ -5229,6 +5234,104 @@ err_gpio_irq:
return retval;
}
+/** Set pin state to active or suspend
+ * @param active 1 for active while 0 for suspend
+ */
+static void fts_pinctrl_setup(struct fts_ts_info *info, bool active)
+{
+ int retval;
+
+ if (info->ts_pinctrl) {
+ /*
+ * Pinctrl setup is optional.
+ * If pinctrl is found, set pins to active/suspend state.
+ * Otherwise, go on without showing error messages.
+ */
+ retval = pinctrl_select_state(info->ts_pinctrl, active ?
+ info->pinctrl_state_active :
+ info->pinctrl_state_suspend);
+ if (retval < 0) {
+ pr_err("Failed to select %s pinstate %d\n", active ?
+ PINCTRL_STATE_ACTIVE : PINCTRL_STATE_SUSPEND,
+ retval);
+ }
+ } else {
+ pr_warn("ts_pinctrl is NULL\n");
+ }
+}
+
+/**
+ * Get/put the touch pinctrl from the specific names. If pinctrl is used, the
+ * active and suspend pin control names and states are necessary.
+ * @param info pointer to fts_ts_info which contains info about the device and
+ * its hw setup
+ * @param get if 1, the pinctrl is get otherwise it is put (released) back to
+ * the system
+ * @return OK if success or an error code which specify the type of error
+ */
+static int fts_pinctrl_get(struct fts_ts_info *info, bool get)
+{
+ int retval;
+
+ if (!get) {
+ retval = 0;
+ goto pinctrl_put;
+ }
+
+ info->ts_pinctrl = devm_pinctrl_get(info->dev);
+ if (IS_ERR_OR_NULL(info->ts_pinctrl)) {
+ retval = PTR_ERR(info->ts_pinctrl);
+ pr_info("Target does not use pinctrl %d\n", retval);
+ goto err_pinctrl_get;
+ }
+
+ info->pinctrl_state_active
+ = pinctrl_lookup_state(info->ts_pinctrl, PINCTRL_STATE_ACTIVE);
+ if (IS_ERR_OR_NULL(info->pinctrl_state_active)) {
+ retval = PTR_ERR(info->pinctrl_state_active);
+ pr_err("Can not lookup %s pinstate %d\n",
+ PINCTRL_STATE_ACTIVE, retval);
+ goto err_pinctrl_lookup;
+ }
+
+ info->pinctrl_state_suspend
+ = pinctrl_lookup_state(info->ts_pinctrl, PINCTRL_STATE_SUSPEND);
+ if (IS_ERR_OR_NULL(info->pinctrl_state_suspend)) {
+ retval = PTR_ERR(info->pinctrl_state_suspend);
+ pr_err("Can not lookup %s pinstate %d\n",
+ PINCTRL_STATE_SUSPEND, retval);
+ goto err_pinctrl_lookup;
+ }
+
+ info->pinctrl_state_release
+ = pinctrl_lookup_state(info->ts_pinctrl, PINCTRL_STATE_RELEASE);
+ if (IS_ERR_OR_NULL(info->pinctrl_state_release)) {
+ retval = PTR_ERR(info->pinctrl_state_release);
+ pr_warn("Can not lookup %s pinstate %d\n",
+ PINCTRL_STATE_RELEASE, retval);
+ }
+
+ return OK;
+
+err_pinctrl_lookup:
+ devm_pinctrl_put(info->ts_pinctrl);
+err_pinctrl_get:
+ info->ts_pinctrl = NULL;
+pinctrl_put:
+ if (info->ts_pinctrl) {
+ if (IS_ERR_OR_NULL(info->pinctrl_state_release)) {
+ devm_pinctrl_put(info->ts_pinctrl);
+ info->ts_pinctrl = NULL;
+ } else {
+ if (pinctrl_select_state(
+ info->ts_pinctrl,
+ info->pinctrl_state_release))
+ pr_warn("Failed to select release pinstate\n");
+ }
+ }
+ return retval;
+}
+
/**
* Retrieve and parse the hw information from the device tree node defined in
* the system.
@@ -5452,6 +5555,11 @@ static int fts_probe(struct spi_device *client)
}
info->client->irq = gpio_to_irq(info->board->irq_gpio);
+ pr_info("SET Pinctrl:\n");
+ retval = fts_pinctrl_get(info, true);
+ if (!retval)
+ fts_pinctrl_setup(info, true);
+
pr_info("SET Event Handler:\n");
wakeup_source_init(&info->wakesrc, "fts_tp");
@@ -5732,6 +5840,8 @@ ProbeErrorExit_4:
/* destroy_workqueue(info->fwu_workqueue); */
wakeup_source_trash(&info->wakesrc);
+ fts_pinctrl_get(info, false);
+
fts_enable_reg(info, false);
ProbeErrorExit_2:
@@ -5804,6 +5914,8 @@ static int fts_remove(struct spi_device *client)
if (info->fwu_workqueue)
destroy_workqueue(info->fwu_workqueue);
+ fts_pinctrl_get(info, false);
+
fts_enable_reg(info, false);
fts_get_reg(info, false);
diff --git a/fts.h b/fts.h
index 0dd5a29..d3e2382 100644
--- a/fts.h
+++ b/fts.h
@@ -68,6 +68,10 @@
#define pr_fmt(fmt) "[ FTS ] " fmt
#endif
+#define PINCTRL_STATE_ACTIVE "pmx_ts_active"
+#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend"
+#define PINCTRL_STATE_RELEASE "pmx_ts_release"
+
#define DRIVER_TEST /* /< if defined allow to use and test special functions
* of the driver and fts_lib from command shell
* (useful for enginering/debug operations) */
@@ -427,6 +431,11 @@ struct fts_ts_info {
struct regulator *vdd_reg; /* DVDD power regulator */
struct regulator *avdd_reg; /* AVDD power regulator */
+ struct pinctrl *ts_pinctrl; /* touch pin control state holder */
+ struct pinctrl_state *pinctrl_state_active; /* Active pin state*/
+ struct pinctrl_state *pinctrl_state_suspend; /* Suspend pin state*/
+ struct pinctrl_state *pinctrl_state_release; /* Release pin state*/
+
spinlock_t fts_int; /* Spinlock to protect interrupt toggling */
bool irq_enabled; /* Interrupt state */