From ce40bdb1a97336d35eeec79ef7b714209d4bf112 Mon Sep 17 00:00:00 2001 From: litong20 Date: Wed, 17 Nov 2021 12:52:53 +0800 Subject: [PATCH] support pmk8350 gpio3 as stylus clk. TP: Support Pmk8350 gpio3 as the stylus clock for Rogue PVT, and the output frequency is 19.2Mhz. Change-Id: I5dae054b6170b921b7afee1853b7de7995531705 Reviewed-on: https://gerrit.mot.com/2111742 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Jianqi Yang Submit-Approved: Jira Key --- .../goodix_berlin_mmi/goodix_ts_core.c | 77 ++++++++++++++-- .../goodix_berlin_mmi/goodix_ts_core.h | 8 ++ .../goodix_berlin_mmi/goodix_ts_mmi.c | 88 ++++++++++++++++--- 3 files changed, 152 insertions(+), 21 deletions(-) diff --git a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.c b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.c index 94f2f4118ff9..b131ccb5d4ae 100644 --- a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.c +++ b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.c @@ -1087,8 +1087,15 @@ static int goodix_parse_dt(struct device_node *node, board_data->stylus_mode_ctrl = of_property_read_bool(node, "goodix,stylus_mode-ctrl"); - if (board_data->stylus_mode_ctrl) + if (board_data->stylus_mode_ctrl) { ts_info("support goodix stylus mode"); + /* get stylus clock name */ + r = of_property_read_string(node, "goodix,stylus-clk-source", &name_tmp); + if (!r) { + ts_info("stylus clk source from source %s", name_tmp); + strncpy(board_data->stylus_clk_src, name_tmp, sizeof(board_data->stylus_clk_src)); + } + } board_data->sensitivity_ctrl = of_property_read_bool(node, "goodix,sensitivity-ctrl"); @@ -1377,6 +1384,61 @@ int goodix_ts_power_off(struct goodix_ts_core *cd) return ret; } +/** + * goodix_ts_stylus_clk_init - Config stylus clock + * return:0 ok, <0 failed + */ +static int goodix_ts_stylus_clk_init(struct goodix_ts_core *core_data) +{ + int ret = 0; + struct goodix_ts_board_data *ts_bdata = board_data(core_data); + struct goodix_bus_interface *bus_interface = core_data->bus; + if (!ts_bdata->stylus_mode_ctrl) { + ts_err("stylus not support!"); + return -EINVAL; + } + if (!strcmp(ts_bdata->stylus_clk_src, STYLUS_CLK_SRC_PMIC)) { + if (of_get_property(bus_interface->dev->of_node, "clocks", NULL)) { + core_data->stylus_clk = devm_clk_get(bus_interface->dev, "stylus_clk"); + if (IS_ERR_OR_NULL(core_data->stylus_clk)) { + ts_err("failed to get stylus clk\n"); + return -EINVAL; + } + } + } else if (!strcmp(ts_bdata->stylus_clk_src, STYLUS_CLK_SRC_GPIO)){ + if (IS_ERR_OR_NULL(core_data->pinctrl)) { + ts_info("Failed to get pinctrl handler[need confirm]"); + core_data->pinctrl = NULL; + return -EINVAL; + } + core_data->stylus_clk_active = pinctrl_lookup_state(core_data->pinctrl, + PINCTRL_STYLUS_CLK_ACTIVE); + if (IS_ERR_OR_NULL(core_data->stylus_clk_active)) { + ret = PTR_ERR(core_data->stylus_clk_active); + ts_err("Failed to get state clk pinctrl state:%s, ret:%d", + PINCTRL_STYLUS_CLK_ACTIVE, ret); + core_data->stylus_clk_active = NULL; + return ret; + } + ts_info("success get stylus clk pinctrl active state"); + + core_data->stylus_clk_suspend = pinctrl_lookup_state(core_data->pinctrl, + PINCTRL_STYLUS_CLK_SUSPEND); + if (IS_ERR_OR_NULL(core_data->stylus_clk_suspend)) { + ret = PTR_ERR(core_data->stylus_clk_suspend); + ts_err("Failed to get state clk pinctrl state:%s, ret:%d", + PINCTRL_STYLUS_CLK_SUSPEND, ret); + core_data->stylus_clk_suspend = NULL; + return ret; + } + ts_info("success get stylus clk pinctrl suspend state"); + } else { + ts_err("The stylus clock source is invalid"); + return -EINVAL; + } + + return ret; +} /** * goodix_ts_pinctrl_init - Get pinctrl handler and pinctrl_state @@ -2235,14 +2297,6 @@ static int goodix_ts_probe(struct platform_device *pdev) ts_err("failed parse device info form dts, %d", ret); return -EINVAL; } - - if (of_get_property(bus_interface->dev->of_node, "clocks", NULL)) { - core_data->stylus_clk = devm_clk_get(bus_interface->dev, "stylus_clk"); - if (IS_ERR_OR_NULL(core_data->stylus_clk)) { - ts_err("failed to get stylus clk\n"); - } - } - } else { ts_err("no valid device tree node found"); return -ENODEV; @@ -2288,6 +2342,11 @@ static int goodix_ts_probe(struct platform_device *pdev) ts_err("Failed to select active pinstate, r:%d", ret); } + /* get stylus clock*/ + ret = goodix_ts_stylus_clk_init(core_data); + if (ret) + ts_err("failed get goodix stylus clock"); + /* confirm it's goodix touch dev or not */ ret = core_data->hw_ops->dev_confirm(core_data); if (ret) { diff --git a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.h b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.h index 83766fce393e..5db68daba2ed 100644 --- a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.h +++ b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.h @@ -46,6 +46,11 @@ #define TS_DEFAULT_FIRMWARE "goodix_firmware.bin" #define TS_DEFAULT_CFG_BIN "goodix_cfg_group.bin" +#define PINCTRL_STYLUS_CLK_ACTIVE "stylus_clk_active" +#define PINCTRL_STYLUS_CLK_SUSPEND "stylus_clk_suspend" +#define STYLUS_CLK_SRC_GPIO "stylus_clk_gpio" +#define STYLUS_CLK_SRC_PMIC "stylus_clk_pmic" + enum CORD_PROB_STA { CORE_MODULE_UNPROBED = 0, CORE_MODULE_PROB_SUCCESS = 1, @@ -269,6 +274,7 @@ struct goodix_ts_board_data { bool pen_enable; char fw_name[GOODIX_MAX_STR_LABLE_LEN]; char cfg_bin_name[GOODIX_MAX_STR_LABLE_LEN]; + char stylus_clk_src[GOODIX_MAX_STR_LABLE_LEN]; /*stylus clock source*/ bool sensitivity_ctrl; bool stylus_mode_ctrl; @@ -468,6 +474,8 @@ struct goodix_ts_core { struct pinctrl *pinctrl; struct pinctrl_state *pin_sta_active; struct pinctrl_state *pin_sta_suspend; + struct pinctrl_state *stylus_clk_active; + struct pinctrl_state *stylus_clk_suspend; int power_on; int irq; diff --git a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_mmi.c b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_mmi.c index e7fa4cc512a8..1b616407acd1 100644 --- a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_mmi.c +++ b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_mmi.c @@ -189,27 +189,85 @@ static ssize_t goodix_ts_sensitivity_store(struct device *dev, return ret; } +static int goodix_clock_enable(struct goodix_ts_core *core_data, bool mode) { + int ret = 0; + struct goodix_ts_board_data *ts_bdata; + + ts_bdata = board_data(core_data); + if (!ts_bdata) { + ts_err("Failed to get ts board data"); + return -ENODEV; + } + + if (mode) { + if (!strcmp(ts_bdata->stylus_clk_src, STYLUS_CLK_SRC_PMIC)) { + if (IS_ERR_OR_NULL(core_data->stylus_clk)) { + ts_err("failed to get stylus clk\n"); + return -EINVAL; + } + ret = clk_prepare_enable(core_data->stylus_clk); + if (ret) { + ts_err("failed to enable stylus clk\n"); + return ret; + } + } else if (!strcmp(ts_bdata->stylus_clk_src, STYLUS_CLK_SRC_GPIO)){ + if (IS_ERR_OR_NULL(core_data->stylus_clk_active)) { + ts_err("Failed to get state clk pinctrl state:%s", + PINCTRL_STYLUS_CLK_ACTIVE); + core_data->stylus_clk_active = NULL; + return -EINVAL; + } + ret = pinctrl_select_state(core_data->pinctrl, + core_data->stylus_clk_active); + if (ret < 0) { + ts_err("Failed to select active stylus clk state, ret:%d", ret); + return ret; + } + } else { + ts_err("stylus clock source is invalid"); + return -EINVAL; + } + ts_info("success to enable stylus clk\n"); + } else { + if (!strcmp(ts_bdata->stylus_clk_src, STYLUS_CLK_SRC_PMIC)) { + if (IS_ERR_OR_NULL(core_data->stylus_clk)) { + ts_err("failed to get stylus clk\n"); + return -EINVAL; + } + clk_disable_unprepare(core_data->stylus_clk); + } else if (!strcmp(ts_bdata->stylus_clk_src, STYLUS_CLK_SRC_GPIO)){ + if (IS_ERR_OR_NULL(core_data->stylus_clk_suspend)) { + ts_err("Failed to get state clk pinctrl state:%s", + PINCTRL_STYLUS_CLK_SUSPEND); + core_data->stylus_clk_suspend = NULL; + return -EINVAL; + } + ret = pinctrl_select_state(core_data->pinctrl, + core_data->stylus_clk_suspend); + if (ret < 0) { + ts_err("Failed to select stylus clk suspend state, ret:%d", ret); + return ret; + } + } else { + ts_err("stylus clock source is invalid"); + return -EINVAL; + } + ts_info("success to disable stylus clk\n"); + } + return ret; +} + static int goodix_stylus_mode(struct goodix_ts_core *core_data, int mode) { int ret = 0; - if (IS_ERR_OR_NULL(core_data->stylus_clk)) { - ts_err("failed to get stylus clk\n"); - return -EINVAL; - } if (mode) { - ret = clk_prepare_enable(core_data->stylus_clk); - if (ret) { - ts_err("failed to enable stylus clk\n"); - return ret; - } - ts_info("success to open stylus clk\n"); + goodix_clock_enable(core_data, mode); ret = goodix_ts_send_cmd(core_data, STYLUS_MODE_SWITCH_CMD, 5, mode, 0x00); msleep(20); } else { ret = goodix_ts_send_cmd(core_data, STYLUS_MODE_SWITCH_CMD, 5, mode, 0x00); msleep(20); - clk_disable_unprepare(core_data->stylus_clk); - ts_info("success to close stylus clk\n"); + goodix_clock_enable(core_data, mode); } return ret; @@ -239,6 +297,12 @@ static ssize_t goodix_ts_stylus_mode_store(struct device *dev, return size; } + if (core_data->power_on == 0) { + core_data->stylus_mode = mode; + ts_debug("The touch is in sleep state, restore the value when resume\n"); + return size; + } + ret = goodix_stylus_mode(core_data, mode); if (ret) { return ret;