Loading drivers/input/touchscreen/synaptics_fw_update.c +21 −1 Original line number Diff line number Diff line Loading @@ -135,6 +135,9 @@ static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev, static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev, struct device_attribute *attr, char *buf); static ssize_t fwu_sysfs_config_id_show(struct device *dev, struct device_attribute *attr, char *buf); static int fwu_wait_for_idle(int timeout_ms); struct image_header { Loading Loading @@ -289,6 +292,9 @@ static struct device_attribute attrs[] = { __ATTR(dispconfigblockcount, S_IRUGO, fwu_sysfs_disp_config_block_count_show, synaptics_rmi4_store_error), __ATTR(config_id, S_IRUGO, fwu_sysfs_config_id_show, synaptics_rmi4_store_error), }; static struct synaptics_rmi4_fwu_handle *fwu; Loading Loading @@ -1519,6 +1525,20 @@ static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "%u\n", fwu->disp_config_block_count); } static ssize_t fwu_sysfs_config_id_show(struct device *dev, struct device_attribute *attr, char *buf) { unsigned char config_id[4]; /* device config id */ fwu->fn_ptr->read(fwu->rmi4_data, fwu->f34_fd.ctrl_base_addr, config_id, sizeof(config_id)); return snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d\n", config_id[0], config_id[1], config_id[2], config_id[3]); } static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data, unsigned char intr_mask) { Loading Loading @@ -1681,4 +1701,4 @@ module_exit(rmi4_fw_update_module_exit); MODULE_AUTHOR("Synaptics, Inc."); MODULE_DESCRIPTION("RMI4 FW Update Module"); MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2"); drivers/input/touchscreen/synaptics_i2c_rmi4.c +264 −65 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ * * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com> * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com> * Copyright (c) 2013, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by Loading Loading @@ -71,6 +72,19 @@ #define NO_SLEEP_OFF (0 << 3) #define NO_SLEEP_ON (1 << 3) #define RMI4_VTG_MIN_UV 2700000 #define RMI4_VTG_MAX_UV 3300000 #define RMI4_ACTIVE_LOAD_UA 15000 #define RMI4_LPM_LOAD_UA 10 #define RMI4_I2C_VTG_MIN_UV 1800000 #define RMI4_I2C_VTG_MAX_UV 1800000 #define RMI4_I2C_LOAD_UA 10000 #define RMI4_I2C_LPM_LOAD_UA 10 #define RMI4_GPIO_SLEEP_LOW_US 10000 #define RMI4_GPIO_WAIT_HIGH_MS 25 static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data, unsigned short addr, unsigned char *data, unsigned short length); Loading Loading @@ -1492,10 +1506,6 @@ static void synaptics_rmi4_detection_work(struct work_struct *work) container_of(work, struct synaptics_rmi4_data, det_work.work); queue_delayed_work(rmi4_data->det_workqueue, &rmi4_data->det_work, msecs_to_jiffies(EXP_FN_DET_INTERVAL)); mutex_lock(&exp_fn_list_mutex); if (!list_empty(&exp_fn_list)) { list_for_each_entry_safe(exp_fhandler, Loading Loading @@ -1575,6 +1585,164 @@ exit: } EXPORT_SYMBOL(synaptics_rmi4_new_function); 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 synaptics_rmi4_regulator_configure(struct synaptics_rmi4_data *rmi4_data, bool on) { int retval; if (on == false) goto hw_shutdown; if (rmi4_data->board->regulator_en) { rmi4_data->vdd = regulator_get(&rmi4_data->i2c_client->dev, "vdd"); if (IS_ERR(rmi4_data->vdd)) { dev_err(&rmi4_data->i2c_client->dev, "%s: Failed to get vdd regulator\n", __func__); return PTR_ERR(rmi4_data->vdd); } if (regulator_count_voltages(rmi4_data->vdd) > 0) { retval = regulator_set_voltage(rmi4_data->vdd, RMI4_VTG_MIN_UV, RMI4_VTG_MAX_UV); if (retval) { dev_err(&rmi4_data->i2c_client->dev, "regulator set_vtg failed retval=%d\n", retval); goto err_set_vtg_vdd; } } } if (rmi4_data->board->i2c_pull_up) { rmi4_data->vcc_i2c = regulator_get(&rmi4_data->i2c_client->dev, "vcc_i2c"); if (IS_ERR(rmi4_data->vcc_i2c)) { dev_err(&rmi4_data->i2c_client->dev, "%s: Failed to get i2c regulator\n", __func__); retval = PTR_ERR(rmi4_data->vcc_i2c); goto err_get_vtg_i2c; } if (regulator_count_voltages(rmi4_data->vcc_i2c) > 0) { retval = regulator_set_voltage(rmi4_data->vcc_i2c, RMI4_I2C_VTG_MIN_UV, RMI4_I2C_VTG_MAX_UV); if (retval) { dev_err(&rmi4_data->i2c_client->dev, "reg set i2c vtg failed retval=%d\n", retval); goto err_set_vtg_i2c; } } } err_set_vtg_i2c: if (rmi4_data->board->i2c_pull_up) regulator_put(rmi4_data->vcc_i2c); err_get_vtg_i2c: if (rmi4_data->board->regulator_en) if (regulator_count_voltages(rmi4_data->vdd) > 0) regulator_set_voltage(rmi4_data->vdd, 0, RMI4_VTG_MAX_UV); err_set_vtg_vdd: if (rmi4_data->board->regulator_en) regulator_put(rmi4_data->vdd); return retval; hw_shutdown: if (rmi4_data->board->regulator_en) { if (regulator_count_voltages(rmi4_data->vdd) > 0) regulator_set_voltage(rmi4_data->vdd, 0, RMI4_VTG_MAX_UV); regulator_put(rmi4_data->vdd); } if (rmi4_data->board->i2c_pull_up) { if (regulator_count_voltages(rmi4_data->vcc_i2c) > 0) regulator_set_voltage(rmi4_data->vcc_i2c, 0, RMI4_I2C_VTG_MAX_UV); regulator_put(rmi4_data->vcc_i2c); } return 0; }; static int synaptics_rmi4_power_on(struct synaptics_rmi4_data *rmi4_data, bool on) { int retval; if (on == false) goto power_off; if (rmi4_data->board->regulator_en) { retval = reg_set_optimum_mode_check(rmi4_data->vdd, RMI4_ACTIVE_LOAD_UA); if (retval < 0) { dev_err(&rmi4_data->i2c_client->dev, "Regulator vdd set_opt failed rc=%d\n", retval); return retval; } retval = regulator_enable(rmi4_data->vdd); if (retval) { dev_err(&rmi4_data->i2c_client->dev, "Regulator vdd enable failed rc=%d\n", retval); goto error_reg_en_vdd; } } if (rmi4_data->board->i2c_pull_up) { retval = reg_set_optimum_mode_check(rmi4_data->vcc_i2c, RMI4_I2C_LOAD_UA); if (retval < 0) { dev_err(&rmi4_data->i2c_client->dev, "Regulator vcc_i2c set_opt failed rc=%d\n", retval); goto error_reg_opt_i2c; } retval = regulator_enable(rmi4_data->vcc_i2c); if (retval) { dev_err(&rmi4_data->i2c_client->dev, "Regulator vcc_i2c enable failed rc=%d\n", retval); goto error_reg_en_vcc_i2c; } } return 0; error_reg_en_vcc_i2c: if (rmi4_data->board->i2c_pull_up) reg_set_optimum_mode_check(rmi4_data->vdd, 0); error_reg_opt_i2c: if (rmi4_data->board->regulator_en) regulator_disable(rmi4_data->vdd); error_reg_en_vdd: if (rmi4_data->board->regulator_en) reg_set_optimum_mode_check(rmi4_data->vdd, 0); return retval; power_off: if (rmi4_data->board->regulator_en) { reg_set_optimum_mode_check(rmi4_data->vdd, 0); regulator_disable(rmi4_data->vdd); } if (rmi4_data->board->i2c_pull_up) { reg_set_optimum_mode_check(rmi4_data->vcc_i2c, 0); regulator_disable(rmi4_data->vcc_i2c); } return 0; } /** * synaptics_rmi4_probe() * Loading @@ -1592,7 +1760,7 @@ EXPORT_SYMBOL(synaptics_rmi4_new_function); static int synaptics_rmi4_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) { int retval; int retval = 0; unsigned char ii; unsigned char attr_count; struct synaptics_rmi4_f1a_handle *f1a; Loading Loading @@ -1629,20 +1797,6 @@ static int synaptics_rmi4_probe(struct i2c_client *client, goto err_input_device; } if (platform_data->regulator_en) { rmi4_data->regulator = devm_regulator_get(&client->dev, "vdd"); if (IS_ERR(rmi4_data->regulator)) { dev_err(&client->dev, "%s: Failed to get regulator\n", __func__); retval = PTR_ERR(rmi4_data->regulator); goto err_regulator; } retval = regulator_enable(rmi4_data->regulator); if (retval) return retval; } rmi4_data->i2c_client = client; rmi4_data->current_page = MASK_8BIT; rmi4_data->board = platform_data; Loading @@ -1655,24 +1809,11 @@ static int synaptics_rmi4_probe(struct i2c_client *client, rmi4_data->irq_enable = synaptics_rmi4_irq_enable; rmi4_data->reset_device = synaptics_rmi4_reset_device; init_waitqueue_head(&rmi4_data->wait); mutex_init(&(rmi4_data->rmi4_io_ctrl_mutex)); retval = synaptics_rmi4_query_device(rmi4_data); if (retval < 0) { dev_err(&client->dev, "%s: Failed to query device\n", __func__); goto err_query_device; } i2c_set_clientdata(client, rmi4_data); rmi4_data->input_dev->name = DRIVER_NAME; rmi4_data->input_dev->phys = INPUT_PHYS_NAME; rmi4_data->input_dev->id.bustype = BUS_I2C; rmi4_data->input_dev->id.product = SYNAPTICS_RMI4_DRIVER_PRODUCT; rmi4_data->input_dev->id.version = SYNAPTICS_RMI4_DRIVER_VERSION; rmi4_data->input_dev->id.product = SYNAPTICS_DSX_DRIVER_PRODUCT; rmi4_data->input_dev->id.version = SYNAPTICS_DSX_DRIVER_VERSION; rmi4_data->input_dev->dev.parent = &client->dev; input_set_drvdata(rmi4_data->input_dev, rmi4_data); Loading Loading @@ -1703,6 +1844,76 @@ static int synaptics_rmi4_probe(struct i2c_client *client, rmi4_data->num_of_fingers); #endif retval = synaptics_rmi4_regulator_configure(rmi4_data, true); if (retval < 0) { dev_err(&client->dev, "Failed to configure regulators\n"); goto err_reg_configure; } retval = synaptics_rmi4_power_on(rmi4_data, true); if (retval < 0) { dev_err(&client->dev, "Failed to power on\n"); goto err_power_device; } if (gpio_is_valid(platform_data->irq_gpio)) { /* configure touchscreen irq gpio */ retval = gpio_request(platform_data->irq_gpio, "rmi4_irq_gpio"); if (retval) { dev_err(&client->dev, "unable to request gpio [%d]\n", platform_data->irq_gpio); goto err_query_device; } retval = gpio_direction_input(platform_data->irq_gpio); if (retval) { dev_err(&client->dev, "unable to set direction for gpio [%d]\n", platform_data->irq_gpio); goto err_irq_gpio_req; } } else { dev_err(&client->dev, "irq gpio not provided\n"); goto err_query_device; } if (gpio_is_valid(platform_data->reset_gpio)) { /* configure touchscreen reset out gpio */ retval = gpio_request(platform_data->reset_gpio, "rmi4_reset_gpio"); if (retval) { dev_err(&client->dev, "unable to request gpio [%d]\n", platform_data->reset_gpio); goto err_irq_gpio_req; } retval = gpio_direction_output(platform_data->reset_gpio, 1); if (retval) { dev_err(&client->dev, "unable to set direction for gpio [%d]\n", platform_data->reset_gpio); goto err_reset_gpio_req; } gpio_set_value(platform_data->reset_gpio, 0); usleep(RMI4_GPIO_SLEEP_LOW_US); gpio_set_value(platform_data->reset_gpio, 1); msleep(RMI4_GPIO_WAIT_HIGH_MS); } init_waitqueue_head(&rmi4_data->wait); mutex_init(&(rmi4_data->rmi4_io_ctrl_mutex)); retval = synaptics_rmi4_query_device(rmi4_data); if (retval < 0) { dev_err(&client->dev, "%s: Failed to query device\n", __func__); goto err_reset_gpio_req; } i2c_set_clientdata(client, rmi4_data); f1a = NULL; if (!list_empty(&rmi->support_fn_list)) { list_for_each_entry(fhandler, &rmi->support_fn_list, link) { Loading Loading @@ -1782,12 +1993,6 @@ err_enable_irq: input_unregister_device(rmi4_data->input_dev); err_register_input: err_query_device: if (platform_data->regulator_en) { regulator_disable(rmi4_data->regulator); regulator_put(rmi4_data->regulator); } if (!list_empty(&rmi->support_fn_list)) { list_for_each_entry(fhandler, &rmi->support_fn_list, link) { if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) Loading @@ -1797,11 +2002,19 @@ err_query_device: kfree(fhandler); } } err_regulator: err_reset_gpio_req: if (gpio_is_valid(platform_data->reset_gpio)) gpio_free(platform_data->reset_gpio); err_irq_gpio_req: if (gpio_is_valid(platform_data->irq_gpio)) gpio_free(platform_data->irq_gpio); err_query_device: synaptics_rmi4_power_on(rmi4_data, false); err_power_device: synaptics_rmi4_regulator_configure(rmi4_data, false); err_reg_configure: input_free_device(rmi4_data->input_dev); rmi4_data->input_dev = NULL; err_input_device: kfree(rmi4_data); Loading @@ -1824,8 +2037,6 @@ static int synaptics_rmi4_remove(struct i2c_client *client) struct synaptics_rmi4_fn *fhandler; struct synaptics_rmi4_data *rmi4_data = i2c_get_clientdata(client); struct synaptics_rmi4_device_info *rmi; const struct synaptics_rmi4_platform_data *platform_data = rmi4_data->board; rmi = &(rmi4_data->rmi4_mod_info); Loading @@ -1845,11 +2056,6 @@ static int synaptics_rmi4_remove(struct i2c_client *client) input_unregister_device(rmi4_data->input_dev); if (platform_data->regulator_en) { regulator_disable(rmi4_data->regulator); regulator_put(rmi4_data->regulator); } if (!list_empty(&rmi->support_fn_list)) { list_for_each_entry(fhandler, &rmi->support_fn_list, link) { if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) Loading @@ -1859,7 +2065,14 @@ static int synaptics_rmi4_remove(struct i2c_client *client) kfree(fhandler); } } input_free_device(rmi4_data->input_dev); if (gpio_is_valid(rmi4_data->board->reset_gpio)) gpio_free(rmi4_data->board->reset_gpio); if (gpio_is_valid(rmi4_data->board->irq_gpio)) gpio_free(rmi4_data->board->irq_gpio); synaptics_rmi4_power_on(rmi4_data, false); synaptics_rmi4_regulator_configure(rmi4_data, false); kfree(rmi4_data); Loading Loading @@ -2013,8 +2226,6 @@ static void synaptics_rmi4_late_resume(struct early_suspend *h) static int synaptics_rmi4_suspend(struct device *dev) { struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); const struct synaptics_rmi4_platform_data *platform_data = rmi4_data->board; if (!rmi4_data->sensor_sleep) { rmi4_data->touch_stopped = true; Loading @@ -2023,9 +2234,6 @@ static int synaptics_rmi4_suspend(struct device *dev) synaptics_rmi4_sensor_sleep(rmi4_data); } if (platform_data->regulator_en) regulator_disable(rmi4_data->regulator); return 0; } Loading @@ -2041,16 +2249,7 @@ static int synaptics_rmi4_suspend(struct device *dev) */ static int synaptics_rmi4_resume(struct device *dev) { int ret; struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); const struct synaptics_rmi4_platform_data *platform_data = rmi4_data->board; if (platform_data->regulator_en) { ret = regulator_enable(rmi4_data->regulator); if (ret) return ret; } synaptics_rmi4_sensor_wake(rmi4_data); rmi4_data->touch_stopped = false; Loading drivers/input/touchscreen/synaptics_i2c_rmi4.h +7 −5 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ * * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com> * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com> * Copyright (c) 2013, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by Loading @@ -20,10 +21,10 @@ #ifndef _SYNAPTICS_DSX_RMI4_H_ #define _SYNAPTICS_DSX_RMI4_H_ #define SYNAPTICS_RMI4_DS4 0x0001 #define SYNAPTICS_RMI4_DS5 0x0002 #define SYNAPTICS_RMI4_DRIVER_PRODUCT SYNAPTICS_RMI4_DS4 #define SYNAPTICS_RMI4_DRIVER_VERSION 0x1001 #define SYNAPTICS_DS4 (1 << 0) #define SYNAPTICS_DS5 (1 << 1) #define SYNAPTICS_DSX_DRIVER_PRODUCT SYNAPTICS_DS4 #define SYNAPTICS_DSX_DRIVER_VERSION 0x1002 #include <linux/version.h> #ifdef CONFIG_HAS_EARLYSUSPEND Loading Loading @@ -187,7 +188,8 @@ struct synaptics_rmi4_data { struct input_dev *input_dev; const struct synaptics_rmi4_platform_data *board; struct synaptics_rmi4_device_info rmi4_mod_info; struct regulator *regulator; struct regulator *vdd; struct regulator *vcc_i2c; struct mutex rmi4_io_ctrl_mutex; struct delayed_work det_work; struct workqueue_struct *det_workqueue; Loading drivers/input/touchscreen/synaptics_rmi_dev.c +1 −1 Original line number Diff line number Diff line Loading @@ -700,4 +700,4 @@ module_exit(rmidev_module_exit); MODULE_AUTHOR("Synaptics, Inc."); MODULE_DESCRIPTION("RMI4 RMI_Dev Module"); MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2"); include/linux/input/synaptics_dsx.h +2 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ * * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com> * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com> * Copyright (c) 2013, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by Loading Loading @@ -47,6 +48,7 @@ struct synaptics_rmi4_platform_data { bool x_flip; bool y_flip; bool regulator_en; bool i2c_pull_up; unsigned irq_gpio; unsigned long irq_flags; unsigned reset_gpio; Loading Loading
drivers/input/touchscreen/synaptics_fw_update.c +21 −1 Original line number Diff line number Diff line Loading @@ -135,6 +135,9 @@ static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev, static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev, struct device_attribute *attr, char *buf); static ssize_t fwu_sysfs_config_id_show(struct device *dev, struct device_attribute *attr, char *buf); static int fwu_wait_for_idle(int timeout_ms); struct image_header { Loading Loading @@ -289,6 +292,9 @@ static struct device_attribute attrs[] = { __ATTR(dispconfigblockcount, S_IRUGO, fwu_sysfs_disp_config_block_count_show, synaptics_rmi4_store_error), __ATTR(config_id, S_IRUGO, fwu_sysfs_config_id_show, synaptics_rmi4_store_error), }; static struct synaptics_rmi4_fwu_handle *fwu; Loading Loading @@ -1519,6 +1525,20 @@ static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "%u\n", fwu->disp_config_block_count); } static ssize_t fwu_sysfs_config_id_show(struct device *dev, struct device_attribute *attr, char *buf) { unsigned char config_id[4]; /* device config id */ fwu->fn_ptr->read(fwu->rmi4_data, fwu->f34_fd.ctrl_base_addr, config_id, sizeof(config_id)); return snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d\n", config_id[0], config_id[1], config_id[2], config_id[3]); } static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data, unsigned char intr_mask) { Loading Loading @@ -1681,4 +1701,4 @@ module_exit(rmi4_fw_update_module_exit); MODULE_AUTHOR("Synaptics, Inc."); MODULE_DESCRIPTION("RMI4 FW Update Module"); MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2");
drivers/input/touchscreen/synaptics_i2c_rmi4.c +264 −65 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ * * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com> * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com> * Copyright (c) 2013, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by Loading Loading @@ -71,6 +72,19 @@ #define NO_SLEEP_OFF (0 << 3) #define NO_SLEEP_ON (1 << 3) #define RMI4_VTG_MIN_UV 2700000 #define RMI4_VTG_MAX_UV 3300000 #define RMI4_ACTIVE_LOAD_UA 15000 #define RMI4_LPM_LOAD_UA 10 #define RMI4_I2C_VTG_MIN_UV 1800000 #define RMI4_I2C_VTG_MAX_UV 1800000 #define RMI4_I2C_LOAD_UA 10000 #define RMI4_I2C_LPM_LOAD_UA 10 #define RMI4_GPIO_SLEEP_LOW_US 10000 #define RMI4_GPIO_WAIT_HIGH_MS 25 static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data, unsigned short addr, unsigned char *data, unsigned short length); Loading Loading @@ -1492,10 +1506,6 @@ static void synaptics_rmi4_detection_work(struct work_struct *work) container_of(work, struct synaptics_rmi4_data, det_work.work); queue_delayed_work(rmi4_data->det_workqueue, &rmi4_data->det_work, msecs_to_jiffies(EXP_FN_DET_INTERVAL)); mutex_lock(&exp_fn_list_mutex); if (!list_empty(&exp_fn_list)) { list_for_each_entry_safe(exp_fhandler, Loading Loading @@ -1575,6 +1585,164 @@ exit: } EXPORT_SYMBOL(synaptics_rmi4_new_function); 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 synaptics_rmi4_regulator_configure(struct synaptics_rmi4_data *rmi4_data, bool on) { int retval; if (on == false) goto hw_shutdown; if (rmi4_data->board->regulator_en) { rmi4_data->vdd = regulator_get(&rmi4_data->i2c_client->dev, "vdd"); if (IS_ERR(rmi4_data->vdd)) { dev_err(&rmi4_data->i2c_client->dev, "%s: Failed to get vdd regulator\n", __func__); return PTR_ERR(rmi4_data->vdd); } if (regulator_count_voltages(rmi4_data->vdd) > 0) { retval = regulator_set_voltage(rmi4_data->vdd, RMI4_VTG_MIN_UV, RMI4_VTG_MAX_UV); if (retval) { dev_err(&rmi4_data->i2c_client->dev, "regulator set_vtg failed retval=%d\n", retval); goto err_set_vtg_vdd; } } } if (rmi4_data->board->i2c_pull_up) { rmi4_data->vcc_i2c = regulator_get(&rmi4_data->i2c_client->dev, "vcc_i2c"); if (IS_ERR(rmi4_data->vcc_i2c)) { dev_err(&rmi4_data->i2c_client->dev, "%s: Failed to get i2c regulator\n", __func__); retval = PTR_ERR(rmi4_data->vcc_i2c); goto err_get_vtg_i2c; } if (regulator_count_voltages(rmi4_data->vcc_i2c) > 0) { retval = regulator_set_voltage(rmi4_data->vcc_i2c, RMI4_I2C_VTG_MIN_UV, RMI4_I2C_VTG_MAX_UV); if (retval) { dev_err(&rmi4_data->i2c_client->dev, "reg set i2c vtg failed retval=%d\n", retval); goto err_set_vtg_i2c; } } } err_set_vtg_i2c: if (rmi4_data->board->i2c_pull_up) regulator_put(rmi4_data->vcc_i2c); err_get_vtg_i2c: if (rmi4_data->board->regulator_en) if (regulator_count_voltages(rmi4_data->vdd) > 0) regulator_set_voltage(rmi4_data->vdd, 0, RMI4_VTG_MAX_UV); err_set_vtg_vdd: if (rmi4_data->board->regulator_en) regulator_put(rmi4_data->vdd); return retval; hw_shutdown: if (rmi4_data->board->regulator_en) { if (regulator_count_voltages(rmi4_data->vdd) > 0) regulator_set_voltage(rmi4_data->vdd, 0, RMI4_VTG_MAX_UV); regulator_put(rmi4_data->vdd); } if (rmi4_data->board->i2c_pull_up) { if (regulator_count_voltages(rmi4_data->vcc_i2c) > 0) regulator_set_voltage(rmi4_data->vcc_i2c, 0, RMI4_I2C_VTG_MAX_UV); regulator_put(rmi4_data->vcc_i2c); } return 0; }; static int synaptics_rmi4_power_on(struct synaptics_rmi4_data *rmi4_data, bool on) { int retval; if (on == false) goto power_off; if (rmi4_data->board->regulator_en) { retval = reg_set_optimum_mode_check(rmi4_data->vdd, RMI4_ACTIVE_LOAD_UA); if (retval < 0) { dev_err(&rmi4_data->i2c_client->dev, "Regulator vdd set_opt failed rc=%d\n", retval); return retval; } retval = regulator_enable(rmi4_data->vdd); if (retval) { dev_err(&rmi4_data->i2c_client->dev, "Regulator vdd enable failed rc=%d\n", retval); goto error_reg_en_vdd; } } if (rmi4_data->board->i2c_pull_up) { retval = reg_set_optimum_mode_check(rmi4_data->vcc_i2c, RMI4_I2C_LOAD_UA); if (retval < 0) { dev_err(&rmi4_data->i2c_client->dev, "Regulator vcc_i2c set_opt failed rc=%d\n", retval); goto error_reg_opt_i2c; } retval = regulator_enable(rmi4_data->vcc_i2c); if (retval) { dev_err(&rmi4_data->i2c_client->dev, "Regulator vcc_i2c enable failed rc=%d\n", retval); goto error_reg_en_vcc_i2c; } } return 0; error_reg_en_vcc_i2c: if (rmi4_data->board->i2c_pull_up) reg_set_optimum_mode_check(rmi4_data->vdd, 0); error_reg_opt_i2c: if (rmi4_data->board->regulator_en) regulator_disable(rmi4_data->vdd); error_reg_en_vdd: if (rmi4_data->board->regulator_en) reg_set_optimum_mode_check(rmi4_data->vdd, 0); return retval; power_off: if (rmi4_data->board->regulator_en) { reg_set_optimum_mode_check(rmi4_data->vdd, 0); regulator_disable(rmi4_data->vdd); } if (rmi4_data->board->i2c_pull_up) { reg_set_optimum_mode_check(rmi4_data->vcc_i2c, 0); regulator_disable(rmi4_data->vcc_i2c); } return 0; } /** * synaptics_rmi4_probe() * Loading @@ -1592,7 +1760,7 @@ EXPORT_SYMBOL(synaptics_rmi4_new_function); static int synaptics_rmi4_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) { int retval; int retval = 0; unsigned char ii; unsigned char attr_count; struct synaptics_rmi4_f1a_handle *f1a; Loading Loading @@ -1629,20 +1797,6 @@ static int synaptics_rmi4_probe(struct i2c_client *client, goto err_input_device; } if (platform_data->regulator_en) { rmi4_data->regulator = devm_regulator_get(&client->dev, "vdd"); if (IS_ERR(rmi4_data->regulator)) { dev_err(&client->dev, "%s: Failed to get regulator\n", __func__); retval = PTR_ERR(rmi4_data->regulator); goto err_regulator; } retval = regulator_enable(rmi4_data->regulator); if (retval) return retval; } rmi4_data->i2c_client = client; rmi4_data->current_page = MASK_8BIT; rmi4_data->board = platform_data; Loading @@ -1655,24 +1809,11 @@ static int synaptics_rmi4_probe(struct i2c_client *client, rmi4_data->irq_enable = synaptics_rmi4_irq_enable; rmi4_data->reset_device = synaptics_rmi4_reset_device; init_waitqueue_head(&rmi4_data->wait); mutex_init(&(rmi4_data->rmi4_io_ctrl_mutex)); retval = synaptics_rmi4_query_device(rmi4_data); if (retval < 0) { dev_err(&client->dev, "%s: Failed to query device\n", __func__); goto err_query_device; } i2c_set_clientdata(client, rmi4_data); rmi4_data->input_dev->name = DRIVER_NAME; rmi4_data->input_dev->phys = INPUT_PHYS_NAME; rmi4_data->input_dev->id.bustype = BUS_I2C; rmi4_data->input_dev->id.product = SYNAPTICS_RMI4_DRIVER_PRODUCT; rmi4_data->input_dev->id.version = SYNAPTICS_RMI4_DRIVER_VERSION; rmi4_data->input_dev->id.product = SYNAPTICS_DSX_DRIVER_PRODUCT; rmi4_data->input_dev->id.version = SYNAPTICS_DSX_DRIVER_VERSION; rmi4_data->input_dev->dev.parent = &client->dev; input_set_drvdata(rmi4_data->input_dev, rmi4_data); Loading Loading @@ -1703,6 +1844,76 @@ static int synaptics_rmi4_probe(struct i2c_client *client, rmi4_data->num_of_fingers); #endif retval = synaptics_rmi4_regulator_configure(rmi4_data, true); if (retval < 0) { dev_err(&client->dev, "Failed to configure regulators\n"); goto err_reg_configure; } retval = synaptics_rmi4_power_on(rmi4_data, true); if (retval < 0) { dev_err(&client->dev, "Failed to power on\n"); goto err_power_device; } if (gpio_is_valid(platform_data->irq_gpio)) { /* configure touchscreen irq gpio */ retval = gpio_request(platform_data->irq_gpio, "rmi4_irq_gpio"); if (retval) { dev_err(&client->dev, "unable to request gpio [%d]\n", platform_data->irq_gpio); goto err_query_device; } retval = gpio_direction_input(platform_data->irq_gpio); if (retval) { dev_err(&client->dev, "unable to set direction for gpio [%d]\n", platform_data->irq_gpio); goto err_irq_gpio_req; } } else { dev_err(&client->dev, "irq gpio not provided\n"); goto err_query_device; } if (gpio_is_valid(platform_data->reset_gpio)) { /* configure touchscreen reset out gpio */ retval = gpio_request(platform_data->reset_gpio, "rmi4_reset_gpio"); if (retval) { dev_err(&client->dev, "unable to request gpio [%d]\n", platform_data->reset_gpio); goto err_irq_gpio_req; } retval = gpio_direction_output(platform_data->reset_gpio, 1); if (retval) { dev_err(&client->dev, "unable to set direction for gpio [%d]\n", platform_data->reset_gpio); goto err_reset_gpio_req; } gpio_set_value(platform_data->reset_gpio, 0); usleep(RMI4_GPIO_SLEEP_LOW_US); gpio_set_value(platform_data->reset_gpio, 1); msleep(RMI4_GPIO_WAIT_HIGH_MS); } init_waitqueue_head(&rmi4_data->wait); mutex_init(&(rmi4_data->rmi4_io_ctrl_mutex)); retval = synaptics_rmi4_query_device(rmi4_data); if (retval < 0) { dev_err(&client->dev, "%s: Failed to query device\n", __func__); goto err_reset_gpio_req; } i2c_set_clientdata(client, rmi4_data); f1a = NULL; if (!list_empty(&rmi->support_fn_list)) { list_for_each_entry(fhandler, &rmi->support_fn_list, link) { Loading Loading @@ -1782,12 +1993,6 @@ err_enable_irq: input_unregister_device(rmi4_data->input_dev); err_register_input: err_query_device: if (platform_data->regulator_en) { regulator_disable(rmi4_data->regulator); regulator_put(rmi4_data->regulator); } if (!list_empty(&rmi->support_fn_list)) { list_for_each_entry(fhandler, &rmi->support_fn_list, link) { if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) Loading @@ -1797,11 +2002,19 @@ err_query_device: kfree(fhandler); } } err_regulator: err_reset_gpio_req: if (gpio_is_valid(platform_data->reset_gpio)) gpio_free(platform_data->reset_gpio); err_irq_gpio_req: if (gpio_is_valid(platform_data->irq_gpio)) gpio_free(platform_data->irq_gpio); err_query_device: synaptics_rmi4_power_on(rmi4_data, false); err_power_device: synaptics_rmi4_regulator_configure(rmi4_data, false); err_reg_configure: input_free_device(rmi4_data->input_dev); rmi4_data->input_dev = NULL; err_input_device: kfree(rmi4_data); Loading @@ -1824,8 +2037,6 @@ static int synaptics_rmi4_remove(struct i2c_client *client) struct synaptics_rmi4_fn *fhandler; struct synaptics_rmi4_data *rmi4_data = i2c_get_clientdata(client); struct synaptics_rmi4_device_info *rmi; const struct synaptics_rmi4_platform_data *platform_data = rmi4_data->board; rmi = &(rmi4_data->rmi4_mod_info); Loading @@ -1845,11 +2056,6 @@ static int synaptics_rmi4_remove(struct i2c_client *client) input_unregister_device(rmi4_data->input_dev); if (platform_data->regulator_en) { regulator_disable(rmi4_data->regulator); regulator_put(rmi4_data->regulator); } if (!list_empty(&rmi->support_fn_list)) { list_for_each_entry(fhandler, &rmi->support_fn_list, link) { if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) Loading @@ -1859,7 +2065,14 @@ static int synaptics_rmi4_remove(struct i2c_client *client) kfree(fhandler); } } input_free_device(rmi4_data->input_dev); if (gpio_is_valid(rmi4_data->board->reset_gpio)) gpio_free(rmi4_data->board->reset_gpio); if (gpio_is_valid(rmi4_data->board->irq_gpio)) gpio_free(rmi4_data->board->irq_gpio); synaptics_rmi4_power_on(rmi4_data, false); synaptics_rmi4_regulator_configure(rmi4_data, false); kfree(rmi4_data); Loading Loading @@ -2013,8 +2226,6 @@ static void synaptics_rmi4_late_resume(struct early_suspend *h) static int synaptics_rmi4_suspend(struct device *dev) { struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); const struct synaptics_rmi4_platform_data *platform_data = rmi4_data->board; if (!rmi4_data->sensor_sleep) { rmi4_data->touch_stopped = true; Loading @@ -2023,9 +2234,6 @@ static int synaptics_rmi4_suspend(struct device *dev) synaptics_rmi4_sensor_sleep(rmi4_data); } if (platform_data->regulator_en) regulator_disable(rmi4_data->regulator); return 0; } Loading @@ -2041,16 +2249,7 @@ static int synaptics_rmi4_suspend(struct device *dev) */ static int synaptics_rmi4_resume(struct device *dev) { int ret; struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); const struct synaptics_rmi4_platform_data *platform_data = rmi4_data->board; if (platform_data->regulator_en) { ret = regulator_enable(rmi4_data->regulator); if (ret) return ret; } synaptics_rmi4_sensor_wake(rmi4_data); rmi4_data->touch_stopped = false; Loading
drivers/input/touchscreen/synaptics_i2c_rmi4.h +7 −5 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ * * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com> * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com> * Copyright (c) 2013, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by Loading @@ -20,10 +21,10 @@ #ifndef _SYNAPTICS_DSX_RMI4_H_ #define _SYNAPTICS_DSX_RMI4_H_ #define SYNAPTICS_RMI4_DS4 0x0001 #define SYNAPTICS_RMI4_DS5 0x0002 #define SYNAPTICS_RMI4_DRIVER_PRODUCT SYNAPTICS_RMI4_DS4 #define SYNAPTICS_RMI4_DRIVER_VERSION 0x1001 #define SYNAPTICS_DS4 (1 << 0) #define SYNAPTICS_DS5 (1 << 1) #define SYNAPTICS_DSX_DRIVER_PRODUCT SYNAPTICS_DS4 #define SYNAPTICS_DSX_DRIVER_VERSION 0x1002 #include <linux/version.h> #ifdef CONFIG_HAS_EARLYSUSPEND Loading Loading @@ -187,7 +188,8 @@ struct synaptics_rmi4_data { struct input_dev *input_dev; const struct synaptics_rmi4_platform_data *board; struct synaptics_rmi4_device_info rmi4_mod_info; struct regulator *regulator; struct regulator *vdd; struct regulator *vcc_i2c; struct mutex rmi4_io_ctrl_mutex; struct delayed_work det_work; struct workqueue_struct *det_workqueue; Loading
drivers/input/touchscreen/synaptics_rmi_dev.c +1 −1 Original line number Diff line number Diff line Loading @@ -700,4 +700,4 @@ module_exit(rmidev_module_exit); MODULE_AUTHOR("Synaptics, Inc."); MODULE_DESCRIPTION("RMI4 RMI_Dev Module"); MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2");
include/linux/input/synaptics_dsx.h +2 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ * * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com> * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com> * Copyright (c) 2013, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by Loading Loading @@ -47,6 +48,7 @@ struct synaptics_rmi4_platform_data { bool x_flip; bool y_flip; bool regulator_en; bool i2c_pull_up; unsigned irq_gpio; unsigned long irq_flags; unsigned reset_gpio; Loading