Loading Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt 0 → 100644 +53 −0 Original line number Original line Diff line number Diff line FocalTech touch controller The focaltech controller is connected to 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 "focaltech,5x06". - reg : i2c slave address of the device. - interrupt-parent : parent of interrupt. - interrupts : touch sample interrupt to indicate presense or release of fingers on the panel. - vdd-supply : Power supply needed to power up the device. - vcc_i2c-supply : Power source required to power up i2c bus. - focaltech,family-id : family identification of the controller. - focaltech,irq-gpio : irq gpio which is to provide interrupts to host, same as "interrupts" node. It will also contain active low or active high information. - focaltech,reset-gpio : reset gpio to control the reset of chip. - focaltech,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: - focaltech,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. - focaltech,i2c-pull-up : to specify pull up is required. - focaltech,no-force-update : to specify force update is allowed. - focaltech,button-map : button map of key codes. The number of key codes depend on panel. Example: i2c@f9924000 { ft5x06_ts@38 { compatible = "focaltech,5x06"; reg = <0x38>; interrupt-parent = <&msmgpio>; interrupts = <61 0x2>; vdd-supply = <&pm8941_l22>; vcc_i2c-supply = <&pm8941_s3>; focaltech,reset-gpio = <&msmgpio 60 0x00>; focaltech,irq-gpio = <&msmgpio 61 0x00>; focaltech,panel-coords = <0 0 480 800>; focaltech,display-coords = <0 0 480 800>; focaltech,button-map= <158 102 139 217>; focaltech,family-id = <0x0a>; }; }; drivers/input/touchscreen/ft5x06_ts.c +195 −10 Original line number Original line Diff line number Diff line Loading @@ -3,7 +3,7 @@ * FocalTech ft5x06 TouchScreen driver. * FocalTech ft5x06 TouchScreen driver. * * * Copyright (c) 2010 Focal tech Ltd. * Copyright (c) 2010 Focal tech Ltd. * Copyright (c) 2012, Code Aurora Forum. All rights reserved. * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. * * * This software is licensed under the terms of the GNU General Public * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * License version 2, as published by the Free Software Foundation, and Loading @@ -24,10 +24,15 @@ #include <linux/kernel.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/module.h> #include <linux/gpio.h> #include <linux/gpio.h> #include <linux/of_gpio.h> #include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h> #include <linux/input/ft5x06_ts.h> #include <linux/input/ft5x06_ts.h> #ifdef CONFIG_HAS_EARLYSUSPEND #if defined(CONFIG_FB) #include <linux/notifier.h> #include <linux/fb.h> #elif defined(CONFIG_HAS_EARLYSUSPEND) #include <linux/earlysuspend.h> #include <linux/earlysuspend.h> /* Early-suspend level */ /* Early-suspend level */ #define FT5X06_SUSPEND_LEVEL 1 #define FT5X06_SUSPEND_LEVEL 1 Loading @@ -51,6 +56,7 @@ #define POINT_READ_BUF (3 + FT_TOUCH_STEP * CFG_MAX_TOUCH_POINTS) #define POINT_READ_BUF (3 + FT_TOUCH_STEP * CFG_MAX_TOUCH_POINTS) /*register address*/ /*register address*/ #define FT5X06_REG_ID 0xA3 #define FT5X06_REG_PMODE 0xA5 #define FT5X06_REG_PMODE 0xA5 #define FT5X06_REG_FW_VER 0xA6 #define FT5X06_REG_FW_VER 0xA6 #define FT5X06_REG_POINT_RATE 0x88 #define FT5X06_REG_POINT_RATE 0x88 Loading @@ -67,6 +73,9 @@ #define FT5X06_I2C_VTG_MIN_UV 1800000 #define FT5X06_I2C_VTG_MIN_UV 1800000 #define FT5X06_I2C_VTG_MAX_UV 1800000 #define FT5X06_I2C_VTG_MAX_UV 1800000 #define FT5X06_COORDS_ARR_SIZE 4 #define MAX_BUTTONS 4 struct ts_event { struct ts_event { u16 x[CFG_MAX_TOUCH_POINTS]; /*x coordinate */ u16 x[CFG_MAX_TOUCH_POINTS]; /*x coordinate */ u16 y[CFG_MAX_TOUCH_POINTS]; /*y coordinate */ u16 y[CFG_MAX_TOUCH_POINTS]; /*y coordinate */ Loading @@ -84,7 +93,9 @@ struct ft5x06_ts_data { const struct ft5x06_ts_platform_data *pdata; const struct ft5x06_ts_platform_data *pdata; struct regulator *vdd; struct regulator *vdd; struct regulator *vcc_i2c; struct regulator *vcc_i2c; #ifdef CONFIG_HAS_EARLYSUSPEND #if defined(CONFIG_FB) struct notifier_block fb_notif; #elif defined(CONFIG_HAS_EARLYSUSPEND) struct early_suspend early_suspend; struct early_suspend early_suspend; #endif #endif }; }; Loading Loading @@ -371,7 +382,27 @@ static int ft5x06_ts_resume(struct device *dev) return 0; return 0; } } #ifdef CONFIG_HAS_EARLYSUSPEND #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 ft5x06_ts_data *ft5x06_data = container_of(self, struct ft5x06_ts_data, fb_notif); if (evdata && evdata->data && event == FB_EVENT_BLANK && ft5x06_data && ft5x06_data->client) { blank = evdata->data; if (*blank == FB_BLANK_UNBLANK) ft5x06_ts_resume(&ft5x06_data->client->dev); else if (*blank == FB_BLANK_POWERDOWN) ft5x06_ts_suspend(&ft5x06_data->client->dev); } return 0; } #elif defined(CONFIG_HAS_EARLYSUSPEND) static void ft5x06_ts_early_suspend(struct early_suspend *handler) static void ft5x06_ts_early_suspend(struct early_suspend *handler) { { struct ft5x06_ts_data *data = container_of(handler, struct ft5x06_ts_data *data = container_of(handler, Loading @@ -392,23 +423,144 @@ static void ft5x06_ts_late_resume(struct early_suspend *handler) #endif #endif static const struct dev_pm_ops ft5x06_ts_pm_ops = { static const struct dev_pm_ops ft5x06_ts_pm_ops = { #ifndef CONFIG_HAS_EARLYSUSPEND #if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND)) .suspend = ft5x06_ts_suspend, .suspend = ft5x06_ts_suspend, .resume = ft5x06_ts_resume, .resume = ft5x06_ts_resume, #endif #endif }; }; #endif #endif #ifdef CONFIG_OF static int ft5x06_get_dt_coords(struct device *dev, char *name, struct ft5x06_ts_platform_data *pdata) { u32 coords[FT5X06_COORDS_ARR_SIZE]; struct property *prop; struct device_node *np = dev->of_node; int coords_size, rc; prop = of_find_property(np, name, NULL); if (!prop) return -EINVAL; if (!prop->value) return -ENODATA; coords_size = prop->length / sizeof(u32); if (coords_size != FT5X06_COORDS_ARR_SIZE) { dev_err(dev, "invalid %s\n", name); return -EINVAL; } rc = of_property_read_u32_array(np, name, coords, coords_size); if (rc && (rc != -EINVAL)) { dev_err(dev, "Unable to read %s\n", name); return rc; } if (!strcmp(name, "focaltech,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, "focaltech,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 ft5x06_parse_dt(struct device *dev, struct ft5x06_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 = ft5x06_get_dt_coords(dev, "focaltech,panel-coords", pdata); if (rc && (rc != -EINVAL)) return rc; rc = ft5x06_get_dt_coords(dev, "focaltech,display-coords", pdata); if (rc) return rc; pdata->i2c_pull_up = of_property_read_bool(np, "focaltech,i2c-pull-up"); pdata->no_force_update = of_property_read_bool(np, "focaltech,no-force-update"); /* reset, irq gpio info */ pdata->reset_gpio = of_get_named_gpio_flags(np, "focaltech,reset-gpio", 0, &pdata->reset_gpio_flags); if (pdata->reset_gpio < 0) return pdata->reset_gpio; pdata->irq_gpio = of_get_named_gpio_flags(np, "focaltech,irq-gpio", 0, &pdata->irq_gpio_flags); if (pdata->irq_gpio < 0) return pdata->irq_gpio; rc = of_property_read_u32(np, "focaltech,family-id", &temp_val); if (!rc) pdata->family_id = temp_val; else return rc; prop = of_find_property(np, "focaltech,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, "focaltech,button-map", button_map, num_buttons); if (rc) { dev_err(dev, "Unable to read key codes\n"); return rc; } } return 0; } #else static int ft5x06_parse_dt(struct device *dev, struct ft5x06_ts_platform_data *pdata) { return -ENODEV; } #endif static int ft5x06_ts_probe(struct i2c_client *client, static int ft5x06_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) const struct i2c_device_id *id) { { const struct ft5x06_ts_platform_data *pdata = client->dev.platform_data; struct ft5x06_ts_platform_data *pdata; struct ft5x06_ts_data *data; struct ft5x06_ts_data *data; struct input_dev *input_dev; struct input_dev *input_dev; u8 reg_value; u8 reg_value; u8 reg_addr; u8 reg_addr; int err; int err; if (client->dev.of_node) { pdata = devm_kzalloc(&client->dev, sizeof(struct ft5x06_ts_platform_data), GFP_KERNEL); if (!pdata) return -ENOMEM; err = ft5x06_parse_dt(&client->dev, pdata); if (err) return err; } else pdata = client->dev.platform_data; if (!pdata) { if (!pdata) { dev_err(&client->dev, "Invalid pdata\n"); dev_err(&client->dev, "Invalid pdata\n"); return -EINVAL; return -EINVAL; Loading Loading @@ -446,9 +598,9 @@ static int ft5x06_ts_probe(struct i2c_client *client, __set_bit(BTN_TOUCH, input_dev->keybit); __set_bit(BTN_TOUCH, input_dev->keybit); __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min, pdata->x_max, 0, 0); pdata->x_max, 0, 0); input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min, pdata->y_max, 0, 0); pdata->y_max, 0, 0); input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, CFG_MAX_TOUCH_POINTS, 0, 0); CFG_MAX_TOUCH_POINTS, 0, 0); Loading Loading @@ -523,6 +675,19 @@ static int ft5x06_ts_probe(struct i2c_client *client, /* make sure CTP already finish startup process */ /* make sure CTP already finish startup process */ msleep(FT_STARTUP_DLY); msleep(FT_STARTUP_DLY); /* check the controller id */ reg_addr = FT5X06_REG_ID; err = ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1); if (err < 0) { dev_err(&client->dev, "version read failed"); return err; } if (pdata->family_id != reg_value) { dev_err(&client->dev, "%s:Unsupported controller\n", __func__); goto free_reset_gpio; } /*get some register information */ /*get some register information */ reg_addr = FT5X06_REG_FW_VER; reg_addr = FT5X06_REG_FW_VER; err = ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1); err = ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1); Loading Loading @@ -550,8 +715,15 @@ static int ft5x06_ts_probe(struct i2c_client *client, dev_err(&client->dev, "request irq failed\n"); dev_err(&client->dev, "request irq failed\n"); goto free_reset_gpio; goto free_reset_gpio; } } #if defined(CONFIG_FB) data->fb_notif.notifier_call = fb_notifier_callback; #ifdef CONFIG_HAS_EARLYSUSPEND err = fb_register_client(&data->fb_notif); if (err) dev_err(&client->dev, "Unable to register fb_notifier: %d\n", err); #elif defined(CONFIG_HAS_EARLYSUSPEND) data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + FT5X06_SUSPEND_LEVEL; FT5X06_SUSPEND_LEVEL; data->early_suspend.suspend = ft5x06_ts_early_suspend; data->early_suspend.suspend = ft5x06_ts_early_suspend; Loading Loading @@ -591,7 +763,10 @@ static int ft5x06_ts_remove(struct i2c_client *client) { { struct ft5x06_ts_data *data = i2c_get_clientdata(client); struct ft5x06_ts_data *data = i2c_get_clientdata(client); #ifdef CONFIG_HAS_EARLYSUSPEND #if defined(CONFIG_FB) if (fb_unregister_client(&data->fb_notif)) dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n"); #elif defined(CONFIG_HAS_EARLYSUSPEND) unregister_early_suspend(&data->early_suspend); unregister_early_suspend(&data->early_suspend); #endif #endif free_irq(client->irq, data); free_irq(client->irq, data); Loading Loading @@ -625,12 +800,22 @@ static const struct i2c_device_id ft5x06_ts_id[] = { MODULE_DEVICE_TABLE(i2c, ft5x06_ts_id); MODULE_DEVICE_TABLE(i2c, ft5x06_ts_id); #ifdef CONFIG_OF static struct of_device_id ft5x06_match_table[] = { { .compatible = "focaltech,5x06",}, { }, }; #else #define ft5x06_match_table NULL #endif static struct i2c_driver ft5x06_ts_driver = { static struct i2c_driver ft5x06_ts_driver = { .probe = ft5x06_ts_probe, .probe = ft5x06_ts_probe, .remove = __devexit_p(ft5x06_ts_remove), .remove = __devexit_p(ft5x06_ts_remove), .driver = { .driver = { .name = "ft5x06_ts", .name = "ft5x06_ts", .owner = THIS_MODULE, .owner = THIS_MODULE, .of_match_table = ft5x06_match_table, #ifdef CONFIG_PM #ifdef CONFIG_PM .pm = &ft5x06_ts_pm_ops, .pm = &ft5x06_ts_pm_ops, #endif #endif Loading include/linux/input/ft5x06_ts.h +20 −4 Original line number Original line Diff line number Diff line Loading @@ -3,7 +3,7 @@ * FocalTech ft5x06 TouchScreen driver header file. * FocalTech ft5x06 TouchScreen driver header file. * * * Copyright (c) 2010 Focal tech Ltd. * Copyright (c) 2010 Focal tech Ltd. * Copyright (c) 2012, Code Aurora Forum. All rights reserved. * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. * * * This software is licensed under the terms of the GNU General Public * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * License version 2, as published by the Free Software Foundation, and Loading @@ -18,12 +18,28 @@ #ifndef __LINUX_FT5X06_TS_H__ #ifndef __LINUX_FT5X06_TS_H__ #define __LINUX_FT5X06_TS_H__ #define __LINUX_FT5X06_TS_H__ #define FT5X06_ID 0x55 #define FT5X16_ID 0x0A #define FT5X36_ID 0x14 #define FT6X06_ID 0x06 struct ft5x06_ts_platform_data { struct ft5x06_ts_platform_data { unsigned long irqflags; u32 irqflags; u32 x_max; u32 y_max; u32 irq_gpio; u32 irq_gpio; u32 irq_gpio_flags; u32 reset_gpio; u32 reset_gpio; u32 reset_gpio_flags; u32 family_id; u32 x_max; u32 y_max; u32 x_min; u32 y_min; u32 panel_minx; u32 panel_miny; u32 panel_maxx; u32 panel_maxy; bool no_force_update; bool i2c_pull_up; int (*power_init)(bool); int (*power_init)(bool); int (*power_on)(bool); int (*power_on)(bool); }; }; Loading Loading
Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt 0 → 100644 +53 −0 Original line number Original line Diff line number Diff line FocalTech touch controller The focaltech controller is connected to 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 "focaltech,5x06". - reg : i2c slave address of the device. - interrupt-parent : parent of interrupt. - interrupts : touch sample interrupt to indicate presense or release of fingers on the panel. - vdd-supply : Power supply needed to power up the device. - vcc_i2c-supply : Power source required to power up i2c bus. - focaltech,family-id : family identification of the controller. - focaltech,irq-gpio : irq gpio which is to provide interrupts to host, same as "interrupts" node. It will also contain active low or active high information. - focaltech,reset-gpio : reset gpio to control the reset of chip. - focaltech,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: - focaltech,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. - focaltech,i2c-pull-up : to specify pull up is required. - focaltech,no-force-update : to specify force update is allowed. - focaltech,button-map : button map of key codes. The number of key codes depend on panel. Example: i2c@f9924000 { ft5x06_ts@38 { compatible = "focaltech,5x06"; reg = <0x38>; interrupt-parent = <&msmgpio>; interrupts = <61 0x2>; vdd-supply = <&pm8941_l22>; vcc_i2c-supply = <&pm8941_s3>; focaltech,reset-gpio = <&msmgpio 60 0x00>; focaltech,irq-gpio = <&msmgpio 61 0x00>; focaltech,panel-coords = <0 0 480 800>; focaltech,display-coords = <0 0 480 800>; focaltech,button-map= <158 102 139 217>; focaltech,family-id = <0x0a>; }; };
drivers/input/touchscreen/ft5x06_ts.c +195 −10 Original line number Original line Diff line number Diff line Loading @@ -3,7 +3,7 @@ * FocalTech ft5x06 TouchScreen driver. * FocalTech ft5x06 TouchScreen driver. * * * Copyright (c) 2010 Focal tech Ltd. * Copyright (c) 2010 Focal tech Ltd. * Copyright (c) 2012, Code Aurora Forum. All rights reserved. * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. * * * This software is licensed under the terms of the GNU General Public * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * License version 2, as published by the Free Software Foundation, and Loading @@ -24,10 +24,15 @@ #include <linux/kernel.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/module.h> #include <linux/gpio.h> #include <linux/gpio.h> #include <linux/of_gpio.h> #include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h> #include <linux/input/ft5x06_ts.h> #include <linux/input/ft5x06_ts.h> #ifdef CONFIG_HAS_EARLYSUSPEND #if defined(CONFIG_FB) #include <linux/notifier.h> #include <linux/fb.h> #elif defined(CONFIG_HAS_EARLYSUSPEND) #include <linux/earlysuspend.h> #include <linux/earlysuspend.h> /* Early-suspend level */ /* Early-suspend level */ #define FT5X06_SUSPEND_LEVEL 1 #define FT5X06_SUSPEND_LEVEL 1 Loading @@ -51,6 +56,7 @@ #define POINT_READ_BUF (3 + FT_TOUCH_STEP * CFG_MAX_TOUCH_POINTS) #define POINT_READ_BUF (3 + FT_TOUCH_STEP * CFG_MAX_TOUCH_POINTS) /*register address*/ /*register address*/ #define FT5X06_REG_ID 0xA3 #define FT5X06_REG_PMODE 0xA5 #define FT5X06_REG_PMODE 0xA5 #define FT5X06_REG_FW_VER 0xA6 #define FT5X06_REG_FW_VER 0xA6 #define FT5X06_REG_POINT_RATE 0x88 #define FT5X06_REG_POINT_RATE 0x88 Loading @@ -67,6 +73,9 @@ #define FT5X06_I2C_VTG_MIN_UV 1800000 #define FT5X06_I2C_VTG_MIN_UV 1800000 #define FT5X06_I2C_VTG_MAX_UV 1800000 #define FT5X06_I2C_VTG_MAX_UV 1800000 #define FT5X06_COORDS_ARR_SIZE 4 #define MAX_BUTTONS 4 struct ts_event { struct ts_event { u16 x[CFG_MAX_TOUCH_POINTS]; /*x coordinate */ u16 x[CFG_MAX_TOUCH_POINTS]; /*x coordinate */ u16 y[CFG_MAX_TOUCH_POINTS]; /*y coordinate */ u16 y[CFG_MAX_TOUCH_POINTS]; /*y coordinate */ Loading @@ -84,7 +93,9 @@ struct ft5x06_ts_data { const struct ft5x06_ts_platform_data *pdata; const struct ft5x06_ts_platform_data *pdata; struct regulator *vdd; struct regulator *vdd; struct regulator *vcc_i2c; struct regulator *vcc_i2c; #ifdef CONFIG_HAS_EARLYSUSPEND #if defined(CONFIG_FB) struct notifier_block fb_notif; #elif defined(CONFIG_HAS_EARLYSUSPEND) struct early_suspend early_suspend; struct early_suspend early_suspend; #endif #endif }; }; Loading Loading @@ -371,7 +382,27 @@ static int ft5x06_ts_resume(struct device *dev) return 0; return 0; } } #ifdef CONFIG_HAS_EARLYSUSPEND #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 ft5x06_ts_data *ft5x06_data = container_of(self, struct ft5x06_ts_data, fb_notif); if (evdata && evdata->data && event == FB_EVENT_BLANK && ft5x06_data && ft5x06_data->client) { blank = evdata->data; if (*blank == FB_BLANK_UNBLANK) ft5x06_ts_resume(&ft5x06_data->client->dev); else if (*blank == FB_BLANK_POWERDOWN) ft5x06_ts_suspend(&ft5x06_data->client->dev); } return 0; } #elif defined(CONFIG_HAS_EARLYSUSPEND) static void ft5x06_ts_early_suspend(struct early_suspend *handler) static void ft5x06_ts_early_suspend(struct early_suspend *handler) { { struct ft5x06_ts_data *data = container_of(handler, struct ft5x06_ts_data *data = container_of(handler, Loading @@ -392,23 +423,144 @@ static void ft5x06_ts_late_resume(struct early_suspend *handler) #endif #endif static const struct dev_pm_ops ft5x06_ts_pm_ops = { static const struct dev_pm_ops ft5x06_ts_pm_ops = { #ifndef CONFIG_HAS_EARLYSUSPEND #if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND)) .suspend = ft5x06_ts_suspend, .suspend = ft5x06_ts_suspend, .resume = ft5x06_ts_resume, .resume = ft5x06_ts_resume, #endif #endif }; }; #endif #endif #ifdef CONFIG_OF static int ft5x06_get_dt_coords(struct device *dev, char *name, struct ft5x06_ts_platform_data *pdata) { u32 coords[FT5X06_COORDS_ARR_SIZE]; struct property *prop; struct device_node *np = dev->of_node; int coords_size, rc; prop = of_find_property(np, name, NULL); if (!prop) return -EINVAL; if (!prop->value) return -ENODATA; coords_size = prop->length / sizeof(u32); if (coords_size != FT5X06_COORDS_ARR_SIZE) { dev_err(dev, "invalid %s\n", name); return -EINVAL; } rc = of_property_read_u32_array(np, name, coords, coords_size); if (rc && (rc != -EINVAL)) { dev_err(dev, "Unable to read %s\n", name); return rc; } if (!strcmp(name, "focaltech,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, "focaltech,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 ft5x06_parse_dt(struct device *dev, struct ft5x06_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 = ft5x06_get_dt_coords(dev, "focaltech,panel-coords", pdata); if (rc && (rc != -EINVAL)) return rc; rc = ft5x06_get_dt_coords(dev, "focaltech,display-coords", pdata); if (rc) return rc; pdata->i2c_pull_up = of_property_read_bool(np, "focaltech,i2c-pull-up"); pdata->no_force_update = of_property_read_bool(np, "focaltech,no-force-update"); /* reset, irq gpio info */ pdata->reset_gpio = of_get_named_gpio_flags(np, "focaltech,reset-gpio", 0, &pdata->reset_gpio_flags); if (pdata->reset_gpio < 0) return pdata->reset_gpio; pdata->irq_gpio = of_get_named_gpio_flags(np, "focaltech,irq-gpio", 0, &pdata->irq_gpio_flags); if (pdata->irq_gpio < 0) return pdata->irq_gpio; rc = of_property_read_u32(np, "focaltech,family-id", &temp_val); if (!rc) pdata->family_id = temp_val; else return rc; prop = of_find_property(np, "focaltech,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, "focaltech,button-map", button_map, num_buttons); if (rc) { dev_err(dev, "Unable to read key codes\n"); return rc; } } return 0; } #else static int ft5x06_parse_dt(struct device *dev, struct ft5x06_ts_platform_data *pdata) { return -ENODEV; } #endif static int ft5x06_ts_probe(struct i2c_client *client, static int ft5x06_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) const struct i2c_device_id *id) { { const struct ft5x06_ts_platform_data *pdata = client->dev.platform_data; struct ft5x06_ts_platform_data *pdata; struct ft5x06_ts_data *data; struct ft5x06_ts_data *data; struct input_dev *input_dev; struct input_dev *input_dev; u8 reg_value; u8 reg_value; u8 reg_addr; u8 reg_addr; int err; int err; if (client->dev.of_node) { pdata = devm_kzalloc(&client->dev, sizeof(struct ft5x06_ts_platform_data), GFP_KERNEL); if (!pdata) return -ENOMEM; err = ft5x06_parse_dt(&client->dev, pdata); if (err) return err; } else pdata = client->dev.platform_data; if (!pdata) { if (!pdata) { dev_err(&client->dev, "Invalid pdata\n"); dev_err(&client->dev, "Invalid pdata\n"); return -EINVAL; return -EINVAL; Loading Loading @@ -446,9 +598,9 @@ static int ft5x06_ts_probe(struct i2c_client *client, __set_bit(BTN_TOUCH, input_dev->keybit); __set_bit(BTN_TOUCH, input_dev->keybit); __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min, pdata->x_max, 0, 0); pdata->x_max, 0, 0); input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min, pdata->y_max, 0, 0); pdata->y_max, 0, 0); input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, CFG_MAX_TOUCH_POINTS, 0, 0); CFG_MAX_TOUCH_POINTS, 0, 0); Loading Loading @@ -523,6 +675,19 @@ static int ft5x06_ts_probe(struct i2c_client *client, /* make sure CTP already finish startup process */ /* make sure CTP already finish startup process */ msleep(FT_STARTUP_DLY); msleep(FT_STARTUP_DLY); /* check the controller id */ reg_addr = FT5X06_REG_ID; err = ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1); if (err < 0) { dev_err(&client->dev, "version read failed"); return err; } if (pdata->family_id != reg_value) { dev_err(&client->dev, "%s:Unsupported controller\n", __func__); goto free_reset_gpio; } /*get some register information */ /*get some register information */ reg_addr = FT5X06_REG_FW_VER; reg_addr = FT5X06_REG_FW_VER; err = ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1); err = ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1); Loading Loading @@ -550,8 +715,15 @@ static int ft5x06_ts_probe(struct i2c_client *client, dev_err(&client->dev, "request irq failed\n"); dev_err(&client->dev, "request irq failed\n"); goto free_reset_gpio; goto free_reset_gpio; } } #if defined(CONFIG_FB) data->fb_notif.notifier_call = fb_notifier_callback; #ifdef CONFIG_HAS_EARLYSUSPEND err = fb_register_client(&data->fb_notif); if (err) dev_err(&client->dev, "Unable to register fb_notifier: %d\n", err); #elif defined(CONFIG_HAS_EARLYSUSPEND) data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + FT5X06_SUSPEND_LEVEL; FT5X06_SUSPEND_LEVEL; data->early_suspend.suspend = ft5x06_ts_early_suspend; data->early_suspend.suspend = ft5x06_ts_early_suspend; Loading Loading @@ -591,7 +763,10 @@ static int ft5x06_ts_remove(struct i2c_client *client) { { struct ft5x06_ts_data *data = i2c_get_clientdata(client); struct ft5x06_ts_data *data = i2c_get_clientdata(client); #ifdef CONFIG_HAS_EARLYSUSPEND #if defined(CONFIG_FB) if (fb_unregister_client(&data->fb_notif)) dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n"); #elif defined(CONFIG_HAS_EARLYSUSPEND) unregister_early_suspend(&data->early_suspend); unregister_early_suspend(&data->early_suspend); #endif #endif free_irq(client->irq, data); free_irq(client->irq, data); Loading Loading @@ -625,12 +800,22 @@ static const struct i2c_device_id ft5x06_ts_id[] = { MODULE_DEVICE_TABLE(i2c, ft5x06_ts_id); MODULE_DEVICE_TABLE(i2c, ft5x06_ts_id); #ifdef CONFIG_OF static struct of_device_id ft5x06_match_table[] = { { .compatible = "focaltech,5x06",}, { }, }; #else #define ft5x06_match_table NULL #endif static struct i2c_driver ft5x06_ts_driver = { static struct i2c_driver ft5x06_ts_driver = { .probe = ft5x06_ts_probe, .probe = ft5x06_ts_probe, .remove = __devexit_p(ft5x06_ts_remove), .remove = __devexit_p(ft5x06_ts_remove), .driver = { .driver = { .name = "ft5x06_ts", .name = "ft5x06_ts", .owner = THIS_MODULE, .owner = THIS_MODULE, .of_match_table = ft5x06_match_table, #ifdef CONFIG_PM #ifdef CONFIG_PM .pm = &ft5x06_ts_pm_ops, .pm = &ft5x06_ts_pm_ops, #endif #endif Loading
include/linux/input/ft5x06_ts.h +20 −4 Original line number Original line Diff line number Diff line Loading @@ -3,7 +3,7 @@ * FocalTech ft5x06 TouchScreen driver header file. * FocalTech ft5x06 TouchScreen driver header file. * * * Copyright (c) 2010 Focal tech Ltd. * Copyright (c) 2010 Focal tech Ltd. * Copyright (c) 2012, Code Aurora Forum. All rights reserved. * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. * * * This software is licensed under the terms of the GNU General Public * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * License version 2, as published by the Free Software Foundation, and Loading @@ -18,12 +18,28 @@ #ifndef __LINUX_FT5X06_TS_H__ #ifndef __LINUX_FT5X06_TS_H__ #define __LINUX_FT5X06_TS_H__ #define __LINUX_FT5X06_TS_H__ #define FT5X06_ID 0x55 #define FT5X16_ID 0x0A #define FT5X36_ID 0x14 #define FT6X06_ID 0x06 struct ft5x06_ts_platform_data { struct ft5x06_ts_platform_data { unsigned long irqflags; u32 irqflags; u32 x_max; u32 y_max; u32 irq_gpio; u32 irq_gpio; u32 irq_gpio_flags; u32 reset_gpio; u32 reset_gpio; u32 reset_gpio_flags; u32 family_id; u32 x_max; u32 y_max; u32 x_min; u32 y_min; u32 panel_minx; u32 panel_miny; u32 panel_maxx; u32 panel_maxy; bool no_force_update; bool i2c_pull_up; int (*power_init)(bool); int (*power_init)(bool); int (*power_on)(bool); int (*power_on)(bool); }; }; Loading