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

Commit 6136f97c authored by Stephen Boyd's avatar Stephen Boyd Committed by Jiri Kosina
Browse files

HID: i2c-hid: Add vddl regulator control



Some wacom w9013 devices have a vddl supply for "low valtage"
requirements. Add support in this driver to turn on this low voltage
supply. We can also drop a handful of error messages because the
regulator core is already printing an error when bulk regulators fail to
enable or disable.

Cc: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Cc: Hans de Goede <hdegoede@redhat.com>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Dmitry Torokhov <dtor@chromium.org>
Cc: Doug Anderson <dianders@chromium.org>
Acked-by: default avatarRob Herring <robh@kernel.org>
Cc: <devicetree@vger.kernel.org>
Signed-off-by: default avatarStephen Boyd <swboyd@chromium.org>
Acked-by: default avatarBenjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent d6f83894
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -26,7 +26,8 @@ device-specific compatible properties, which should be used in addition to the


- compatible:
- compatible:
  * "wacom,w9013" (Wacom W9013 digitizer). Supports:
  * "wacom,w9013" (Wacom W9013 digitizer). Supports:
    - vdd-supply
    - vdd-supply (3.3V)
    - vddl-supply (1.8V)
    - post-power-on-delay-ms
    - post-power-on-delay-ms


- vdd-supply: phandle of the regulator that provides the supply voltage.
- vdd-supply: phandle of the regulator that provides the supply voltage.
+24 −24
Original line number Original line Diff line number Diff line
@@ -1021,21 +1021,20 @@ static int i2c_hid_probe(struct i2c_client *client,
	/* Parse platform agnostic common properties from ACPI / device tree */
	/* Parse platform agnostic common properties from ACPI / device tree */
	i2c_hid_fwnode_probe(client, &ihid->pdata);
	i2c_hid_fwnode_probe(client, &ihid->pdata);


	ihid->pdata.supply = devm_regulator_get(&client->dev, "vdd");
	ihid->pdata.supplies[0].supply = "vdd";
	if (IS_ERR(ihid->pdata.supply)) {
	ihid->pdata.supplies[1].supply = "vddl";
		ret = PTR_ERR(ihid->pdata.supply);

		if (ret != -EPROBE_DEFER)
	ret = devm_regulator_bulk_get(&client->dev,
			dev_err(&client->dev, "Failed to get regulator: %d\n",
				      ARRAY_SIZE(ihid->pdata.supplies),
				ret);
				      ihid->pdata.supplies);
		goto err;
	if (ret)
	}
		return ret;

	ret = regulator_bulk_enable(ARRAY_SIZE(ihid->pdata.supplies),
				    ihid->pdata.supplies);
	if (ret < 0)
		return ret;


	ret = regulator_enable(ihid->pdata.supply);
	if (ret < 0) {
		dev_err(&client->dev, "Failed to enable regulator: %d\n",
			ret);
		goto err;
	}
	if (ihid->pdata.post_power_delay_ms)
	if (ihid->pdata.post_power_delay_ms)
		msleep(ihid->pdata.post_power_delay_ms);
		msleep(ihid->pdata.post_power_delay_ms);


@@ -1122,9 +1121,8 @@ static int i2c_hid_probe(struct i2c_client *client,
	pm_runtime_disable(&client->dev);
	pm_runtime_disable(&client->dev);


err_regulator:
err_regulator:
	regulator_disable(ihid->pdata.supply);
	regulator_bulk_disable(ARRAY_SIZE(ihid->pdata.supplies),

			       ihid->pdata.supplies);
err:
	i2c_hid_free_buffers(ihid);
	i2c_hid_free_buffers(ihid);
	return ret;
	return ret;
}
}
@@ -1147,7 +1145,8 @@ static int i2c_hid_remove(struct i2c_client *client)
	if (ihid->bufsize)
	if (ihid->bufsize)
		i2c_hid_free_buffers(ihid);
		i2c_hid_free_buffers(ihid);


	regulator_disable(ihid->pdata.supply);
	regulator_bulk_disable(ARRAY_SIZE(ihid->pdata.supplies),
			       ihid->pdata.supplies);


	return 0;
	return 0;
}
}
@@ -1198,9 +1197,8 @@ static int i2c_hid_suspend(struct device *dev)
			hid_warn(hid, "Failed to enable irq wake: %d\n",
			hid_warn(hid, "Failed to enable irq wake: %d\n",
				wake_status);
				wake_status);
	} else {
	} else {
		ret = regulator_disable(ihid->pdata.supply);
		regulator_bulk_disable(ARRAY_SIZE(ihid->pdata.supplies),
		if (ret < 0)
				       ihid->pdata.supplies);
			hid_warn(hid, "Failed to disable supply: %d\n", ret);
	}
	}


	return 0;
	return 0;
@@ -1215,9 +1213,11 @@ static int i2c_hid_resume(struct device *dev)
	int wake_status;
	int wake_status;


	if (!device_may_wakeup(&client->dev)) {
	if (!device_may_wakeup(&client->dev)) {
		ret = regulator_enable(ihid->pdata.supply);
		ret = regulator_bulk_enable(ARRAY_SIZE(ihid->pdata.supplies),
		if (ret < 0)
					    ihid->pdata.supplies);
			hid_warn(hid, "Failed to enable supply: %d\n", ret);
		if (ret)
			hid_warn(hid, "Failed to enable supplies: %d\n", ret);

		if (ihid->pdata.post_power_delay_ms)
		if (ihid->pdata.post_power_delay_ms)
			msleep(ihid->pdata.post_power_delay_ms);
			msleep(ihid->pdata.post_power_delay_ms);
	} else if (ihid->irq_wake_enabled) {
	} else if (ihid->irq_wake_enabled) {
+3 −4
Original line number Original line Diff line number Diff line
@@ -12,14 +12,13 @@
#ifndef __LINUX_I2C_HID_H
#ifndef __LINUX_I2C_HID_H
#define __LINUX_I2C_HID_H
#define __LINUX_I2C_HID_H


#include <linux/regulator/consumer.h>
#include <linux/types.h>
#include <linux/types.h>


struct regulator;

/**
/**
 * struct i2chid_platform_data - used by hid over i2c implementation.
 * struct i2chid_platform_data - used by hid over i2c implementation.
 * @hid_descriptor_address: i2c register where the HID descriptor is stored.
 * @hid_descriptor_address: i2c register where the HID descriptor is stored.
 * @supply: regulator for powering on the device.
 * @supplies: regulators for powering on the device.
 * @post_power_delay_ms: delay after powering on before device is usable.
 * @post_power_delay_ms: delay after powering on before device is usable.
 *
 *
 * Note that it is the responsibility of the platform driver (or the acpi 5.0
 * Note that it is the responsibility of the platform driver (or the acpi 5.0
@@ -35,7 +34,7 @@ struct regulator;
 */
 */
struct i2c_hid_platform_data {
struct i2c_hid_platform_data {
	u16 hid_descriptor_address;
	u16 hid_descriptor_address;
	struct regulator *supply;
	struct regulator_bulk_data supplies[2];
	int post_power_delay_ms;
	int post_power_delay_ms;
};
};