touch: offload fw boot up to workqueue

touch faststartup is consuming more than 700ms during power on,
created workqueue to handle touch firmware boot up sequence.

Change-Id: I67a288f41001052e5dcdb2ed465055b3a23d3233
Signed-off-by: Sachin Kumar Garg <quic_sachinku@quicinc.com>
This commit is contained in:
Sachin Kumar Garg
2022-09-27 10:36:22 +05:30
committed by Gerrit - the friendly Code Review server
parent 13fe897650
commit a6675f0aee
2 changed files with 152 additions and 47 deletions

View File

@@ -41,6 +41,11 @@
#define FT_I2C_VTG_MIN_UV 1800000 #define FT_I2C_VTG_MIN_UV 1800000
#define FT_I2C_VTG_MAX_UV 1800000 #define FT_I2C_VTG_MAX_UV 1800000
#define PWR_SUSPEND_LOAD_UA 165
#define I2C_SUSPEND_LOAD_UA 100
#define PWR_ACTIVE_LOAD_MA 12000
#define I2C_ACTIVE_LOAD_MA 30000
#define PT_CORE_STARTUP_RETRY_COUNT 3 #define PT_CORE_STARTUP_RETRY_COUNT 3
#define PT_STATUS_STR_LEN (50) #define PT_STATUS_STR_LEN (50)
@@ -51,6 +56,7 @@ static struct drm_panel *active_panel;
MODULE_FIRMWARE(PT_FW_FILE_NAME); MODULE_FIRMWARE(PT_FW_FILE_NAME);
static int pt_lpm_regulator(struct regulator *reg, int load_uA);
static const char *pt_driver_core_name = PT_CORE_NAME; static const char *pt_driver_core_name = PT_CORE_NAME;
static const char *pt_driver_core_version = PT_DRIVER_VERSION; static const char *pt_driver_core_version = PT_DRIVER_VERSION;
static const char *pt_driver_core_date = PT_DRIVER_DATE; static const char *pt_driver_core_date = PT_DRIVER_DATE;
@@ -7660,7 +7666,7 @@ static int pt_core_sleep_(struct pt_core_data *cd)
mutex_unlock(&cd->system_lock); mutex_unlock(&cd->system_lock);
pt_debug(cd->dev, DL_INFO, pt_debug(cd->dev, DL_INFO,
"%s - Skip slee[ state %d\n", __func__, cd->sleep_state); "%s - Skip slee[ state %d\n", __func__, cd->sleep_state);
return 1; return 0;
} }
mutex_unlock(&cd->system_lock); mutex_unlock(&cd->system_lock);
@@ -7714,11 +7720,11 @@ static int pt_core_easywake_on_(struct pt_core_data *cd)
mutex_lock(&cd->system_lock); mutex_lock(&cd->system_lock);
if (cd->sleep_state == SS_SLEEP_ON) { if (cd->sleep_state == SS_EASY_WAKING_ON) {
mutex_unlock(&cd->system_lock); mutex_unlock(&cd->system_lock);
pt_debug(cd->dev, DL_INFO, "%s - Skip sleep state %d\n", pt_debug(cd->dev, DL_INFO, "%s - Skip sleep state %d\n",
__func__, cd->sleep_state); __func__, cd->sleep_state);
return 1; return 0;
} }
mutex_unlock(&cd->system_lock); mutex_unlock(&cd->system_lock);
@@ -7733,6 +7739,9 @@ static int pt_core_easywake_on_(struct pt_core_data *cd)
if (rc) if (rc)
pr_err("%s: Easy wakeup error detected :rc=%d\n", __func__, rc); pr_err("%s: Easy wakeup error detected :rc=%d\n", __func__, rc);
} }
mutex_lock(&cd->system_lock);
cd->sleep_state = SS_EASY_WAKING_ON;
mutex_unlock(&cd->system_lock);
return rc; return rc;
} }
@@ -8499,7 +8508,7 @@ static int pt_read_input(struct pt_core_data *cd)
mutex_lock(&cd->system_lock); mutex_lock(&cd->system_lock);
if (IS_EASY_WAKE_CONFIGURED(cd->easy_wakeup_gesture)) { if (IS_EASY_WAKE_CONFIGURED(cd->easy_wakeup_gesture)) {
if (cd->sleep_state == SS_SLEEP_ON) { if (cd->sleep_state == SS_SLEEP_ON || cd->sleep_state == SS_EASY_WAKING_ON) {
mutex_unlock(&cd->system_lock); mutex_unlock(&cd->system_lock);
if (!dev->power.is_suspended) if (!dev->power.is_suspended)
goto read; goto read;
@@ -9579,11 +9588,11 @@ static int pt_core_easywake_off_(struct pt_core_data *cd)
int rc = 0; int rc = 0;
mutex_lock(&cd->system_lock); mutex_lock(&cd->system_lock);
if (cd->sleep_state == SS_SLEEP_OFF) { if (cd->sleep_state == SS_EASY_WAKING_OFF) {
mutex_unlock(&cd->system_lock); mutex_unlock(&cd->system_lock);
pt_debug(cd->dev, DL_INFO, pt_debug(cd->dev, DL_INFO,
"%s - %d skip wakeoff\n", __func__, cd->sleep_state); "%s - %d skip wakeoff\n", __func__, cd->sleep_state);
return 1; return 0;
} }
mutex_unlock(&cd->system_lock); mutex_unlock(&cd->system_lock);
@@ -9595,6 +9604,9 @@ static int pt_core_easywake_off_(struct pt_core_data *cd)
"%s - %d failed %d\n", __func__, rc); "%s - %d failed %d\n", __func__, rc);
} }
mutex_lock(&cd->system_lock);
cd->sleep_state = SS_EASY_WAKING_OFF;
mutex_unlock(&cd->system_lock);
pt_start_wd_timer(cd); pt_start_wd_timer(cd);
return rc; return rc;
} }
@@ -9660,7 +9672,7 @@ static int pt_core_wake_(struct pt_core_data *cd)
mutex_unlock(&cd->system_lock); mutex_unlock(&cd->system_lock);
pt_debug(cd->dev, DL_INFO, pt_debug(cd->dev, DL_INFO,
"%s - skip wake sleep state %d\n", __func__, cd->sleep_state); "%s - skip wake sleep state %d\n", __func__, cd->sleep_state);
return 1; return 0;
} }
mutex_unlock(&cd->system_lock); mutex_unlock(&cd->system_lock);
@@ -9701,7 +9713,7 @@ static int pt_core_wake_(struct pt_core_data *cd)
******************************************************************************/ ******************************************************************************/
static int pt_core_wake(struct pt_core_data *cd) static int pt_core_wake(struct pt_core_data *cd)
{ {
int rc; int rc = 0;
rc = request_exclusive(cd, cd->dev, PT_REQUEST_EXCLUSIVE_TIMEOUT); rc = request_exclusive(cd, cd->dev, PT_REQUEST_EXCLUSIVE_TIMEOUT);
if (rc < 0) { if (rc < 0) {
@@ -10512,6 +10524,49 @@ regulator_put:
return rc; return rc;
} }
static int pt_enable_vdd_regulator(struct pt_core_data *cd, bool en)
{
int rc;
if (!en) {
rc = 0;
goto disable_vdd_reg;
}
if (cd->vdd) {
if (regulator_count_voltages(cd->vdd) > 0) {
rc = regulator_set_voltage(cd->vdd, FT_VTG_MIN_UV,
FT_VTG_MAX_UV);
if (rc) {
dev_err(cd->dev,
"Regulator set_vtg failed vdd rc=%d\n", rc);
goto exit;
}
}
rc = regulator_enable(cd->vdd);
if (rc) {
dev_err(cd->dev,
"Regulator vdd enable failed rc=%d\n", rc);
goto exit;
}
}
return 0;
disable_vdd_reg:
if (cd->vdd) {
if (regulator_count_voltages(cd->vdd) > 0)
regulator_set_voltage(cd->vdd, FT_VTG_MIN_UV,
FT_VTG_MAX_UV);
regulator_disable(cd->vdd);
}
exit:
return rc;
}
static int pt_enable_regulator(struct pt_core_data *cd, bool en) static int pt_enable_regulator(struct pt_core_data *cd, bool en)
{ {
int rc; int rc;
@@ -10606,19 +10661,9 @@ exit:
static int pt_core_rt_suspend(struct device *dev) static int pt_core_rt_suspend(struct device *dev)
{ {
struct pt_core_data *cd = dev_get_drvdata(dev); struct pt_core_data *cd = dev_get_drvdata(dev);
int rc = 0;
dev_info(dev, "%s: Entering into runtime suspend mode:\n", pt_debug(dev, DL_DEBUG, "%s Skip - probe state %d\n",
__func__); __func__, cd->core_probe_complete);
if (cd->cpdata->flags & PT_CORE_FLAG_SKIP_RUNTIME)
return 0;
rc = pt_core_easywake_on(cd);
if (rc < 0) {
pt_debug(dev, DL_ERROR, "%s: Error on sleep\n", __func__);
return -EAGAIN;
}
return 0; return 0;
} }
@@ -10638,18 +10683,8 @@ static int pt_core_rt_suspend(struct device *dev)
static int pt_core_rt_resume(struct device *dev) static int pt_core_rt_resume(struct device *dev)
{ {
struct pt_core_data *cd = dev_get_drvdata(dev); struct pt_core_data *cd = dev_get_drvdata(dev);
int rc = 0; pt_debug(dev, DL_DEBUG, "%s Skip - probe state %d\n",
__func__, cd->core_probe_complete);
dev_info(dev, "%s: Entering into runtime resume mode:\n",
__func__);
if (cd->cpdata->flags & PT_CORE_FLAG_SKIP_RUNTIME)
return 0;
rc = pt_core_easywake_off(cd);
if (rc < 0) {
pt_debug(dev, DL_ERROR, "%s: Error on wake\n", __func__);
return -EAGAIN;
}
return 0; return 0;
} }
@@ -10683,11 +10718,17 @@ static int pt_core_suspend_(struct device *dev)
return -EAGAIN; return -EAGAIN;
} }
#ifdef REGULATOR rc = pt_enable_vdd_regulator(cd, false);
rc = pt_enable_regulator(cd, false); if (rc) {
if (rc) dev_err(dev, "%s: Failed to disable vdd regulators: rc=%d\n",
dev_err(dev, "%s: Failed to disable regulators: rc=%d\n", __func__, rc); __func__, rc);
#endif }
rc = pt_lpm_regulator(cd->vcc_i2c, I2C_ACTIVE_LOAD_MA);
if (rc) {
dev_err(dev, "%s: Failed to enter to lpm mode rc=%d\n",
__func__, rc);
}
if (!IS_EASY_WAKE_CONFIGURED(cd->easy_wakeup_gesture)) if (!IS_EASY_WAKE_CONFIGURED(cd->easy_wakeup_gesture))
return 0; return 0;
@@ -10708,6 +10749,13 @@ static int pt_core_suspend_(struct device *dev)
return rc; return rc;
} }
static int pt_lpm_regulator(struct regulator *reg, int load_uA)
{
return (regulator_count_voltages(reg) > 0) ?
regulator_set_load(reg, load_uA) : 0;
}
/******************************************************************************* /*******************************************************************************
* FUNCTION: pt_core_suspend * FUNCTION: pt_core_suspend
* *
@@ -10732,7 +10780,7 @@ static int pt_core_suspend(struct device *dev)
rc = pt_core_suspend_(dev); rc = pt_core_suspend_(dev);
pt_debug(dev, DL_WARN, "%s Exit - rc = %d\n", __func__, rc); pt_debug(dev, DL_WARN, "%s Exit - rc = %d\n", __func__, rc);
return rc; return 0;
} }
/******************************************************************************* /*******************************************************************************
@@ -10756,13 +10804,17 @@ static int pt_core_resume_(struct device *dev)
dev_info(dev, "%s: Entering into resume mode:\n", dev_info(dev, "%s: Entering into resume mode:\n",
__func__); __func__);
#ifdef REGULATOR rc = pt_lpm_regulator(cd->vcc_i2c, I2C_ACTIVE_LOAD_MA);
rc = pt_enable_regulator(cd, true);
if (rc < 0) { if (rc < 0) {
dev_err(dev, "%s: Failed to enable regulators: rc=%d\n", dev_err(dev, "%s: Failed to exit lpm mode: rc=%d\n",
__func__, rc);
}
rc = pt_enable_vdd_regulator(cd, true);
if (rc < 0) {
dev_err(dev, "%s: Failed to enable vdd regulators: rc=%d\n",
__func__, rc); __func__, rc);
} }
#endif
dev_info(dev, "%s: Voltage regulator enabled: rc=%d\n", dev_info(dev, "%s: Voltage regulator enabled: rc=%d\n",
__func__, rc); __func__, rc);
@@ -10799,9 +10851,53 @@ exit:
return -EAGAIN; return -EAGAIN;
} }
return 0; return rc;
} }
/*******************************************************************************
* FUNCTION: resume_offload_work
*
* SUMMARY: Wrapper function of pt_core_resume_() to avoid TP to be waken/slept
* along with kernel power state even the display is off based on the check of
* TTDL core platform flag.
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *dev - pointer to core device
******************************************************************************/
static void pt_resume_offload_work(struct work_struct *work)
{
int rc = 0;
int retry_count = 10;
struct pt_core_data *pt_data = container_of(work, struct pt_core_data,
resume_offload_work);
do {
retry_count--;
rc = pt_core_resume_(pt_data->dev);
if (rc < 0)
pt_debug(pt_data->dev, DL_ERROR,
"%s: Error on wake\n", __func__);
} while (retry_count && rc < 0);
#ifdef TOUCH_TO_WAKE_POWER_FEATURE_WORK_AROUND
rc = pt_core_easywake_on(pt_data);
if (rc < 0) {
pt_debug(pt_data->dev, DL_ERROR,
"%s: Error on enable touch to wake key\n",
__func__);
return;
}
pt_data->fb_state = FB_OFF;
pt_debug(pt_data->dev, DL_INFO, "%s End\n", __func__);
#endif
}
/******************************************************************************* /*******************************************************************************
* FUNCTION: pt_core_resume * FUNCTION: pt_core_resume
* *
@@ -10819,10 +10915,14 @@ exit:
static int pt_core_resume(struct device *dev) static int pt_core_resume(struct device *dev)
{ {
struct pt_core_data *cd = dev_get_drvdata(dev); struct pt_core_data *cd = dev_get_drvdata(dev);
int rc = 0;
if (cd->cpdata->flags & PT_CORE_FLAG_SKIP_SYS_SLEEP) if (cd->cpdata->flags & PT_CORE_FLAG_SKIP_SYS_SLEEP)
return 0; return 0;
return pt_core_resume_(dev); queue_work(cd->pt_workqueue, &cd->resume_offload_work);
pt_debug(cd->dev, DL_ERROR, "%s End\n", __func__);
return rc;
} }
#endif #endif
@@ -12587,9 +12687,8 @@ static void pt_resume_work(struct work_struct *work)
if (rc < 0) { if (rc < 0) {
pt_debug(pt_data->dev, DL_ERROR, pt_debug(pt_data->dev, DL_ERROR,
"%s: Error on wake\n", __func__); "%s: Error on wake\n", __func__);
return;
} }
return;
} }
static void pt_suspend_work(struct work_struct *work) static void pt_suspend_work(struct work_struct *work)
@@ -12609,7 +12708,7 @@ static void pt_suspend_work(struct work_struct *work)
return; return;
} }
pt_debug(pt_data->dev, DL_INFO, "%s Exit\n", __func__); pt_debug(pt_data->dev, DL_INFO, "%s Exit\n", __func__);
return;
} }
/******************************************************************************* /*******************************************************************************
@@ -17649,6 +17748,7 @@ skip_enum:
#elif defined(CONFIG_DRM) #elif defined(CONFIG_DRM)
pt_debug(dev, DL_ERROR, "%s: Probe: Setup drm notifier\n", __func__); pt_debug(dev, DL_ERROR, "%s: Probe: Setup drm notifier\n", __func__);
pt_setup_drm_notifier(cd); pt_setup_drm_notifier(cd);
INIT_WORK(&cd->resume_offload_work, pt_resume_offload_work);
#elif defined(CONFIG_FB) #elif defined(CONFIG_FB)
pt_setup_fb_notifier(cd); pt_setup_fb_notifier(cd);
#endif #endif

View File

@@ -143,6 +143,8 @@
#define TT7XXX_EXAMPLE #define TT7XXX_EXAMPLE
#endif #endif
#define TOUCH_TO_WAKE_POWER_FEATURE_WORK_AROUND
/* /*
* The largest PIP message is the PIP2 FILE_WRITE which has: * The largest PIP message is the PIP2 FILE_WRITE which has:
* 2 byte register * 2 byte register
@@ -1108,6 +1110,8 @@ enum pt_sleep_state {
SS_SLEEP_ON, SS_SLEEP_ON,
SS_SLEEPING, SS_SLEEPING,
SS_WAKING, SS_WAKING,
SS_EASY_WAKING_ON,
SS_EASY_WAKING_OFF,
}; };
enum pt_fb_state { enum pt_fb_state {
@@ -1443,6 +1447,7 @@ struct pt_core_data {
char core_id[20]; char core_id[20];
struct device *dev; struct device *dev;
struct workqueue_struct *pt_workqueue; struct workqueue_struct *pt_workqueue;
struct work_struct resume_offload_work;
struct work_struct suspend_work; struct work_struct suspend_work;
struct work_struct resume_work; struct work_struct resume_work;