mirror of
https://github.com/torvalds/linux.git
synced 2024-12-30 23:02:08 +00:00
Merge branch 'for-6.3/i2c-hid' into for-linus
- dev_dbg cleanup (Thomas Weißschuh) - cleanup i2c-hid-acpi (Andy Shevchenko) - goodix: revert/fixes for an actual production device compared to the manufacturer sample (Douglas Anderson)
This commit is contained in:
commit
0f7566c7e5
@ -36,6 +36,13 @@ properties:
|
||||
vdd-supply:
|
||||
description: The 3.3V supply to the touchscreen.
|
||||
|
||||
mainboard-vddio-supply:
|
||||
description:
|
||||
The supply on the main board needed to power up IO signals going
|
||||
to the touchscreen. This supply need not go to the touchscreen
|
||||
itself as long as it allows the main board to make signals compatible
|
||||
with what the touchscreen is expecting for its IO rails.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -39,8 +39,8 @@ static const struct acpi_device_id i2c_hid_acpi_blacklist[] = {
|
||||
* The CHPN0001 ACPI device, which is used to describe the Chipone
|
||||
* ICN8505 controller, has a _CID of PNP0C50 but is not HID compatible.
|
||||
*/
|
||||
{"CHPN0001", 0 },
|
||||
{ },
|
||||
{ "CHPN0001" },
|
||||
{ }
|
||||
};
|
||||
|
||||
/* HID I²C Device: 3cdff6f7-4267-4555-ad05-b30a3d8938de */
|
||||
@ -48,8 +48,9 @@ static guid_t i2c_hid_guid =
|
||||
GUID_INIT(0x3CDFF6F7, 0x4267, 0x4555,
|
||||
0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE);
|
||||
|
||||
static int i2c_hid_acpi_get_descriptor(struct acpi_device *adev)
|
||||
static int i2c_hid_acpi_get_descriptor(struct i2c_hid_acpi *ihid_acpi)
|
||||
{
|
||||
struct acpi_device *adev = ihid_acpi->adev;
|
||||
acpi_handle handle = acpi_device_handle(adev);
|
||||
union acpi_object *obj;
|
||||
u16 hid_descriptor_address;
|
||||
@ -81,38 +82,31 @@ static int i2c_hid_acpi_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct i2c_hid_acpi *ihid_acpi;
|
||||
struct acpi_device *adev;
|
||||
u16 hid_descriptor_address;
|
||||
int ret;
|
||||
|
||||
adev = ACPI_COMPANION(dev);
|
||||
if (!adev) {
|
||||
dev_err(&client->dev, "Error could not get ACPI device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ihid_acpi = devm_kzalloc(&client->dev, sizeof(*ihid_acpi), GFP_KERNEL);
|
||||
if (!ihid_acpi)
|
||||
return -ENOMEM;
|
||||
|
||||
ihid_acpi->adev = adev;
|
||||
ihid_acpi->adev = ACPI_COMPANION(dev);
|
||||
ihid_acpi->ops.shutdown_tail = i2c_hid_acpi_shutdown_tail;
|
||||
|
||||
ret = i2c_hid_acpi_get_descriptor(adev);
|
||||
ret = i2c_hid_acpi_get_descriptor(ihid_acpi);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
hid_descriptor_address = ret;
|
||||
|
||||
acpi_device_fix_up_power(adev);
|
||||
acpi_device_fix_up_power(ihid_acpi->adev);
|
||||
|
||||
return i2c_hid_core_probe(client, &ihid_acpi->ops,
|
||||
hid_descriptor_address, 0);
|
||||
}
|
||||
|
||||
static const struct acpi_device_id i2c_hid_acpi_match[] = {
|
||||
{"ACPI0C50", 0 },
|
||||
{"PNP0C50", 0 },
|
||||
{ },
|
||||
{ "ACPI0C50" },
|
||||
{ "PNP0C50" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, i2c_hid_acpi_match);
|
||||
|
||||
|
@ -67,16 +67,7 @@
|
||||
#define I2C_HID_PWR_ON 0x00
|
||||
#define I2C_HID_PWR_SLEEP 0x01
|
||||
|
||||
/* debug option */
|
||||
static bool debug;
|
||||
module_param(debug, bool, 0444);
|
||||
MODULE_PARM_DESC(debug, "print a lot of debug information");
|
||||
|
||||
#define i2c_hid_dbg(ihid, fmt, arg...) \
|
||||
do { \
|
||||
if (debug) \
|
||||
dev_printk(KERN_DEBUG, &(ihid)->client->dev, fmt, ##arg); \
|
||||
} while (0)
|
||||
#define i2c_hid_dbg(ihid, ...) dev_dbg(&(ihid)->client->dev, __VA_ARGS__)
|
||||
|
||||
struct i2c_hid_desc {
|
||||
__le16 wHIDDescLength;
|
||||
@ -858,7 +849,7 @@ static int i2c_hid_init_irq(struct i2c_client *client)
|
||||
unsigned long irqflags = 0;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&client->dev, "Requesting IRQ: %d\n", client->irq);
|
||||
i2c_hid_dbg(ihid, "Requesting IRQ: %d\n", client->irq);
|
||||
|
||||
if (!irq_get_trigger_type(client->irq))
|
||||
irqflags = IRQF_TRIGGER_LOW;
|
||||
@ -1002,7 +993,7 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
|
||||
/* Make sure there is something at this address */
|
||||
ret = i2c_smbus_read_byte(client);
|
||||
if (ret < 0) {
|
||||
dev_dbg(&client->dev, "nothing at this address: %d\n", ret);
|
||||
i2c_hid_dbg(ihid, "nothing at this address: %d\n", ret);
|
||||
ret = -ENXIO;
|
||||
goto err_powered;
|
||||
}
|
||||
|
@ -26,28 +26,33 @@ struct i2c_hid_of_goodix {
|
||||
struct i2chid_ops ops;
|
||||
|
||||
struct regulator *vdd;
|
||||
struct notifier_block nb;
|
||||
struct regulator *vddio;
|
||||
struct gpio_desc *reset_gpio;
|
||||
const struct goodix_i2c_hid_timing_data *timings;
|
||||
};
|
||||
|
||||
static void goodix_i2c_hid_deassert_reset(struct i2c_hid_of_goodix *ihid_goodix,
|
||||
bool regulator_just_turned_on)
|
||||
{
|
||||
if (regulator_just_turned_on && ihid_goodix->timings->post_power_delay_ms)
|
||||
msleep(ihid_goodix->timings->post_power_delay_ms);
|
||||
|
||||
gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 0);
|
||||
if (ihid_goodix->timings->post_gpio_reset_delay_ms)
|
||||
msleep(ihid_goodix->timings->post_gpio_reset_delay_ms);
|
||||
}
|
||||
|
||||
static int goodix_i2c_hid_power_up(struct i2chid_ops *ops)
|
||||
{
|
||||
struct i2c_hid_of_goodix *ihid_goodix =
|
||||
container_of(ops, struct i2c_hid_of_goodix, ops);
|
||||
int ret;
|
||||
|
||||
return regulator_enable(ihid_goodix->vdd);
|
||||
ret = regulator_enable(ihid_goodix->vdd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regulator_enable(ihid_goodix->vddio);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ihid_goodix->timings->post_power_delay_ms)
|
||||
msleep(ihid_goodix->timings->post_power_delay_ms);
|
||||
|
||||
gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 0);
|
||||
if (ihid_goodix->timings->post_gpio_reset_delay_ms)
|
||||
msleep(ihid_goodix->timings->post_gpio_reset_delay_ms);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void goodix_i2c_hid_power_down(struct i2chid_ops *ops)
|
||||
@ -55,42 +60,15 @@ static void goodix_i2c_hid_power_down(struct i2chid_ops *ops)
|
||||
struct i2c_hid_of_goodix *ihid_goodix =
|
||||
container_of(ops, struct i2c_hid_of_goodix, ops);
|
||||
|
||||
gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 1);
|
||||
regulator_disable(ihid_goodix->vddio);
|
||||
regulator_disable(ihid_goodix->vdd);
|
||||
}
|
||||
|
||||
static int ihid_goodix_vdd_notify(struct notifier_block *nb,
|
||||
unsigned long event,
|
||||
void *ignored)
|
||||
{
|
||||
struct i2c_hid_of_goodix *ihid_goodix =
|
||||
container_of(nb, struct i2c_hid_of_goodix, nb);
|
||||
int ret = NOTIFY_OK;
|
||||
|
||||
switch (event) {
|
||||
case REGULATOR_EVENT_PRE_DISABLE:
|
||||
gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 1);
|
||||
break;
|
||||
|
||||
case REGULATOR_EVENT_ENABLE:
|
||||
goodix_i2c_hid_deassert_reset(ihid_goodix, true);
|
||||
break;
|
||||
|
||||
case REGULATOR_EVENT_ABORT_DISABLE:
|
||||
goodix_i2c_hid_deassert_reset(ihid_goodix, false);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = NOTIFY_DONE;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int i2c_hid_of_goodix_probe(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_hid_of_goodix *ihid_goodix;
|
||||
int ret;
|
||||
|
||||
ihid_goodix = devm_kzalloc(&client->dev, sizeof(*ihid_goodix),
|
||||
GFP_KERNEL);
|
||||
if (!ihid_goodix)
|
||||
@ -109,42 +87,12 @@ static int i2c_hid_of_goodix_probe(struct i2c_client *client)
|
||||
if (IS_ERR(ihid_goodix->vdd))
|
||||
return PTR_ERR(ihid_goodix->vdd);
|
||||
|
||||
ihid_goodix->vddio = devm_regulator_get(&client->dev, "mainboard-vddio");
|
||||
if (IS_ERR(ihid_goodix->vddio))
|
||||
return PTR_ERR(ihid_goodix->vddio);
|
||||
|
||||
ihid_goodix->timings = device_get_match_data(&client->dev);
|
||||
|
||||
/*
|
||||
* We need to control the "reset" line in lockstep with the regulator
|
||||
* actually turning on an off instead of just when we make the request.
|
||||
* This matters if the regulator is shared with another consumer.
|
||||
* - If the regulator is off then we must assert reset. The reset
|
||||
* line is active low and on some boards it could cause a current
|
||||
* leak if left high.
|
||||
* - If the regulator is on then we don't want reset asserted for very
|
||||
* long. Holding the controller in reset apparently draws extra
|
||||
* power.
|
||||
*/
|
||||
ihid_goodix->nb.notifier_call = ihid_goodix_vdd_notify;
|
||||
ret = devm_regulator_register_notifier(ihid_goodix->vdd, &ihid_goodix->nb);
|
||||
if (ret)
|
||||
return dev_err_probe(&client->dev, ret,
|
||||
"regulator notifier request failed\n");
|
||||
|
||||
/*
|
||||
* If someone else is holding the regulator on (or the regulator is
|
||||
* an always-on one) we might never be told to deassert reset. Do it
|
||||
* now... and temporarily bump the regulator reference count just to
|
||||
* make sure it is impossible for this to race with our own notifier!
|
||||
* We also assume that someone else might have _just barely_ turned
|
||||
* the regulator on so we'll do the full "post_power_delay" just in
|
||||
* case.
|
||||
*/
|
||||
if (ihid_goodix->reset_gpio && regulator_is_enabled(ihid_goodix->vdd)) {
|
||||
ret = regulator_enable(ihid_goodix->vdd);
|
||||
if (ret)
|
||||
return ret;
|
||||
goodix_i2c_hid_deassert_reset(ihid_goodix, true);
|
||||
regulator_disable(ihid_goodix->vdd);
|
||||
}
|
||||
|
||||
return i2c_hid_core_probe(client, &ihid_goodix->ops, 0x0001, 0);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user