Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 98899f1f authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "input: it7258_ts_i2c: add gpio configuration support"

parents 1e746d12 1b0bf399
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ Required properties:
			  same as "interrupts" node. It will also
			  contain active low or active high information.
 - ite,reset-gpio	: reset gpio to control the reset of chip
 - ite,reset-delay	: reset delay for controller (ms), default 20

Optional properties:
 - avdd-supply		: Analog power supply needed to power device
@@ -41,6 +42,9 @@ Optional properties:
			config defined in pin groups of interrupt and reset gpio.
			"pmx_ts_release" : Release configuration of pins, this should specify
			release config defined in pin groups of interrupt and reset gpio.
 - ite,low-reset	: boolean, if the controller needs low-state of the reset gpio while
			  initializing, and reset gpio should be made as high-state to reset the
			  controller. It means the controller needs "active-high" reset gpio.

Required properties palm-detect-en feature:
 - ite,palm-detect-keycode	: The keycode that is required to be sent when
@@ -70,5 +74,7 @@ Example:
			ite,panel-coords = <0 0 320 320>;
			ite,display-coords = <0 0 320 320>;
			ite,num-fingers = <2>;
			ite,reset-delay = <20>;
			ite,low-reset;
		};
	};
+271 −89
Original line number Diff line number Diff line
@@ -124,12 +124,15 @@

#define IT_VTG_MIN_UV		1800000
#define IT_VTG_MAX_UV		1800000
#define IT_ACTIVE_LOAD_UA	15000
#define IT_I2C_VTG_MIN_UV	2600000
#define IT_I2C_VTG_MAX_UV	3300000
#define IT_I2C_ACTIVE_LOAD_UA	10000

#define PINCTRL_STATE_ACTIVE	"pmx_ts_active"
#define PINCTRL_STATE_SUSPEND	"pmx_ts_suspend"
#define PINCTRL_STATE_RELEASE	"pmx_ts_release"
#define IT_I2C_WAIT		1000

struct FingerData {
	uint8_t xLo;
@@ -163,6 +166,8 @@ struct IT7260_ts_platform_data {
	unsigned int disp_maxx;
	unsigned int disp_maxy;
	unsigned num_of_fingers;
	unsigned int reset_delay;
	bool low_reset;
};

struct IT7260_ts_data {
@@ -285,7 +290,7 @@ static bool IT7260_waitDeviceReady(bool forever, bool slowly)
			query = CMD_STATUS_BUSY;

		if (slowly)
			mdelay(1000);
			msleep(IT_I2C_WAIT);
		if (!forever)
			count--;

@@ -1153,6 +1158,226 @@ static bool IT7260_chipIdentify(void)
	return true;
}

static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA)
{
	return (regulator_count_voltages(reg) > 0) ?
		regulator_set_optimum_mode(reg, load_uA) : 0;
}

static int IT7260_regulator_configure(bool on)
{
	int retval;

	if (on == false)
		goto hw_shutdown;

	gl_ts->vdd = devm_regulator_get(&gl_ts->client->dev, "vdd");
	if (IS_ERR(gl_ts->vdd)) {
		dev_err(&gl_ts->client->dev,
				"%s: Failed to get vdd regulator\n", __func__);
		return PTR_ERR(gl_ts->vdd);
	}

	if (regulator_count_voltages(gl_ts->vdd) > 0) {
		retval = regulator_set_voltage(gl_ts->vdd,
			IT_VTG_MIN_UV, IT_VTG_MAX_UV);
		if (retval) {
			dev_err(&gl_ts->client->dev,
				"regulator set_vtg failed retval =%d\n",
				retval);
			goto err_set_vtg_vdd;
		}
	}

	gl_ts->avdd = devm_regulator_get(&gl_ts->client->dev, "avdd");
	if (IS_ERR(gl_ts->avdd)) {
		dev_err(&gl_ts->client->dev,
				"%s: Failed to get i2c regulator\n", __func__);
		retval = PTR_ERR(gl_ts->avdd);
		goto err_get_vtg_i2c;
	}

	if (regulator_count_voltages(gl_ts->avdd) > 0) {
		retval = regulator_set_voltage(gl_ts->avdd,
			IT_I2C_VTG_MIN_UV, IT_I2C_VTG_MAX_UV);
		if (retval) {
			dev_err(&gl_ts->client->dev,
				"reg set i2c vtg failed retval =%d\n",
				retval);
		goto err_set_vtg_i2c;
		}
	}

	return 0;

err_set_vtg_i2c:
err_get_vtg_i2c:
	if (regulator_count_voltages(gl_ts->vdd) > 0)
		regulator_set_voltage(gl_ts->vdd, 0, IT_VTG_MAX_UV);
err_set_vtg_vdd:
	return retval;

hw_shutdown:
	if (regulator_count_voltages(gl_ts->vdd) > 0)
		regulator_set_voltage(gl_ts->vdd, 0, IT_VTG_MAX_UV);
	if (regulator_count_voltages(gl_ts->avdd) > 0)
		regulator_set_voltage(gl_ts->avdd, 0, IT_I2C_VTG_MAX_UV);
	return 0;
};

