Commit 5b5e3d03 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

Pull input fixes from Dmitry Torokhov:
 "A few small updates to drivers.

  Of note we are now deferring probes of i8042 on some Asus devices as
  the controller is not ready to respond to queries first time around
  when the driver is compiled into the kernel"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: elants_i2c - do not check Remark ID on eKTH3900/eKTH5312
  Input: atmel_mxt_ts - fix double free in mxt_read_info_block
  Input: goodix - fix memory leak in goodix_firmware_upload
  Input: goodix - add id->model mapping for the "9111" model
  Input: goodix - try not to touch the reset-pin on x86/ACPI devices
  Input: i8042 - enable deferred probe quirk for ASUS UM325UA
  Input: elantech - fix stack out of bound access in elantech_change_report_id()
  Input: iqs626a - prohibit inlining of channel parsing functions
  Input: i8042 - add deferred probe support
parents d0cc67b2 4ebfee2b
...@@ -1689,6 +1689,8 @@ ...@@ -1689,6 +1689,8 @@
architectures force reset to be always executed architectures force reset to be always executed
i8042.unlock [HW] Unlock (ignore) the keylock i8042.unlock [HW] Unlock (ignore) the keylock
i8042.kbdreset [HW] Reset device connected to KBD port i8042.kbdreset [HW] Reset device connected to KBD port
i8042.probe_defer
[HW] Allow deferred probing upon i8042 probe errors
i810= [HW,DRM] i810= [HW,DRM]
......
...@@ -456,9 +456,10 @@ struct iqs626_private { ...@@ -456,9 +456,10 @@ struct iqs626_private {
unsigned int suspend_mode; unsigned int suspend_mode;
}; };
static int iqs626_parse_events(struct iqs626_private *iqs626, static noinline_for_stack int
const struct fwnode_handle *ch_node, iqs626_parse_events(struct iqs626_private *iqs626,
enum iqs626_ch_id ch_id) const struct fwnode_handle *ch_node,
enum iqs626_ch_id ch_id)
{ {
struct iqs626_sys_reg *sys_reg = &iqs626->sys_reg; struct iqs626_sys_reg *sys_reg = &iqs626->sys_reg;
struct i2c_client *client = iqs626->client; struct i2c_client *client = iqs626->client;
...@@ -604,9 +605,10 @@ static int iqs626_parse_events(struct iqs626_private *iqs626, ...@@ -604,9 +605,10 @@ static int iqs626_parse_events(struct iqs626_private *iqs626,
return 0; return 0;
} }
static int iqs626_parse_ati_target(struct iqs626_private *iqs626, static noinline_for_stack int
const struct fwnode_handle *ch_node, iqs626_parse_ati_target(struct iqs626_private *iqs626,
enum iqs626_ch_id ch_id) const struct fwnode_handle *ch_node,
enum iqs626_ch_id ch_id)
{ {
struct iqs626_sys_reg *sys_reg = &iqs626->sys_reg; struct iqs626_sys_reg *sys_reg = &iqs626->sys_reg;
struct i2c_client *client = iqs626->client; struct i2c_client *client = iqs626->client;
...@@ -885,9 +887,10 @@ static int iqs626_parse_trackpad(struct iqs626_private *iqs626, ...@@ -885,9 +887,10 @@ static int iqs626_parse_trackpad(struct iqs626_private *iqs626,
return 0; return 0;
} }
static int iqs626_parse_channel(struct iqs626_private *iqs626, static noinline_for_stack int
const struct fwnode_handle *ch_node, iqs626_parse_channel(struct iqs626_private *iqs626,
enum iqs626_ch_id ch_id) const struct fwnode_handle *ch_node,
enum iqs626_ch_id ch_id)
{ {
struct iqs626_sys_reg *sys_reg = &iqs626->sys_reg; struct iqs626_sys_reg *sys_reg = &iqs626->sys_reg;
struct i2c_client *client = iqs626->client; struct i2c_client *client = iqs626->client;
......
...@@ -1588,7 +1588,13 @@ static const struct dmi_system_id no_hw_res_dmi_table[] = { ...@@ -1588,7 +1588,13 @@ static const struct dmi_system_id no_hw_res_dmi_table[] = {
*/ */
static int elantech_change_report_id(struct psmouse *psmouse) static int elantech_change_report_id(struct psmouse *psmouse)
{ {
unsigned char param[2] = { 0x10, 0x03 }; /*
* NOTE: the code is expecting to receive param[] as an array of 3
* items (see __ps2_command()), even if in this case only 2 are
* actually needed. Make sure the array size is 3 to avoid potential
* stack out-of-bound accesses.
*/
unsigned char param[3] = { 0x10, 0x03 };
if (elantech_write_reg_params(psmouse, 0x7, param) || if (elantech_write_reg_params(psmouse, 0x7, param) ||
elantech_read_reg_params(psmouse, 0x7, param) || elantech_read_reg_params(psmouse, 0x7, param) ||
......
...@@ -995,6 +995,24 @@ static const struct dmi_system_id __initconst i8042_dmi_kbdreset_table[] = { ...@@ -995,6 +995,24 @@ static const struct dmi_system_id __initconst i8042_dmi_kbdreset_table[] = {
{ } { }
}; };
static const struct dmi_system_id i8042_dmi_probe_defer_table[] __initconst = {
{
/* ASUS ZenBook UX425UA */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX425UA"),
},
},
{
/* ASUS ZenBook UM325UA */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX325UA_UM325UA"),
},
},
{ }
};
#endif /* CONFIG_X86 */ #endif /* CONFIG_X86 */
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
...@@ -1315,6 +1333,9 @@ static int __init i8042_platform_init(void) ...@@ -1315,6 +1333,9 @@ static int __init i8042_platform_init(void)
if (dmi_check_system(i8042_dmi_kbdreset_table)) if (dmi_check_system(i8042_dmi_kbdreset_table))
i8042_kbdreset = true; i8042_kbdreset = true;
if (dmi_check_system(i8042_dmi_probe_defer_table))
i8042_probe_defer = true;
/* /*
* A20 was already enabled during early kernel init. But some buggy * A20 was already enabled during early kernel init. But some buggy
* BIOSes (in MSI Laptops) require A20 to be enabled using 8042 to * BIOSes (in MSI Laptops) require A20 to be enabled using 8042 to
......
...@@ -45,6 +45,10 @@ static bool i8042_unlock; ...@@ -45,6 +45,10 @@ static bool i8042_unlock;
module_param_named(unlock, i8042_unlock, bool, 0); module_param_named(unlock, i8042_unlock, bool, 0);
MODULE_PARM_DESC(unlock, "Ignore keyboard lock."); MODULE_PARM_DESC(unlock, "Ignore keyboard lock.");
static bool i8042_probe_defer;
module_param_named(probe_defer, i8042_probe_defer, bool, 0);
MODULE_PARM_DESC(probe_defer, "Allow deferred probing.");
enum i8042_controller_reset_mode { enum i8042_controller_reset_mode {
I8042_RESET_NEVER, I8042_RESET_NEVER,
I8042_RESET_ALWAYS, I8042_RESET_ALWAYS,
...@@ -711,7 +715,7 @@ static int i8042_set_mux_mode(bool multiplex, unsigned char *mux_version) ...@@ -711,7 +715,7 @@ static int i8042_set_mux_mode(bool multiplex, unsigned char *mux_version)
* LCS/Telegraphics. * LCS/Telegraphics.
*/ */
static int __init i8042_check_mux(void) static int i8042_check_mux(void)
{ {
unsigned char mux_version; unsigned char mux_version;
...@@ -740,10 +744,10 @@ static int __init i8042_check_mux(void) ...@@ -740,10 +744,10 @@ static int __init i8042_check_mux(void)
/* /*
* The following is used to test AUX IRQ delivery. * The following is used to test AUX IRQ delivery.
*/ */
static struct completion i8042_aux_irq_delivered __initdata; static struct completion i8042_aux_irq_delivered;
static bool i8042_irq_being_tested __initdata; static bool i8042_irq_being_tested;
static irqreturn_t __init i8042_aux_test_irq(int irq, void *dev_id) static irqreturn_t i8042_aux_test_irq(int irq, void *dev_id)
{ {
unsigned long flags; unsigned long flags;
unsigned char str, data; unsigned char str, data;
...@@ -770,7 +774,7 @@ static irqreturn_t __init i8042_aux_test_irq(int irq, void *dev_id) ...@@ -770,7 +774,7 @@ static irqreturn_t __init i8042_aux_test_irq(int irq, void *dev_id)
* verifies success by readinng CTR. Used when testing for presence of AUX * verifies success by readinng CTR. Used when testing for presence of AUX
* port. * port.
*/ */
static int __init i8042_toggle_aux(bool on) static int i8042_toggle_aux(bool on)
{ {
unsigned char param; unsigned char param;
int i; int i;
...@@ -798,7 +802,7 @@ static int __init i8042_toggle_aux(bool on) ...@@ -798,7 +802,7 @@ static int __init i8042_toggle_aux(bool on)
* the presence of an AUX interface. * the presence of an AUX interface.
*/ */
static int __init i8042_check_aux(void) static int i8042_check_aux(void)
{ {
int retval = -1; int retval = -1;
bool irq_registered = false; bool irq_registered = false;
...@@ -1005,7 +1009,7 @@ static int i8042_controller_init(void) ...@@ -1005,7 +1009,7 @@ static int i8042_controller_init(void)
if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) { if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) {
pr_err("Can't read CTR while initializing i8042\n"); pr_err("Can't read CTR while initializing i8042\n");
return -EIO; return i8042_probe_defer ? -EPROBE_DEFER : -EIO;
} }
} while (n < 2 || ctr[0] != ctr[1]); } while (n < 2 || ctr[0] != ctr[1]);
...@@ -1320,7 +1324,7 @@ static void i8042_shutdown(struct platform_device *dev) ...@@ -1320,7 +1324,7 @@ static void i8042_shutdown(struct platform_device *dev)
i8042_controller_reset(false); i8042_controller_reset(false);
} }
static int __init i8042_create_kbd_port(void) static int i8042_create_kbd_port(void)
{ {
struct serio *serio; struct serio *serio;
struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO];
...@@ -1349,7 +1353,7 @@ static int __init i8042_create_kbd_port(void) ...@@ -1349,7 +1353,7 @@ static int __init i8042_create_kbd_port(void)
return 0; return 0;
} }
static int __init i8042_create_aux_port(int idx) static int i8042_create_aux_port(int idx)
{ {
struct serio *serio; struct serio *serio;
int port_no = idx < 0 ? I8042_AUX_PORT_NO : I8042_MUX_PORT_NO + idx; int port_no = idx < 0 ? I8042_AUX_PORT_NO : I8042_MUX_PORT_NO + idx;
...@@ -1386,13 +1390,13 @@ static int __init i8042_create_aux_port(int idx) ...@@ -1386,13 +1390,13 @@ static int __init i8042_create_aux_port(int idx)
return 0; return 0;
} }
static void __init i8042_free_kbd_port(void) static void i8042_free_kbd_port(void)
{ {
kfree(i8042_ports[I8042_KBD_PORT_NO].serio); kfree(i8042_ports[I8042_KBD_PORT_NO].serio);
i8042_ports[I8042_KBD_PORT_NO].serio = NULL; i8042_ports[I8042_KBD_PORT_NO].serio = NULL;
} }
static void __init i8042_free_aux_ports(void) static void i8042_free_aux_ports(void)
{ {
int i; int i;
...@@ -1402,7 +1406,7 @@ static void __init i8042_free_aux_ports(void) ...@@ -1402,7 +1406,7 @@ static void __init i8042_free_aux_ports(void)
} }
} }
static void __init i8042_register_ports(void) static void i8042_register_ports(void)
{ {
int i; int i;
...@@ -1443,7 +1447,7 @@ static void i8042_free_irqs(void) ...@@ -1443,7 +1447,7 @@ static void i8042_free_irqs(void)
i8042_aux_irq_registered = i8042_kbd_irq_registered = false; i8042_aux_irq_registered = i8042_kbd_irq_registered = false;
} }
static int __init i8042_setup_aux(void) static int i8042_setup_aux(void)
{ {
int (*aux_enable)(void); int (*aux_enable)(void);
int error; int error;
...@@ -1485,7 +1489,7 @@ static int __init i8042_setup_aux(void) ...@@ -1485,7 +1489,7 @@ static int __init i8042_setup_aux(void)
return error; return error;
} }
static int __init i8042_setup_kbd(void) static int i8042_setup_kbd(void)
{ {
int error; int error;
...@@ -1535,7 +1539,7 @@ static int i8042_kbd_bind_notifier(struct notifier_block *nb, ...@@ -1535,7 +1539,7 @@ static int i8042_kbd_bind_notifier(struct notifier_block *nb,
return 0; return 0;
} }
static int __init i8042_probe(struct platform_device *dev) static int i8042_probe(struct platform_device *dev)
{ {
int error; int error;
...@@ -1600,6 +1604,7 @@ static struct platform_driver i8042_driver = { ...@@ -1600,6 +1604,7 @@ static struct platform_driver i8042_driver = {
.pm = &i8042_pm_ops, .pm = &i8042_pm_ops,
#endif #endif
}, },
.probe = i8042_probe,
.remove = i8042_remove, .remove = i8042_remove,
.shutdown = i8042_shutdown, .shutdown = i8042_shutdown,
}; };
...@@ -1610,7 +1615,6 @@ static struct notifier_block i8042_kbd_bind_notifier_block = { ...@@ -1610,7 +1615,6 @@ static struct notifier_block i8042_kbd_bind_notifier_block = {
static int __init i8042_init(void) static int __init i8042_init(void)
{ {
struct platform_device *pdev;
int err; int err;
dbg_init(); dbg_init();
...@@ -1626,17 +1630,29 @@ static int __init i8042_init(void) ...@@ -1626,17 +1630,29 @@ static int __init i8042_init(void)
/* Set this before creating the dev to allow i8042_command to work right away */ /* Set this before creating the dev to allow i8042_command to work right away */
i8042_present = true; i8042_present = true;
pdev = platform_create_bundle(&i8042_driver, i8042_probe, NULL, 0, NULL, 0); err = platform_driver_register(&i8042_driver);
if (IS_ERR(pdev)) { if (err)
err = PTR_ERR(pdev);
goto err_platform_exit; goto err_platform_exit;
i8042_platform_device = platform_device_alloc("i8042", -1);
if (!i8042_platform_device) {
err = -ENOMEM;
goto err_unregister_driver;
} }
err = platform_device_add(i8042_platform_device);
if (err)
goto err_free_device;
bus_register_notifier(&serio_bus, &i8042_kbd_bind_notifier_block); bus_register_notifier(&serio_bus, &i8042_kbd_bind_notifier_block);
panic_blink = i8042_panic_blink; panic_blink = i8042_panic_blink;
return 0; return 0;
err_free_device:
platform_device_put(i8042_platform_device);
err_unregister_driver:
platform_driver_unregister(&i8042_driver);
err_platform_exit: err_platform_exit:
i8042_platform_exit(); i8042_platform_exit();
return err; return err;
......
...@@ -1882,7 +1882,7 @@ static int mxt_read_info_block(struct mxt_data *data) ...@@ -1882,7 +1882,7 @@ static int mxt_read_info_block(struct mxt_data *data)
if (error) { if (error) {
dev_err(&client->dev, "Error %d parsing object table\n", error); dev_err(&client->dev, "Error %d parsing object table\n", error);
mxt_free_object_table(data); mxt_free_object_table(data);
goto err_free_mem; return error;
} }
data->object_table = (struct mxt_object *)(id_buf + MXT_OBJECT_START); data->object_table = (struct mxt_object *)(id_buf + MXT_OBJECT_START);
......
...@@ -117,6 +117,19 @@ ...@@ -117,6 +117,19 @@
#define ELAN_POWERON_DELAY_USEC 500 #define ELAN_POWERON_DELAY_USEC 500
#define ELAN_RESET_DELAY_MSEC 20 #define ELAN_RESET_DELAY_MSEC 20
/* FW boot code version */
#define BC_VER_H_BYTE_FOR_EKTH3900x1_I2C 0x72
#define BC_VER_H_BYTE_FOR_EKTH3900x2_I2C 0x82
#define BC_VER_H_BYTE_FOR_EKTH3900x3_I2C 0x92
#define BC_VER_H_BYTE_FOR_EKTH5312x1_I2C 0x6D
#define BC_VER_H_BYTE_FOR_EKTH5312x2_I2C 0x6E
#define BC_VER_H_BYTE_FOR_EKTH5312cx1_I2C 0x77
#define BC_VER_H_BYTE_FOR_EKTH5312cx2_I2C 0x78
#define BC_VER_H_BYTE_FOR_EKTH5312x1_I2C_USB 0x67
#define BC_VER_H_BYTE_FOR_EKTH5312x2_I2C_USB 0x68
#define BC_VER_H_BYTE_FOR_EKTH5312cx1_I2C_USB 0x74
#define BC_VER_H_BYTE_FOR_EKTH5312cx2_I2C_USB 0x75
enum elants_chip_id { enum elants_chip_id {
EKTH3500, EKTH3500,
EKTF3624, EKTF3624,
...@@ -736,6 +749,37 @@ static int elants_i2c_validate_remark_id(struct elants_data *ts, ...@@ -736,6 +749,37 @@ static int elants_i2c_validate_remark_id(struct elants_data *ts,
return 0; return 0;
} }
static bool elants_i2c_should_check_remark_id(struct elants_data *ts)
{
struct i2c_client *client = ts->client;
const u8 bootcode_version = ts->iap_version;
bool check;
/* I2C eKTH3900 and eKTH5312 are NOT support Remark ID */
if ((bootcode_version == BC_VER_H_BYTE_FOR_EKTH3900x1_I2C) ||
(bootcode_version == BC_VER_H_BYTE_FOR_EKTH3900x2_I2C) ||
(bootcode_version == BC_VER_H_BYTE_FOR_EKTH3900x3_I2C) ||
(bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312x1_I2C) ||
(bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312x2_I2C) ||
(bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312cx1_I2C) ||
(bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312cx2_I2C) ||
(bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312x1_I2C_USB) ||
(bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312x2_I2C_USB) ||
(bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312cx1_I2C_USB) ||
(bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312cx2_I2C_USB)) {
dev_dbg(&client->dev,
"eKTH3900/eKTH5312(0x%02x) are not support remark id\n",
bootcode_version);
check = false;
} else if (bootcode_version >= 0x60) {
check = true;
} else {
check = false;
}
return check;
}
static int elants_i2c_do_update_firmware(struct i2c_client *client, static int elants_i2c_do_update_firmware(struct i2c_client *client,
const struct firmware *fw, const struct firmware *fw,
bool force) bool force)
...@@ -749,7 +793,7 @@ static int elants_i2c_do_update_firmware(struct i2c_client *client, ...@@ -749,7 +793,7 @@ static int elants_i2c_do_update_firmware(struct i2c_client *client,
u16 send_id; u16 send_id;
int page, n_fw_pages; int page, n_fw_pages;
int error; int error;
bool check_remark_id = ts->iap_version >= 0x60; bool check_remark_id = elants_i2c_should_check_remark_id(ts);
/* Recovery mode detection! */ /* Recovery mode detection! */
if (force) { if (force) {
......
...@@ -102,6 +102,7 @@ static const struct goodix_chip_id goodix_chip_ids[] = { ...@@ -102,6 +102,7 @@ static const struct goodix_chip_id goodix_chip_ids[] = {
{ .id = "911", .data = &gt911_chip_data }, { .id = "911", .data = &gt911_chip_data },
{ .id = "9271", .data = &gt911_chip_data }, { .id = "9271", .data = &gt911_chip_data },
{ .id = "9110", .data = &gt911_chip_data }, { .id = "9110", .data = &gt911_chip_data },
{ .id = "9111", .data = &gt911_chip_data },
{ .id = "927", .data = &gt911_chip_data }, { .id = "927", .data = &gt911_chip_data },
{ .id = "928", .data = &gt911_chip_data }, { .id = "928", .data = &gt911_chip_data },
...@@ -650,10 +651,16 @@ int goodix_reset_no_int_sync(struct goodix_ts_data *ts) ...@@ -650,10 +651,16 @@ int goodix_reset_no_int_sync(struct goodix_ts_data *ts)
usleep_range(6000, 10000); /* T4: > 5ms */ usleep_range(6000, 10000); /* T4: > 5ms */
/* end select I2C slave addr */ /*
error = gpiod_direction_input(ts->gpiod_rst); * Put the reset pin back in to input / high-impedance mode to save
if (error) * power. Only do this in the non ACPI case since some ACPI boards
goto error; * don't have a pull-up, so there the reset pin must stay active-high.
*/
if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_GPIO) {
error = gpiod_direction_input(ts->gpiod_rst);
if (error)
goto error;
}
return 0; return 0;
...@@ -787,6 +794,14 @@ static int goodix_add_acpi_gpio_mappings(struct goodix_ts_data *ts) ...@@ -787,6 +794,14 @@ static int goodix_add_acpi_gpio_mappings(struct goodix_ts_data *ts)
return -EINVAL; return -EINVAL;
} }
/*
* Normally we put the reset pin in input / high-impedance mode to save
* power. But some x86/ACPI boards don't have a pull-up, so for the ACPI
* case, leave the pin as is. This results in the pin not being touched
* at all on x86/ACPI boards, except when needed for error-recover.
*/
ts->gpiod_rst_flags = GPIOD_ASIS;
return devm_acpi_dev_add_driver_gpios(dev, gpio_mapping); return devm_acpi_dev_add_driver_gpios(dev, gpio_mapping);
} }
#else #else
...@@ -812,6 +827,12 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts) ...@@ -812,6 +827,12 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts)
return -EINVAL; return -EINVAL;
dev = &ts->client->dev; dev = &ts->client->dev;
/*
* By default we request the reset pin as input, leaving it in
* high-impedance when not resetting the controller to save power.
*/
ts->gpiod_rst_flags = GPIOD_IN;
ts->avdd28 = devm_regulator_get(dev, "AVDD28"); ts->avdd28 = devm_regulator_get(dev, "AVDD28");
if (IS_ERR(ts->avdd28)) { if (IS_ERR(ts->avdd28)) {
error = PTR_ERR(ts->avdd28); error = PTR_ERR(ts->avdd28);
...@@ -849,7 +870,7 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts) ...@@ -849,7 +870,7 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts)
ts->gpiod_int = gpiod; ts->gpiod_int = gpiod;
/* Get the reset line GPIO pin number */ /* Get the reset line GPIO pin number */
gpiod = devm_gpiod_get_optional(dev, GOODIX_GPIO_RST_NAME, GPIOD_IN); gpiod = devm_gpiod_get_optional(dev, GOODIX_GPIO_RST_NAME, ts->gpiod_rst_flags);
if (IS_ERR(gpiod)) { if (IS_ERR(gpiod)) {
error = PTR_ERR(gpiod); error = PTR_ERR(gpiod);
if (error != -EPROBE_DEFER) if (error != -EPROBE_DEFER)
......
...@@ -87,6 +87,7 @@ struct goodix_ts_data { ...@@ -87,6 +87,7 @@ struct goodix_ts_data {
struct gpio_desc *gpiod_rst; struct gpio_desc *gpiod_rst;
int gpio_count; int gpio_count;
int gpio_int_idx; int gpio_int_idx;
enum gpiod_flags gpiod_rst_flags;
char id[GOODIX_ID_MAX_LEN + 1]; char id[GOODIX_ID_MAX_LEN + 1];
char cfg_name[64]; char cfg_name[64];
u16 version; u16 version;
......
...@@ -207,7 +207,7 @@ static int goodix_firmware_upload(struct goodix_ts_data *ts) ...@@ -207,7 +207,7 @@ static int goodix_firmware_upload(struct goodix_ts_data *ts)
error = goodix_reset_no_int_sync(ts); error = goodix_reset_no_int_sync(ts);
if (error) if (error)
return error; goto release;
error = goodix_enter_upload_mode(ts->client); error = goodix_enter_upload_mode(ts->client);
if (error) if (error)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment