diff options
Diffstat (limited to 'drivers/input/touchscreen')
-rw-r--r-- | drivers/input/touchscreen/Kconfig | 42 | ||||
-rw-r--r-- | drivers/input/touchscreen/Makefile | 3 | ||||
-rw-r--r-- | drivers/input/touchscreen/ar1021_i2c.c | 2 | ||||
-rw-r--r-- | drivers/input/touchscreen/atmel_mxt_ts.c | 391 | ||||
-rw-r--r-- | drivers/input/touchscreen/bcm_iproc_tsc.c | 522 | ||||
-rw-r--r-- | drivers/input/touchscreen/chipone_icn8318.c | 316 | ||||
-rw-r--r-- | drivers/input/touchscreen/edt-ft5x06.c | 6 | ||||
-rw-r--r-- | drivers/input/touchscreen/elants_i2c.c | 14 | ||||
-rw-r--r-- | drivers/input/touchscreen/goodix.c | 36 | ||||
-rw-r--r-- | drivers/input/touchscreen/of_touchscreen.c | 62 | ||||
-rw-r--r-- | drivers/input/touchscreen/sun4i-ts.c | 46 | ||||
-rw-r--r-- | drivers/input/touchscreen/sx8654.c | 286 | ||||
-rw-r--r-- | drivers/input/touchscreen/tsc2007.c | 11 | ||||
-rw-r--r-- | drivers/input/touchscreen/usbtouchscreen.c | 11 |
14 files changed, 1659 insertions, 89 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index f8d16f15c1d1..80f6386709bf 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -140,6 +140,19 @@ config TOUCHSCREEN_BU21013 | |||
140 | To compile this driver as a module, choose M here: the | 140 | To compile this driver as a module, choose M here: the |
141 | module will be called bu21013_ts. | 141 | module will be called bu21013_ts. |
142 | 142 | ||
143 | config TOUCHSCREEN_CHIPONE_ICN8318 | ||
144 | tristate "chipone icn8318 touchscreen controller" | ||
145 | depends on GPIOLIB | ||
146 | depends on I2C | ||
147 | depends on OF | ||
148 | help | ||
149 | Say Y here if you have a ChipOne icn8318 based I2C touchscreen. | ||
150 | |||
151 | If unsure, say N. | ||
152 | |||
153 | To compile this driver as a module, choose M here: the | ||
154 | module will be called chipone_icn8318. | ||
155 | |||
143 | config TOUCHSCREEN_CY8CTMG110 | 156 | config TOUCHSCREEN_CY8CTMG110 |
144 | tristate "cy8ctmg110 touchscreen" | 157 | tristate "cy8ctmg110 touchscreen" |
145 | depends on I2C | 158 | depends on I2C |
@@ -297,11 +310,12 @@ config TOUCHSCREEN_FUJITSU | |||
297 | 310 | ||
298 | config TOUCHSCREEN_GOODIX | 311 | config TOUCHSCREEN_GOODIX |
299 | tristate "Goodix I2C touchscreen" | 312 | tristate "Goodix I2C touchscreen" |
300 | depends on I2C && ACPI | 313 | depends on I2C |
301 | help | 314 | help |
302 | Say Y here if you have the Goodix touchscreen (such as one | 315 | Say Y here if you have the Goodix touchscreen (such as one |
303 | installed in Onda v975w tablets) connected to your | 316 | installed in Onda v975w tablets) connected to your |
304 | system. | 317 | system. It also supports 5-finger chip models, which can be |
318 | found on ARM tablets, like Wexler TAB7200 and MSI Primo73. | ||
305 | 319 | ||
306 | If unsure, say N. | 320 | If unsure, say N. |
307 | 321 | ||
@@ -323,6 +337,18 @@ config TOUCHSCREEN_ILI210X | |||
323 | To compile this driver as a module, choose M here: the | 337 | To compile this driver as a module, choose M here: the |
324 | module will be called ili210x. | 338 | module will be called ili210x. |
325 | 339 | ||
340 | config TOUCHSCREEN_IPROC | ||
341 | tristate "IPROC touch panel driver support" | ||
342 | depends on ARCH_BCM_IPROC || COMPILE_TEST | ||
343 | help | ||
344 | Say Y here if you want to add support for the IPROC touch | ||
345 | controller to your system. | ||
346 | |||
347 | If unsure, say N. | ||
348 | |||
349 | To compile this driver as a module, choose M here: the | ||
350 | module will be called bcm_iproc_tsc. | ||
351 | |||
326 | config TOUCHSCREEN_S3C2410 | 352 | config TOUCHSCREEN_S3C2410 |
327 | tristate "Samsung S3C2410/generic touchscreen input driver" | 353 | tristate "Samsung S3C2410/generic touchscreen input driver" |
328 | depends on ARCH_S3C24XX || SAMSUNG_DEV_TS | 354 | depends on ARCH_S3C24XX || SAMSUNG_DEV_TS |
@@ -943,6 +969,7 @@ config TOUCHSCREEN_SUN4I | |||
943 | tristate "Allwinner sun4i resistive touchscreen controller support" | 969 | tristate "Allwinner sun4i resistive touchscreen controller support" |
944 | depends on ARCH_SUNXI || COMPILE_TEST | 970 | depends on ARCH_SUNXI || COMPILE_TEST |
945 | depends on HWMON | 971 | depends on HWMON |
972 | depends on THERMAL || !THERMAL_OF | ||
946 | help | 973 | help |
947 | This selects support for the resistive touchscreen controller | 974 | This selects support for the resistive touchscreen controller |
948 | found on Allwinner sunxi SoCs. | 975 | found on Allwinner sunxi SoCs. |
@@ -963,6 +990,17 @@ config TOUCHSCREEN_SUR40 | |||
963 | To compile this driver as a module, choose M here: the | 990 | To compile this driver as a module, choose M here: the |
964 | module will be called sur40. | 991 | module will be called sur40. |
965 | 992 | ||
993 | config TOUCHSCREEN_SX8654 | ||
994 | tristate "Semtech SX8654 touchscreen" | ||
995 | depends on I2C | ||
996 | help | ||
997 | Say Y here if you have a Semtech SX8654 touchscreen controller. | ||
998 | |||
999 | If unsure, say N | ||
1000 | |||
1001 | To compile this driver as a module, choose M here: the | ||
1002 | module will be called sx8654. | ||
1003 | |||
966 | config TOUCHSCREEN_TPS6507X | 1004 | config TOUCHSCREEN_TPS6507X |
967 | tristate "TPS6507x based touchscreens" | 1005 | tristate "TPS6507x based touchscreens" |
968 | depends on I2C | 1006 | depends on I2C |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 0242fea2102a..44deea743d02 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -17,6 +17,7 @@ obj-$(CONFIG_TOUCHSCREEN_AR1021_I2C) += ar1021_i2c.o | |||
17 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o | 17 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o |
18 | obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o | 18 | obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o |
19 | obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o | 19 | obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o |
20 | obj-$(CONFIG_TOUCHSCREEN_CHIPONE_ICN8318) += chipone_icn8318.o | ||
20 | obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o | 21 | obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o |
21 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o | 22 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o |
22 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o cyttsp_i2c_common.o | 23 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o cyttsp_i2c_common.o |
@@ -39,6 +40,7 @@ obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o | |||
39 | obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o | 40 | obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o |
40 | obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o | 41 | obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o |
41 | obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o | 42 | obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o |
43 | obj-$(CONFIG_TOUCHSCREEN_IPROC) += bcm_iproc_tsc.o | ||
42 | obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o | 44 | obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o |
43 | obj-$(CONFIG_TOUCHSCREEN_MAX11801) += max11801_ts.o | 45 | obj-$(CONFIG_TOUCHSCREEN_MAX11801) += max11801_ts.o |
44 | obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o | 46 | obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o |
@@ -79,5 +81,6 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) += atmel-wm97xx.o | |||
79 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o | 81 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o |
80 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o | 82 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o |
81 | obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o | 83 | obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o |
84 | obj-$(CONFIG_TOUCHSCREEN_SX8654) += sx8654.o | ||
82 | obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o | 85 | obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o |
83 | obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o | 86 | obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o |
diff --git a/drivers/input/touchscreen/ar1021_i2c.c b/drivers/input/touchscreen/ar1021_i2c.c index ba30578e296e..f0b954d46a25 100644 --- a/drivers/input/touchscreen/ar1021_i2c.c +++ b/drivers/input/touchscreen/ar1021_i2c.c | |||
@@ -157,7 +157,7 @@ static const struct i2c_device_id ar1021_i2c_id[] = { | |||
157 | }; | 157 | }; |
158 | MODULE_DEVICE_TABLE(i2c, ar1021_i2c_id); | 158 | MODULE_DEVICE_TABLE(i2c, ar1021_i2c_id); |
159 | 159 | ||
160 | static struct of_device_id ar1021_i2c_of_match[] = { | 160 | static const struct of_device_id ar1021_i2c_of_match[] = { |
161 | { .compatible = "microchip,ar1021-i2c", }, | 161 | { .compatible = "microchip,ar1021-i2c", }, |
162 | { } | 162 | { } |
163 | }; | 163 | }; |
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 95ee92a91bd2..2875ddf37289 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/of.h> | 26 | #include <linux/of.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <asm/unaligned.h> | ||
28 | 29 | ||
29 | /* Version */ | 30 | /* Version */ |
30 | #define MXT_VER_20 20 | 31 | #define MXT_VER_20 20 |
@@ -79,6 +80,7 @@ | |||
79 | #define MXT_SPT_DIGITIZER_T43 43 | 80 | #define MXT_SPT_DIGITIZER_T43 43 |
80 | #define MXT_SPT_MESSAGECOUNT_T44 44 | 81 | #define MXT_SPT_MESSAGECOUNT_T44 44 |
81 | #define MXT_SPT_CTECONFIG_T46 46 | 82 | #define MXT_SPT_CTECONFIG_T46 46 |
83 | #define MXT_TOUCH_MULTITOUCHSCREEN_T100 100 | ||
82 | 84 | ||
83 | /* MXT_GEN_MESSAGE_T5 object */ | 85 | /* MXT_GEN_MESSAGE_T5 object */ |
84 | #define MXT_RPTID_NOMSG 0xff | 86 | #define MXT_RPTID_NOMSG 0xff |
@@ -185,6 +187,36 @@ struct t9_range { | |||
185 | #define MXT_RESET_VALUE 0x01 | 187 | #define MXT_RESET_VALUE 0x01 |
186 | #define MXT_BACKUP_VALUE 0x55 | 188 | #define MXT_BACKUP_VALUE 0x55 |
187 | 189 | ||
190 | /* T100 Multiple Touch Touchscreen */ | ||
191 | #define MXT_T100_CTRL 0 | ||
192 | #define MXT_T100_CFG1 1 | ||
193 | #define MXT_T100_TCHAUX 3 | ||
194 | #define MXT_T100_XRANGE 13 | ||
195 | #define MXT_T100_YRANGE 24 | ||
196 | |||
197 | #define MXT_T100_CFG_SWITCHXY BIT(5) | ||
198 | |||
199 | #define MXT_T100_TCHAUX_VECT BIT(0) | ||
200 | #define MXT_T100_TCHAUX_AMPL BIT(1) | ||
201 | #define MXT_T100_TCHAUX_AREA BIT(2) | ||
202 | |||
203 | #define MXT_T100_DETECT BIT(7) | ||
204 | #define MXT_T100_TYPE_MASK 0x70 | ||
205 | |||
206 | enum t100_type { | ||
207 | MXT_T100_TYPE_FINGER = 1, | ||
208 | MXT_T100_TYPE_PASSIVE_STYLUS = 2, | ||
209 | MXT_T100_TYPE_HOVERING_FINGER = 4, | ||
210 | MXT_T100_TYPE_GLOVE = 5, | ||
211 | MXT_T100_TYPE_LARGE_TOUCH = 6, | ||
212 | }; | ||
213 | |||
214 | #define MXT_DISTANCE_ACTIVE_TOUCH 0 | ||
215 | #define MXT_DISTANCE_HOVERING 1 | ||
216 | |||
217 | #define MXT_TOUCH_MAJOR_DEFAULT 1 | ||
218 | #define MXT_PRESSURE_DEFAULT 1 | ||
219 | |||
188 | /* Delay times */ | 220 | /* Delay times */ |
189 | #define MXT_BACKUP_TIME 50 /* msec */ | 221 | #define MXT_BACKUP_TIME 50 /* msec */ |
190 | #define MXT_RESET_TIME 200 /* msec */ | 222 | #define MXT_RESET_TIME 200 /* msec */ |
@@ -244,6 +276,9 @@ struct mxt_data { | |||
244 | unsigned int max_y; | 276 | unsigned int max_y; |
245 | bool in_bootloader; | 277 | bool in_bootloader; |
246 | u16 mem_size; | 278 | u16 mem_size; |
279 | u8 t100_aux_ampl; | ||
280 | u8 t100_aux_area; | ||
281 | u8 t100_aux_vect; | ||
247 | u8 max_reportid; | 282 | u8 max_reportid; |
248 | u32 config_crc; | 283 | u32 config_crc; |
249 | u32 info_crc; | 284 | u32 info_crc; |
@@ -253,6 +288,7 @@ struct mxt_data { | |||
253 | bool update_input; | 288 | bool update_input; |
254 | u8 last_message_count; | 289 | u8 last_message_count; |
255 | u8 num_touchids; | 290 | u8 num_touchids; |
291 | u8 multitouch; | ||
256 | 292 | ||
257 | /* Cached parameters from object table */ | 293 | /* Cached parameters from object table */ |
258 | u16 T5_address; | 294 | u16 T5_address; |
@@ -264,6 +300,8 @@ struct mxt_data { | |||
264 | u8 T9_reportid_max; | 300 | u8 T9_reportid_max; |
265 | u8 T19_reportid; | 301 | u8 T19_reportid; |
266 | u16 T44_address; | 302 | u16 T44_address; |
303 | u8 T100_reportid_min; | ||
304 | u8 T100_reportid_max; | ||
267 | 305 | ||
268 | /* for fw update in bootloader */ | 306 | /* for fw update in bootloader */ |
269 | struct completion bl_completion; | 307 | struct completion bl_completion; |
@@ -771,6 +809,114 @@ static void mxt_proc_t9_message(struct mxt_data *data, u8 *message) | |||
771 | data->update_input = true; | 809 | data->update_input = true; |
772 | } | 810 | } |
773 | 811 | ||
812 | static void mxt_proc_t100_message(struct mxt_data *data, u8 *message) | ||
813 | { | ||
814 | struct device *dev = &data->client->dev; | ||
815 | struct input_dev *input_dev = data->input_dev; | ||
816 | int id; | ||
817 | u8 status; | ||
818 | u8 type = 0; | ||
819 | u16 x; | ||
820 | u16 y; | ||
821 | int distance = 0; | ||
822 | int tool = 0; | ||
823 | u8 major = 0; | ||
824 | u8 pressure = 0; | ||
825 | u8 orientation = 0; | ||
826 | |||
827 | id = message[0] - data->T100_reportid_min - 2; | ||
828 | |||
829 | /* ignore SCRSTATUS events */ | ||
830 | if (id < 0) | ||
831 | return; | ||
832 | |||
833 | status = message[1]; | ||
834 | x = get_unaligned_le16(&message[2]); | ||
835 | y = get_unaligned_le16(&message[4]); | ||
836 | |||
837 | if (status & MXT_T100_DETECT) { | ||
838 | type = (status & MXT_T100_TYPE_MASK) >> 4; | ||
839 | |||
840 | switch (type) { | ||
841 | case MXT_T100_TYPE_HOVERING_FINGER: | ||
842 | tool = MT_TOOL_FINGER; | ||
843 | distance = MXT_DISTANCE_HOVERING; | ||
844 | |||
845 | if (data->t100_aux_vect) | ||
846 | orientation = message[data->t100_aux_vect]; | ||
847 | |||
848 | break; | ||
849 | |||
850 | case MXT_T100_TYPE_FINGER: | ||
851 | case MXT_T100_TYPE_GLOVE: | ||
852 | tool = MT_TOOL_FINGER; | ||
853 | distance = MXT_DISTANCE_ACTIVE_TOUCH; | ||
854 | |||
855 | if (data->t100_aux_area) | ||
856 | major = message[data->t100_aux_area]; | ||
857 | |||
858 | if (data->t100_aux_ampl) | ||
859 | pressure = message[data->t100_aux_ampl]; | ||
860 | |||
861 | if (data->t100_aux_vect) | ||
862 | orientation = message[data->t100_aux_vect]; | ||
863 | |||
864 | break; | ||
865 | |||
866 | case MXT_T100_TYPE_PASSIVE_STYLUS: | ||
867 | tool = MT_TOOL_PEN; | ||
868 | |||
869 | /* | ||
870 | * Passive stylus is reported with size zero so | ||
871 | * hardcode. | ||
872 | */ | ||
873 | major = MXT_TOUCH_MAJOR_DEFAULT; | ||
874 | |||
875 | if (data->t100_aux_ampl) | ||
876 | pressure = message[data->t100_aux_ampl]; | ||
877 | |||
878 | break; | ||
879 | |||
880 | case MXT_T100_TYPE_LARGE_TOUCH: | ||
881 | /* Ignore suppressed touch */ | ||
882 | break; | ||
883 | |||
884 | default: | ||
885 | dev_dbg(dev, "Unexpected T100 type\n"); | ||
886 | return; | ||
887 | } | ||
888 | } | ||
889 | |||
890 | /* | ||
891 | * Values reported should be non-zero if tool is touching the | ||
892 | * device | ||
893 | */ | ||
894 | if (!pressure && type != MXT_T100_TYPE_HOVERING_FINGER) | ||
895 | pressure = MXT_PRESSURE_DEFAULT; | ||
896 | |||
897 | input_mt_slot(input_dev, id); | ||
898 | |||
899 | if (status & MXT_T100_DETECT) { | ||
900 | dev_dbg(dev, "[%u] type:%u x:%u y:%u a:%02X p:%02X v:%02X\n", | ||
901 | id, type, x, y, major, pressure, orientation); | ||
902 | |||
903 | input_mt_report_slot_state(input_dev, tool, 1); | ||
904 | input_report_abs(input_dev, ABS_MT_POSITION_X, x); | ||
905 | input_report_abs(input_dev, ABS_MT_POSITION_Y, y); | ||
906 | input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, major); | ||
907 | input_report_abs(input_dev, ABS_MT_PRESSURE, pressure); | ||
908 | input_report_abs(input_dev, ABS_MT_DISTANCE, distance); | ||
909 | input_report_abs(input_dev, ABS_MT_ORIENTATION, orientation); | ||
910 | } else { | ||
911 | dev_dbg(dev, "[%u] release\n", id); | ||
912 | |||
913 | /* close out slot */ | ||
914 | input_mt_report_slot_state(input_dev, 0, 0); | ||
915 | } | ||
916 | |||
917 | data->update_input = true; | ||
918 | } | ||
919 | |||
774 | static int mxt_proc_message(struct mxt_data *data, u8 *message) | 920 | static int mxt_proc_message(struct mxt_data *data, u8 *message) |
775 | { | 921 | { |
776 | u8 report_id = message[0]; | 922 | u8 report_id = message[0]; |
@@ -786,9 +932,12 @@ static int mxt_proc_message(struct mxt_data *data, u8 *message) | |||
786 | * is not yet registered. | 932 | * is not yet registered. |
787 | */ | 933 | */ |
788 | mxt_dump_message(data, message); | 934 | mxt_dump_message(data, message); |
789 | } else if (report_id >= data->T9_reportid_min | 935 | } else if (report_id >= data->T9_reportid_min && |
790 | && report_id <= data->T9_reportid_max) { | 936 | report_id <= data->T9_reportid_max) { |
791 | mxt_proc_t9_message(data, message); | 937 | mxt_proc_t9_message(data, message); |
938 | } else if (report_id >= data->T100_reportid_min && | ||
939 | report_id <= data->T100_reportid_max) { | ||
940 | mxt_proc_t100_message(data, message); | ||
792 | } else if (report_id == data->T19_reportid) { | 941 | } else if (report_id == data->T19_reportid) { |
793 | mxt_input_button(data, message); | 942 | mxt_input_button(data, message); |
794 | data->update_input = true; | 943 | data->update_input = true; |
@@ -1411,6 +1560,8 @@ static void mxt_free_object_table(struct mxt_data *data) | |||
1411 | data->T9_reportid_max = 0; | 1560 | data->T9_reportid_max = 0; |
1412 | data->T19_reportid = 0; | 1561 | data->T19_reportid = 0; |
1413 | data->T44_address = 0; | 1562 | data->T44_address = 0; |
1563 | data->T100_reportid_min = 0; | ||
1564 | data->T100_reportid_max = 0; | ||
1414 | data->max_reportid = 0; | 1565 | data->max_reportid = 0; |
1415 | } | 1566 | } |
1416 | 1567 | ||
@@ -1487,6 +1638,7 @@ static int mxt_get_object_table(struct mxt_data *data) | |||
1487 | data->T7_address = object->start_address; | 1638 | data->T7_address = object->start_address; |
1488 | break; | 1639 | break; |
1489 | case MXT_TOUCH_MULTI_T9: | 1640 | case MXT_TOUCH_MULTI_T9: |
1641 | data->multitouch = MXT_TOUCH_MULTI_T9; | ||
1490 | data->T9_reportid_min = min_id; | 1642 | data->T9_reportid_min = min_id; |
1491 | data->T9_reportid_max = max_id; | 1643 | data->T9_reportid_max = max_id; |
1492 | data->num_touchids = object->num_report_ids | 1644 | data->num_touchids = object->num_report_ids |
@@ -1498,6 +1650,13 @@ static int mxt_get_object_table(struct mxt_data *data) | |||
1498 | case MXT_SPT_GPIOPWM_T19: | 1650 | case MXT_SPT_GPIOPWM_T19: |
1499 | data->T19_reportid = min_id; | 1651 | data->T19_reportid = min_id; |
1500 | break; | 1652 | break; |
1653 | case MXT_TOUCH_MULTITOUCHSCREEN_T100: | ||
1654 | data->multitouch = MXT_TOUCH_MULTITOUCHSCREEN_T100; | ||
1655 | data->T100_reportid_min = min_id; | ||
1656 | data->T100_reportid_max = max_id; | ||
1657 | /* first two report IDs reserved */ | ||
1658 | data->num_touchids = object->num_report_ids - 2; | ||
1659 | break; | ||
1501 | } | 1660 | } |
1502 | 1661 | ||
1503 | end_address = object->start_address | 1662 | end_address = object->start_address |
@@ -1582,22 +1741,138 @@ static int mxt_read_t9_resolution(struct mxt_data *data) | |||
1582 | return 0; | 1741 | return 0; |
1583 | } | 1742 | } |
1584 | 1743 | ||
1744 | static int mxt_read_t100_config(struct mxt_data *data) | ||
1745 | { | ||
1746 | struct i2c_client *client = data->client; | ||
1747 | int error; | ||
1748 | struct mxt_object *object; | ||
1749 | u16 range_x, range_y; | ||
1750 | u8 cfg, tchaux; | ||
1751 | u8 aux; | ||
1752 | |||
1753 | object = mxt_get_object(data, MXT_TOUCH_MULTITOUCHSCREEN_T100); | ||
1754 | if (!object) | ||
1755 | return -EINVAL; | ||
1756 | |||
1757 | error = __mxt_read_reg(client, | ||
1758 | object->start_address + MXT_T100_XRANGE, | ||
1759 | sizeof(range_x), &range_x); | ||
1760 | if (error) | ||
1761 | return error; | ||
1762 | |||
1763 | le16_to_cpus(&range_x); | ||
1764 | |||
1765 | error = __mxt_read_reg(client, | ||
1766 | object->start_address + MXT_T100_YRANGE, | ||
1767 | sizeof(range_y), &range_y); | ||
1768 | if (error) | ||
1769 | return error; | ||
1770 | |||
1771 | le16_to_cpus(&range_y); | ||
1772 | |||
1773 | error = __mxt_read_reg(client, | ||
1774 | object->start_address + MXT_T100_CFG1, | ||
1775 | 1, &cfg); | ||
1776 | if (error) | ||
1777 | return error; | ||
1778 | |||
1779 | error = __mxt_read_reg(client, | ||
1780 | object->start_address + MXT_T100_TCHAUX, | ||
1781 | 1, &tchaux); | ||
1782 | if (error) | ||
1783 | return error; | ||
1784 | |||
1785 | /* Handle default values */ | ||
1786 | if (range_x == 0) | ||
1787 | range_x = 1023; | ||
1788 | |||
1789 | if (range_y == 0) | ||
1790 | range_y = 1023; | ||
1791 | |||
1792 | if (cfg & MXT_T100_CFG_SWITCHXY) { | ||
1793 | data->max_x = range_y; | ||
1794 | data->max_y = range_x; | ||
1795 | } else { | ||
1796 | data->max_x = range_x; | ||
1797 | data->max_y = range_y; | ||
1798 | } | ||
1799 | |||
1800 | /* allocate aux bytes */ | ||
1801 | aux = 6; | ||
1802 | |||
1803 | if (tchaux & MXT_T100_TCHAUX_VECT) | ||
1804 | data->t100_aux_vect = aux++; | ||
1805 | |||
1806 | if (tchaux & MXT_T100_TCHAUX_AMPL) | ||
1807 | data->t100_aux_ampl = aux++; | ||
1808 | |||
1809 | if (tchaux & MXT_T100_TCHAUX_AREA) | ||
1810 | data->t100_aux_area = aux++; | ||
1811 | |||
1812 | dev_dbg(&client->dev, | ||
1813 | "T100 aux mappings vect:%u ampl:%u area:%u\n", | ||
1814 | data->t100_aux_vect, data->t100_aux_ampl, data->t100_aux_area); | ||
1815 | |||
1816 | dev_info(&client->dev, | ||
1817 | "T100 Touchscreen size X%uY%u\n", data->max_x, data->max_y); | ||
1818 | |||
1819 | return 0; | ||
1820 | } | ||
1821 | |||
1585 | static int mxt_input_open(struct input_dev *dev); | 1822 | static int mxt_input_open(struct input_dev *dev); |
1586 | static void mxt_input_close(struct input_dev *dev); | 1823 | static void mxt_input_close(struct input_dev *dev); |
1587 | 1824 | ||
1588 | static int mxt_initialize_t9_input_device(struct mxt_data *data) | 1825 | static void mxt_set_up_as_touchpad(struct input_dev *input_dev, |
1826 | struct mxt_data *data) | ||
1589 | { | 1827 | { |
1590 | struct device *dev = &data->client->dev; | ||
1591 | const struct mxt_platform_data *pdata = data->pdata; | 1828 | const struct mxt_platform_data *pdata = data->pdata; |
1829 | int i; | ||
1830 | |||
1831 | input_dev->name = "Atmel maXTouch Touchpad"; | ||
1832 | |||
1833 | __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); | ||
1834 | |||
1835 | input_abs_set_res(input_dev, ABS_X, MXT_PIXELS_PER_MM); | ||
1836 | input_abs_set_res(input_dev, ABS_Y, MXT_PIXELS_PER_MM); | ||
1837 | input_abs_set_res(input_dev, ABS_MT_POSITION_X, | ||
1838 | MXT_PIXELS_PER_MM); | ||
1839 | input_abs_set_res(input_dev, ABS_MT_POSITION_Y, | ||
1840 | MXT_PIXELS_PER_MM); | ||
1841 | |||
1842 | for (i = 0; i < pdata->t19_num_keys; i++) | ||
1843 | if (pdata->t19_keymap[i] != KEY_RESERVED) | ||
1844 | input_set_capability(input_dev, EV_KEY, | ||
1845 | pdata->t19_keymap[i]); | ||
1846 | } | ||
1847 | |||
1848 | static int mxt_initialize_input_device(struct mxt_data *data) | ||
1849 | { | ||
1850 | const struct mxt_platform_data *pdata = data->pdata; | ||
1851 | struct device *dev = &data->client->dev; | ||
1592 | struct input_dev *input_dev; | 1852 | struct input_dev *input_dev; |
1593 | int error; | 1853 | int error; |
1594 | unsigned int num_mt_slots; | 1854 | unsigned int num_mt_slots; |
1595 | unsigned int mt_flags = 0; | 1855 | unsigned int mt_flags = 0; |
1596 | int i; | ||
1597 | 1856 | ||
1598 | error = mxt_read_t9_resolution(data); | 1857 | switch (data->multitouch) { |
1599 | if (error) | 1858 | case MXT_TOUCH_MULTI_T9: |
1600 | dev_warn(dev, "Failed to initialize T9 resolution\n"); | 1859 | num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1; |
1860 | error = mxt_read_t9_resolution(data); | ||
1861 | if (error) | ||
1862 | dev_warn(dev, "Failed to initialize T9 resolution\n"); | ||
1863 | break; | ||
1864 | |||
1865 | case MXT_TOUCH_MULTITOUCHSCREEN_T100: | ||
1866 | num_mt_slots = data->num_touchids; | ||
1867 | error = mxt_read_t100_config(data); | ||
1868 | if (error) | ||
1869 | dev_warn(dev, "Failed to read T100 config\n"); | ||
1870 | break; | ||
1871 | |||
1872 | default: | ||
1873 | dev_err(dev, "Invalid multitouch object\n"); | ||
1874 | return -EINVAL; | ||
1875 | } | ||
1601 | 1876 | ||
1602 | input_dev = input_allocate_device(); | 1877 | input_dev = input_allocate_device(); |
1603 | if (!input_dev) { | 1878 | if (!input_dev) { |
@@ -1612,54 +1887,76 @@ static int mxt_initialize_t9_input_device(struct mxt_data *data) | |||
1612 | input_dev->open = mxt_input_open; | 1887 | input_dev->open = mxt_input_open; |
1613 | input_dev->close = mxt_input_close; | 1888 | input_dev->close = mxt_input_close; |
1614 | 1889 | ||
1615 | __set_bit(EV_ABS, input_dev->evbit); | 1890 | input_set_capability(input_dev, EV_KEY, BTN_TOUCH); |
1616 | __set_bit(EV_KEY, input_dev->evbit); | ||
1617 | __set_bit(BTN_TOUCH, input_dev->keybit); | ||
1618 | 1891 | ||
1619 | if (pdata->t19_num_keys) { | 1892 | /* For single touch */ |
1620 | __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); | 1893 | input_set_abs_params(input_dev, ABS_X, 0, data->max_x, 0, 0); |
1894 | input_set_abs_params(input_dev, ABS_Y, 0, data->max_y, 0, 0); | ||
1621 | 1895 | ||
1622 | for (i = 0; i < pdata->t19_num_keys; i++) | 1896 | if (data->multitouch == MXT_TOUCH_MULTI_T9 || |
1623 | if (pdata->t19_keymap[i] != KEY_RESERVED) | 1897 | (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 && |
1624 | input_set_capability(input_dev, EV_KEY, | 1898 | data->t100_aux_ampl)) { |
1625 | pdata->t19_keymap[i]); | 1899 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0); |
1900 | } | ||
1626 | 1901 | ||
1902 | /* If device has buttons we assume it is a touchpad */ | ||
1903 | if (pdata->t19_num_keys) { | ||
1904 | mxt_set_up_as_touchpad(input_dev, data); | ||
1627 | mt_flags |= INPUT_MT_POINTER; | 1905 | mt_flags |= INPUT_MT_POINTER; |
1628 | |||
1629 | input_abs_set_res(input_dev, ABS_X, MXT_PIXELS_PER_MM); | ||
1630 | input_abs_set_res(input_dev, ABS_Y, MXT_PIXELS_PER_MM); | ||
1631 | input_abs_set_res(input_dev, ABS_MT_POSITION_X, | ||
1632 | MXT_PIXELS_PER_MM); | ||
1633 | input_abs_set_res(input_dev, ABS_MT_POSITION_Y, | ||
1634 | MXT_PIXELS_PER_MM); | ||
1635 | |||
1636 | input_dev->name = "Atmel maXTouch Touchpad"; | ||
1637 | } | 1906 | } |
1638 | 1907 | ||
1639 | /* For single touch */ | ||
1640 | input_set_abs_params(input_dev, ABS_X, | ||
1641 | 0, data->max_x, 0, 0); | ||
1642 | input_set_abs_params(input_dev, ABS_Y, | ||
1643 | 0, data->max_y, 0, 0); | ||
1644 | input_set_abs_params(input_dev, ABS_PRESSURE, | ||
1645 | 0, 255, 0, 0); | ||
1646 | |||
1647 | /* For multi touch */ | 1908 | /* For multi touch */ |
1648 | num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1; | ||
1649 | error = input_mt_init_slots(input_dev, num_mt_slots, mt_flags); | 1909 | error = input_mt_init_slots(input_dev, num_mt_slots, mt_flags); |
1650 | if (error) { | 1910 | if (error) { |
1651 | dev_err(dev, "Error %d initialising slots\n", error); | 1911 | dev_err(dev, "Error %d initialising slots\n", error); |
1652 | goto err_free_mem; | 1912 | goto err_free_mem; |
1653 | } | 1913 | } |
1654 | 1914 | ||
1655 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, | 1915 | if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100) { |
1656 | 0, MXT_MAX_AREA, 0, 0); | 1916 | input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE, |
1917 | 0, MT_TOOL_MAX, 0, 0); | ||
1918 | input_set_abs_params(input_dev, ABS_MT_DISTANCE, | ||
1919 | MXT_DISTANCE_ACTIVE_TOUCH, | ||
1920 | MXT_DISTANCE_HOVERING, | ||
1921 | 0, 0); | ||
1922 | } | ||
1923 | |||
1657 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | 1924 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, |
1658 | 0, data->max_x, 0, 0); | 1925 | 0, data->max_x, 0, 0); |
1659 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, | 1926 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, |
1660 | 0, data->max_y, 0, 0); | 1927 | 0, data->max_y, 0, 0); |
1661 | input_set_abs_params(input_dev, ABS_MT_PRESSURE, | 1928 | |
1662 | 0, 255, 0, 0); | 1929 | if (data->multitouch == MXT_TOUCH_MULTI_T9 || |
1930 | (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 && | ||
1931 | data->t100_aux_area)) { | ||
1932 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, | ||
1933 | 0, MXT_MAX_AREA, 0, 0); | ||
1934 | } | ||
1935 | |||
1936 | if (data->multitouch == MXT_TOUCH_MULTI_T9 || | ||
1937 | (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 && | ||
1938 | data->t100_aux_ampl)) { | ||
1939 | input_set_abs_params(input_dev, ABS_MT_PRESSURE, | ||
1940 | 0, 255, 0, 0); | ||
1941 | } | ||
1942 | |||
1943 | if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 && | ||
1944 | data->t100_aux_vect) { | ||
1945 | input_set_abs_params(input_dev, ABS_MT_ORIENTATION, | ||
1946 | 0, 255, 0, 0); | ||
1947 | } | ||
1948 | |||
1949 | if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 && | ||
1950 | data->t100_aux_ampl) { | ||
1951 | input_set_abs_params(input_dev, ABS_MT_PRESSURE, | ||
1952 | 0, 255, 0, 0); | ||
1953 | } | ||
1954 | |||
1955 | if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 && | ||
1956 | data->t100_aux_vect) { | ||
1957 | input_set_abs_params(input_dev, ABS_MT_ORIENTATION, | ||
1958 | 0, 255, 0, 0); | ||
1959 | } | ||
1663 | 1960 | ||
1664 | input_set_drvdata(input_dev, data); | 1961 | input_set_drvdata(input_dev, data); |
1665 | 1962 | ||
@@ -1765,9 +2062,13 @@ static int mxt_configure_objects(struct mxt_data *data, | |||
1765 | dev_warn(dev, "Error %d updating config\n", error); | 2062 | dev_warn(dev, "Error %d updating config\n", error); |
1766 | } | 2063 | } |
1767 | 2064 | ||
1768 | error = mxt_initialize_t9_input_device(data); | 2065 | if (data->multitouch) { |
1769 | if (error) | 2066 | error = mxt_initialize_input_device(data); |
1770 | return error; | 2067 | if (error) |
2068 | return error; | ||
2069 | } else { | ||
2070 | dev_warn(dev, "No touch object detected\n"); | ||
2071 | } | ||
1771 | 2072 | ||
1772 | dev_info(dev, | 2073 | dev_info(dev, |
1773 | "Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n", | 2074 | "Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n", |
@@ -2044,15 +2345,13 @@ static const struct attribute_group mxt_attr_group = { | |||
2044 | static void mxt_start(struct mxt_data *data) | 2345 | static void mxt_start(struct mxt_data *data) |
2045 | { | 2346 | { |
2046 | /* Touch enable */ | 2347 | /* Touch enable */ |
2047 | mxt_write_object(data, | 2348 | mxt_write_object(data, data->multitouch, MXT_TOUCH_CTRL, 0x83); |
2048 | MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0x83); | ||
2049 | } | 2349 | } |
2050 | 2350 | ||
2051 | static void mxt_stop(struct mxt_data *data) | 2351 | static void mxt_stop(struct mxt_data *data) |
2052 | { | 2352 | { |
2053 | /* Touch disable */ | 2353 | /* Touch disable */ |
2054 | mxt_write_object(data, | 2354 | mxt_write_object(data, data->multitouch, MXT_TOUCH_CTRL, 0); |
2055 | MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0); | ||
2056 | } | 2355 | } |
2057 | 2356 | ||
2058 | static int mxt_input_open(struct input_dev *dev) | 2357 | static int mxt_input_open(struct input_dev *dev) |
diff --git a/drivers/input/touchscreen/bcm_iproc_tsc.c b/drivers/input/touchscreen/bcm_iproc_tsc.c new file mode 100644 index 000000000000..ae460a5c93d5 --- /dev/null +++ b/drivers/input/touchscreen/bcm_iproc_tsc.c | |||
@@ -0,0 +1,522 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 Broadcom Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License as | ||
6 | * published by the Free Software Foundation version 2. | ||
7 | * | ||
8 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
9 | * kind, whether express or implied; without even the implied warranty | ||
10 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/input.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/keyboard.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/of.h> | ||
22 | #include <asm/irq.h> | ||
23 | #include <linux/io.h> | ||
24 | #include <linux/clk.h> | ||
25 | #include <linux/serio.h> | ||
26 | |||
27 | #define IPROC_TS_NAME "iproc-ts" | ||
28 | |||
29 | #define PEN_DOWN_STATUS 1 | ||
30 | #define PEN_UP_STATUS 0 | ||
31 | |||
32 | #define X_MIN 0 | ||
33 | #define Y_MIN 0 | ||
34 | #define X_MAX 0xFFF | ||
35 | #define Y_MAX 0xFFF | ||
36 | |||
37 | /* Value given by controller for invalid coordinate. */ | ||
38 | #define INVALID_COORD 0xFFFFFFFF | ||
39 | |||
40 | /* Register offsets */ | ||
41 | #define REGCTL1 0x00 | ||
42 | #define REGCTL2 0x04 | ||
43 | #define INTERRUPT_THRES 0x08 | ||
44 | #define INTERRUPT_MASK 0x0c | ||
45 | |||
46 | #define INTERRUPT_STATUS 0x10 | ||
47 | #define CONTROLLER_STATUS 0x14 | ||
48 | #define FIFO_DATA 0x18 | ||
49 | #define FIFO_DATA_X_Y_MASK 0xFFFF | ||
50 | #define ANALOG_CONTROL 0x1c | ||
51 | |||
52 | #define AUX_DATA 0x20 | ||
53 | #define DEBOUNCE_CNTR_STAT 0x24 | ||
54 | #define SCAN_CNTR_STAT 0x28 | ||
55 | #define REM_CNTR_STAT 0x2c | ||
56 | |||
57 | #define SETTLING_TIMER_STAT 0x30 | ||
58 | #define SPARE_REG 0x34 | ||
59 | #define SOFT_BYPASS_CONTROL 0x38 | ||
60 | #define SOFT_BYPASS_DATA 0x3c | ||
61 | |||
62 | |||
63 | /* Bit values for INTERRUPT_MASK and INTERRUPT_STATUS regs */ | ||
64 | #define TS_PEN_INTR_MASK BIT(0) | ||
65 | #define TS_FIFO_INTR_MASK BIT(2) | ||
66 | |||
67 | /* Bit values for CONTROLLER_STATUS reg1 */ | ||
68 | #define TS_PEN_DOWN BIT(0) | ||
69 | |||
70 | /* Shift values for control reg1 */ | ||
71 | #define SCANNING_PERIOD_SHIFT 24 | ||
72 | #define DEBOUNCE_TIMEOUT_SHIFT 16 | ||
73 | #define SETTLING_TIMEOUT_SHIFT 8 | ||
74 | #define TOUCH_TIMEOUT_SHIFT 0 | ||
75 | |||
76 | /* Shift values for coordinates from fifo */ | ||
77 | #define X_COORD_SHIFT 0 | ||
78 | #define Y_COORD_SHIFT 16 | ||
79 | |||
80 | /* Bit values for REGCTL2 */ | ||
81 | #define TS_CONTROLLER_EN_BIT BIT(16) | ||
82 | #define TS_CONTROLLER_AVGDATA_SHIFT 8 | ||
83 | #define TS_CONTROLLER_AVGDATA_MASK (0x7 << TS_CONTROLLER_AVGDATA_SHIFT) | ||
84 | #define TS_CONTROLLER_PWR_LDO BIT(5) | ||
85 | #define TS_CONTROLLER_PWR_ADC BIT(4) | ||
86 | #define TS_CONTROLLER_PWR_BGP BIT(3) | ||
87 | #define TS_CONTROLLER_PWR_TS BIT(2) | ||
88 | #define TS_WIRE_MODE_BIT BIT(1) | ||
89 | |||
90 | #define dbg_reg(dev, priv, reg) \ | ||
91 | dev_dbg(dev, "%20s= 0x%08x\n", #reg, readl((priv)->regs + reg)) | ||
92 | |||
93 | struct tsc_param { | ||
94 | /* Each step is 1024 us. Valid 1-256 */ | ||
95 | u32 scanning_period; | ||
96 | |||
97 | /* Each step is 512 us. Valid 0-255 */ | ||
98 | u32 debounce_timeout; | ||
99 | |||
100 | /* | ||
101 | * The settling duration (in ms) is the amount of time the tsc | ||
102 | * waits to allow the voltage to settle after turning on the | ||
103 | * drivers in detection mode. Valid values: 0-11 | ||
104 | * 0 = 0.008 ms | ||
105 | * 1 = 0.01 ms | ||
106 | * 2 = 0.02 ms | ||
107 | * 3 = 0.04 ms | ||
108 | * 4 = 0.08 ms | ||
109 | * 5 = 0.16 ms | ||
110 | * 6 = 0.32 ms | ||
111 | * 7 = 0.64 ms | ||
112 | * 8 = 1.28 ms | ||
113 | * 9 = 2.56 ms | ||
114 | * 10 = 5.12 ms | ||
115 | * 11 = 10.24 ms | ||
116 | */ | ||
117 | u32 settling_timeout; | ||
118 | |||
119 | /* touch timeout in sample counts */ | ||
120 | u32 touch_timeout; | ||
121 | |||
122 | /* | ||
123 | * Number of data samples which are averaged before a final data point | ||
124 | * is placed into the FIFO | ||
125 | */ | ||
126 | u32 average_data; | ||
127 | |||
128 | /* FIFO threshold */ | ||
129 | u32 fifo_threshold; | ||
130 | |||
131 | /* Optional standard touchscreen properties. */ | ||
132 | u32 max_x; | ||
133 | u32 max_y; | ||
134 | u32 fuzz_x; | ||
135 | u32 fuzz_y; | ||
136 | bool invert_x; | ||
137 | bool invert_y; | ||
138 | }; | ||
139 | |||
140 | struct iproc_ts_priv { | ||
141 | struct platform_device *pdev; | ||
142 | struct input_dev *idev; | ||
143 | |||
144 | void __iomem *regs; | ||
145 | struct clk *tsc_clk; | ||
146 | |||
147 | int pen_status; | ||
148 | struct tsc_param cfg_params; | ||
149 | }; | ||
150 | |||
151 | /* | ||
152 | * Set default values the same as hardware reset values | ||
153 | * except for fifo_threshold with is set to 1. | ||
154 | */ | ||
155 | static const struct tsc_param iproc_default_config = { | ||
156 | .scanning_period = 0x5, /* 1 to 256 */ | ||
157 | .debounce_timeout = 0x28, /* 0 to 255 */ | ||
158 | .settling_timeout = 0x7, /* 0 to 11 */ | ||
159 | .touch_timeout = 0xa, /* 0 to 255 */ | ||
160 | .average_data = 5, /* entry 5 = 32 pts */ | ||
161 | .fifo_threshold = 1, /* 0 to 31 */ | ||
162 | .max_x = X_MAX, | ||
163 | .max_y = Y_MAX, | ||
164 | }; | ||
165 | |||
166 | static void ts_reg_dump(struct iproc_ts_priv *priv) | ||
167 | { | ||
168 | struct device *dev = &priv->pdev->dev; | ||
169 | |||
170 | dbg_reg(dev, priv, REGCTL1); | ||
171 | dbg_reg(dev, priv, REGCTL2); | ||
172 | dbg_reg(dev, priv, INTERRUPT_THRES); | ||
173 | dbg_reg(dev, priv, INTERRUPT_MASK); | ||
174 | dbg_reg(dev, priv, INTERRUPT_STATUS); | ||
175 | dbg_reg(dev, priv, CONTROLLER_STATUS); | ||
176 | dbg_reg(dev, priv, FIFO_DATA); | ||
177 | dbg_reg(dev, priv, ANALOG_CONTROL); | ||
178 | dbg_reg(dev, priv, AUX_DATA); | ||
179 | dbg_reg(dev, priv, DEBOUNCE_CNTR_STAT); | ||
180 | dbg_reg(dev, priv, SCAN_CNTR_STAT); | ||
181 | dbg_reg(dev, priv, REM_CNTR_STAT); | ||
182 | dbg_reg(dev, priv, SETTLING_TIMER_STAT); | ||
183 | dbg_reg(dev, priv, SPARE_REG); | ||
184 | dbg_reg(dev, priv, SOFT_BYPASS_CONTROL); | ||
185 | dbg_reg(dev, priv, SOFT_BYPASS_DATA); | ||
186 | } | ||
187 | |||
188 | static irqreturn_t iproc_touchscreen_interrupt(int irq, void *data) | ||
189 | { | ||
190 | struct platform_device *pdev = data; | ||
191 | struct iproc_ts_priv *priv = platform_get_drvdata(pdev); | ||
192 | u32 intr_status; | ||
193 | u32 raw_coordinate; | ||
194 | u16 x; | ||
195 | u16 y; | ||
196 | int i; | ||
197 | bool needs_sync = false; | ||
198 | |||
199 | intr_status = readl(priv->regs + INTERRUPT_STATUS); | ||
200 | intr_status &= TS_PEN_INTR_MASK | TS_FIFO_INTR_MASK; | ||
201 | if (intr_status == 0) | ||
202 | return IRQ_NONE; | ||
203 | |||
204 | /* Clear all interrupt status bits, write-1-clear */ | ||
205 | writel(intr_status, priv->regs + INTERRUPT_STATUS); | ||
206 | |||
207 | /* Pen up/down */ | ||
208 | if (intr_status & TS_PEN_INTR_MASK) { | ||
209 | if (readl(priv->regs + CONTROLLER_STATUS) & TS_PEN_DOWN) | ||
210 | priv->pen_status = PEN_DOWN_STATUS; | ||
211 | else | ||
212 | priv->pen_status = PEN_UP_STATUS; | ||
213 | |||
214 | input_report_key(priv->idev, BTN_TOUCH, priv->pen_status); | ||
215 | needs_sync = true; | ||
216 | |||
217 | dev_dbg(&priv->pdev->dev, | ||
218 | "pen up-down (%d)\n", priv->pen_status); | ||
219 | } | ||
220 | |||
221 | /* coordinates in FIFO exceed the theshold */ | ||
222 | if (intr_status & TS_FIFO_INTR_MASK) { | ||
223 | for (i = 0; i < priv->cfg_params.fifo_threshold; i++) { | ||
224 | raw_coordinate = readl(priv->regs + FIFO_DATA); | ||
225 | if (raw_coordinate == INVALID_COORD) | ||
226 | continue; | ||
227 | |||
228 | /* | ||
229 | * The x and y coordinate are 16 bits each | ||
230 | * with the x in the lower 16 bits and y in the | ||
231 | * upper 16 bits. | ||
232 | */ | ||
233 | x = (raw_coordinate >> X_COORD_SHIFT) & | ||
234 | FIFO_DATA_X_Y_MASK; | ||
235 | y = (raw_coordinate >> Y_COORD_SHIFT) & | ||
236 | FIFO_DATA_X_Y_MASK; | ||
237 | |||
238 | /* We only want to retain the 12 msb of the 16 */ | ||
239 | x = (x >> 4) & 0x0FFF; | ||
240 | y = (y >> 4) & 0x0FFF; | ||
241 | |||
242 | /* adjust x y according to lcd tsc mount angle */ | ||
243 | if (priv->cfg_params.invert_x) | ||
244 | x = priv->cfg_params.max_x - x; | ||
245 | |||
246 | if (priv->cfg_params.invert_y) | ||
247 | y = priv->cfg_params.max_y - y; | ||
248 | |||
249 | input_report_abs(priv->idev, ABS_X, x); | ||
250 | input_report_abs(priv->idev, ABS_Y, y); | ||
251 | needs_sync = true; | ||
252 | |||
253 | dev_dbg(&priv->pdev->dev, "xy (0x%x 0x%x)\n", x, y); | ||
254 | } | ||
255 | } | ||
256 | |||
257 | if (needs_sync) | ||
258 | input_sync(priv->idev); | ||
259 | |||
260 | return IRQ_HANDLED; | ||
261 | } | ||
262 | |||
263 | static int iproc_ts_start(struct input_dev *idev) | ||
264 | { | ||
265 | struct iproc_ts_priv *priv = input_get_drvdata(idev); | ||
266 | u32 val; | ||
267 | int error; | ||
268 | |||
269 | /* Enable clock */ | ||
270 | error = clk_prepare_enable(priv->tsc_clk); | ||
271 | if (error) { | ||
272 | dev_err(&priv->pdev->dev, "%s clk_prepare_enable failed %d\n", | ||
273 | __func__, error); | ||
274 | return error; | ||
275 | } | ||
276 | |||
277 | /* | ||
278 | * Interrupt is generated when: | ||
279 | * FIFO reaches the int_th value, and pen event(up/down) | ||
280 | */ | ||
281 | val = TS_PEN_INTR_MASK | TS_FIFO_INTR_MASK; | ||
282 | writel(val, priv->regs + INTERRUPT_MASK); | ||
283 | |||
284 | writel(priv->cfg_params.fifo_threshold, priv->regs + INTERRUPT_THRES); | ||
285 | |||
286 | /* Initialize control reg1 */ | ||
287 | val = 0; | ||
288 | val |= priv->cfg_params.scanning_period << SCANNING_PERIOD_SHIFT; | ||
289 | val |= priv->cfg_params.debounce_timeout << DEBOUNCE_TIMEOUT_SHIFT; | ||
290 | val |= priv->cfg_params.settling_timeout << SETTLING_TIMEOUT_SHIFT; | ||
291 | val |= priv->cfg_params.touch_timeout << TOUCH_TIMEOUT_SHIFT; | ||
292 | writel(val, priv->regs + REGCTL1); | ||
293 | |||
294 | /* Try to clear all interrupt status */ | ||
295 | val = readl(priv->regs + INTERRUPT_STATUS); | ||
296 | val |= TS_FIFO_INTR_MASK | TS_PEN_INTR_MASK; | ||
297 | writel(val, priv->regs + INTERRUPT_STATUS); | ||
298 | |||
299 | /* Initialize control reg2 */ | ||
300 | val = readl(priv->regs + REGCTL2); | ||
301 | val |= TS_CONTROLLER_EN_BIT | TS_WIRE_MODE_BIT; | ||
302 | |||
303 | val &= ~TS_CONTROLLER_AVGDATA_MASK; | ||
304 | val |= priv->cfg_params.average_data << TS_CONTROLLER_AVGDATA_SHIFT; | ||
305 | |||
306 | val &= ~(TS_CONTROLLER_PWR_LDO | /* PWR up LDO */ | ||
307 | TS_CONTROLLER_PWR_ADC | /* PWR up ADC */ | ||
308 | TS_CONTROLLER_PWR_BGP | /* PWR up BGP */ | ||
309 | TS_CONTROLLER_PWR_TS); /* PWR up TS */ | ||
310 | |||
311 | writel(val, priv->regs + REGCTL2); | ||
312 | |||
313 | ts_reg_dump(priv); | ||
314 | |||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | static void iproc_ts_stop(struct input_dev *dev) | ||
319 | { | ||
320 | u32 val; | ||
321 | struct iproc_ts_priv *priv = input_get_drvdata(dev); | ||
322 | |||
323 | writel(0, priv->regs + INTERRUPT_MASK); /* Disable all interrupts */ | ||
324 | |||
325 | /* Only power down touch screen controller */ | ||
326 | val = readl(priv->regs + REGCTL2); | ||
327 | val |= TS_CONTROLLER_PWR_TS; | ||
328 | writel(val, priv->regs + REGCTL2); | ||
329 | |||
330 | clk_disable(priv->tsc_clk); | ||
331 | } | ||
332 | |||
333 | static int iproc_get_tsc_config(struct device *dev, struct iproc_ts_priv *priv) | ||
334 | { | ||
335 | struct device_node *np = dev->of_node; | ||
336 | u32 val; | ||
337 | |||
338 | priv->cfg_params = iproc_default_config; | ||
339 | |||
340 | if (!np) | ||
341 | return 0; | ||
342 | |||
343 | if (of_property_read_u32(np, "scanning_period", &val) >= 0) { | ||
344 | if (val < 1 || val > 256) { | ||
345 | dev_err(dev, "scanning_period (%u) must be [1-256]\n", | ||
346 | val); | ||
347 | return -EINVAL; | ||
348 | } | ||
349 | priv->cfg_params.scanning_period = val; | ||
350 | } | ||
351 | |||
352 | if (of_property_read_u32(np, "debounce_timeout", &val) >= 0) { | ||
353 | if (val > 255) { | ||
354 | dev_err(dev, "debounce_timeout (%u) must be [0-255]\n", | ||
355 | val); | ||
356 | return -EINVAL; | ||
357 | } | ||
358 | priv->cfg_params.debounce_timeout = val; | ||
359 | } | ||
360 | |||
361 | if (of_property_read_u32(np, "settling_timeout", &val) >= 0) { | ||
362 | if (val > 11) { | ||
363 | dev_err(dev, "settling_timeout (%u) must be [0-11]\n", | ||
364 | val); | ||
365 | return -EINVAL; | ||
366 | } | ||
367 | priv->cfg_params.settling_timeout = val; | ||
368 | } | ||
369 | |||
370 | if (of_property_read_u32(np, "touch_timeout", &val) >= 0) { | ||
371 | if (val > 255) { | ||
372 | dev_err(dev, "touch_timeout (%u) must be [0-255]\n", | ||
373 | val); | ||
374 | return -EINVAL; | ||
375 | } | ||
376 | priv->cfg_params.touch_timeout = val; | ||
377 | } | ||
378 | |||
379 | if (of_property_read_u32(np, "average_data", &val) >= 0) { | ||
380 | if (val > 8) { | ||
381 | dev_err(dev, "average_data (%u) must be [0-8]\n", val); | ||
382 | return -EINVAL; | ||
383 | } | ||
384 | priv->cfg_params.average_data = val; | ||
385 | } | ||
386 | |||
387 | if (of_property_read_u32(np, "fifo_threshold", &val) >= 0) { | ||
388 | if (val > 31) { | ||
389 | dev_err(dev, "fifo_threshold (%u)) must be [0-31]\n", | ||
390 | val); | ||
391 | return -EINVAL; | ||
392 | } | ||
393 | priv->cfg_params.fifo_threshold = val; | ||
394 | } | ||
395 | |||
396 | /* Parse optional properties. */ | ||
397 | of_property_read_u32(np, "touchscreen-size-x", &priv->cfg_params.max_x); | ||
398 | of_property_read_u32(np, "touchscreen-size-y", &priv->cfg_params.max_y); | ||
399 | |||
400 | of_property_read_u32(np, "touchscreen-fuzz-x", | ||
401 | &priv->cfg_params.fuzz_x); | ||
402 | of_property_read_u32(np, "touchscreen-fuzz-y", | ||
403 | &priv->cfg_params.fuzz_y); | ||
404 | |||
405 | priv->cfg_params.invert_x = | ||
406 | of_property_read_bool(np, "touchscreen-inverted-x"); | ||
407 | priv->cfg_params.invert_y = | ||
408 | of_property_read_bool(np, "touchscreen-inverted-y"); | ||
409 | |||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | static int iproc_ts_probe(struct platform_device *pdev) | ||
414 | { | ||
415 | struct iproc_ts_priv *priv; | ||
416 | struct input_dev *idev; | ||
417 | struct resource *res; | ||
418 | int irq; | ||
419 | int error; | ||
420 | |||
421 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
422 | if (!priv) | ||
423 | return -ENOMEM; | ||
424 | |||
425 | /* touchscreen controller memory mapped regs */ | ||
426 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
427 | priv->regs = devm_ioremap_resource(&pdev->dev, res); | ||
428 | if (IS_ERR(priv->regs)) { | ||
429 | error = PTR_ERR(priv->regs); | ||
430 | dev_err(&pdev->dev, "unable to map I/O memory: %d\n", error); | ||
431 | return error; | ||
432 | } | ||
433 | |||
434 | priv->tsc_clk = devm_clk_get(&pdev->dev, "tsc_clk"); | ||
435 | if (IS_ERR(priv->tsc_clk)) { | ||
436 | error = PTR_ERR(priv->tsc_clk); | ||
437 | dev_err(&pdev->dev, | ||
438 | "failed getting clock tsc_clk: %d\n", error); | ||
439 | return error; | ||
440 | } | ||
441 | |||
442 | priv->pdev = pdev; | ||
443 | error = iproc_get_tsc_config(&pdev->dev, priv); | ||
444 | if (error) { | ||
445 | dev_err(&pdev->dev, "get_tsc_config failed: %d\n", error); | ||
446 | return error; | ||
447 | } | ||
448 | |||
449 | idev = devm_input_allocate_device(&pdev->dev); | ||
450 | if (!idev) { | ||
451 | dev_err(&pdev->dev, "failed to allocate input device\n"); | ||
452 | return -ENOMEM; | ||
453 | } | ||
454 | |||
455 | priv->idev = idev; | ||
456 | priv->pen_status = PEN_UP_STATUS; | ||
457 | |||
458 | /* Set input device info */ | ||
459 | idev->name = IPROC_TS_NAME; | ||
460 | idev->dev.parent = &pdev->dev; | ||
461 | |||
462 | idev->id.bustype = BUS_HOST; | ||
463 | idev->id.vendor = SERIO_UNKNOWN; | ||
464 | idev->id.product = 0; | ||
465 | idev->id.version = 0; | ||
466 | |||
467 | idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
468 | __set_bit(BTN_TOUCH, idev->keybit); | ||
469 | |||
470 | input_set_abs_params(idev, ABS_X, X_MIN, priv->cfg_params.max_x, | ||
471 | priv->cfg_params.fuzz_x, 0); | ||
472 | input_set_abs_params(idev, ABS_Y, Y_MIN, priv->cfg_params.max_y, | ||
473 | priv->cfg_params.fuzz_y, 0); | ||
474 | |||
475 | idev->open = iproc_ts_start; | ||
476 | idev->close = iproc_ts_stop; | ||
477 | |||
478 | input_set_drvdata(idev, priv); | ||
479 | platform_set_drvdata(pdev, priv); | ||
480 | |||
481 | /* get interrupt */ | ||
482 | irq = platform_get_irq(pdev, 0); | ||
483 | if (irq < 0) { | ||
484 | dev_err(&pdev->dev, "platform_get_irq failed: %d\n", irq); | ||
485 | return irq; | ||
486 | } | ||
487 | |||
488 | error = devm_request_irq(&pdev->dev, irq, | ||
489 | iproc_touchscreen_interrupt, | ||
490 | IRQF_SHARED, IPROC_TS_NAME, pdev); | ||
491 | if (error) | ||
492 | return error; | ||
493 | |||
494 | error = input_register_device(priv->idev); | ||
495 | if (error) { | ||
496 | dev_err(&pdev->dev, | ||
497 | "failed to register input device: %d\n", error); | ||
498 | return error; | ||
499 | } | ||
500 | |||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | static const struct of_device_id iproc_ts_of_match[] = { | ||
505 | {.compatible = "brcm,iproc-touchscreen", }, | ||
506 | { }, | ||
507 | }; | ||
508 | MODULE_DEVICE_TABLE(of, iproc_ts_of_match); | ||
509 | |||
510 | static struct platform_driver iproc_ts_driver = { | ||
511 | .probe = iproc_ts_probe, | ||
512 | .driver = { | ||
513 | .name = IPROC_TS_NAME, | ||
514 | .of_match_table = of_match_ptr(iproc_ts_of_match), | ||
515 | }, | ||
516 | }; | ||
517 | |||
518 | module_platform_driver(iproc_ts_driver); | ||
519 | |||
520 | MODULE_DESCRIPTION("IPROC Touchscreen driver"); | ||
521 | MODULE_AUTHOR("Broadcom"); | ||
522 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/touchscreen/chipone_icn8318.c b/drivers/input/touchscreen/chipone_icn8318.c new file mode 100644 index 000000000000..32e9db0e04bf --- /dev/null +++ b/drivers/input/touchscreen/chipone_icn8318.c | |||
@@ -0,0 +1,316 @@ | |||
1 | /* | ||
2 | * Driver for ChipOne icn8318 i2c touchscreen controller | ||
3 | * | ||
4 | * Copyright (c) 2015 Red Hat Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * Red Hat authors: | ||
12 | * Hans de Goede <hdegoede@redhat.com> | ||
13 | */ | ||
14 | |||
15 | #include <linux/gpio/consumer.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/input.h> | ||
19 | #include <linux/input/mt.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/of.h> | ||
22 | |||
23 | #define ICN8318_REG_POWER 4 | ||
24 | #define ICN8318_REG_TOUCHDATA 16 | ||
25 | |||
26 | #define ICN8318_POWER_ACTIVE 0 | ||
27 | #define ICN8318_POWER_MONITOR 1 | ||
28 | #define ICN8318_POWER_HIBERNATE 2 | ||
29 | |||
30 | #define ICN8318_MAX_TOUCHES 5 | ||
31 | |||
32 | struct icn8318_touch { | ||
33 | __u8 slot; | ||
34 | __be16 x; | ||
35 | __be16 y; | ||
36 | __u8 pressure; /* Seems more like finger width then pressure really */ | ||
37 | __u8 event; | ||
38 | /* The difference between 2 and 3 is unclear */ | ||
39 | #define ICN8318_EVENT_NO_DATA 1 /* No finger seen yet since wakeup */ | ||
40 | #define ICN8318_EVENT_UPDATE1 2 /* New or updated coordinates */ | ||
41 | #define ICN8318_EVENT_UPDATE2 3 /* New or updated coordinates */ | ||
42 | #define ICN8318_EVENT_END 4 /* Finger lifted */ | ||
43 | } __packed; | ||
44 | |||
45 | struct icn8318_touch_data { | ||
46 | __u8 softbutton; | ||
47 | __u8 touch_count; | ||
48 | struct icn8318_touch touches[ICN8318_MAX_TOUCHES]; | ||
49 | } __packed; | ||
50 | |||
51 | struct icn8318_data { | ||
52 | struct i2c_client *client; | ||
53 | struct input_dev *input; | ||
54 | struct gpio_desc *wake_gpio; | ||
55 | u32 max_x; | ||
56 | u32 max_y; | ||
57 | bool invert_x; | ||
58 | bool invert_y; | ||
59 | bool swap_x_y; | ||
60 | }; | ||
61 | |||
62 | static int icn8318_read_touch_data(struct i2c_client *client, | ||
63 | struct icn8318_touch_data *touch_data) | ||
64 | { | ||
65 | u8 reg = ICN8318_REG_TOUCHDATA; | ||
66 | struct i2c_msg msg[2] = { | ||
67 | { | ||
68 | .addr = client->addr, | ||
69 | .len = 1, | ||
70 | .buf = ® | ||
71 | }, | ||
72 | { | ||
73 | .addr = client->addr, | ||
74 | .flags = I2C_M_RD, | ||
75 | .len = sizeof(struct icn8318_touch_data), | ||
76 | .buf = (u8 *)touch_data | ||
77 | } | ||
78 | }; | ||
79 | |||
80 | return i2c_transfer(client->adapter, msg, 2); | ||
81 | } | ||
82 | |||
83 | static inline bool icn8318_touch_active(u8 event) | ||
84 | { | ||
85 | return (event == ICN8318_EVENT_UPDATE1) || | ||
86 | (event == ICN8318_EVENT_UPDATE2); | ||
87 | } | ||
88 | |||
89 | static irqreturn_t icn8318_irq(int irq, void *dev_id) | ||
90 | { | ||
91 | struct icn8318_data *data = dev_id; | ||
92 | struct device *dev = &data->client->dev; | ||
93 | struct icn8318_touch_data touch_data; | ||
94 | int i, ret, x, y; | ||
95 | |||
96 | ret = icn8318_read_touch_data(data->client, &touch_data); | ||
97 | if (ret < 0) { | ||
98 | dev_err(dev, "Error reading touch data: %d\n", ret); | ||
99 | return IRQ_HANDLED; | ||
100 | } | ||
101 | |||
102 | if (touch_data.softbutton) { | ||
103 | /* | ||
104 | * Other data is invalid when a softbutton is pressed. | ||
105 | * This needs some extra devicetree bindings to map the icn8318 | ||
106 | * softbutton codes to evdev codes. Currently no known devices | ||
107 | * use this. | ||
108 | */ | ||
109 | return IRQ_HANDLED; | ||
110 | } | ||
111 | |||
112 | if (touch_data.touch_count > ICN8318_MAX_TOUCHES) { | ||
113 | dev_warn(dev, "Too much touches %d > %d\n", | ||
114 | touch_data.touch_count, ICN8318_MAX_TOUCHES); | ||
115 | touch_data.touch_count = ICN8318_MAX_TOUCHES; | ||
116 | } | ||
117 | |||
118 | for (i = 0; i < touch_data.touch_count; i++) { | ||
119 | struct icn8318_touch *touch = &touch_data.touches[i]; | ||
120 | bool act = icn8318_touch_active(touch->event); | ||
121 | |||
122 | input_mt_slot(data->input, touch->slot); | ||
123 | input_mt_report_slot_state(data->input, MT_TOOL_FINGER, act); | ||
124 | if (!act) | ||
125 | continue; | ||
126 | |||
127 | x = be16_to_cpu(touch->x); | ||
128 | y = be16_to_cpu(touch->y); | ||
129 | |||
130 | if (data->invert_x) | ||
131 | x = data->max_x - x; | ||
132 | |||
133 | if (data->invert_y) | ||
134 | y = data->max_y - y; | ||
135 | |||
136 | if (!data->swap_x_y) { | ||
137 | input_event(data->input, EV_ABS, ABS_MT_POSITION_X, x); | ||
138 | input_event(data->input, EV_ABS, ABS_MT_POSITION_Y, y); | ||
139 | } else { | ||
140 | input_event(data->input, EV_ABS, ABS_MT_POSITION_X, y); | ||
141 | input_event(data->input, EV_ABS, ABS_MT_POSITION_Y, x); | ||
142 | } | ||
143 | } | ||
144 | |||
145 | input_mt_sync_frame(data->input); | ||
146 | input_sync(data->input); | ||
147 | |||
148 | return IRQ_HANDLED; | ||
149 | } | ||
150 | |||
151 | static int icn8318_start(struct input_dev *dev) | ||
152 | { | ||
153 | struct icn8318_data *data = input_get_drvdata(dev); | ||
154 | |||
155 | enable_irq(data->client->irq); | ||
156 | gpiod_set_value_cansleep(data->wake_gpio, 1); | ||
157 | |||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static void icn8318_stop(struct input_dev *dev) | ||
162 | { | ||
163 | struct icn8318_data *data = input_get_drvdata(dev); | ||
164 | |||
165 | disable_irq(data->client->irq); | ||
166 | i2c_smbus_write_byte_data(data->client, ICN8318_REG_POWER, | ||
167 | ICN8318_POWER_HIBERNATE); | ||
168 | gpiod_set_value_cansleep(data->wake_gpio, 0); | ||
169 | } | ||
170 | |||
171 | #ifdef CONFIG_PM_SLEEP | ||
172 | static int icn8318_suspend(struct device *dev) | ||
173 | { | ||
174 | struct icn8318_data *data = i2c_get_clientdata(to_i2c_client(dev)); | ||
175 | |||
176 | mutex_lock(&data->input->mutex); | ||
177 | if (data->input->users) | ||
178 | icn8318_stop(data->input); | ||
179 | mutex_unlock(&data->input->mutex); | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static int icn8318_resume(struct device *dev) | ||
185 | { | ||
186 | struct icn8318_data *data = i2c_get_clientdata(to_i2c_client(dev)); | ||
187 | |||
188 | mutex_lock(&data->input->mutex); | ||
189 | if (data->input->users) | ||
190 | icn8318_start(data->input); | ||
191 | mutex_unlock(&data->input->mutex); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | #endif | ||
196 | |||
197 | static SIMPLE_DEV_PM_OPS(icn8318_pm_ops, icn8318_suspend, icn8318_resume); | ||
198 | |||
199 | static int icn8318_probe(struct i2c_client *client, | ||
200 | const struct i2c_device_id *id) | ||
201 | { | ||
202 | struct device *dev = &client->dev; | ||
203 | struct device_node *np = dev->of_node; | ||
204 | struct icn8318_data *data; | ||
205 | struct input_dev *input; | ||
206 | u32 fuzz_x = 0, fuzz_y = 0; | ||
207 | int error; | ||
208 | |||
209 | if (!client->irq) { | ||
210 | dev_err(dev, "Error no irq specified\n"); | ||
211 | return -EINVAL; | ||
212 | } | ||
213 | |||
214 | data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); | ||
215 | if (!data) | ||
216 | return -ENOMEM; | ||
217 | |||
218 | data->wake_gpio = devm_gpiod_get(dev, "wake", GPIOD_OUT_LOW); | ||
219 | if (IS_ERR(data->wake_gpio)) { | ||
220 | error = PTR_ERR(data->wake_gpio); | ||
221 | if (error != -EPROBE_DEFER) | ||
222 | dev_err(dev, "Error getting wake gpio: %d\n", error); | ||
223 | return error; | ||
224 | } | ||
225 | |||
226 | if (of_property_read_u32(np, "touchscreen-size-x", &data->max_x) || | ||
227 | of_property_read_u32(np, "touchscreen-size-y", &data->max_y)) { | ||
228 | dev_err(dev, "Error touchscreen-size-x and/or -y missing\n"); | ||
229 | return -EINVAL; | ||
230 | } | ||
231 | |||
232 | /* Optional */ | ||
233 | of_property_read_u32(np, "touchscreen-fuzz-x", &fuzz_x); | ||
234 | of_property_read_u32(np, "touchscreen-fuzz-y", &fuzz_y); | ||
235 | data->invert_x = of_property_read_bool(np, "touchscreen-inverted-x"); | ||
236 | data->invert_y = of_property_read_bool(np, "touchscreen-inverted-y"); | ||
237 | data->swap_x_y = of_property_read_bool(np, "touchscreen-swapped-x-y"); | ||
238 | |||
239 | input = devm_input_allocate_device(dev); | ||
240 | if (!input) | ||
241 | return -ENOMEM; | ||
242 | |||
243 | input->name = client->name; | ||
244 | input->id.bustype = BUS_I2C; | ||
245 | input->open = icn8318_start; | ||
246 | input->close = icn8318_stop; | ||
247 | input->dev.parent = dev; | ||
248 | |||
249 | if (!data->swap_x_y) { | ||
250 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, | ||
251 | data->max_x, fuzz_x, 0); | ||
252 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, | ||
253 | data->max_y, fuzz_y, 0); | ||
254 | } else { | ||
255 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, | ||
256 | data->max_y, fuzz_y, 0); | ||
257 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, | ||
258 | data->max_x, fuzz_x, 0); | ||
259 | } | ||
260 | |||
261 | error = input_mt_init_slots(input, ICN8318_MAX_TOUCHES, | ||
262 | INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); | ||
263 | if (error) | ||
264 | return error; | ||
265 | |||
266 | data->client = client; | ||
267 | data->input = input; | ||
268 | input_set_drvdata(input, data); | ||
269 | |||
270 | error = devm_request_threaded_irq(dev, client->irq, NULL, icn8318_irq, | ||
271 | IRQF_ONESHOT, client->name, data); | ||
272 | if (error) { | ||
273 | dev_err(dev, "Error requesting irq: %d\n", error); | ||
274 | return error; | ||
275 | } | ||
276 | |||
277 | /* Stop device till opened */ | ||
278 | icn8318_stop(data->input); | ||
279 | |||
280 | error = input_register_device(input); | ||
281 | if (error) | ||
282 | return error; | ||
283 | |||
284 | i2c_set_clientdata(client, data); | ||
285 | |||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static const struct of_device_id icn8318_of_match[] = { | ||
290 | { .compatible = "chipone,icn8318" }, | ||
291 | { } | ||
292 | }; | ||
293 | MODULE_DEVICE_TABLE(of, icn8318_of_match); | ||
294 | |||
295 | /* This is useless for OF-enabled devices, but it is needed by I2C subsystem */ | ||
296 | static const struct i2c_device_id icn8318_i2c_id[] = { | ||
297 | { }, | ||
298 | }; | ||
299 | MODULE_DEVICE_TABLE(i2c, icn8318_i2c_id); | ||
300 | |||
301 | static struct i2c_driver icn8318_driver = { | ||
302 | .driver = { | ||
303 | .owner = THIS_MODULE, | ||
304 | .name = "chipone_icn8318", | ||
305 | .pm = &icn8318_pm_ops, | ||
306 | .of_match_table = icn8318_of_match, | ||
307 | }, | ||
308 | .probe = icn8318_probe, | ||
309 | .id_table = icn8318_i2c_id, | ||
310 | }; | ||
311 | |||
312 | module_i2c_driver(icn8318_driver); | ||
313 | |||
314 | MODULE_DESCRIPTION("ChipOne icn8318 I2C Touchscreen Driver"); | ||
315 | MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); | ||
316 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index d4c24fb7704f..e6aef3e48bd9 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/gpio.h> | 37 | #include <linux/gpio.h> |
38 | #include <linux/of_gpio.h> | 38 | #include <linux/of_gpio.h> |
39 | #include <linux/input/mt.h> | 39 | #include <linux/input/mt.h> |
40 | #include <linux/input/touchscreen.h> | ||
40 | #include <linux/input/edt-ft5x06.h> | 41 | #include <linux/input/edt-ft5x06.h> |
41 | 42 | ||
42 | #define MAX_SUPPORT_POINTS 5 | 43 | #define MAX_SUPPORT_POINTS 5 |
@@ -1034,7 +1035,6 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, | |||
1034 | input->id.bustype = BUS_I2C; | 1035 | input->id.bustype = BUS_I2C; |
1035 | input->dev.parent = &client->dev; | 1036 | input->dev.parent = &client->dev; |
1036 | 1037 | ||
1037 | __set_bit(EV_SYN, input->evbit); | ||
1038 | __set_bit(EV_KEY, input->evbit); | 1038 | __set_bit(EV_KEY, input->evbit); |
1039 | __set_bit(EV_ABS, input->evbit); | 1039 | __set_bit(EV_ABS, input->evbit); |
1040 | __set_bit(BTN_TOUCH, input->keybit); | 1040 | __set_bit(BTN_TOUCH, input->keybit); |
@@ -1044,6 +1044,10 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, | |||
1044 | 0, tsdata->num_x * 64 - 1, 0, 0); | 1044 | 0, tsdata->num_x * 64 - 1, 0, 0); |
1045 | input_set_abs_params(input, ABS_MT_POSITION_Y, | 1045 | input_set_abs_params(input, ABS_MT_POSITION_Y, |
1046 | 0, tsdata->num_y * 64 - 1, 0, 0); | 1046 | 0, tsdata->num_y * 64 - 1, 0, 0); |
1047 | |||
1048 | if (!pdata) | ||
1049 | touchscreen_parse_of_params(input); | ||
1050 | |||
1047 | error = input_mt_init_slots(input, MAX_SUPPORT_POINTS, 0); | 1051 | error = input_mt_init_slots(input, MAX_SUPPORT_POINTS, 0); |
1048 | if (error) { | 1052 | if (error) { |
1049 | dev_err(&client->dev, "Unable to init MT slots.\n"); | 1053 | dev_err(&client->dev, "Unable to init MT slots.\n"); |
diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index 926c58e540c0..43b3c9c2d788 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c | |||
@@ -98,7 +98,6 @@ | |||
98 | #define MAX_FW_UPDATE_RETRIES 30 | 98 | #define MAX_FW_UPDATE_RETRIES 30 |
99 | 99 | ||
100 | #define ELAN_FW_PAGESIZE 132 | 100 | #define ELAN_FW_PAGESIZE 132 |
101 | #define ELAN_FW_FILENAME "elants_i2c.bin" | ||
102 | 101 | ||
103 | /* calibration timeout definition */ | 102 | /* calibration timeout definition */ |
104 | #define ELAN_CALI_TIMEOUT_MSEC 10000 | 103 | #define ELAN_CALI_TIMEOUT_MSEC 10000 |
@@ -697,12 +696,19 @@ static int elants_i2c_fw_update(struct elants_data *ts) | |||
697 | { | 696 | { |
698 | struct i2c_client *client = ts->client; | 697 | struct i2c_client *client = ts->client; |
699 | const struct firmware *fw; | 698 | const struct firmware *fw; |
699 | char *fw_name; | ||
700 | int error; | 700 | int error; |
701 | 701 | ||
702 | error = request_firmware(&fw, ELAN_FW_FILENAME, &client->dev); | 702 | fw_name = kasprintf(GFP_KERNEL, "elants_i2c_%4x.bin", ts->hw_version); |
703 | if (!fw_name) | ||
704 | return -ENOMEM; | ||
705 | |||
706 | dev_info(&client->dev, "requesting fw name = %s\n", fw_name); | ||
707 | error = request_firmware(&fw, fw_name, &client->dev); | ||
708 | kfree(fw_name); | ||
703 | if (error) { | 709 | if (error) { |
704 | dev_err(&client->dev, "failed to request firmware %s: %d\n", | 710 | dev_err(&client->dev, "failed to request firmware: %d\n", |
705 | ELAN_FW_FILENAME, error); | 711 | error); |
706 | return error; | 712 | return error; |
707 | } | 713 | } |
708 | 714 | ||
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index ca196689f025..3af16984d57c 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <linux/irq.h> | 23 | #include <linux/irq.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/acpi.h> | ||
27 | #include <linux/of.h> | ||
26 | #include <asm/unaligned.h> | 28 | #include <asm/unaligned.h> |
27 | 29 | ||
28 | struct goodix_ts_data { | 30 | struct goodix_ts_data { |
@@ -48,6 +50,7 @@ struct goodix_ts_data { | |||
48 | #define GOODIX_REG_VERSION 0x8140 | 50 | #define GOODIX_REG_VERSION 0x8140 |
49 | 51 | ||
50 | #define RESOLUTION_LOC 1 | 52 | #define RESOLUTION_LOC 1 |
53 | #define MAX_CONTACTS_LOC 5 | ||
51 | #define TRIGGER_LOC 6 | 54 | #define TRIGGER_LOC 6 |
52 | 55 | ||
53 | static const unsigned long goodix_irq_flags[] = { | 56 | static const unsigned long goodix_irq_flags[] = { |
@@ -99,7 +102,7 @@ static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data) | |||
99 | } | 102 | } |
100 | 103 | ||
101 | touch_num = data[0] & 0x0f; | 104 | touch_num = data[0] & 0x0f; |
102 | if (touch_num > GOODIX_MAX_CONTACTS) | 105 | if (touch_num > ts->max_touch_num) |
103 | return -EPROTO; | 106 | return -EPROTO; |
104 | 107 | ||
105 | if (touch_num > 1) { | 108 | if (touch_num > 1) { |
@@ -141,7 +144,7 @@ static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data) | |||
141 | */ | 144 | */ |
142 | static void goodix_process_events(struct goodix_ts_data *ts) | 145 | static void goodix_process_events(struct goodix_ts_data *ts) |
143 | { | 146 | { |
144 | u8 point_data[1 + GOODIX_CONTACT_SIZE * GOODIX_MAX_CONTACTS]; | 147 | u8 point_data[1 + GOODIX_CONTACT_SIZE * ts->max_touch_num]; |
145 | int touch_num; | 148 | int touch_num; |
146 | int i; | 149 | int i; |
147 | 150 | ||
@@ -202,21 +205,23 @@ static void goodix_read_config(struct goodix_ts_data *ts) | |||
202 | ts->abs_x_max = GOODIX_MAX_WIDTH; | 205 | ts->abs_x_max = GOODIX_MAX_WIDTH; |
203 | ts->abs_y_max = GOODIX_MAX_HEIGHT; | 206 | ts->abs_y_max = GOODIX_MAX_HEIGHT; |
204 | ts->int_trigger_type = GOODIX_INT_TRIGGER; | 207 | ts->int_trigger_type = GOODIX_INT_TRIGGER; |
208 | ts->max_touch_num = GOODIX_MAX_CONTACTS; | ||
205 | return; | 209 | return; |
206 | } | 210 | } |
207 | 211 | ||
208 | ts->abs_x_max = get_unaligned_le16(&config[RESOLUTION_LOC]); | 212 | ts->abs_x_max = get_unaligned_le16(&config[RESOLUTION_LOC]); |
209 | ts->abs_y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]); | 213 | ts->abs_y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]); |
210 | ts->int_trigger_type = (config[TRIGGER_LOC]) & 0x03; | 214 | ts->int_trigger_type = config[TRIGGER_LOC] & 0x03; |
211 | if (!ts->abs_x_max || !ts->abs_y_max) { | 215 | ts->max_touch_num = config[MAX_CONTACTS_LOC] & 0x0f; |
216 | if (!ts->abs_x_max || !ts->abs_y_max || !ts->max_touch_num) { | ||
212 | dev_err(&ts->client->dev, | 217 | dev_err(&ts->client->dev, |
213 | "Invalid config, using defaults\n"); | 218 | "Invalid config, using defaults\n"); |
214 | ts->abs_x_max = GOODIX_MAX_WIDTH; | 219 | ts->abs_x_max = GOODIX_MAX_WIDTH; |
215 | ts->abs_y_max = GOODIX_MAX_HEIGHT; | 220 | ts->abs_y_max = GOODIX_MAX_HEIGHT; |
221 | ts->max_touch_num = GOODIX_MAX_CONTACTS; | ||
216 | } | 222 | } |
217 | } | 223 | } |
218 | 224 | ||
219 | |||
220 | /** | 225 | /** |
221 | * goodix_read_version - Read goodix touchscreen version | 226 | * goodix_read_version - Read goodix touchscreen version |
222 | * | 227 | * |
@@ -295,7 +300,7 @@ static int goodix_request_input_dev(struct goodix_ts_data *ts) | |||
295 | input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); | 300 | input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); |
296 | input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); | 301 | input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); |
297 | 302 | ||
298 | input_mt_init_slots(ts->input_dev, GOODIX_MAX_CONTACTS, | 303 | input_mt_init_slots(ts->input_dev, ts->max_touch_num, |
299 | INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); | 304 | INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); |
300 | 305 | ||
301 | ts->input_dev->name = "Goodix Capacitive TouchScreen"; | 306 | ts->input_dev->name = "Goodix Capacitive TouchScreen"; |
@@ -372,11 +377,27 @@ static const struct i2c_device_id goodix_ts_id[] = { | |||
372 | { } | 377 | { } |
373 | }; | 378 | }; |
374 | 379 | ||
380 | #ifdef CONFIG_ACPI | ||
375 | static const struct acpi_device_id goodix_acpi_match[] = { | 381 | static const struct acpi_device_id goodix_acpi_match[] = { |
376 | { "GDIX1001", 0 }, | 382 | { "GDIX1001", 0 }, |
377 | { } | 383 | { } |
378 | }; | 384 | }; |
379 | MODULE_DEVICE_TABLE(acpi, goodix_acpi_match); | 385 | MODULE_DEVICE_TABLE(acpi, goodix_acpi_match); |
386 | #endif | ||
387 | |||
388 | #ifdef CONFIG_OF | ||
389 | static const struct of_device_id goodix_of_match[] = { | ||
390 | { .compatible = "goodix,gt911" }, | ||
391 | { .compatible = "goodix,gt9110" }, | ||
392 | { .compatible = "goodix,gt912" }, | ||
393 | { .compatible = "goodix,gt927" }, | ||
394 | { .compatible = "goodix,gt9271" }, | ||
395 | { .compatible = "goodix,gt928" }, | ||
396 | { .compatible = "goodix,gt967" }, | ||
397 | { } | ||
398 | }; | ||
399 | MODULE_DEVICE_TABLE(of, goodix_of_match); | ||
400 | #endif | ||
380 | 401 | ||
381 | static struct i2c_driver goodix_ts_driver = { | 402 | static struct i2c_driver goodix_ts_driver = { |
382 | .probe = goodix_ts_probe, | 403 | .probe = goodix_ts_probe, |
@@ -384,7 +405,8 @@ static struct i2c_driver goodix_ts_driver = { | |||
384 | .driver = { | 405 | .driver = { |
385 | .name = "Goodix-TS", | 406 | .name = "Goodix-TS", |
386 | .owner = THIS_MODULE, | 407 | .owner = THIS_MODULE, |
387 | .acpi_match_table = goodix_acpi_match, | 408 | .acpi_match_table = ACPI_PTR(goodix_acpi_match), |
409 | .of_match_table = of_match_ptr(goodix_of_match), | ||
388 | }, | 410 | }, |
389 | }; | 411 | }; |
390 | module_i2c_driver(goodix_ts_driver); | 412 | module_i2c_driver(goodix_ts_driver); |
diff --git a/drivers/input/touchscreen/of_touchscreen.c b/drivers/input/touchscreen/of_touchscreen.c index f8f9b84230b1..b82b5207c78b 100644 --- a/drivers/input/touchscreen/of_touchscreen.c +++ b/drivers/input/touchscreen/of_touchscreen.c | |||
@@ -11,8 +11,41 @@ | |||
11 | 11 | ||
12 | #include <linux/of.h> | 12 | #include <linux/of.h> |
13 | #include <linux/input.h> | 13 | #include <linux/input.h> |
14 | #include <linux/input/mt.h> | ||
14 | #include <linux/input/touchscreen.h> | 15 | #include <linux/input/touchscreen.h> |
15 | 16 | ||
17 | static u32 of_get_optional_u32(struct device_node *np, | ||
18 | const char *property) | ||
19 | { | ||
20 | u32 val = 0; | ||
21 | |||
22 | of_property_read_u32(np, property, &val); | ||
23 | |||
24 | return val; | ||
25 | } | ||
26 | |||
27 | static void touchscreen_set_params(struct input_dev *dev, | ||
28 | unsigned long axis, | ||
29 | int max, int fuzz) | ||
30 | { | ||
31 | struct input_absinfo *absinfo; | ||
32 | |||
33 | if (!test_bit(axis, dev->absbit)) { | ||
34 | /* | ||
35 | * Emit a warning only if the axis is not a multitouch | ||
36 | * axis, which might not be set by the driver. | ||
37 | */ | ||
38 | if (!input_is_mt_axis(axis)) | ||
39 | dev_warn(&dev->dev, | ||
40 | "DT specifies parameters but the axis is not set up\n"); | ||
41 | return; | ||
42 | } | ||
43 | |||
44 | absinfo = &dev->absinfo[axis]; | ||
45 | absinfo->maximum = max; | ||
46 | absinfo->fuzz = fuzz; | ||
47 | } | ||
48 | |||
16 | /** | 49 | /** |
17 | * touchscreen_parse_of_params - parse common touchscreen DT properties | 50 | * touchscreen_parse_of_params - parse common touchscreen DT properties |
18 | * @dev: device that should be parsed | 51 | * @dev: device that should be parsed |
@@ -24,22 +57,31 @@ | |||
24 | void touchscreen_parse_of_params(struct input_dev *dev) | 57 | void touchscreen_parse_of_params(struct input_dev *dev) |
25 | { | 58 | { |
26 | struct device_node *np = dev->dev.parent->of_node; | 59 | struct device_node *np = dev->dev.parent->of_node; |
27 | struct input_absinfo *absinfo; | 60 | u32 maximum, fuzz; |
28 | 61 | ||
29 | input_alloc_absinfo(dev); | 62 | input_alloc_absinfo(dev); |
30 | if (!dev->absinfo) | 63 | if (!dev->absinfo) |
31 | return; | 64 | return; |
32 | 65 | ||
33 | absinfo = &dev->absinfo[ABS_X]; | 66 | maximum = of_get_optional_u32(np, "touchscreen-size-x"); |
34 | of_property_read_u32(np, "touchscreen-size-x", &absinfo->maximum); | 67 | fuzz = of_get_optional_u32(np, "touchscreen-fuzz-x"); |
35 | of_property_read_u32(np, "touchscreen-fuzz-x", &absinfo->fuzz); | 68 | if (maximum || fuzz) { |
69 | touchscreen_set_params(dev, ABS_X, maximum, fuzz); | ||
70 | touchscreen_set_params(dev, ABS_MT_POSITION_X, maximum, fuzz); | ||
71 | } | ||
36 | 72 | ||
37 | absinfo = &dev->absinfo[ABS_Y]; | 73 | maximum = of_get_optional_u32(np, "touchscreen-size-y"); |
38 | of_property_read_u32(np, "touchscreen-size-y", &absinfo->maximum); | 74 | fuzz = of_get_optional_u32(np, "touchscreen-fuzz-y"); |
39 | of_property_read_u32(np, "touchscreen-fuzz-y", &absinfo->fuzz); | 75 | if (maximum || fuzz) { |
76 | touchscreen_set_params(dev, ABS_Y, maximum, fuzz); | ||
77 | touchscreen_set_params(dev, ABS_MT_POSITION_Y, maximum, fuzz); | ||
78 | } | ||
40 | 79 | ||
41 | absinfo = &dev->absinfo[ABS_PRESSURE]; | 80 | maximum = of_get_optional_u32(np, "touchscreen-max-pressure"); |
42 | of_property_read_u32(np, "touchscreen-max-pressure", &absinfo->maximum); | 81 | fuzz = of_get_optional_u32(np, "touchscreen-fuzz-pressure"); |
43 | of_property_read_u32(np, "touchscreen-fuzz-pressure", &absinfo->fuzz); | 82 | if (maximum || fuzz) { |
83 | touchscreen_set_params(dev, ABS_PRESSURE, maximum, fuzz); | ||
84 | touchscreen_set_params(dev, ABS_MT_PRESSURE, maximum, fuzz); | ||
85 | } | ||
44 | } | 86 | } |
45 | EXPORT_SYMBOL(touchscreen_parse_of_params); | 87 | EXPORT_SYMBOL(touchscreen_parse_of_params); |
diff --git a/drivers/input/touchscreen/sun4i-ts.c b/drivers/input/touchscreen/sun4i-ts.c index b93a28b955fd..c0116994067d 100644 --- a/drivers/input/touchscreen/sun4i-ts.c +++ b/drivers/input/touchscreen/sun4i-ts.c | |||
@@ -30,6 +30,10 @@ | |||
30 | * These kinds of heuristics are just asking for trouble (and don't belong | 30 | * These kinds of heuristics are just asking for trouble (and don't belong |
31 | * in the kernel). So this driver offers straight forward, reliable single | 31 | * in the kernel). So this driver offers straight forward, reliable single |
32 | * touch functionality only. | 32 | * touch functionality only. |
33 | * | ||
34 | * s.a. A20 User Manual "1.15 TP" (Documentation/arm/sunxi/README) | ||
35 | * (looks like the description in the A20 User Manual v1.3 is better | ||
36 | * than the one in the A10 User Manual v.1.5) | ||
33 | */ | 37 | */ |
34 | 38 | ||
35 | #include <linux/err.h> | 39 | #include <linux/err.h> |
@@ -193,7 +197,7 @@ static int sun4i_get_temp(const struct sun4i_ts_data *ts, long *temp) | |||
193 | if (ts->temp_data == -1) | 197 | if (ts->temp_data == -1) |
194 | return -EAGAIN; | 198 | return -EAGAIN; |
195 | 199 | ||
196 | *temp = (ts->temp_data - ts->temp_offset) * ts->temp_step; | 200 | *temp = ts->temp_data * ts->temp_step - ts->temp_offset; |
197 | 201 | ||
198 | return 0; | 202 | return 0; |
199 | } | 203 | } |
@@ -246,6 +250,8 @@ static int sun4i_ts_probe(struct platform_device *pdev) | |||
246 | int error; | 250 | int error; |
247 | u32 reg; | 251 | u32 reg; |
248 | bool ts_attached; | 252 | bool ts_attached; |
253 | u32 tp_sensitive_adjust = 15; | ||
254 | u32 filter_type = 1; | ||
249 | 255 | ||
250 | ts = devm_kzalloc(dev, sizeof(struct sun4i_ts_data), GFP_KERNEL); | 256 | ts = devm_kzalloc(dev, sizeof(struct sun4i_ts_data), GFP_KERNEL); |
251 | if (!ts) | 257 | if (!ts) |
@@ -255,22 +261,31 @@ static int sun4i_ts_probe(struct platform_device *pdev) | |||
255 | ts->ignore_fifo_data = true; | 261 | ts->ignore_fifo_data = true; |
256 | ts->temp_data = -1; | 262 | ts->temp_data = -1; |
257 | if (of_device_is_compatible(np, "allwinner,sun6i-a31-ts")) { | 263 | if (of_device_is_compatible(np, "allwinner,sun6i-a31-ts")) { |
258 | /* Allwinner SDK has temperature = -271 + (value / 6) (C) */ | 264 | /* Allwinner SDK has temperature (C) = (value / 6) - 271 */ |
259 | ts->temp_offset = 1626; | 265 | ts->temp_offset = 271000; |
260 | ts->temp_step = 167; | 266 | ts->temp_step = 167; |
267 | } else if (of_device_is_compatible(np, "allwinner,sun4i-a10-ts")) { | ||
268 | /* | ||
269 | * The A10 temperature sensor has quite a wide spread, these | ||
270 | * parameters are based on the averaging of the calibration | ||
271 | * results of 4 completely different boards, with a spread of | ||
272 | * temp_step from 0.096 - 0.170 and temp_offset from 176 - 331. | ||
273 | */ | ||
274 | ts->temp_offset = 257000; | ||
275 | ts->temp_step = 133; | ||
261 | } else { | 276 | } else { |
262 | /* | 277 | /* |
263 | * The user manuals do not contain the formula for calculating | 278 | * The user manuals do not contain the formula for calculating |
264 | * the temperature. The formula used here is from the AXP209, | 279 | * the temperature. The formula used here is from the AXP209, |
265 | * which is designed by X-Powers, an affiliate of Allwinner: | 280 | * which is designed by X-Powers, an affiliate of Allwinner: |
266 | * | 281 | * |
267 | * temperature = -144.7 + (value * 0.1) | 282 | * temperature (C) = (value * 0.1) - 144.7 |
268 | * | 283 | * |
269 | * Allwinner does not have any documentation whatsoever for | 284 | * Allwinner does not have any documentation whatsoever for |
270 | * this hardware. Moreover, it is claimed that the sensor | 285 | * this hardware. Moreover, it is claimed that the sensor |
271 | * is inaccurate and cannot work properly. | 286 | * is inaccurate and cannot work properly. |
272 | */ | 287 | */ |
273 | ts->temp_offset = 1447; | 288 | ts->temp_offset = 144700; |
274 | ts->temp_step = 100; | 289 | ts->temp_step = 100; |
275 | } | 290 | } |
276 | 291 | ||
@@ -313,14 +328,20 @@ static int sun4i_ts_probe(struct platform_device *pdev) | |||
313 | ts->base + TP_CTRL0); | 328 | ts->base + TP_CTRL0); |
314 | 329 | ||
315 | /* | 330 | /* |
316 | * sensitive_adjust = 15 : max, which is not all that sensitive, | 331 | * tp_sensitive_adjust is an optional property |
317 | * tp_mode = 0 : only x and y coordinates, as we don't use dual touch | 332 | * tp_mode = 0 : only x and y coordinates, as we don't use dual touch |
318 | */ | 333 | */ |
319 | writel(TP_SENSITIVE_ADJUST(15) | TP_MODE_SELECT(0), | 334 | of_property_read_u32(np, "allwinner,tp-sensitive-adjust", |
335 | &tp_sensitive_adjust); | ||
336 | writel(TP_SENSITIVE_ADJUST(tp_sensitive_adjust) | TP_MODE_SELECT(0), | ||
320 | ts->base + TP_CTRL2); | 337 | ts->base + TP_CTRL2); |
321 | 338 | ||
322 | /* Enable median filter, type 1 : 5/3 */ | 339 | /* |
323 | writel(FILTER_EN(1) | FILTER_TYPE(1), ts->base + TP_CTRL3); | 340 | * Enable median and averaging filter, optional property for |
341 | * filter type. | ||
342 | */ | ||
343 | of_property_read_u32(np, "allwinner,filter-type", &filter_type); | ||
344 | writel(FILTER_EN(1) | FILTER_TYPE(filter_type), ts->base + TP_CTRL3); | ||
324 | 345 | ||
325 | /* Enable temperature measurement, period 1953 (2 seconds) */ | 346 | /* Enable temperature measurement, period 1953 (2 seconds) */ |
326 | writel(TEMP_ENABLE(1) | TEMP_PERIOD(1953), ts->base + TP_TPR); | 347 | writel(TEMP_ENABLE(1) | TEMP_PERIOD(1953), ts->base + TP_TPR); |
@@ -330,10 +351,10 @@ static int sun4i_ts_probe(struct platform_device *pdev) | |||
330 | * finally enable tp mode. | 351 | * finally enable tp mode. |
331 | */ | 352 | */ |
332 | reg = STYLUS_UP_DEBOUN(5) | STYLUS_UP_DEBOUN_EN(1); | 353 | reg = STYLUS_UP_DEBOUN(5) | STYLUS_UP_DEBOUN_EN(1); |
333 | if (of_device_is_compatible(np, "allwinner,sun4i-a10-ts")) | 354 | if (of_device_is_compatible(np, "allwinner,sun6i-a31-ts")) |
334 | reg |= TP_MODE_EN(1); | ||
335 | else | ||
336 | reg |= SUN6I_TP_MODE_EN(1); | 355 | reg |= SUN6I_TP_MODE_EN(1); |
356 | else | ||
357 | reg |= TP_MODE_EN(1); | ||
337 | writel(reg, ts->base + TP_CTRL1); | 358 | writel(reg, ts->base + TP_CTRL1); |
338 | 359 | ||
339 | /* | 360 | /* |
@@ -383,6 +404,7 @@ static int sun4i_ts_remove(struct platform_device *pdev) | |||
383 | 404 | ||
384 | static const struct of_device_id sun4i_ts_of_match[] = { | 405 | static const struct of_device_id sun4i_ts_of_match[] = { |
385 | { .compatible = "allwinner,sun4i-a10-ts", }, | 406 | { .compatible = "allwinner,sun4i-a10-ts", }, |
407 | { .compatible = "allwinner,sun5i-a13-ts", }, | ||
386 | { .compatible = "allwinner,sun6i-a31-ts", }, | 408 | { .compatible = "allwinner,sun6i-a31-ts", }, |
387 | { /* sentinel */ } | 409 | { /* sentinel */ } |
388 | }; | 410 | }; |
diff --git a/drivers/input/touchscreen/sx8654.c b/drivers/input/touchscreen/sx8654.c new file mode 100644 index 000000000000..aecb9ad2e701 --- /dev/null +++ b/drivers/input/touchscreen/sx8654.c | |||
@@ -0,0 +1,286 @@ | |||
1 | /* | ||
2 | * Driver for Semtech SX8654 I2C touchscreen controller. | ||
3 | * | ||
4 | * Copyright (c) 2015 Armadeus Systems | ||
5 | * Sébastien Szymanski <sebastien.szymanski@armadeus.com> | ||
6 | * | ||
7 | * Using code from: | ||
8 | * - sx865x.c | ||
9 | * Copyright (c) 2013 U-MoBo Srl | ||
10 | * Pierluigi Passaro <p.passaro@u-mobo.com> | ||
11 | * - sx8650.c | ||
12 | * Copyright (c) 2009 Wayne Roberts | ||
13 | * - tsc2007.c | ||
14 | * Copyright (c) 2008 Kwangwoo Lee | ||
15 | * - ads7846.c | ||
16 | * Copyright (c) 2005 David Brownell | ||
17 | * Copyright (c) 2006 Nokia Corporation | ||
18 | * - corgi_ts.c | ||
19 | * Copyright (C) 2004-2005 Richard Purdie | ||
20 | * - omap_ts.[hc], ads7846.h, ts_osk.c | ||
21 | * Copyright (C) 2002 MontaVista Software | ||
22 | * Copyright (C) 2004 Texas Instruments | ||
23 | * Copyright (C) 2005 Dirk Behme | ||
24 | * | ||
25 | * This program is free software; you can redistribute it and/or modify | ||
26 | * it under the terms of the GNU General Public License version 2 as | ||
27 | * published by the Free Software Foundation. | ||
28 | */ | ||
29 | |||
30 | #include <linux/input.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/of.h> | ||
33 | #include <linux/i2c.h> | ||
34 | #include <linux/interrupt.h> | ||
35 | #include <linux/irq.h> | ||
36 | |||
37 | /* register addresses */ | ||
38 | #define I2C_REG_TOUCH0 0x00 | ||
39 | #define I2C_REG_TOUCH1 0x01 | ||
40 | #define I2C_REG_CHANMASK 0x04 | ||
41 | #define I2C_REG_IRQMASK 0x22 | ||
42 | #define I2C_REG_IRQSRC 0x23 | ||
43 | #define I2C_REG_SOFTRESET 0x3f | ||
44 | |||
45 | /* commands */ | ||
46 | #define CMD_READ_REGISTER 0x40 | ||
47 | #define CMD_MANUAL 0xc0 | ||
48 | #define CMD_PENTRG 0xe0 | ||
49 | |||
50 | /* value for I2C_REG_SOFTRESET */ | ||
51 | #define SOFTRESET_VALUE 0xde | ||
52 | |||
53 | /* bits for I2C_REG_IRQSRC */ | ||
54 | #define IRQ_PENTOUCH_TOUCHCONVDONE 0x08 | ||
55 | #define IRQ_PENRELEASE 0x04 | ||
56 | |||
57 | /* bits for RegTouch1 */ | ||
58 | #define CONDIRQ 0x20 | ||
59 | #define FILT_7SA 0x03 | ||
60 | |||
61 | /* bits for I2C_REG_CHANMASK */ | ||
62 | #define CONV_X 0x80 | ||
63 | #define CONV_Y 0x40 | ||
64 | |||
65 | /* coordinates rate: higher nibble of CTRL0 register */ | ||
66 | #define RATE_MANUAL 0x00 | ||
67 | #define RATE_5000CPS 0xf0 | ||
68 | |||
69 | /* power delay: lower nibble of CTRL0 register */ | ||
70 | #define POWDLY_1_1MS 0x0b | ||
71 | |||
72 | #define MAX_12BIT ((1 << 12) - 1) | ||
73 | |||
74 | struct sx8654 { | ||
75 | struct input_dev *input; | ||
76 | struct i2c_client *client; | ||
77 | }; | ||
78 | |||
79 | static irqreturn_t sx8654_irq(int irq, void *handle) | ||
80 | { | ||
81 | struct sx8654 *sx8654 = handle; | ||
82 | int irqsrc; | ||
83 | u8 data[4]; | ||
84 | unsigned int x, y; | ||
85 | int retval; | ||
86 | |||
87 | irqsrc = i2c_smbus_read_byte_data(sx8654->client, | ||
88 | CMD_READ_REGISTER | I2C_REG_IRQSRC); | ||
89 | dev_dbg(&sx8654->client->dev, "irqsrc = 0x%x", irqsrc); | ||
90 | |||
91 | if (irqsrc < 0) | ||
92 | goto out; | ||
93 | |||
94 | if (irqsrc & IRQ_PENRELEASE) { | ||
95 | dev_dbg(&sx8654->client->dev, "pen release interrupt"); | ||
96 | |||
97 | input_report_key(sx8654->input, BTN_TOUCH, 0); | ||
98 | input_sync(sx8654->input); | ||
99 | } | ||
100 | |||
101 | if (irqsrc & IRQ_PENTOUCH_TOUCHCONVDONE) { | ||
102 | dev_dbg(&sx8654->client->dev, "pen touch interrupt"); | ||
103 | |||
104 | retval = i2c_master_recv(sx8654->client, data, sizeof(data)); | ||
105 | if (retval != sizeof(data)) | ||
106 | goto out; | ||
107 | |||
108 | /* invalid data */ | ||
109 | if (unlikely(data[0] & 0x80 || data[2] & 0x80)) | ||
110 | goto out; | ||
111 | |||
112 | x = ((data[0] & 0xf) << 8) | (data[1]); | ||
113 | y = ((data[2] & 0xf) << 8) | (data[3]); | ||
114 | |||
115 | input_report_abs(sx8654->input, ABS_X, x); | ||
116 | input_report_abs(sx8654->input, ABS_Y, y); | ||
117 | input_report_key(sx8654->input, BTN_TOUCH, 1); | ||
118 | input_sync(sx8654->input); | ||
119 | |||
120 | dev_dbg(&sx8654->client->dev, "point(%4d,%4d)\n", x, y); | ||
121 | } | ||
122 | |||
123 | out: | ||
124 | return IRQ_HANDLED; | ||
125 | } | ||
126 | |||
127 | static int sx8654_open(struct input_dev *dev) | ||
128 | { | ||
129 | struct sx8654 *sx8654 = input_get_drvdata(dev); | ||
130 | struct i2c_client *client = sx8654->client; | ||
131 | int error; | ||
132 | |||
133 | /* enable pen trigger mode */ | ||
134 | error = i2c_smbus_write_byte_data(client, I2C_REG_TOUCH0, | ||
135 | RATE_5000CPS | POWDLY_1_1MS); | ||
136 | if (error) { | ||
137 | dev_err(&client->dev, "writing to I2C_REG_TOUCH0 failed"); | ||
138 | return error; | ||
139 | } | ||
140 | |||
141 | error = i2c_smbus_write_byte(client, CMD_PENTRG); | ||
142 | if (error) { | ||
143 | dev_err(&client->dev, "writing command CMD_PENTRG failed"); | ||
144 | return error; | ||
145 | } | ||
146 | |||
147 | enable_irq(client->irq); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static void sx8654_close(struct input_dev *dev) | ||
153 | { | ||
154 | struct sx8654 *sx8654 = input_get_drvdata(dev); | ||
155 | struct i2c_client *client = sx8654->client; | ||
156 | int error; | ||
157 | |||
158 | disable_irq(client->irq); | ||
159 | |||
160 | /* enable manual mode mode */ | ||
161 | error = i2c_smbus_write_byte(client, CMD_MANUAL); | ||
162 | if (error) { | ||
163 | dev_err(&client->dev, "writing command CMD_MANUAL failed"); | ||
164 | return; | ||
165 | } | ||
166 | |||
167 | error = i2c_smbus_write_byte_data(client, I2C_REG_TOUCH0, 0); | ||
168 | if (error) { | ||
169 | dev_err(&client->dev, "writing to I2C_REG_TOUCH0 failed"); | ||
170 | return; | ||
171 | } | ||
172 | } | ||
173 | |||
174 | static int sx8654_probe(struct i2c_client *client, | ||
175 | const struct i2c_device_id *id) | ||
176 | { | ||
177 | struct sx8654 *sx8654; | ||
178 | struct input_dev *input; | ||
179 | int error; | ||
180 | |||
181 | if (!i2c_check_functionality(client->adapter, | ||
182 | I2C_FUNC_SMBUS_READ_WORD_DATA)) | ||
183 | return -ENXIO; | ||
184 | |||
185 | sx8654 = devm_kzalloc(&client->dev, sizeof(*sx8654), GFP_KERNEL); | ||
186 | if (!sx8654) | ||
187 | return -ENOMEM; | ||
188 | |||
189 | input = devm_input_allocate_device(&client->dev); | ||
190 | if (!sx8654) | ||
191 | return -ENOMEM; | ||
192 | |||
193 | input->name = "SX8654 I2C Touchscreen"; | ||
194 | input->id.bustype = BUS_I2C; | ||
195 | input->dev.parent = &client->dev; | ||
196 | input->open = sx8654_open; | ||
197 | input->close = sx8654_close; | ||
198 | |||
199 | __set_bit(INPUT_PROP_DIRECT, input->propbit); | ||
200 | input_set_capability(input, EV_KEY, BTN_TOUCH); | ||
201 | input_set_abs_params(input, ABS_X, 0, MAX_12BIT, 0, 0); | ||
202 | input_set_abs_params(input, ABS_Y, 0, MAX_12BIT, 0, 0); | ||
203 | |||
204 | sx8654->client = client; | ||
205 | sx8654->input = input; | ||
206 | |||
207 | input_set_drvdata(sx8654->input, sx8654); | ||
208 | |||
209 | error = i2c_smbus_write_byte_data(client, I2C_REG_SOFTRESET, | ||
210 | SOFTRESET_VALUE); | ||
211 | if (error) { | ||
212 | dev_err(&client->dev, "writing softreset value failed"); | ||
213 | return error; | ||
214 | } | ||
215 | |||
216 | error = i2c_smbus_write_byte_data(client, I2C_REG_CHANMASK, | ||
217 | CONV_X | CONV_Y); | ||
218 | if (error) { | ||
219 | dev_err(&client->dev, "writing to I2C_REG_CHANMASK failed"); | ||
220 | return error; | ||
221 | } | ||
222 | |||
223 | error = i2c_smbus_write_byte_data(client, I2C_REG_IRQMASK, | ||
224 | IRQ_PENTOUCH_TOUCHCONVDONE | | ||
225 | IRQ_PENRELEASE); | ||
226 | if (error) { | ||
227 | dev_err(&client->dev, "writing to I2C_REG_IRQMASK failed"); | ||
228 | return error; | ||
229 | } | ||
230 | |||
231 | error = i2c_smbus_write_byte_data(client, I2C_REG_TOUCH1, | ||
232 | CONDIRQ | FILT_7SA); | ||
233 | if (error) { | ||
234 | dev_err(&client->dev, "writing to I2C_REG_TOUCH1 failed"); | ||
235 | return error; | ||
236 | } | ||
237 | |||
238 | error = devm_request_threaded_irq(&client->dev, client->irq, | ||
239 | NULL, sx8654_irq, | ||
240 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
241 | client->name, sx8654); | ||
242 | if (error) { | ||
243 | dev_err(&client->dev, | ||
244 | "Failed to enable IRQ %d, error: %d\n", | ||
245 | client->irq, error); | ||
246 | return error; | ||
247 | } | ||
248 | |||
249 | /* Disable the IRQ, we'll enable it in sx8654_open() */ | ||
250 | disable_irq(client->irq); | ||
251 | |||
252 | error = input_register_device(sx8654->input); | ||
253 | if (error) | ||
254 | return error; | ||
255 | |||
256 | i2c_set_clientdata(client, sx8654); | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | #ifdef CONFIG_OF | ||
261 | static const struct of_device_id sx8654_of_match[] = { | ||
262 | { .compatible = "semtech,sx8654", }, | ||
263 | { }, | ||
264 | }; | ||
265 | MODULE_DEVICE_TABLE(of, sx8654_of_match); | ||
266 | #endif | ||
267 | |||
268 | static const struct i2c_device_id sx8654_id_table[] = { | ||
269 | { "semtech_sx8654", 0 }, | ||
270 | { }, | ||
271 | }; | ||
272 | MODULE_DEVICE_TABLE(i2c, sx8654_id_table); | ||
273 | |||
274 | static struct i2c_driver sx8654_driver = { | ||
275 | .driver = { | ||
276 | .name = "sx8654", | ||
277 | .of_match_table = of_match_ptr(sx8654_of_match), | ||
278 | }, | ||
279 | .id_table = sx8654_id_table, | ||
280 | .probe = sx8654_probe, | ||
281 | }; | ||
282 | module_i2c_driver(sx8654_driver); | ||
283 | |||
284 | MODULE_AUTHOR("Sébastien Szymanski <sebastien.szymanski@armadeus.com>"); | ||
285 | MODULE_DESCRIPTION("Semtech SX8654 I2C Touchscreen Driver"); | ||
286 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index 1bf9906b5a3f..ccc8aa615709 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c | |||
@@ -75,7 +75,7 @@ struct tsc2007 { | |||
75 | u16 model; | 75 | u16 model; |
76 | u16 x_plate_ohms; | 76 | u16 x_plate_ohms; |
77 | u16 max_rt; | 77 | u16 max_rt; |
78 | unsigned long poll_period; | 78 | unsigned long poll_period; /* in jiffies */ |
79 | int fuzzx; | 79 | int fuzzx; |
80 | int fuzzy; | 80 | int fuzzy; |
81 | int fuzzz; | 81 | int fuzzz; |
@@ -214,8 +214,7 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle) | |||
214 | dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt); | 214 | dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt); |
215 | } | 215 | } |
216 | 216 | ||
217 | wait_event_timeout(ts->wait, ts->stopped, | 217 | wait_event_timeout(ts->wait, ts->stopped, ts->poll_period); |
218 | msecs_to_jiffies(ts->poll_period)); | ||
219 | } | 218 | } |
220 | 219 | ||
221 | dev_dbg(&ts->client->dev, "UP\n"); | 220 | dev_dbg(&ts->client->dev, "UP\n"); |
@@ -314,9 +313,9 @@ static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts) | |||
314 | ts->fuzzz = val32; | 313 | ts->fuzzz = val32; |
315 | 314 | ||
316 | if (!of_property_read_u64(np, "ti,poll-period", &val64)) | 315 | if (!of_property_read_u64(np, "ti,poll-period", &val64)) |
317 | ts->poll_period = val64; | 316 | ts->poll_period = msecs_to_jiffies(val64); |
318 | else | 317 | else |
319 | ts->poll_period = 1; | 318 | ts->poll_period = msecs_to_jiffies(1); |
320 | 319 | ||
321 | if (!of_property_read_u32(np, "ti,x-plate-ohms", &val32)) { | 320 | if (!of_property_read_u32(np, "ti,x-plate-ohms", &val32)) { |
322 | ts->x_plate_ohms = val32; | 321 | ts->x_plate_ohms = val32; |
@@ -350,7 +349,7 @@ static int tsc2007_probe_pdev(struct i2c_client *client, struct tsc2007 *ts, | |||
350 | ts->model = pdata->model; | 349 | ts->model = pdata->model; |
351 | ts->x_plate_ohms = pdata->x_plate_ohms; | 350 | ts->x_plate_ohms = pdata->x_plate_ohms; |
352 | ts->max_rt = pdata->max_rt ? : MAX_12BIT; | 351 | ts->max_rt = pdata->max_rt ? : MAX_12BIT; |
353 | ts->poll_period = pdata->poll_period ? : 1; | 352 | ts->poll_period = msecs_to_jiffies(pdata->poll_period ? : 1); |
354 | ts->get_pendown_state = pdata->get_pendown_state; | 353 | ts->get_pendown_state = pdata->get_pendown_state; |
355 | ts->clear_penirq = pdata->clear_penirq; | 354 | ts->clear_penirq = pdata->clear_penirq; |
356 | ts->fuzzx = pdata->fuzzx; | 355 | ts->fuzzx = pdata->fuzzx; |
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index a0966331a89b..f2c6c352c55a 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c | |||
@@ -132,6 +132,7 @@ enum { | |||
132 | DEVTYPE_GUNZE, | 132 | DEVTYPE_GUNZE, |
133 | DEVTYPE_DMC_TSC10, | 133 | DEVTYPE_DMC_TSC10, |
134 | DEVTYPE_IRTOUCH, | 134 | DEVTYPE_IRTOUCH, |
135 | DEVTYPE_IRTOUCH_HIRES, | ||
135 | DEVTYPE_IDEALTEK, | 136 | DEVTYPE_IDEALTEK, |
136 | DEVTYPE_GENERAL_TOUCH, | 137 | DEVTYPE_GENERAL_TOUCH, |
137 | DEVTYPE_GOTOP, | 138 | DEVTYPE_GOTOP, |
@@ -198,6 +199,7 @@ static const struct usb_device_id usbtouch_devices[] = { | |||
198 | #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH | 199 | #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH |
199 | {USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, | 200 | {USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, |
200 | {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, | 201 | {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, |
202 | {USB_DEVICE(0x6615, 0x0012), .driver_info = DEVTYPE_IRTOUCH_HIRES}, | ||
201 | #endif | 203 | #endif |
202 | 204 | ||
203 | #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK | 205 | #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK |
@@ -1177,6 +1179,15 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { | |||
1177 | .rept_size = 8, | 1179 | .rept_size = 8, |
1178 | .read_data = irtouch_read_data, | 1180 | .read_data = irtouch_read_data, |
1179 | }, | 1181 | }, |
1182 | |||
1183 | [DEVTYPE_IRTOUCH_HIRES] = { | ||
1184 | .min_xc = 0x0, | ||
1185 | .max_xc = 0x7fff, | ||
1186 | .min_yc = 0x0, | ||
1187 | .max_yc = 0x7fff, | ||
1188 | .rept_size = 8, | ||
1189 | .read_data = irtouch_read_data, | ||
1190 | }, | ||
1180 | #endif | 1191 | #endif |
1181 | 1192 | ||
1182 | #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK | 1193 | #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK |