From 417ef43ab5c8c8a1730e27058ae5d4d5b0056f04 Mon Sep 17 00:00:00 2001 From: zhuwg1 Date: Thu, 24 Feb 2022 16:03:04 +0800 Subject: [PATCH] Add CLI parade touch suspend/resume logic CLI parade touch need to do suspend and resume when receiving suspend and resume notifications from display module. Change-Id: Ibcb2e10f5974b9e546b9ffd0aa2ead3d106e4a0d Signed-off-by: zhuwg1 Reviewed-on: https://gerrit.mot.com/2200231 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: litong Reviewed-by: Jichao Zou Submit-Approved: Jira Key --- .../parade_tma5xx_mmi/cyttsp5_core.c | 6 +- .../parade_tma5xx_mmi/cyttsp5_devtree.c | 29 ++++ .../parade_tma5xx_mmi/cyttsp5_i2c.c | 2 + .../parade_tma5xx_mmi/cyttsp5_platform.c | 124 +++++++++++++++++- .../parade_tma5xx_mmi/cyttsp5_regs.h | 1 + .../parade_tma5xx_mmi/cyttsp5_ts_mmi.c | 108 ++++++++++++++- include/linux/cyttsp5_core.h | 4 + 7 files changed, 268 insertions(+), 6 deletions(-) diff --git a/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_core.c b/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_core.c index 9a9907832942..83a187370c94 100644 --- a/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_core.c +++ b/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_core.c @@ -5045,8 +5045,8 @@ static int cyttsp5_core_rt_resume(struct device *dev) } #endif -#if defined(CONFIG_PM_SLEEP) -static int cyttsp5_core_suspend(struct device *dev) +#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_INPUT_TOUCHSCREEN_MMI) +int cyttsp5_core_suspend(struct device *dev) { struct cyttsp5_core_data *cd = dev_get_drvdata(dev); @@ -5075,7 +5075,7 @@ static int cyttsp5_core_suspend(struct device *dev) return 0; } -static int cyttsp5_core_resume(struct device *dev) +int cyttsp5_core_resume(struct device *dev) { struct cyttsp5_core_data *cd = dev_get_drvdata(dev); diff --git a/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_devtree.c b/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_devtree.c index b5cd79c65395..de2aa7bcc68d 100644 --- a/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_devtree.c +++ b/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_devtree.c @@ -547,6 +547,7 @@ static struct cyttsp5_core_platform_data *create_and_get_core_pdata( u32 value; int rc; int i; + const char *name_tmp; pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); if (!pdata) { @@ -554,6 +555,34 @@ static struct cyttsp5_core_platform_data *create_and_get_core_pdata( goto fail; } + /* get avdd power */ + memset(pdata->avdd_name, 0, sizeof(pdata->avdd_name)); + rc = of_property_read_string(core_node, "cyttsp5,avdd-name", &name_tmp); + if (!rc) { + pr_info("%s, avdd name from dt: %s", __func__, name_tmp); + if (strlen(name_tmp) < sizeof(pdata->avdd_name)) + strncpy(pdata->avdd_name, + name_tmp, sizeof(pdata->avdd_name)); + else + pr_info("%s, invalied avdd name length: %ld > %ld", __func__, + strlen(name_tmp), + sizeof(pdata->avdd_name)); + } + + /* get iovdd power */ + memset(pdata->iovdd_name, 0, sizeof(pdata->iovdd_name)); + rc = of_property_read_string(core_node, "cyttsp5,iovdd-name", &name_tmp); + if (!rc) { + pr_info("%s, iovdd name from dt: %s", __func__, name_tmp); + if (strlen(name_tmp) < sizeof(pdata->iovdd_name)) + strncpy(pdata->iovdd_name, + name_tmp, sizeof(pdata->iovdd_name)); + else + pr_info("%s, invalied iovdd name length: %ld > %ld", __func__, + strlen(name_tmp), + sizeof(pdata->iovdd_name)); + } + /* Required fields */ rc = of_get_named_gpio(core_node, "cy,irq_gpio", 0); if (!gpio_is_valid(rc)) { diff --git a/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_i2c.c b/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_i2c.c index 7f12671468e5..eb646825e630 100644 --- a/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_i2c.c +++ b/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_i2c.c @@ -188,7 +188,9 @@ static struct i2c_driver cyttsp5_i2c_driver = { .driver = { .name = CYTTSP5_I2C_NAME, .owner = THIS_MODULE, +#ifndef CONFIG_INPUT_TOUCHSCREEN_MMI .pm = &cyttsp5_pm_ops, +#endif #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT .of_match_table = cyttsp5_i2c_of_match, #endif diff --git a/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_platform.c b/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_platform.c index 7831ee2a0f1f..46891d5c43e3 100644 --- a/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_platform.c +++ b/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_platform.c @@ -185,6 +185,94 @@ int cyttsp5_xres(struct cyttsp5_core_platform_data *pdata, return rc; } +/** + * cyttsp5_ts_power_init - Get regulator for touch device + * @pdata: pointer to touch core platform data + * @dev: pointer to touch device + * return: 0 ok, <0 failed + */ +static int cyttsp5_ts_power_init(struct cyttsp5_core_platform_data *pdata, struct device *dev) +{ + int ret = 0; + + dev_info(dev, "%s:Get regulator for touch device", __func__); + if (strlen(pdata->avdd_name)) { + pdata->avdd = devm_regulator_get(dev, + pdata->avdd_name); + if (IS_ERR_OR_NULL(pdata->avdd)) { + ret = PTR_ERR(pdata->avdd); + pr_err("%s, Failed to get regulator avdd:%d", __func__, ret); + pdata->avdd = NULL; + return ret; + } + } else { + dev_info(dev, "%s: Avdd name is NULL", __func__); + return -1; + } + + if (strlen(pdata->iovdd_name)) { + pdata->iovdd = devm_regulator_get(dev, + pdata->iovdd_name); + if (IS_ERR_OR_NULL(pdata->iovdd)) { + ret = PTR_ERR(pdata->iovdd); + pr_err("%s: Failed to get regulator iovdd:%d", __func__, ret); + pdata->iovdd = NULL; + return ret; + } + } else { + dev_info(dev, "%s: iovdd name is NULL", __func__); + return -1; + } + + return ret; +} + +/** + * cyttsp5_ts_power_control - Set regulator power on or off + * @dev: pointer to touch device + * @on: indicating the on/off the power + * return: 0 ok, <0 failed + */ +static int cyttsp5_ts_power_control(struct cyttsp5_core_platform_data *pdata, + struct device *dev, int on) +{ + int ret =0; + if(on) { + pr_info("%s: Device power on", __func__); + + if (!IS_ERR_OR_NULL(pdata->iovdd)) { + ret = regulator_enable(pdata->iovdd); + if (ret < 0) { + pr_err("%s: Failed to enable iovdd:%d", __func__, ret); + goto power_off; + } + } + + if (!IS_ERR_OR_NULL(pdata->avdd)) { + ret = regulator_enable(pdata->avdd); + if (ret < 0) { + pr_err("%s: Failed to enable avdd:%d", __func__, ret); + goto power_off; + } + } + return 0; + } + +power_off: + pr_info("%s: Device power off", __func__); + if (!IS_ERR_OR_NULL(pdata->iovdd)) { + if (regulator_is_enabled(pdata->iovdd)) + regulator_disable(pdata->iovdd); + } + + if (!IS_ERR_OR_NULL(pdata->avdd)) { + if (regulator_is_enabled(pdata->avdd)) + regulator_disable(pdata->avdd); + } + + return ret; +} + int cyttsp5_init(struct cyttsp5_core_platform_data *pdata, int on, struct device *dev) { @@ -193,6 +281,20 @@ int cyttsp5_init(struct cyttsp5_core_platform_data *pdata, int rc = 0; if (on) { + rc = cyttsp5_ts_power_init(pdata, dev); + if(rc < 0) { + dev_err(dev, + "%s: Fail init cyttsp5 power regulator =%d\n", __func__, rc); + return rc; + } + + rc = cyttsp5_ts_power_control(pdata, dev, 1); + if(rc < 0) { + dev_err(dev, + "%s: Power on cyttsp5 failed = %d\n", __func__, rc); + return rc; + } + rc = gpio_request(rst_gpio, NULL); if (rc < 0) { gpio_free(rst_gpio); @@ -238,13 +340,31 @@ int cyttsp5_init(struct cyttsp5_core_platform_data *pdata, static int cyttsp5_wakeup(struct cyttsp5_core_platform_data *pdata, struct device *dev, atomic_t *ignore_irq) { - return 0; + int ret =0; + + ret = cyttsp5_ts_power_control(pdata, dev, 1); + if(ret < 0) { + dev_err(dev, + "%s: Power on cyttsp5 failed = %d\n", __func__, ret); + return ret; + } + + return ret; } static int cyttsp5_sleep(struct cyttsp5_core_platform_data *pdata, struct device *dev, atomic_t *ignore_irq) { - return 0; + int ret =0; + + ret = cyttsp5_ts_power_control(pdata, dev, 0); + if(ret < 0) { + dev_err(dev, + "%s: Power off cyttsp5 failed = %d\n", __func__, ret); + return ret; + } + + return ret; } int cyttsp5_power(struct cyttsp5_core_platform_data *pdata, diff --git a/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_regs.h b/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_regs.h index b9cd1e02c2a4..105140976bc0 100644 --- a/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_regs.h +++ b/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_regs.h @@ -64,6 +64,7 @@ #include #include #include +#include //#define PT_PANEL_ID_FROM_MFG diff --git a/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_ts_mmi.c b/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_ts_mmi.c index 93d9463feb31..a71d8a2fd324 100644 --- a/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_ts_mmi.c +++ b/drivers/input/touchscreen/parade_tma5xx_mmi/cyttsp5_ts_mmi.c @@ -24,6 +24,9 @@ return -ENODEV; \ } +extern int cyttsp5_core_suspend(struct device *dev); +extern int cyttsp5_core_resume(struct device *dev); + static int cyttsp5_ts_mmi_methods_get_vendor(struct device *dev, void *cdata) { return scnprintf(TO_CHARP(cdata), TS_MMI_MAX_VENDOR_LEN, "%s", "parade"); } @@ -127,7 +130,12 @@ static int cyttsp5_ts_mmi_methods_get_drv_irq(struct device *dev, void *idata) { static int cyttsp5_ts_mmi_methods_get_poweron(struct device *dev, void *idata) { - TO_INT(idata) = 1; + struct cyttsp5_platform_data *pdata = dev_get_platdata(dev); + ASSERT_PTR(pdata); + + TO_INT(idata) = (regulator_is_enabled(pdata->core_pdata->avdd) && + regulator_is_enabled(pdata->core_pdata->iovdd)) ? 1 : 0; + return 0; } @@ -173,9 +181,103 @@ static int cyttsp5_ts_firmware_update(struct device *dev, char *fwname) { cd->force_fw_upgrade = 1; snprintf(cd->firmware_name, CYTTSP5_FIRMWARE_NAME_MAX_LEN, "%s", fwname); + if(cd->sleep_state != SS_SLEEP_OFF) { + dev_err(dev, "%s: Error, touch IC is on sleep state, can not do upgrade\n", + __func__); + return -EINVAL; + } + return cd->firmware_update(dev, fwname); } +static __maybe_unused int cyttsp5_ts_mmi_methods_drv_irq(struct device *dev, int state) { + int ret = -ENODEV; + struct cyttsp5_core_data *cd = dev_get_drvdata(dev); + ASSERT_PTR(cd); + + mutex_lock(&cd->system_lock); + switch (state) { + case 0: + if (cd->irq_enabled) { + cd->irq_enabled = false; + /* Disable IRQ */ + disable_irq_nosync(cd->irq); + dev_info(dev, "%s: Driver IRQ now disabled\n", + __func__); + } else + dev_info(dev, "%s: Driver IRQ already disabled\n", + __func__); + ret = 0; + break; + + case 1: + if (cd->irq_enabled == false) { + cd->irq_enabled = true; + /* Enable IRQ */ + enable_irq(cd->irq); + dev_info(dev, "%s: Driver IRQ now enabled\n", + __func__); + } else + dev_info(dev, "%s: Driver IRQ already enabled\n", + __func__); + ret = 0; + break; + + default: + dev_err(dev, "%s: Invalid value\n", __func__); + } + mutex_unlock(&(cd->system_lock)); + + return ret; +} + +static int cyttsp5_ts_mmi_methods_power(struct device *dev, int on) { + int rc = 0; + atomic_t is_ignore; + struct cyttsp5_core_data *cd = dev_get_drvdata(dev); + ASSERT_PTR(cd); + + atomic_set(&is_ignore, 1); + /* Call platform power function */ + if (cd->cpdata->power) { + dev_info(cd->dev, "%s: Touch IC power on/off \n", __func__); + if(on == TS_MMI_POWER_ON) + { + rc = cd->cpdata->power(cd->cpdata, TS_MMI_POWER_ON, cd->dev, &is_ignore); + if (rc) { + dev_info(cd->dev, "%s: Power on touch IC success\n", __func__); + rc = -ENODEV; + } + } + else if(on == TS_MMI_POWER_OFF) + { + rc = cd->cpdata->power(cd->cpdata, TS_MMI_POWER_OFF, cd->dev, &is_ignore); + if (rc) { + dev_info(cd->dev, "%s: Power on touch IC failed \n", __func__); + rc = -ENODEV; + } + } + } + else { + dev_info(cd->dev, "%s: No Power operation func\n", __func__); + rc = -ENODEV; + } + + return rc; +} + +static int cyttsp5_ts_mmi_post_suspend(struct device *dev) { + pr_info("%s: Post suspend end", __func__); + cyttsp5_core_suspend(dev); + return 0; +} + +static int cyttsp5_ts_mmi_post_resume(struct device *dev) { + pr_info("%s: Post resume end", __func__); + cyttsp5_core_resume(dev); + return 0; +} + static struct ts_mmi_methods cyttsp5_ts_mmi_methods = { .get_vendor = cyttsp5_ts_mmi_methods_get_vendor, .get_class_entry_name = cyttsp5_mmi_get_class_entry_name, @@ -189,8 +291,12 @@ static struct ts_mmi_methods cyttsp5_ts_mmi_methods = { .get_flashprog = cyttsp5_ts_mmi_methods_get_flashprog, /* SET methods */ .reset = cyttsp5_ts_mmi_methods_reset, + .power = cyttsp5_ts_mmi_methods_power, /* Firmware */ .firmware_update = cyttsp5_ts_firmware_update, + /* PM callback */ + .post_resume = cyttsp5_ts_mmi_post_resume, + .post_suspend = cyttsp5_ts_mmi_post_suspend, }; int cyttsp5_ts_mmi_dev_register(struct device *dev) { diff --git a/include/linux/cyttsp5_core.h b/include/linux/cyttsp5_core.h index 995184d00041..9c9fe09dbc31 100644 --- a/include/linux/cyttsp5_core.h +++ b/include/linux/cyttsp5_core.h @@ -124,6 +124,10 @@ struct cyttsp5_core_platform_data { u16 vendor_id; u16 product_id; const char *class_entry_name; + char avdd_name[CYTTSP5_MAX_STR_LABLE_LEN]; + char iovdd_name[CYTTSP5_MAX_STR_LABLE_LEN]; + struct regulator *avdd; + struct regulator *iovdd; int (*xres)(struct cyttsp5_core_platform_data *pdata, struct device *dev);