goodix_gtx8_v1430_mmi: proper avdd/iovdd handling

Touch power supplies AVDD and IOVDD might not be always on and then
kernel driver needs to vote for them. Adding optional handling for
avdd and iovdd. Both power supplies can be configured in device tree

Change-Id: I9e22a4e1fe18c9d1e36defe7c98ce6c3852b722b
Signed-off-by: Konstantin Makariev <hcv867@motorola.com>
Reviewed-on: https://gerrit.mot.com/1428943
SLTApproved: Slta Waiver
SME-Granted: SME Approvals Granted
Tested-by: Jira Key
Reviewed-by: Konstantin Makariev <kmakariev@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
Konstantin Makariev 2019-09-26 17:12:17 -05:00 • committed by Konstantin Makariev
commit 80f24245c7
3 changed files with 70 additions and 48 deletions

View file

@ -1138,7 +1138,7 @@ static int goodix_ts_power_init(struct goodix_ts_core *core_data)
dev = core_data->ts_dev->dev;
ts_bdata = board_data(core_data);
if (strlen(ts_bdata->avdd_name)) {
if (ts_bdata->avdd_name) {
core_data->avdd = devm_regulator_get(dev,
ts_bdata->avdd_name);
if (IS_ERR_OR_NULL(core_data->avdd)) {
@ -1151,6 +1151,18 @@ static int goodix_ts_power_init(struct goodix_ts_core *core_data)
ts_info("Avdd name is NULL[skip]");
}
if (ts_bdata->iovdd_name) {
core_data->iovdd = devm_regulator_get(dev,
ts_bdata->iovdd_name);
if (IS_ERR_OR_NULL(core_data->iovdd)) {
r = PTR_ERR(core_data->iovdd);
ts_err("Failed to get regulator iovdd:%d", r);
core_data->iovdd = NULL;
}
} else {
ts_info("iovdd name is NULL");
}
return r;
}
@ -1162,30 +1174,36 @@ static int goodix_ts_power_init(struct goodix_ts_core *core_data)
int goodix_ts_power_on(struct goodix_ts_core *core_data)
{
struct goodix_ts_board_data *ts_bdata = board_data(core_data);
int r;
int r = 0;
ts_info("Device power on");
if (core_data->power_on)
return 0;
if (!core_data->avdd) {
core_data->power_on = 1;
return 0;
if (core_data->avdd) {
r = regulator_enable(core_data->avdd);
if (!r) {
ts_info("regulator enable SUCCESS");
if (ts_bdata->power_on_delay_us)
usleep_range(ts_bdata->power_on_delay_us,
ts_bdata->power_on_delay_us);
} else {
ts_err("Failed to enable avdd:%d", r);
goto err_exit;
}
}
r = regulator_enable(core_data->avdd);
if (!r) {
ts_info("regulator enable SUCCESS");
if (ts_bdata->power_on_delay_us)
usleep_range(ts_bdata->power_on_delay_us,
ts_bdata->power_on_delay_us);
} else {
ts_err("Failed to enable analog power:%d", r);
return r;
if (core_data->iovdd) {
r = regulator_enable(core_data->iovdd);
if (r) {
ts_err("Failed to enable iovdd:%d", r);
goto err_exit;
}
}
core_data->power_on = 1;
return 0;
err_exit:
return r;
}
/**
@ -1196,7 +1214,7 @@ int goodix_ts_power_on(struct goodix_ts_core *core_data)
int goodix_ts_power_off(struct goodix_ts_core *core_data)
{
struct goodix_ts_board_data *ts_bdata = board_data(core_data);
int r;
int r = 0;
ts_info("Device power off");
if (!core_data->power_on)
@ -1210,13 +1228,22 @@ int goodix_ts_power_off(struct goodix_ts_core *core_data)
usleep_range(ts_bdata->power_off_delay_us,
ts_bdata->power_off_delay_us);
} else {
ts_err("Failed to disable analog power:%d", r);
return r;
ts_err("Failed to disable avdd:%d", r);
goto err_exit;
}
}
if (core_data->iovdd) {
r = regulator_disable(core_data->iovdd);
if (r) {
ts_err("Failed to disable iovdd:%d", r);
goto err_exit;
}
}
core_data->power_on = 0;
return 0;
err_exit:
return r;
}
#ifdef CONFIG_PINCTRL

View file

@ -110,7 +110,8 @@ struct goodix_module {
* @fw_name: name of the firmware image
*/
struct goodix_ts_board_data {
char avdd_name[24];
const char *avdd_name;
const char *iovdd_name;
unsigned int reset_gpio;
unsigned int irq_gpio;
int irq;
@ -435,6 +436,7 @@ struct goodix_ts_core {
struct input_dev *pen_dev;
struct regulator *avdd;
struct regulator *iovdd;
#ifdef CONFIG_PINCTRL
struct pinctrl *pinctrl;
struct pinctrl_state *pin_sta_active;

View file

@ -125,6 +125,19 @@ static int goodix_parse_dt_resolution(struct device_node *node,
return 0;
}
static const char *goodix_parse_dt_text(struct device_node *node,
const char *name)
{
const char *prop = NULL;
int r;
r = of_property_read_string(node, name, &prop);
if (r) {
ts_err("%s: error reading property = %d", name, r);
}
return prop;
}
/**
* goodix_parse_dt - parse board data from dt
* @dev: pointer to device
@ -135,7 +148,6 @@ static int goodix_parse_dt(struct device_node *node,
struct goodix_ts_board_data *board_data)
{
struct property *prop;
const char *name_tmp;
int r;
if (!board_data) {
@ -166,34 +178,15 @@ static int goodix_parse_dt(struct device_node *node,
return -EINVAL;
}
board_data->cfg_bin_name = kzalloc(32 * sizeof(char), GFP_KERNEL);
r = of_property_read_string(node, "goodix,cfg_bin_name",
&board_data->cfg_bin_name);
if (r) {
ts_err("Unable to read cfg name %d\n", r);
board_data->cfg_bin_name = NULL;
}
board_data->cfg_bin_name = goodix_parse_dt_text(node,
"goodix,cfg_bin_name");
board_data->fw_name = goodix_parse_dt_text(node,
"goodix,fw_name");
board_data->avdd_name = goodix_parse_dt_text(node,
"goodix,avdd-name");
board_data->iovdd_name = goodix_parse_dt_text(node,
"goodix,iovdd-name");
board_data->fw_name = kzalloc(32 * sizeof(char), GFP_KERNEL);
r = of_property_read_string(node, "goodix,fw_name",
&board_data->fw_name);
if (r) {
ts_err("Unable to read fw name %d\n", r);
board_data->fw_name = NULL;
}
memset(board_data->avdd_name, 0, sizeof(board_data->avdd_name));
r = of_property_read_string(node, "goodix,avdd-name", &name_tmp);
if (!r) {
ts_info("avdd name form dt: %s", name_tmp);
if (strlen(name_tmp) < sizeof(board_data->avdd_name))
strncpy(board_data->avdd_name,
name_tmp, sizeof(board_data->avdd_name));
else
ts_info("invalied avdd name length: %ld > %ld",
strlen(name_tmp),
sizeof(board_data->avdd_name));
}
r = of_property_read_u32(node, "goodix,power-on-delay-us",
&board_data->power_on_delay_us);
if (!r) {