aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSundar Raman2013-08-07 13:57:48 -0500
committerPraneeth Bajjuri2013-08-09 16:11:21 -0500
commit70af0c5ff9ea2b0aa1deb8674398c4714eaf2869 (patch)
tree029dcf62b8e26f1e94e4b7317823448457550aea
parentc5444cc3fe1dd3a812d4ec9e2c1890da5040eac6 (diff)
downloadkernel-audio-70af0c5ff9ea2b0aa1deb8674398c4714eaf2869.tar.gz
kernel-audio-70af0c5ff9ea2b0aa1deb8674398c4714eaf2869.tar.xz
kernel-audio-70af0c5ff9ea2b0aa1deb8674398c4714eaf2869.zip
Input: atmel_mxt_ts: Add device tree support
Add device tree support for Atmel touch driver. All platform specific data is now read from dts files and parsed inside the driver. NOTE: Provision for supplying config data for controller is given from board specific dts file since the driver no longer configures these values for different firmware revisions, after this commit: 71749f5c66e797a39600dae9de58aab3858dc488 Change-Id: Ic88bc62246e2465d527410e6fef78b301d681628 Signed-off-by: Sundar Raman <sunds@ti.com> Acked-by: Nishanth Menon <nm@ti.com>
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/atmel_mxt_ts.txt108
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c135
2 files changed, 238 insertions, 5 deletions
diff --git a/Documentation/devicetree/bindings/input/touchscreen/atmel_mxt_ts.txt b/Documentation/devicetree/bindings/input/touchscreen/atmel_mxt_ts.txt
new file mode 100644
index 000000000000..effc1abe5dcb
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/atmel_mxt_ts.txt
@@ -0,0 +1,108 @@
1Atmel MaxTouch Touchscreen
2--------------------------
3Required properties:
4 - compatible: "atmel,mXT244" or "atmel,qt602240_ts"
5 or "atmel,atmel_mxt_ts"
6 - reg: I2C address of the chip
7 - interrupts: interrupt signal to which the chip is connected
8 - atmel,x-line: Number of x lines the touch object occupies in pixels
9 - atmel,y-line: Number of y lines the touch object occupies in pixels
10 - atmel,x-size: Horizontal resolution of touchscreen in pixels
11 - atmel,y-size: Vertical resolution of touchscreen in pixels
12 - atmel,blen: Sets the gain of the analog circuit in front of ADC
13 Gain setting depends on package type. Range: 0-3
14 - atmel,threshold: Channel detection threshold value. Range: 0-255
15 Typical: 30-80. Lower the threshold, higher the
16 sensitivity
17 - atmel,voltage: Nominal AVdd in uV for analog circuitry, greater than
18 or less than base voltage of 2.7V, used for optimizing
19 capacitive sensing. For example, if you want to
20 program an optimum voltage of 2.8V in your design,
21 specify 2800000 for this parameter
22 - atmel,orientation: touchscreen orientation, must be one of following,
23 as defined inside include/linux/i2c/atmel_mxt_ts.h
24 - 0: MXT_NORMAL - normal
25 - 1: MXT_DIAGONAL - diagonal
26 - 2: MXT_HORIZONTAL_FLIP - horizonally flipped
27 - 3: MXT_ROTATED_90_COUNTER - rotated by 90 degrees
28 counter-clockwise
29 - 4: MXT_VERTICAL_FLIP - vertically flipped
30 - 5: MXT_ROTATED_90 - rotated by 90 degress clockwise
31 - 6: MXT_ROTATED_180 - rotated by 180 degrees
32 - 7: MXT_DIAGONAL_COUNTER - diagonal counter
33
34Optional properties:
35 - atmel,config: list of 8-bit register values for controller objects
36 in the following order. Number of objects and values depends on the
37 particular model of Atmel touch screen you are using. Please check
38 with your Atmel representative for helping you tune these values
39 GEN_COMMAND, GEN_POWER, GEN_ACQUIRE, TOUCH_MULTI
40 TOUCH_KEYARRAY, MXT244_COMMSCONFIG_T18, SPT_GPIOPWM, PROCI_GRIPFACE,
41 PROCG_NOISE, TOUCH_PROXIMITY, PROCI_ONETOUCH, SPT_SELFTEST,
42 PROCI_TWOTOUCH, SPT_CTECONFIG
43 Note: These register values can be specified here according to
44 the specific controller and platform configuration desired. The
45 driver does not configure these registers by default and leaves it
46 to the platform dts file to supply them
47
48Example:
49
50 &i2c1 {
51 mXT244:mXT244@4a {
52 reg = <0x4a>;
53 };
54 };
55
56 &mXT244 {
57 compatible = "atmel,mXT244";
58 interrupts = <0 119 0x4>;
59
60 atmel,config = <
61 /* MXT244_GEN_COMMAND(6) */
62 0x00 0x00 0x00 0x00 0x00 0x00
63 /* MXT244_GEN_POWER(7) */
64 0x20 0xff 0x32
65 /* MXT244_GEN_ACQUIRE(8) */
66 0x0a 0x00 0x05 0x00 0x00 0x00 0x09 0x23
67 /* MXT244_TOUCH_MULTI(9) */
68 0x00 0x00 0x00 0x13 0x0b 0x00 0x00 0x00 0x02 0x00
69 0x00 0x01 0x01 0x0e 0x0a 0x0a 0x0a 0x0a 0x00 0x00
70 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
71 0x00
72 /* MXT244_TOUCH_KEYARRAY(15) */
73 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
74 0x00
75 /* MXT244_COMMSCONFIG_T18(2) */
76 0x00 0x00
77 /* MXT244_SPT_GPIOPWM(19) */
78 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
79 0x00 0x00 0x00 0x00 0x00 0x00
80 /* MXT244_PROCI_GRIPFACE(20) */
81 0x07 0x00 0x00 0x00 0x00 0x00 0x00 0x50 0x28 0x04
82 0x0f 0x0a
83 /* MXT244_PROCG_NOISE(22) */
84 0x05 0x00 0x00 0x00 0x00 0x00 0x00 0x03 0x23 0x00
85 0x00 0x05 0x0f 0x19 0x23 0x2d 0x03
86 /* MXT244_TOUCH_PROXIMITY(23) */
87 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
88 0x00 0x00 0x00 0x00 0x00
89 /* MXT244_PROCI_ONETOUCH(24) */
90 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
91 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
92 /* MXT244_SPT_SELFTEST(25) */
93 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
94 0x00 0x00 0x00 0x00
95 /* MXT244_PROCI_TWOTOUCH(27) */
96 0x00 0x00 0x00 0x00 0x00 0x00 0x00
97 /* MXT244_SPT_CTECONFIG(28) */
98 0x00 0x00 0x02 0x08 0x10 0x00 >;
99
100 atmel,x_line = <18>;
101 atmel,y_line = <12>;
102 atmel,x_size = <800>;
103 atmel,y_size = <480>;
104 atmel,blen = <0x01>;
105 atmel,threshold = <30>;
106 atmel,voltage = <2800000>;
107 atmel,orient = <0x4>;
108 };
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 7dc24a3b31a5..69da9b335078 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -20,6 +20,8 @@
20#include <linux/input/mt.h> 20#include <linux/input/mt.h>
21#include <linux/interrupt.h> 21#include <linux/interrupt.h>
22#include <linux/slab.h> 22#include <linux/slab.h>
23#include <linux/of.h>
24#include <linux/of_device.h>
23 25
24/* Version */ 26/* Version */
25#define MXT_VER_20 20 27#define MXT_VER_20 20
@@ -324,6 +326,105 @@ static void mxt_dump_message(struct device *dev,
324 message->reportid, 7, message->message); 326 message->reportid, 7, message->message);
325} 327}
326 328
329static int mxt_of_get_platform_info(struct i2c_client *client,
330 struct mxt_platform_data *pdata)
331
332{
333 int size, index = 0;
334 u32 val;
335 const __be32 *config_be;
336 u8 *config;
337 const char *pname;
338 struct device_node *node = client->dev.of_node;
339
340 config_be = of_get_property(node, "atmel,config", &size);
341 if (config_be && size) {
342 size /= sizeof(*config_be);
343 config = devm_kzalloc(&client->dev, size, GFP_KERNEL);
344 if (!config) {
345 dev_err(&client->dev, "Failed to allocate memory\n");
346 return -ENOMEM;
347 }
348
349 pdata->config = config;
350 pdata->config_length = size;
351
352 while (index < size) {
353 config[index] = be32_to_cpup(config_be + index) & 0xFF;
354 index++;
355 }
356 } else {
357 dev_dbg(&client->dev, "%s:no config data specified\n",
358 __func__);
359 }
360
361 pname = "atmel,x_line";
362 if (of_property_read_u32(node, pname, &pdata->x_line)) {
363 dev_err(&client->dev, "%s: Failed to read %s property\n",
364 __func__, pname);
365 return -EINVAL;
366 }
367
368 pname = "atmel,y_line";
369 if (of_property_read_u32(node, pname, &pdata->y_line)) {
370 dev_err(&client->dev, "%s: Failed to read %s property\n",
371 __func__, pname);
372 return -EINVAL;
373 }
374
375 pname = "atmel,x_size";
376 if (of_property_read_u32(node, pname, &pdata->x_size)) {
377 dev_err(&client->dev, "%s: Failed to read %s property\n",
378 __func__, pname);
379 return -EINVAL;
380 }
381
382 pname = "atmel,y_size";
383 if (of_property_read_u32(node, pname, &pdata->y_size)) {
384 dev_err(&client->dev, "%s: Failed to read %s property\n",
385 __func__, pname);
386 return -EINVAL;
387 }
388
389 pname = "atmel,blen";
390 if (of_property_read_u32(node, pname, &pdata->blen)) {
391 dev_err(&client->dev, "%s: Failed to read %s property\n",
392 __func__, pname);
393 return -EINVAL;
394 }
395
396 pname = "atmel,threshold";
397 if (of_property_read_u32(node, pname, &pdata->threshold)) {
398 dev_err(&client->dev, "%s: Failed to read %s property\n",
399 __func__, pname);
400 return -EINVAL;
401 }
402
403 pname = "atmel,voltage";
404 if (of_property_read_u32(node, pname, &pdata->voltage)) {
405 dev_err(&client->dev,
406 "%s: Failed to read %s property\n",
407 __func__, pname);
408 return -EINVAL;
409 }
410
411 pname = "atmel,orient";
412 if (of_property_read_u32(node, pname, &val)) {
413 dev_err(&client->dev, "%s: Failed to read %s property\n",
414 __func__, pname);
415 return -EINVAL;
416 }
417
418 if (val > 0xFF) {
419 dev_err(&client->dev, "%s: Bad %s property value %d\n",
420 __func__, pname, val);
421 return -EINVAL;
422 }
423 pdata->orient = val & 0xFF;
424
425 return 0;
426}
427
327static int mxt_check_bootloader(struct i2c_client *client, 428static int mxt_check_bootloader(struct i2c_client *client,
328 unsigned int state) 429 unsigned int state)
329{ 430{
@@ -1095,17 +1196,40 @@ static void mxt_input_close(struct input_dev *dev)
1095 mxt_stop(data); 1196 mxt_stop(data);
1096} 1197}
1097 1198
1199static const struct of_device_id mxt_dt_ids[] = {
1200 { .compatible = "atmel,qt602240_ts", },
1201 { .compatible = "atmel,atmel_mxt_ts", },
1202 { .compatible = "atmel,mXT244", },
1203 { /* sentinel */ }
1204};
1205
1098static int mxt_probe(struct i2c_client *client, 1206static int mxt_probe(struct i2c_client *client,
1099 const struct i2c_device_id *id) 1207 const struct i2c_device_id *id)
1100{ 1208{
1101 const struct mxt_platform_data *pdata = client->dev.platform_data; 1209 struct mxt_platform_data *pdata;
1102 struct mxt_data *data; 1210 struct mxt_data *data;
1103 struct input_dev *input_dev; 1211 struct input_dev *input_dev;
1104 int error; 1212 int error;
1105 unsigned int num_mt_slots; 1213 unsigned int num_mt_slots;
1106 1214 const struct of_device_id *match;
1107 if (!pdata) 1215
1108 return -EINVAL; 1216 match = of_match_device(of_match_ptr(mxt_dt_ids), &client->dev);
1217 if (match) {
1218 pdata = devm_kzalloc(&client->dev,
1219 sizeof(struct mxt_platform_data),
1220 GFP_KERNEL);
1221 if (!pdata)
1222 return -ENOMEM;
1223 error = mxt_of_get_platform_info(client, pdata);
1224 if (error)
1225 return error;
1226 } else {
1227 pdata = client->dev.platform_data;
1228 if (!pdata) {
1229 dev_err(&client->dev, "Platform data not populated\n");
1230 return -EINVAL;
1231 }
1232 }
1109 1233
1110 data = devm_kzalloc(&client->dev, sizeof(struct mxt_data), GFP_KERNEL); 1234 data = devm_kzalloc(&client->dev, sizeof(struct mxt_data), GFP_KERNEL);
1111 input_dev = input_allocate_device(); 1235 input_dev = input_allocate_device();
@@ -1167,7 +1291,7 @@ static int mxt_probe(struct i2c_client *client,
1167 1291
1168 error = devm_request_threaded_irq(&client->dev, client->irq, 1292 error = devm_request_threaded_irq(&client->dev, client->irq,
1169 NULL, mxt_interrupt, 1293 NULL, mxt_interrupt,
1170 pdata->irqflags | IRQF_ONESHOT, 1294 IRQF_ONESHOT,
1171 dev_name(&client->dev), data); 1295 dev_name(&client->dev), data);
1172 if (error) { 1296 if (error) {
1173 dev_err(&client->dev, "Failed to register interrupt\n"); 1297 dev_err(&client->dev, "Failed to register interrupt\n");
@@ -1264,6 +1388,7 @@ static struct i2c_driver mxt_driver = {
1264 .name = "atmel_mxt_ts", 1388 .name = "atmel_mxt_ts",
1265 .owner = THIS_MODULE, 1389 .owner = THIS_MODULE,
1266 .pm = &mxt_pm_ops, 1390 .pm = &mxt_pm_ops,
1391 .of_match_table = mxt_dt_ids,
1267 }, 1392 },
1268 .probe = mxt_probe, 1393 .probe = mxt_probe,
1269 .remove = mxt_remove, 1394 .remove = mxt_remove,