Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

Pull second round of input updates from Dmitry Torokhov:
"A new driver for Weida wdt87xx touch controllers, and a bunch of
fixups for other drivers"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
Input: wdt87xx_i2c - add a scaling factor for TOUCH_MAJOR event
Input: wdt87xx_i2c - remove stray newline in diagnostic message
Input: arc_ps2 - add HAS_IOMEM dependency
Input: wdt87xx_i2c - fix format warning
Input: improve parsing OF parameters for touchscreens
Input: edt-ft5x06 - mark as direct input device
Input: use for_each_set_bit() where appropriate
Input: add a driver for wdt87xx touchscreen controller
Input: axp20x-pek - fix reporting button state as inverted
Input: xpad - re-send LED command on present event
Input: xpad - set the LEDs properly on XBox Wireless controllers
Input: imx_keypad - check for clk_prepare_enable() error

+1296 -76
+9 -25
drivers/input/input.c
··· 677 677 int code; 678 678 679 679 if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) { 680 - for (code = 0; code <= KEY_MAX; code++) { 681 - if (is_event_supported(code, dev->keybit, KEY_MAX) && 682 - __test_and_clear_bit(code, dev->key)) { 683 - input_pass_event(dev, EV_KEY, code, 0); 684 - } 685 - } 680 + for_each_set_bit(code, dev->key, KEY_CNT) 681 + input_pass_event(dev, EV_KEY, code, 0); 682 + memset(dev->key, 0, sizeof(dev->key)); 686 683 input_pass_event(dev, EV_SYN, SYN_REPORT, 1); 687 684 } 688 685 } ··· 1623 1626 if (!test_bit(EV_##type, dev->evbit)) \ 1624 1627 break; \ 1625 1628 \ 1626 - for (i = 0; i < type##_MAX; i++) { \ 1627 - if (!test_bit(i, dev->bits##bit)) \ 1628 - continue; \ 1629 - \ 1629 + for_each_set_bit(i, dev->bits##bit, type##_CNT) { \ 1630 1630 active = test_bit(i, dev->bits); \ 1631 1631 if (!active && !on) \ 1632 1632 continue; \ ··· 1974 1980 1975 1981 events = mt_slots + 1; /* count SYN_MT_REPORT and SYN_REPORT */ 1976 1982 1977 - if (test_bit(EV_ABS, dev->evbit)) { 1978 - for (i = 0; i < ABS_CNT; i++) { 1979 - if (test_bit(i, dev->absbit)) { 1980 - if (input_is_mt_axis(i)) 1981 - events += mt_slots; 1982 - else 1983 - events++; 1984 - } 1985 - } 1986 - } 1983 + if (test_bit(EV_ABS, dev->evbit)) 1984 + for_each_set_bit(i, dev->absbit, ABS_CNT) 1985 + events += input_is_mt_axis(i) ? mt_slots : 1; 1987 1986 1988 - if (test_bit(EV_REL, dev->evbit)) { 1989 - for (i = 0; i < REL_CNT; i++) 1990 - if (test_bit(i, dev->relbit)) 1991 - events++; 1992 - } 1987 + if (test_bit(EV_REL, dev->evbit)) 1988 + events += bitmap_weight(dev->relbit, REL_CNT); 1993 1989 1994 1990 /* Make room for KEY and MSC events */ 1995 1991 events += 7;
+65 -13
drivers/input/joystick/xpad.c
··· 344 344 345 345 int mapping; /* map d-pad to buttons or to axes */ 346 346 int xtype; /* type of xbox device */ 347 + unsigned long led_no; /* led to lit on xbox360 controllers */ 347 348 }; 348 349 349 350 /* ··· 489 488 input_sync(dev); 490 489 } 491 490 491 + static void xpad_identify_controller(struct usb_xpad *xpad); 492 + 492 493 /* 493 494 * xpad360w_process_packet 494 495 * ··· 513 510 if (data[1] & 0x80) { 514 511 xpad->pad_present = 1; 515 512 usb_submit_urb(xpad->bulk_out, GFP_ATOMIC); 513 + /* 514 + * Light up the segment corresponding to 515 + * controller number. 516 + */ 517 + xpad_identify_controller(xpad); 516 518 } else 517 519 xpad->pad_present = 0; 518 520 } ··· 889 881 struct usb_xpad *xpad; 890 882 }; 891 883 884 + /** 885 + * @param command 886 + * 0: off 887 + * 1: all blink, then previous setting 888 + * 2: 1/top-left blink, then on 889 + * 3: 2/top-right blink, then on 890 + * 4: 3/bottom-left blink, then on 891 + * 5: 4/bottom-right blink, then on 892 + * 6: 1/top-left on 893 + * 7: 2/top-right on 894 + * 8: 3/bottom-left on 895 + * 9: 4/bottom-right on 896 + * 10: rotate 897 + * 11: blink, based on previous setting 898 + * 12: slow blink, based on previous setting 899 + * 13: rotate with two lights 900 + * 14: persistent slow all blink 901 + * 15: blink once, then previous setting 902 + */ 892 903 static void xpad_send_led_command(struct usb_xpad *xpad, int command) 893 904 { 894 - if (command >= 0 && command < 14) { 895 - mutex_lock(&xpad->odata_mutex); 905 + command %= 16; 906 + 907 + mutex_lock(&xpad->odata_mutex); 908 + 909 + switch (xpad->xtype) { 910 + case XTYPE_XBOX360: 896 911 xpad->odata[0] = 0x01; 897 912 xpad->odata[1] = 0x03; 898 913 xpad->odata[2] = command; 899 914 xpad->irq_out->transfer_buffer_length = 3; 900 - usb_submit_urb(xpad->irq_out, GFP_KERNEL); 901 - mutex_unlock(&xpad->odata_mutex); 915 + break; 916 + case XTYPE_XBOX360W: 917 + xpad->odata[0] = 0x00; 918 + xpad->odata[1] = 0x00; 919 + xpad->odata[2] = 0x08; 920 + xpad->odata[3] = 0x40 + command; 921 + xpad->odata[4] = 0x00; 922 + xpad->odata[5] = 0x00; 923 + xpad->odata[6] = 0x00; 924 + xpad->odata[7] = 0x00; 925 + xpad->odata[8] = 0x00; 926 + xpad->odata[9] = 0x00; 927 + xpad->odata[10] = 0x00; 928 + xpad->odata[11] = 0x00; 929 + xpad->irq_out->transfer_buffer_length = 12; 930 + break; 902 931 } 932 + 933 + usb_submit_urb(xpad->irq_out, GFP_KERNEL); 934 + mutex_unlock(&xpad->odata_mutex); 935 + } 936 + 937 + static void xpad_identify_controller(struct usb_xpad *xpad) 938 + { 939 + /* Light up the segment corresponding to controller number */ 940 + xpad_send_led_command(xpad, (xpad->led_no % 4) + 2); 903 941 } 904 942 905 943 static void xpad_led_set(struct led_classdev *led_cdev, ··· 959 905 960 906 static int xpad_led_probe(struct usb_xpad *xpad) 961 907 { 962 - static atomic_t led_seq = ATOMIC_INIT(-1); 963 - unsigned long led_no; 908 + static atomic_t led_seq = ATOMIC_INIT(-1); 964 909 struct xpad_led *led; 965 910 struct led_classdev *led_cdev; 966 911 int error; 967 912 968 - if (xpad->xtype != XTYPE_XBOX360) 913 + if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX360W) 969 914 return 0; 970 915 971 916 xpad->led = led = kzalloc(sizeof(struct xpad_led), GFP_KERNEL); 972 917 if (!led) 973 918 return -ENOMEM; 974 919 975 - led_no = atomic_inc_return(&led_seq); 920 + xpad->led_no = atomic_inc_return(&led_seq); 976 921 977 - snprintf(led->name, sizeof(led->name), "xpad%lu", led_no); 922 + snprintf(led->name, sizeof(led->name), "xpad%lu", xpad->led_no); 978 923 led->xpad = xpad; 979 924 980 925 led_cdev = &led->led_cdev; ··· 987 934 return error; 988 935 } 989 936 990 - /* 991 - * Light up the segment corresponding to controller number 992 - */ 993 - xpad_send_led_command(xpad, (led_no % 4) + 2); 937 + /* Light up the segment corresponding to controller number */ 938 + xpad_identify_controller(xpad); 994 939 995 940 return 0; 996 941 } ··· 1005 954 #else 1006 955 static int xpad_led_probe(struct usb_xpad *xpad) { return 0; } 1007 956 static void xpad_led_disconnect(struct usb_xpad *xpad) { } 957 + static void xpad_identify_controller(struct usb_xpad *xpad) { } 1008 958 #endif 1009 959 1010 960
+3 -1
drivers/input/keyboard/imx_keypad.c
··· 506 506 input_set_drvdata(input_dev, keypad); 507 507 508 508 /* Ensure that the keypad will stay dormant until opened */ 509 - clk_prepare_enable(keypad->clk); 509 + error = clk_prepare_enable(keypad->clk); 510 + if (error) 511 + return error; 510 512 imx_keypad_inhibit(keypad); 511 513 clk_disable_unprepare(keypad->clk); 512 514
+6 -2
drivers/input/misc/axp20x-pek.c
··· 167 167 struct input_dev *idev = pwr; 168 168 struct axp20x_pek *axp20x_pek = input_get_drvdata(idev); 169 169 170 - if (irq == axp20x_pek->irq_dbr) 170 + /* 171 + * The power-button is connected to ground so a falling edge (dbf) 172 + * means it is pressed. 173 + */ 174 + if (irq == axp20x_pek->irq_dbf) 171 175 input_report_key(idev, KEY_POWER, true); 172 - else if (irq == axp20x_pek->irq_dbf) 176 + else if (irq == axp20x_pek->irq_dbr) 173 177 input_report_key(idev, KEY_POWER, false); 174 178 175 179 input_sync(idev);
+1
drivers/input/serio/Kconfig
··· 244 244 245 245 config SERIO_ARC_PS2 246 246 tristate "ARC PS/2 support" 247 + depends on HAS_IOMEM 247 248 help 248 249 Say Y here if you have an ARC FPGA platform with a PS/2 249 250 controller in it.
+12
drivers/input/touchscreen/Kconfig
··· 658 658 To compile this driver as a module, choose M here: the 659 659 module will be called pixcir_i2c_ts. 660 660 661 + config TOUCHSCREEN_WDT87XX_I2C 662 + tristate "Weida HiTech I2C touchscreen" 663 + depends on I2C 664 + help 665 + Say Y here if you have a Weida WDT87XX I2C touchscreen 666 + connected to your system. 667 + 668 + If unsure, say N. 669 + 670 + To compile this driver as a module, choose M here: the 671 + module will be called wdt87xx_i2c. 672 + 661 673 config TOUCHSCREEN_WM831X 662 674 tristate "Support for WM831x touchscreen controllers" 663 675 depends on MFD_WM831X
+1
drivers/input/touchscreen/Makefile
··· 72 72 obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o 73 73 obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o 74 74 obj-$(CONFIG_TOUCHSCREEN_WACOM_I2C) += wacom_i2c.o 75 + obj-$(CONFIG_TOUCHSCREEN_WDT87XX_I2C) += wdt87xx_i2c.o 75 76 obj-$(CONFIG_TOUCHSCREEN_WM831X) += wm831x-ts.o 76 77 obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o 77 78 wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
+2 -7
drivers/input/touchscreen/edt-ft5x06.c
··· 1035 1035 input->id.bustype = BUS_I2C; 1036 1036 input->dev.parent = &client->dev; 1037 1037 1038 - __set_bit(EV_KEY, input->evbit); 1039 - __set_bit(EV_ABS, input->evbit); 1040 - __set_bit(BTN_TOUCH, input->keybit); 1041 - input_set_abs_params(input, ABS_X, 0, tsdata->num_x * 64 - 1, 0, 0); 1042 - input_set_abs_params(input, ABS_Y, 0, tsdata->num_y * 64 - 1, 0, 0); 1043 1038 input_set_abs_params(input, ABS_MT_POSITION_X, 1044 1039 0, tsdata->num_x * 64 - 1, 0, 0); 1045 1040 input_set_abs_params(input, ABS_MT_POSITION_Y, 1046 1041 0, tsdata->num_y * 64 - 1, 0, 0); 1047 1042 1048 1043 if (!pdata) 1049 - touchscreen_parse_of_params(input); 1044 + touchscreen_parse_of_params(input, true); 1050 1045 1051 - error = input_mt_init_slots(input, MAX_SUPPORT_POINTS, 0); 1046 + error = input_mt_init_slots(input, MAX_SUPPORT_POINTS, INPUT_MT_DIRECT); 1052 1047 if (error) { 1053 1048 dev_err(&client->dev, "Unable to init MT slots.\n"); 1054 1049 return error;
+44 -25
drivers/input/touchscreen/of_touchscreen.c
··· 14 14 #include <linux/input/mt.h> 15 15 #include <linux/input/touchscreen.h> 16 16 17 - static u32 of_get_optional_u32(struct device_node *np, 18 - const char *property) 17 + static bool touchscreen_get_prop_u32(struct device_node *np, 18 + const char *property, 19 + unsigned int default_value, 20 + unsigned int *value) 19 21 { 20 - u32 val = 0; 22 + u32 val; 23 + int error; 21 24 22 - of_property_read_u32(np, property, &val); 25 + error = of_property_read_u32(np, property, &val); 26 + if (error) { 27 + *value = default_value; 28 + return false; 29 + } 23 30 24 - return val; 31 + *value = val; 32 + return true; 25 33 } 26 34 27 35 static void touchscreen_set_params(struct input_dev *dev, ··· 62 54 * input device accordingly. The function keeps previously setuped default 63 55 * values if no value is specified via DT. 64 56 */ 65 - void touchscreen_parse_of_params(struct input_dev *dev) 57 + void touchscreen_parse_of_params(struct input_dev *dev, bool multitouch) 66 58 { 67 59 struct device_node *np = dev->dev.parent->of_node; 68 - u32 maximum, fuzz; 60 + unsigned int axis; 61 + unsigned int maximum, fuzz; 62 + bool data_present; 69 63 70 64 input_alloc_absinfo(dev); 71 65 if (!dev->absinfo) 72 66 return; 73 67 74 - maximum = of_get_optional_u32(np, "touchscreen-size-x"); 75 - fuzz = of_get_optional_u32(np, "touchscreen-fuzz-x"); 76 - if (maximum || fuzz) { 77 - touchscreen_set_params(dev, ABS_X, maximum, fuzz); 78 - touchscreen_set_params(dev, ABS_MT_POSITION_X, maximum, fuzz); 79 - } 68 + axis = multitouch ? ABS_MT_POSITION_X : ABS_X; 69 + data_present = touchscreen_get_prop_u32(np, "touchscreen-size-x", 70 + input_abs_get_max(dev, axis), 71 + &maximum) | 72 + touchscreen_get_prop_u32(np, "touchscreen-fuzz-x", 73 + input_abs_get_fuzz(dev, axis), 74 + &fuzz); 75 + if (data_present) 76 + touchscreen_set_params(dev, axis, maximum, fuzz); 80 77 81 - maximum = of_get_optional_u32(np, "touchscreen-size-y"); 82 - fuzz = of_get_optional_u32(np, "touchscreen-fuzz-y"); 83 - if (maximum || fuzz) { 84 - touchscreen_set_params(dev, ABS_Y, maximum, fuzz); 85 - touchscreen_set_params(dev, ABS_MT_POSITION_Y, maximum, fuzz); 86 - } 78 + axis = multitouch ? ABS_MT_POSITION_Y : ABS_Y; 79 + data_present = touchscreen_get_prop_u32(np, "touchscreen-size-y", 80 + input_abs_get_max(dev, axis), 81 + &maximum) | 82 + touchscreen_get_prop_u32(np, "touchscreen-fuzz-y", 83 + input_abs_get_fuzz(dev, axis), 84 + &fuzz); 85 + if (data_present) 86 + touchscreen_set_params(dev, axis, maximum, fuzz); 87 87 88 - maximum = of_get_optional_u32(np, "touchscreen-max-pressure"); 89 - fuzz = of_get_optional_u32(np, "touchscreen-fuzz-pressure"); 90 - if (maximum || fuzz) { 91 - touchscreen_set_params(dev, ABS_PRESSURE, maximum, fuzz); 92 - touchscreen_set_params(dev, ABS_MT_PRESSURE, maximum, fuzz); 93 - } 88 + axis = multitouch ? ABS_MT_PRESSURE : ABS_PRESSURE; 89 + data_present = touchscreen_get_prop_u32(np, "touchscreen-max-pressure", 90 + input_abs_get_max(dev, axis), 91 + &maximum) | 92 + touchscreen_get_prop_u32(np, "touchscreen-fuzz-pressure", 93 + input_abs_get_fuzz(dev, axis), 94 + &fuzz); 95 + if (data_present) 96 + touchscreen_set_params(dev, axis, maximum, fuzz); 94 97 } 95 98 EXPORT_SYMBOL(touchscreen_parse_of_params);
+1 -1
drivers/input/touchscreen/tsc2005.c
··· 709 709 input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0); 710 710 711 711 if (np) 712 - touchscreen_parse_of_params(input_dev); 712 + touchscreen_parse_of_params(input_dev, false); 713 713 714 714 input_dev->open = tsc2005_open; 715 715 input_dev->close = tsc2005_close;
+1149
drivers/input/touchscreen/wdt87xx_i2c.c
··· 1 + /* 2 + * Weida HiTech WDT87xx TouchScreen I2C driver 3 + * 4 + * Copyright (c) 2015 Weida Hi-Tech Co., Ltd. 5 + * HN Chen <hn.chen@weidahitech.com> 6 + * 7 + * This software is licensed under the terms of the GNU General Public 8 + * License, as published by the Free Software Foundation, and 9 + * may be copied, distributed, and modified under those terms. 10 + */ 11 + 12 + #include <linux/i2c.h> 13 + #include <linux/input.h> 14 + #include <linux/interrupt.h> 15 + #include <linux/delay.h> 16 + #include <linux/irq.h> 17 + #include <linux/io.h> 18 + #include <linux/module.h> 19 + #include <linux/slab.h> 20 + #include <linux/firmware.h> 21 + #include <linux/input/mt.h> 22 + #include <linux/acpi.h> 23 + #include <asm/unaligned.h> 24 + 25 + #define WDT87XX_NAME "wdt87xx_i2c" 26 + #define WDT87XX_DRV_VER "0.9.6" 27 + #define WDT87XX_FW_NAME "wdt87xx_fw.bin" 28 + #define WDT87XX_CFG_NAME "wdt87xx_cfg.bin" 29 + 30 + #define MODE_ACTIVE 0x01 31 + #define MODE_READY 0x02 32 + #define MODE_IDLE 0x03 33 + #define MODE_SLEEP 0x04 34 + #define MODE_STOP 0xFF 35 + 36 + #define WDT_MAX_FINGER 10 37 + #define WDT_RAW_BUF_COUNT 54 38 + #define WDT_V1_RAW_BUF_COUNT 74 39 + #define WDT_FIRMWARE_ID 0xa9e368f5 40 + 41 + #define PG_SIZE 0x1000 42 + #define MAX_RETRIES 3 43 + 44 + #define MAX_UNIT_AXIS 0x7FFF 45 + 46 + #define PKT_READ_SIZE 72 47 + #define PKT_WRITE_SIZE 80 48 + 49 + /* the finger definition of the report event */ 50 + #define FINGER_EV_OFFSET_ID 0 51 + #define FINGER_EV_OFFSET_X 1 52 + #define FINGER_EV_OFFSET_Y 3 53 + #define FINGER_EV_SIZE 5 54 + 55 + #define FINGER_EV_V1_OFFSET_ID 0 56 + #define FINGER_EV_V1_OFFSET_W 1 57 + #define FINGER_EV_V1_OFFSET_P 2 58 + #define FINGER_EV_V1_OFFSET_X 3 59 + #define FINGER_EV_V1_OFFSET_Y 5 60 + #define FINGER_EV_V1_SIZE 7 61 + 62 + /* The definition of a report packet */ 63 + #define TOUCH_PK_OFFSET_REPORT_ID 0 64 + #define TOUCH_PK_OFFSET_EVENT 1 65 + #define TOUCH_PK_OFFSET_SCAN_TIME 51 66 + #define TOUCH_PK_OFFSET_FNGR_NUM 53 67 + 68 + #define TOUCH_PK_V1_OFFSET_REPORT_ID 0 69 + #define TOUCH_PK_V1_OFFSET_EVENT 1 70 + #define TOUCH_PK_V1_OFFSET_SCAN_TIME 71 71 + #define TOUCH_PK_V1_OFFSET_FNGR_NUM 73 72 + 73 + /* The definition of the controller parameters */ 74 + #define CTL_PARAM_OFFSET_FW_ID 0 75 + #define CTL_PARAM_OFFSET_PLAT_ID 2 76 + #define CTL_PARAM_OFFSET_XMLS_ID1 4 77 + #define CTL_PARAM_OFFSET_XMLS_ID2 6 78 + #define CTL_PARAM_OFFSET_PHY_CH_X 8 79 + #define CTL_PARAM_OFFSET_PHY_CH_Y 10 80 + #define CTL_PARAM_OFFSET_PHY_X0 12 81 + #define CTL_PARAM_OFFSET_PHY_X1 14 82 + #define CTL_PARAM_OFFSET_PHY_Y0 16 83 + #define CTL_PARAM_OFFSET_PHY_Y1 18 84 + #define CTL_PARAM_OFFSET_PHY_W 22 85 + #define CTL_PARAM_OFFSET_PHY_H 24 86 + #define CTL_PARAM_OFFSET_FACTOR 32 87 + 88 + /* Communication commands */ 89 + #define PACKET_SIZE 56 90 + #define VND_REQ_READ 0x06 91 + #define VND_READ_DATA 0x07 92 + #define VND_REQ_WRITE 0x08 93 + 94 + #define VND_CMD_START 0x00 95 + #define VND_CMD_STOP 0x01 96 + #define VND_CMD_RESET 0x09 97 + 98 + #define VND_CMD_ERASE 0x1A 99 + 100 + #define VND_GET_CHECKSUM 0x66 101 + 102 + #define VND_SET_DATA 0x83 103 + #define VND_SET_COMMAND_DATA 0x84 104 + #define VND_SET_CHECKSUM_CALC 0x86 105 + #define VND_SET_CHECKSUM_LENGTH 0x87 106 + 107 + #define VND_CMD_SFLCK 0xFC 108 + #define VND_CMD_SFUNL 0xFD 109 + 110 + #define CMD_SFLCK_KEY 0xC39B 111 + #define CMD_SFUNL_KEY 0x95DA 112 + 113 + #define STRIDX_PLATFORM_ID 0x80 114 + #define STRIDX_PARAMETERS 0x81 115 + 116 + #define CMD_BUF_SIZE 8 117 + #define PKT_BUF_SIZE 64 118 + 119 + /* The definition of the command packet */ 120 + #define CMD_REPORT_ID_OFFSET 0x0 121 + #define CMD_TYPE_OFFSET 0x1 122 + #define CMD_INDEX_OFFSET 0x2 123 + #define CMD_KEY_OFFSET 0x3 124 + #define CMD_LENGTH_OFFSET 0x4 125 + #define CMD_DATA_OFFSET 0x8 126 + 127 + /* The definition of firmware chunk tags */ 128 + #define FOURCC_ID_RIFF 0x46464952 129 + #define FOURCC_ID_WHIF 0x46494857 130 + #define FOURCC_ID_FRMT 0x544D5246 131 + #define FOURCC_ID_FRWR 0x52575246 132 + #define FOURCC_ID_CNFG 0x47464E43 133 + 134 + #define CHUNK_ID_FRMT FOURCC_ID_FRMT 135 + #define CHUNK_ID_FRWR FOURCC_ID_FRWR 136 + #define CHUNK_ID_CNFG FOURCC_ID_CNFG 137 + 138 + #define FW_FOURCC1_OFFSET 0 139 + #define FW_SIZE_OFFSET 4 140 + #define FW_FOURCC2_OFFSET 8 141 + #define FW_PAYLOAD_OFFSET 40 142 + 143 + #define FW_CHUNK_ID_OFFSET 0 144 + #define FW_CHUNK_SIZE_OFFSET 4 145 + #define FW_CHUNK_TGT_START_OFFSET 8 146 + #define FW_CHUNK_PAYLOAD_LEN_OFFSET 12 147 + #define FW_CHUNK_SRC_START_OFFSET 16 148 + #define FW_CHUNK_VERSION_OFFSET 20 149 + #define FW_CHUNK_ATTR_OFFSET 24 150 + #define FW_CHUNK_PAYLOAD_OFFSET 32 151 + 152 + /* Controller requires minimum 300us between commands */ 153 + #define WDT_COMMAND_DELAY_MS 2 154 + #define WDT_FLASH_WRITE_DELAY_MS 4 155 + 156 + struct wdt87xx_sys_param { 157 + u16 fw_id; 158 + u16 plat_id; 159 + u16 xmls_id1; 160 + u16 xmls_id2; 161 + u16 phy_ch_x; 162 + u16 phy_ch_y; 163 + u16 phy_w; 164 + u16 phy_h; 165 + u16 scaling_factor; 166 + u32 max_x; 167 + u32 max_y; 168 + }; 169 + 170 + struct wdt87xx_data { 171 + struct i2c_client *client; 172 + struct input_dev *input; 173 + /* Mutex for fw update to prevent concurrent access */ 174 + struct mutex fw_mutex; 175 + struct wdt87xx_sys_param param; 176 + u8 phys[32]; 177 + }; 178 + 179 + static int wdt87xx_i2c_xfer(struct i2c_client *client, 180 + void *txdata, size_t txlen, 181 + void *rxdata, size_t rxlen) 182 + { 183 + struct i2c_msg msgs[] = { 184 + { 185 + .addr = client->addr, 186 + .flags = 0, 187 + .len = txlen, 188 + .buf = txdata, 189 + }, 190 + { 191 + .addr = client->addr, 192 + .flags = I2C_M_RD, 193 + .len = rxlen, 194 + .buf = rxdata, 195 + }, 196 + }; 197 + int error; 198 + int ret; 199 + 200 + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); 201 + if (ret != ARRAY_SIZE(msgs)) { 202 + error = ret < 0 ? ret : -EIO; 203 + dev_err(&client->dev, "%s: i2c transfer failed: %d\n", 204 + __func__, error); 205 + return error; 206 + } 207 + 208 + return 0; 209 + } 210 + 211 + static int wdt87xx_get_string(struct i2c_client *client, u8 str_idx, 212 + u8 *buf, size_t len) 213 + { 214 + u8 tx_buf[] = { 0x22, 0x00, 0x13, 0x0E, str_idx, 0x23, 0x00 }; 215 + u8 rx_buf[PKT_WRITE_SIZE]; 216 + size_t rx_len = len + 2; 217 + int error; 218 + 219 + if (rx_len > sizeof(rx_buf)) 220 + return -EINVAL; 221 + 222 + error = wdt87xx_i2c_xfer(client, tx_buf, sizeof(tx_buf), 223 + rx_buf, rx_len); 224 + if (error) { 225 + dev_err(&client->dev, "get string failed: %d\n", error); 226 + return error; 227 + } 228 + 229 + if (rx_buf[1] != 0x03) { 230 + dev_err(&client->dev, "unexpected response to get string: %d\n", 231 + rx_buf[1]); 232 + return -EINVAL; 233 + } 234 + 235 + rx_len = min_t(size_t, len, rx_buf[0]); 236 + memcpy(buf, &rx_buf[2], rx_len); 237 + 238 + mdelay(WDT_COMMAND_DELAY_MS); 239 + 240 + return 0; 241 + } 242 + 243 + static int wdt87xx_get_feature(struct i2c_client *client, 244 + u8 *buf, size_t buf_size) 245 + { 246 + u8 tx_buf[8]; 247 + u8 rx_buf[PKT_WRITE_SIZE]; 248 + size_t tx_len = 0; 249 + size_t rx_len = buf_size + 2; 250 + int error; 251 + 252 + if (rx_len > sizeof(rx_buf)) 253 + return -EINVAL; 254 + 255 + /* Get feature command packet */ 256 + tx_buf[tx_len++] = 0x22; 257 + tx_buf[tx_len++] = 0x00; 258 + if (buf[CMD_REPORT_ID_OFFSET] > 0xF) { 259 + tx_buf[tx_len++] = 0x30; 260 + tx_buf[tx_len++] = 0x02; 261 + tx_buf[tx_len++] = buf[CMD_REPORT_ID_OFFSET]; 262 + } else { 263 + tx_buf[tx_len++] = 0x30 | buf[CMD_REPORT_ID_OFFSET]; 264 + tx_buf[tx_len++] = 0x02; 265 + } 266 + tx_buf[tx_len++] = 0x23; 267 + tx_buf[tx_len++] = 0x00; 268 + 269 + error = wdt87xx_i2c_xfer(client, tx_buf, tx_len, rx_buf, rx_len); 270 + if (error) { 271 + dev_err(&client->dev, "get feature failed: %d\n", error); 272 + return error; 273 + } 274 + 275 + rx_len = min_t(size_t, buf_size, get_unaligned_le16(rx_buf)); 276 + memcpy(buf, &rx_buf[2], rx_len); 277 + 278 + mdelay(WDT_COMMAND_DELAY_MS); 279 + 280 + return 0; 281 + } 282 + 283 + static int wdt87xx_set_feature(struct i2c_client *client, 284 + const u8 *buf, size_t buf_size) 285 + { 286 + u8 tx_buf[PKT_WRITE_SIZE]; 287 + int tx_len = 0; 288 + int error; 289 + 290 + /* Set feature command packet */ 291 + tx_buf[tx_len++] = 0x22; 292 + tx_buf[tx_len++] = 0x00; 293 + if (buf[CMD_REPORT_ID_OFFSET] > 0xF) { 294 + tx_buf[tx_len++] = 0x30; 295 + tx_buf[tx_len++] = 0x03; 296 + tx_buf[tx_len++] = buf[CMD_REPORT_ID_OFFSET]; 297 + } else { 298 + tx_buf[tx_len++] = 0x30 | buf[CMD_REPORT_ID_OFFSET]; 299 + tx_buf[tx_len++] = 0x03; 300 + } 301 + tx_buf[tx_len++] = 0x23; 302 + tx_buf[tx_len++] = 0x00; 303 + tx_buf[tx_len++] = (buf_size & 0xFF); 304 + tx_buf[tx_len++] = ((buf_size & 0xFF00) >> 8); 305 + 306 + if (tx_len + buf_size > sizeof(tx_buf)) 307 + return -EINVAL; 308 + 309 + memcpy(&tx_buf[tx_len], buf, buf_size); 310 + tx_len += buf_size; 311 + 312 + error = i2c_master_send(client, tx_buf, tx_len); 313 + if (error < 0) { 314 + dev_err(&client->dev, "set feature failed: %d\n", error); 315 + return error; 316 + } 317 + 318 + mdelay(WDT_COMMAND_DELAY_MS); 319 + 320 + return 0; 321 + } 322 + 323 + static int wdt87xx_send_command(struct i2c_client *client, int cmd, int value) 324 + { 325 + u8 cmd_buf[CMD_BUF_SIZE]; 326 + 327 + /* Set the command packet */ 328 + cmd_buf[CMD_REPORT_ID_OFFSET] = VND_REQ_WRITE; 329 + cmd_buf[CMD_TYPE_OFFSET] = VND_SET_COMMAND_DATA; 330 + put_unaligned_le16((u16)cmd, &cmd_buf[CMD_INDEX_OFFSET]); 331 + 332 + switch (cmd) { 333 + case VND_CMD_START: 334 + case VND_CMD_STOP: 335 + case VND_CMD_RESET: 336 + /* Mode selector */ 337 + put_unaligned_le32((value & 0xFF), &cmd_buf[CMD_LENGTH_OFFSET]); 338 + break; 339 + 340 + case VND_CMD_SFLCK: 341 + put_unaligned_le16(CMD_SFLCK_KEY, &cmd_buf[CMD_KEY_OFFSET]); 342 + break; 343 + 344 + case VND_CMD_SFUNL: 345 + put_unaligned_le16(CMD_SFUNL_KEY, &cmd_buf[CMD_KEY_OFFSET]); 346 + break; 347 + 348 + case VND_CMD_ERASE: 349 + case VND_SET_CHECKSUM_CALC: 350 + case VND_SET_CHECKSUM_LENGTH: 351 + put_unaligned_le32(value, &cmd_buf[CMD_KEY_OFFSET]); 352 + break; 353 + 354 + default: 355 + cmd_buf[CMD_REPORT_ID_OFFSET] = 0; 356 + dev_err(&client->dev, "Invalid command: %d\n", cmd); 357 + return -EINVAL; 358 + } 359 + 360 + return wdt87xx_set_feature(client, cmd_buf, sizeof(cmd_buf)); 361 + } 362 + 363 + static int wdt87xx_sw_reset(struct i2c_client *client) 364 + { 365 + int error; 366 + 367 + dev_dbg(&client->dev, "resetting device now\n"); 368 + 369 + error = wdt87xx_send_command(client, VND_CMD_RESET, 0); 370 + if (error) { 371 + dev_err(&client->dev, "reset failed\n"); 372 + return error; 373 + } 374 + 375 + /* Wait the device to be ready */ 376 + msleep(200); 377 + 378 + return 0; 379 + } 380 + 381 + static const void *wdt87xx_get_fw_chunk(const struct firmware *fw, u32 id) 382 + { 383 + size_t pos = FW_PAYLOAD_OFFSET; 384 + u32 chunk_id, chunk_size; 385 + 386 + while (pos < fw->size) { 387 + chunk_id = get_unaligned_le32(fw->data + 388 + pos + FW_CHUNK_ID_OFFSET); 389 + if (chunk_id == id) 390 + return fw->data + pos; 391 + 392 + chunk_size = get_unaligned_le32(fw->data + 393 + pos + FW_CHUNK_SIZE_OFFSET); 394 + pos += chunk_size + 2 * sizeof(u32); /* chunk ID + size */ 395 + } 396 + 397 + return NULL; 398 + } 399 + 400 + static int wdt87xx_get_sysparam(struct i2c_client *client, 401 + struct wdt87xx_sys_param *param) 402 + { 403 + u8 buf[PKT_READ_SIZE]; 404 + int error; 405 + 406 + error = wdt87xx_get_string(client, STRIDX_PARAMETERS, buf, 34); 407 + if (error) { 408 + dev_err(&client->dev, "failed to get parameters\n"); 409 + return error; 410 + } 411 + 412 + param->xmls_id1 = get_unaligned_le16(buf + CTL_PARAM_OFFSET_XMLS_ID1); 413 + param->xmls_id2 = get_unaligned_le16(buf + CTL_PARAM_OFFSET_XMLS_ID2); 414 + param->phy_ch_x = get_unaligned_le16(buf + CTL_PARAM_OFFSET_PHY_CH_X); 415 + param->phy_ch_y = get_unaligned_le16(buf + CTL_PARAM_OFFSET_PHY_CH_Y); 416 + param->phy_w = get_unaligned_le16(buf + CTL_PARAM_OFFSET_PHY_W) / 10; 417 + param->phy_h = get_unaligned_le16(buf + CTL_PARAM_OFFSET_PHY_H) / 10; 418 + 419 + /* Get the scaling factor of pixel to logical coordinate */ 420 + param->scaling_factor = 421 + get_unaligned_le16(buf + CTL_PARAM_OFFSET_FACTOR); 422 + 423 + param->max_x = MAX_UNIT_AXIS; 424 + param->max_y = DIV_ROUND_CLOSEST(MAX_UNIT_AXIS * param->phy_h, 425 + param->phy_w); 426 + 427 + error = wdt87xx_get_string(client, STRIDX_PLATFORM_ID, buf, 8); 428 + if (error) { 429 + dev_err(&client->dev, "failed to get platform id\n"); 430 + return error; 431 + } 432 + 433 + param->plat_id = buf[1]; 434 + 435 + buf[0] = 0xf2; 436 + error = wdt87xx_get_feature(client, buf, 16); 437 + if (error) { 438 + dev_err(&client->dev, "failed to get firmware id\n"); 439 + return error; 440 + } 441 + 442 + if (buf[0] != 0xf2) { 443 + dev_err(&client->dev, "wrong id of fw response: 0x%x\n", 444 + buf[0]); 445 + return -EINVAL; 446 + } 447 + 448 + param->fw_id = get_unaligned_le16(&buf[1]); 449 + 450 + dev_info(&client->dev, 451 + "fw_id: 0x%x, plat_id: 0x%x, xml_id1: %04x, xml_id2: %04x\n", 452 + param->fw_id, param->plat_id, 453 + param->xmls_id1, param->xmls_id2); 454 + 455 + return 0; 456 + } 457 + 458 + static int wdt87xx_validate_firmware(struct wdt87xx_data *wdt, 459 + const struct firmware *fw) 460 + { 461 + const void *fw_chunk; 462 + u32 data1, data2; 463 + u32 size; 464 + u8 fw_chip_id; 465 + u8 chip_id; 466 + 467 + data1 = get_unaligned_le32(fw->data + FW_FOURCC1_OFFSET); 468 + data2 = get_unaligned_le32(fw->data + FW_FOURCC2_OFFSET); 469 + if (data1 != FOURCC_ID_RIFF || data2 != FOURCC_ID_WHIF) { 470 + dev_err(&wdt->client->dev, "check fw tag failed\n"); 471 + return -EINVAL; 472 + } 473 + 474 + size = get_unaligned_le32(fw->data + FW_SIZE_OFFSET); 475 + if (size != fw->size) { 476 + dev_err(&wdt->client->dev, 477 + "fw size mismatch: expected %d, actual %zu\n", 478 + size, fw->size); 479 + return -EINVAL; 480 + } 481 + 482 + /* 483 + * Get the chip_id from the firmware. Make sure that it is the 484 + * right controller to do the firmware and config update. 485 + */ 486 + fw_chunk = wdt87xx_get_fw_chunk(fw, CHUNK_ID_FRWR); 487 + if (!fw_chunk) { 488 + dev_err(&wdt->client->dev, 489 + "unable to locate firmware chunk\n"); 490 + return -EINVAL; 491 + } 492 + 493 + fw_chip_id = (get_unaligned_le32(fw_chunk + 494 + FW_CHUNK_VERSION_OFFSET) >> 12) & 0xF; 495 + chip_id = (wdt->param.fw_id >> 12) & 0xF; 496 + 497 + if (fw_chip_id != chip_id) { 498 + dev_err(&wdt->client->dev, 499 + "fw version mismatch: fw %d vs. chip %d\n", 500 + fw_chip_id, chip_id); 501 + return -ENODEV; 502 + } 503 + 504 + return 0; 505 + } 506 + 507 + static int wdt87xx_validate_fw_chunk(const void *data, int id) 508 + { 509 + if (id == CHUNK_ID_FRWR) { 510 + u32 fw_id; 511 + 512 + fw_id = get_unaligned_le32(data + FW_CHUNK_PAYLOAD_OFFSET); 513 + if (fw_id != WDT_FIRMWARE_ID) 514 + return -EINVAL; 515 + } 516 + 517 + return 0; 518 + } 519 + 520 + static int wdt87xx_write_data(struct i2c_client *client, const char *data, 521 + u32 address, int length) 522 + { 523 + u16 packet_size; 524 + int count = 0; 525 + int error; 526 + u8 pkt_buf[PKT_BUF_SIZE]; 527 + 528 + /* Address and length should be 4 bytes aligned */ 529 + if ((address & 0x3) != 0 || (length & 0x3) != 0) { 530 + dev_err(&client->dev, 531 + "addr & len must be 4 bytes aligned %x, %x\n", 532 + address, length); 533 + return -EINVAL; 534 + } 535 + 536 + while (length) { 537 + packet_size = min(length, PACKET_SIZE); 538 + 539 + pkt_buf[CMD_REPORT_ID_OFFSET] = VND_REQ_WRITE; 540 + pkt_buf[CMD_TYPE_OFFSET] = VND_SET_DATA; 541 + put_unaligned_le16(packet_size, &pkt_buf[CMD_INDEX_OFFSET]); 542 + put_unaligned_le32(address, &pkt_buf[CMD_LENGTH_OFFSET]); 543 + memcpy(&pkt_buf[CMD_DATA_OFFSET], data, packet_size); 544 + 545 + error = wdt87xx_set_feature(client, pkt_buf, sizeof(pkt_buf)); 546 + if (error) 547 + return error; 548 + 549 + length -= packet_size; 550 + data += packet_size; 551 + address += packet_size; 552 + 553 + /* Wait for the controller to finish the write */ 554 + mdelay(WDT_FLASH_WRITE_DELAY_MS); 555 + 556 + if ((++count % 32) == 0) { 557 + /* Delay for fw to clear watch dog */ 558 + msleep(20); 559 + } 560 + } 561 + 562 + return 0; 563 + } 564 + 565 + static u16 misr(u16 cur_value, u8 new_value) 566 + { 567 + u32 a, b; 568 + u32 bit0; 569 + u32 y; 570 + 571 + a = cur_value; 572 + b = new_value; 573 + bit0 = a ^ (b & 1); 574 + bit0 ^= a >> 1; 575 + bit0 ^= a >> 2; 576 + bit0 ^= a >> 4; 577 + bit0 ^= a >> 5; 578 + bit0 ^= a >> 7; 579 + bit0 ^= a >> 11; 580 + bit0 ^= a >> 15; 581 + y = (a << 1) ^ b; 582 + y = (y & ~1) | (bit0 & 1); 583 + 584 + return (u16)y; 585 + } 586 + 587 + static u16 wdt87xx_calculate_checksum(const u8 *data, size_t length) 588 + { 589 + u16 checksum = 0; 590 + size_t i; 591 + 592 + for (i = 0; i < length; i++) 593 + checksum = misr(checksum, data[i]); 594 + 595 + return checksum; 596 + } 597 + 598 + static int wdt87xx_get_checksum(struct i2c_client *client, u16 *checksum, 599 + u32 address, int length) 600 + { 601 + int error; 602 + int time_delay; 603 + u8 pkt_buf[PKT_BUF_SIZE]; 604 + u8 cmd_buf[CMD_BUF_SIZE]; 605 + 606 + error = wdt87xx_send_command(client, VND_SET_CHECKSUM_LENGTH, length); 607 + if (error) { 608 + dev_err(&client->dev, "failed to set checksum length\n"); 609 + return error; 610 + } 611 + 612 + error = wdt87xx_send_command(client, VND_SET_CHECKSUM_CALC, address); 613 + if (error) { 614 + dev_err(&client->dev, "failed to set checksum address\n"); 615 + return error; 616 + } 617 + 618 + /* Wait the operation to complete */ 619 + time_delay = DIV_ROUND_UP(length, 1024); 620 + msleep(time_delay * 30); 621 + 622 + memset(cmd_buf, 0, sizeof(cmd_buf)); 623 + cmd_buf[CMD_REPORT_ID_OFFSET] = VND_REQ_READ; 624 + cmd_buf[CMD_TYPE_OFFSET] = VND_GET_CHECKSUM; 625 + error = wdt87xx_set_feature(client, cmd_buf, sizeof(cmd_buf)); 626 + if (error) { 627 + dev_err(&client->dev, "failed to request checksum\n"); 628 + return error; 629 + } 630 + 631 + memset(pkt_buf, 0, sizeof(pkt_buf)); 632 + pkt_buf[CMD_REPORT_ID_OFFSET] = VND_READ_DATA; 633 + error = wdt87xx_get_feature(client, pkt_buf, sizeof(pkt_buf)); 634 + if (error) { 635 + dev_err(&client->dev, "failed to read checksum\n"); 636 + return error; 637 + } 638 + 639 + *checksum = get_unaligned_le16(&pkt_buf[CMD_DATA_OFFSET]); 640 + return 0; 641 + } 642 + 643 + static int wdt87xx_write_firmware(struct i2c_client *client, const void *chunk) 644 + { 645 + u32 start_addr = get_unaligned_le32(chunk + FW_CHUNK_TGT_START_OFFSET); 646 + u32 size = get_unaligned_le32(chunk + FW_CHUNK_PAYLOAD_LEN_OFFSET); 647 + const void *data = chunk + FW_CHUNK_PAYLOAD_OFFSET; 648 + int error; 649 + int err1; 650 + int page_size; 651 + int retry = 0; 652 + u16 device_checksum, firmware_checksum; 653 + 654 + dev_dbg(&client->dev, "start 4k page program\n"); 655 + 656 + error = wdt87xx_send_command(client, VND_CMD_STOP, MODE_STOP); 657 + if (error) { 658 + dev_err(&client->dev, "stop report mode failed\n"); 659 + return error; 660 + } 661 + 662 + error = wdt87xx_send_command(client, VND_CMD_SFUNL, 0); 663 + if (error) { 664 + dev_err(&client->dev, "unlock failed\n"); 665 + goto out_enable_reporting; 666 + } 667 + 668 + mdelay(10); 669 + 670 + while (size) { 671 + dev_dbg(&client->dev, "%s: %x, %x\n", __func__, 672 + start_addr, size); 673 + 674 + page_size = min_t(u32, size, PG_SIZE); 675 + size -= page_size; 676 + 677 + for (retry = 0; retry < MAX_RETRIES; retry++) { 678 + error = wdt87xx_send_command(client, VND_CMD_ERASE, 679 + start_addr); 680 + if (error) { 681 + dev_err(&client->dev, 682 + "erase failed at %#08x\n", start_addr); 683 + break; 684 + } 685 + 686 + msleep(50); 687 + 688 + error = wdt87xx_write_data(client, data, start_addr, 689 + page_size); 690 + if (error) { 691 + dev_err(&client->dev, 692 + "write failed at %#08x (%d bytes)\n", 693 + start_addr, page_size); 694 + break; 695 + } 696 + 697 + error = wdt87xx_get_checksum(client, &device_checksum, 698 + start_addr, page_size); 699 + if (error) { 700 + dev_err(&client->dev, 701 + "failed to retrieve checksum for %#08x (len: %d)\n", 702 + start_addr, page_size); 703 + break; 704 + } 705 + 706 + firmware_checksum = 707 + wdt87xx_calculate_checksum(data, page_size); 708 + 709 + if (device_checksum == firmware_checksum) 710 + break; 711 + 712 + dev_err(&client->dev, 713 + "checksum fail: %d vs %d, retry %d\n", 714 + device_checksum, firmware_checksum, retry); 715 + } 716 + 717 + if (retry == MAX_RETRIES) { 718 + dev_err(&client->dev, "page write failed\n"); 719 + error = -EIO; 720 + goto out_lock_device; 721 + } 722 + 723 + start_addr = start_addr + page_size; 724 + data = data + page_size; 725 + } 726 + 727 + out_lock_device: 728 + err1 = wdt87xx_send_command(client, VND_CMD_SFLCK, 0); 729 + if (err1) 730 + dev_err(&client->dev, "lock failed\n"); 731 + 732 + mdelay(10); 733 + 734 + out_enable_reporting: 735 + err1 = wdt87xx_send_command(client, VND_CMD_START, 0); 736 + if (err1) 737 + dev_err(&client->dev, "start to report failed\n"); 738 + 739 + return error ? error : err1; 740 + } 741 + 742 + static int wdt87xx_load_chunk(struct i2c_client *client, 743 + const struct firmware *fw, u32 ck_id) 744 + { 745 + const void *chunk; 746 + int error; 747 + 748 + chunk = wdt87xx_get_fw_chunk(fw, ck_id); 749 + if (!chunk) { 750 + dev_err(&client->dev, "unable to locate chunk (type %d)\n", 751 + ck_id); 752 + return -EINVAL; 753 + } 754 + 755 + error = wdt87xx_validate_fw_chunk(chunk, ck_id); 756 + if (error) { 757 + dev_err(&client->dev, "invalid chunk (type %d): %d\n", 758 + ck_id, error); 759 + return error; 760 + } 761 + 762 + error = wdt87xx_write_firmware(client, chunk); 763 + if (error) { 764 + dev_err(&client->dev, 765 + "failed to write fw chunk (type %d): %d\n", 766 + ck_id, error); 767 + return error; 768 + } 769 + 770 + return 0; 771 + } 772 + 773 + static int wdt87xx_do_update_firmware(struct i2c_client *client, 774 + const struct firmware *fw, 775 + unsigned int chunk_id) 776 + { 777 + struct wdt87xx_data *wdt = i2c_get_clientdata(client); 778 + int error; 779 + 780 + error = wdt87xx_validate_firmware(wdt, fw); 781 + if (error) 782 + return error; 783 + 784 + error = mutex_lock_interruptible(&wdt->fw_mutex); 785 + if (error) 786 + return error; 787 + 788 + disable_irq(client->irq); 789 + 790 + error = wdt87xx_load_chunk(client, fw, chunk_id); 791 + if (error) { 792 + dev_err(&client->dev, 793 + "firmware load failed (type: %d): %d\n", 794 + chunk_id, error); 795 + goto out; 796 + } 797 + 798 + error = wdt87xx_sw_reset(client); 799 + if (error) { 800 + dev_err(&client->dev, "soft reset failed: %d\n", error); 801 + goto out; 802 + } 803 + 804 + /* Refresh the parameters */ 805 + error = wdt87xx_get_sysparam(client, &wdt->param); 806 + if (error) 807 + dev_err(&client->dev, 808 + "failed to refresh system paramaters: %d\n", error); 809 + out: 810 + enable_irq(client->irq); 811 + mutex_unlock(&wdt->fw_mutex); 812 + 813 + return error ? error : 0; 814 + } 815 + 816 + static int wdt87xx_update_firmware(struct device *dev, 817 + const char *fw_name, unsigned int chunk_id) 818 + { 819 + struct i2c_client *client = to_i2c_client(dev); 820 + const struct firmware *fw; 821 + int error; 822 + 823 + error = request_firmware(&fw, fw_name, dev); 824 + if (error) { 825 + dev_err(&client->dev, "unable to retrieve firmware %s: %d\n", 826 + fw_name, error); 827 + return error; 828 + } 829 + 830 + error = wdt87xx_do_update_firmware(client, fw, chunk_id); 831 + 832 + release_firmware(fw); 833 + 834 + return error ? error : 0; 835 + } 836 + 837 + static ssize_t config_csum_show(struct device *dev, 838 + struct device_attribute *attr, char *buf) 839 + { 840 + struct i2c_client *client = to_i2c_client(dev); 841 + struct wdt87xx_data *wdt = i2c_get_clientdata(client); 842 + u32 cfg_csum; 843 + 844 + cfg_csum = wdt->param.xmls_id1; 845 + cfg_csum = (cfg_csum << 16) | wdt->param.xmls_id2; 846 + 847 + return scnprintf(buf, PAGE_SIZE, "%x\n", cfg_csum); 848 + } 849 + 850 + static ssize_t fw_version_show(struct device *dev, 851 + struct device_attribute *attr, char *buf) 852 + { 853 + struct i2c_client *client = to_i2c_client(dev); 854 + struct wdt87xx_data *wdt = i2c_get_clientdata(client); 855 + 856 + return scnprintf(buf, PAGE_SIZE, "%x\n", wdt->param.fw_id); 857 + } 858 + 859 + static ssize_t plat_id_show(struct device *dev, 860 + struct device_attribute *attr, char *buf) 861 + { 862 + struct i2c_client *client = to_i2c_client(dev); 863 + struct wdt87xx_data *wdt = i2c_get_clientdata(client); 864 + 865 + return scnprintf(buf, PAGE_SIZE, "%x\n", wdt->param.plat_id); 866 + } 867 + 868 + static ssize_t update_config_store(struct device *dev, 869 + struct device_attribute *attr, 870 + const char *buf, size_t count) 871 + { 872 + int error; 873 + 874 + error = wdt87xx_update_firmware(dev, WDT87XX_CFG_NAME, CHUNK_ID_CNFG); 875 + 876 + return error ? error : count; 877 + } 878 + 879 + static ssize_t update_fw_store(struct device *dev, 880 + struct device_attribute *attr, 881 + const char *buf, size_t count) 882 + { 883 + int error; 884 + 885 + error = wdt87xx_update_firmware(dev, WDT87XX_FW_NAME, CHUNK_ID_FRWR); 886 + 887 + return error ? error : count; 888 + } 889 + 890 + static DEVICE_ATTR_RO(config_csum); 891 + static DEVICE_ATTR_RO(fw_version); 892 + static DEVICE_ATTR_RO(plat_id); 893 + static DEVICE_ATTR_WO(update_config); 894 + static DEVICE_ATTR_WO(update_fw); 895 + 896 + static struct attribute *wdt87xx_attrs[] = { 897 + &dev_attr_config_csum.attr, 898 + &dev_attr_fw_version.attr, 899 + &dev_attr_plat_id.attr, 900 + &dev_attr_update_config.attr, 901 + &dev_attr_update_fw.attr, 902 + NULL 903 + }; 904 + 905 + static const struct attribute_group wdt87xx_attr_group = { 906 + .attrs = wdt87xx_attrs, 907 + }; 908 + 909 + static void wdt87xx_report_contact(struct input_dev *input, 910 + struct wdt87xx_sys_param *param, 911 + u8 *buf) 912 + { 913 + int finger_id; 914 + u32 x, y, w; 915 + u8 p; 916 + 917 + finger_id = (buf[FINGER_EV_V1_OFFSET_ID] >> 3) - 1; 918 + if (finger_id < 0) 919 + return; 920 + 921 + /* Check if this is an active contact */ 922 + if (!(buf[FINGER_EV_V1_OFFSET_ID] & 0x1)) 923 + return; 924 + 925 + w = buf[FINGER_EV_V1_OFFSET_W]; 926 + w *= param->scaling_factor; 927 + 928 + p = buf[FINGER_EV_V1_OFFSET_P]; 929 + 930 + x = get_unaligned_le16(buf + FINGER_EV_V1_OFFSET_X); 931 + 932 + y = get_unaligned_le16(buf + FINGER_EV_V1_OFFSET_Y); 933 + y = DIV_ROUND_CLOSEST(y * param->phy_h, param->phy_w); 934 + 935 + /* Refuse incorrect coordinates */ 936 + if (x > param->max_x || y > param->max_y) 937 + return; 938 + 939 + dev_dbg(input->dev.parent, "tip on (%d), x(%d), y(%d)\n", 940 + finger_id, x, y); 941 + 942 + input_mt_slot(input, finger_id); 943 + input_mt_report_slot_state(input, MT_TOOL_FINGER, 1); 944 + input_report_abs(input, ABS_MT_TOUCH_MAJOR, w); 945 + input_report_abs(input, ABS_MT_PRESSURE, p); 946 + input_report_abs(input, ABS_MT_POSITION_X, x); 947 + input_report_abs(input, ABS_MT_POSITION_Y, y); 948 + } 949 + 950 + static irqreturn_t wdt87xx_ts_interrupt(int irq, void *dev_id) 951 + { 952 + struct wdt87xx_data *wdt = dev_id; 953 + struct i2c_client *client = wdt->client; 954 + int i, fingers; 955 + int error; 956 + u8 raw_buf[WDT_V1_RAW_BUF_COUNT] = {0}; 957 + 958 + error = i2c_master_recv(client, raw_buf, WDT_V1_RAW_BUF_COUNT); 959 + if (error < 0) { 960 + dev_err(&client->dev, "read v1 raw data failed: %d\n", error); 961 + goto irq_exit; 962 + } 963 + 964 + fingers = raw_buf[TOUCH_PK_V1_OFFSET_FNGR_NUM]; 965 + if (!fingers) 966 + goto irq_exit; 967 + 968 + for (i = 0; i < WDT_MAX_FINGER; i++) 969 + wdt87xx_report_contact(wdt->input, 970 + &wdt->param, 971 + &raw_buf[TOUCH_PK_V1_OFFSET_EVENT + 972 + i * FINGER_EV_V1_SIZE]); 973 + 974 + input_mt_sync_frame(wdt->input); 975 + input_sync(wdt->input); 976 + 977 + irq_exit: 978 + return IRQ_HANDLED; 979 + } 980 + 981 + static int wdt87xx_ts_create_input_device(struct wdt87xx_data *wdt) 982 + { 983 + struct device *dev = &wdt->client->dev; 984 + struct input_dev *input; 985 + unsigned int res = DIV_ROUND_CLOSEST(MAX_UNIT_AXIS, wdt->param.phy_w); 986 + int error; 987 + 988 + input = devm_input_allocate_device(dev); 989 + if (!input) { 990 + dev_err(dev, "failed to allocate input device\n"); 991 + return -ENOMEM; 992 + } 993 + wdt->input = input; 994 + 995 + input->name = "WDT87xx Touchscreen"; 996 + input->id.bustype = BUS_I2C; 997 + input->phys = wdt->phys; 998 + 999 + input_set_abs_params(input, ABS_MT_POSITION_X, 0, 1000 + wdt->param.max_x, 0, 0); 1001 + input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 1002 + wdt->param.max_y, 0, 0); 1003 + input_abs_set_res(input, ABS_MT_POSITION_X, res); 1004 + input_abs_set_res(input, ABS_MT_POSITION_Y, res); 1005 + 1006 + input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 1007 + 0, wdt->param.max_x, 0, 0); 1008 + input_set_abs_params(input, ABS_MT_PRESSURE, 0, 0xFF, 0, 0); 1009 + 1010 + input_mt_init_slots(input, WDT_MAX_FINGER, 1011 + INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); 1012 + 1013 + error = input_register_device(input); 1014 + if (error) { 1015 + dev_err(dev, "failed to register input device: %d\n", error); 1016 + return error; 1017 + } 1018 + 1019 + return 0; 1020 + } 1021 + 1022 + static int wdt87xx_ts_probe(struct i2c_client *client, 1023 + const struct i2c_device_id *id) 1024 + { 1025 + struct wdt87xx_data *wdt; 1026 + int error; 1027 + 1028 + dev_dbg(&client->dev, "adapter=%d, client irq: %d\n", 1029 + client->adapter->nr, client->irq); 1030 + 1031 + /* Check if the I2C function is ok in this adaptor */ 1032 + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) 1033 + return -ENXIO; 1034 + 1035 + wdt = devm_kzalloc(&client->dev, sizeof(*wdt), GFP_KERNEL); 1036 + if (!wdt) 1037 + return -ENOMEM; 1038 + 1039 + wdt->client = client; 1040 + mutex_init(&wdt->fw_mutex); 1041 + i2c_set_clientdata(client, wdt); 1042 + 1043 + snprintf(wdt->phys, sizeof(wdt->phys), "i2c-%u-%04x/input0", 1044 + client->adapter->nr, client->addr); 1045 + 1046 + error = wdt87xx_get_sysparam(client, &wdt->param); 1047 + if (error) 1048 + return error; 1049 + 1050 + error = wdt87xx_ts_create_input_device(wdt); 1051 + if (error) 1052 + return error; 1053 + 1054 + error = devm_request_threaded_irq(&client->dev, client->irq, 1055 + NULL, wdt87xx_ts_interrupt, 1056 + IRQF_ONESHOT, 1057 + client->name, wdt); 1058 + if (error) { 1059 + dev_err(&client->dev, "request irq failed: %d\n", error); 1060 + return error; 1061 + } 1062 + 1063 + error = sysfs_create_group(&client->dev.kobj, &wdt87xx_attr_group); 1064 + if (error) { 1065 + dev_err(&client->dev, "create sysfs failed: %d\n", error); 1066 + return error; 1067 + } 1068 + 1069 + return 0; 1070 + } 1071 + 1072 + static int wdt87xx_ts_remove(struct i2c_client *client) 1073 + { 1074 + sysfs_remove_group(&client->dev.kobj, &wdt87xx_attr_group); 1075 + 1076 + return 0; 1077 + } 1078 + 1079 + static int __maybe_unused wdt87xx_suspend(struct device *dev) 1080 + { 1081 + struct i2c_client *client = to_i2c_client(dev); 1082 + int error; 1083 + 1084 + disable_irq(client->irq); 1085 + 1086 + error = wdt87xx_send_command(client, VND_CMD_STOP, MODE_IDLE); 1087 + if (error) { 1088 + enable_irq(client->irq); 1089 + dev_err(&client->dev, 1090 + "failed to stop device when suspending: %d\n", 1091 + error); 1092 + return error; 1093 + } 1094 + 1095 + return 0; 1096 + } 1097 + 1098 + static int __maybe_unused wdt87xx_resume(struct device *dev) 1099 + { 1100 + struct i2c_client *client = to_i2c_client(dev); 1101 + int error; 1102 + 1103 + /* 1104 + * The chip may have been reset while system is resuming, 1105 + * give it some time to settle. 1106 + */ 1107 + mdelay(100); 1108 + 1109 + error = wdt87xx_send_command(client, VND_CMD_START, 0); 1110 + if (error) 1111 + dev_err(&client->dev, 1112 + "failed to start device when resuming: %d\n", 1113 + error); 1114 + 1115 + enable_irq(client->irq); 1116 + 1117 + return 0; 1118 + } 1119 + 1120 + static SIMPLE_DEV_PM_OPS(wdt87xx_pm_ops, wdt87xx_suspend, wdt87xx_resume); 1121 + 1122 + static const struct i2c_device_id wdt87xx_dev_id[] = { 1123 + { WDT87XX_NAME, 0 }, 1124 + { } 1125 + }; 1126 + MODULE_DEVICE_TABLE(i2c, wdt87xx_dev_id); 1127 + 1128 + static const struct acpi_device_id wdt87xx_acpi_id[] = { 1129 + { "WDHT0001", 0 }, 1130 + { } 1131 + }; 1132 + MODULE_DEVICE_TABLE(acpi, wdt87xx_acpi_id); 1133 + 1134 + static struct i2c_driver wdt87xx_driver = { 1135 + .probe = wdt87xx_ts_probe, 1136 + .remove = wdt87xx_ts_remove, 1137 + .id_table = wdt87xx_dev_id, 1138 + .driver = { 1139 + .name = WDT87XX_NAME, 1140 + .pm = &wdt87xx_pm_ops, 1141 + .acpi_match_table = ACPI_PTR(wdt87xx_acpi_id), 1142 + }, 1143 + }; 1144 + module_i2c_driver(wdt87xx_driver); 1145 + 1146 + MODULE_AUTHOR("HN Chen <hn.chen@weidahitech.com>"); 1147 + MODULE_DESCRIPTION("WeidaHiTech WDT87XX Touchscreen driver"); 1148 + MODULE_VERSION(WDT87XX_DRV_VER); 1149 + MODULE_LICENSE("GPL");
+3 -2
include/linux/input/touchscreen.h
··· 12 12 #include <linux/input.h> 13 13 14 14 #ifdef CONFIG_OF 15 - void touchscreen_parse_of_params(struct input_dev *dev); 15 + void touchscreen_parse_of_params(struct input_dev *dev, bool multitouch); 16 16 #else 17 - static inline void touchscreen_parse_of_params(struct input_dev *dev) 17 + static inline void touchscreen_parse_of_params(struct input_dev *dev, 18 + bool multitouch) 18 19 { 19 20 } 20 21 #endif