diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2018-05-24 12:30:15 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2018-05-24 12:30:15 -0400 |
commit | 754451342fc5954061ede74b0a8485ec4a4c6eaa (patch) | |
tree | 82daccba5779de492631c42e47a614bd9d4cddd2 /drivers/input | |
parent | bf232e460a3530adf17da7d7f1332347b73a3d08 (diff) | |
parent | 771c577c23bac90597c685971d7297ea00f99d11 (diff) |
Merge tag 'v4.17-rc6' into next
Sync up with mainline to bring in Atmel controller changes for Caroline.
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/input-leds.c | 8 | ||||
-rw-r--r-- | drivers/input/joystick/analog.c | 2 | ||||
-rw-r--r-- | drivers/input/joystick/xpad.c | 9 | ||||
-rw-r--r-- | drivers/input/keyboard/Kconfig | 9 | ||||
-rw-r--r-- | drivers/input/keyboard/Makefile | 1 | ||||
-rw-r--r-- | drivers/input/keyboard/bf54x-keys.c | 396 | ||||
-rw-r--r-- | drivers/input/keyboard/stmpe-keypad.c | 16 | ||||
-rw-r--r-- | drivers/input/misc/Kconfig | 9 | ||||
-rw-r--r-- | drivers/input/misc/Makefile | 1 | ||||
-rw-r--r-- | drivers/input/misc/bfin_rotary.c | 294 | ||||
-rw-r--r-- | drivers/input/mouse/alps.c | 26 | ||||
-rw-r--r-- | drivers/input/rmi4/rmi_spi.c | 7 | ||||
-rw-r--r-- | drivers/input/serio/gscps2.c | 11 | ||||
-rw-r--r-- | drivers/input/serio/i8042-x86ia64io.h | 7 | ||||
-rw-r--r-- | drivers/input/touchscreen/Kconfig | 2 | ||||
-rw-r--r-- | drivers/input/touchscreen/atmel_mxt_ts.c | 200 | ||||
-rw-r--r-- | drivers/input/touchscreen/silead.c | 1 | ||||
-rw-r--r-- | drivers/input/touchscreen/sur40.c | 178 |
18 files changed, 366 insertions, 811 deletions
diff --git a/drivers/input/input-leds.c b/drivers/input/input-leds.c index 766bf2660116..5f04b2d94635 100644 --- a/drivers/input/input-leds.c +++ b/drivers/input/input-leds.c | |||
@@ -88,6 +88,7 @@ static int input_leds_connect(struct input_handler *handler, | |||
88 | const struct input_device_id *id) | 88 | const struct input_device_id *id) |
89 | { | 89 | { |
90 | struct input_leds *leds; | 90 | struct input_leds *leds; |
91 | struct input_led *led; | ||
91 | unsigned int num_leds; | 92 | unsigned int num_leds; |
92 | unsigned int led_code; | 93 | unsigned int led_code; |
93 | int led_no; | 94 | int led_no; |
@@ -119,14 +120,13 @@ static int input_leds_connect(struct input_handler *handler, | |||
119 | 120 | ||
120 | led_no = 0; | 121 | led_no = 0; |
121 | for_each_set_bit(led_code, dev->ledbit, LED_CNT) { | 122 | for_each_set_bit(led_code, dev->ledbit, LED_CNT) { |
122 | struct input_led *led = &leds->leds[led_no]; | 123 | if (!input_led_info[led_code].name) |
124 | continue; | ||
123 | 125 | ||
126 | led = &leds->leds[led_no]; | ||
124 | led->handle = &leds->handle; | 127 | led->handle = &leds->handle; |
125 | led->code = led_code; | 128 | led->code = led_code; |
126 | 129 | ||
127 | if (!input_led_info[led_code].name) | ||
128 | continue; | ||
129 | |||
130 | led->cdev.name = kasprintf(GFP_KERNEL, "%s::%s", | 130 | led->cdev.name = kasprintf(GFP_KERNEL, "%s::%s", |
131 | dev_name(&dev->dev), | 131 | dev_name(&dev->dev), |
132 | input_led_info[led_code].name); | 132 | input_led_info[led_code].name); |
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index c868a878c84f..c79dbcb4d146 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c | |||
@@ -163,7 +163,7 @@ static unsigned int get_time_pit(void) | |||
163 | #define GET_TIME(x) do { x = (unsigned int)rdtsc(); } while (0) | 163 | #define GET_TIME(x) do { x = (unsigned int)rdtsc(); } while (0) |
164 | #define DELTA(x,y) ((y)-(x)) | 164 | #define DELTA(x,y) ((y)-(x)) |
165 | #define TIME_NAME "TSC" | 165 | #define TIME_NAME "TSC" |
166 | #elif defined(__alpha__) || defined(CONFIG_MN10300) || defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined(CONFIG_RISCV) || defined(CONFIG_TILE) | 166 | #elif defined(__alpha__) || defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined(CONFIG_PPC) || defined(CONFIG_RISCV) |
167 | #define GET_TIME(x) do { x = get_cycles(); } while (0) | 167 | #define GET_TIME(x) do { x = get_cycles(); } while (0) |
168 | #define DELTA(x,y) ((y)-(x)) | 168 | #define DELTA(x,y) ((y)-(x)) |
169 | #define TIME_NAME "get_cycles" | 169 | #define TIME_NAME "get_cycles" |
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index cef21b2c4e6e..f5d2b5147dd4 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
@@ -229,6 +229,7 @@ static const struct xpad_device { | |||
229 | { 0x0e6f, 0x021f, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, | 229 | { 0x0e6f, 0x021f, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, |
230 | { 0x0e6f, 0x0246, "Rock Candy Gamepad for Xbox One 2015", 0, XTYPE_XBOXONE }, | 230 | { 0x0e6f, 0x0246, "Rock Candy Gamepad for Xbox One 2015", 0, XTYPE_XBOXONE }, |
231 | { 0x0e6f, 0x02ab, "PDP Controller for Xbox One", 0, XTYPE_XBOXONE }, | 231 | { 0x0e6f, 0x02ab, "PDP Controller for Xbox One", 0, XTYPE_XBOXONE }, |
232 | { 0x0e6f, 0x02a4, "PDP Wired Controller for Xbox One - Stealth Series", 0, XTYPE_XBOXONE }, | ||
232 | { 0x0e6f, 0x0301, "Logic3 Controller", 0, XTYPE_XBOX360 }, | 233 | { 0x0e6f, 0x0301, "Logic3 Controller", 0, XTYPE_XBOX360 }, |
233 | { 0x0e6f, 0x0346, "Rock Candy Gamepad for Xbox One 2016", 0, XTYPE_XBOXONE }, | 234 | { 0x0e6f, 0x0346, "Rock Candy Gamepad for Xbox One 2016", 0, XTYPE_XBOXONE }, |
234 | { 0x0e6f, 0x0401, "Logic3 Controller", 0, XTYPE_XBOX360 }, | 235 | { 0x0e6f, 0x0401, "Logic3 Controller", 0, XTYPE_XBOX360 }, |
@@ -477,7 +478,8 @@ static const u8 xboxone_hori_init[] = { | |||
477 | 478 | ||
478 | /* | 479 | /* |
479 | * This packet is required for some of the PDP pads to start | 480 | * This packet is required for some of the PDP pads to start |
480 | * sending input reports. One of those pads is (0x0e6f:0x02ab). | 481 | * sending input reports. These pads include: (0x0e6f:0x02ab), |
482 | * (0x0e6f:0x02a4). | ||
481 | */ | 483 | */ |
482 | static const u8 xboxone_pdp_init1[] = { | 484 | static const u8 xboxone_pdp_init1[] = { |
483 | 0x0a, 0x20, 0x00, 0x03, 0x00, 0x01, 0x14 | 485 | 0x0a, 0x20, 0x00, 0x03, 0x00, 0x01, 0x14 |
@@ -485,7 +487,8 @@ static const u8 xboxone_pdp_init1[] = { | |||
485 | 487 | ||
486 | /* | 488 | /* |
487 | * This packet is required for some of the PDP pads to start | 489 | * This packet is required for some of the PDP pads to start |
488 | * sending input reports. One of those pads is (0x0e6f:0x02ab). | 490 | * sending input reports. These pads include: (0x0e6f:0x02ab), |
491 | * (0x0e6f:0x02a4). | ||
489 | */ | 492 | */ |
490 | static const u8 xboxone_pdp_init2[] = { | 493 | static const u8 xboxone_pdp_init2[] = { |
491 | 0x06, 0x20, 0x00, 0x02, 0x01, 0x00 | 494 | 0x06, 0x20, 0x00, 0x02, 0x01, 0x00 |
@@ -523,6 +526,8 @@ static const struct xboxone_init_packet xboxone_init_packets[] = { | |||
523 | XBOXONE_INIT_PKT(0x0000, 0x0000, xboxone_fw2015_init), | 526 | XBOXONE_INIT_PKT(0x0000, 0x0000, xboxone_fw2015_init), |
524 | XBOXONE_INIT_PKT(0x0e6f, 0x02ab, xboxone_pdp_init1), | 527 | XBOXONE_INIT_PKT(0x0e6f, 0x02ab, xboxone_pdp_init1), |
525 | XBOXONE_INIT_PKT(0x0e6f, 0x02ab, xboxone_pdp_init2), | 528 | XBOXONE_INIT_PKT(0x0e6f, 0x02ab, xboxone_pdp_init2), |
529 | XBOXONE_INIT_PKT(0x0e6f, 0x02a4, xboxone_pdp_init1), | ||
530 | XBOXONE_INIT_PKT(0x0e6f, 0x02a4, xboxone_pdp_init2), | ||
526 | XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_rumblebegin_init), | 531 | XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_rumblebegin_init), |
527 | XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_rumblebegin_init), | 532 | XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_rumblebegin_init), |
528 | XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumblebegin_init), | 533 | XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumblebegin_init), |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 4c4ab1ced235..2b469cc47a78 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -157,15 +157,6 @@ config KEYBOARD_QT2160 | |||
157 | This driver can also be built as a module. If so, the module | 157 | This driver can also be built as a module. If so, the module |
158 | will be called qt2160. | 158 | will be called qt2160. |
159 | 159 | ||
160 | config KEYBOARD_BFIN | ||
161 | tristate "Blackfin BF54x keypad support" | ||
162 | depends on (BF54x && !BF544) | ||
163 | help | ||
164 | Say Y here if you want to use the BF54x keypad. | ||
165 | |||
166 | To compile this driver as a module, choose M here: the | ||
167 | module will be called bf54x-keys. | ||
168 | |||
169 | config KEYBOARD_CLPS711X | 160 | config KEYBOARD_CLPS711X |
170 | tristate "CLPS711X Keypad support" | 161 | tristate "CLPS711X Keypad support" |
171 | depends on OF_GPIO && (ARCH_CLPS711X || COMPILE_TEST) | 162 | depends on OF_GPIO && (ARCH_CLPS711X || COMPILE_TEST) |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 526e68294e6e..8fab920afa58 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -13,7 +13,6 @@ obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o | |||
13 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o | 13 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o |
14 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o | 14 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o |
15 | obj-$(CONFIG_KEYBOARD_BCM) += bcm-keypad.o | 15 | obj-$(CONFIG_KEYBOARD_BCM) += bcm-keypad.o |
16 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o | ||
17 | obj-$(CONFIG_KEYBOARD_CAP11XX) += cap11xx.o | 16 | obj-$(CONFIG_KEYBOARD_CAP11XX) += cap11xx.o |
18 | obj-$(CONFIG_KEYBOARD_CLPS711X) += clps711x-keypad.o | 17 | obj-$(CONFIG_KEYBOARD_CLPS711X) += clps711x-keypad.o |
19 | obj-$(CONFIG_KEYBOARD_CROS_EC) += cros_ec_keyb.o | 18 | obj-$(CONFIG_KEYBOARD_CROS_EC) += cros_ec_keyb.o |
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c deleted file mode 100644 index 8a07a426f88e..000000000000 --- a/drivers/input/keyboard/bf54x-keys.c +++ /dev/null | |||
@@ -1,396 +0,0 @@ | |||
1 | /* | ||
2 | * File: drivers/input/keyboard/bf54x-keys.c | ||
3 | * Based on: | ||
4 | * Author: Michael Hennerich <hennerich@blackfin.uclinux.org> | ||
5 | * | ||
6 | * Created: | ||
7 | * Description: keypad driver for Analog Devices Blackfin BF54x Processors | ||
8 | * | ||
9 | * | ||
10 | * Modified: | ||
11 | * Copyright 2007-2008 Analog Devices Inc. | ||
12 | * | ||
13 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, see the file COPYING, or write | ||
27 | * to the Free Software Foundation, Inc., | ||
28 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
29 | */ | ||
30 | |||
31 | #include <linux/module.h> | ||
32 | |||
33 | #include <linux/fs.h> | ||
34 | #include <linux/interrupt.h> | ||
35 | #include <linux/irq.h> | ||
36 | #include <linux/slab.h> | ||
37 | #include <linux/sched.h> | ||
38 | #include <linux/pm.h> | ||
39 | #include <linux/sysctl.h> | ||
40 | #include <linux/proc_fs.h> | ||
41 | #include <linux/delay.h> | ||
42 | #include <linux/platform_device.h> | ||
43 | #include <linux/input.h> | ||
44 | |||
45 | #include <asm/portmux.h> | ||
46 | #include <mach/bf54x_keys.h> | ||
47 | |||
48 | #define DRV_NAME "bf54x-keys" | ||
49 | #define TIME_SCALE 100 /* 100 ns */ | ||
50 | #define MAX_MULT (0xFF * TIME_SCALE) | ||
51 | #define MAX_RC 8 /* Max Row/Col */ | ||
52 | |||
53 | static const u16 per_rows[] = { | ||
54 | P_KEY_ROW7, | ||
55 | P_KEY_ROW6, | ||
56 | P_KEY_ROW5, | ||
57 | P_KEY_ROW4, | ||
58 | P_KEY_ROW3, | ||
59 | P_KEY_ROW2, | ||
60 | P_KEY_ROW1, | ||
61 | P_KEY_ROW0, | ||
62 | 0 | ||
63 | }; | ||
64 | |||
65 | static const u16 per_cols[] = { | ||
66 | P_KEY_COL7, | ||
67 | P_KEY_COL6, | ||
68 | P_KEY_COL5, | ||
69 | P_KEY_COL4, | ||
70 | P_KEY_COL3, | ||
71 | P_KEY_COL2, | ||
72 | P_KEY_COL1, | ||
73 | P_KEY_COL0, | ||
74 | 0 | ||
75 | }; | ||
76 | |||
77 | struct bf54x_kpad { | ||
78 | struct input_dev *input; | ||
79 | int irq; | ||
80 | unsigned short lastkey; | ||
81 | unsigned short *keycode; | ||
82 | struct timer_list timer; | ||
83 | unsigned int keyup_test_jiffies; | ||
84 | unsigned short kpad_msel; | ||
85 | unsigned short kpad_prescale; | ||
86 | unsigned short kpad_ctl; | ||
87 | }; | ||
88 | |||
89 | static inline int bfin_kpad_find_key(struct bf54x_kpad *bf54x_kpad, | ||
90 | struct input_dev *input, u16 keyident) | ||
91 | { | ||
92 | u16 i; | ||
93 | |||
94 | for (i = 0; i < input->keycodemax; i++) | ||
95 | if (bf54x_kpad->keycode[i + input->keycodemax] == keyident) | ||
96 | return bf54x_kpad->keycode[i]; | ||
97 | return -1; | ||
98 | } | ||
99 | |||
100 | static inline void bfin_keycodecpy(unsigned short *keycode, | ||
101 | const unsigned int *pdata_kc, | ||
102 | unsigned short keymapsize) | ||
103 | { | ||
104 | unsigned int i; | ||
105 | |||
106 | for (i = 0; i < keymapsize; i++) { | ||
107 | keycode[i] = pdata_kc[i] & 0xffff; | ||
108 | keycode[i + keymapsize] = pdata_kc[i] >> 16; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | static inline u16 bfin_kpad_get_prescale(u32 timescale) | ||
113 | { | ||
114 | u32 sclk = get_sclk(); | ||
115 | |||
116 | return ((((sclk / 1000) * timescale) / 1024) - 1); | ||
117 | } | ||
118 | |||
119 | static inline u16 bfin_kpad_get_keypressed(struct bf54x_kpad *bf54x_kpad) | ||
120 | { | ||
121 | return (bfin_read_KPAD_STAT() & KPAD_PRESSED); | ||
122 | } | ||
123 | |||
124 | static inline void bfin_kpad_clear_irq(void) | ||
125 | { | ||
126 | bfin_write_KPAD_STAT(0xFFFF); | ||
127 | bfin_write_KPAD_ROWCOL(0xFFFF); | ||
128 | } | ||
129 | |||
130 | static void bfin_kpad_timer(struct timer_list *t) | ||
131 | { | ||
132 | struct bf54x_kpad *bf54x_kpad = from_timer(bf54x_kpad, t, timer); | ||
133 | |||
134 | if (bfin_kpad_get_keypressed(bf54x_kpad)) { | ||
135 | /* Try again later */ | ||
136 | mod_timer(&bf54x_kpad->timer, | ||
137 | jiffies + bf54x_kpad->keyup_test_jiffies); | ||
138 | return; | ||
139 | } | ||
140 | |||
141 | input_report_key(bf54x_kpad->input, bf54x_kpad->lastkey, 0); | ||
142 | input_sync(bf54x_kpad->input); | ||
143 | |||
144 | /* Clear IRQ Status */ | ||
145 | |||
146 | bfin_kpad_clear_irq(); | ||
147 | enable_irq(bf54x_kpad->irq); | ||
148 | } | ||
149 | |||
150 | static irqreturn_t bfin_kpad_isr(int irq, void *dev_id) | ||
151 | { | ||
152 | struct platform_device *pdev = dev_id; | ||
153 | struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); | ||
154 | struct input_dev *input = bf54x_kpad->input; | ||
155 | int key; | ||
156 | u16 rowcol = bfin_read_KPAD_ROWCOL(); | ||
157 | |||
158 | key = bfin_kpad_find_key(bf54x_kpad, input, rowcol); | ||
159 | |||
160 | input_report_key(input, key, 1); | ||
161 | input_sync(input); | ||
162 | |||
163 | if (bfin_kpad_get_keypressed(bf54x_kpad)) { | ||
164 | disable_irq_nosync(bf54x_kpad->irq); | ||
165 | bf54x_kpad->lastkey = key; | ||
166 | mod_timer(&bf54x_kpad->timer, | ||
167 | jiffies + bf54x_kpad->keyup_test_jiffies); | ||
168 | } else { | ||
169 | input_report_key(input, key, 0); | ||
170 | input_sync(input); | ||
171 | |||
172 | bfin_kpad_clear_irq(); | ||
173 | } | ||
174 | |||
175 | return IRQ_HANDLED; | ||
176 | } | ||
177 | |||
178 | static int bfin_kpad_probe(struct platform_device *pdev) | ||
179 | { | ||
180 | struct bf54x_kpad *bf54x_kpad; | ||
181 | struct bfin_kpad_platform_data *pdata = dev_get_platdata(&pdev->dev); | ||
182 | struct input_dev *input; | ||
183 | int i, error; | ||
184 | |||
185 | if (!pdata->rows || !pdata->cols || !pdata->keymap) { | ||
186 | dev_err(&pdev->dev, "no rows, cols or keymap from pdata\n"); | ||
187 | return -EINVAL; | ||
188 | } | ||
189 | |||
190 | if (!pdata->keymapsize || | ||
191 | pdata->keymapsize > (pdata->rows * pdata->cols)) { | ||
192 | dev_err(&pdev->dev, "invalid keymapsize\n"); | ||
193 | return -EINVAL; | ||
194 | } | ||
195 | |||
196 | bf54x_kpad = kzalloc(sizeof(struct bf54x_kpad), GFP_KERNEL); | ||
197 | if (!bf54x_kpad) | ||
198 | return -ENOMEM; | ||
199 | |||
200 | platform_set_drvdata(pdev, bf54x_kpad); | ||
201 | |||
202 | /* Allocate memory for keymap followed by private LUT */ | ||
203 | bf54x_kpad->keycode = kmalloc(pdata->keymapsize * | ||
204 | sizeof(unsigned short) * 2, GFP_KERNEL); | ||
205 | if (!bf54x_kpad->keycode) { | ||
206 | error = -ENOMEM; | ||
207 | goto out; | ||
208 | } | ||
209 | |||
210 | if (!pdata->debounce_time || pdata->debounce_time > MAX_MULT || | ||
211 | !pdata->coldrive_time || pdata->coldrive_time > MAX_MULT) { | ||
212 | dev_warn(&pdev->dev, | ||
213 | "invalid platform debounce/columndrive time\n"); | ||
214 | bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ | ||
215 | } else { | ||
216 | bfin_write_KPAD_MSEL( | ||
217 | ((pdata->debounce_time / TIME_SCALE) | ||
218 | & DBON_SCALE) | | ||
219 | (((pdata->coldrive_time / TIME_SCALE) << 8) | ||
220 | & COLDRV_SCALE)); | ||
221 | |||
222 | } | ||
223 | |||
224 | if (!pdata->keyup_test_interval) | ||
225 | bf54x_kpad->keyup_test_jiffies = msecs_to_jiffies(50); | ||
226 | else | ||
227 | bf54x_kpad->keyup_test_jiffies = | ||
228 | msecs_to_jiffies(pdata->keyup_test_interval); | ||
229 | |||
230 | if (peripheral_request_list((u16 *)&per_rows[MAX_RC - pdata->rows], | ||
231 | DRV_NAME)) { | ||
232 | dev_err(&pdev->dev, "requesting peripherals failed\n"); | ||
233 | error = -EFAULT; | ||
234 | goto out0; | ||
235 | } | ||
236 | |||
237 | if (peripheral_request_list((u16 *)&per_cols[MAX_RC - pdata->cols], | ||
238 | DRV_NAME)) { | ||
239 | dev_err(&pdev->dev, "requesting peripherals failed\n"); | ||
240 | error = -EFAULT; | ||
241 | goto out1; | ||
242 | } | ||
243 | |||
244 | bf54x_kpad->irq = platform_get_irq(pdev, 0); | ||
245 | if (bf54x_kpad->irq < 0) { | ||
246 | error = -ENODEV; | ||
247 | goto out2; | ||
248 | } | ||
249 | |||
250 | error = request_irq(bf54x_kpad->irq, bfin_kpad_isr, | ||
251 | 0, DRV_NAME, pdev); | ||
252 | if (error) { | ||
253 | dev_err(&pdev->dev, "unable to claim irq %d\n", | ||
254 | bf54x_kpad->irq); | ||
255 | goto out2; | ||
256 | } | ||
257 | |||
258 | input = input_allocate_device(); | ||
259 | if (!input) { | ||
260 | error = -ENOMEM; | ||
261 | goto out3; | ||
262 | } | ||
263 | |||
264 | bf54x_kpad->input = input; | ||
265 | |||
266 | input->name = pdev->name; | ||
267 | input->phys = "bf54x-keys/input0"; | ||
268 | input->dev.parent = &pdev->dev; | ||
269 | |||
270 | input->id.bustype = BUS_HOST; | ||
271 | input->id.vendor = 0x0001; | ||
272 | input->id.product = 0x0001; | ||
273 | input->id.version = 0x0100; | ||
274 | |||
275 | input->keycodesize = sizeof(unsigned short); | ||
276 | input->keycodemax = pdata->keymapsize; | ||
277 | input->keycode = bf54x_kpad->keycode; | ||
278 | |||
279 | bfin_keycodecpy(bf54x_kpad->keycode, pdata->keymap, pdata->keymapsize); | ||
280 | |||
281 | /* setup input device */ | ||
282 | __set_bit(EV_KEY, input->evbit); | ||
283 | |||
284 | if (pdata->repeat) | ||
285 | __set_bit(EV_REP, input->evbit); | ||
286 | |||
287 | for (i = 0; i < input->keycodemax; i++) | ||
288 | if (bf54x_kpad->keycode[i] <= KEY_MAX) | ||
289 | __set_bit(bf54x_kpad->keycode[i], input->keybit); | ||
290 | __clear_bit(KEY_RESERVED, input->keybit); | ||
291 | |||
292 | error = input_register_device(input); | ||
293 | if (error) { | ||
294 | dev_err(&pdev->dev, "unable to register input device\n"); | ||
295 | goto out4; | ||
296 | } | ||
297 | |||
298 | /* Init Keypad Key Up/Release test timer */ | ||
299 | |||
300 | timer_setup(&bf54x_kpad->timer, bfin_kpad_timer, 0); | ||
301 | |||
302 | bfin_write_KPAD_PRESCALE(bfin_kpad_get_prescale(TIME_SCALE)); | ||
303 | |||
304 | bfin_write_KPAD_CTL((((pdata->cols - 1) << 13) & KPAD_COLEN) | | ||
305 | (((pdata->rows - 1) << 10) & KPAD_ROWEN) | | ||
306 | (2 & KPAD_IRQMODE)); | ||
307 | |||
308 | bfin_write_KPAD_CTL(bfin_read_KPAD_CTL() | KPAD_EN); | ||
309 | |||
310 | device_init_wakeup(&pdev->dev, 1); | ||
311 | |||
312 | return 0; | ||
313 | |||
314 | out4: | ||
315 | input_free_device(input); | ||
316 | out3: | ||
317 | free_irq(bf54x_kpad->irq, pdev); | ||
318 | out2: | ||
319 | peripheral_free_list((u16 *)&per_cols[MAX_RC - pdata->cols]); | ||
320 | out1: | ||
321 | peripheral_free_list((u16 *)&per_rows[MAX_RC - pdata->rows]); | ||
322 | out0: | ||
323 | kfree(bf54x_kpad->keycode); | ||
324 | out: | ||
325 | kfree(bf54x_kpad); | ||
326 | |||
327 | return error; | ||
328 | } | ||
329 | |||
330 | static int bfin_kpad_remove(struct platform_device *pdev) | ||
331 | { | ||
332 | struct bfin_kpad_platform_data *pdata = dev_get_platdata(&pdev->dev); | ||
333 | struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); | ||
334 | |||
335 | del_timer_sync(&bf54x_kpad->timer); | ||
336 | free_irq(bf54x_kpad->irq, pdev); | ||
337 | |||
338 | input_unregister_device(bf54x_kpad->input); | ||
339 | |||
340 | peripheral_free_list((u16 *)&per_rows[MAX_RC - pdata->rows]); | ||
341 | peripheral_free_list((u16 *)&per_cols[MAX_RC - pdata->cols]); | ||
342 | |||
343 | kfree(bf54x_kpad->keycode); | ||
344 | kfree(bf54x_kpad); | ||
345 | |||
346 | return 0; | ||
347 | } | ||
348 | |||
349 | #ifdef CONFIG_PM | ||
350 | static int bfin_kpad_suspend(struct platform_device *pdev, pm_message_t state) | ||
351 | { | ||
352 | struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); | ||
353 | |||
354 | bf54x_kpad->kpad_msel = bfin_read_KPAD_MSEL(); | ||
355 | bf54x_kpad->kpad_prescale = bfin_read_KPAD_PRESCALE(); | ||
356 | bf54x_kpad->kpad_ctl = bfin_read_KPAD_CTL(); | ||
357 | |||
358 | if (device_may_wakeup(&pdev->dev)) | ||
359 | enable_irq_wake(bf54x_kpad->irq); | ||
360 | |||
361 | return 0; | ||
362 | } | ||
363 | |||
364 | static int bfin_kpad_resume(struct platform_device *pdev) | ||
365 | { | ||
366 | struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); | ||
367 | |||
368 | bfin_write_KPAD_MSEL(bf54x_kpad->kpad_msel); | ||
369 | bfin_write_KPAD_PRESCALE(bf54x_kpad->kpad_prescale); | ||
370 | bfin_write_KPAD_CTL(bf54x_kpad->kpad_ctl); | ||
371 | |||
372 | if (device_may_wakeup(&pdev->dev)) | ||
373 | disable_irq_wake(bf54x_kpad->irq); | ||
374 | |||
375 | return 0; | ||
376 | } | ||
377 | #else | ||
378 | # define bfin_kpad_suspend NULL | ||
379 | # define bfin_kpad_resume NULL | ||
380 | #endif | ||
381 | |||
382 | static struct platform_driver bfin_kpad_device_driver = { | ||
383 | .driver = { | ||
384 | .name = DRV_NAME, | ||
385 | }, | ||
386 | .probe = bfin_kpad_probe, | ||
387 | .remove = bfin_kpad_remove, | ||
388 | .suspend = bfin_kpad_suspend, | ||
389 | .resume = bfin_kpad_resume, | ||
390 | }; | ||
391 | module_platform_driver(bfin_kpad_device_driver); | ||
392 | |||
393 | MODULE_LICENSE("GPL"); | ||
394 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
395 | MODULE_DESCRIPTION("Keypad driver for BF54x Processors"); | ||
396 | MODULE_ALIAS("platform:bf54x-keys"); | ||
diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c index 8c6c0b9109c7..d69e631cfa0a 100644 --- a/drivers/input/keyboard/stmpe-keypad.c +++ b/drivers/input/keyboard/stmpe-keypad.c | |||
@@ -48,6 +48,14 @@ | |||
48 | #define STMPE_KEYPAD_KEYMAP_MAX_SIZE \ | 48 | #define STMPE_KEYPAD_KEYMAP_MAX_SIZE \ |
49 | (STMPE_KEYPAD_MAX_ROWS * STMPE_KEYPAD_MAX_COLS) | 49 | (STMPE_KEYPAD_MAX_ROWS * STMPE_KEYPAD_MAX_COLS) |
50 | 50 | ||
51 | |||
52 | #define STMPE1601_NUM_DATA 5 | ||
53 | #define STMPE2401_NUM_DATA 3 | ||
54 | #define STMPE2403_NUM_DATA 5 | ||
55 | |||
56 | /* Make sure it covers all cases above */ | ||
57 | #define MAX_NUM_DATA 5 | ||
58 | |||
51 | /** | 59 | /** |
52 | * struct stmpe_keypad_variant - model-specific attributes | 60 | * struct stmpe_keypad_variant - model-specific attributes |
53 | * @auto_increment: whether the KPC_DATA_BYTE register address | 61 | * @auto_increment: whether the KPC_DATA_BYTE register address |
@@ -74,7 +82,7 @@ struct stmpe_keypad_variant { | |||
74 | static const struct stmpe_keypad_variant stmpe_keypad_variants[] = { | 82 | static const struct stmpe_keypad_variant stmpe_keypad_variants[] = { |
75 | [STMPE1601] = { | 83 | [STMPE1601] = { |
76 | .auto_increment = true, | 84 | .auto_increment = true, |
77 | .num_data = 5, | 85 | .num_data = STMPE1601_NUM_DATA, |
78 | .num_normal_data = 3, | 86 | .num_normal_data = 3, |
79 | .max_cols = 8, | 87 | .max_cols = 8, |
80 | .max_rows = 8, | 88 | .max_rows = 8, |
@@ -84,7 +92,7 @@ static const struct stmpe_keypad_variant stmpe_keypad_variants[] = { | |||
84 | [STMPE2401] = { | 92 | [STMPE2401] = { |
85 | .auto_increment = false, | 93 | .auto_increment = false, |
86 | .set_pullup = true, | 94 | .set_pullup = true, |
87 | .num_data = 3, | 95 | .num_data = STMPE2401_NUM_DATA, |
88 | .num_normal_data = 2, | 96 | .num_normal_data = 2, |
89 | .max_cols = 8, | 97 | .max_cols = 8, |
90 | .max_rows = 12, | 98 | .max_rows = 12, |
@@ -94,7 +102,7 @@ static const struct stmpe_keypad_variant stmpe_keypad_variants[] = { | |||
94 | [STMPE2403] = { | 102 | [STMPE2403] = { |
95 | .auto_increment = true, | 103 | .auto_increment = true, |
96 | .set_pullup = true, | 104 | .set_pullup = true, |
97 | .num_data = 5, | 105 | .num_data = STMPE2403_NUM_DATA, |
98 | .num_normal_data = 3, | 106 | .num_normal_data = 3, |
99 | .max_cols = 8, | 107 | .max_cols = 8, |
100 | .max_rows = 12, | 108 | .max_rows = 12, |
@@ -156,7 +164,7 @@ static irqreturn_t stmpe_keypad_irq(int irq, void *dev) | |||
156 | struct stmpe_keypad *keypad = dev; | 164 | struct stmpe_keypad *keypad = dev; |
157 | struct input_dev *input = keypad->input; | 165 | struct input_dev *input = keypad->input; |
158 | const struct stmpe_keypad_variant *variant = keypad->variant; | 166 | const struct stmpe_keypad_variant *variant = keypad->variant; |
159 | u8 fifo[variant->num_data]; | 167 | u8 fifo[MAX_NUM_DATA]; |
160 | int ret; | 168 | int ret; |
161 | int i; | 169 | int i; |
162 | 170 | ||
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 6a3c753b093b..572b15fa18c2 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -655,15 +655,6 @@ config INPUT_DM355EVM | |||
655 | To compile this driver as a module, choose M here: the | 655 | To compile this driver as a module, choose M here: the |
656 | module will be called dm355evm_keys. | 656 | module will be called dm355evm_keys. |
657 | 657 | ||
658 | config INPUT_BFIN_ROTARY | ||
659 | tristate "Blackfin Rotary support" | ||
660 | depends on BF54x || BF52x | ||
661 | help | ||
662 | Say Y here if you want to use the Blackfin Rotary. | ||
663 | |||
664 | To compile this driver as a module, choose M here: the | ||
665 | module will be called bfin-rotary. | ||
666 | |||
667 | config INPUT_WM831X_ON | 658 | config INPUT_WM831X_ON |
668 | tristate "WM831X ON pin" | 659 | tristate "WM831X ON pin" |
669 | depends on MFD_WM831X | 660 | depends on MFD_WM831X |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 8cc58f362bb8..72cde28649e2 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -19,7 +19,6 @@ obj-$(CONFIG_INPUT_ARIZONA_HAPTICS) += arizona-haptics.o | |||
19 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o | 19 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o |
20 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o | 20 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o |
21 | obj-$(CONFIG_INPUT_ATMEL_CAPTOUCH) += atmel_captouch.o | 21 | obj-$(CONFIG_INPUT_ATMEL_CAPTOUCH) += atmel_captouch.o |
22 | obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o | ||
23 | obj-$(CONFIG_INPUT_BMA150) += bma150.o | 22 | obj-$(CONFIG_INPUT_BMA150) += bma150.o |
24 | obj-$(CONFIG_INPUT_CM109) += cm109.o | 23 | obj-$(CONFIG_INPUT_CM109) += cm109.o |
25 | obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o | 24 | obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o |
diff --git a/drivers/input/misc/bfin_rotary.c b/drivers/input/misc/bfin_rotary.c deleted file mode 100644 index 799ce3d2820e..000000000000 --- a/drivers/input/misc/bfin_rotary.c +++ /dev/null | |||
@@ -1,294 +0,0 @@ | |||
1 | /* | ||
2 | * Rotary counter driver for Analog Devices Blackfin Processors | ||
3 | * | ||
4 | * Copyright 2008-2009 Analog Devices Inc. | ||
5 | * Licensed under the GPL-2 or later. | ||
6 | */ | ||
7 | |||
8 | #include <linux/module.h> | ||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/io.h> | ||
11 | #include <linux/irq.h> | ||
12 | #include <linux/pm.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/input.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/platform_data/bfin_rotary.h> | ||
17 | |||
18 | #include <asm/portmux.h> | ||
19 | |||
20 | #define CNT_CONFIG_OFF 0 /* CNT Config Offset */ | ||
21 | #define CNT_IMASK_OFF 4 /* CNT Interrupt Mask Offset */ | ||
22 | #define CNT_STATUS_OFF 8 /* CNT Status Offset */ | ||
23 | #define CNT_COMMAND_OFF 12 /* CNT Command Offset */ | ||
24 | #define CNT_DEBOUNCE_OFF 16 /* CNT Debounce Offset */ | ||
25 | #define CNT_COUNTER_OFF 20 /* CNT Counter Offset */ | ||
26 | #define CNT_MAX_OFF 24 /* CNT Maximum Count Offset */ | ||
27 | #define CNT_MIN_OFF 28 /* CNT Minimum Count Offset */ | ||
28 | |||
29 | struct bfin_rot { | ||
30 | struct input_dev *input; | ||
31 | void __iomem *base; | ||
32 | int irq; | ||
33 | unsigned int up_key; | ||
34 | unsigned int down_key; | ||
35 | unsigned int button_key; | ||
36 | unsigned int rel_code; | ||
37 | |||
38 | unsigned short mode; | ||
39 | unsigned short debounce; | ||
40 | |||
41 | unsigned short cnt_config; | ||
42 | unsigned short cnt_imask; | ||
43 | unsigned short cnt_debounce; | ||
44 | }; | ||
45 | |||
46 | static void report_key_event(struct input_dev *input, int keycode) | ||
47 | { | ||
48 | /* simulate a press-n-release */ | ||
49 | input_report_key(input, keycode, 1); | ||
50 | input_sync(input); | ||
51 | input_report_key(input, keycode, 0); | ||
52 | input_sync(input); | ||
53 | } | ||
54 | |||
55 | static void report_rotary_event(struct bfin_rot *rotary, int delta) | ||
56 | { | ||
57 | struct input_dev *input = rotary->input; | ||
58 | |||
59 | if (rotary->up_key) { | ||
60 | report_key_event(input, | ||
61 | delta > 0 ? rotary->up_key : rotary->down_key); | ||
62 | } else { | ||
63 | input_report_rel(input, rotary->rel_code, delta); | ||
64 | input_sync(input); | ||
65 | } | ||
66 | } | ||
67 | |||
68 | static irqreturn_t bfin_rotary_isr(int irq, void *dev_id) | ||
69 | { | ||
70 | struct bfin_rot *rotary = dev_id; | ||
71 | int delta; | ||
72 | |||
73 | switch (readw(rotary->base + CNT_STATUS_OFF)) { | ||
74 | |||
75 | case ICII: | ||
76 | break; | ||
77 | |||
78 | case UCII: | ||
79 | case DCII: | ||
80 | delta = readl(rotary->base + CNT_COUNTER_OFF); | ||
81 | if (delta) | ||
82 | report_rotary_event(rotary, delta); | ||
83 | break; | ||
84 | |||
85 | case CZMII: | ||
86 | report_key_event(rotary->input, rotary->button_key); | ||
87 | break; | ||
88 | |||
89 | default: | ||
90 | break; | ||
91 | } | ||
92 | |||
93 | writew(W1LCNT_ZERO, rotary->base + CNT_COMMAND_OFF); /* Clear COUNTER */ | ||
94 | writew(-1, rotary->base + CNT_STATUS_OFF); /* Clear STATUS */ | ||
95 | |||
96 | return IRQ_HANDLED; | ||
97 | } | ||
98 | |||
99 | static int bfin_rotary_open(struct input_dev *input) | ||
100 | { | ||
101 | struct bfin_rot *rotary = input_get_drvdata(input); | ||
102 | unsigned short val; | ||
103 | |||
104 | if (rotary->mode & ROT_DEBE) | ||
105 | writew(rotary->debounce & DPRESCALE, | ||
106 | rotary->base + CNT_DEBOUNCE_OFF); | ||
107 | |||
108 | writew(rotary->mode & ~CNTE, rotary->base + CNT_CONFIG_OFF); | ||
109 | |||
110 | val = UCIE | DCIE; | ||
111 | if (rotary->button_key) | ||
112 | val |= CZMIE; | ||
113 | writew(val, rotary->base + CNT_IMASK_OFF); | ||
114 | |||
115 | writew(rotary->mode | CNTE, rotary->base + CNT_CONFIG_OFF); | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static void bfin_rotary_close(struct input_dev *input) | ||
121 | { | ||
122 | struct bfin_rot *rotary = input_get_drvdata(input); | ||
123 | |||
124 | writew(0, rotary->base + CNT_CONFIG_OFF); | ||
125 | writew(0, rotary->base + CNT_IMASK_OFF); | ||
126 | } | ||
127 | |||
128 | static void bfin_rotary_free_action(void *data) | ||
129 | { | ||
130 | peripheral_free_list(data); | ||
131 | } | ||
132 | |||
133 | static int bfin_rotary_probe(struct platform_device *pdev) | ||
134 | { | ||
135 | struct device *dev = &pdev->dev; | ||
136 | const struct bfin_rotary_platform_data *pdata = dev_get_platdata(dev); | ||
137 | struct bfin_rot *rotary; | ||
138 | struct resource *res; | ||
139 | struct input_dev *input; | ||
140 | int error; | ||
141 | |||
142 | /* Basic validation */ | ||
143 | if ((pdata->rotary_up_key && !pdata->rotary_down_key) || | ||
144 | (!pdata->rotary_up_key && pdata->rotary_down_key)) { | ||
145 | return -EINVAL; | ||
146 | } | ||
147 | |||
148 | if (pdata->pin_list) { | ||
149 | error = peripheral_request_list(pdata->pin_list, | ||
150 | dev_name(dev)); | ||
151 | if (error) { | ||
152 | dev_err(dev, "requesting peripherals failed: %d\n", | ||
153 | error); | ||
154 | return error; | ||
155 | } | ||
156 | |||
157 | error = devm_add_action_or_reset(dev, bfin_rotary_free_action, | ||
158 | pdata->pin_list); | ||
159 | if (error) { | ||
160 | dev_err(dev, "setting cleanup action failed: %d\n", | ||
161 | error); | ||
162 | return error; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | rotary = devm_kzalloc(dev, sizeof(struct bfin_rot), GFP_KERNEL); | ||
167 | if (!rotary) | ||
168 | return -ENOMEM; | ||
169 | |||
170 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
171 | rotary->base = devm_ioremap_resource(dev, res); | ||
172 | if (IS_ERR(rotary->base)) | ||
173 | return PTR_ERR(rotary->base); | ||
174 | |||
175 | input = devm_input_allocate_device(dev); | ||
176 | if (!input) | ||
177 | return -ENOMEM; | ||
178 | |||
179 | rotary->input = input; | ||
180 | |||
181 | rotary->up_key = pdata->rotary_up_key; | ||
182 | rotary->down_key = pdata->rotary_down_key; | ||
183 | rotary->button_key = pdata->rotary_button_key; | ||
184 | rotary->rel_code = pdata->rotary_rel_code; | ||
185 | |||
186 | rotary->mode = pdata->mode; | ||
187 | rotary->debounce = pdata->debounce; | ||
188 | |||
189 | input->name = pdev->name; | ||
190 | input->phys = "bfin-rotary/input0"; | ||
191 | input->dev.parent = dev; | ||
192 | |||
193 | input_set_drvdata(input, rotary); | ||
194 | |||
195 | input->id.bustype = BUS_HOST; | ||
196 | input->id.vendor = 0x0001; | ||
197 | input->id.product = 0x0001; | ||
198 | input->id.version = 0x0100; | ||
199 | |||
200 | input->open = bfin_rotary_open; | ||
201 | input->close = bfin_rotary_close; | ||
202 | |||
203 | if (rotary->up_key) { | ||
204 | __set_bit(EV_KEY, input->evbit); | ||
205 | __set_bit(rotary->up_key, input->keybit); | ||
206 | __set_bit(rotary->down_key, input->keybit); | ||
207 | } else { | ||
208 | __set_bit(EV_REL, input->evbit); | ||
209 | __set_bit(rotary->rel_code, input->relbit); | ||
210 | } | ||
211 | |||
212 | if (rotary->button_key) { | ||
213 | __set_bit(EV_KEY, input->evbit); | ||
214 | __set_bit(rotary->button_key, input->keybit); | ||
215 | } | ||
216 | |||
217 | /* Quiesce the device before requesting irq */ | ||
218 | bfin_rotary_close(input); | ||
219 | |||
220 | rotary->irq = platform_get_irq(pdev, 0); | ||
221 | if (rotary->irq < 0) { | ||
222 | dev_err(dev, "No rotary IRQ specified\n"); | ||
223 | return -ENOENT; | ||
224 | } | ||
225 | |||
226 | error = devm_request_irq(dev, rotary->irq, bfin_rotary_isr, | ||
227 | 0, dev_name(dev), rotary); | ||
228 | if (error) { | ||
229 | dev_err(dev, "unable to claim irq %d; error %d\n", | ||
230 | rotary->irq, error); | ||
231 | return error; | ||
232 | } | ||
233 | |||
234 | error = input_register_device(input); | ||
235 | if (error) { | ||
236 | dev_err(dev, "unable to register input device (%d)\n", error); | ||
237 | return error; | ||
238 | } | ||
239 | |||
240 | platform_set_drvdata(pdev, rotary); | ||
241 | device_init_wakeup(dev, 1); | ||
242 | |||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static int __maybe_unused bfin_rotary_suspend(struct device *dev) | ||
247 | { | ||
248 | struct platform_device *pdev = to_platform_device(dev); | ||
249 | struct bfin_rot *rotary = platform_get_drvdata(pdev); | ||
250 | |||
251 | rotary->cnt_config = readw(rotary->base + CNT_CONFIG_OFF); | ||
252 | rotary->cnt_imask = readw(rotary->base + CNT_IMASK_OFF); | ||
253 | rotary->cnt_debounce = readw(rotary->base + CNT_DEBOUNCE_OFF); | ||
254 | |||
255 | if (device_may_wakeup(&pdev->dev)) | ||
256 | enable_irq_wake(rotary->irq); | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | static int __maybe_unused bfin_rotary_resume(struct device *dev) | ||
262 | { | ||
263 | struct platform_device *pdev = to_platform_device(dev); | ||
264 | struct bfin_rot *rotary = platform_get_drvdata(pdev); | ||
265 | |||
266 | writew(rotary->cnt_debounce, rotary->base + CNT_DEBOUNCE_OFF); | ||
267 | writew(rotary->cnt_imask, rotary->base + CNT_IMASK_OFF); | ||
268 | writew(rotary->cnt_config & ~CNTE, rotary->base + CNT_CONFIG_OFF); | ||
269 | |||
270 | if (device_may_wakeup(&pdev->dev)) | ||
271 | disable_irq_wake(rotary->irq); | ||
272 | |||
273 | if (rotary->cnt_config & CNTE) | ||
274 | writew(rotary->cnt_config, rotary->base + CNT_CONFIG_OFF); | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static SIMPLE_DEV_PM_OPS(bfin_rotary_pm_ops, | ||
280 | bfin_rotary_suspend, bfin_rotary_resume); | ||
281 | |||
282 | static struct platform_driver bfin_rotary_device_driver = { | ||
283 | .probe = bfin_rotary_probe, | ||
284 | .driver = { | ||
285 | .name = "bfin-rotary", | ||
286 | .pm = &bfin_rotary_pm_ops, | ||
287 | }, | ||
288 | }; | ||
289 | module_platform_driver(bfin_rotary_device_driver); | ||
290 | |||
291 | MODULE_LICENSE("GPL"); | ||
292 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
293 | MODULE_DESCRIPTION("Rotary Counter driver for Blackfin Processors"); | ||
294 | MODULE_ALIAS("platform:bfin-rotary"); | ||
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index adf7f05c643a..cb5579716dba 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -583,7 +583,7 @@ static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) | |||
583 | 583 | ||
584 | x = (s8)(((packet[0] & 0x20) << 2) | (packet[1] & 0x7f)); | 584 | x = (s8)(((packet[0] & 0x20) << 2) | (packet[1] & 0x7f)); |
585 | y = (s8)(((packet[0] & 0x10) << 3) | (packet[2] & 0x7f)); | 585 | y = (s8)(((packet[0] & 0x10) << 3) | (packet[2] & 0x7f)); |
586 | z = packet[4] & 0x7c; | 586 | z = packet[4] & 0x7f; |
587 | 587 | ||
588 | /* | 588 | /* |
589 | * The x and y values tend to be quite large, and when used | 589 | * The x and y values tend to be quite large, and when used |
@@ -2548,13 +2548,31 @@ static int alps_update_btn_info_ss4_v2(unsigned char otp[][4], | |||
2548 | } | 2548 | } |
2549 | 2549 | ||
2550 | static int alps_update_dual_info_ss4_v2(unsigned char otp[][4], | 2550 | static int alps_update_dual_info_ss4_v2(unsigned char otp[][4], |
2551 | struct alps_data *priv) | 2551 | struct alps_data *priv, |
2552 | struct psmouse *psmouse) | ||
2552 | { | 2553 | { |
2553 | bool is_dual = false; | 2554 | bool is_dual = false; |
2555 | int reg_val = 0; | ||
2556 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
2554 | 2557 | ||
2555 | if (IS_SS4PLUS_DEV(priv->dev_id)) | 2558 | if (IS_SS4PLUS_DEV(priv->dev_id)) { |
2556 | is_dual = (otp[0][0] >> 4) & 0x01; | 2559 | is_dual = (otp[0][0] >> 4) & 0x01; |
2557 | 2560 | ||
2561 | if (!is_dual) { | ||
2562 | /* For support TrackStick of Thinkpad L/E series */ | ||
2563 | if (alps_exit_command_mode(psmouse) == 0 && | ||
2564 | alps_enter_command_mode(psmouse) == 0) { | ||
2565 | reg_val = alps_command_mode_read_reg(psmouse, | ||
2566 | 0xD7); | ||
2567 | } | ||
2568 | alps_exit_command_mode(psmouse); | ||
2569 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); | ||
2570 | |||
2571 | if (reg_val == 0x0C || reg_val == 0x1D) | ||
2572 | is_dual = true; | ||
2573 | } | ||
2574 | } | ||
2575 | |||
2558 | if (is_dual) | 2576 | if (is_dual) |
2559 | priv->flags |= ALPS_DUALPOINT | | 2577 | priv->flags |= ALPS_DUALPOINT | |
2560 | ALPS_DUALPOINT_WITH_PRESSURE; | 2578 | ALPS_DUALPOINT_WITH_PRESSURE; |
@@ -2577,7 +2595,7 @@ static int alps_set_defaults_ss4_v2(struct psmouse *psmouse, | |||
2577 | 2595 | ||
2578 | alps_update_btn_info_ss4_v2(otp, priv); | 2596 | alps_update_btn_info_ss4_v2(otp, priv); |
2579 | 2597 | ||
2580 | alps_update_dual_info_ss4_v2(otp, priv); | 2598 | alps_update_dual_info_ss4_v2(otp, priv, psmouse); |
2581 | 2599 | ||
2582 | return 0; | 2600 | return 0; |
2583 | } | 2601 | } |
diff --git a/drivers/input/rmi4/rmi_spi.c b/drivers/input/rmi4/rmi_spi.c index 76edbf2c1bce..082defc329a8 100644 --- a/drivers/input/rmi4/rmi_spi.c +++ b/drivers/input/rmi4/rmi_spi.c | |||
@@ -147,8 +147,11 @@ static int rmi_spi_xfer(struct rmi_spi_xport *rmi_spi, | |||
147 | if (len > RMI_SPI_XFER_SIZE_LIMIT) | 147 | if (len > RMI_SPI_XFER_SIZE_LIMIT) |
148 | return -EINVAL; | 148 | return -EINVAL; |
149 | 149 | ||
150 | if (rmi_spi->xfer_buf_size < len) | 150 | if (rmi_spi->xfer_buf_size < len) { |
151 | rmi_spi_manage_pools(rmi_spi, len); | 151 | ret = rmi_spi_manage_pools(rmi_spi, len); |
152 | if (ret < 0) | ||
153 | return ret; | ||
154 | } | ||
152 | 155 | ||
153 | if (addr == 0) | 156 | if (addr == 0) |
154 | /* | 157 | /* |
diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index aa9f29b875de..49d8d53e50b7 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c | |||
@@ -91,7 +91,7 @@ struct gscps2port { | |||
91 | struct parisc_device *padev; | 91 | struct parisc_device *padev; |
92 | struct serio *port; | 92 | struct serio *port; |
93 | spinlock_t lock; | 93 | spinlock_t lock; |
94 | char *addr; | 94 | char __iomem *addr; |
95 | u8 act, append; /* position in buffer[] */ | 95 | u8 act, append; /* position in buffer[] */ |
96 | struct { | 96 | struct { |
97 | u8 data; | 97 | u8 data; |
@@ -114,7 +114,7 @@ struct gscps2port { | |||
114 | * wait_TBE() - wait for Transmit Buffer Empty | 114 | * wait_TBE() - wait for Transmit Buffer Empty |
115 | */ | 115 | */ |
116 | 116 | ||
117 | static int wait_TBE(char *addr) | 117 | static int wait_TBE(char __iomem *addr) |
118 | { | 118 | { |
119 | int timeout = 25000; /* device is expected to react within 250 msec */ | 119 | int timeout = 25000; /* device is expected to react within 250 msec */ |
120 | while (gscps2_readb_status(addr) & GSC_STAT_TBNE) { | 120 | while (gscps2_readb_status(addr) & GSC_STAT_TBNE) { |
@@ -146,14 +146,14 @@ static void gscps2_flush(struct gscps2port *ps2port) | |||
146 | static inline int gscps2_writeb_output(struct gscps2port *ps2port, u8 data) | 146 | static inline int gscps2_writeb_output(struct gscps2port *ps2port, u8 data) |
147 | { | 147 | { |
148 | unsigned long flags; | 148 | unsigned long flags; |
149 | char *addr = ps2port->addr; | 149 | char __iomem *addr = ps2port->addr; |
150 | 150 | ||
151 | if (!wait_TBE(addr)) { | 151 | if (!wait_TBE(addr)) { |
152 | printk(KERN_DEBUG PFX "timeout - could not write byte %#x\n", data); | 152 | printk(KERN_DEBUG PFX "timeout - could not write byte %#x\n", data); |
153 | return 0; | 153 | return 0; |
154 | } | 154 | } |
155 | 155 | ||
156 | while (gscps2_readb_status(ps2port->addr) & GSC_STAT_RBNE) | 156 | while (gscps2_readb_status(addr) & GSC_STAT_RBNE) |
157 | /* wait */; | 157 | /* wait */; |
158 | 158 | ||
159 | spin_lock_irqsave(&ps2port->lock, flags); | 159 | spin_lock_irqsave(&ps2port->lock, flags); |
@@ -200,13 +200,12 @@ static void gscps2_enable(struct gscps2port *ps2port, int enable) | |||
200 | 200 | ||
201 | static void gscps2_reset(struct gscps2port *ps2port) | 201 | static void gscps2_reset(struct gscps2port *ps2port) |
202 | { | 202 | { |
203 | char *addr = ps2port->addr; | ||
204 | unsigned long flags; | 203 | unsigned long flags; |
205 | 204 | ||
206 | /* reset the interface */ | 205 | /* reset the interface */ |
207 | spin_lock_irqsave(&ps2port->lock, flags); | 206 | spin_lock_irqsave(&ps2port->lock, flags); |
208 | gscps2_flush(ps2port); | 207 | gscps2_flush(ps2port); |
209 | writeb(0xff, addr+GSC_RESET); | 208 | writeb(0xff, ps2port->addr + GSC_RESET); |
210 | gscps2_flush(ps2port); | 209 | gscps2_flush(ps2port); |
211 | spin_unlock_irqrestore(&ps2port->lock, flags); | 210 | spin_unlock_irqrestore(&ps2port->lock, flags); |
212 | } | 211 | } |
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 87e84a085a23..b353d494ad40 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -635,6 +635,13 @@ static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = { | |||
635 | }, | 635 | }, |
636 | }, | 636 | }, |
637 | { | 637 | { |
638 | /* Lenovo ThinkPad L460 */ | ||
639 | .matches = { | ||
640 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
641 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L460"), | ||
642 | }, | ||
643 | }, | ||
644 | { | ||
638 | /* Clevo P650RS, 650RP6, Sager NP8152-S, and others */ | 645 | /* Clevo P650RS, 650RP6, Sager NP8152-S, and others */ |
639 | .matches = { | 646 | .matches = { |
640 | DMI_MATCH(DMI_SYS_VENDOR, "Notebook"), | 647 | DMI_MATCH(DMI_SYS_VENDOR, "Notebook"), |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 94cc740a4203..32267c1afebc 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -373,7 +373,7 @@ config TOUCHSCREEN_HIDEEP | |||
373 | 373 | ||
374 | If unsure, say N. | 374 | If unsure, say N. |
375 | 375 | ||
376 | To compile this driver as a moudle, choose M here : the | 376 | To compile this driver as a module, choose M here : the |
377 | module will be called hideep_ts. | 377 | module will be called hideep_ts. |
378 | 378 | ||
379 | config TOUCHSCREEN_ILI210X | 379 | config TOUCHSCREEN_ILI210X |
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 5d9699fe1b55..09194721aed2 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c | |||
@@ -280,7 +280,8 @@ struct mxt_data { | |||
280 | struct input_dev *input_dev; | 280 | struct input_dev *input_dev; |
281 | char phys[64]; /* device physical location */ | 281 | char phys[64]; /* device physical location */ |
282 | struct mxt_object *object_table; | 282 | struct mxt_object *object_table; |
283 | struct mxt_info info; | 283 | struct mxt_info *info; |
284 | void *raw_info_block; | ||
284 | unsigned int irq; | 285 | unsigned int irq; |
285 | unsigned int max_x; | 286 | unsigned int max_x; |
286 | unsigned int max_y; | 287 | unsigned int max_y; |
@@ -460,12 +461,13 @@ static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry) | |||
460 | { | 461 | { |
461 | u8 appmode = data->client->addr; | 462 | u8 appmode = data->client->addr; |
462 | u8 bootloader; | 463 | u8 bootloader; |
464 | u8 family_id = data->info ? data->info->family_id : 0; | ||
463 | 465 | ||
464 | switch (appmode) { | 466 | switch (appmode) { |
465 | case 0x4a: | 467 | case 0x4a: |
466 | case 0x4b: | 468 | case 0x4b: |
467 | /* Chips after 1664S use different scheme */ | 469 | /* Chips after 1664S use different scheme */ |
468 | if (retry || data->info.family_id >= 0xa2) { | 470 | if (retry || family_id >= 0xa2) { |
469 | bootloader = appmode - 0x24; | 471 | bootloader = appmode - 0x24; |
470 | break; | 472 | break; |
471 | } | 473 | } |
@@ -692,7 +694,7 @@ mxt_get_object(struct mxt_data *data, u8 type) | |||
692 | struct mxt_object *object; | 694 | struct mxt_object *object; |
693 | int i; | 695 | int i; |
694 | 696 | ||
695 | for (i = 0; i < data->info.object_num; i++) { | 697 | for (i = 0; i < data->info->object_num; i++) { |
696 | object = data->object_table + i; | 698 | object = data->object_table + i; |
697 | if (object->type == type) | 699 | if (object->type == type) |
698 | return object; | 700 | return object; |
@@ -1462,12 +1464,12 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) | |||
1462 | data_pos += offset; | 1464 | data_pos += offset; |
1463 | } | 1465 | } |
1464 | 1466 | ||
1465 | if (cfg_info.family_id != data->info.family_id) { | 1467 | if (cfg_info.family_id != data->info->family_id) { |
1466 | dev_err(dev, "Family ID mismatch!\n"); | 1468 | dev_err(dev, "Family ID mismatch!\n"); |
1467 | return -EINVAL; | 1469 | return -EINVAL; |
1468 | } | 1470 | } |
1469 | 1471 | ||
1470 | if (cfg_info.variant_id != data->info.variant_id) { | 1472 | if (cfg_info.variant_id != data->info->variant_id) { |
1471 | dev_err(dev, "Variant ID mismatch!\n"); | 1473 | dev_err(dev, "Variant ID mismatch!\n"); |
1472 | return -EINVAL; | 1474 | return -EINVAL; |
1473 | } | 1475 | } |
@@ -1512,7 +1514,7 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) | |||
1512 | 1514 | ||
1513 | /* Malloc memory to store configuration */ | 1515 | /* Malloc memory to store configuration */ |
1514 | cfg_start_ofs = MXT_OBJECT_START + | 1516 | cfg_start_ofs = MXT_OBJECT_START + |
1515 | data->info.object_num * sizeof(struct mxt_object) + | 1517 | data->info->object_num * sizeof(struct mxt_object) + |
1516 | MXT_INFO_CHECKSUM_SIZE; | 1518 | MXT_INFO_CHECKSUM_SIZE; |
1517 | config_mem_size = data->mem_size - cfg_start_ofs; | 1519 | config_mem_size = data->mem_size - cfg_start_ofs; |
1518 | config_mem = kzalloc(config_mem_size, GFP_KERNEL); | 1520 | config_mem = kzalloc(config_mem_size, GFP_KERNEL); |
@@ -1563,20 +1565,6 @@ release_mem: | |||
1563 | return ret; | 1565 | return ret; |
1564 | } | 1566 | } |
1565 | 1567 | ||
1566 | static int mxt_get_info(struct mxt_data *data) | ||
1567 | { | ||
1568 | struct i2c_client *client = data->client; | ||
1569 | struct mxt_info *info = &data->info; | ||
1570 | int error; | ||
1571 | |||
1572 | /* Read 7-byte info block starting at address 0 */ | ||
1573 | error = __mxt_read_reg(client, 0, sizeof(*info), info); | ||
1574 | if (error) | ||
1575 | return error; | ||
1576 | |||
1577 | return 0; | ||
1578 | } | ||
1579 | |||
1580 | static void mxt_free_input_device(struct mxt_data *data) | 1568 | static void mxt_free_input_device(struct mxt_data *data) |
1581 | { | 1569 | { |
1582 | if (data->input_dev) { | 1570 | if (data->input_dev) { |
@@ -1591,9 +1579,10 @@ static void mxt_free_object_table(struct mxt_data *data) | |||
1591 | video_unregister_device(&data->dbg.vdev); | 1579 | video_unregister_device(&data->dbg.vdev); |
1592 | v4l2_device_unregister(&data->dbg.v4l2); | 1580 | v4l2_device_unregister(&data->dbg.v4l2); |
1593 | #endif | 1581 | #endif |
1594 | |||
1595 | kfree(data->object_table); | ||
1596 | data->object_table = NULL; | 1582 | data->object_table = NULL; |
1583 | data->info = NULL; | ||
1584 | kfree(data->raw_info_block); | ||
1585 | data->raw_info_block = NULL; | ||
1597 | kfree(data->msg_buf); | 1586 | kfree(data->msg_buf); |
1598 | data->msg_buf = NULL; | 1587 | data->msg_buf = NULL; |
1599 | data->T5_address = 0; | 1588 | data->T5_address = 0; |
@@ -1609,34 +1598,18 @@ static void mxt_free_object_table(struct mxt_data *data) | |||
1609 | data->max_reportid = 0; | 1598 | data->max_reportid = 0; |
1610 | } | 1599 | } |
1611 | 1600 | ||
1612 | static int mxt_get_object_table(struct mxt_data *data) | 1601 | static int mxt_parse_object_table(struct mxt_data *data, |
1602 | struct mxt_object *object_table) | ||
1613 | { | 1603 | { |
1614 | struct i2c_client *client = data->client; | 1604 | struct i2c_client *client = data->client; |
1615 | size_t table_size; | ||
1616 | struct mxt_object *object_table; | ||
1617 | int error; | ||
1618 | int i; | 1605 | int i; |
1619 | u8 reportid; | 1606 | u8 reportid; |
1620 | u16 end_address; | 1607 | u16 end_address; |
1621 | 1608 | ||
1622 | table_size = data->info.object_num * sizeof(struct mxt_object); | ||
1623 | object_table = kzalloc(table_size, GFP_KERNEL); | ||
1624 | if (!object_table) { | ||
1625 | dev_err(&data->client->dev, "Failed to allocate memory\n"); | ||
1626 | return -ENOMEM; | ||
1627 | } | ||
1628 | |||
1629 | error = __mxt_read_reg(client, MXT_OBJECT_START, table_size, | ||
1630 | object_table); | ||
1631 | if (error) { | ||
1632 | kfree(object_table); | ||
1633 | return error; | ||
1634 | } | ||
1635 | |||
1636 | /* Valid Report IDs start counting from 1 */ | 1609 | /* Valid Report IDs start counting from 1 */ |
1637 | reportid = 1; | 1610 | reportid = 1; |
1638 | data->mem_size = 0; | 1611 | data->mem_size = 0; |
1639 | for (i = 0; i < data->info.object_num; i++) { | 1612 | for (i = 0; i < data->info->object_num; i++) { |
1640 | struct mxt_object *object = object_table + i; | 1613 | struct mxt_object *object = object_table + i; |
1641 | u8 min_id, max_id; | 1614 | u8 min_id, max_id; |
1642 | 1615 | ||
@@ -1660,8 +1633,8 @@ static int mxt_get_object_table(struct mxt_data *data) | |||
1660 | 1633 | ||
1661 | switch (object->type) { | 1634 | switch (object->type) { |
1662 | case MXT_GEN_MESSAGE_T5: | 1635 | case MXT_GEN_MESSAGE_T5: |
1663 | if (data->info.family_id == 0x80 && | 1636 | if (data->info->family_id == 0x80 && |
1664 | data->info.version < 0x20) { | 1637 | data->info->version < 0x20) { |
1665 | /* | 1638 | /* |
1666 | * On mXT224 firmware versions prior to V2.0 | 1639 | * On mXT224 firmware versions prior to V2.0 |
1667 | * read and discard unused CRC byte otherwise | 1640 | * read and discard unused CRC byte otherwise |
@@ -1716,24 +1689,102 @@ static int mxt_get_object_table(struct mxt_data *data) | |||
1716 | /* If T44 exists, T5 position has to be directly after */ | 1689 | /* If T44 exists, T5 position has to be directly after */ |
1717 | if (data->T44_address && (data->T5_address != data->T44_address + 1)) { | 1690 | if (data->T44_address && (data->T5_address != data->T44_address + 1)) { |
1718 | dev_err(&client->dev, "Invalid T44 position\n"); | 1691 | dev_err(&client->dev, "Invalid T44 position\n"); |
1719 | error = -EINVAL; | 1692 | return -EINVAL; |
1720 | goto free_object_table; | ||
1721 | } | 1693 | } |
1722 | 1694 | ||
1723 | data->msg_buf = kcalloc(data->max_reportid, | 1695 | data->msg_buf = kcalloc(data->max_reportid, |
1724 | data->T5_msg_size, GFP_KERNEL); | 1696 | data->T5_msg_size, GFP_KERNEL); |
1725 | if (!data->msg_buf) { | 1697 | if (!data->msg_buf) |
1726 | dev_err(&client->dev, "Failed to allocate message buffer\n"); | 1698 | return -ENOMEM; |
1699 | |||
1700 | return 0; | ||
1701 | } | ||
1702 | |||
1703 | static int mxt_read_info_block(struct mxt_data *data) | ||
1704 | { | ||
1705 | struct i2c_client *client = data->client; | ||
1706 | int error; | ||
1707 | size_t size; | ||
1708 | void *id_buf, *buf; | ||
1709 | uint8_t num_objects; | ||
1710 | u32 calculated_crc; | ||
1711 | u8 *crc_ptr; | ||
1712 | |||
1713 | /* If info block already allocated, free it */ | ||
1714 | if (data->raw_info_block) | ||
1715 | mxt_free_object_table(data); | ||
1716 | |||
1717 | /* Read 7-byte ID information block starting at address 0 */ | ||
1718 | size = sizeof(struct mxt_info); | ||
1719 | id_buf = kzalloc(size, GFP_KERNEL); | ||
1720 | if (!id_buf) | ||
1721 | return -ENOMEM; | ||
1722 | |||
1723 | error = __mxt_read_reg(client, 0, size, id_buf); | ||
1724 | if (error) | ||
1725 | goto err_free_mem; | ||
1726 | |||
1727 | /* Resize buffer to give space for rest of info block */ | ||
1728 | num_objects = ((struct mxt_info *)id_buf)->object_num; | ||
1729 | size += (num_objects * sizeof(struct mxt_object)) | ||
1730 | + MXT_INFO_CHECKSUM_SIZE; | ||
1731 | |||
1732 | buf = krealloc(id_buf, size, GFP_KERNEL); | ||
1733 | if (!buf) { | ||
1727 | error = -ENOMEM; | 1734 | error = -ENOMEM; |
1728 | goto free_object_table; | 1735 | goto err_free_mem; |
1736 | } | ||
1737 | id_buf = buf; | ||
1738 | |||
1739 | /* Read rest of info block */ | ||
1740 | error = __mxt_read_reg(client, MXT_OBJECT_START, | ||
1741 | size - MXT_OBJECT_START, | ||
1742 | id_buf + MXT_OBJECT_START); | ||
1743 | if (error) | ||
1744 | goto err_free_mem; | ||
1745 | |||
1746 | /* Extract & calculate checksum */ | ||
1747 | crc_ptr = id_buf + size - MXT_INFO_CHECKSUM_SIZE; | ||
1748 | data->info_crc = crc_ptr[0] | (crc_ptr[1] << 8) | (crc_ptr[2] << 16); | ||
1749 | |||
1750 | calculated_crc = mxt_calculate_crc(id_buf, 0, | ||
1751 | size - MXT_INFO_CHECKSUM_SIZE); | ||
1752 | |||
1753 | /* | ||
1754 | * CRC mismatch can be caused by data corruption due to I2C comms | ||
1755 | * issue or else device is not using Object Based Protocol (eg i2c-hid) | ||
1756 | */ | ||
1757 | if ((data->info_crc == 0) || (data->info_crc != calculated_crc)) { | ||
1758 | dev_err(&client->dev, | ||
1759 | "Info Block CRC error calculated=0x%06X read=0x%06X\n", | ||
1760 | calculated_crc, data->info_crc); | ||
1761 | error = -EIO; | ||
1762 | goto err_free_mem; | ||
1763 | } | ||
1764 | |||
1765 | data->raw_info_block = id_buf; | ||
1766 | data->info = (struct mxt_info *)id_buf; | ||
1767 | |||
1768 | dev_info(&client->dev, | ||
1769 | "Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n", | ||
1770 | data->info->family_id, data->info->variant_id, | ||
1771 | data->info->version >> 4, data->info->version & 0xf, | ||
1772 | data->info->build, data->info->object_num); | ||
1773 | |||
1774 | /* Parse object table information */ | ||
1775 | error = mxt_parse_object_table(data, id_buf + MXT_OBJECT_START); | ||
1776 | if (error) { | ||
1777 | dev_err(&client->dev, "Error %d parsing object table\n", error); | ||
1778 | mxt_free_object_table(data); | ||
1779 | goto err_free_mem; | ||
1729 | } | 1780 | } |
1730 | 1781 | ||
1731 | data->object_table = object_table; | 1782 | data->object_table = (struct mxt_object *)(id_buf + MXT_OBJECT_START); |
1732 | 1783 | ||
1733 | return 0; | 1784 | return 0; |
1734 | 1785 | ||
1735 | free_object_table: | 1786 | err_free_mem: |
1736 | mxt_free_object_table(data); | 1787 | kfree(id_buf); |
1737 | return error; | 1788 | return error; |
1738 | } | 1789 | } |
1739 | 1790 | ||
@@ -2046,7 +2097,7 @@ static int mxt_initialize(struct mxt_data *data) | |||
2046 | int error; | 2097 | int error; |
2047 | 2098 | ||
2048 | while (1) { | 2099 | while (1) { |
2049 | error = mxt_get_info(data); | 2100 | error = mxt_read_info_block(data); |
2050 | if (!error) | 2101 | if (!error) |
2051 | break; | 2102 | break; |
2052 | 2103 | ||
@@ -2077,16 +2128,9 @@ static int mxt_initialize(struct mxt_data *data) | |||
2077 | msleep(MXT_FW_RESET_TIME); | 2128 | msleep(MXT_FW_RESET_TIME); |
2078 | } | 2129 | } |
2079 | 2130 | ||
2080 | /* Get object table information */ | ||
2081 | error = mxt_get_object_table(data); | ||
2082 | if (error) { | ||
2083 | dev_err(&client->dev, "Error %d reading object table\n", error); | ||
2084 | return error; | ||
2085 | } | ||
2086 | |||
2087 | error = mxt_acquire_irq(data); | 2131 | error = mxt_acquire_irq(data); |
2088 | if (error) | 2132 | if (error) |
2089 | goto err_free_object_table; | 2133 | return error; |
2090 | 2134 | ||
2091 | error = request_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME, | 2135 | error = request_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME, |
2092 | &client->dev, GFP_KERNEL, data, | 2136 | &client->dev, GFP_KERNEL, data, |
@@ -2094,14 +2138,10 @@ static int mxt_initialize(struct mxt_data *data) | |||
2094 | if (error) { | 2138 | if (error) { |
2095 | dev_err(&client->dev, "Failed to invoke firmware loader: %d\n", | 2139 | dev_err(&client->dev, "Failed to invoke firmware loader: %d\n", |
2096 | error); | 2140 | error); |
2097 | goto err_free_object_table; | 2141 | return error; |
2098 | } | 2142 | } |
2099 | 2143 | ||
2100 | return 0; | 2144 | return 0; |
2101 | |||
2102 | err_free_object_table: | ||
2103 | mxt_free_object_table(data); | ||
2104 | return error; | ||
2105 | } | 2145 | } |
2106 | 2146 | ||
2107 | static int mxt_set_t7_power_cfg(struct mxt_data *data, u8 sleep) | 2147 | static int mxt_set_t7_power_cfg(struct mxt_data *data, u8 sleep) |
@@ -2162,7 +2202,7 @@ recheck: | |||
2162 | static u16 mxt_get_debug_value(struct mxt_data *data, unsigned int x, | 2202 | static u16 mxt_get_debug_value(struct mxt_data *data, unsigned int x, |
2163 | unsigned int y) | 2203 | unsigned int y) |
2164 | { | 2204 | { |
2165 | struct mxt_info *info = &data->info; | 2205 | struct mxt_info *info = data->info; |
2166 | struct mxt_dbg *dbg = &data->dbg; | 2206 | struct mxt_dbg *dbg = &data->dbg; |
2167 | unsigned int ofs, page; | 2207 | unsigned int ofs, page; |
2168 | unsigned int col = 0; | 2208 | unsigned int col = 0; |
@@ -2490,7 +2530,7 @@ static const struct video_device mxt_video_device = { | |||
2490 | 2530 | ||
2491 | static void mxt_debug_init(struct mxt_data *data) | 2531 | static void mxt_debug_init(struct mxt_data *data) |
2492 | { | 2532 | { |
2493 | struct mxt_info *info = &data->info; | 2533 | struct mxt_info *info = data->info; |
2494 | struct mxt_dbg *dbg = &data->dbg; | 2534 | struct mxt_dbg *dbg = &data->dbg; |
2495 | struct mxt_object *object; | 2535 | struct mxt_object *object; |
2496 | int error; | 2536 | int error; |
@@ -2576,7 +2616,6 @@ static int mxt_configure_objects(struct mxt_data *data, | |||
2576 | const struct firmware *cfg) | 2616 | const struct firmware *cfg) |
2577 | { | 2617 | { |
2578 | struct device *dev = &data->client->dev; | 2618 | struct device *dev = &data->client->dev; |
2579 | struct mxt_info *info = &data->info; | ||
2580 | int error; | 2619 | int error; |
2581 | 2620 | ||
2582 | error = mxt_init_t7_power_cfg(data); | 2621 | error = mxt_init_t7_power_cfg(data); |
@@ -2601,11 +2640,6 @@ static int mxt_configure_objects(struct mxt_data *data, | |||
2601 | 2640 | ||
2602 | mxt_debug_init(data); | 2641 | mxt_debug_init(data); |
2603 | 2642 | ||
2604 | dev_info(dev, | ||
2605 | "Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n", | ||
2606 | info->family_id, info->variant_id, info->version >> 4, | ||
2607 | info->version & 0xf, info->build, info->object_num); | ||
2608 | |||
2609 | return 0; | 2643 | return 0; |
2610 | } | 2644 | } |
2611 | 2645 | ||
@@ -2614,7 +2648,7 @@ static ssize_t mxt_fw_version_show(struct device *dev, | |||
2614 | struct device_attribute *attr, char *buf) | 2648 | struct device_attribute *attr, char *buf) |
2615 | { | 2649 | { |
2616 | struct mxt_data *data = dev_get_drvdata(dev); | 2650 | struct mxt_data *data = dev_get_drvdata(dev); |
2617 | struct mxt_info *info = &data->info; | 2651 | struct mxt_info *info = data->info; |
2618 | return scnprintf(buf, PAGE_SIZE, "%u.%u.%02X\n", | 2652 | return scnprintf(buf, PAGE_SIZE, "%u.%u.%02X\n", |
2619 | info->version >> 4, info->version & 0xf, info->build); | 2653 | info->version >> 4, info->version & 0xf, info->build); |
2620 | } | 2654 | } |
@@ -2624,7 +2658,7 @@ static ssize_t mxt_hw_version_show(struct device *dev, | |||
2624 | struct device_attribute *attr, char *buf) | 2658 | struct device_attribute *attr, char *buf) |
2625 | { | 2659 | { |
2626 | struct mxt_data *data = dev_get_drvdata(dev); | 2660 | struct mxt_data *data = dev_get_drvdata(dev); |
2627 | struct mxt_info *info = &data->info; | 2661 | struct mxt_info *info = data->info; |
2628 | return scnprintf(buf, PAGE_SIZE, "%u.%u\n", | 2662 | return scnprintf(buf, PAGE_SIZE, "%u.%u\n", |
2629 | info->family_id, info->variant_id); | 2663 | info->family_id, info->variant_id); |
2630 | } | 2664 | } |
@@ -2663,7 +2697,7 @@ static ssize_t mxt_object_show(struct device *dev, | |||
2663 | return -ENOMEM; | 2697 | return -ENOMEM; |
2664 | 2698 | ||
2665 | error = 0; | 2699 | error = 0; |
2666 | for (i = 0; i < data->info.object_num; i++) { | 2700 | for (i = 0; i < data->info->object_num; i++) { |
2667 | object = data->object_table + i; | 2701 | object = data->object_table + i; |
2668 | 2702 | ||
2669 | if (!mxt_object_readable(object->type)) | 2703 | if (!mxt_object_readable(object->type)) |
@@ -3035,6 +3069,15 @@ static const struct dmi_system_id mxt_dmi_table[] = { | |||
3035 | .driver_data = samus_platform_data, | 3069 | .driver_data = samus_platform_data, |
3036 | }, | 3070 | }, |
3037 | { | 3071 | { |
3072 | /* Samsung Chromebook Pro */ | ||
3073 | .ident = "Samsung Chromebook Pro", | ||
3074 | .matches = { | ||
3075 | DMI_MATCH(DMI_SYS_VENDOR, "Google"), | ||
3076 | DMI_MATCH(DMI_PRODUCT_NAME, "Caroline"), | ||
3077 | }, | ||
3078 | .driver_data = samus_platform_data, | ||
3079 | }, | ||
3080 | { | ||
3038 | /* Other Google Chromebooks */ | 3081 | /* Other Google Chromebooks */ |
3039 | .ident = "Chromebook", | 3082 | .ident = "Chromebook", |
3040 | .matches = { | 3083 | .matches = { |
@@ -3254,6 +3297,11 @@ static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume); | |||
3254 | 3297 | ||
3255 | static const struct of_device_id mxt_of_match[] = { | 3298 | static const struct of_device_id mxt_of_match[] = { |
3256 | { .compatible = "atmel,maxtouch", }, | 3299 | { .compatible = "atmel,maxtouch", }, |
3300 | /* Compatibles listed below are deprecated */ | ||
3301 | { .compatible = "atmel,qt602240_ts", }, | ||
3302 | { .compatible = "atmel,atmel_mxt_ts", }, | ||
3303 | { .compatible = "atmel,atmel_mxt_tp", }, | ||
3304 | { .compatible = "atmel,mXT224", }, | ||
3257 | {}, | 3305 | {}, |
3258 | }; | 3306 | }; |
3259 | MODULE_DEVICE_TABLE(of, mxt_of_match); | 3307 | MODULE_DEVICE_TABLE(of, mxt_of_match); |
diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c index 646b1e768e6b..ff7043f74a3d 100644 --- a/drivers/input/touchscreen/silead.c +++ b/drivers/input/touchscreen/silead.c | |||
@@ -602,6 +602,7 @@ static const struct acpi_device_id silead_ts_acpi_match[] = { | |||
602 | { "GSL3675", 0 }, | 602 | { "GSL3675", 0 }, |
603 | { "GSL3692", 0 }, | 603 | { "GSL3692", 0 }, |
604 | { "MSSL1680", 0 }, | 604 | { "MSSL1680", 0 }, |
605 | { "MSSL0001", 0 }, | ||
605 | { } | 606 | { } |
606 | }; | 607 | }; |
607 | MODULE_DEVICE_TABLE(acpi, silead_ts_acpi_match); | 608 | MODULE_DEVICE_TABLE(acpi, silead_ts_acpi_match); |
diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c index f16f8358c70a..894843a7ec7b 100644 --- a/drivers/input/touchscreen/sur40.c +++ b/drivers/input/touchscreen/sur40.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <media/v4l2-device.h> | 38 | #include <media/v4l2-device.h> |
39 | #include <media/v4l2-dev.h> | 39 | #include <media/v4l2-dev.h> |
40 | #include <media/v4l2-ioctl.h> | 40 | #include <media/v4l2-ioctl.h> |
41 | #include <media/v4l2-ctrls.h> | ||
41 | #include <media/videobuf2-v4l2.h> | 42 | #include <media/videobuf2-v4l2.h> |
42 | #include <media/videobuf2-dma-sg.h> | 43 | #include <media/videobuf2-dma-sg.h> |
43 | 44 | ||
@@ -81,7 +82,10 @@ struct sur40_blob { | |||
81 | 82 | ||
82 | __le32 area; /* size in pixels/pressure (?) */ | 83 | __le32 area; /* size in pixels/pressure (?) */ |
83 | 84 | ||
84 | u8 padding[32]; | 85 | u8 padding[24]; |
86 | |||
87 | __le32 tag_id; /* valid when type == 0x04 (SUR40_TAG) */ | ||
88 | __le32 unknown; | ||
85 | 89 | ||
86 | } __packed; | 90 | } __packed; |
87 | 91 | ||
@@ -146,6 +150,40 @@ struct sur40_image_header { | |||
146 | #define SUR40_TOUCH 0x02 | 150 | #define SUR40_TOUCH 0x02 |
147 | #define SUR40_TAG 0x04 | 151 | #define SUR40_TAG 0x04 |
148 | 152 | ||
153 | /* video controls */ | ||
154 | #define SUR40_BRIGHTNESS_MAX 0xff | ||
155 | #define SUR40_BRIGHTNESS_MIN 0x00 | ||
156 | #define SUR40_BRIGHTNESS_DEF 0xff | ||
157 | |||
158 | #define SUR40_CONTRAST_MAX 0x0f | ||
159 | #define SUR40_CONTRAST_MIN 0x00 | ||
160 | #define SUR40_CONTRAST_DEF 0x0a | ||
161 | |||
162 | #define SUR40_GAIN_MAX 0x09 | ||
163 | #define SUR40_GAIN_MIN 0x00 | ||
164 | #define SUR40_GAIN_DEF 0x08 | ||
165 | |||
166 | #define SUR40_BACKLIGHT_MAX 0x01 | ||
167 | #define SUR40_BACKLIGHT_MIN 0x00 | ||
168 | #define SUR40_BACKLIGHT_DEF 0x01 | ||
169 | |||
170 | #define sur40_str(s) #s | ||
171 | #define SUR40_PARAM_RANGE(lo, hi) " (range " sur40_str(lo) "-" sur40_str(hi) ")" | ||
172 | |||
173 | /* module parameters */ | ||
174 | static uint brightness = SUR40_BRIGHTNESS_DEF; | ||
175 | module_param(brightness, uint, 0644); | ||
176 | MODULE_PARM_DESC(brightness, "set initial brightness" | ||
177 | SUR40_PARAM_RANGE(SUR40_BRIGHTNESS_MIN, SUR40_BRIGHTNESS_MAX)); | ||
178 | static uint contrast = SUR40_CONTRAST_DEF; | ||
179 | module_param(contrast, uint, 0644); | ||
180 | MODULE_PARM_DESC(contrast, "set initial contrast" | ||
181 | SUR40_PARAM_RANGE(SUR40_CONTRAST_MIN, SUR40_CONTRAST_MAX)); | ||
182 | static uint gain = SUR40_GAIN_DEF; | ||
183 | module_param(gain, uint, 0644); | ||
184 | MODULE_PARM_DESC(gain, "set initial gain" | ||
185 | SUR40_PARAM_RANGE(SUR40_GAIN_MIN, SUR40_GAIN_MAX)); | ||
186 | |||
149 | static const struct v4l2_pix_format sur40_pix_format[] = { | 187 | static const struct v4l2_pix_format sur40_pix_format[] = { |
150 | { | 188 | { |
151 | .pixelformat = V4L2_TCH_FMT_TU08, | 189 | .pixelformat = V4L2_TCH_FMT_TU08, |
@@ -178,6 +216,7 @@ struct sur40_state { | |||
178 | struct video_device vdev; | 216 | struct video_device vdev; |
179 | struct mutex lock; | 217 | struct mutex lock; |
180 | struct v4l2_pix_format pix_fmt; | 218 | struct v4l2_pix_format pix_fmt; |
219 | struct v4l2_ctrl_handler hdl; | ||
181 | 220 | ||
182 | struct vb2_queue queue; | 221 | struct vb2_queue queue; |
183 | struct list_head buf_list; | 222 | struct list_head buf_list; |
@@ -187,6 +226,7 @@ struct sur40_state { | |||
187 | struct sur40_data *bulk_in_buffer; | 226 | struct sur40_data *bulk_in_buffer; |
188 | size_t bulk_in_size; | 227 | size_t bulk_in_size; |
189 | u8 bulk_in_epaddr; | 228 | u8 bulk_in_epaddr; |
229 | u8 vsvideo; | ||
190 | 230 | ||
191 | char phys[64]; | 231 | char phys[64]; |
192 | }; | 232 | }; |
@@ -200,6 +240,11 @@ struct sur40_buffer { | |||
200 | static const struct video_device sur40_video_device; | 240 | static const struct video_device sur40_video_device; |
201 | static const struct vb2_queue sur40_queue; | 241 | static const struct vb2_queue sur40_queue; |
202 | static void sur40_process_video(struct sur40_state *sur40); | 242 | static void sur40_process_video(struct sur40_state *sur40); |
243 | static int sur40_s_ctrl(struct v4l2_ctrl *ctrl); | ||
244 | |||
245 | static const struct v4l2_ctrl_ops sur40_ctrl_ops = { | ||
246 | .s_ctrl = sur40_s_ctrl, | ||
247 | }; | ||
203 | 248 | ||
204 | /* | 249 | /* |
205 | * Note: an earlier, non-public version of this driver used USB_RECIP_ENDPOINT | 250 | * Note: an earlier, non-public version of this driver used USB_RECIP_ENDPOINT |
@@ -220,6 +265,81 @@ static int sur40_command(struct sur40_state *dev, | |||
220 | 0x00, index, buffer, size, 1000); | 265 | 0x00, index, buffer, size, 1000); |
221 | } | 266 | } |
222 | 267 | ||
268 | /* poke a byte in the panel register space */ | ||
269 | static int sur40_poke(struct sur40_state *dev, u8 offset, u8 value) | ||
270 | { | ||
271 | int result; | ||
272 | u8 index = 0x96; // 0xae for permanent write | ||
273 | |||
274 | result = usb_control_msg(dev->usbdev, usb_sndctrlpipe(dev->usbdev, 0), | ||
275 | SUR40_POKE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | ||
276 | 0x32, index, NULL, 0, 1000); | ||
277 | if (result < 0) | ||
278 | goto error; | ||
279 | msleep(5); | ||
280 | |||
281 | result = usb_control_msg(dev->usbdev, usb_sndctrlpipe(dev->usbdev, 0), | ||
282 | SUR40_POKE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | ||
283 | 0x72, offset, NULL, 0, 1000); | ||
284 | if (result < 0) | ||
285 | goto error; | ||
286 | msleep(5); | ||
287 | |||
288 | result = usb_control_msg(dev->usbdev, usb_sndctrlpipe(dev->usbdev, 0), | ||
289 | SUR40_POKE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | ||
290 | 0xb2, value, NULL, 0, 1000); | ||
291 | if (result < 0) | ||
292 | goto error; | ||
293 | msleep(5); | ||
294 | |||
295 | error: | ||
296 | return result; | ||
297 | } | ||
298 | |||
299 | static int sur40_set_preprocessor(struct sur40_state *dev, u8 value) | ||
300 | { | ||
301 | u8 setting_07[2] = { 0x01, 0x00 }; | ||
302 | u8 setting_17[2] = { 0x85, 0x80 }; | ||
303 | int result; | ||
304 | |||
305 | if (value > 1) | ||
306 | return -ERANGE; | ||
307 | |||
308 | result = usb_control_msg(dev->usbdev, usb_sndctrlpipe(dev->usbdev, 0), | ||
309 | SUR40_POKE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | ||
310 | 0x07, setting_07[value], NULL, 0, 1000); | ||
311 | if (result < 0) | ||
312 | goto error; | ||
313 | msleep(5); | ||
314 | |||
315 | result = usb_control_msg(dev->usbdev, usb_sndctrlpipe(dev->usbdev, 0), | ||
316 | SUR40_POKE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | ||
317 | 0x17, setting_17[value], NULL, 0, 1000); | ||
318 | if (result < 0) | ||
319 | goto error; | ||
320 | msleep(5); | ||
321 | |||
322 | error: | ||
323 | return result; | ||
324 | } | ||
325 | |||
326 | static void sur40_set_vsvideo(struct sur40_state *handle, u8 value) | ||
327 | { | ||
328 | int i; | ||
329 | |||
330 | for (i = 0; i < 4; i++) | ||
331 | sur40_poke(handle, 0x1c+i, value); | ||
332 | handle->vsvideo = value; | ||
333 | } | ||
334 | |||
335 | static void sur40_set_irlevel(struct sur40_state *handle, u8 value) | ||
336 | { | ||
337 | int i; | ||
338 | |||
339 | for (i = 0; i < 8; i++) | ||
340 | sur40_poke(handle, 0x08+(2*i), value); | ||
341 | } | ||
342 | |||
223 | /* Initialization routine, called from sur40_open */ | 343 | /* Initialization routine, called from sur40_open */ |
224 | static int sur40_init(struct sur40_state *dev) | 344 | static int sur40_init(struct sur40_state *dev) |
225 | { | 345 | { |
@@ -631,6 +751,36 @@ static int sur40_probe(struct usb_interface *interface, | |||
631 | sur40->vdev.queue = &sur40->queue; | 751 | sur40->vdev.queue = &sur40->queue; |
632 | video_set_drvdata(&sur40->vdev, sur40); | 752 | video_set_drvdata(&sur40->vdev, sur40); |
633 | 753 | ||
754 | /* initialize the control handler for 4 controls */ | ||
755 | v4l2_ctrl_handler_init(&sur40->hdl, 4); | ||
756 | sur40->v4l2.ctrl_handler = &sur40->hdl; | ||
757 | sur40->vsvideo = (SUR40_CONTRAST_DEF << 4) | SUR40_GAIN_DEF; | ||
758 | |||
759 | v4l2_ctrl_new_std(&sur40->hdl, &sur40_ctrl_ops, V4L2_CID_BRIGHTNESS, | ||
760 | SUR40_BRIGHTNESS_MIN, SUR40_BRIGHTNESS_MAX, 1, clamp(brightness, | ||
761 | (uint)SUR40_BRIGHTNESS_MIN, (uint)SUR40_BRIGHTNESS_MAX)); | ||
762 | |||
763 | v4l2_ctrl_new_std(&sur40->hdl, &sur40_ctrl_ops, V4L2_CID_CONTRAST, | ||
764 | SUR40_CONTRAST_MIN, SUR40_CONTRAST_MAX, 1, clamp(contrast, | ||
765 | (uint)SUR40_CONTRAST_MIN, (uint)SUR40_CONTRAST_MAX)); | ||
766 | |||
767 | v4l2_ctrl_new_std(&sur40->hdl, &sur40_ctrl_ops, V4L2_CID_GAIN, | ||
768 | SUR40_GAIN_MIN, SUR40_GAIN_MAX, 1, clamp(gain, | ||
769 | (uint)SUR40_GAIN_MIN, (uint)SUR40_GAIN_MAX)); | ||
770 | |||
771 | v4l2_ctrl_new_std(&sur40->hdl, &sur40_ctrl_ops, | ||
772 | V4L2_CID_BACKLIGHT_COMPENSATION, SUR40_BACKLIGHT_MIN, | ||
773 | SUR40_BACKLIGHT_MAX, 1, SUR40_BACKLIGHT_DEF); | ||
774 | |||
775 | v4l2_ctrl_handler_setup(&sur40->hdl); | ||
776 | |||
777 | if (sur40->hdl.error) { | ||
778 | dev_err(&interface->dev, | ||
779 | "Unable to register video controls."); | ||
780 | v4l2_ctrl_handler_free(&sur40->hdl); | ||
781 | goto err_unreg_v4l2; | ||
782 | } | ||
783 | |||
634 | error = video_register_device(&sur40->vdev, VFL_TYPE_TOUCH, -1); | 784 | error = video_register_device(&sur40->vdev, VFL_TYPE_TOUCH, -1); |
635 | if (error) { | 785 | if (error) { |
636 | dev_err(&interface->dev, | 786 | dev_err(&interface->dev, |
@@ -663,6 +813,7 @@ static void sur40_disconnect(struct usb_interface *interface) | |||
663 | { | 813 | { |
664 | struct sur40_state *sur40 = usb_get_intfdata(interface); | 814 | struct sur40_state *sur40 = usb_get_intfdata(interface); |
665 | 815 | ||
816 | v4l2_ctrl_handler_free(&sur40->hdl); | ||
666 | video_unregister_device(&sur40->vdev); | 817 | video_unregister_device(&sur40->vdev); |
667 | v4l2_device_unregister(&sur40->v4l2); | 818 | v4l2_device_unregister(&sur40->v4l2); |
668 | 819 | ||
@@ -856,6 +1007,31 @@ static int sur40_vidioc_g_fmt(struct file *file, void *priv, | |||
856 | return 0; | 1007 | return 0; |
857 | } | 1008 | } |
858 | 1009 | ||
1010 | static int sur40_s_ctrl(struct v4l2_ctrl *ctrl) | ||
1011 | { | ||
1012 | struct sur40_state *sur40 = container_of(ctrl->handler, | ||
1013 | struct sur40_state, hdl); | ||
1014 | u8 value = sur40->vsvideo; | ||
1015 | |||
1016 | switch (ctrl->id) { | ||
1017 | case V4L2_CID_BRIGHTNESS: | ||
1018 | sur40_set_irlevel(sur40, ctrl->val); | ||
1019 | break; | ||
1020 | case V4L2_CID_CONTRAST: | ||
1021 | value = (value & 0x0f) | (ctrl->val << 4); | ||
1022 | sur40_set_vsvideo(sur40, value); | ||
1023 | break; | ||
1024 | case V4L2_CID_GAIN: | ||
1025 | value = (value & 0xf0) | (ctrl->val); | ||
1026 | sur40_set_vsvideo(sur40, value); | ||
1027 | break; | ||
1028 | case V4L2_CID_BACKLIGHT_COMPENSATION: | ||
1029 | sur40_set_preprocessor(sur40, ctrl->val); | ||
1030 | break; | ||
1031 | } | ||
1032 | return 0; | ||
1033 | } | ||
1034 | |||
859 | static int sur40_ioctl_parm(struct file *file, void *priv, | 1035 | static int sur40_ioctl_parm(struct file *file, void *priv, |
860 | struct v4l2_streamparm *p) | 1036 | struct v4l2_streamparm *p) |
861 | { | 1037 | { |