Loading Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt 0 → 100644 +79 −0 Original line number Diff line number Diff line Goodix GT9xx series touch controller The Goodix GT9xx series touch controller is connected to the host processor via I2C. The controller generates interrupts when the user touches the panel. The host controller is expected to read the touch coordinates over I2C and pass the coordinates to the rest of the system. Required properties: - compatible : Should be "goodix,gt9xx" - reg : I2C slave address of the device. - interrupt-parent : Parent of interrupt. - interrupts : Configuration of touch panel controller interrupt GPIO. - goodix,family-id : Family identification of the controller. - interrupt-gpios : Interrupt gpio which is to provide interrupts to host, same as "interrupts" node. - reset-gpios : Reset gpio to control the reset of chip. - goodix,display-coords : Display coordinates in pixels. It is a four tuple consisting of min x, min y, max x and max y values. Optional properties: - avdd-supply : Power supply needed to power up the device, this is for fixed voltage external regulator. - vdd-supply : Power supply needed to power up the device, when use external regulator, do not add this property. - vcc-i2c-supply : Power source required to power up i2c bus. GT9xx series can provide 1.8V from internal LDO, add this properties base on hardware design. - goodix,panel-coords : Panel coordinates for the chip in pixels. It is a four tuple consisting of min x, min y, max x and max y values. - goodix,i2c-pull-up : To specify pull up is required. - goodix,no-force-update : To specify force update is allowed. - goodix,button-map : Button map of key codes. The number of key codes depend on panel. - goodix,cfg-data : Touchpanel controller configuration data, ask vendor to provide that. Default configuration will be used if this property is not present. Example: i2c@f9927000 { goodix@5d { compatible = "goodix,gt9xx"; reg = <0x5d>; interrupt-parent = <&msmgpio>; interrupts = <17 0x2008>; reset-gpios = <&msmgpio 16 0x00>; interrupt-gpios = <&msmgpio 17 0x00>; avdd-supply = <&tp_power>; goodix,panel-coords = <0 0 720 1200>; goodix,display-coords = <0 0 720 1080>; goodix,button-map= <158 102 139>; goodix,family-id = <0x0>; goodix,cfg-data = [ 41 D0 02 00 05 0A 05 01 01 08 12 58 50 41 03 05 00 00 00 00 00 00 00 00 00 00 00 8C 2E 0E 28 24 73 13 00 00 00 83 03 1D 40 02 00 00 00 03 64 32 00 00 00 1A 38 94 C0 02 00 00 00 04 9E 1C 00 8D 20 00 7A 26 00 6D 2C 00 60 34 00 60 10 38 68 00 F0 50 35 FF FF 27 00 00 00 00 00 01 1B 14 0C 14 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 02 04 06 08 0A 0C 0E 10 12 14 16 18 1A 1C FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 00 02 04 06 08 0A 0C 0F 10 12 13 14 16 18 1C 1D 1E 1F 20 21 22 24 26 28 29 2A FF FF FF FF FF FF FF FF FF 22 22 22 22 22 22 FF 07 01]; }; }; Documentation/devicetree/bindings/vendor-prefixes.txt +1 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,7 @@ firefly Firefly focaltech FocalTech Systems Co.,Ltd fsl Freescale Semiconductor GEFanuc GE Fanuc Intelligent Platforms Embedded Systems, Inc. goodix Goodix. Ltd. gef GE Fanuc Intelligent Platforms Embedded Systems, Inc. geniatech Geniatech, Inc. giantplus Giantplus Technology Co., Ltd. Loading drivers/input/touchscreen/gt9xx/gt9xx.c +498 −49 Original line number Diff line number Diff line Loading @@ -40,8 +40,11 @@ * By Meta, 2013/06/08 */ #include <linux/regulator/consumer.h> #include "gt9xx.h" #include <linux/of_gpio.h> #if GTP_ICS_SLOT_REPORT #include <linux/input/mt.h> #endif Loading @@ -55,6 +58,15 @@ #define GTP_I2C_ADDRESS_HIGH 0x14 #define GTP_I2C_ADDRESS_LOW 0x5D #define GOODIX_VTG_MIN_UV 2600000 #define GOODIX_VTG_MAX_UV 3300000 #define GOODIX_I2C_VTG_MIN_UV 1800000 #define GOODIX_I2C_VTG_MAX_UV 1800000 #define GOODIX_VDD_LOAD_MIN_UA 0 #define GOODIX_VDD_LOAD_MAX_UA 10000 #define GOODIX_VIO_LOAD_MIN_UA 0 #define GOODIX_VIO_LOAD_MAX_UA 10000 #define RESET_DELAY_T3_US 200 /* T3: > 100us */ #define RESET_DELAY_T4 20 /* T4: > 5ms */ Loading @@ -80,7 +92,10 @@ static void gtp_reset_guitar(struct goodix_ts_data *ts, int ms); static void gtp_int_sync(struct goodix_ts_data *ts, int ms); static int gtp_i2c_test(struct i2c_client *client); #ifdef CONFIG_HAS_EARLYSUSPEND #if defined(CONFIG_FB) static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data); #elif defined(CONFIG_HAS_EARLYSUSPEND) static void goodix_ts_early_suspend(struct early_suspend *h); static void goodix_ts_late_resume(struct early_suspend *h); #endif Loading Loading @@ -755,7 +770,7 @@ static void gtp_reset_guitar(struct goodix_ts_data *ts, int ms) #endif } #ifdef CONFIG_HAS_EARLYSUSPEND #if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_FB) #if GTP_SLIDE_WAKEUP /******************************************************* Function: Loading Loading @@ -860,16 +875,12 @@ static s8 gtp_wakeup_sleep(struct goodix_ts_data *ts) GTP_DEBUG_FUNC(); #if GTP_POWER_CTRL_SLEEP while (retry++ < 5) { gtp_reset_guitar(ts, 20); ret = gtp_send_cfg(ts); if (ret > 0) { dev_dbg(&ts->client->dev, "Wakeup sleep send config success."); continue; } dev_dbg(&ts->client->dev, "GTP Wakeup!"); return 1; } #else Loading Loading @@ -910,7 +921,7 @@ static s8 gtp_wakeup_sleep(struct goodix_ts_data *ts) dev_err(&ts->client->dev, "GTP wakeup sleep failed.\n"); return ret; } #endif /* !CONFIG_HAS_EARLYSUSPEND */ #endif /* !CONFIG_HAS_EARLYSUSPEND && !CONFIG_FB*/ /******************************************************* Function: Loading Loading @@ -1014,6 +1025,11 @@ static int gtp_init_panel(struct goodix_ts_data *ts) return -EINVAL; } if (ts->pdata->gtp_cfg_len) { config_data = ts->pdata->config_data; ts->config_data = ts->pdata->config_data; ts->gtp_cfg_len = ts->pdata->gtp_cfg_len; } else { config_data = devm_kzalloc(&client->dev, GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH, GFP_KERNEL); Loading @@ -1029,6 +1045,7 @@ static int gtp_init_panel(struct goodix_ts_data *ts) memset(&config_data[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH); memcpy(&config_data[GTP_ADDR_LENGTH], send_cfg_buf[sensor_id], ts->gtp_cfg_len); } #if GTP_CUSTOM_CFG config_data[RESOLUTION_LOC] = Loading Loading @@ -1345,6 +1362,318 @@ exit_free_inputdev: return ret; } 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; } /** * goodix_power_on - Turn device power ON * @ts: driver private data * * Returns zero on success, else an error. */ static int goodix_power_on(struct goodix_ts_data *ts) { int ret; if (!IS_ERR(ts->avdd)) { ret = reg_set_optimum_mode_check(ts->avdd, GOODIX_VDD_LOAD_MAX_UA); if (ret < 0) { dev_err(&ts->client->dev, "Regulator avdd set_opt failed rc=%d\n", ret); goto err_set_opt_avdd; } ret = regulator_enable(ts->avdd); if (ret) { dev_err(&ts->client->dev, "Regulator avdd enable failed ret=%d\n", ret); goto err_enable_avdd; } } if (!IS_ERR(ts->vdd)) { ret = regulator_set_voltage(ts->vdd, GOODIX_VTG_MIN_UV, GOODIX_VTG_MAX_UV); if (ret) { dev_err(&ts->client->dev, "Regulator set_vtg failed vdd ret=%d\n", ret); goto err_set_vtg_vdd; } ret = reg_set_optimum_mode_check(ts->vdd, GOODIX_VDD_LOAD_MAX_UA); if (ret < 0) { dev_err(&ts->client->dev, "Regulator vdd set_opt failed rc=%d\n", ret); goto err_set_opt_vdd; } ret = regulator_enable(ts->vdd); if (ret) { dev_err(&ts->client->dev, "Regulator vdd enable failed ret=%d\n", ret); goto err_enable_vdd; } } if (!IS_ERR(ts->vcc_i2c)) { ret = regulator_set_voltage(ts->vcc_i2c, GOODIX_I2C_VTG_MIN_UV, GOODIX_I2C_VTG_MAX_UV); if (ret) { dev_err(&ts->client->dev, "Regulator set_vtg failed vcc_i2c ret=%d\n", ret); goto err_set_vtg_vcc_i2c; } ret = reg_set_optimum_mode_check(ts->vcc_i2c, GOODIX_VIO_LOAD_MAX_UA); if (ret < 0) { dev_err(&ts->client->dev, "Regulator vcc_i2c set_opt failed rc=%d\n", ret); goto err_set_opt_vcc_i2c; } ret = regulator_enable(ts->vcc_i2c); if (ret) { dev_err(&ts->client->dev, "Regulator vcc_i2c enable failed ret=%d\n", ret); regulator_disable(ts->vdd); goto err_enable_vcc_i2c; } } return 0; err_enable_vcc_i2c: err_set_opt_vcc_i2c: if (!IS_ERR(ts->vcc_i2c)) regulator_set_voltage(ts->vcc_i2c, 0, GOODIX_I2C_VTG_MAX_UV); err_set_vtg_vcc_i2c: if (!IS_ERR(ts->vdd)) regulator_disable(ts->vdd); err_enable_vdd: err_set_opt_vdd: if (!IS_ERR(ts->vdd)) regulator_set_voltage(ts->vdd, 0, GOODIX_VTG_MAX_UV); err_set_vtg_vdd: if (!IS_ERR(ts->avdd)) regulator_disable(ts->avdd); err_enable_avdd: err_set_opt_avdd: return ret; } /** * goodix_power_off - Turn device power OFF * @ts: driver private data * * Returns zero on success, else an error. */ static int goodix_power_off(struct goodix_ts_data *ts) { int ret; if (!IS_ERR(ts->vcc_i2c)) { ret = regulator_set_voltage(ts->vcc_i2c, 0, GOODIX_I2C_VTG_MAX_UV); if (ret < 0) dev_err(&ts->client->dev, "Regulator vcc_i2c set_vtg failed ret=%d\n", ret); ret = regulator_disable(ts->vcc_i2c); if (ret) dev_err(&ts->client->dev, "Regulator vcc_i2c disable failed ret=%d\n", ret); } if (!IS_ERR(ts->vdd)) { ret = regulator_set_voltage(ts->vdd, 0, GOODIX_VTG_MAX_UV); if (ret < 0) dev_err(&ts->client->dev, "Regulator vdd set_vtg failed ret=%d\n", ret); ret = regulator_disable(ts->vdd); if (ret) dev_err(&ts->client->dev, "Regulator vdd disable failed ret=%d\n", ret); } if (!IS_ERR(ts->avdd)) { ret = regulator_disable(ts->avdd); if (ret) dev_err(&ts->client->dev, "Regulator avdd disable failed ret=%d\n", ret); } return 0; } /** * goodix_power_init - Initialize device power * @ts: driver private data * * Returns zero on success, else an error. */ static int goodix_power_init(struct goodix_ts_data *ts) { int ret; ts->avdd = regulator_get(&ts->client->dev, "avdd"); if (IS_ERR(ts->avdd)) { ret = PTR_ERR(ts->avdd); dev_info(&ts->client->dev, "Regulator get failed avdd ret=%d\n", ret); } ts->vdd = regulator_get(&ts->client->dev, "vdd"); if (IS_ERR(ts->vdd)) { ret = PTR_ERR(ts->vdd); dev_info(&ts->client->dev, "Regulator get failed vdd ret=%d\n", ret); } ts->vcc_i2c = regulator_get(&ts->client->dev, "vcc-i2c"); if (IS_ERR(ts->vcc_i2c)) { ret = PTR_ERR(ts->vcc_i2c); dev_info(&ts->client->dev, "Regulator get failed vcc_i2c ret=%d\n", ret); } return 0; } /** * goodix_power_deinit - Deinitialize device power * @ts: driver private data * * Returns zero on success, else an error. */ static int goodix_power_deinit(struct goodix_ts_data *ts) { regulator_put(ts->vdd); regulator_put(ts->vcc_i2c); regulator_put(ts->avdd); return 0; } static int goodix_ts_get_dt_coords(struct device *dev, char *name, struct goodix_ts_platform_data *pdata) { struct property *prop; struct device_node *np = dev->of_node; int rc; u32 coords[GOODIX_COORDS_ARR_SIZE]; prop = of_find_property(np, name, NULL); if (!prop) return -EINVAL; if (!prop->value) return -ENODATA; rc = of_property_read_u32_array(np, name, coords, GOODIX_COORDS_ARR_SIZE); if (rc && (rc != -EINVAL)) { dev_err(dev, "Unable to read %s\n", name); return rc; } if (!strcmp(name, "goodix,panel-coords")) { pdata->panel_minx = coords[0]; pdata->panel_miny = coords[1]; pdata->panel_maxx = coords[2]; pdata->panel_maxy = coords[3]; } else if (!strcmp(name, "goodix,display-coords")) { pdata->x_min = coords[0]; pdata->y_min = coords[1]; pdata->x_max = coords[2]; pdata->y_max = coords[3]; } else { dev_err(dev, "unsupported property %s\n", name); return -EINVAL; } return 0; } static int goodix_parse_dt(struct device *dev, struct goodix_ts_platform_data *pdata) { int rc; struct device_node *np = dev->of_node; struct property *prop; u32 temp_val, num_buttons; u32 button_map[MAX_BUTTONS]; rc = goodix_ts_get_dt_coords(dev, "goodix,panel-coords", pdata); if (rc && (rc != -EINVAL)) return rc; rc = goodix_ts_get_dt_coords(dev, "goodix,display-coords", pdata); if (rc) return rc; pdata->i2c_pull_up = of_property_read_bool(np, "goodix,i2c-pull-up"); pdata->no_force_update = of_property_read_bool(np, "goodix,no-force-update"); /* reset, irq gpio info */ pdata->reset_gpio = of_get_named_gpio_flags(np, "reset-gpios", 0, &pdata->reset_gpio_flags); if (pdata->reset_gpio < 0) return pdata->reset_gpio; pdata->irq_gpio = of_get_named_gpio_flags(np, "interrupt-gpios", 0, &pdata->irq_gpio_flags); if (pdata->irq_gpio < 0) return pdata->irq_gpio; rc = of_property_read_u32(np, "goodix,family-id", &temp_val); if (!rc) pdata->family_id = temp_val; else return rc; prop = of_find_property(np, "goodix,button-map", NULL); if (prop) { num_buttons = prop->length / sizeof(temp_val); if (num_buttons > MAX_BUTTONS) return -EINVAL; rc = of_property_read_u32_array(np, "goodix,button-map", button_map, num_buttons); if (rc) { dev_err(dev, "Unable to read key codes\n"); return rc; } } prop = of_find_property(np, "goodix,cfg-data", &pdata->gtp_cfg_len); if (prop && prop->value) { pdata->config_data = devm_kzalloc(dev, GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH, GFP_KERNEL); if (!pdata->config_data) return -ENOMEM; pdata->config_data[0] = GTP_REG_CONFIG_DATA >> 8; pdata->config_data[1] = GTP_REG_CONFIG_DATA & 0xff; memset(&pdata->config_data[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH); memcpy(&pdata->config_data[GTP_ADDR_LENGTH], prop->value, pdata->gtp_cfg_len); } else { dev_err(dev, "Unable to get configure data, default will be used.\n"); pdata->gtp_cfg_len = 0; } return 0; } /******************************************************* Function: I2c probe. Loading @@ -1359,15 +1688,34 @@ Output: static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct goodix_ts_platform_data *pdata; struct goodix_ts_data *ts; u16 version_info; int ret; dev_dbg(&client->dev, "GTP I2C Address: 0x%02x\n", client->addr); if (client->dev.of_node) { pdata = devm_kzalloc(&client->dev, sizeof(struct goodix_ts_platform_data), GFP_KERNEL); if (!pdata) return -ENOMEM; ret = goodix_parse_dt(&client->dev, pdata); if (ret) return ret; } else { pdata = client->dev.platform_data; } if (!pdata) { dev_err(&client->dev, "GTP invalid pdata\n"); return -EINVAL; } #if GTP_ESD_PROTECT i2c_connect_client = client; #endif if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { dev_err(&client->dev, "GTP I2C not supported\n"); return -ENODEV; Loading @@ -1379,14 +1727,26 @@ static int goodix_ts_probe(struct i2c_client *client, memset(ts, 0, sizeof(*ts)); ts->client = client; /* For kernel 2.6.39 later we spin_lock_init(&ts->irq_lock) ts->pdata = pdata; /* For 2.6.39 & later use spin_lock_init(&ts->irq_lock) * For 2.6.39 & before, use ts->irq_lock = SPIN_LOCK_UNLOCKED */ spin_lock_init(&ts->irq_lock); i2c_set_clientdata(client, ts); ts->gtp_rawdiff_mode = 0; ret = goodix_power_init(ts); if (ret) { dev_err(&client->dev, "GTP power init failed\n"); goto exit_free_client_data; } ret = goodix_power_on(ts); if (ret) { dev_err(&client->dev, "GTP power on failed\n"); goto exit_deinit_power; } ret = gtp_request_io_port(ts); if (ret) { dev_err(&client->dev, "GTP request IO port failed.\n"); Loading Loading @@ -1424,6 +1784,20 @@ static int goodix_ts_probe(struct i2c_client *client, goto exit_free_inputdev; } #if defined(CONFIG_FB) ts->fb_notif.notifier_call = fb_notifier_callback; ret = fb_register_client(&ts->fb_notif); if (ret) dev_err(&ts->client->dev, "Unable to register fb_notifier: %d\n", ret); #elif defined(CONFIG_HAS_EARLYSUSPEND) ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; ts->early_suspend.suspend = goodix_ts_early_suspend; ts->early_suspend.resume = goodix_ts_late_resume; register_early_suspend(&ts->early_suspend); #endif ts->goodix_wq = create_singlethread_workqueue("goodix_wq"); INIT_WORK(&ts->work, goodix_ts_work_func); Loading Loading @@ -1451,6 +1825,13 @@ static int goodix_ts_probe(struct i2c_client *client, init_done = true; return 0; exit_free_irq: #if defined(CONFIG_FB) if (fb_unregister_client(&ts->fb_notif)) dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n"); #elif defined(CONFIG_HAS_EARLYSUSPEND) unregister_early_suspend(&ts->early_suspend); #endif if (ts->use_irq) free_irq(client->irq, ts); else Loading @@ -1467,7 +1848,15 @@ exit_free_irq: exit_free_inputdev: kfree(ts->config_data); exit_free_io_port: if (gpio_is_valid(pdata->reset_gpio)) gpio_free(pdata->reset_gpio); if (gpio_is_valid(pdata->irq_gpio)) gpio_free(pdata->irq_gpio); exit_power_off: goodix_power_off(ts); exit_deinit_power: goodix_power_deinit(ts); exit_free_client_data: i2c_set_clientdata(client, NULL); kfree(ts); return ret; Loading @@ -1486,7 +1875,11 @@ static int goodix_ts_remove(struct i2c_client *client) struct goodix_ts_data *ts = i2c_get_clientdata(client); GTP_DEBUG_FUNC(); #ifdef CONFIG_HAS_EARLYSUSPEND #if defined(CONFIG_FB) if (fb_unregister_client(&ts->fb_notif)) dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n"); #elif defined(CONFIG_HAS_EARLYSUSPEND) unregister_early_suspend(&ts->early_suspend); #endif Loading Loading @@ -1522,6 +1915,8 @@ static int goodix_ts_remove(struct i2c_client *client) if (gpio_is_valid(ts->pdata->irq_gpio)) gpio_free(ts->pdata->irq_gpio); goodix_power_off(ts); goodix_power_deinit(ts); i2c_set_clientdata(client, NULL); kfree(ts); } Loading @@ -1529,7 +1924,7 @@ static int goodix_ts_remove(struct i2c_client *client) return 0; } #ifdef CONFIG_HAS_EARLYSUSPEND #if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_FB) /******************************************************* Function: Early suspend function. Loading @@ -1538,12 +1933,9 @@ Input: Output: None. *******************************************************/ static void goodix_ts_early_suspend(struct early_suspend *h) static void goodix_ts_suspend(struct goodix_ts_data *ts) { struct goodix_ts_data *ts; s8 ret = -1; ts = container_of(h, struct goodix_ts_data, early_suspend); int ret = -1; GTP_DEBUG_FUNC(); Loading Loading @@ -1577,12 +1969,9 @@ Input: Output: None. *******************************************************/ static void goodix_ts_late_resume(struct early_suspend *h) static void goodix_ts_resume(struct goodix_ts_data *ts) { struct goodix_ts_data *ts; s8 ret = -1; ts = container_of(h, struct goodix_ts_data, early_suspend); int ret = -1; GTP_DEBUG_FUNC(); Loading @@ -1593,7 +1982,7 @@ static void goodix_ts_late_resume(struct early_suspend *h) #endif if (ret < 0) dev_err(&ts->client->dev, "GTP later resume failed.\n"); dev_err(&ts->client->dev, "GTP resume failed.\n"); if (ts->use_irq) gtp_irq_enable(ts); Loading @@ -1606,18 +1995,72 @@ static void goodix_ts_late_resume(struct early_suspend *h) gtp_esd_switch(ts->client, SWITCH_ON); #endif } #if defined(CONFIG_FB) static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data) { struct fb_event *evdata = data; int *blank; struct goodix_ts_data *ts = container_of(self, struct goodix_ts_data, fb_notif); if (evdata && evdata->data && event == FB_EVENT_BLANK && ts && ts->client) { blank = evdata->data; if (*blank == FB_BLANK_UNBLANK) goodix_ts_resume(ts); else if (*blank == FB_BLANK_POWERDOWN) goodix_ts_suspend(ts); } return 0; } #elif defined(CONFIG_HAS_EARLYSUSPEND) /* * Function: * Early suspend function. * Input: * h: early_suspend struct. * Output: * None. */ static void goodix_ts_early_suspend(struct early_suspend *h) { struct goodix_ts_data *ts; ts = container_of(h, struct goodix_ts_data, early_suspend); goodix_ts_suspend(ts); } /* * Function: * Late resume function. * Input: * h: early_suspend struct. * Output: * None. */ static void goodix_ts_late_resume(struct early_suspend *h) { struct goodix_ts_data *ts; ts = container_of(h, struct goodix_ts_data, early_suspend); goodix_ts_late_resume(ts); } #endif #endif /* !CONFIG_HAS_EARLYSUSPEND && !CONFIG_FB*/ #if GTP_ESD_PROTECT /******************************************************* Function: switch on & off esd delayed work Input: client: i2c device on: SWITCH_ON / SWITCH_OFF Output: void *********************************************************/ /* * Function: * switch on & off esd delayed work * Input: * client: i2c device * on: SWITCH_ON / SWITCH_OFF * Output: * void */ void gtp_esd_switch(struct i2c_client *client, int on) { struct goodix_ts_data *ts; Loading Loading @@ -1749,6 +2192,11 @@ static const struct i2c_device_id goodix_ts_id[] = { { } }; static const struct of_device_id goodix_match_table[] = { { .compatible = "goodix,gt9xx", }, { }, }; static struct i2c_driver goodix_ts_driver = { .probe = goodix_ts_probe, .remove = goodix_ts_remove, Loading @@ -1760,6 +2208,7 @@ static struct i2c_driver goodix_ts_driver = { .driver = { .name = GTP_I2C_NAME, .owner = THIS_MODULE, .of_match_table = goodix_match_table, }, }; Loading drivers/input/touchscreen/gt9xx/gt9xx.h +16 −7 Original line number Diff line number Diff line Loading @@ -33,7 +33,11 @@ #include <linux/regulator/consumer.h> #include <linux/firmware.h> #include <linux/debugfs.h> #if defined(CONFIG_HAS_EARLYSUSPEND) #if defined(CONFIG_FB) #include <linux/notifier.h> #include <linux/fb.h> #elif defined(CONFIG_HAS_EARLYSUSPEND) #include <linux/earlysuspend.h> #define GOODIX_SUSPEND_LEVEL 1 #endif Loading @@ -43,8 +47,6 @@ struct goodix_ts_platform_data { u32 irq_gpio_flags; int reset_gpio; u32 reset_gpio_flags; int ldo_en_gpio; u32 ldo_en_gpio_flags; u32 family_id; u32 x_max; u32 y_max; Loading @@ -56,6 +58,8 @@ struct goodix_ts_platform_data { u32 panel_maxy; bool no_force_update; bool i2c_pull_up; int gtp_cfg_len; u8 *config_data; }; struct goodix_ts_data { spinlock_t irq_lock; Loading @@ -65,9 +69,6 @@ struct goodix_ts_data { struct hrtimer timer; struct workqueue_struct *goodix_wq; struct work_struct work; #if defined(CONFIG_HAS_EARLYSUSPEND) struct early_suspend early_suspend; #endif s32 irq_is_disabled; s32 use_irq; u16 abs_x_max; Loading @@ -84,6 +85,14 @@ struct goodix_ts_data { u8 fixed_cfg; u8 esd_running; u8 fw_error; struct regulator *avdd; struct regulator *vdd; struct regulator *vcc_i2c; #if defined(CONFIG_FB) struct notifier_block fb_notif; #elif defined(CONFIG_HAS_EARLYSUSPEND) struct early_suspend early_suspend; #endif }; extern u16 show_len; Loading @@ -94,7 +103,7 @@ extern u16 total_len; #define GTP_CHANGE_X2Y 0 #define GTP_DRIVER_SEND_CFG 1 #define GTP_HAVE_TOUCH_KEY 1 #define GTP_POWER_CTRL_SLEEP 1 #define GTP_POWER_CTRL_SLEEP 0 #define GTP_ICS_SLOT_REPORT 0 /* auto updated by .bin file as default */ Loading Loading
Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt 0 → 100644 +79 −0 Original line number Diff line number Diff line Goodix GT9xx series touch controller The Goodix GT9xx series touch controller is connected to the host processor via I2C. The controller generates interrupts when the user touches the panel. The host controller is expected to read the touch coordinates over I2C and pass the coordinates to the rest of the system. Required properties: - compatible : Should be "goodix,gt9xx" - reg : I2C slave address of the device. - interrupt-parent : Parent of interrupt. - interrupts : Configuration of touch panel controller interrupt GPIO. - goodix,family-id : Family identification of the controller. - interrupt-gpios : Interrupt gpio which is to provide interrupts to host, same as "interrupts" node. - reset-gpios : Reset gpio to control the reset of chip. - goodix,display-coords : Display coordinates in pixels. It is a four tuple consisting of min x, min y, max x and max y values. Optional properties: - avdd-supply : Power supply needed to power up the device, this is for fixed voltage external regulator. - vdd-supply : Power supply needed to power up the device, when use external regulator, do not add this property. - vcc-i2c-supply : Power source required to power up i2c bus. GT9xx series can provide 1.8V from internal LDO, add this properties base on hardware design. - goodix,panel-coords : Panel coordinates for the chip in pixels. It is a four tuple consisting of min x, min y, max x and max y values. - goodix,i2c-pull-up : To specify pull up is required. - goodix,no-force-update : To specify force update is allowed. - goodix,button-map : Button map of key codes. The number of key codes depend on panel. - goodix,cfg-data : Touchpanel controller configuration data, ask vendor to provide that. Default configuration will be used if this property is not present. Example: i2c@f9927000 { goodix@5d { compatible = "goodix,gt9xx"; reg = <0x5d>; interrupt-parent = <&msmgpio>; interrupts = <17 0x2008>; reset-gpios = <&msmgpio 16 0x00>; interrupt-gpios = <&msmgpio 17 0x00>; avdd-supply = <&tp_power>; goodix,panel-coords = <0 0 720 1200>; goodix,display-coords = <0 0 720 1080>; goodix,button-map= <158 102 139>; goodix,family-id = <0x0>; goodix,cfg-data = [ 41 D0 02 00 05 0A 05 01 01 08 12 58 50 41 03 05 00 00 00 00 00 00 00 00 00 00 00 8C 2E 0E 28 24 73 13 00 00 00 83 03 1D 40 02 00 00 00 03 64 32 00 00 00 1A 38 94 C0 02 00 00 00 04 9E 1C 00 8D 20 00 7A 26 00 6D 2C 00 60 34 00 60 10 38 68 00 F0 50 35 FF FF 27 00 00 00 00 00 01 1B 14 0C 14 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 02 04 06 08 0A 0C 0E 10 12 14 16 18 1A 1C FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 00 02 04 06 08 0A 0C 0F 10 12 13 14 16 18 1C 1D 1E 1F 20 21 22 24 26 28 29 2A FF FF FF FF FF FF FF FF FF 22 22 22 22 22 22 FF 07 01]; }; };
Documentation/devicetree/bindings/vendor-prefixes.txt +1 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,7 @@ firefly Firefly focaltech FocalTech Systems Co.,Ltd fsl Freescale Semiconductor GEFanuc GE Fanuc Intelligent Platforms Embedded Systems, Inc. goodix Goodix. Ltd. gef GE Fanuc Intelligent Platforms Embedded Systems, Inc. geniatech Geniatech, Inc. giantplus Giantplus Technology Co., Ltd. Loading
drivers/input/touchscreen/gt9xx/gt9xx.c +498 −49 Original line number Diff line number Diff line Loading @@ -40,8 +40,11 @@ * By Meta, 2013/06/08 */ #include <linux/regulator/consumer.h> #include "gt9xx.h" #include <linux/of_gpio.h> #if GTP_ICS_SLOT_REPORT #include <linux/input/mt.h> #endif Loading @@ -55,6 +58,15 @@ #define GTP_I2C_ADDRESS_HIGH 0x14 #define GTP_I2C_ADDRESS_LOW 0x5D #define GOODIX_VTG_MIN_UV 2600000 #define GOODIX_VTG_MAX_UV 3300000 #define GOODIX_I2C_VTG_MIN_UV 1800000 #define GOODIX_I2C_VTG_MAX_UV 1800000 #define GOODIX_VDD_LOAD_MIN_UA 0 #define GOODIX_VDD_LOAD_MAX_UA 10000 #define GOODIX_VIO_LOAD_MIN_UA 0 #define GOODIX_VIO_LOAD_MAX_UA 10000 #define RESET_DELAY_T3_US 200 /* T3: > 100us */ #define RESET_DELAY_T4 20 /* T4: > 5ms */ Loading @@ -80,7 +92,10 @@ static void gtp_reset_guitar(struct goodix_ts_data *ts, int ms); static void gtp_int_sync(struct goodix_ts_data *ts, int ms); static int gtp_i2c_test(struct i2c_client *client); #ifdef CONFIG_HAS_EARLYSUSPEND #if defined(CONFIG_FB) static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data); #elif defined(CONFIG_HAS_EARLYSUSPEND) static void goodix_ts_early_suspend(struct early_suspend *h); static void goodix_ts_late_resume(struct early_suspend *h); #endif Loading Loading @@ -755,7 +770,7 @@ static void gtp_reset_guitar(struct goodix_ts_data *ts, int ms) #endif } #ifdef CONFIG_HAS_EARLYSUSPEND #if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_FB) #if GTP_SLIDE_WAKEUP /******************************************************* Function: Loading Loading @@ -860,16 +875,12 @@ static s8 gtp_wakeup_sleep(struct goodix_ts_data *ts) GTP_DEBUG_FUNC(); #if GTP_POWER_CTRL_SLEEP while (retry++ < 5) { gtp_reset_guitar(ts, 20); ret = gtp_send_cfg(ts); if (ret > 0) { dev_dbg(&ts->client->dev, "Wakeup sleep send config success."); continue; } dev_dbg(&ts->client->dev, "GTP Wakeup!"); return 1; } #else Loading Loading @@ -910,7 +921,7 @@ static s8 gtp_wakeup_sleep(struct goodix_ts_data *ts) dev_err(&ts->client->dev, "GTP wakeup sleep failed.\n"); return ret; } #endif /* !CONFIG_HAS_EARLYSUSPEND */ #endif /* !CONFIG_HAS_EARLYSUSPEND && !CONFIG_FB*/ /******************************************************* Function: Loading Loading @@ -1014,6 +1025,11 @@ static int gtp_init_panel(struct goodix_ts_data *ts) return -EINVAL; } if (ts->pdata->gtp_cfg_len) { config_data = ts->pdata->config_data; ts->config_data = ts->pdata->config_data; ts->gtp_cfg_len = ts->pdata->gtp_cfg_len; } else { config_data = devm_kzalloc(&client->dev, GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH, GFP_KERNEL); Loading @@ -1029,6 +1045,7 @@ static int gtp_init_panel(struct goodix_ts_data *ts) memset(&config_data[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH); memcpy(&config_data[GTP_ADDR_LENGTH], send_cfg_buf[sensor_id], ts->gtp_cfg_len); } #if GTP_CUSTOM_CFG config_data[RESOLUTION_LOC] = Loading Loading @@ -1345,6 +1362,318 @@ exit_free_inputdev: return ret; } 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; } /** * goodix_power_on - Turn device power ON * @ts: driver private data * * Returns zero on success, else an error. */ static int goodix_power_on(struct goodix_ts_data *ts) { int ret; if (!IS_ERR(ts->avdd)) { ret = reg_set_optimum_mode_check(ts->avdd, GOODIX_VDD_LOAD_MAX_UA); if (ret < 0) { dev_err(&ts->client->dev, "Regulator avdd set_opt failed rc=%d\n", ret); goto err_set_opt_avdd; } ret = regulator_enable(ts->avdd); if (ret) { dev_err(&ts->client->dev, "Regulator avdd enable failed ret=%d\n", ret); goto err_enable_avdd; } } if (!IS_ERR(ts->vdd)) { ret = regulator_set_voltage(ts->vdd, GOODIX_VTG_MIN_UV, GOODIX_VTG_MAX_UV); if (ret) { dev_err(&ts->client->dev, "Regulator set_vtg failed vdd ret=%d\n", ret); goto err_set_vtg_vdd; } ret = reg_set_optimum_mode_check(ts->vdd, GOODIX_VDD_LOAD_MAX_UA); if (ret < 0) { dev_err(&ts->client->dev, "Regulator vdd set_opt failed rc=%d\n", ret); goto err_set_opt_vdd; } ret = regulator_enable(ts->vdd); if (ret) { dev_err(&ts->client->dev, "Regulator vdd enable failed ret=%d\n", ret); goto err_enable_vdd; } } if (!IS_ERR(ts->vcc_i2c)) { ret = regulator_set_voltage(ts->vcc_i2c, GOODIX_I2C_VTG_MIN_UV, GOODIX_I2C_VTG_MAX_UV); if (ret) { dev_err(&ts->client->dev, "Regulator set_vtg failed vcc_i2c ret=%d\n", ret); goto err_set_vtg_vcc_i2c; } ret = reg_set_optimum_mode_check(ts->vcc_i2c, GOODIX_VIO_LOAD_MAX_UA); if (ret < 0) { dev_err(&ts->client->dev, "Regulator vcc_i2c set_opt failed rc=%d\n", ret); goto err_set_opt_vcc_i2c; } ret = regulator_enable(ts->vcc_i2c); if (ret) { dev_err(&ts->client->dev, "Regulator vcc_i2c enable failed ret=%d\n", ret); regulator_disable(ts->vdd); goto err_enable_vcc_i2c; } } return 0; err_enable_vcc_i2c: err_set_opt_vcc_i2c: if (!IS_ERR(ts->vcc_i2c)) regulator_set_voltage(ts->vcc_i2c, 0, GOODIX_I2C_VTG_MAX_UV); err_set_vtg_vcc_i2c: if (!IS_ERR(ts->vdd)) regulator_disable(ts->vdd); err_enable_vdd: err_set_opt_vdd: if (!IS_ERR(ts->vdd)) regulator_set_voltage(ts->vdd, 0, GOODIX_VTG_MAX_UV); err_set_vtg_vdd: if (!IS_ERR(ts->avdd)) regulator_disable(ts->avdd); err_enable_avdd: err_set_opt_avdd: return ret; } /** * goodix_power_off - Turn device power OFF * @ts: driver private data * * Returns zero on success, else an error. */ static int goodix_power_off(struct goodix_ts_data *ts) { int ret; if (!IS_ERR(ts->vcc_i2c)) { ret = regulator_set_voltage(ts->vcc_i2c, 0, GOODIX_I2C_VTG_MAX_UV); if (ret < 0) dev_err(&ts->client->dev, "Regulator vcc_i2c set_vtg failed ret=%d\n", ret); ret = regulator_disable(ts->vcc_i2c); if (ret) dev_err(&ts->client->dev, "Regulator vcc_i2c disable failed ret=%d\n", ret); } if (!IS_ERR(ts->vdd)) { ret = regulator_set_voltage(ts->vdd, 0, GOODIX_VTG_MAX_UV); if (ret < 0) dev_err(&ts->client->dev, "Regulator vdd set_vtg failed ret=%d\n", ret); ret = regulator_disable(ts->vdd); if (ret) dev_err(&ts->client->dev, "Regulator vdd disable failed ret=%d\n", ret); } if (!IS_ERR(ts->avdd)) { ret = regulator_disable(ts->avdd); if (ret) dev_err(&ts->client->dev, "Regulator avdd disable failed ret=%d\n", ret); } return 0; } /** * goodix_power_init - Initialize device power * @ts: driver private data * * Returns zero on success, else an error. */ static int goodix_power_init(struct goodix_ts_data *ts) { int ret; ts->avdd = regulator_get(&ts->client->dev, "avdd"); if (IS_ERR(ts->avdd)) { ret = PTR_ERR(ts->avdd); dev_info(&ts->client->dev, "Regulator get failed avdd ret=%d\n", ret); } ts->vdd = regulator_get(&ts->client->dev, "vdd"); if (IS_ERR(ts->vdd)) { ret = PTR_ERR(ts->vdd); dev_info(&ts->client->dev, "Regulator get failed vdd ret=%d\n", ret); } ts->vcc_i2c = regulator_get(&ts->client->dev, "vcc-i2c"); if (IS_ERR(ts->vcc_i2c)) { ret = PTR_ERR(ts->vcc_i2c); dev_info(&ts->client->dev, "Regulator get failed vcc_i2c ret=%d\n", ret); } return 0; } /** * goodix_power_deinit - Deinitialize device power * @ts: driver private data * * Returns zero on success, else an error. */ static int goodix_power_deinit(struct goodix_ts_data *ts) { regulator_put(ts->vdd); regulator_put(ts->vcc_i2c); regulator_put(ts->avdd); return 0; } static int goodix_ts_get_dt_coords(struct device *dev, char *name, struct goodix_ts_platform_data *pdata) { struct property *prop; struct device_node *np = dev->of_node; int rc; u32 coords[GOODIX_COORDS_ARR_SIZE]; prop = of_find_property(np, name, NULL); if (!prop) return -EINVAL; if (!prop->value) return -ENODATA; rc = of_property_read_u32_array(np, name, coords, GOODIX_COORDS_ARR_SIZE); if (rc && (rc != -EINVAL)) { dev_err(dev, "Unable to read %s\n", name); return rc; } if (!strcmp(name, "goodix,panel-coords")) { pdata->panel_minx = coords[0]; pdata->panel_miny = coords[1]; pdata->panel_maxx = coords[2]; pdata->panel_maxy = coords[3]; } else if (!strcmp(name, "goodix,display-coords")) { pdata->x_min = coords[0]; pdata->y_min = coords[1]; pdata->x_max = coords[2]; pdata->y_max = coords[3]; } else { dev_err(dev, "unsupported property %s\n", name); return -EINVAL; } return 0; } static int goodix_parse_dt(struct device *dev, struct goodix_ts_platform_data *pdata) { int rc; struct device_node *np = dev->of_node; struct property *prop; u32 temp_val, num_buttons; u32 button_map[MAX_BUTTONS]; rc = goodix_ts_get_dt_coords(dev, "goodix,panel-coords", pdata); if (rc && (rc != -EINVAL)) return rc; rc = goodix_ts_get_dt_coords(dev, "goodix,display-coords", pdata); if (rc) return rc; pdata->i2c_pull_up = of_property_read_bool(np, "goodix,i2c-pull-up"); pdata->no_force_update = of_property_read_bool(np, "goodix,no-force-update"); /* reset, irq gpio info */ pdata->reset_gpio = of_get_named_gpio_flags(np, "reset-gpios", 0, &pdata->reset_gpio_flags); if (pdata->reset_gpio < 0) return pdata->reset_gpio; pdata->irq_gpio = of_get_named_gpio_flags(np, "interrupt-gpios", 0, &pdata->irq_gpio_flags); if (pdata->irq_gpio < 0) return pdata->irq_gpio; rc = of_property_read_u32(np, "goodix,family-id", &temp_val); if (!rc) pdata->family_id = temp_val; else return rc; prop = of_find_property(np, "goodix,button-map", NULL); if (prop) { num_buttons = prop->length / sizeof(temp_val); if (num_buttons > MAX_BUTTONS) return -EINVAL; rc = of_property_read_u32_array(np, "goodix,button-map", button_map, num_buttons); if (rc) { dev_err(dev, "Unable to read key codes\n"); return rc; } } prop = of_find_property(np, "goodix,cfg-data", &pdata->gtp_cfg_len); if (prop && prop->value) { pdata->config_data = devm_kzalloc(dev, GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH, GFP_KERNEL); if (!pdata->config_data) return -ENOMEM; pdata->config_data[0] = GTP_REG_CONFIG_DATA >> 8; pdata->config_data[1] = GTP_REG_CONFIG_DATA & 0xff; memset(&pdata->config_data[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH); memcpy(&pdata->config_data[GTP_ADDR_LENGTH], prop->value, pdata->gtp_cfg_len); } else { dev_err(dev, "Unable to get configure data, default will be used.\n"); pdata->gtp_cfg_len = 0; } return 0; } /******************************************************* Function: I2c probe. Loading @@ -1359,15 +1688,34 @@ Output: static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct goodix_ts_platform_data *pdata; struct goodix_ts_data *ts; u16 version_info; int ret; dev_dbg(&client->dev, "GTP I2C Address: 0x%02x\n", client->addr); if (client->dev.of_node) { pdata = devm_kzalloc(&client->dev, sizeof(struct goodix_ts_platform_data), GFP_KERNEL); if (!pdata) return -ENOMEM; ret = goodix_parse_dt(&client->dev, pdata); if (ret) return ret; } else { pdata = client->dev.platform_data; } if (!pdata) { dev_err(&client->dev, "GTP invalid pdata\n"); return -EINVAL; } #if GTP_ESD_PROTECT i2c_connect_client = client; #endif if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { dev_err(&client->dev, "GTP I2C not supported\n"); return -ENODEV; Loading @@ -1379,14 +1727,26 @@ static int goodix_ts_probe(struct i2c_client *client, memset(ts, 0, sizeof(*ts)); ts->client = client; /* For kernel 2.6.39 later we spin_lock_init(&ts->irq_lock) ts->pdata = pdata; /* For 2.6.39 & later use spin_lock_init(&ts->irq_lock) * For 2.6.39 & before, use ts->irq_lock = SPIN_LOCK_UNLOCKED */ spin_lock_init(&ts->irq_lock); i2c_set_clientdata(client, ts); ts->gtp_rawdiff_mode = 0; ret = goodix_power_init(ts); if (ret) { dev_err(&client->dev, "GTP power init failed\n"); goto exit_free_client_data; } ret = goodix_power_on(ts); if (ret) { dev_err(&client->dev, "GTP power on failed\n"); goto exit_deinit_power; } ret = gtp_request_io_port(ts); if (ret) { dev_err(&client->dev, "GTP request IO port failed.\n"); Loading Loading @@ -1424,6 +1784,20 @@ static int goodix_ts_probe(struct i2c_client *client, goto exit_free_inputdev; } #if defined(CONFIG_FB) ts->fb_notif.notifier_call = fb_notifier_callback; ret = fb_register_client(&ts->fb_notif); if (ret) dev_err(&ts->client->dev, "Unable to register fb_notifier: %d\n", ret); #elif defined(CONFIG_HAS_EARLYSUSPEND) ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; ts->early_suspend.suspend = goodix_ts_early_suspend; ts->early_suspend.resume = goodix_ts_late_resume; register_early_suspend(&ts->early_suspend); #endif ts->goodix_wq = create_singlethread_workqueue("goodix_wq"); INIT_WORK(&ts->work, goodix_ts_work_func); Loading Loading @@ -1451,6 +1825,13 @@ static int goodix_ts_probe(struct i2c_client *client, init_done = true; return 0; exit_free_irq: #if defined(CONFIG_FB) if (fb_unregister_client(&ts->fb_notif)) dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n"); #elif defined(CONFIG_HAS_EARLYSUSPEND) unregister_early_suspend(&ts->early_suspend); #endif if (ts->use_irq) free_irq(client->irq, ts); else Loading @@ -1467,7 +1848,15 @@ exit_free_irq: exit_free_inputdev: kfree(ts->config_data); exit_free_io_port: if (gpio_is_valid(pdata->reset_gpio)) gpio_free(pdata->reset_gpio); if (gpio_is_valid(pdata->irq_gpio)) gpio_free(pdata->irq_gpio); exit_power_off: goodix_power_off(ts); exit_deinit_power: goodix_power_deinit(ts); exit_free_client_data: i2c_set_clientdata(client, NULL); kfree(ts); return ret; Loading @@ -1486,7 +1875,11 @@ static int goodix_ts_remove(struct i2c_client *client) struct goodix_ts_data *ts = i2c_get_clientdata(client); GTP_DEBUG_FUNC(); #ifdef CONFIG_HAS_EARLYSUSPEND #if defined(CONFIG_FB) if (fb_unregister_client(&ts->fb_notif)) dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n"); #elif defined(CONFIG_HAS_EARLYSUSPEND) unregister_early_suspend(&ts->early_suspend); #endif Loading Loading @@ -1522,6 +1915,8 @@ static int goodix_ts_remove(struct i2c_client *client) if (gpio_is_valid(ts->pdata->irq_gpio)) gpio_free(ts->pdata->irq_gpio); goodix_power_off(ts); goodix_power_deinit(ts); i2c_set_clientdata(client, NULL); kfree(ts); } Loading @@ -1529,7 +1924,7 @@ static int goodix_ts_remove(struct i2c_client *client) return 0; } #ifdef CONFIG_HAS_EARLYSUSPEND #if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_FB) /******************************************************* Function: Early suspend function. Loading @@ -1538,12 +1933,9 @@ Input: Output: None. *******************************************************/ static void goodix_ts_early_suspend(struct early_suspend *h) static void goodix_ts_suspend(struct goodix_ts_data *ts) { struct goodix_ts_data *ts; s8 ret = -1; ts = container_of(h, struct goodix_ts_data, early_suspend); int ret = -1; GTP_DEBUG_FUNC(); Loading Loading @@ -1577,12 +1969,9 @@ Input: Output: None. *******************************************************/ static void goodix_ts_late_resume(struct early_suspend *h) static void goodix_ts_resume(struct goodix_ts_data *ts) { struct goodix_ts_data *ts; s8 ret = -1; ts = container_of(h, struct goodix_ts_data, early_suspend); int ret = -1; GTP_DEBUG_FUNC(); Loading @@ -1593,7 +1982,7 @@ static void goodix_ts_late_resume(struct early_suspend *h) #endif if (ret < 0) dev_err(&ts->client->dev, "GTP later resume failed.\n"); dev_err(&ts->client->dev, "GTP resume failed.\n"); if (ts->use_irq) gtp_irq_enable(ts); Loading @@ -1606,18 +1995,72 @@ static void goodix_ts_late_resume(struct early_suspend *h) gtp_esd_switch(ts->client, SWITCH_ON); #endif } #if defined(CONFIG_FB) static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data) { struct fb_event *evdata = data; int *blank; struct goodix_ts_data *ts = container_of(self, struct goodix_ts_data, fb_notif); if (evdata && evdata->data && event == FB_EVENT_BLANK && ts && ts->client) { blank = evdata->data; if (*blank == FB_BLANK_UNBLANK) goodix_ts_resume(ts); else if (*blank == FB_BLANK_POWERDOWN) goodix_ts_suspend(ts); } return 0; } #elif defined(CONFIG_HAS_EARLYSUSPEND) /* * Function: * Early suspend function. * Input: * h: early_suspend struct. * Output: * None. */ static void goodix_ts_early_suspend(struct early_suspend *h) { struct goodix_ts_data *ts; ts = container_of(h, struct goodix_ts_data, early_suspend); goodix_ts_suspend(ts); } /* * Function: * Late resume function. * Input: * h: early_suspend struct. * Output: * None. */ static void goodix_ts_late_resume(struct early_suspend *h) { struct goodix_ts_data *ts; ts = container_of(h, struct goodix_ts_data, early_suspend); goodix_ts_late_resume(ts); } #endif #endif /* !CONFIG_HAS_EARLYSUSPEND && !CONFIG_FB*/ #if GTP_ESD_PROTECT /******************************************************* Function: switch on & off esd delayed work Input: client: i2c device on: SWITCH_ON / SWITCH_OFF Output: void *********************************************************/ /* * Function: * switch on & off esd delayed work * Input: * client: i2c device * on: SWITCH_ON / SWITCH_OFF * Output: * void */ void gtp_esd_switch(struct i2c_client *client, int on) { struct goodix_ts_data *ts; Loading Loading @@ -1749,6 +2192,11 @@ static const struct i2c_device_id goodix_ts_id[] = { { } }; static const struct of_device_id goodix_match_table[] = { { .compatible = "goodix,gt9xx", }, { }, }; static struct i2c_driver goodix_ts_driver = { .probe = goodix_ts_probe, .remove = goodix_ts_remove, Loading @@ -1760,6 +2208,7 @@ static struct i2c_driver goodix_ts_driver = { .driver = { .name = GTP_I2C_NAME, .owner = THIS_MODULE, .of_match_table = goodix_match_table, }, }; Loading
drivers/input/touchscreen/gt9xx/gt9xx.h +16 −7 Original line number Diff line number Diff line Loading @@ -33,7 +33,11 @@ #include <linux/regulator/consumer.h> #include <linux/firmware.h> #include <linux/debugfs.h> #if defined(CONFIG_HAS_EARLYSUSPEND) #if defined(CONFIG_FB) #include <linux/notifier.h> #include <linux/fb.h> #elif defined(CONFIG_HAS_EARLYSUSPEND) #include <linux/earlysuspend.h> #define GOODIX_SUSPEND_LEVEL 1 #endif Loading @@ -43,8 +47,6 @@ struct goodix_ts_platform_data { u32 irq_gpio_flags; int reset_gpio; u32 reset_gpio_flags; int ldo_en_gpio; u32 ldo_en_gpio_flags; u32 family_id; u32 x_max; u32 y_max; Loading @@ -56,6 +58,8 @@ struct goodix_ts_platform_data { u32 panel_maxy; bool no_force_update; bool i2c_pull_up; int gtp_cfg_len; u8 *config_data; }; struct goodix_ts_data { spinlock_t irq_lock; Loading @@ -65,9 +69,6 @@ struct goodix_ts_data { struct hrtimer timer; struct workqueue_struct *goodix_wq; struct work_struct work; #if defined(CONFIG_HAS_EARLYSUSPEND) struct early_suspend early_suspend; #endif s32 irq_is_disabled; s32 use_irq; u16 abs_x_max; Loading @@ -84,6 +85,14 @@ struct goodix_ts_data { u8 fixed_cfg; u8 esd_running; u8 fw_error; struct regulator *avdd; struct regulator *vdd; struct regulator *vcc_i2c; #if defined(CONFIG_FB) struct notifier_block fb_notif; #elif defined(CONFIG_HAS_EARLYSUSPEND) struct early_suspend early_suspend; #endif }; extern u16 show_len; Loading @@ -94,7 +103,7 @@ extern u16 total_len; #define GTP_CHANGE_X2Y 0 #define GTP_DRIVER_SEND_CFG 1 #define GTP_HAVE_TOUCH_KEY 1 #define GTP_POWER_CTRL_SLEEP 1 #define GTP_POWER_CTRL_SLEEP 0 #define GTP_ICS_SLOT_REPORT 0 /* auto updated by .bin file as default */ Loading