static int IT7260_power_on(bool on)
{
	int retval;

	if (on == false)
		goto power_off;

	retval = reg_set_optimum_mode_check(gl_ts->vdd,
		IT_ACTIVE_LOAD_UA);
	if (retval < 0) {
		dev_err(&gl_ts->client->dev,
			"Regulator vdd set_opt failed rc=%d\n",
			retval);
		return retval;
	}

	retval = regulator_enable(gl_ts->vdd);
	if (retval) {
		dev_err(&gl_ts->client->dev,
			"Regulator vdd enable failed rc=%d\n",
			retval);
		goto error_reg_en_vdd;
	}

	retval = reg_set_optimum_mode_check(gl_ts->avdd,
		IT_I2C_ACTIVE_LOAD_UA);
	if (retval < 0) {
		dev_err(&gl_ts->client->dev,
			"Regulator avdd set_opt failed rc=%d\n",
			retval);
		goto error_reg_opt_i2c;
	}

	retval = regulator_enable(gl_ts->avdd);
	if (retval) {
		dev_err(&gl_ts->client->dev,
			"Regulator avdd enable failed rc=%d\n",
			retval);
		goto error_reg_en_avdd;
	}

	return 0;

error_reg_en_avdd:
	reg_set_optimum_mode_check(gl_ts->avdd, 0);
error_reg_opt_i2c:
	regulator_disable(gl_ts->vdd);
error_reg_en_vdd:
	reg_set_optimum_mode_check(gl_ts->vdd, 0);
	return retval;

power_off:
	reg_set_optimum_mode_check(gl_ts->vdd, 0);
	regulator_disable(gl_ts->vdd);
	reg_set_optimum_mode_check(gl_ts->avdd, 0);
	regulator_disable(gl_ts->avdd);

	return 0;
}

static int IT7260_gpio_configure(bool on)
{
	int retval = 0;

	if (on) {
		if (gpio_is_valid(gl_ts->pdata->irq_gpio)) {
			/* configure touchscreen irq gpio */
			retval = gpio_request(gl_ts->pdata->irq_gpio,
					"ite_irq_gpio");
			if (retval) {
				dev_err(&gl_ts->client->dev,
					"unable to request irq gpio [%d]\n",
					retval);
				goto err_irq_gpio_req;
			}

			retval = gpio_direction_input(gl_ts->pdata->irq_gpio);
			if (retval) {
				dev_err(&gl_ts->client->dev,
					"unable to set direction for irq gpio [%d]\n",
					retval);
				goto err_irq_gpio_dir;
			}
		} else {
			dev_err(&gl_ts->client->dev,
				"irq gpio not provided\n");
				goto err_irq_gpio_req;
		}

		if (gpio_is_valid(gl_ts->pdata->reset_gpio)) {
			/* configure touchscreen reset out gpio */
			retval = gpio_request(gl_ts->pdata->reset_gpio,
					"ite_reset_gpio");
			if (retval) {
				dev_err(&gl_ts->client->dev,
					"unable to request reset gpio [%d]\n",
					retval);
					goto err_reset_gpio_req;
			}

			retval = gpio_direction_output(
					gl_ts->pdata->reset_gpio, 1);
			if (retval) {
				dev_err(&gl_ts->client->dev,
					"unable to set direction for reset gpio [%d]\n",
					retval);
				goto err_reset_gpio_dir;
			}

			if (gl_ts->pdata->low_reset)
				gpio_set_value(gl_ts->pdata->reset_gpio, 0);
			else
				gpio_set_value(gl_ts->pdata->reset_gpio, 1);

			msleep(gl_ts->pdata->reset_delay);
		} else {
			dev_err(&gl_ts->client->dev,
				"reset gpio not provided\n");
				goto err_reset_gpio_req;
		}
	} else {
		if (gpio_is_valid(gl_ts->pdata->irq_gpio))
			gpio_free(gl_ts->pdata->irq_gpio);
		if (gpio_is_valid(gl_ts->pdata->reset_gpio)) {
			/*
			 * This is intended to save leakage current
			 * only. Even if the call(gpio_direction_input)
			 * fails, only leakage current will be more but
			 * functionality will not be affected.
			 */
			retval = gpio_direction_input(gl_ts->pdata->reset_gpio);
			if (retval) {
				dev_err(&gl_ts->client->dev,
					"unable to set direction for gpio reset [%d]\n",
					retval);
			}
			gpio_free(gl_ts->pdata->reset_gpio);
		}
	}

	return 0;

err_reset_gpio_dir:
	if (gpio_is_valid(gl_ts->pdata->reset_gpio))
		gpio_free(gl_ts->pdata->reset_gpio);
err_reset_gpio_req:
err_irq_gpio_dir:
	if (gpio_is_valid(gl_ts->pdata->irq_gpio))
		gpio_free(gl_ts->pdata->irq_gpio);
err_irq_gpio_req:
	return retval;
}

#if CONFIG_OF
static int IT7260_get_dt_coords(struct device *dev, char *name,
				struct IT7260_ts_platform_data *pdata)
@@ -1259,6 +1484,16 @@ static int IT7260_parse_dt(struct device *dev,
	snprintf(gl_ts->cfg_name, MAX_BUFFER_SIZE, "%s",
		(pdata->cfg_name != NULL) ? pdata->cfg_name : CFG_NAME);

	rc = of_property_read_u32(np, "ite,reset-delay", &temp_val);
	if (!rc)
		pdata->reset_delay = temp_val;
	else if (rc != -EINVAL) {
		dev_err(dev, "Unable to read reset delay\n");
		return rc;
	}

	pdata->low_reset = of_property_read_bool(np, "ite,low-reset");

	rc = IT7260_get_dt_coords(dev, "ite,display-coords", pdata);
	if (rc && (rc != -EINVAL))
		return rc;
@@ -1372,52 +1607,16 @@ static int IT7260_ts_probe(struct i2c_client *client,

	gl_ts->pdata = pdata;

	gl_ts->vdd = devm_regulator_get(&gl_ts->client->dev, "vdd");
	if (IS_ERR(gl_ts->vdd)) {
		dev_err(&client->dev,
				"Regulator get failed vdd\n");
		gl_ts->vdd = NULL;
	} else {
		ret = regulator_set_voltage(gl_ts->vdd,
				IT_VTG_MIN_UV, IT_VTG_MAX_UV);
		if (ret) {
			dev_err(&client->dev,
				"Regulator set_vtg failed vdd %d\n", ret);
			return ret;
		}
	}

	gl_ts->avdd = devm_regulator_get(&gl_ts->client->dev, "avdd");
	if (IS_ERR(gl_ts->avdd)) {
		dev_err(&client->dev,
				"Regulator get failed avdd\n");
		gl_ts->avdd = NULL;
	} else {
		ret = regulator_set_voltage(gl_ts->avdd, IT_I2C_VTG_MIN_UV,
							IT_I2C_VTG_MAX_UV);
		if (ret) {
			dev_err(&client->dev,
				"Regulator get failed avdd %d\n", ret);
			return ret;
		}
	}

	if (gl_ts->vdd) {
		ret = regulator_enable(gl_ts->vdd);
		if (ret) {
			dev_err(&gl_ts->client->dev,
				"Regulator vdd enable failed ret=%d\n", ret);
			return ret;
		}
	ret = IT7260_regulator_configure(true);
	if (ret < 0) {
		dev_err(&client->dev, "Failed to configure regulators\n");
		goto err_reg_configure;
	}

	if (gl_ts->avdd) {
		ret = regulator_enable(gl_ts->avdd);
		if (ret) {
			dev_err(&gl_ts->client->dev,
				"Regulator avdd enable failed ret=%d\n", ret);
			return ret;
		}
	ret = IT7260_power_on(true);
	if (ret < 0) {
		dev_err(&client->dev, "Failed to power on\n");
		goto err_power_device;
	}

	ret = IT7260_ts_pinctrl_init(gl_ts);
@@ -1434,32 +1633,12 @@ static int IT7260_ts_probe(struct i2c_client *client,
				"failed to select pin to active state %d",
				ret);
		}
	}

	/* reset gpio info */
	if (gpio_is_valid(pdata->reset_gpio)) {
		if (gpio_request(pdata->reset_gpio, "ite_reset_gpio")) {
			dev_err(&client->dev,
				"gpio_request failed for reset GPIO\n");
			return -EINVAL;
		}
		if (gpio_direction_output(pdata->reset_gpio, 0)) {
			dev_err(&client->dev,
				"gpio_direction_output for reset GPIO\n");
			return -EINVAL;
		}
		dev_dbg(&gl_ts->client->dev, "Reset GPIO %d\n",
							pdata->reset_gpio);
	} else {
		return pdata->reset_gpio;
		ret = IT7260_gpio_configure(true);
		if (ret < 0) {
			dev_err(&client->dev, "Failed to configure gpios\n");
			goto err_gpio_config;
		}

	/* irq gpio info */
	if (gpio_is_valid(pdata->irq_gpio)) {
		dev_dbg(&gl_ts->client->dev, "IRQ GPIO %d, IRQ # %d\n",
				pdata->irq_gpio, gpio_to_irq(pdata->irq_gpio));
	} else {
		return pdata->irq_gpio;
	}

	if (!IT7260_chipIdentify()) {
@@ -1533,9 +1712,9 @@ static int IT7260_ts_probe(struct i2c_client *client,
#endif
	
	IT7260_i2cWriteNoReadyCheck(BUF_COMMAND, cmd_start, sizeof(cmd_start));
	mdelay(10);
	msleep(pdata->reset_delay);
	IT7260_i2cReadNoReadyCheck(BUF_RESPONSE, rsp, sizeof(rsp));
	mdelay(10);
	msleep(pdata->reset_delay);

	gl_ts->dir = debugfs_create_dir(DEBUGFS_DIR_NAME, NULL);
	if (gl_ts->dir == NULL || IS_ERR(gl_ts->dir)) {
@@ -1584,11 +1763,6 @@ err_input_register:

err_input_alloc:
err_identification_fail:
	if (gpio_is_valid(pdata->reset_gpio))
		gpio_free(pdata->reset_gpio);
	if (gpio_is_valid(pdata->irq_gpio))
		gpio_free(pdata->irq_gpio);

	if (gl_ts->ts_pinctrl) {
		if (IS_ERR_OR_NULL(gl_ts->pinctrl_state_release)) {
			devm_pinctrl_put(gl_ts->ts_pinctrl);
@@ -1601,12 +1775,20 @@ err_identification_fail:
					"failed to select relase pinctrl state %d\n",
					ret);
		}
	} else {
		if (gpio_is_valid(pdata->reset_gpio))
			gpio_free(pdata->reset_gpio);
		if (gpio_is_valid(pdata->irq_gpio))
			gpio_free(pdata->irq_gpio);
	}
	regulator_disable(gl_ts->vdd);
	regulator_disable(gl_ts->avdd);
	regulator_put(gl_ts->vdd);
	regulator_put(gl_ts->avdd);

err_gpio_config:
	IT7260_power_on(false);

err_power_device:
	IT7260_regulator_configure(false);

err_reg_configure:
	return ret;
}

@@ -1629,10 +1811,6 @@ static int IT7260_ts_remove(struct i2c_client *client)
		cancel_work_sync(&gl_ts->work_pm_relax);
		device_init_wakeup(&client->dev, false);
	}
	if (gpio_is_valid(gl_ts->pdata->reset_gpio))
		gpio_free(gl_ts->pdata->reset_gpio);
	if (gpio_is_valid(gl_ts->pdata->irq_gpio))
		gpio_free(gl_ts->pdata->irq_gpio);
	if (gl_ts->ts_pinctrl) {
		if (IS_ERR_OR_NULL(gl_ts->pinctrl_state_release)) {
			devm_pinctrl_put(gl_ts->ts_pinctrl);
@@ -1645,11 +1823,15 @@ static int IT7260_ts_remove(struct i2c_client *client)
					"failed to select relase pinctrl state %d\n",
					ret);
		}
	} else {
		if (gpio_is_valid(gl_ts->pdata->reset_gpio))
			gpio_free(gl_ts->pdata->reset_gpio);
		if (gpio_is_valid(gl_ts->pdata->irq_gpio))
			gpio_free(gl_ts->pdata->irq_gpio);
	}
	regulator_disable(gl_ts->vdd);
	regulator_disable(gl_ts->avdd);
	regulator_put(gl_ts->vdd);
	regulator_put(gl_ts->avdd);
	IT7260_power_on(false);
	IT7260_regulator_configure(false);

	return 0;
}