diff options
Diffstat (limited to 'drivers')
24 files changed, 1619 insertions, 1208 deletions
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index a673c9f3a0b9..76842d7dc2e3 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -151,6 +151,18 @@ config KEYBOARD_BFIN | |||
151 | To compile this driver as a module, choose M here: the | 151 | To compile this driver as a module, choose M here: the |
152 | module will be called bf54x-keys. | 152 | module will be called bf54x-keys. |
153 | 153 | ||
154 | config KEYBOARD_CLPS711X | ||
155 | tristate "CLPS711X Keypad support" | ||
156 | depends on OF_GPIO && (ARCH_CLPS711X || COMPILE_TEST) | ||
157 | select INPUT_MATRIXKMAP | ||
158 | select INPUT_POLLDEV | ||
159 | help | ||
160 | Say Y here to enable the matrix keypad on the Cirrus Logic | ||
161 | CLPS711X CPUs. | ||
162 | |||
163 | To compile this driver as a module, choose M here: the | ||
164 | module will be called clps711x-keypad. | ||
165 | |||
154 | config KEYBOARD_LKKBD | 166 | config KEYBOARD_LKKBD |
155 | tristate "DECstation/VAXstation LK201/LK401 keyboard" | 167 | tristate "DECstation/VAXstation LK201/LK401 keyboard" |
156 | select SERIO | 168 | select SERIO |
@@ -595,16 +607,6 @@ config KEYBOARD_TC3589X | |||
595 | To compile this driver as a module, choose M here: the | 607 | To compile this driver as a module, choose M here: the |
596 | module will be called tc3589x-keypad. | 608 | module will be called tc3589x-keypad. |
597 | 609 | ||
598 | config KEYBOARD_TNETV107X | ||
599 | tristate "TI TNETV107X keypad support" | ||
600 | depends on ARCH_DAVINCI_TNETV107X | ||
601 | select INPUT_MATRIXKMAP | ||
602 | help | ||
603 | Say Y here if you want to use the TNETV107X keypad. | ||
604 | |||
605 | To compile this driver as a module, choose M here: the | ||
606 | module will be called tnetv107x-keypad. | ||
607 | |||
608 | config KEYBOARD_TWL4030 | 610 | config KEYBOARD_TWL4030 |
609 | tristate "TI TWL4030/TWL5030/TPS659x0 keypad support" | 611 | tristate "TI TWL4030/TWL5030/TPS659x0 keypad support" |
610 | depends on TWL4030_CORE | 612 | depends on TWL4030_CORE |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index a699b6172303..11cff7b84b47 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -11,6 +11,7 @@ obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o | |||
11 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o | 11 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o |
12 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o | 12 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o |
13 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o | 13 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o |
14 | obj-$(CONFIG_KEYBOARD_CLPS711X) += clps711x-keypad.o | ||
14 | obj-$(CONFIG_KEYBOARD_CROS_EC) += cros_ec_keyb.o | 15 | obj-$(CONFIG_KEYBOARD_CROS_EC) += cros_ec_keyb.o |
15 | obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o | 16 | obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o |
16 | obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o | 17 | obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o |
@@ -53,7 +54,6 @@ obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | |||
53 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o | 54 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o |
54 | obj-$(CONFIG_KEYBOARD_TC3589X) += tc3589x-keypad.o | 55 | obj-$(CONFIG_KEYBOARD_TC3589X) += tc3589x-keypad.o |
55 | obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o | 56 | obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o |
56 | obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o | ||
57 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o | 57 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o |
58 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o | 58 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o |
59 | obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o | 59 | obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o |
diff --git a/drivers/input/keyboard/clps711x-keypad.c b/drivers/input/keyboard/clps711x-keypad.c new file mode 100644 index 000000000000..3955aecee44b --- /dev/null +++ b/drivers/input/keyboard/clps711x-keypad.c | |||
@@ -0,0 +1,207 @@ | |||
1 | /* | ||
2 | * Cirrus Logic CLPS711X Keypad driver | ||
3 | * | ||
4 | * Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/input.h> | ||
13 | #include <linux/input-polldev.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/of_gpio.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/regmap.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <linux/input/matrix_keypad.h> | ||
20 | #include <linux/mfd/syscon.h> | ||
21 | #include <linux/mfd/syscon/clps711x.h> | ||
22 | |||
23 | #define CLPS711X_KEYPAD_COL_COUNT 8 | ||
24 | |||
25 | struct clps711x_gpio_data { | ||
26 | struct gpio_desc *desc; | ||
27 | DECLARE_BITMAP(last_state, CLPS711X_KEYPAD_COL_COUNT); | ||
28 | }; | ||
29 | |||
30 | struct clps711x_keypad_data { | ||
31 | struct regmap *syscon; | ||
32 | int row_count; | ||
33 | unsigned int row_shift; | ||
34 | struct clps711x_gpio_data *gpio_data; | ||
35 | }; | ||
36 | |||
37 | static void clps711x_keypad_poll(struct input_polled_dev *dev) | ||
38 | { | ||
39 | const unsigned short *keycodes = dev->input->keycode; | ||
40 | struct clps711x_keypad_data *priv = dev->private; | ||
41 | bool sync = false; | ||
42 | int col, row; | ||
43 | |||
44 | for (col = 0; col < CLPS711X_KEYPAD_COL_COUNT; col++) { | ||
45 | /* Assert column */ | ||
46 | regmap_update_bits(priv->syscon, SYSCON_OFFSET, | ||
47 | SYSCON1_KBDSCAN_MASK, | ||
48 | SYSCON1_KBDSCAN(8 + col)); | ||
49 | |||
50 | /* Scan rows */ | ||
51 | for (row = 0; row < priv->row_count; row++) { | ||
52 | struct clps711x_gpio_data *data = &priv->gpio_data[row]; | ||
53 | bool state, state1; | ||
54 | |||
55 | /* Read twice for protection against fluctuations */ | ||
56 | do { | ||
57 | state = gpiod_get_value_cansleep(data->desc); | ||
58 | cond_resched(); | ||
59 | state1 = gpiod_get_value_cansleep(data->desc); | ||
60 | } while (state != state1); | ||
61 | |||
62 | if (test_bit(col, data->last_state) != state) { | ||
63 | int code = MATRIX_SCAN_CODE(row, col, | ||
64 | priv->row_shift); | ||
65 | |||
66 | if (state) { | ||
67 | set_bit(col, data->last_state); | ||
68 | input_event(dev->input, EV_MSC, | ||
69 | MSC_SCAN, code); | ||
70 | } else { | ||
71 | clear_bit(col, data->last_state); | ||
72 | } | ||
73 | |||
74 | if (keycodes[code]) | ||
75 | input_report_key(dev->input, | ||
76 | keycodes[code], state); | ||
77 | sync = true; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | /* Set all columns to low */ | ||
82 | regmap_update_bits(priv->syscon, SYSCON_OFFSET, | ||
83 | SYSCON1_KBDSCAN_MASK, SYSCON1_KBDSCAN(1)); | ||
84 | } | ||
85 | |||
86 | if (sync) | ||
87 | input_sync(dev->input); | ||
88 | } | ||
89 | |||
90 | static int clps711x_keypad_probe(struct platform_device *pdev) | ||
91 | { | ||
92 | struct clps711x_keypad_data *priv; | ||
93 | struct device *dev = &pdev->dev; | ||
94 | struct device_node *np = dev->of_node; | ||
95 | struct input_polled_dev *poll_dev; | ||
96 | u32 poll_interval; | ||
97 | int i, err; | ||
98 | |||
99 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
100 | if (!priv) | ||
101 | return -ENOMEM; | ||
102 | |||
103 | priv->syscon = | ||
104 | syscon_regmap_lookup_by_compatible("cirrus,clps711x-syscon1"); | ||
105 | if (IS_ERR(priv->syscon)) | ||
106 | return PTR_ERR(priv->syscon); | ||
107 | |||
108 | priv->row_count = of_gpio_named_count(np, "row-gpios"); | ||
109 | if (priv->row_count < 1) | ||
110 | return -EINVAL; | ||
111 | |||
112 | priv->gpio_data = devm_kzalloc(dev, | ||
113 | sizeof(*priv->gpio_data) * priv->row_count, | ||
114 | GFP_KERNEL); | ||
115 | if (!priv->gpio_data) | ||
116 | return -ENOMEM; | ||
117 | |||
118 | priv->row_shift = get_count_order(CLPS711X_KEYPAD_COL_COUNT); | ||
119 | |||
120 | for (i = 0; i < priv->row_count; i++) { | ||
121 | struct clps711x_gpio_data *data = &priv->gpio_data[i]; | ||
122 | |||
123 | data->desc = devm_gpiod_get_index(dev, "row", i); | ||
124 | if (!data->desc) | ||
125 | return -EINVAL; | ||
126 | |||
127 | if (IS_ERR(data->desc)) | ||
128 | return PTR_ERR(data->desc); | ||
129 | |||
130 | gpiod_direction_input(data->desc); | ||
131 | } | ||
132 | |||
133 | err = of_property_read_u32(np, "poll-interval", &poll_interval); | ||
134 | if (err) | ||
135 | return err; | ||
136 | |||
137 | poll_dev = input_allocate_polled_device(); | ||
138 | if (!poll_dev) | ||
139 | return -ENOMEM; | ||
140 | |||
141 | poll_dev->private = priv; | ||
142 | poll_dev->poll = clps711x_keypad_poll; | ||
143 | poll_dev->poll_interval = poll_interval; | ||
144 | poll_dev->input->name = pdev->name; | ||
145 | poll_dev->input->dev.parent = dev; | ||
146 | poll_dev->input->id.bustype = BUS_HOST; | ||
147 | poll_dev->input->id.vendor = 0x0001; | ||
148 | poll_dev->input->id.product = 0x0001; | ||
149 | poll_dev->input->id.version = 0x0100; | ||
150 | |||
151 | err = matrix_keypad_build_keymap(NULL, NULL, priv->row_count, | ||
152 | CLPS711X_KEYPAD_COL_COUNT, | ||
153 | NULL, poll_dev->input); | ||
154 | if (err) | ||
155 | goto out_err; | ||
156 | |||
157 | input_set_capability(poll_dev->input, EV_MSC, MSC_SCAN); | ||
158 | if (of_property_read_bool(np, "autorepeat")) | ||
159 | __set_bit(EV_REP, poll_dev->input->evbit); | ||
160 | |||
161 | platform_set_drvdata(pdev, poll_dev); | ||
162 | |||
163 | /* Set all columns to low */ | ||
164 | regmap_update_bits(priv->syscon, SYSCON_OFFSET, SYSCON1_KBDSCAN_MASK, | ||
165 | SYSCON1_KBDSCAN(1)); | ||
166 | |||
167 | err = input_register_polled_device(poll_dev); | ||
168 | if (err) | ||
169 | goto out_err; | ||
170 | |||
171 | return 0; | ||
172 | |||
173 | out_err: | ||
174 | input_free_polled_device(poll_dev); | ||
175 | return err; | ||
176 | } | ||
177 | |||
178 | static int clps711x_keypad_remove(struct platform_device *pdev) | ||
179 | { | ||
180 | struct input_polled_dev *poll_dev = platform_get_drvdata(pdev); | ||
181 | |||
182 | input_unregister_polled_device(poll_dev); | ||
183 | input_free_polled_device(poll_dev); | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static struct of_device_id clps711x_keypad_of_match[] = { | ||
189 | { .compatible = "cirrus,clps711x-keypad", }, | ||
190 | { } | ||
191 | }; | ||
192 | MODULE_DEVICE_TABLE(of, clps711x_keypad_of_match); | ||
193 | |||
194 | static struct platform_driver clps711x_keypad_driver = { | ||
195 | .driver = { | ||
196 | .name = "clps711x-keypad", | ||
197 | .owner = THIS_MODULE, | ||
198 | .of_match_table = clps711x_keypad_of_match, | ||
199 | }, | ||
200 | .probe = clps711x_keypad_probe, | ||
201 | .remove = clps711x_keypad_remove, | ||
202 | }; | ||
203 | module_platform_driver(clps711x_keypad_driver); | ||
204 | |||
205 | MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>"); | ||
206 | MODULE_DESCRIPTION("Cirrus Logic CLPS711X Keypad driver"); | ||
207 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index cbf4f8038cba..97ec33572e56 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c | |||
@@ -439,7 +439,7 @@ static int imx_keypad_probe(struct platform_device *pdev) | |||
439 | irq = platform_get_irq(pdev, 0); | 439 | irq = platform_get_irq(pdev, 0); |
440 | if (irq < 0) { | 440 | if (irq < 0) { |
441 | dev_err(&pdev->dev, "no irq defined in platform data\n"); | 441 | dev_err(&pdev->dev, "no irq defined in platform data\n"); |
442 | return -EINVAL; | 442 | return irq; |
443 | } | 443 | } |
444 | 444 | ||
445 | input_dev = devm_input_allocate_device(&pdev->dev); | 445 | input_dev = devm_input_allocate_device(&pdev->dev); |
@@ -449,7 +449,7 @@ static int imx_keypad_probe(struct platform_device *pdev) | |||
449 | } | 449 | } |
450 | 450 | ||
451 | keypad = devm_kzalloc(&pdev->dev, sizeof(struct imx_keypad), | 451 | keypad = devm_kzalloc(&pdev->dev, sizeof(struct imx_keypad), |
452 | GFP_KERNEL); | 452 | GFP_KERNEL); |
453 | if (!keypad) { | 453 | if (!keypad) { |
454 | dev_err(&pdev->dev, "not enough memory for driver data\n"); | 454 | dev_err(&pdev->dev, "not enough memory for driver data\n"); |
455 | return -ENOMEM; | 455 | return -ENOMEM; |
diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c index 2c9f19ac35ea..80c6b0ef3fc8 100644 --- a/drivers/input/keyboard/pmic8xxx-keypad.c +++ b/drivers/input/keyboard/pmic8xxx-keypad.c | |||
@@ -19,10 +19,9 @@ | |||
19 | #include <linux/bitops.h> | 19 | #include <linux/bitops.h> |
20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/mutex.h> | 21 | #include <linux/mutex.h> |
22 | 22 | #include <linux/regmap.h> | |
23 | #include <linux/mfd/pm8xxx/core.h> | 23 | #include <linux/of.h> |
24 | #include <linux/mfd/pm8xxx/gpio.h> | 24 | #include <linux/input/matrix_keypad.h> |
25 | #include <linux/input/pmic8xxx-keypad.h> | ||
26 | 25 | ||
27 | #define PM8XXX_MAX_ROWS 18 | 26 | #define PM8XXX_MAX_ROWS 18 |
28 | #define PM8XXX_MAX_COLS 8 | 27 | #define PM8XXX_MAX_COLS 8 |
@@ -85,8 +84,10 @@ | |||
85 | 84 | ||
86 | /** | 85 | /** |
87 | * struct pmic8xxx_kp - internal keypad data structure | 86 | * struct pmic8xxx_kp - internal keypad data structure |
88 | * @pdata - keypad platform data pointer | 87 | * @num_cols - number of columns of keypad |
88 | * @num_rows - number of row of keypad | ||
89 | * @input - input device pointer for keypad | 89 | * @input - input device pointer for keypad |
90 | * @regmap - regmap handle | ||
90 | * @key_sense_irq - key press/release irq number | 91 | * @key_sense_irq - key press/release irq number |
91 | * @key_stuck_irq - key stuck notification irq number | 92 | * @key_stuck_irq - key stuck notification irq number |
92 | * @keycodes - array to hold the key codes | 93 | * @keycodes - array to hold the key codes |
@@ -96,8 +97,10 @@ | |||
96 | * @ctrl_reg - control register value | 97 | * @ctrl_reg - control register value |
97 | */ | 98 | */ |
98 | struct pmic8xxx_kp { | 99 | struct pmic8xxx_kp { |
99 | const struct pm8xxx_keypad_platform_data *pdata; | 100 | unsigned int num_rows; |
101 | unsigned int num_cols; | ||
100 | struct input_dev *input; | 102 | struct input_dev *input; |
103 | struct regmap *regmap; | ||
101 | int key_sense_irq; | 104 | int key_sense_irq; |
102 | int key_stuck_irq; | 105 | int key_stuck_irq; |
103 | 106 | ||
@@ -110,40 +113,13 @@ struct pmic8xxx_kp { | |||
110 | u8 ctrl_reg; | 113 | u8 ctrl_reg; |
111 | }; | 114 | }; |
112 | 115 | ||
113 | static int pmic8xxx_kp_write_u8(struct pmic8xxx_kp *kp, | ||
114 | u8 data, u16 reg) | ||
115 | { | ||
116 | int rc; | ||
117 | |||
118 | rc = pm8xxx_writeb(kp->dev->parent, reg, data); | ||
119 | return rc; | ||
120 | } | ||
121 | |||
122 | static int pmic8xxx_kp_read(struct pmic8xxx_kp *kp, | ||
123 | u8 *data, u16 reg, unsigned num_bytes) | ||
124 | { | ||
125 | int rc; | ||
126 | |||
127 | rc = pm8xxx_read_buf(kp->dev->parent, reg, data, num_bytes); | ||
128 | return rc; | ||
129 | } | ||
130 | |||
131 | static int pmic8xxx_kp_read_u8(struct pmic8xxx_kp *kp, | ||
132 | u8 *data, u16 reg) | ||
133 | { | ||
134 | int rc; | ||
135 | |||
136 | rc = pmic8xxx_kp_read(kp, data, reg, 1); | ||
137 | return rc; | ||
138 | } | ||
139 | |||
140 | static u8 pmic8xxx_col_state(struct pmic8xxx_kp *kp, u8 col) | 116 | static u8 pmic8xxx_col_state(struct pmic8xxx_kp *kp, u8 col) |
141 | { | 117 | { |
142 | /* all keys pressed on that particular row? */ | 118 | /* all keys pressed on that particular row? */ |
143 | if (col == 0x00) | 119 | if (col == 0x00) |
144 | return 1 << kp->pdata->num_cols; | 120 | return 1 << kp->num_cols; |
145 | else | 121 | else |
146 | return col & ((1 << kp->pdata->num_cols) - 1); | 122 | return col & ((1 << kp->num_cols) - 1); |
147 | } | 123 | } |
148 | 124 | ||
149 | /* | 125 | /* |
@@ -161,9 +137,9 @@ static u8 pmic8xxx_col_state(struct pmic8xxx_kp *kp, u8 col) | |||
161 | static int pmic8xxx_chk_sync_read(struct pmic8xxx_kp *kp) | 137 | static int pmic8xxx_chk_sync_read(struct pmic8xxx_kp *kp) |
162 | { | 138 | { |
163 | int rc; | 139 | int rc; |
164 | u8 scan_val; | 140 | unsigned int scan_val; |
165 | 141 | ||
166 | rc = pmic8xxx_kp_read_u8(kp, &scan_val, KEYP_SCAN); | 142 | rc = regmap_read(kp->regmap, KEYP_SCAN, &scan_val); |
167 | if (rc < 0) { | 143 | if (rc < 0) { |
168 | dev_err(kp->dev, "Error reading KEYP_SCAN reg, rc=%d\n", rc); | 144 | dev_err(kp->dev, "Error reading KEYP_SCAN reg, rc=%d\n", rc); |
169 | return rc; | 145 | return rc; |
@@ -171,7 +147,7 @@ static int pmic8xxx_chk_sync_read(struct pmic8xxx_kp *kp) | |||
171 | 147 | ||
172 | scan_val |= 0x1; | 148 | scan_val |= 0x1; |
173 | 149 | ||
174 | rc = pmic8xxx_kp_write_u8(kp, scan_val, KEYP_SCAN); | 150 | rc = regmap_write(kp->regmap, KEYP_SCAN, scan_val); |
175 | if (rc < 0) { | 151 | if (rc < 0) { |
176 | dev_err(kp->dev, "Error writing KEYP_SCAN reg, rc=%d\n", rc); | 152 | dev_err(kp->dev, "Error writing KEYP_SCAN reg, rc=%d\n", rc); |
177 | return rc; | 153 | return rc; |
@@ -187,31 +163,29 @@ static int pmic8xxx_kp_read_data(struct pmic8xxx_kp *kp, u16 *state, | |||
187 | u16 data_reg, int read_rows) | 163 | u16 data_reg, int read_rows) |
188 | { | 164 | { |
189 | int rc, row; | 165 | int rc, row; |
190 | u8 new_data[PM8XXX_MAX_ROWS]; | 166 | unsigned int val; |
191 | |||
192 | rc = pmic8xxx_kp_read(kp, new_data, data_reg, read_rows); | ||
193 | if (rc) | ||
194 | return rc; | ||
195 | 167 | ||
196 | for (row = 0; row < kp->pdata->num_rows; row++) { | 168 | for (row = 0; row < read_rows; row++) { |
197 | dev_dbg(kp->dev, "new_data[%d] = %d\n", row, | 169 | rc = regmap_read(kp->regmap, data_reg, &val); |
198 | new_data[row]); | 170 | if (rc) |
199 | state[row] = pmic8xxx_col_state(kp, new_data[row]); | 171 | return rc; |
172 | dev_dbg(kp->dev, "%d = %d\n", row, val); | ||
173 | state[row] = pmic8xxx_col_state(kp, val); | ||
200 | } | 174 | } |
201 | 175 | ||
202 | return rc; | 176 | return 0; |
203 | } | 177 | } |
204 | 178 | ||
205 | static int pmic8xxx_kp_read_matrix(struct pmic8xxx_kp *kp, u16 *new_state, | 179 | static int pmic8xxx_kp_read_matrix(struct pmic8xxx_kp *kp, u16 *new_state, |
206 | u16 *old_state) | 180 | u16 *old_state) |
207 | { | 181 | { |
208 | int rc, read_rows; | 182 | int rc, read_rows; |
209 | u8 scan_val; | 183 | unsigned int scan_val; |
210 | 184 | ||
211 | if (kp->pdata->num_rows < PM8XXX_MIN_ROWS) | 185 | if (kp->num_rows < PM8XXX_MIN_ROWS) |
212 | read_rows = PM8XXX_MIN_ROWS; | 186 | read_rows = PM8XXX_MIN_ROWS; |
213 | else | 187 | else |
214 | read_rows = kp->pdata->num_rows; | 188 | read_rows = kp->num_rows; |
215 | 189 | ||
216 | pmic8xxx_chk_sync_read(kp); | 190 | pmic8xxx_chk_sync_read(kp); |
217 | 191 | ||
@@ -236,14 +210,14 @@ static int pmic8xxx_kp_read_matrix(struct pmic8xxx_kp *kp, u16 *new_state, | |||
236 | /* 4 * 32KHz clocks */ | 210 | /* 4 * 32KHz clocks */ |
237 | udelay((4 * DIV_ROUND_UP(USEC_PER_SEC, KEYP_CLOCK_FREQ)) + 1); | 211 | udelay((4 * DIV_ROUND_UP(USEC_PER_SEC, KEYP_CLOCK_FREQ)) + 1); |
238 | 212 | ||
239 | rc = pmic8xxx_kp_read_u8(kp, &scan_val, KEYP_SCAN); | 213 | rc = regmap_read(kp->regmap, KEYP_SCAN, &scan_val); |
240 | if (rc < 0) { | 214 | if (rc < 0) { |
241 | dev_err(kp->dev, "Error reading KEYP_SCAN reg, rc=%d\n", rc); | 215 | dev_err(kp->dev, "Error reading KEYP_SCAN reg, rc=%d\n", rc); |
242 | return rc; | 216 | return rc; |
243 | } | 217 | } |
244 | 218 | ||
245 | scan_val &= 0xFE; | 219 | scan_val &= 0xFE; |
246 | rc = pmic8xxx_kp_write_u8(kp, scan_val, KEYP_SCAN); | 220 | rc = regmap_write(kp->regmap, KEYP_SCAN, scan_val); |
247 | if (rc < 0) | 221 | if (rc < 0) |
248 | dev_err(kp->dev, "Error writing KEYP_SCAN reg, rc=%d\n", rc); | 222 | dev_err(kp->dev, "Error writing KEYP_SCAN reg, rc=%d\n", rc); |
249 | 223 | ||
@@ -255,13 +229,13 @@ static void __pmic8xxx_kp_scan_matrix(struct pmic8xxx_kp *kp, u16 *new_state, | |||
255 | { | 229 | { |
256 | int row, col, code; | 230 | int row, col, code; |
257 | 231 | ||
258 | for (row = 0; row < kp->pdata->num_rows; row++) { | 232 | for (row = 0; row < kp->num_rows; row++) { |
259 | int bits_changed = new_state[row] ^ old_state[row]; | 233 | int bits_changed = new_state[row] ^ old_state[row]; |
260 | 234 | ||
261 | if (!bits_changed) | 235 | if (!bits_changed) |
262 | continue; | 236 | continue; |
263 | 237 | ||
264 | for (col = 0; col < kp->pdata->num_cols; col++) { | 238 | for (col = 0; col < kp->num_cols; col++) { |
265 | if (!(bits_changed & (1 << col))) | 239 | if (!(bits_changed & (1 << col))) |
266 | continue; | 240 | continue; |
267 | 241 | ||
@@ -287,9 +261,9 @@ static bool pmic8xxx_detect_ghost_keys(struct pmic8xxx_kp *kp, u16 *new_state) | |||
287 | u16 check, row_state; | 261 | u16 check, row_state; |
288 | 262 | ||
289 | check = 0; | 263 | check = 0; |
290 | for (row = 0; row < kp->pdata->num_rows; row++) { | 264 | for (row = 0; row < kp->num_rows; row++) { |
291 | row_state = (~new_state[row]) & | 265 | row_state = (~new_state[row]) & |
292 | ((1 << kp->pdata->num_cols) - 1); | 266 | ((1 << kp->num_cols) - 1); |
293 | 267 | ||
294 | if (hweight16(row_state) > 1) { | 268 | if (hweight16(row_state) > 1) { |
295 | if (found_first == -1) | 269 | if (found_first == -1) |
@@ -379,10 +353,10 @@ static irqreturn_t pmic8xxx_kp_stuck_irq(int irq, void *data) | |||
379 | static irqreturn_t pmic8xxx_kp_irq(int irq, void *data) | 353 | static irqreturn_t pmic8xxx_kp_irq(int irq, void *data) |
380 | { | 354 | { |
381 | struct pmic8xxx_kp *kp = data; | 355 | struct pmic8xxx_kp *kp = data; |
382 | u8 ctrl_val, events; | 356 | unsigned int ctrl_val, events; |
383 | int rc; | 357 | int rc; |
384 | 358 | ||
385 | rc = pmic8xxx_kp_read(kp, &ctrl_val, KEYP_CTRL, 1); | 359 | rc = regmap_read(kp->regmap, KEYP_CTRL, &ctrl_val); |
386 | if (rc < 0) { | 360 | if (rc < 0) { |
387 | dev_err(kp->dev, "failed to read keyp_ctrl register\n"); | 361 | dev_err(kp->dev, "failed to read keyp_ctrl register\n"); |
388 | return IRQ_HANDLED; | 362 | return IRQ_HANDLED; |
@@ -397,8 +371,13 @@ static irqreturn_t pmic8xxx_kp_irq(int irq, void *data) | |||
397 | return IRQ_HANDLED; | 371 | return IRQ_HANDLED; |
398 | } | 372 | } |
399 | 373 | ||
400 | static int pmic8xxx_kpd_init(struct pmic8xxx_kp *kp) | 374 | static int pmic8xxx_kpd_init(struct pmic8xxx_kp *kp, |
375 | struct platform_device *pdev) | ||
401 | { | 376 | { |
377 | const struct device_node *of_node = pdev->dev.of_node; | ||
378 | unsigned int scan_delay_ms; | ||
379 | unsigned int row_hold_ns; | ||
380 | unsigned int debounce_ms; | ||
402 | int bits, rc, cycles; | 381 | int bits, rc, cycles; |
403 | u8 scan_val = 0, ctrl_val = 0; | 382 | u8 scan_val = 0, ctrl_val = 0; |
404 | static const u8 row_bits[] = { | 383 | static const u8 row_bits[] = { |
@@ -406,40 +385,69 @@ static int pmic8xxx_kpd_init(struct pmic8xxx_kp *kp) | |||
406 | }; | 385 | }; |
407 | 386 | ||
408 | /* Find column bits */ | 387 | /* Find column bits */ |
409 | if (kp->pdata->num_cols < KEYP_CTRL_SCAN_COLS_MIN) | 388 | if (kp->num_cols < KEYP_CTRL_SCAN_COLS_MIN) |
410 | bits = 0; | 389 | bits = 0; |
411 | else | 390 | else |
412 | bits = kp->pdata->num_cols - KEYP_CTRL_SCAN_COLS_MIN; | 391 | bits = kp->num_cols - KEYP_CTRL_SCAN_COLS_MIN; |
413 | ctrl_val = (bits & KEYP_CTRL_SCAN_COLS_BITS) << | 392 | ctrl_val = (bits & KEYP_CTRL_SCAN_COLS_BITS) << |
414 | KEYP_CTRL_SCAN_COLS_SHIFT; | 393 | KEYP_CTRL_SCAN_COLS_SHIFT; |
415 | 394 | ||
416 | /* Find row bits */ | 395 | /* Find row bits */ |
417 | if (kp->pdata->num_rows < KEYP_CTRL_SCAN_ROWS_MIN) | 396 | if (kp->num_rows < KEYP_CTRL_SCAN_ROWS_MIN) |
418 | bits = 0; | 397 | bits = 0; |
419 | else | 398 | else |
420 | bits = row_bits[kp->pdata->num_rows - KEYP_CTRL_SCAN_ROWS_MIN]; | 399 | bits = row_bits[kp->num_rows - KEYP_CTRL_SCAN_ROWS_MIN]; |
421 | 400 | ||
422 | ctrl_val |= (bits << KEYP_CTRL_SCAN_ROWS_SHIFT); | 401 | ctrl_val |= (bits << KEYP_CTRL_SCAN_ROWS_SHIFT); |
423 | 402 | ||
424 | rc = pmic8xxx_kp_write_u8(kp, ctrl_val, KEYP_CTRL); | 403 | rc = regmap_write(kp->regmap, KEYP_CTRL, ctrl_val); |
425 | if (rc < 0) { | 404 | if (rc < 0) { |
426 | dev_err(kp->dev, "Error writing KEYP_CTRL reg, rc=%d\n", rc); | 405 | dev_err(kp->dev, "Error writing KEYP_CTRL reg, rc=%d\n", rc); |
427 | return rc; | 406 | return rc; |
428 | } | 407 | } |
429 | 408 | ||
430 | bits = (kp->pdata->debounce_ms / 5) - 1; | 409 | if (of_property_read_u32(of_node, "scan-delay", &scan_delay_ms)) |
410 | scan_delay_ms = MIN_SCAN_DELAY; | ||
411 | |||
412 | if (scan_delay_ms > MAX_SCAN_DELAY || scan_delay_ms < MIN_SCAN_DELAY || | ||
413 | !is_power_of_2(scan_delay_ms)) { | ||
414 | dev_err(&pdev->dev, "invalid keypad scan time supplied\n"); | ||
415 | return -EINVAL; | ||
416 | } | ||
417 | |||
418 | if (of_property_read_u32(of_node, "row-hold", &row_hold_ns)) | ||
419 | row_hold_ns = MIN_ROW_HOLD_DELAY; | ||
420 | |||
421 | if (row_hold_ns > MAX_ROW_HOLD_DELAY || | ||
422 | row_hold_ns < MIN_ROW_HOLD_DELAY || | ||
423 | ((row_hold_ns % MIN_ROW_HOLD_DELAY) != 0)) { | ||
424 | dev_err(&pdev->dev, "invalid keypad row hold time supplied\n"); | ||
425 | return -EINVAL; | ||
426 | } | ||
427 | |||
428 | if (of_property_read_u32(of_node, "debounce", &debounce_ms)) | ||
429 | debounce_ms = MIN_DEBOUNCE_TIME; | ||
430 | |||
431 | if (((debounce_ms % 5) != 0) || | ||
432 | debounce_ms > MAX_DEBOUNCE_TIME || | ||
433 | debounce_ms < MIN_DEBOUNCE_TIME) { | ||
434 | dev_err(&pdev->dev, "invalid debounce time supplied\n"); | ||
435 | return -EINVAL; | ||
436 | } | ||
437 | |||
438 | bits = (debounce_ms / 5) - 1; | ||
431 | 439 | ||
432 | scan_val |= (bits << KEYP_SCAN_DBOUNCE_SHIFT); | 440 | scan_val |= (bits << KEYP_SCAN_DBOUNCE_SHIFT); |
433 | 441 | ||
434 | bits = fls(kp->pdata->scan_delay_ms) - 1; | 442 | bits = fls(scan_delay_ms) - 1; |
435 | scan_val |= (bits << KEYP_SCAN_PAUSE_SHIFT); | 443 | scan_val |= (bits << KEYP_SCAN_PAUSE_SHIFT); |
436 | 444 | ||
437 | /* Row hold time is a multiple of 32KHz cycles. */ | 445 | /* Row hold time is a multiple of 32KHz cycles. */ |
438 | cycles = (kp->pdata->row_hold_ns * KEYP_CLOCK_FREQ) / NSEC_PER_SEC; | 446 | cycles = (row_hold_ns * KEYP_CLOCK_FREQ) / NSEC_PER_SEC; |
439 | 447 | ||
440 | scan_val |= (cycles << KEYP_SCAN_ROW_HOLD_SHIFT); | 448 | scan_val |= (cycles << KEYP_SCAN_ROW_HOLD_SHIFT); |
441 | 449 | ||
442 | rc = pmic8xxx_kp_write_u8(kp, scan_val, KEYP_SCAN); | 450 | rc = regmap_write(kp->regmap, KEYP_SCAN, scan_val); |
443 | if (rc) | 451 | if (rc) |
444 | dev_err(kp->dev, "Error writing KEYP_SCAN reg, rc=%d\n", rc); | 452 | dev_err(kp->dev, "Error writing KEYP_SCAN reg, rc=%d\n", rc); |
445 | 453 | ||
@@ -447,34 +455,13 @@ static int pmic8xxx_kpd_init(struct pmic8xxx_kp *kp) | |||
447 | 455 | ||
448 | } | 456 | } |
449 | 457 | ||
450 | static int pmic8xxx_kp_config_gpio(int gpio_start, int num_gpios, | ||
451 | struct pmic8xxx_kp *kp, struct pm_gpio *gpio_config) | ||
452 | { | ||
453 | int rc, i; | ||
454 | |||
455 | if (gpio_start < 0 || num_gpios < 0) | ||
456 | return -EINVAL; | ||
457 | |||
458 | for (i = 0; i < num_gpios; i++) { | ||
459 | rc = pm8xxx_gpio_config(gpio_start + i, gpio_config); | ||
460 | if (rc) { | ||
461 | dev_err(kp->dev, "%s: FAIL pm8xxx_gpio_config():" | ||
462 | "for PM GPIO [%d] rc=%d.\n", | ||
463 | __func__, gpio_start + i, rc); | ||
464 | return rc; | ||
465 | } | ||
466 | } | ||
467 | |||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | static int pmic8xxx_kp_enable(struct pmic8xxx_kp *kp) | 458 | static int pmic8xxx_kp_enable(struct pmic8xxx_kp *kp) |
472 | { | 459 | { |
473 | int rc; | 460 | int rc; |
474 | 461 | ||
475 | kp->ctrl_reg |= KEYP_CTRL_KEYP_EN; | 462 | kp->ctrl_reg |= KEYP_CTRL_KEYP_EN; |
476 | 463 | ||
477 | rc = pmic8xxx_kp_write_u8(kp, kp->ctrl_reg, KEYP_CTRL); | 464 | rc = regmap_write(kp->regmap, KEYP_CTRL, kp->ctrl_reg); |
478 | if (rc < 0) | 465 | if (rc < 0) |
479 | dev_err(kp->dev, "Error writing KEYP_CTRL reg, rc=%d\n", rc); | 466 | dev_err(kp->dev, "Error writing KEYP_CTRL reg, rc=%d\n", rc); |
480 | 467 | ||
@@ -487,7 +474,7 @@ static int pmic8xxx_kp_disable(struct pmic8xxx_kp *kp) | |||
487 | 474 | ||
488 | kp->ctrl_reg &= ~KEYP_CTRL_KEYP_EN; | 475 | kp->ctrl_reg &= ~KEYP_CTRL_KEYP_EN; |
489 | 476 | ||
490 | rc = pmic8xxx_kp_write_u8(kp, kp->ctrl_reg, KEYP_CTRL); | 477 | rc = regmap_write(kp->regmap, KEYP_CTRL, kp->ctrl_reg); |
491 | if (rc < 0) | 478 | if (rc < 0) |
492 | return rc; | 479 | return rc; |
493 | 480 | ||
@@ -520,106 +507,62 @@ static void pmic8xxx_kp_close(struct input_dev *dev) | |||
520 | */ | 507 | */ |
521 | static int pmic8xxx_kp_probe(struct platform_device *pdev) | 508 | static int pmic8xxx_kp_probe(struct platform_device *pdev) |
522 | { | 509 | { |
523 | const struct pm8xxx_keypad_platform_data *pdata = | 510 | unsigned int rows, cols; |
524 | dev_get_platdata(&pdev->dev); | 511 | bool repeat; |
525 | const struct matrix_keymap_data *keymap_data; | 512 | bool wakeup; |
526 | struct pmic8xxx_kp *kp; | 513 | struct pmic8xxx_kp *kp; |
527 | int rc; | 514 | int rc; |
528 | u8 ctrl_val; | 515 | unsigned int ctrl_val; |
529 | |||
530 | struct pm_gpio kypd_drv = { | ||
531 | .direction = PM_GPIO_DIR_OUT, | ||
532 | .output_buffer = PM_GPIO_OUT_BUF_OPEN_DRAIN, | ||
533 | .output_value = 0, | ||
534 | .pull = PM_GPIO_PULL_NO, | ||
535 | .vin_sel = PM_GPIO_VIN_S3, | ||
536 | .out_strength = PM_GPIO_STRENGTH_LOW, | ||
537 | .function = PM_GPIO_FUNC_1, | ||
538 | .inv_int_pol = 1, | ||
539 | }; | ||
540 | |||
541 | struct pm_gpio kypd_sns = { | ||
542 | .direction = PM_GPIO_DIR_IN, | ||
543 | .pull = PM_GPIO_PULL_UP_31P5, | ||
544 | .vin_sel = PM_GPIO_VIN_S3, | ||
545 | .out_strength = PM_GPIO_STRENGTH_NO, | ||
546 | .function = PM_GPIO_FUNC_NORMAL, | ||
547 | .inv_int_pol = 1, | ||
548 | }; | ||
549 | 516 | ||
517 | rc = matrix_keypad_parse_of_params(&pdev->dev, &rows, &cols); | ||
518 | if (rc) | ||
519 | return rc; | ||
550 | 520 | ||
551 | if (!pdata || !pdata->num_cols || !pdata->num_rows || | 521 | if (cols > PM8XXX_MAX_COLS || rows > PM8XXX_MAX_ROWS || |
552 | pdata->num_cols > PM8XXX_MAX_COLS || | 522 | cols < PM8XXX_MIN_COLS) { |
553 | pdata->num_rows > PM8XXX_MAX_ROWS || | ||
554 | pdata->num_cols < PM8XXX_MIN_COLS) { | ||
555 | dev_err(&pdev->dev, "invalid platform data\n"); | 523 | dev_err(&pdev->dev, "invalid platform data\n"); |
556 | return -EINVAL; | 524 | return -EINVAL; |
557 | } | 525 | } |
558 | 526 | ||
559 | if (!pdata->scan_delay_ms || | 527 | repeat = !of_property_read_bool(pdev->dev.of_node, |
560 | pdata->scan_delay_ms > MAX_SCAN_DELAY || | 528 | "linux,input-no-autorepeat"); |
561 | pdata->scan_delay_ms < MIN_SCAN_DELAY || | 529 | wakeup = of_property_read_bool(pdev->dev.of_node, |
562 | !is_power_of_2(pdata->scan_delay_ms)) { | 530 | "linux,keypad-wakeup"); |
563 | dev_err(&pdev->dev, "invalid keypad scan time supplied\n"); | ||
564 | return -EINVAL; | ||
565 | } | ||
566 | |||
567 | if (!pdata->row_hold_ns || | ||
568 | pdata->row_hold_ns > MAX_ROW_HOLD_DELAY || | ||
569 | pdata->row_hold_ns < MIN_ROW_HOLD_DELAY || | ||
570 | ((pdata->row_hold_ns % MIN_ROW_HOLD_DELAY) != 0)) { | ||
571 | dev_err(&pdev->dev, "invalid keypad row hold time supplied\n"); | ||
572 | return -EINVAL; | ||
573 | } | ||
574 | |||
575 | if (!pdata->debounce_ms || | ||
576 | ((pdata->debounce_ms % 5) != 0) || | ||
577 | pdata->debounce_ms > MAX_DEBOUNCE_TIME || | ||
578 | pdata->debounce_ms < MIN_DEBOUNCE_TIME) { | ||
579 | dev_err(&pdev->dev, "invalid debounce time supplied\n"); | ||
580 | return -EINVAL; | ||
581 | } | ||
582 | |||
583 | keymap_data = pdata->keymap_data; | ||
584 | if (!keymap_data) { | ||
585 | dev_err(&pdev->dev, "no keymap data supplied\n"); | ||
586 | return -EINVAL; | ||
587 | } | ||
588 | 531 | ||
589 | kp = kzalloc(sizeof(*kp), GFP_KERNEL); | 532 | kp = devm_kzalloc(&pdev->dev, sizeof(*kp), GFP_KERNEL); |
590 | if (!kp) | 533 | if (!kp) |
591 | return -ENOMEM; | 534 | return -ENOMEM; |
592 | 535 | ||
536 | kp->regmap = dev_get_regmap(pdev->dev.parent, NULL); | ||
537 | if (!kp->regmap) | ||
538 | return -ENODEV; | ||
539 | |||
593 | platform_set_drvdata(pdev, kp); | 540 | platform_set_drvdata(pdev, kp); |
594 | 541 | ||
595 | kp->pdata = pdata; | 542 | kp->num_rows = rows; |
543 | kp->num_cols = cols; | ||
596 | kp->dev = &pdev->dev; | 544 | kp->dev = &pdev->dev; |
597 | 545 | ||
598 | kp->input = input_allocate_device(); | 546 | kp->input = devm_input_allocate_device(&pdev->dev); |
599 | if (!kp->input) { | 547 | if (!kp->input) { |
600 | dev_err(&pdev->dev, "unable to allocate input device\n"); | 548 | dev_err(&pdev->dev, "unable to allocate input device\n"); |
601 | rc = -ENOMEM; | 549 | return -ENOMEM; |
602 | goto err_alloc_device; | ||
603 | } | 550 | } |
604 | 551 | ||
605 | kp->key_sense_irq = platform_get_irq(pdev, 0); | 552 | kp->key_sense_irq = platform_get_irq(pdev, 0); |
606 | if (kp->key_sense_irq < 0) { | 553 | if (kp->key_sense_irq < 0) { |
607 | dev_err(&pdev->dev, "unable to get keypad sense irq\n"); | 554 | dev_err(&pdev->dev, "unable to get keypad sense irq\n"); |
608 | rc = -ENXIO; | 555 | return kp->key_sense_irq; |
609 | goto err_get_irq; | ||
610 | } | 556 | } |
611 | 557 | ||
612 | kp->key_stuck_irq = platform_get_irq(pdev, 1); | 558 | kp->key_stuck_irq = platform_get_irq(pdev, 1); |
613 | if (kp->key_stuck_irq < 0) { | 559 | if (kp->key_stuck_irq < 0) { |
614 | dev_err(&pdev->dev, "unable to get keypad stuck irq\n"); | 560 | dev_err(&pdev->dev, "unable to get keypad stuck irq\n"); |
615 | rc = -ENXIO; | 561 | return kp->key_stuck_irq; |
616 | goto err_get_irq; | ||
617 | } | 562 | } |
618 | 563 | ||
619 | kp->input->name = pdata->input_name ? : "PMIC8XXX keypad"; | 564 | kp->input->name = "PMIC8XXX keypad"; |
620 | kp->input->phys = pdata->input_phys_device ? : "pmic8xxx_keypad/input0"; | 565 | kp->input->phys = "pmic8xxx_keypad/input0"; |
621 | |||
622 | kp->input->dev.parent = &pdev->dev; | ||
623 | 566 | ||
624 | kp->input->id.bustype = BUS_I2C; | 567 | kp->input->id.bustype = BUS_I2C; |
625 | kp->input->id.version = 0x0001; | 568 | kp->input->id.version = 0x0001; |
@@ -629,15 +572,15 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev) | |||
629 | kp->input->open = pmic8xxx_kp_open; | 572 | kp->input->open = pmic8xxx_kp_open; |
630 | kp->input->close = pmic8xxx_kp_close; | 573 | kp->input->close = pmic8xxx_kp_close; |
631 | 574 | ||
632 | rc = matrix_keypad_build_keymap(keymap_data, NULL, | 575 | rc = matrix_keypad_build_keymap(NULL, NULL, |
633 | PM8XXX_MAX_ROWS, PM8XXX_MAX_COLS, | 576 | PM8XXX_MAX_ROWS, PM8XXX_MAX_COLS, |
634 | kp->keycodes, kp->input); | 577 | kp->keycodes, kp->input); |
635 | if (rc) { | 578 | if (rc) { |
636 | dev_err(&pdev->dev, "failed to build keymap\n"); | 579 | dev_err(&pdev->dev, "failed to build keymap\n"); |
637 | goto err_get_irq; | 580 | return rc; |
638 | } | 581 | } |
639 | 582 | ||
640 | if (pdata->rep) | 583 | if (repeat) |
641 | __set_bit(EV_REP, kp->input->evbit); | 584 | __set_bit(EV_REP, kp->input->evbit); |
642 | input_set_capability(kp->input, EV_MSC, MSC_SCAN); | 585 | input_set_capability(kp->input, EV_MSC, MSC_SCAN); |
643 | 586 | ||
@@ -647,44 +590,32 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev) | |||
647 | memset(kp->keystate, 0xff, sizeof(kp->keystate)); | 590 | memset(kp->keystate, 0xff, sizeof(kp->keystate)); |
648 | memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate)); | 591 | memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate)); |
649 | 592 | ||
650 | rc = pmic8xxx_kpd_init(kp); | 593 | rc = pmic8xxx_kpd_init(kp, pdev); |
651 | if (rc < 0) { | 594 | if (rc < 0) { |
652 | dev_err(&pdev->dev, "unable to initialize keypad controller\n"); | 595 | dev_err(&pdev->dev, "unable to initialize keypad controller\n"); |
653 | goto err_get_irq; | 596 | return rc; |
654 | } | ||
655 | |||
656 | rc = pmic8xxx_kp_config_gpio(pdata->cols_gpio_start, | ||
657 | pdata->num_cols, kp, &kypd_sns); | ||
658 | if (rc < 0) { | ||
659 | dev_err(&pdev->dev, "unable to configure keypad sense lines\n"); | ||
660 | goto err_gpio_config; | ||
661 | } | ||
662 | |||
663 | rc = pmic8xxx_kp_config_gpio(pdata->rows_gpio_start, | ||
664 | pdata->num_rows, kp, &kypd_drv); | ||
665 | if (rc < 0) { | ||
666 | dev_err(&pdev->dev, "unable to configure keypad drive lines\n"); | ||
667 | goto err_gpio_config; | ||
668 | } | 597 | } |
669 | 598 | ||
670 | rc = request_any_context_irq(kp->key_sense_irq, pmic8xxx_kp_irq, | 599 | rc = devm_request_any_context_irq(&pdev->dev, kp->key_sense_irq, |
671 | IRQF_TRIGGER_RISING, "pmic-keypad", kp); | 600 | pmic8xxx_kp_irq, IRQF_TRIGGER_RISING, "pmic-keypad", |
601 | kp); | ||
672 | if (rc < 0) { | 602 | if (rc < 0) { |
673 | dev_err(&pdev->dev, "failed to request keypad sense irq\n"); | 603 | dev_err(&pdev->dev, "failed to request keypad sense irq\n"); |
674 | goto err_get_irq; | 604 | return rc; |
675 | } | 605 | } |
676 | 606 | ||
677 | rc = request_any_context_irq(kp->key_stuck_irq, pmic8xxx_kp_stuck_irq, | 607 | rc = devm_request_any_context_irq(&pdev->dev, kp->key_stuck_irq, |
678 | IRQF_TRIGGER_RISING, "pmic-keypad-stuck", kp); | 608 | pmic8xxx_kp_stuck_irq, IRQF_TRIGGER_RISING, |
609 | "pmic-keypad-stuck", kp); | ||
679 | if (rc < 0) { | 610 | if (rc < 0) { |
680 | dev_err(&pdev->dev, "failed to request keypad stuck irq\n"); | 611 | dev_err(&pdev->dev, "failed to request keypad stuck irq\n"); |
681 | goto err_req_stuck_irq; | 612 | return rc; |
682 | } | 613 | } |
683 | 614 | ||
684 | rc = pmic8xxx_kp_read_u8(kp, &ctrl_val, KEYP_CTRL); | 615 | rc = regmap_read(kp->regmap, KEYP_CTRL, &ctrl_val); |
685 | if (rc < 0) { | 616 | if (rc < 0) { |
686 | dev_err(&pdev->dev, "failed to read KEYP_CTRL register\n"); | 617 | dev_err(&pdev->dev, "failed to read KEYP_CTRL register\n"); |
687 | goto err_pmic_reg_read; | 618 | return rc; |
688 | } | 619 | } |
689 | 620 | ||
690 | kp->ctrl_reg = ctrl_val; | 621 | kp->ctrl_reg = ctrl_val; |
@@ -692,34 +623,10 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev) | |||
692 | rc = input_register_device(kp->input); | 623 | rc = input_register_device(kp->input); |
693 | if (rc < 0) { | 624 | if (rc < 0) { |
694 | dev_err(&pdev->dev, "unable to register keypad input device\n"); | 625 | dev_err(&pdev->dev, "unable to register keypad input device\n"); |
695 | goto err_pmic_reg_read; | 626 | return rc; |
696 | } | 627 | } |
697 | 628 | ||
698 | device_init_wakeup(&pdev->dev, pdata->wakeup); | 629 | device_init_wakeup(&pdev->dev, wakeup); |
699 | |||
700 | return 0; | ||
701 | |||
702 | err_pmic_reg_read: | ||
703 | free_irq(kp->key_stuck_irq, kp); | ||
704 | err_req_stuck_irq: | ||
705 | free_irq(kp->key_sense_irq, kp); | ||
706 | err_gpio_config: | ||
707 | err_get_irq: | ||
708 | input_free_device(kp->input); | ||
709 | err_alloc_device: | ||
710 | kfree(kp); | ||
711 | return rc; | ||
712 | } | ||
713 | |||
714 | static int pmic8xxx_kp_remove(struct platform_device *pdev) | ||
715 | { | ||
716 | struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); | ||
717 | |||
718 | device_init_wakeup(&pdev->dev, 0); | ||
719 | free_irq(kp->key_stuck_irq, kp); | ||
720 | free_irq(kp->key_sense_irq, kp); | ||
721 | input_unregister_device(kp->input); | ||
722 | kfree(kp); | ||
723 | 630 | ||
724 | return 0; | 631 | return 0; |
725 | } | 632 | } |
@@ -769,13 +676,20 @@ static int pmic8xxx_kp_resume(struct device *dev) | |||
769 | static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops, | 676 | static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops, |
770 | pmic8xxx_kp_suspend, pmic8xxx_kp_resume); | 677 | pmic8xxx_kp_suspend, pmic8xxx_kp_resume); |
771 | 678 | ||
679 | static const struct of_device_id pm8xxx_match_table[] = { | ||
680 | { .compatible = "qcom,pm8058-keypad" }, | ||
681 | { .compatible = "qcom,pm8921-keypad" }, | ||
682 | { } | ||
683 | }; | ||
684 | MODULE_DEVICE_TABLE(of, pm8xxx_match_table); | ||
685 | |||
772 | static struct platform_driver pmic8xxx_kp_driver = { | 686 | static struct platform_driver pmic8xxx_kp_driver = { |
773 | .probe = pmic8xxx_kp_probe, | 687 | .probe = pmic8xxx_kp_probe, |
774 | .remove = pmic8xxx_kp_remove, | ||
775 | .driver = { | 688 | .driver = { |
776 | .name = PM8XXX_KEYPAD_DEV_NAME, | 689 | .name = "pm8xxx-keypad", |
777 | .owner = THIS_MODULE, | 690 | .owner = THIS_MODULE, |
778 | .pm = &pm8xxx_kp_pm_ops, | 691 | .pm = &pm8xxx_kp_pm_ops, |
692 | .of_match_table = pm8xxx_match_table, | ||
779 | }, | 693 | }, |
780 | }; | 694 | }; |
781 | module_platform_driver(pmic8xxx_kp_driver); | 695 | module_platform_driver(pmic8xxx_kp_driver); |
diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c deleted file mode 100644 index 086511c2121b..000000000000 --- a/drivers/input/keyboard/tnetv107x-keypad.c +++ /dev/null | |||
@@ -1,329 +0,0 @@ | |||
1 | /* | ||
2 | * Texas Instruments TNETV107X Keypad Driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Texas Instruments | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation version 2. | ||
9 | * | ||
10 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
11 | * kind, whether express or implied; without even the implied warranty | ||
12 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/input.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/io.h> | ||
25 | #include <linux/clk.h> | ||
26 | #include <linux/input/matrix_keypad.h> | ||
27 | #include <linux/module.h> | ||
28 | |||
29 | #define BITS(x) (BIT(x) - 1) | ||
30 | |||
31 | #define KEYPAD_ROWS 9 | ||
32 | #define KEYPAD_COLS 9 | ||
33 | |||
34 | #define DEBOUNCE_MIN 0x400ul | ||
35 | #define DEBOUNCE_MAX 0x3ffffffful | ||
36 | |||
37 | struct keypad_regs { | ||
38 | u32 rev; | ||
39 | u32 mode; | ||
40 | u32 mask; | ||
41 | u32 pol; | ||
42 | u32 dclock; | ||
43 | u32 rclock; | ||
44 | u32 stable_cnt; | ||
45 | u32 in_en; | ||
46 | u32 out; | ||
47 | u32 out_en; | ||
48 | u32 in; | ||
49 | u32 lock; | ||
50 | u32 pres[3]; | ||
51 | }; | ||
52 | |||
53 | #define keypad_read(kp, reg) __raw_readl(&(kp)->regs->reg) | ||
54 | #define keypad_write(kp, reg, val) __raw_writel(val, &(kp)->regs->reg) | ||
55 | |||
56 | struct keypad_data { | ||
57 | struct input_dev *input_dev; | ||
58 | struct resource *res; | ||
59 | struct keypad_regs __iomem *regs; | ||
60 | struct clk *clk; | ||
61 | struct device *dev; | ||
62 | spinlock_t lock; | ||
63 | int irq_press; | ||
64 | int irq_release; | ||
65 | int rows, cols, row_shift; | ||
66 | int debounce_ms, active_low; | ||
67 | u32 prev_keys[3]; | ||
68 | unsigned short keycodes[]; | ||
69 | }; | ||
70 | |||
71 | static irqreturn_t keypad_irq(int irq, void *data) | ||
72 | { | ||
73 | struct keypad_data *kp = data; | ||
74 | int i, bit, val, row, col, code; | ||
75 | unsigned long flags; | ||
76 | u32 curr_keys[3]; | ||
77 | u32 change; | ||
78 | |||
79 | spin_lock_irqsave(&kp->lock, flags); | ||
80 | |||
81 | memset(curr_keys, 0, sizeof(curr_keys)); | ||
82 | if (irq == kp->irq_press) | ||
83 | for (i = 0; i < 3; i++) | ||
84 | curr_keys[i] = keypad_read(kp, pres[i]); | ||
85 | |||
86 | for (i = 0; i < 3; i++) { | ||
87 | change = curr_keys[i] ^ kp->prev_keys[i]; | ||
88 | |||
89 | while (change) { | ||
90 | bit = fls(change) - 1; | ||
91 | change ^= BIT(bit); | ||
92 | val = curr_keys[i] & BIT(bit); | ||
93 | bit += i * 32; | ||
94 | row = bit / KEYPAD_COLS; | ||
95 | col = bit % KEYPAD_COLS; | ||
96 | |||
97 | code = MATRIX_SCAN_CODE(row, col, kp->row_shift); | ||
98 | input_event(kp->input_dev, EV_MSC, MSC_SCAN, code); | ||
99 | input_report_key(kp->input_dev, kp->keycodes[code], | ||
100 | val); | ||
101 | } | ||
102 | } | ||
103 | input_sync(kp->input_dev); | ||
104 | memcpy(kp->prev_keys, curr_keys, sizeof(curr_keys)); | ||
105 | |||
106 | if (irq == kp->irq_press) | ||
107 | keypad_write(kp, lock, 0); /* Allow hardware updates */ | ||
108 | |||
109 | spin_unlock_irqrestore(&kp->lock, flags); | ||
110 | |||
111 | return IRQ_HANDLED; | ||
112 | } | ||
113 | |||
114 | static int keypad_start(struct input_dev *dev) | ||
115 | { | ||
116 | struct keypad_data *kp = input_get_drvdata(dev); | ||
117 | unsigned long mask, debounce, clk_rate_khz; | ||
118 | unsigned long flags; | ||
119 | |||
120 | clk_enable(kp->clk); | ||
121 | clk_rate_khz = clk_get_rate(kp->clk) / 1000; | ||
122 | |||
123 | spin_lock_irqsave(&kp->lock, flags); | ||
124 | |||
125 | /* Initialize device registers */ | ||
126 | keypad_write(kp, mode, 0); | ||
127 | |||
128 | mask = BITS(kp->rows) << KEYPAD_COLS; | ||
129 | mask |= BITS(kp->cols); | ||
130 | keypad_write(kp, mask, ~mask); | ||
131 | |||
132 | keypad_write(kp, pol, kp->active_low ? 0 : 0x3ffff); | ||
133 | keypad_write(kp, stable_cnt, 3); | ||
134 | |||
135 | debounce = kp->debounce_ms * clk_rate_khz; | ||
136 | debounce = clamp(debounce, DEBOUNCE_MIN, DEBOUNCE_MAX); | ||
137 | keypad_write(kp, dclock, debounce); | ||
138 | keypad_write(kp, rclock, 4 * debounce); | ||
139 | |||
140 | keypad_write(kp, in_en, 1); | ||
141 | |||
142 | spin_unlock_irqrestore(&kp->lock, flags); | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static void keypad_stop(struct input_dev *dev) | ||
148 | { | ||
149 | struct keypad_data *kp = input_get_drvdata(dev); | ||
150 | |||
151 | synchronize_irq(kp->irq_press); | ||
152 | synchronize_irq(kp->irq_release); | ||
153 | clk_disable(kp->clk); | ||
154 | } | ||
155 | |||
156 | static int keypad_probe(struct platform_device *pdev) | ||
157 | { | ||
158 | const struct matrix_keypad_platform_data *pdata; | ||
159 | const struct matrix_keymap_data *keymap_data; | ||
160 | struct device *dev = &pdev->dev; | ||
161 | struct keypad_data *kp; | ||
162 | int error = 0, sz, row_shift; | ||
163 | u32 rev = 0; | ||
164 | |||
165 | pdata = dev_get_platdata(&pdev->dev); | ||
166 | if (!pdata) { | ||
167 | dev_err(dev, "cannot find device data\n"); | ||
168 | return -EINVAL; | ||
169 | } | ||
170 | |||
171 | keymap_data = pdata->keymap_data; | ||
172 | if (!keymap_data) { | ||
173 | dev_err(dev, "cannot find keymap data\n"); | ||
174 | return -EINVAL; | ||
175 | } | ||
176 | |||
177 | row_shift = get_count_order(pdata->num_col_gpios); | ||
178 | sz = offsetof(struct keypad_data, keycodes); | ||
179 | sz += (pdata->num_row_gpios << row_shift) * sizeof(kp->keycodes[0]); | ||
180 | kp = kzalloc(sz, GFP_KERNEL); | ||
181 | if (!kp) { | ||
182 | dev_err(dev, "cannot allocate device info\n"); | ||
183 | return -ENOMEM; | ||
184 | } | ||
185 | |||
186 | kp->dev = dev; | ||
187 | kp->rows = pdata->num_row_gpios; | ||
188 | kp->cols = pdata->num_col_gpios; | ||
189 | kp->row_shift = row_shift; | ||
190 | platform_set_drvdata(pdev, kp); | ||
191 | spin_lock_init(&kp->lock); | ||
192 | |||
193 | kp->irq_press = platform_get_irq_byname(pdev, "press"); | ||
194 | kp->irq_release = platform_get_irq_byname(pdev, "release"); | ||
195 | if (kp->irq_press < 0 || kp->irq_release < 0) { | ||
196 | dev_err(dev, "cannot determine device interrupts\n"); | ||
197 | error = -ENODEV; | ||
198 | goto error_res; | ||
199 | } | ||
200 | |||
201 | kp->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
202 | if (!kp->res) { | ||
203 | dev_err(dev, "cannot determine register area\n"); | ||
204 | error = -ENODEV; | ||
205 | goto error_res; | ||
206 | } | ||
207 | |||
208 | if (!request_mem_region(kp->res->start, resource_size(kp->res), | ||
209 | pdev->name)) { | ||
210 | dev_err(dev, "cannot claim register memory\n"); | ||
211 | kp->res = NULL; | ||
212 | error = -EINVAL; | ||
213 | goto error_res; | ||
214 | } | ||
215 | |||
216 | kp->regs = ioremap(kp->res->start, resource_size(kp->res)); | ||
217 | if (!kp->regs) { | ||
218 | dev_err(dev, "cannot map register memory\n"); | ||
219 | error = -ENOMEM; | ||
220 | goto error_map; | ||
221 | } | ||
222 | |||
223 | kp->clk = clk_get(dev, NULL); | ||
224 | if (IS_ERR(kp->clk)) { | ||
225 | dev_err(dev, "cannot claim device clock\n"); | ||
226 | error = PTR_ERR(kp->clk); | ||
227 | goto error_clk; | ||
228 | } | ||
229 | |||
230 | error = request_threaded_irq(kp->irq_press, NULL, keypad_irq, | ||
231 | IRQF_ONESHOT, dev_name(dev), kp); | ||
232 | if (error < 0) { | ||
233 | dev_err(kp->dev, "Could not allocate keypad press key irq\n"); | ||
234 | goto error_irq_press; | ||
235 | } | ||
236 | |||
237 | error = request_threaded_irq(kp->irq_release, NULL, keypad_irq, | ||
238 | IRQF_ONESHOT, dev_name(dev), kp); | ||
239 | if (error < 0) { | ||
240 | dev_err(kp->dev, "Could not allocate keypad release key irq\n"); | ||
241 | goto error_irq_release; | ||
242 | } | ||
243 | |||
244 | kp->input_dev = input_allocate_device(); | ||
245 | if (!kp->input_dev) { | ||
246 | dev_err(dev, "cannot allocate input device\n"); | ||
247 | error = -ENOMEM; | ||
248 | goto error_input; | ||
249 | } | ||
250 | |||
251 | kp->input_dev->name = pdev->name; | ||
252 | kp->input_dev->dev.parent = &pdev->dev; | ||
253 | kp->input_dev->open = keypad_start; | ||
254 | kp->input_dev->close = keypad_stop; | ||
255 | |||
256 | clk_enable(kp->clk); | ||
257 | rev = keypad_read(kp, rev); | ||
258 | kp->input_dev->id.bustype = BUS_HOST; | ||
259 | kp->input_dev->id.product = ((rev >> 8) & 0x07); | ||
260 | kp->input_dev->id.version = ((rev >> 16) & 0xfff); | ||
261 | clk_disable(kp->clk); | ||
262 | |||
263 | error = matrix_keypad_build_keymap(keymap_data, NULL, | ||
264 | kp->rows, kp->cols, | ||
265 | kp->keycodes, kp->input_dev); | ||
266 | if (error) { | ||
267 | dev_err(dev, "Failed to build keymap\n"); | ||
268 | goto error_reg; | ||
269 | } | ||
270 | |||
271 | if (!pdata->no_autorepeat) | ||
272 | kp->input_dev->evbit[0] |= BIT_MASK(EV_REP); | ||
273 | input_set_capability(kp->input_dev, EV_MSC, MSC_SCAN); | ||
274 | |||
275 | input_set_drvdata(kp->input_dev, kp); | ||
276 | |||
277 | error = input_register_device(kp->input_dev); | ||
278 | if (error < 0) { | ||
279 | dev_err(dev, "Could not register input device\n"); | ||
280 | goto error_reg; | ||
281 | } | ||
282 | |||
283 | return 0; | ||
284 | |||
285 | |||
286 | error_reg: | ||
287 | input_free_device(kp->input_dev); | ||
288 | error_input: | ||
289 | free_irq(kp->irq_release, kp); | ||
290 | error_irq_release: | ||
291 | free_irq(kp->irq_press, kp); | ||
292 | error_irq_press: | ||
293 | clk_put(kp->clk); | ||
294 | error_clk: | ||
295 | iounmap(kp->regs); | ||
296 | error_map: | ||
297 | release_mem_region(kp->res->start, resource_size(kp->res)); | ||
298 | error_res: | ||
299 | kfree(kp); | ||
300 | return error; | ||
301 | } | ||
302 | |||
303 | static int keypad_remove(struct platform_device *pdev) | ||
304 | { | ||
305 | struct keypad_data *kp = platform_get_drvdata(pdev); | ||
306 | |||
307 | free_irq(kp->irq_press, kp); | ||
308 | free_irq(kp->irq_release, kp); | ||
309 | input_unregister_device(kp->input_dev); | ||
310 | clk_put(kp->clk); | ||
311 | iounmap(kp->regs); | ||
312 | release_mem_region(kp->res->start, resource_size(kp->res)); | ||
313 | kfree(kp); | ||
314 | |||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | static struct platform_driver keypad_driver = { | ||
319 | .probe = keypad_probe, | ||
320 | .remove = keypad_remove, | ||
321 | .driver.name = "tnetv107x-keypad", | ||
322 | .driver.owner = THIS_MODULE, | ||
323 | }; | ||
324 | module_platform_driver(keypad_driver); | ||
325 | |||
326 | MODULE_AUTHOR("Cyril Chemparathy"); | ||
327 | MODULE_DESCRIPTION("TNETV107X Keypad Driver"); | ||
328 | MODULE_ALIAS("platform:tnetv107x-keypad"); | ||
329 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 7904ab05527a..f772981bdcdb 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -269,7 +269,7 @@ config INPUT_COBALT_BTNS | |||
269 | 269 | ||
270 | config INPUT_WISTRON_BTNS | 270 | config INPUT_WISTRON_BTNS |
271 | tristate "x86 Wistron laptop button interface" | 271 | tristate "x86 Wistron laptop button interface" |
272 | depends on X86 && !X86_64 | 272 | depends on X86_32 |
273 | select INPUT_POLLDEV | 273 | select INPUT_POLLDEV |
274 | select INPUT_SPARSEKMAP | 274 | select INPUT_SPARSEKMAP |
275 | select NEW_LEDS | 275 | select NEW_LEDS |
@@ -666,4 +666,14 @@ config INPUT_IDEAPAD_SLIDEBAR | |||
666 | To compile this driver as a module, choose M here: the | 666 | To compile this driver as a module, choose M here: the |
667 | module will be called ideapad_slidebar. | 667 | module will be called ideapad_slidebar. |
668 | 668 | ||
669 | config INPUT_SOC_BUTTON_ARRAY | ||
670 | tristate "Windows-compatible SoC Button Array" | ||
671 | depends on KEYBOARD_GPIO | ||
672 | help | ||
673 | Say Y here if you have a SoC-based tablet that originally | ||
674 | runs Windows 8. | ||
675 | |||
676 | To compile this driver as a module, choose M here: the | ||
677 | module will be called soc_button_array. | ||
678 | |||
669 | endif | 679 | endif |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index cda71fc52fb3..4955ad322a01 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -53,6 +53,7 @@ obj-$(CONFIG_INPUT_RETU_PWRBUTTON) += retu-pwrbutton.o | |||
53 | obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o | 53 | obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o |
54 | obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o | 54 | obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o |
55 | obj-$(CONFIG_INPUT_SIRFSOC_ONKEY) += sirfsoc-onkey.o | 55 | obj-$(CONFIG_INPUT_SIRFSOC_ONKEY) += sirfsoc-onkey.o |
56 | obj-$(CONFIG_INPUT_SOC_BUTTON_ARRAY) += soc_button_array.o | ||
56 | obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o | 57 | obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o |
57 | obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o | 58 | obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o |
58 | obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o | 59 | obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o |
diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c index e204f26b0011..5a736397d9c8 100644 --- a/drivers/input/misc/ims-pcu.c +++ b/drivers/input/misc/ims-pcu.c | |||
@@ -51,6 +51,8 @@ struct ims_pcu_backlight { | |||
51 | #define IMS_PCU_BL_VERSION_LEN (9 + 1) | 51 | #define IMS_PCU_BL_VERSION_LEN (9 + 1) |
52 | #define IMS_PCU_BL_RESET_REASON_LEN (2 + 1) | 52 | #define IMS_PCU_BL_RESET_REASON_LEN (2 + 1) |
53 | 53 | ||
54 | #define IMS_PCU_PCU_B_DEVICE_ID 5 | ||
55 | |||
54 | #define IMS_PCU_BUF_SIZE 128 | 56 | #define IMS_PCU_BUF_SIZE 128 |
55 | 57 | ||
56 | struct ims_pcu { | 58 | struct ims_pcu { |
@@ -68,6 +70,9 @@ struct ims_pcu { | |||
68 | char bl_version[IMS_PCU_BL_VERSION_LEN]; | 70 | char bl_version[IMS_PCU_BL_VERSION_LEN]; |
69 | char reset_reason[IMS_PCU_BL_RESET_REASON_LEN]; | 71 | char reset_reason[IMS_PCU_BL_RESET_REASON_LEN]; |
70 | int update_firmware_status; | 72 | int update_firmware_status; |
73 | u8 device_id; | ||
74 | |||
75 | u8 ofn_reg_addr; | ||
71 | 76 | ||
72 | struct usb_interface *ctrl_intf; | 77 | struct usb_interface *ctrl_intf; |
73 | 78 | ||
@@ -371,6 +376,8 @@ static void ims_pcu_destroy_gamepad(struct ims_pcu *pcu) | |||
371 | #define IMS_PCU_CMD_GET_DEVICE_ID 0xae | 376 | #define IMS_PCU_CMD_GET_DEVICE_ID 0xae |
372 | #define IMS_PCU_CMD_SPECIAL_INFO 0xb0 | 377 | #define IMS_PCU_CMD_SPECIAL_INFO 0xb0 |
373 | #define IMS_PCU_CMD_BOOTLOADER 0xb1 /* Pass data to bootloader */ | 378 | #define IMS_PCU_CMD_BOOTLOADER 0xb1 /* Pass data to bootloader */ |
379 | #define IMS_PCU_CMD_OFN_SET_CONFIG 0xb3 | ||
380 | #define IMS_PCU_CMD_OFN_GET_CONFIG 0xb4 | ||
374 | 381 | ||
375 | /* PCU responses */ | 382 | /* PCU responses */ |
376 | #define IMS_PCU_RSP_STATUS 0xc0 | 383 | #define IMS_PCU_RSP_STATUS 0xc0 |
@@ -389,6 +396,9 @@ static void ims_pcu_destroy_gamepad(struct ims_pcu *pcu) | |||
389 | #define IMS_PCU_RSP_GET_DEVICE_ID 0xce | 396 | #define IMS_PCU_RSP_GET_DEVICE_ID 0xce |
390 | #define IMS_PCU_RSP_SPECIAL_INFO 0xd0 | 397 | #define IMS_PCU_RSP_SPECIAL_INFO 0xd0 |
391 | #define IMS_PCU_RSP_BOOTLOADER 0xd1 /* Bootloader response */ | 398 | #define IMS_PCU_RSP_BOOTLOADER 0xd1 /* Bootloader response */ |
399 | #define IMS_PCU_RSP_OFN_SET_CONFIG 0xd2 | ||
400 | #define IMS_PCU_RSP_OFN_GET_CONFIG 0xd3 | ||
401 | |||
392 | 402 | ||
393 | #define IMS_PCU_RSP_EVNT_BUTTONS 0xe0 /* Unsolicited, button state */ | 403 | #define IMS_PCU_RSP_EVNT_BUTTONS 0xe0 /* Unsolicited, button state */ |
394 | #define IMS_PCU_GAMEPAD_MASK 0x0001ff80UL /* Bits 7 through 16 */ | 404 | #define IMS_PCU_GAMEPAD_MASK 0x0001ff80UL /* Bits 7 through 16 */ |
@@ -1256,6 +1266,225 @@ static struct attribute_group ims_pcu_attr_group = { | |||
1256 | .attrs = ims_pcu_attrs, | 1266 | .attrs = ims_pcu_attrs, |
1257 | }; | 1267 | }; |
1258 | 1268 | ||
1269 | /* Support for a separate OFN attribute group */ | ||
1270 | |||
1271 | #define OFN_REG_RESULT_OFFSET 2 | ||
1272 | |||
1273 | static int ims_pcu_read_ofn_config(struct ims_pcu *pcu, u8 addr, u8 *data) | ||
1274 | { | ||
1275 | int error; | ||
1276 | s16 result; | ||
1277 | |||
1278 | error = ims_pcu_execute_command(pcu, OFN_GET_CONFIG, | ||
1279 | &addr, sizeof(addr)); | ||
1280 | if (error) | ||
1281 | return error; | ||
1282 | |||
1283 | result = (s16)get_unaligned_le16(pcu->cmd_buf + OFN_REG_RESULT_OFFSET); | ||
1284 | if (result < 0) | ||
1285 | return -EIO; | ||
1286 | |||
1287 | /* We only need LSB */ | ||
1288 | *data = pcu->cmd_buf[OFN_REG_RESULT_OFFSET]; | ||
1289 | return 0; | ||
1290 | } | ||
1291 | |||
1292 | static int ims_pcu_write_ofn_config(struct ims_pcu *pcu, u8 addr, u8 data) | ||
1293 | { | ||
1294 | u8 buffer[] = { addr, data }; | ||
1295 | int error; | ||
1296 | s16 result; | ||
1297 | |||
1298 | error = ims_pcu_execute_command(pcu, OFN_SET_CONFIG, | ||
1299 | &buffer, sizeof(buffer)); | ||
1300 | if (error) | ||
1301 | return error; | ||
1302 | |||
1303 | result = (s16)get_unaligned_le16(pcu->cmd_buf + OFN_REG_RESULT_OFFSET); | ||
1304 | if (result < 0) | ||
1305 | return -EIO; | ||
1306 | |||
1307 | return 0; | ||
1308 | } | ||
1309 | |||
1310 | static ssize_t ims_pcu_ofn_reg_data_show(struct device *dev, | ||
1311 | struct device_attribute *dattr, | ||
1312 | char *buf) | ||
1313 | { | ||
1314 | struct usb_interface *intf = to_usb_interface(dev); | ||
1315 | struct ims_pcu *pcu = usb_get_intfdata(intf); | ||
1316 | int error; | ||
1317 | u8 data; | ||
1318 | |||
1319 | mutex_lock(&pcu->cmd_mutex); | ||
1320 | error = ims_pcu_read_ofn_config(pcu, pcu->ofn_reg_addr, &data); | ||
1321 | mutex_unlock(&pcu->cmd_mutex); | ||
1322 | |||
1323 | if (error) | ||
1324 | return error; | ||
1325 | |||
1326 | return scnprintf(buf, PAGE_SIZE, "%x\n", data); | ||
1327 | } | ||
1328 | |||
1329 | static ssize_t ims_pcu_ofn_reg_data_store(struct device *dev, | ||
1330 | struct device_attribute *dattr, | ||
1331 | const char *buf, size_t count) | ||
1332 | { | ||
1333 | struct usb_interface *intf = to_usb_interface(dev); | ||
1334 | struct ims_pcu *pcu = usb_get_intfdata(intf); | ||
1335 | int error; | ||
1336 | u8 value; | ||
1337 | |||
1338 | error = kstrtou8(buf, 0, &value); | ||
1339 | if (error) | ||
1340 | return error; | ||
1341 | |||
1342 | mutex_lock(&pcu->cmd_mutex); | ||
1343 | error = ims_pcu_write_ofn_config(pcu, pcu->ofn_reg_addr, value); | ||
1344 | mutex_unlock(&pcu->cmd_mutex); | ||
1345 | |||
1346 | return error ?: count; | ||
1347 | } | ||
1348 | |||
1349 | static DEVICE_ATTR(reg_data, S_IRUGO | S_IWUSR, | ||
1350 | ims_pcu_ofn_reg_data_show, ims_pcu_ofn_reg_data_store); | ||
1351 | |||
1352 | static ssize_t ims_pcu_ofn_reg_addr_show(struct device *dev, | ||
1353 | struct device_attribute *dattr, | ||
1354 | char *buf) | ||
1355 | { | ||
1356 | struct usb_interface *intf = to_usb_interface(dev); | ||
1357 | struct ims_pcu *pcu = usb_get_intfdata(intf); | ||
1358 | int error; | ||
1359 | |||
1360 | mutex_lock(&pcu->cmd_mutex); | ||
1361 | error = scnprintf(buf, PAGE_SIZE, "%x\n", pcu->ofn_reg_addr); | ||
1362 | mutex_unlock(&pcu->cmd_mutex); | ||
1363 | |||
1364 | return error; | ||
1365 | } | ||
1366 | |||
1367 | static ssize_t ims_pcu_ofn_reg_addr_store(struct device *dev, | ||
1368 | struct device_attribute *dattr, | ||
1369 | const char *buf, size_t count) | ||
1370 | { | ||
1371 | struct usb_interface *intf = to_usb_interface(dev); | ||
1372 | struct ims_pcu *pcu = usb_get_intfdata(intf); | ||
1373 | int error; | ||
1374 | u8 value; | ||
1375 | |||
1376 | error = kstrtou8(buf, 0, &value); | ||
1377 | if (error) | ||
1378 | return error; | ||
1379 | |||
1380 | mutex_lock(&pcu->cmd_mutex); | ||
1381 | pcu->ofn_reg_addr = value; | ||
1382 | mutex_unlock(&pcu->cmd_mutex); | ||
1383 | |||
1384 | return error ?: count; | ||
1385 | } | ||
1386 | |||
1387 | static DEVICE_ATTR(reg_addr, S_IRUGO | S_IWUSR, | ||
1388 | ims_pcu_ofn_reg_addr_show, ims_pcu_ofn_reg_addr_store); | ||
1389 | |||
1390 | struct ims_pcu_ofn_bit_attribute { | ||
1391 | struct device_attribute dattr; | ||
1392 | u8 addr; | ||
1393 | u8 nr; | ||
1394 | }; | ||
1395 | |||
1396 | static ssize_t ims_pcu_ofn_bit_show(struct device *dev, | ||
1397 | struct device_attribute *dattr, | ||
1398 | char *buf) | ||
1399 | { | ||
1400 | struct usb_interface *intf = to_usb_interface(dev); | ||
1401 | struct ims_pcu *pcu = usb_get_intfdata(intf); | ||
1402 | struct ims_pcu_ofn_bit_attribute *attr = | ||
1403 | container_of(dattr, struct ims_pcu_ofn_bit_attribute, dattr); | ||
1404 | int error; | ||
1405 | u8 data; | ||
1406 | |||
1407 | mutex_lock(&pcu->cmd_mutex); | ||
1408 | error = ims_pcu_read_ofn_config(pcu, attr->addr, &data); | ||
1409 | mutex_unlock(&pcu->cmd_mutex); | ||
1410 | |||
1411 | if (error) | ||
1412 | return error; | ||
1413 | |||
1414 | return scnprintf(buf, PAGE_SIZE, "%d\n", !!(data & (1 << attr->nr))); | ||
1415 | } | ||
1416 | |||
1417 | static ssize_t ims_pcu_ofn_bit_store(struct device *dev, | ||
1418 | struct device_attribute *dattr, | ||
1419 | const char *buf, size_t count) | ||
1420 | { | ||
1421 | struct usb_interface *intf = to_usb_interface(dev); | ||
1422 | struct ims_pcu *pcu = usb_get_intfdata(intf); | ||
1423 | struct ims_pcu_ofn_bit_attribute *attr = | ||
1424 | container_of(dattr, struct ims_pcu_ofn_bit_attribute, dattr); | ||
1425 | int error; | ||
1426 | int value; | ||
1427 | u8 data; | ||
1428 | |||
1429 | error = kstrtoint(buf, 0, &value); | ||
1430 | if (error) | ||
1431 | return error; | ||
1432 | |||
1433 | if (value > 1) | ||
1434 | return -EINVAL; | ||
1435 | |||
1436 | mutex_lock(&pcu->cmd_mutex); | ||
1437 | |||
1438 | error = ims_pcu_read_ofn_config(pcu, attr->addr, &data); | ||
1439 | if (!error) { | ||
1440 | if (value) | ||
1441 | data |= 1U << attr->nr; | ||
1442 | else | ||
1443 | data &= ~(1U << attr->nr); | ||
1444 | |||
1445 | error = ims_pcu_write_ofn_config(pcu, attr->addr, data); | ||
1446 | } | ||
1447 | |||
1448 | mutex_unlock(&pcu->cmd_mutex); | ||
1449 | |||
1450 | return error ?: count; | ||
1451 | } | ||
1452 | |||
1453 | #define IMS_PCU_OFN_BIT_ATTR(_field, _addr, _nr) \ | ||
1454 | struct ims_pcu_ofn_bit_attribute ims_pcu_ofn_attr_##_field = { \ | ||
1455 | .dattr = __ATTR(_field, S_IWUSR | S_IRUGO, \ | ||
1456 | ims_pcu_ofn_bit_show, ims_pcu_ofn_bit_store), \ | ||
1457 | .addr = _addr, \ | ||
1458 | .nr = _nr, \ | ||
1459 | } | ||
1460 | |||
1461 | static IMS_PCU_OFN_BIT_ATTR(engine_enable, 0x60, 7); | ||
1462 | static IMS_PCU_OFN_BIT_ATTR(speed_enable, 0x60, 6); | ||
1463 | static IMS_PCU_OFN_BIT_ATTR(assert_enable, 0x60, 5); | ||
1464 | static IMS_PCU_OFN_BIT_ATTR(xyquant_enable, 0x60, 4); | ||
1465 | static IMS_PCU_OFN_BIT_ATTR(xyscale_enable, 0x60, 1); | ||
1466 | |||
1467 | static IMS_PCU_OFN_BIT_ATTR(scale_x2, 0x63, 6); | ||
1468 | static IMS_PCU_OFN_BIT_ATTR(scale_y2, 0x63, 7); | ||
1469 | |||
1470 | static struct attribute *ims_pcu_ofn_attrs[] = { | ||
1471 | &dev_attr_reg_data.attr, | ||
1472 | &dev_attr_reg_addr.attr, | ||
1473 | &ims_pcu_ofn_attr_engine_enable.dattr.attr, | ||
1474 | &ims_pcu_ofn_attr_speed_enable.dattr.attr, | ||
1475 | &ims_pcu_ofn_attr_assert_enable.dattr.attr, | ||
1476 | &ims_pcu_ofn_attr_xyquant_enable.dattr.attr, | ||
1477 | &ims_pcu_ofn_attr_xyscale_enable.dattr.attr, | ||
1478 | &ims_pcu_ofn_attr_scale_x2.dattr.attr, | ||
1479 | &ims_pcu_ofn_attr_scale_y2.dattr.attr, | ||
1480 | NULL | ||
1481 | }; | ||
1482 | |||
1483 | static struct attribute_group ims_pcu_ofn_attr_group = { | ||
1484 | .name = "ofn", | ||
1485 | .attrs = ims_pcu_ofn_attrs, | ||
1486 | }; | ||
1487 | |||
1259 | static void ims_pcu_irq(struct urb *urb) | 1488 | static void ims_pcu_irq(struct urb *urb) |
1260 | { | 1489 | { |
1261 | struct ims_pcu *pcu = urb->context; | 1490 | struct ims_pcu *pcu = urb->context; |
@@ -1624,7 +1853,6 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu) | |||
1624 | static atomic_t device_no = ATOMIC_INIT(0); | 1853 | static atomic_t device_no = ATOMIC_INIT(0); |
1625 | 1854 | ||
1626 | const struct ims_pcu_device_info *info; | 1855 | const struct ims_pcu_device_info *info; |
1627 | u8 device_id; | ||
1628 | int error; | 1856 | int error; |
1629 | 1857 | ||
1630 | error = ims_pcu_get_device_info(pcu); | 1858 | error = ims_pcu_get_device_info(pcu); |
@@ -1633,7 +1861,7 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu) | |||
1633 | return error; | 1861 | return error; |
1634 | } | 1862 | } |
1635 | 1863 | ||
1636 | error = ims_pcu_identify_type(pcu, &device_id); | 1864 | error = ims_pcu_identify_type(pcu, &pcu->device_id); |
1637 | if (error) { | 1865 | if (error) { |
1638 | dev_err(pcu->dev, | 1866 | dev_err(pcu->dev, |
1639 | "Failed to identify device, error: %d\n", error); | 1867 | "Failed to identify device, error: %d\n", error); |
@@ -1645,9 +1873,9 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu) | |||
1645 | return 0; | 1873 | return 0; |
1646 | } | 1874 | } |
1647 | 1875 | ||
1648 | if (device_id >= ARRAY_SIZE(ims_pcu_device_info) || | 1876 | if (pcu->device_id >= ARRAY_SIZE(ims_pcu_device_info) || |
1649 | !ims_pcu_device_info[device_id].keymap) { | 1877 | !ims_pcu_device_info[pcu->device_id].keymap) { |
1650 | dev_err(pcu->dev, "Device ID %d is not valid\n", device_id); | 1878 | dev_err(pcu->dev, "Device ID %d is not valid\n", pcu->device_id); |
1651 | /* Same as above, punt to userspace */ | 1879 | /* Same as above, punt to userspace */ |
1652 | return 0; | 1880 | return 0; |
1653 | } | 1881 | } |
@@ -1655,11 +1883,21 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu) | |||
1655 | /* Device appears to be operable, complete initialization */ | 1883 | /* Device appears to be operable, complete initialization */ |
1656 | pcu->device_no = atomic_inc_return(&device_no) - 1; | 1884 | pcu->device_no = atomic_inc_return(&device_no) - 1; |
1657 | 1885 | ||
1886 | /* | ||
1887 | * PCU-B devices, both GEN_1 and GEN_2 do not have OFN sensor | ||
1888 | */ | ||
1889 | if (pcu->device_id != IMS_PCU_PCU_B_DEVICE_ID) { | ||
1890 | error = sysfs_create_group(&pcu->dev->kobj, | ||
1891 | &ims_pcu_ofn_attr_group); | ||
1892 | if (error) | ||
1893 | return error; | ||
1894 | } | ||
1895 | |||
1658 | error = ims_pcu_setup_backlight(pcu); | 1896 | error = ims_pcu_setup_backlight(pcu); |
1659 | if (error) | 1897 | if (error) |
1660 | return error; | 1898 | return error; |
1661 | 1899 | ||
1662 | info = &ims_pcu_device_info[device_id]; | 1900 | info = &ims_pcu_device_info[pcu->device_id]; |
1663 | error = ims_pcu_setup_buttons(pcu, info->keymap, info->keymap_len); | 1901 | error = ims_pcu_setup_buttons(pcu, info->keymap, info->keymap_len); |
1664 | if (error) | 1902 | if (error) |
1665 | goto err_destroy_backlight; | 1903 | goto err_destroy_backlight; |
@@ -1674,10 +1912,10 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu) | |||
1674 | 1912 | ||
1675 | return 0; | 1913 | return 0; |
1676 | 1914 | ||
1677 | err_destroy_backlight: | ||
1678 | ims_pcu_destroy_backlight(pcu); | ||
1679 | err_destroy_buttons: | 1915 | err_destroy_buttons: |
1680 | ims_pcu_destroy_buttons(pcu); | 1916 | ims_pcu_destroy_buttons(pcu); |
1917 | err_destroy_backlight: | ||
1918 | ims_pcu_destroy_backlight(pcu); | ||
1681 | return error; | 1919 | return error; |
1682 | } | 1920 | } |
1683 | 1921 | ||
@@ -1691,6 +1929,10 @@ static void ims_pcu_destroy_application_mode(struct ims_pcu *pcu) | |||
1691 | ims_pcu_destroy_gamepad(pcu); | 1929 | ims_pcu_destroy_gamepad(pcu); |
1692 | ims_pcu_destroy_buttons(pcu); | 1930 | ims_pcu_destroy_buttons(pcu); |
1693 | ims_pcu_destroy_backlight(pcu); | 1931 | ims_pcu_destroy_backlight(pcu); |
1932 | |||
1933 | if (pcu->device_id != IMS_PCU_PCU_B_DEVICE_ID) | ||
1934 | sysfs_remove_group(&pcu->dev->kobj, | ||
1935 | &ims_pcu_ofn_attr_group); | ||
1694 | } | 1936 | } |
1695 | } | 1937 | } |
1696 | 1938 | ||
diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c index b88b7cbf93e2..6a915ba31bba 100644 --- a/drivers/input/misc/pm8xxx-vibrator.c +++ b/drivers/input/misc/pm8xxx-vibrator.c | |||
@@ -142,7 +142,6 @@ static int pm8xxx_vib_play_effect(struct input_dev *dev, void *data, | |||
142 | } | 142 | } |
143 | 143 | ||
144 | static int pm8xxx_vib_probe(struct platform_device *pdev) | 144 | static int pm8xxx_vib_probe(struct platform_device *pdev) |
145 | |||
146 | { | 145 | { |
147 | struct pm8xxx_vib *vib; | 146 | struct pm8xxx_vib *vib; |
148 | struct input_dev *input_dev; | 147 | struct input_dev *input_dev; |
@@ -214,12 +213,20 @@ static int pm8xxx_vib_suspend(struct device *dev) | |||
214 | 213 | ||
215 | static SIMPLE_DEV_PM_OPS(pm8xxx_vib_pm_ops, pm8xxx_vib_suspend, NULL); | 214 | static SIMPLE_DEV_PM_OPS(pm8xxx_vib_pm_ops, pm8xxx_vib_suspend, NULL); |
216 | 215 | ||
216 | static const struct of_device_id pm8xxx_vib_id_table[] = { | ||
217 | { .compatible = "qcom,pm8058-vib" }, | ||
218 | { .compatible = "qcom,pm8921-vib" }, | ||
219 | { } | ||
220 | }; | ||
221 | MODULE_DEVICE_TABLE(of, pm8xxx_vib_id_table); | ||
222 | |||
217 | static struct platform_driver pm8xxx_vib_driver = { | 223 | static struct platform_driver pm8xxx_vib_driver = { |
218 | .probe = pm8xxx_vib_probe, | 224 | .probe = pm8xxx_vib_probe, |
219 | .driver = { | 225 | .driver = { |
220 | .name = "pm8xxx-vib", | 226 | .name = "pm8xxx-vib", |
221 | .owner = THIS_MODULE, | 227 | .owner = THIS_MODULE, |
222 | .pm = &pm8xxx_vib_pm_ops, | 228 | .pm = &pm8xxx_vib_pm_ops, |
229 | .of_match_table = pm8xxx_vib_id_table, | ||
223 | }, | 230 | }, |
224 | }; | 231 | }; |
225 | module_platform_driver(pm8xxx_vib_driver); | 232 | module_platform_driver(pm8xxx_vib_driver); |
diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c index 0e1a05f95858..1cb8fda7a166 100644 --- a/drivers/input/misc/pmic8xxx-pwrkey.c +++ b/drivers/input/misc/pmic8xxx-pwrkey.c | |||
@@ -19,8 +19,7 @@ | |||
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/regmap.h> | 20 | #include <linux/regmap.h> |
21 | #include <linux/log2.h> | 21 | #include <linux/log2.h> |
22 | 22 | #include <linux/of.h> | |
23 | #include <linux/input/pmic8xxx-pwrkey.h> | ||
24 | 23 | ||
25 | #define PON_CNTL_1 0x1C | 24 | #define PON_CNTL_1 0x1C |
26 | #define PON_CNTL_PULL_UP BIT(7) | 25 | #define PON_CNTL_PULL_UP BIT(7) |
@@ -89,15 +88,15 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev) | |||
89 | unsigned int pon_cntl; | 88 | unsigned int pon_cntl; |
90 | struct regmap *regmap; | 89 | struct regmap *regmap; |
91 | struct pmic8xxx_pwrkey *pwrkey; | 90 | struct pmic8xxx_pwrkey *pwrkey; |
92 | const struct pm8xxx_pwrkey_platform_data *pdata = | 91 | u32 kpd_delay; |
93 | dev_get_platdata(&pdev->dev); | 92 | bool pull_up; |
94 | 93 | ||
95 | if (!pdata) { | 94 | if (of_property_read_u32(pdev->dev.of_node, "debounce", &kpd_delay)) |
96 | dev_err(&pdev->dev, "power key platform data not supplied\n"); | 95 | kpd_delay = 0; |
97 | return -EINVAL; | ||
98 | } | ||
99 | 96 | ||
100 | if (pdata->kpd_trigger_delay_us > 62500) { | 97 | pull_up = of_property_read_bool(pdev->dev.of_node, "pull-up"); |
98 | |||
99 | if (kpd_delay > 62500) { | ||
101 | dev_err(&pdev->dev, "invalid power key trigger delay\n"); | 100 | dev_err(&pdev->dev, "invalid power key trigger delay\n"); |
102 | return -EINVAL; | 101 | return -EINVAL; |
103 | } | 102 | } |
@@ -125,7 +124,7 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev) | |||
125 | pwr->name = "pmic8xxx_pwrkey"; | 124 | pwr->name = "pmic8xxx_pwrkey"; |
126 | pwr->phys = "pmic8xxx_pwrkey/input0"; | 125 | pwr->phys = "pmic8xxx_pwrkey/input0"; |
127 | 126 | ||
128 | delay = (pdata->kpd_trigger_delay_us << 10) / USEC_PER_SEC; | 127 | delay = (kpd_delay << 10) / USEC_PER_SEC; |
129 | delay = 1 + ilog2(delay); | 128 | delay = 1 + ilog2(delay); |
130 | 129 | ||
131 | err = regmap_read(regmap, PON_CNTL_1, &pon_cntl); | 130 | err = regmap_read(regmap, PON_CNTL_1, &pon_cntl); |
@@ -136,7 +135,7 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev) | |||
136 | 135 | ||
137 | pon_cntl &= ~PON_CNTL_TRIG_DELAY_MASK; | 136 | pon_cntl &= ~PON_CNTL_TRIG_DELAY_MASK; |
138 | pon_cntl |= (delay & PON_CNTL_TRIG_DELAY_MASK); | 137 | pon_cntl |= (delay & PON_CNTL_TRIG_DELAY_MASK); |
139 | if (pdata->pull_up) | 138 | if (pull_up) |
140 | pon_cntl |= PON_CNTL_PULL_UP; | 139 | pon_cntl |= PON_CNTL_PULL_UP; |
141 | else | 140 | else |
142 | pon_cntl &= ~PON_CNTL_PULL_UP; | 141 | pon_cntl &= ~PON_CNTL_PULL_UP; |
@@ -172,7 +171,7 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev) | |||
172 | } | 171 | } |
173 | 172 | ||
174 | platform_set_drvdata(pdev, pwrkey); | 173 | platform_set_drvdata(pdev, pwrkey); |
175 | device_init_wakeup(&pdev->dev, pdata->wakeup); | 174 | device_init_wakeup(&pdev->dev, 1); |
176 | 175 | ||
177 | return 0; | 176 | return 0; |
178 | } | 177 | } |
@@ -184,13 +183,21 @@ static int pmic8xxx_pwrkey_remove(struct platform_device *pdev) | |||
184 | return 0; | 183 | return 0; |
185 | } | 184 | } |
186 | 185 | ||
186 | static const struct of_device_id pm8xxx_pwr_key_id_table[] = { | ||
187 | { .compatible = "qcom,pm8058-pwrkey" }, | ||
188 | { .compatible = "qcom,pm8921-pwrkey" }, | ||
189 | { } | ||
190 | }; | ||
191 | MODULE_DEVICE_TABLE(of, pm8xxx_pwr_key_id_table); | ||
192 | |||
187 | static struct platform_driver pmic8xxx_pwrkey_driver = { | 193 | static struct platform_driver pmic8xxx_pwrkey_driver = { |
188 | .probe = pmic8xxx_pwrkey_probe, | 194 | .probe = pmic8xxx_pwrkey_probe, |
189 | .remove = pmic8xxx_pwrkey_remove, | 195 | .remove = pmic8xxx_pwrkey_remove, |
190 | .driver = { | 196 | .driver = { |
191 | .name = PM8XXX_PWRKEY_DEV_NAME, | 197 | .name = "pm8xxx-pwrkey", |
192 | .owner = THIS_MODULE, | 198 | .owner = THIS_MODULE, |
193 | .pm = &pm8xxx_pwr_key_pm_ops, | 199 | .pm = &pm8xxx_pwr_key_pm_ops, |
200 | .of_match_table = pm8xxx_pwr_key_id_table, | ||
194 | }, | 201 | }, |
195 | }; | 202 | }; |
196 | module_platform_driver(pmic8xxx_pwrkey_driver); | 203 | module_platform_driver(pmic8xxx_pwrkey_driver); |
diff --git a/drivers/input/misc/sirfsoc-onkey.c b/drivers/input/misc/sirfsoc-onkey.c index e8897c36d21b..e4104f9b2e6d 100644 --- a/drivers/input/misc/sirfsoc-onkey.c +++ b/drivers/input/misc/sirfsoc-onkey.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Power key driver for SiRF PrimaII | 2 | * Power key driver for SiRF PrimaII |
3 | * | 3 | * |
4 | * Copyright (c) 2013 Cambridge Silicon Radio Limited, a CSR plc group company. | 4 | * Copyright (c) 2013 - 2014 Cambridge Silicon Radio Limited, a CSR plc group |
5 | * company. | ||
5 | * | 6 | * |
6 | * Licensed under GPLv2 or later. | 7 | * Licensed under GPLv2 or later. |
7 | */ | 8 | */ |
@@ -13,16 +14,41 @@ | |||
13 | #include <linux/input.h> | 14 | #include <linux/input.h> |
14 | #include <linux/rtc/sirfsoc_rtciobrg.h> | 15 | #include <linux/rtc/sirfsoc_rtciobrg.h> |
15 | #include <linux/of.h> | 16 | #include <linux/of.h> |
17 | #include <linux/workqueue.h> | ||
16 | 18 | ||
17 | struct sirfsoc_pwrc_drvdata { | 19 | struct sirfsoc_pwrc_drvdata { |
18 | u32 pwrc_base; | 20 | u32 pwrc_base; |
19 | struct input_dev *input; | 21 | struct input_dev *input; |
22 | struct delayed_work work; | ||
20 | }; | 23 | }; |
21 | 24 | ||
22 | #define PWRC_ON_KEY_BIT (1 << 0) | 25 | #define PWRC_ON_KEY_BIT (1 << 0) |
23 | 26 | ||
24 | #define PWRC_INT_STATUS 0xc | 27 | #define PWRC_INT_STATUS 0xc |
25 | #define PWRC_INT_MASK 0x10 | 28 | #define PWRC_INT_MASK 0x10 |
29 | #define PWRC_PIN_STATUS 0x14 | ||
30 | #define PWRC_KEY_DETECT_UP_TIME 20 /* ms*/ | ||
31 | |||
32 | static int sirfsoc_pwrc_is_on_key_down(struct sirfsoc_pwrc_drvdata *pwrcdrv) | ||
33 | { | ||
34 | u32 state = sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + | ||
35 | PWRC_PIN_STATUS); | ||
36 | return !(state & PWRC_ON_KEY_BIT); /* ON_KEY is active low */ | ||
37 | } | ||
38 | |||
39 | static void sirfsoc_pwrc_report_event(struct work_struct *work) | ||
40 | { | ||
41 | struct sirfsoc_pwrc_drvdata *pwrcdrv = | ||
42 | container_of(work, struct sirfsoc_pwrc_drvdata, work.work); | ||
43 | |||
44 | if (sirfsoc_pwrc_is_on_key_down(pwrcdrv)) { | ||
45 | schedule_delayed_work(&pwrcdrv->work, | ||
46 | msecs_to_jiffies(PWRC_KEY_DETECT_UP_TIME)); | ||
47 | } else { | ||
48 | input_event(pwrcdrv->input, EV_KEY, KEY_POWER, 0); | ||
49 | input_sync(pwrcdrv->input); | ||
50 | } | ||
51 | } | ||
26 | 52 | ||
27 | static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id) | 53 | static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id) |
28 | { | 54 | { |
@@ -34,21 +60,44 @@ static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id) | |||
34 | sirfsoc_rtc_iobrg_writel(int_status & ~PWRC_ON_KEY_BIT, | 60 | sirfsoc_rtc_iobrg_writel(int_status & ~PWRC_ON_KEY_BIT, |
35 | pwrcdrv->pwrc_base + PWRC_INT_STATUS); | 61 | pwrcdrv->pwrc_base + PWRC_INT_STATUS); |
36 | 62 | ||
37 | /* | 63 | input_event(pwrcdrv->input, EV_KEY, KEY_POWER, 1); |
38 | * For a typical Linux system, we report KEY_SUSPEND to trigger apm-power.c | ||
39 | * to queue a SUSPEND APM event | ||
40 | */ | ||
41 | input_event(pwrcdrv->input, EV_PWR, KEY_SUSPEND, 1); | ||
42 | input_sync(pwrcdrv->input); | 64 | input_sync(pwrcdrv->input); |
43 | 65 | schedule_delayed_work(&pwrcdrv->work, | |
44 | /* | 66 | msecs_to_jiffies(PWRC_KEY_DETECT_UP_TIME)); |
45 | * Todo: report KEY_POWER event for Android platforms, Android PowerManager | ||
46 | * will handle the suspend and powerdown/hibernation | ||
47 | */ | ||
48 | 67 | ||
49 | return IRQ_HANDLED; | 68 | return IRQ_HANDLED; |
50 | } | 69 | } |
51 | 70 | ||
71 | static void sirfsoc_pwrc_toggle_interrupts(struct sirfsoc_pwrc_drvdata *pwrcdrv, | ||
72 | bool enable) | ||
73 | { | ||
74 | u32 int_mask; | ||
75 | |||
76 | int_mask = sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + PWRC_INT_MASK); | ||
77 | if (enable) | ||
78 | int_mask |= PWRC_ON_KEY_BIT; | ||
79 | else | ||
80 | int_mask &= ~PWRC_ON_KEY_BIT; | ||
81 | sirfsoc_rtc_iobrg_writel(int_mask, pwrcdrv->pwrc_base + PWRC_INT_MASK); | ||
82 | } | ||
83 | |||
84 | static int sirfsoc_pwrc_open(struct input_dev *input) | ||
85 | { | ||
86 | struct sirfsoc_pwrc_drvdata *pwrcdrv = input_get_drvdata(input); | ||
87 | |||
88 | sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true); | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | static void sirfsoc_pwrc_close(struct input_dev *input) | ||
94 | { | ||
95 | struct sirfsoc_pwrc_drvdata *pwrcdrv = input_get_drvdata(input); | ||
96 | |||
97 | sirfsoc_pwrc_toggle_interrupts(pwrcdrv, false); | ||
98 | cancel_delayed_work_sync(&pwrcdrv->work); | ||
99 | } | ||
100 | |||
52 | static const struct of_device_id sirfsoc_pwrc_of_match[] = { | 101 | static const struct of_device_id sirfsoc_pwrc_of_match[] = { |
53 | { .compatible = "sirf,prima2-pwrc" }, | 102 | { .compatible = "sirf,prima2-pwrc" }, |
54 | {}, | 103 | {}, |
@@ -70,7 +119,7 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev) | |||
70 | } | 119 | } |
71 | 120 | ||
72 | /* | 121 | /* |
73 | * we can't use of_iomap because pwrc is not mapped in memory, | 122 | * We can't use of_iomap because pwrc is not mapped in memory, |
74 | * the so-called base address is only offset in rtciobrg | 123 | * the so-called base address is only offset in rtciobrg |
75 | */ | 124 | */ |
76 | error = of_property_read_u32(np, "reg", &pwrcdrv->pwrc_base); | 125 | error = of_property_read_u32(np, "reg", &pwrcdrv->pwrc_base); |
@@ -86,11 +135,22 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev) | |||
86 | 135 | ||
87 | pwrcdrv->input->name = "sirfsoc pwrckey"; | 136 | pwrcdrv->input->name = "sirfsoc pwrckey"; |
88 | pwrcdrv->input->phys = "pwrc/input0"; | 137 | pwrcdrv->input->phys = "pwrc/input0"; |
89 | pwrcdrv->input->evbit[0] = BIT_MASK(EV_PWR); | 138 | pwrcdrv->input->evbit[0] = BIT_MASK(EV_KEY); |
139 | input_set_capability(pwrcdrv->input, EV_KEY, KEY_POWER); | ||
140 | |||
141 | INIT_DELAYED_WORK(&pwrcdrv->work, sirfsoc_pwrc_report_event); | ||
142 | |||
143 | pwrcdrv->input->open = sirfsoc_pwrc_open; | ||
144 | pwrcdrv->input->close = sirfsoc_pwrc_close; | ||
145 | |||
146 | input_set_drvdata(pwrcdrv->input, pwrcdrv); | ||
147 | |||
148 | /* Make sure the device is quiesced */ | ||
149 | sirfsoc_pwrc_toggle_interrupts(pwrcdrv, false); | ||
90 | 150 | ||
91 | irq = platform_get_irq(pdev, 0); | 151 | irq = platform_get_irq(pdev, 0); |
92 | error = devm_request_irq(&pdev->dev, irq, | 152 | error = devm_request_irq(&pdev->dev, irq, |
93 | sirfsoc_pwrc_isr, IRQF_SHARED, | 153 | sirfsoc_pwrc_isr, 0, |
94 | "sirfsoc_pwrc_int", pwrcdrv); | 154 | "sirfsoc_pwrc_int", pwrcdrv); |
95 | if (error) { | 155 | if (error) { |
96 | dev_err(&pdev->dev, "unable to claim irq %d, error: %d\n", | 156 | dev_err(&pdev->dev, "unable to claim irq %d, error: %d\n", |
@@ -98,11 +158,6 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev) | |||
98 | return error; | 158 | return error; |
99 | } | 159 | } |
100 | 160 | ||
101 | sirfsoc_rtc_iobrg_writel( | ||
102 | sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + PWRC_INT_MASK) | | ||
103 | PWRC_ON_KEY_BIT, | ||
104 | pwrcdrv->pwrc_base + PWRC_INT_MASK); | ||
105 | |||
106 | error = input_register_device(pwrcdrv->input); | 161 | error = input_register_device(pwrcdrv->input); |
107 | if (error) { | 162 | if (error) { |
108 | dev_err(&pdev->dev, | 163 | dev_err(&pdev->dev, |
@@ -111,7 +166,7 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev) | |||
111 | return error; | 166 | return error; |
112 | } | 167 | } |
113 | 168 | ||
114 | platform_set_drvdata(pdev, pwrcdrv); | 169 | dev_set_drvdata(&pdev->dev, pwrcdrv); |
115 | device_init_wakeup(&pdev->dev, 1); | 170 | device_init_wakeup(&pdev->dev, 1); |
116 | 171 | ||
117 | return 0; | 172 | return 0; |
@@ -125,25 +180,25 @@ static int sirfsoc_pwrc_remove(struct platform_device *pdev) | |||
125 | } | 180 | } |
126 | 181 | ||
127 | #ifdef CONFIG_PM_SLEEP | 182 | #ifdef CONFIG_PM_SLEEP |
128 | static int pwrc_resume(struct device *dev) | 183 | static int sirfsoc_pwrc_resume(struct device *dev) |
129 | { | 184 | { |
130 | struct platform_device *pdev = to_platform_device(dev); | 185 | struct sirfsoc_pwrc_drvdata *pwrcdrv = dev_get_drvdata(dev); |
131 | struct sirfsoc_pwrc_drvdata *pwrcdrv = platform_get_drvdata(pdev); | 186 | struct input_dev *input = pwrcdrv->input; |
132 | 187 | ||
133 | /* | 188 | /* |
134 | * Do not mask pwrc interrupt as we want pwrc work as a wakeup source | 189 | * Do not mask pwrc interrupt as we want pwrc work as a wakeup source |
135 | * if users touch X_ONKEY_B, see arch/arm/mach-prima2/pm.c | 190 | * if users touch X_ONKEY_B, see arch/arm/mach-prima2/pm.c |
136 | */ | 191 | */ |
137 | sirfsoc_rtc_iobrg_writel( | 192 | mutex_lock(&input->mutex); |
138 | sirfsoc_rtc_iobrg_readl( | 193 | if (input->users) |
139 | pwrcdrv->pwrc_base + PWRC_INT_MASK) | PWRC_ON_KEY_BIT, | 194 | sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true); |
140 | pwrcdrv->pwrc_base + PWRC_INT_MASK); | 195 | mutex_unlock(&input->mutex); |
141 | 196 | ||
142 | return 0; | 197 | return 0; |
143 | } | 198 | } |
144 | #endif | 199 | #endif |
145 | 200 | ||
146 | static SIMPLE_DEV_PM_OPS(sirfsoc_pwrc_pm_ops, NULL, pwrc_resume); | 201 | static SIMPLE_DEV_PM_OPS(sirfsoc_pwrc_pm_ops, NULL, sirfsoc_pwrc_resume); |
147 | 202 | ||
148 | static struct platform_driver sirfsoc_pwrc_driver = { | 203 | static struct platform_driver sirfsoc_pwrc_driver = { |
149 | .probe = sirfsoc_pwrc_probe, | 204 | .probe = sirfsoc_pwrc_probe, |
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c new file mode 100644 index 000000000000..08ead2aaede5 --- /dev/null +++ b/drivers/input/misc/soc_button_array.c | |||
@@ -0,0 +1,218 @@ | |||
1 | /* | ||
2 | * Supports for the button array on SoC tablets originally running | ||
3 | * Windows 8. | ||
4 | * | ||
5 | * (C) Copyright 2014 Intel Corporation | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/input.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/acpi.h> | ||
18 | #include <linux/gpio/consumer.h> | ||
19 | #include <linux/gpio_keys.h> | ||
20 | #include <linux/input.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/pnp.h> | ||
23 | |||
24 | /* | ||
25 | * Definition of buttons on the tablet. The ACPI index of each button | ||
26 | * is defined in section 2.8.7.2 of "Windows ACPI Design Guide for SoC | ||
27 | * Platforms" | ||
28 | */ | ||
29 | #define MAX_NBUTTONS 5 | ||
30 | |||
31 | struct soc_button_info { | ||
32 | const char *name; | ||
33 | int acpi_index; | ||
34 | unsigned int event_type; | ||
35 | unsigned int event_code; | ||
36 | bool autorepeat; | ||
37 | bool wakeup; | ||
38 | }; | ||
39 | |||
40 | /* | ||
41 | * Some of the buttons like volume up/down are auto repeat, while others | ||
42 | * are not. To support both, we register two platform devices, and put | ||
43 | * buttons into them based on whether the key should be auto repeat. | ||
44 | */ | ||
45 | #define BUTTON_TYPES 2 | ||
46 | |||
47 | struct soc_button_data { | ||
48 | struct platform_device *children[BUTTON_TYPES]; | ||
49 | }; | ||
50 | |||
51 | /* | ||
52 | * Get the Nth GPIO number from the ACPI object. | ||
53 | */ | ||
54 | static int soc_button_lookup_gpio(struct device *dev, int acpi_index) | ||
55 | { | ||
56 | struct gpio_desc *desc; | ||
57 | int gpio; | ||
58 | |||
59 | desc = gpiod_get_index(dev, KBUILD_MODNAME, acpi_index); | ||
60 | if (IS_ERR(desc)) | ||
61 | return PTR_ERR(desc); | ||
62 | |||
63 | gpio = desc_to_gpio(desc); | ||
64 | |||
65 | gpiod_put(desc); | ||
66 | |||
67 | return gpio; | ||
68 | } | ||
69 | |||
70 | static struct platform_device * | ||
71 | soc_button_device_create(struct pnp_dev *pdev, | ||
72 | const struct soc_button_info *button_info, | ||
73 | bool autorepeat) | ||
74 | { | ||
75 | const struct soc_button_info *info; | ||
76 | struct platform_device *pd; | ||
77 | struct gpio_keys_button *gpio_keys; | ||
78 | struct gpio_keys_platform_data *gpio_keys_pdata; | ||
79 | int n_buttons = 0; | ||
80 | int gpio; | ||
81 | int error; | ||
82 | |||
83 | gpio_keys_pdata = devm_kzalloc(&pdev->dev, | ||
84 | sizeof(*gpio_keys_pdata) + | ||
85 | sizeof(*gpio_keys) * MAX_NBUTTONS, | ||
86 | GFP_KERNEL); | ||
87 | gpio_keys = (void *)(gpio_keys_pdata + 1); | ||
88 | |||
89 | for (info = button_info; info->name; info++) { | ||
90 | if (info->autorepeat != autorepeat) | ||
91 | continue; | ||
92 | |||
93 | gpio = soc_button_lookup_gpio(&pdev->dev, info->acpi_index); | ||
94 | if (gpio < 0) | ||
95 | continue; | ||
96 | |||
97 | gpio_keys[n_buttons].type = info->event_type; | ||
98 | gpio_keys[n_buttons].code = info->event_code; | ||
99 | gpio_keys[n_buttons].gpio = gpio; | ||
100 | gpio_keys[n_buttons].active_low = 1; | ||
101 | gpio_keys[n_buttons].desc = info->name; | ||
102 | gpio_keys[n_buttons].wakeup = info->wakeup; | ||
103 | n_buttons++; | ||
104 | } | ||
105 | |||
106 | if (n_buttons == 0) { | ||
107 | error = -ENODEV; | ||
108 | goto err_free_mem; | ||
109 | } | ||
110 | |||
111 | gpio_keys_pdata->buttons = gpio_keys; | ||
112 | gpio_keys_pdata->nbuttons = n_buttons; | ||
113 | gpio_keys_pdata->rep = autorepeat; | ||
114 | |||
115 | pd = platform_device_alloc("gpio-keys", PLATFORM_DEVID_AUTO); | ||
116 | if (!pd) { | ||
117 | error = -ENOMEM; | ||
118 | goto err_free_mem; | ||
119 | } | ||
120 | |||
121 | error = platform_device_add_data(pd, gpio_keys_pdata, | ||
122 | sizeof(*gpio_keys_pdata)); | ||
123 | if (error) | ||
124 | goto err_free_pdev; | ||
125 | |||
126 | error = platform_device_add(pd); | ||
127 | if (error) | ||
128 | goto err_free_pdev; | ||
129 | |||
130 | return pd; | ||
131 | |||
132 | err_free_pdev: | ||
133 | platform_device_put(pd); | ||
134 | err_free_mem: | ||
135 | devm_kfree(&pdev->dev, gpio_keys_pdata); | ||
136 | return ERR_PTR(error); | ||
137 | } | ||
138 | |||
139 | static void soc_button_remove(struct pnp_dev *pdev) | ||
140 | { | ||
141 | struct soc_button_data *priv = pnp_get_drvdata(pdev); | ||
142 | int i; | ||
143 | |||
144 | for (i = 0; i < BUTTON_TYPES; i++) | ||
145 | if (priv->children[i]) | ||
146 | platform_device_unregister(priv->children[i]); | ||
147 | } | ||
148 | |||
149 | static int soc_button_pnp_probe(struct pnp_dev *pdev, | ||
150 | const struct pnp_device_id *id) | ||
151 | { | ||
152 | const struct soc_button_info *button_info = (void *)id->driver_data; | ||
153 | struct soc_button_data *priv; | ||
154 | struct platform_device *pd; | ||
155 | int i; | ||
156 | int error; | ||
157 | |||
158 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
159 | if (!priv) | ||
160 | return -ENOMEM; | ||
161 | |||
162 | pnp_set_drvdata(pdev, priv); | ||
163 | |||
164 | for (i = 0; i < BUTTON_TYPES; i++) { | ||
165 | pd = soc_button_device_create(pdev, button_info, i == 0); | ||
166 | if (IS_ERR(pd)) { | ||
167 | error = PTR_ERR(pd); | ||
168 | if (error != -ENODEV) { | ||
169 | soc_button_remove(pdev); | ||
170 | return error; | ||
171 | } | ||
172 | } | ||
173 | |||
174 | priv->children[i] = pd; | ||
175 | } | ||
176 | |||
177 | if (!priv->children[0] && !priv->children[1]) | ||
178 | return -ENODEV; | ||
179 | |||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static struct soc_button_info soc_button_PNP0C40[] = { | ||
184 | { "power", 0, EV_KEY, KEY_POWER, false, true }, | ||
185 | { "home", 1, EV_KEY, KEY_HOME, false, true }, | ||
186 | { "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false }, | ||
187 | { "volume_down", 3, EV_KEY, KEY_VOLUMEDOWN, true, false }, | ||
188 | { "rotation_lock", 4, EV_SW, SW_ROTATE_LOCK, false, false }, | ||
189 | { } | ||
190 | }; | ||
191 | |||
192 | static const struct pnp_device_id soc_button_pnp_match[] = { | ||
193 | { .id = "PNP0C40", .driver_data = (long)soc_button_PNP0C40 }, | ||
194 | { .id = "" } | ||
195 | }; | ||
196 | MODULE_DEVICE_TABLE(pnp, soc_button_pnp_match); | ||
197 | |||
198 | static struct pnp_driver soc_button_pnp_driver = { | ||
199 | .name = KBUILD_MODNAME, | ||
200 | .id_table = soc_button_pnp_match, | ||
201 | .probe = soc_button_pnp_probe, | ||
202 | .remove = soc_button_remove, | ||
203 | }; | ||
204 | |||
205 | static int __init soc_button_init(void) | ||
206 | { | ||
207 | return pnp_register_driver(&soc_button_pnp_driver); | ||
208 | } | ||
209 | |||
210 | static void __exit soc_button_exit(void) | ||
211 | { | ||
212 | pnp_unregister_driver(&soc_button_pnp_driver); | ||
213 | } | ||
214 | |||
215 | module_init(soc_button_init); | ||
216 | module_exit(soc_button_exit); | ||
217 | |||
218 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 772835938a52..856936247500 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c | |||
@@ -20,6 +20,8 @@ | |||
20 | * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org> | 20 | * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org> |
21 | * | 21 | * |
22 | * Changes/Revisions: | 22 | * Changes/Revisions: |
23 | * 0.4 01/09/2014 (Benjamin Tissoires <benjamin.tissoires@redhat.com>) | ||
24 | * - add UI_GET_SYSNAME ioctl | ||
23 | * 0.3 09/04/2006 (Anssi Hannula <anssi.hannula@gmail.com>) | 25 | * 0.3 09/04/2006 (Anssi Hannula <anssi.hannula@gmail.com>) |
24 | * - updated ff support for the changes in kernel interface | 26 | * - updated ff support for the changes in kernel interface |
25 | * - added MODULE_VERSION | 27 | * - added MODULE_VERSION |
@@ -670,6 +672,31 @@ static int uinput_ff_upload_from_user(const char __user *buffer, | |||
670 | __ret; \ | 672 | __ret; \ |
671 | }) | 673 | }) |
672 | 674 | ||
675 | static int uinput_str_to_user(void __user *dest, const char *str, | ||
676 | unsigned int maxlen) | ||
677 | { | ||
678 | char __user *p = dest; | ||
679 | int len, ret; | ||
680 | |||
681 | if (!str) | ||
682 | return -ENOENT; | ||
683 | |||
684 | if (maxlen == 0) | ||
685 | return -EINVAL; | ||
686 | |||
687 | len = strlen(str) + 1; | ||
688 | if (len > maxlen) | ||
689 | len = maxlen; | ||
690 | |||
691 | ret = copy_to_user(p, str, len); | ||
692 | if (ret) | ||
693 | return -EFAULT; | ||
694 | |||
695 | /* force terminating '\0' */ | ||
696 | ret = put_user(0, p + len - 1); | ||
697 | return ret ? -EFAULT : len; | ||
698 | } | ||
699 | |||
673 | static long uinput_ioctl_handler(struct file *file, unsigned int cmd, | 700 | static long uinput_ioctl_handler(struct file *file, unsigned int cmd, |
674 | unsigned long arg, void __user *p) | 701 | unsigned long arg, void __user *p) |
675 | { | 702 | { |
@@ -679,6 +706,8 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, | |||
679 | struct uinput_ff_erase ff_erase; | 706 | struct uinput_ff_erase ff_erase; |
680 | struct uinput_request *req; | 707 | struct uinput_request *req; |
681 | char *phys; | 708 | char *phys; |
709 | const char *name; | ||
710 | unsigned int size; | ||
682 | 711 | ||
683 | retval = mutex_lock_interruptible(&udev->mutex); | 712 | retval = mutex_lock_interruptible(&udev->mutex); |
684 | if (retval) | 713 | if (retval) |
@@ -693,51 +722,51 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, | |||
693 | switch (cmd) { | 722 | switch (cmd) { |
694 | case UI_DEV_CREATE: | 723 | case UI_DEV_CREATE: |
695 | retval = uinput_create_device(udev); | 724 | retval = uinput_create_device(udev); |
696 | break; | 725 | goto out; |
697 | 726 | ||
698 | case UI_DEV_DESTROY: | 727 | case UI_DEV_DESTROY: |
699 | uinput_destroy_device(udev); | 728 | uinput_destroy_device(udev); |
700 | break; | 729 | goto out; |
701 | 730 | ||
702 | case UI_SET_EVBIT: | 731 | case UI_SET_EVBIT: |
703 | retval = uinput_set_bit(arg, evbit, EV_MAX); | 732 | retval = uinput_set_bit(arg, evbit, EV_MAX); |
704 | break; | 733 | goto out; |
705 | 734 | ||
706 | case UI_SET_KEYBIT: | 735 | case UI_SET_KEYBIT: |
707 | retval = uinput_set_bit(arg, keybit, KEY_MAX); | 736 | retval = uinput_set_bit(arg, keybit, KEY_MAX); |
708 | break; | 737 | goto out; |
709 | 738 | ||
710 | case UI_SET_RELBIT: | 739 | case UI_SET_RELBIT: |
711 | retval = uinput_set_bit(arg, relbit, REL_MAX); | 740 | retval = uinput_set_bit(arg, relbit, REL_MAX); |
712 | break; | 741 | goto out; |
713 | 742 | ||
714 | case UI_SET_ABSBIT: | 743 | case UI_SET_ABSBIT: |
715 | retval = uinput_set_bit(arg, absbit, ABS_MAX); | 744 | retval = uinput_set_bit(arg, absbit, ABS_MAX); |
716 | break; | 745 | goto out; |
717 | 746 | ||
718 | case UI_SET_MSCBIT: | 747 | case UI_SET_MSCBIT: |
719 | retval = uinput_set_bit(arg, mscbit, MSC_MAX); | 748 | retval = uinput_set_bit(arg, mscbit, MSC_MAX); |
720 | break; | 749 | goto out; |
721 | 750 | ||
722 | case UI_SET_LEDBIT: | 751 | case UI_SET_LEDBIT: |
723 | retval = uinput_set_bit(arg, ledbit, LED_MAX); | 752 | retval = uinput_set_bit(arg, ledbit, LED_MAX); |
724 | break; | 753 | goto out; |
725 | 754 | ||
726 | case UI_SET_SNDBIT: | 755 | case UI_SET_SNDBIT: |
727 | retval = uinput_set_bit(arg, sndbit, SND_MAX); | 756 | retval = uinput_set_bit(arg, sndbit, SND_MAX); |
728 | break; | 757 | goto out; |
729 | 758 | ||
730 | case UI_SET_FFBIT: | 759 | case UI_SET_FFBIT: |
731 | retval = uinput_set_bit(arg, ffbit, FF_MAX); | 760 | retval = uinput_set_bit(arg, ffbit, FF_MAX); |
732 | break; | 761 | goto out; |
733 | 762 | ||
734 | case UI_SET_SWBIT: | 763 | case UI_SET_SWBIT: |
735 | retval = uinput_set_bit(arg, swbit, SW_MAX); | 764 | retval = uinput_set_bit(arg, swbit, SW_MAX); |
736 | break; | 765 | goto out; |
737 | 766 | ||
738 | case UI_SET_PROPBIT: | 767 | case UI_SET_PROPBIT: |
739 | retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX); | 768 | retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX); |
740 | break; | 769 | goto out; |
741 | 770 | ||
742 | case UI_SET_PHYS: | 771 | case UI_SET_PHYS: |
743 | if (udev->state == UIST_CREATED) { | 772 | if (udev->state == UIST_CREATED) { |
@@ -753,18 +782,18 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, | |||
753 | 782 | ||
754 | kfree(udev->dev->phys); | 783 | kfree(udev->dev->phys); |
755 | udev->dev->phys = phys; | 784 | udev->dev->phys = phys; |
756 | break; | 785 | goto out; |
757 | 786 | ||
758 | case UI_BEGIN_FF_UPLOAD: | 787 | case UI_BEGIN_FF_UPLOAD: |
759 | retval = uinput_ff_upload_from_user(p, &ff_up); | 788 | retval = uinput_ff_upload_from_user(p, &ff_up); |
760 | if (retval) | 789 | if (retval) |
761 | break; | 790 | goto out; |
762 | 791 | ||
763 | req = uinput_request_find(udev, ff_up.request_id); | 792 | req = uinput_request_find(udev, ff_up.request_id); |
764 | if (!req || req->code != UI_FF_UPLOAD || | 793 | if (!req || req->code != UI_FF_UPLOAD || |
765 | !req->u.upload.effect) { | 794 | !req->u.upload.effect) { |
766 | retval = -EINVAL; | 795 | retval = -EINVAL; |
767 | break; | 796 | goto out; |
768 | } | 797 | } |
769 | 798 | ||
770 | ff_up.retval = 0; | 799 | ff_up.retval = 0; |
@@ -775,65 +804,77 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, | |||
775 | memset(&ff_up.old, 0, sizeof(struct ff_effect)); | 804 | memset(&ff_up.old, 0, sizeof(struct ff_effect)); |
776 | 805 | ||
777 | retval = uinput_ff_upload_to_user(p, &ff_up); | 806 | retval = uinput_ff_upload_to_user(p, &ff_up); |
778 | break; | 807 | goto out; |
779 | 808 | ||
780 | case UI_BEGIN_FF_ERASE: | 809 | case UI_BEGIN_FF_ERASE: |
781 | if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) { | 810 | if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) { |
782 | retval = -EFAULT; | 811 | retval = -EFAULT; |
783 | break; | 812 | goto out; |
784 | } | 813 | } |
785 | 814 | ||
786 | req = uinput_request_find(udev, ff_erase.request_id); | 815 | req = uinput_request_find(udev, ff_erase.request_id); |
787 | if (!req || req->code != UI_FF_ERASE) { | 816 | if (!req || req->code != UI_FF_ERASE) { |
788 | retval = -EINVAL; | 817 | retval = -EINVAL; |
789 | break; | 818 | goto out; |
790 | } | 819 | } |
791 | 820 | ||
792 | ff_erase.retval = 0; | 821 | ff_erase.retval = 0; |
793 | ff_erase.effect_id = req->u.effect_id; | 822 | ff_erase.effect_id = req->u.effect_id; |
794 | if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) { | 823 | if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) { |
795 | retval = -EFAULT; | 824 | retval = -EFAULT; |
796 | break; | 825 | goto out; |
797 | } | 826 | } |
798 | 827 | ||
799 | break; | 828 | goto out; |
800 | 829 | ||
801 | case UI_END_FF_UPLOAD: | 830 | case UI_END_FF_UPLOAD: |
802 | retval = uinput_ff_upload_from_user(p, &ff_up); | 831 | retval = uinput_ff_upload_from_user(p, &ff_up); |
803 | if (retval) | 832 | if (retval) |
804 | break; | 833 | goto out; |
805 | 834 | ||
806 | req = uinput_request_find(udev, ff_up.request_id); | 835 | req = uinput_request_find(udev, ff_up.request_id); |
807 | if (!req || req->code != UI_FF_UPLOAD || | 836 | if (!req || req->code != UI_FF_UPLOAD || |
808 | !req->u.upload.effect) { | 837 | !req->u.upload.effect) { |
809 | retval = -EINVAL; | 838 | retval = -EINVAL; |
810 | break; | 839 | goto out; |
811 | } | 840 | } |
812 | 841 | ||
813 | req->retval = ff_up.retval; | 842 | req->retval = ff_up.retval; |
814 | uinput_request_done(udev, req); | 843 | uinput_request_done(udev, req); |
815 | break; | 844 | goto out; |
816 | 845 | ||
817 | case UI_END_FF_ERASE: | 846 | case UI_END_FF_ERASE: |
818 | if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) { | 847 | if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) { |
819 | retval = -EFAULT; | 848 | retval = -EFAULT; |
820 | break; | 849 | goto out; |
821 | } | 850 | } |
822 | 851 | ||
823 | req = uinput_request_find(udev, ff_erase.request_id); | 852 | req = uinput_request_find(udev, ff_erase.request_id); |
824 | if (!req || req->code != UI_FF_ERASE) { | 853 | if (!req || req->code != UI_FF_ERASE) { |
825 | retval = -EINVAL; | 854 | retval = -EINVAL; |
826 | break; | 855 | goto out; |
827 | } | 856 | } |
828 | 857 | ||
829 | req->retval = ff_erase.retval; | 858 | req->retval = ff_erase.retval; |
830 | uinput_request_done(udev, req); | 859 | uinput_request_done(udev, req); |
831 | break; | 860 | goto out; |
861 | } | ||
832 | 862 | ||
833 | default: | 863 | size = _IOC_SIZE(cmd); |
834 | retval = -EINVAL; | 864 | |
865 | /* Now check variable-length commands */ | ||
866 | switch (cmd & ~IOCSIZE_MASK) { | ||
867 | case UI_GET_SYSNAME(0): | ||
868 | if (udev->state != UIST_CREATED) { | ||
869 | retval = -ENOENT; | ||
870 | goto out; | ||
871 | } | ||
872 | name = dev_name(&udev->dev->dev); | ||
873 | retval = uinput_str_to_user(p, name, size); | ||
874 | goto out; | ||
835 | } | 875 | } |
836 | 876 | ||
877 | retval = -EINVAL; | ||
837 | out: | 878 | out: |
838 | mutex_unlock(&udev->mutex); | 879 | mutex_unlock(&udev->mutex); |
839 | return retval; | 880 | return retval; |
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index b6505454bcc4..7b7add5061a5 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
@@ -277,6 +277,16 @@ static struct key_entry keymap_fs_amilo_pro_v3505[] __initdata = { | |||
277 | { KE_END, 0 } | 277 | { KE_END, 0 } |
278 | }; | 278 | }; |
279 | 279 | ||
280 | static struct key_entry keymap_fs_amilo_pro_v8210[] __initdata = { | ||
281 | { KE_KEY, 0x01, {KEY_HELP} }, /* Fn+F1 */ | ||
282 | { KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Fn+F4 */ | ||
283 | { KE_BLUETOOTH, 0x30 }, /* Fn+F10 */ | ||
284 | { KE_KEY, 0x31, {KEY_MAIL} }, /* mail button */ | ||
285 | { KE_KEY, 0x36, {KEY_WWW} }, /* www button */ | ||
286 | { KE_WIFI, 0x78 }, /* satelite dish button */ | ||
287 | { KE_END, FE_WIFI_LED } | ||
288 | }; | ||
289 | |||
280 | static struct key_entry keymap_fujitsu_n3510[] __initdata = { | 290 | static struct key_entry keymap_fujitsu_n3510[] __initdata = { |
281 | { KE_KEY, 0x11, {KEY_PROG1} }, | 291 | { KE_KEY, 0x11, {KEY_PROG1} }, |
282 | { KE_KEY, 0x12, {KEY_PROG2} }, | 292 | { KE_KEY, 0x12, {KEY_PROG2} }, |
@@ -654,6 +664,15 @@ static const struct dmi_system_id dmi_ids[] __initconst = { | |||
654 | .driver_data = keymap_fs_amilo_pro_v3505 | 664 | .driver_data = keymap_fs_amilo_pro_v3505 |
655 | }, | 665 | }, |
656 | { | 666 | { |
667 | /* Fujitsu-Siemens Amilo Pro Edition V8210 */ | ||
668 | .callback = dmi_matched, | ||
669 | .matches = { | ||
670 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
671 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Series V8210"), | ||
672 | }, | ||
673 | .driver_data = keymap_fs_amilo_pro_v8210 | ||
674 | }, | ||
675 | { | ||
657 | /* Fujitsu-Siemens Amilo M7400 */ | 676 | /* Fujitsu-Siemens Amilo M7400 */ |
658 | .callback = dmi_matched, | 677 | .callback = dmi_matched, |
659 | .matches = { | 678 | .matches = { |
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 800ca7dfafc2..ef234c9b2f2f 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c | |||
@@ -48,6 +48,7 @@ struct atp_info { | |||
48 | int yfact; /* Y multiplication factor */ | 48 | int yfact; /* Y multiplication factor */ |
49 | int datalen; /* size of USB transfers */ | 49 | int datalen; /* size of USB transfers */ |
50 | void (*callback)(struct urb *); /* callback function */ | 50 | void (*callback)(struct urb *); /* callback function */ |
51 | int fuzz; /* fuzz touchpad generates */ | ||
51 | }; | 52 | }; |
52 | 53 | ||
53 | static void atp_complete_geyser_1_2(struct urb *urb); | 54 | static void atp_complete_geyser_1_2(struct urb *urb); |
@@ -61,6 +62,7 @@ static const struct atp_info fountain_info = { | |||
61 | .yfact = 43, | 62 | .yfact = 43, |
62 | .datalen = 81, | 63 | .datalen = 81, |
63 | .callback = atp_complete_geyser_1_2, | 64 | .callback = atp_complete_geyser_1_2, |
65 | .fuzz = 16, | ||
64 | }; | 66 | }; |
65 | 67 | ||
66 | static const struct atp_info geyser1_info = { | 68 | static const struct atp_info geyser1_info = { |
@@ -71,6 +73,7 @@ static const struct atp_info geyser1_info = { | |||
71 | .yfact = 43, | 73 | .yfact = 43, |
72 | .datalen = 81, | 74 | .datalen = 81, |
73 | .callback = atp_complete_geyser_1_2, | 75 | .callback = atp_complete_geyser_1_2, |
76 | .fuzz = 16, | ||
74 | }; | 77 | }; |
75 | 78 | ||
76 | static const struct atp_info geyser2_info = { | 79 | static const struct atp_info geyser2_info = { |
@@ -81,6 +84,7 @@ static const struct atp_info geyser2_info = { | |||
81 | .yfact = 43, | 84 | .yfact = 43, |
82 | .datalen = 64, | 85 | .datalen = 64, |
83 | .callback = atp_complete_geyser_1_2, | 86 | .callback = atp_complete_geyser_1_2, |
87 | .fuzz = 0, | ||
84 | }; | 88 | }; |
85 | 89 | ||
86 | static const struct atp_info geyser3_info = { | 90 | static const struct atp_info geyser3_info = { |
@@ -90,6 +94,7 @@ static const struct atp_info geyser3_info = { | |||
90 | .yfact = 64, | 94 | .yfact = 64, |
91 | .datalen = 64, | 95 | .datalen = 64, |
92 | .callback = atp_complete_geyser_3_4, | 96 | .callback = atp_complete_geyser_3_4, |
97 | .fuzz = 0, | ||
93 | }; | 98 | }; |
94 | 99 | ||
95 | static const struct atp_info geyser4_info = { | 100 | static const struct atp_info geyser4_info = { |
@@ -99,6 +104,7 @@ static const struct atp_info geyser4_info = { | |||
99 | .yfact = 64, | 104 | .yfact = 64, |
100 | .datalen = 64, | 105 | .datalen = 64, |
101 | .callback = atp_complete_geyser_3_4, | 106 | .callback = atp_complete_geyser_3_4, |
107 | .fuzz = 0, | ||
102 | }; | 108 | }; |
103 | 109 | ||
104 | #define ATP_DEVICE(prod, info) \ | 110 | #define ATP_DEVICE(prod, info) \ |
@@ -155,8 +161,11 @@ MODULE_DEVICE_TABLE(usb, atp_table); | |||
155 | #define ATP_XSENSORS 26 | 161 | #define ATP_XSENSORS 26 |
156 | #define ATP_YSENSORS 16 | 162 | #define ATP_YSENSORS 16 |
157 | 163 | ||
158 | /* amount of fuzz this touchpad generates */ | 164 | /* |
159 | #define ATP_FUZZ 16 | 165 | * The largest possible bank of sensors with additional buffer of 4 extra values |
166 | * on either side, for an array of smoothed sensor values. | ||
167 | */ | ||
168 | #define ATP_SMOOTHSIZE 34 | ||
160 | 169 | ||
161 | /* maximum pressure this driver will report */ | 170 | /* maximum pressure this driver will report */ |
162 | #define ATP_PRESSURE 300 | 171 | #define ATP_PRESSURE 300 |
@@ -165,7 +174,13 @@ MODULE_DEVICE_TABLE(usb, atp_table); | |||
165 | * Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is | 174 | * Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is |
166 | * ignored. | 175 | * ignored. |
167 | */ | 176 | */ |
168 | #define ATP_THRESHOLD 5 | 177 | #define ATP_THRESHOLD 5 |
178 | |||
179 | /* | ||
180 | * How far we'll bitshift our sensor values before averaging them. Mitigates | ||
181 | * rounding errors. | ||
182 | */ | ||
183 | #define ATP_SCALE 12 | ||
169 | 184 | ||
170 | /* Geyser initialization constants */ | 185 | /* Geyser initialization constants */ |
171 | #define ATP_GEYSER_MODE_READ_REQUEST_ID 1 | 186 | #define ATP_GEYSER_MODE_READ_REQUEST_ID 1 |
@@ -203,11 +218,14 @@ struct atp { | |||
203 | bool valid; /* are the samples valid? */ | 218 | bool valid; /* are the samples valid? */ |
204 | bool size_detect_done; | 219 | bool size_detect_done; |
205 | bool overflow_warned; | 220 | bool overflow_warned; |
221 | int fingers_old; /* last reported finger count */ | ||
206 | int x_old; /* last reported x/y, */ | 222 | int x_old; /* last reported x/y, */ |
207 | int y_old; /* used for smoothing */ | 223 | int y_old; /* used for smoothing */ |
208 | signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS]; | 224 | signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS]; |
209 | signed char xy_old[ATP_XSENSORS + ATP_YSENSORS]; | 225 | signed char xy_old[ATP_XSENSORS + ATP_YSENSORS]; |
210 | int xy_acc[ATP_XSENSORS + ATP_YSENSORS]; | 226 | int xy_acc[ATP_XSENSORS + ATP_YSENSORS]; |
227 | int smooth[ATP_SMOOTHSIZE]; | ||
228 | int smooth_tmp[ATP_SMOOTHSIZE]; | ||
211 | int idlecount; /* number of empty packets */ | 229 | int idlecount; /* number of empty packets */ |
212 | struct work_struct work; | 230 | struct work_struct work; |
213 | }; | 231 | }; |
@@ -326,10 +344,17 @@ static void atp_reinit(struct work_struct *work) | |||
326 | retval); | 344 | retval); |
327 | } | 345 | } |
328 | 346 | ||
329 | static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, | 347 | static int atp_calculate_abs(struct atp *dev, int offset, int nb_sensors, |
330 | int *z, int *fingers) | 348 | int fact, int *z, int *fingers) |
331 | { | 349 | { |
332 | int i; | 350 | int i, pass; |
351 | |||
352 | /* | ||
353 | * Use offset to point xy_sensors at the first value in dev->xy_acc | ||
354 | * for whichever dimension we're looking at this particular go-round. | ||
355 | */ | ||
356 | int *xy_sensors = dev->xy_acc + offset; | ||
357 | |||
333 | /* values to calculate mean */ | 358 | /* values to calculate mean */ |
334 | int pcum = 0, psum = 0; | 359 | int pcum = 0, psum = 0; |
335 | int is_increasing = 0; | 360 | int is_increasing = 0; |
@@ -341,9 +366,6 @@ static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, | |||
341 | if (is_increasing) | 366 | if (is_increasing) |
342 | is_increasing = 0; | 367 | is_increasing = 0; |
343 | 368 | ||
344 | continue; | ||
345 | } | ||
346 | |||
347 | /* | 369 | /* |
348 | * Makes the finger detection more versatile. For example, | 370 | * Makes the finger detection more versatile. For example, |
349 | * two fingers with no gap will be detected. Also, my | 371 | * two fingers with no gap will be detected. Also, my |
@@ -358,27 +380,63 @@ static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, | |||
358 | * | 380 | * |
359 | * - Jason Parekh <jasonparekh@gmail.com> | 381 | * - Jason Parekh <jasonparekh@gmail.com> |
360 | */ | 382 | */ |
361 | if (i < 1 || | 383 | |
384 | } else if (i < 1 || | ||
362 | (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) { | 385 | (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) { |
363 | (*fingers)++; | 386 | (*fingers)++; |
364 | is_increasing = 1; | 387 | is_increasing = 1; |
365 | } else if (i > 0 && (xy_sensors[i - 1] - xy_sensors[i] > threshold)) { | 388 | } else if (i > 0 && (xy_sensors[i - 1] - xy_sensors[i] > threshold)) { |
366 | is_increasing = 0; | 389 | is_increasing = 0; |
367 | } | 390 | } |
391 | } | ||
392 | |||
393 | if (*fingers < 1) /* No need to continue if no fingers are found. */ | ||
394 | return 0; | ||
368 | 395 | ||
396 | /* | ||
397 | * Use a smoothed version of sensor data for movement calculations, to | ||
398 | * combat noise without needing to rely so heavily on a threshold. | ||
399 | * This improves tracking. | ||
400 | * | ||
401 | * The smoothed array is bigger than the original so that the smoothing | ||
402 | * doesn't result in edge values being truncated. | ||
403 | */ | ||
404 | |||
405 | memset(dev->smooth, 0, 4 * sizeof(dev->smooth[0])); | ||
406 | /* Pull base values, scaled up to help avoid truncation errors. */ | ||
407 | for (i = 0; i < nb_sensors; i++) | ||
408 | dev->smooth[i + 4] = xy_sensors[i] << ATP_SCALE; | ||
409 | memset(&dev->smooth[nb_sensors + 4], 0, 4 * sizeof(dev->smooth[0])); | ||
410 | |||
411 | for (pass = 0; pass < 4; pass++) { | ||
412 | /* Handle edge. */ | ||
413 | dev->smooth_tmp[0] = (dev->smooth[0] + dev->smooth[1]) / 2; | ||
414 | |||
415 | /* Average values with neighbors. */ | ||
416 | for (i = 1; i < nb_sensors + 7; i++) | ||
417 | dev->smooth_tmp[i] = (dev->smooth[i - 1] + | ||
418 | dev->smooth[i] * 2 + | ||
419 | dev->smooth[i + 1]) / 4; | ||
420 | |||
421 | /* Handle other edge. */ | ||
422 | dev->smooth_tmp[i] = (dev->smooth[i - 1] + dev->smooth[i]) / 2; | ||
423 | |||
424 | memcpy(dev->smooth, dev->smooth_tmp, sizeof(dev->smooth)); | ||
425 | } | ||
426 | |||
427 | for (i = 0; i < nb_sensors + 8; i++) { | ||
369 | /* | 428 | /* |
370 | * Subtracts threshold so a high sensor that just passes the | 429 | * Skip values if they're small enough to be truncated to 0 |
371 | * threshold won't skew the calculated absolute coordinate. | 430 | * by scale. Mostly noise. |
372 | * Fixes an issue where slowly moving the mouse would | ||
373 | * occasionally jump a number of pixels (slowly moving the | ||
374 | * finger makes this issue most apparent.) | ||
375 | */ | 431 | */ |
376 | pcum += (xy_sensors[i] - threshold) * i; | 432 | if ((dev->smooth[i] >> ATP_SCALE) > 0) { |
377 | psum += (xy_sensors[i] - threshold); | 433 | pcum += dev->smooth[i] * i; |
434 | psum += dev->smooth[i]; | ||
435 | } | ||
378 | } | 436 | } |
379 | 437 | ||
380 | if (psum > 0) { | 438 | if (psum > 0) { |
381 | *z = psum; | 439 | *z = psum >> ATP_SCALE; /* Scale down pressure output. */ |
382 | return pcum * fact / psum; | 440 | return pcum * fact / psum; |
383 | } | 441 | } |
384 | 442 | ||
@@ -455,7 +513,7 @@ static void atp_detect_size(struct atp *dev) | |||
455 | input_set_abs_params(dev->input, ABS_X, 0, | 513 | input_set_abs_params(dev->input, ABS_X, 0, |
456 | (dev->info->xsensors_17 - 1) * | 514 | (dev->info->xsensors_17 - 1) * |
457 | dev->info->xfact - 1, | 515 | dev->info->xfact - 1, |
458 | ATP_FUZZ, 0); | 516 | dev->info->fuzz, 0); |
459 | break; | 517 | break; |
460 | } | 518 | } |
461 | } | 519 | } |
@@ -471,7 +529,7 @@ static void atp_complete_geyser_1_2(struct urb *urb) | |||
471 | { | 529 | { |
472 | int x, y, x_z, y_z, x_f, y_f; | 530 | int x, y, x_z, y_z, x_f, y_f; |
473 | int retval, i, j; | 531 | int retval, i, j; |
474 | int key; | 532 | int key, fingers; |
475 | struct atp *dev = urb->context; | 533 | struct atp *dev = urb->context; |
476 | int status = atp_status_check(urb); | 534 | int status = atp_status_check(urb); |
477 | 535 | ||
@@ -548,16 +606,18 @@ static void atp_complete_geyser_1_2(struct urb *urb) | |||
548 | 606 | ||
549 | dbg_dump("accumulator", dev->xy_acc); | 607 | dbg_dump("accumulator", dev->xy_acc); |
550 | 608 | ||
551 | x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS, | 609 | x = atp_calculate_abs(dev, 0, ATP_XSENSORS, |
552 | dev->info->xfact, &x_z, &x_f); | 610 | dev->info->xfact, &x_z, &x_f); |
553 | y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, | 611 | y = atp_calculate_abs(dev, ATP_XSENSORS, ATP_YSENSORS, |
554 | dev->info->yfact, &y_z, &y_f); | 612 | dev->info->yfact, &y_z, &y_f); |
555 | key = dev->data[dev->info->datalen - 1] & ATP_STATUS_BUTTON; | 613 | key = dev->data[dev->info->datalen - 1] & ATP_STATUS_BUTTON; |
556 | 614 | ||
557 | if (x && y) { | 615 | fingers = max(x_f, y_f); |
616 | |||
617 | if (x && y && fingers == dev->fingers_old) { | ||
558 | if (dev->x_old != -1) { | 618 | if (dev->x_old != -1) { |
559 | x = (dev->x_old * 3 + x) >> 2; | 619 | x = (dev->x_old * 7 + x) >> 3; |
560 | y = (dev->y_old * 3 + y) >> 2; | 620 | y = (dev->y_old * 7 + y) >> 3; |
561 | dev->x_old = x; | 621 | dev->x_old = x; |
562 | dev->y_old = y; | 622 | dev->y_old = y; |
563 | 623 | ||
@@ -571,7 +631,7 @@ static void atp_complete_geyser_1_2(struct urb *urb) | |||
571 | input_report_abs(dev->input, ABS_Y, y); | 631 | input_report_abs(dev->input, ABS_Y, y); |
572 | input_report_abs(dev->input, ABS_PRESSURE, | 632 | input_report_abs(dev->input, ABS_PRESSURE, |
573 | min(ATP_PRESSURE, x_z + y_z)); | 633 | min(ATP_PRESSURE, x_z + y_z)); |
574 | atp_report_fingers(dev->input, max(x_f, y_f)); | 634 | atp_report_fingers(dev->input, fingers); |
575 | } | 635 | } |
576 | dev->x_old = x; | 636 | dev->x_old = x; |
577 | dev->y_old = y; | 637 | dev->y_old = y; |
@@ -579,6 +639,7 @@ static void atp_complete_geyser_1_2(struct urb *urb) | |||
579 | } else if (!x && !y) { | 639 | } else if (!x && !y) { |
580 | 640 | ||
581 | dev->x_old = dev->y_old = -1; | 641 | dev->x_old = dev->y_old = -1; |
642 | dev->fingers_old = 0; | ||
582 | input_report_key(dev->input, BTN_TOUCH, 0); | 643 | input_report_key(dev->input, BTN_TOUCH, 0); |
583 | input_report_abs(dev->input, ABS_PRESSURE, 0); | 644 | input_report_abs(dev->input, ABS_PRESSURE, 0); |
584 | atp_report_fingers(dev->input, 0); | 645 | atp_report_fingers(dev->input, 0); |
@@ -587,6 +648,10 @@ static void atp_complete_geyser_1_2(struct urb *urb) | |||
587 | memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); | 648 | memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); |
588 | } | 649 | } |
589 | 650 | ||
651 | if (fingers != dev->fingers_old) | ||
652 | dev->x_old = dev->y_old = -1; | ||
653 | dev->fingers_old = fingers; | ||
654 | |||
590 | input_report_key(dev->input, BTN_LEFT, key); | 655 | input_report_key(dev->input, BTN_LEFT, key); |
591 | input_sync(dev->input); | 656 | input_sync(dev->input); |
592 | 657 | ||
@@ -604,7 +669,7 @@ static void atp_complete_geyser_3_4(struct urb *urb) | |||
604 | { | 669 | { |
605 | int x, y, x_z, y_z, x_f, y_f; | 670 | int x, y, x_z, y_z, x_f, y_f; |
606 | int retval, i, j; | 671 | int retval, i, j; |
607 | int key; | 672 | int key, fingers; |
608 | struct atp *dev = urb->context; | 673 | struct atp *dev = urb->context; |
609 | int status = atp_status_check(urb); | 674 | int status = atp_status_check(urb); |
610 | 675 | ||
@@ -660,16 +725,19 @@ static void atp_complete_geyser_3_4(struct urb *urb) | |||
660 | 725 | ||
661 | dbg_dump("accumulator", dev->xy_acc); | 726 | dbg_dump("accumulator", dev->xy_acc); |
662 | 727 | ||
663 | x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS, | 728 | x = atp_calculate_abs(dev, 0, ATP_XSENSORS, |
664 | dev->info->xfact, &x_z, &x_f); | 729 | dev->info->xfact, &x_z, &x_f); |
665 | y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, | 730 | y = atp_calculate_abs(dev, ATP_XSENSORS, ATP_YSENSORS, |
666 | dev->info->yfact, &y_z, &y_f); | 731 | dev->info->yfact, &y_z, &y_f); |
732 | |||
667 | key = dev->data[dev->info->datalen - 1] & ATP_STATUS_BUTTON; | 733 | key = dev->data[dev->info->datalen - 1] & ATP_STATUS_BUTTON; |
668 | 734 | ||
669 | if (x && y) { | 735 | fingers = max(x_f, y_f); |
736 | |||
737 | if (x && y && fingers == dev->fingers_old) { | ||
670 | if (dev->x_old != -1) { | 738 | if (dev->x_old != -1) { |
671 | x = (dev->x_old * 3 + x) >> 2; | 739 | x = (dev->x_old * 7 + x) >> 3; |
672 | y = (dev->y_old * 3 + y) >> 2; | 740 | y = (dev->y_old * 7 + y) >> 3; |
673 | dev->x_old = x; | 741 | dev->x_old = x; |
674 | dev->y_old = y; | 742 | dev->y_old = y; |
675 | 743 | ||
@@ -683,7 +751,7 @@ static void atp_complete_geyser_3_4(struct urb *urb) | |||
683 | input_report_abs(dev->input, ABS_Y, y); | 751 | input_report_abs(dev->input, ABS_Y, y); |
684 | input_report_abs(dev->input, ABS_PRESSURE, | 752 | input_report_abs(dev->input, ABS_PRESSURE, |
685 | min(ATP_PRESSURE, x_z + y_z)); | 753 | min(ATP_PRESSURE, x_z + y_z)); |
686 | atp_report_fingers(dev->input, max(x_f, y_f)); | 754 | atp_report_fingers(dev->input, fingers); |
687 | } | 755 | } |
688 | dev->x_old = x; | 756 | dev->x_old = x; |
689 | dev->y_old = y; | 757 | dev->y_old = y; |
@@ -691,6 +759,7 @@ static void atp_complete_geyser_3_4(struct urb *urb) | |||
691 | } else if (!x && !y) { | 759 | } else if (!x && !y) { |
692 | 760 | ||
693 | dev->x_old = dev->y_old = -1; | 761 | dev->x_old = dev->y_old = -1; |
762 | dev->fingers_old = 0; | ||
694 | input_report_key(dev->input, BTN_TOUCH, 0); | 763 | input_report_key(dev->input, BTN_TOUCH, 0); |
695 | input_report_abs(dev->input, ABS_PRESSURE, 0); | 764 | input_report_abs(dev->input, ABS_PRESSURE, 0); |
696 | atp_report_fingers(dev->input, 0); | 765 | atp_report_fingers(dev->input, 0); |
@@ -699,6 +768,10 @@ static void atp_complete_geyser_3_4(struct urb *urb) | |||
699 | memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); | 768 | memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); |
700 | } | 769 | } |
701 | 770 | ||
771 | if (fingers != dev->fingers_old) | ||
772 | dev->x_old = dev->y_old = -1; | ||
773 | dev->fingers_old = fingers; | ||
774 | |||
702 | input_report_key(dev->input, BTN_LEFT, key); | 775 | input_report_key(dev->input, BTN_LEFT, key); |
703 | input_sync(dev->input); | 776 | input_sync(dev->input); |
704 | 777 | ||
@@ -843,10 +916,10 @@ static int atp_probe(struct usb_interface *iface, | |||
843 | 916 | ||
844 | input_set_abs_params(input_dev, ABS_X, 0, | 917 | input_set_abs_params(input_dev, ABS_X, 0, |
845 | (dev->info->xsensors - 1) * dev->info->xfact - 1, | 918 | (dev->info->xsensors - 1) * dev->info->xfact - 1, |
846 | ATP_FUZZ, 0); | 919 | dev->info->fuzz, 0); |
847 | input_set_abs_params(input_dev, ABS_Y, 0, | 920 | input_set_abs_params(input_dev, ABS_Y, 0, |
848 | (dev->info->ysensors - 1) * dev->info->yfact - 1, | 921 | (dev->info->ysensors - 1) * dev->info->yfact - 1, |
849 | ATP_FUZZ, 0); | 922 | dev->info->fuzz, 0); |
850 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0); | 923 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0); |
851 | 924 | ||
852 | set_bit(EV_KEY, input_dev->evbit); | 925 | set_bit(EV_KEY, input_dev->evbit); |
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index aec54e283580..bc2d47431bdc 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig | |||
@@ -263,7 +263,7 @@ config SERIO_APBPS2 | |||
263 | 263 | ||
264 | config SERIO_OLPC_APSP | 264 | config SERIO_OLPC_APSP |
265 | tristate "OLPC AP-SP input support" | 265 | tristate "OLPC AP-SP input support" |
266 | depends on OF | 266 | depends on OLPC || COMPILE_TEST |
267 | help | 267 | help |
268 | Say Y here if you want support for the keyboard and touchpad included | 268 | Say Y here if you want support for the keyboard and touchpad included |
269 | in the OLPC XO-1.75 and XO-4 laptops. | 269 | in the OLPC XO-1.75 and XO-4 laptops. |
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c index d7a7e54f6465..852858e5d8d0 100644 --- a/drivers/input/serio/hp_sdc.c +++ b/drivers/input/serio/hp_sdc.c | |||
@@ -984,7 +984,7 @@ static void hp_sdc_exit(void) | |||
984 | free_irq(hp_sdc.irq, &hp_sdc); | 984 | free_irq(hp_sdc.irq, &hp_sdc); |
985 | write_unlock_irq(&hp_sdc.lock); | 985 | write_unlock_irq(&hp_sdc.lock); |
986 | 986 | ||
987 | del_timer(&hp_sdc.kicker); | 987 | del_timer_sync(&hp_sdc.kicker); |
988 | 988 | ||
989 | tasklet_kill(&hp_sdc.task); | 989 | tasklet_kill(&hp_sdc.task); |
990 | 990 | ||
diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c index caecffe8caff..858045694e9d 100644 --- a/drivers/input/tablet/gtco.c +++ b/drivers/input/tablet/gtco.c | |||
@@ -848,7 +848,7 @@ static int gtco_probe(struct usb_interface *usbinterface, | |||
848 | gtco->inputdevice = input_dev; | 848 | gtco->inputdevice = input_dev; |
849 | 849 | ||
850 | /* Save interface information */ | 850 | /* Save interface information */ |
851 | gtco->usbdev = usb_get_dev(interface_to_usbdev(usbinterface)); | 851 | gtco->usbdev = interface_to_usbdev(usbinterface); |
852 | gtco->intf = usbinterface; | 852 | gtco->intf = usbinterface; |
853 | 853 | ||
854 | /* Allocate some data for incoming reports */ | 854 | /* Allocate some data for incoming reports */ |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 07e9e82029d1..68edc9db2c64 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -514,15 +514,6 @@ config TOUCHSCREEN_MIGOR | |||
514 | To compile this driver as a module, choose M here: the | 514 | To compile this driver as a module, choose M here: the |
515 | module will be called migor_ts. | 515 | module will be called migor_ts. |
516 | 516 | ||
517 | config TOUCHSCREEN_TNETV107X | ||
518 | tristate "TI TNETV107X touchscreen support" | ||
519 | depends on ARCH_DAVINCI_TNETV107X | ||
520 | help | ||
521 | Say Y here if you want to use the TNETV107X touchscreen. | ||
522 | |||
523 | To compile this driver as a module, choose M here: the | ||
524 | module will be called tnetv107x-ts. | ||
525 | |||
526 | config TOUCHSCREEN_TOUCHRIGHT | 517 | config TOUCHSCREEN_TOUCHRIGHT |
527 | tristate "Touchright serial touchscreen" | 518 | tristate "Touchright serial touchscreen" |
528 | select SERIO | 519 | select SERIO |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 62801f213346..4bc954b7c7c3 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -56,7 +56,6 @@ obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o | |||
56 | obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o | 56 | obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o |
57 | obj-$(CONFIG_TOUCHSCREEN_SUR40) += sur40.o | 57 | obj-$(CONFIG_TOUCHSCREEN_SUR40) += sur40.o |
58 | obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o | 58 | obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o |
59 | obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o | ||
60 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o | 59 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o |
61 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o | 60 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o |
62 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o | 61 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o |
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 412a85ec9ba5..f8815bebc9ef 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c | |||
@@ -1,5 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2012 Simon Budig, <simon.budig@kernelconcepts.de> | 2 | * Copyright (C) 2012 Simon Budig, <simon.budig@kernelconcepts.de> |
3 | * Daniel Wagener <daniel.wagener@kernelconcepts.de> (M09 firmware support) | ||
4 | * Lothar Waßmann <LW@KARO-electronics.de> (DT support) | ||
3 | * | 5 | * |
4 | * This software is licensed under the terms of the GNU General Public | 6 | * This software is licensed under the terms of the GNU General Public |
5 | * License version 2, as published by the Free Software Foundation, and | 7 | * License version 2, as published by the Free Software Foundation, and |
@@ -33,6 +35,7 @@ | |||
33 | #include <linux/debugfs.h> | 35 | #include <linux/debugfs.h> |
34 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
35 | #include <linux/gpio.h> | 37 | #include <linux/gpio.h> |
38 | #include <linux/of_gpio.h> | ||
36 | #include <linux/input/mt.h> | 39 | #include <linux/input/mt.h> |
37 | #include <linux/input/edt-ft5x06.h> | 40 | #include <linux/input/edt-ft5x06.h> |
38 | 41 | ||
@@ -45,6 +48,14 @@ | |||
45 | #define WORK_REGISTER_NUM_X 0x33 | 48 | #define WORK_REGISTER_NUM_X 0x33 |
46 | #define WORK_REGISTER_NUM_Y 0x34 | 49 | #define WORK_REGISTER_NUM_Y 0x34 |
47 | 50 | ||
51 | #define M09_REGISTER_THRESHOLD 0x80 | ||
52 | #define M09_REGISTER_GAIN 0x92 | ||
53 | #define M09_REGISTER_OFFSET 0x93 | ||
54 | #define M09_REGISTER_NUM_X 0x94 | ||
55 | #define M09_REGISTER_NUM_Y 0x95 | ||
56 | |||
57 | #define NO_REGISTER 0xff | ||
58 | |||
48 | #define WORK_REGISTER_OPMODE 0x3c | 59 | #define WORK_REGISTER_OPMODE 0x3c |
49 | #define FACTORY_REGISTER_OPMODE 0x01 | 60 | #define FACTORY_REGISTER_OPMODE 0x01 |
50 | 61 | ||
@@ -59,12 +70,30 @@ | |||
59 | #define EDT_RAW_DATA_RETRIES 100 | 70 | #define EDT_RAW_DATA_RETRIES 100 |
60 | #define EDT_RAW_DATA_DELAY 1 /* msec */ | 71 | #define EDT_RAW_DATA_DELAY 1 /* msec */ |
61 | 72 | ||
73 | enum edt_ver { | ||
74 | M06, | ||
75 | M09, | ||
76 | }; | ||
77 | |||
78 | struct edt_reg_addr { | ||
79 | int reg_threshold; | ||
80 | int reg_report_rate; | ||
81 | int reg_gain; | ||
82 | int reg_offset; | ||
83 | int reg_num_x; | ||
84 | int reg_num_y; | ||
85 | }; | ||
86 | |||
62 | struct edt_ft5x06_ts_data { | 87 | struct edt_ft5x06_ts_data { |
63 | struct i2c_client *client; | 88 | struct i2c_client *client; |
64 | struct input_dev *input; | 89 | struct input_dev *input; |
65 | u16 num_x; | 90 | u16 num_x; |
66 | u16 num_y; | 91 | u16 num_y; |
67 | 92 | ||
93 | int reset_pin; | ||
94 | int irq_pin; | ||
95 | int wake_pin; | ||
96 | |||
68 | #if defined(CONFIG_DEBUG_FS) | 97 | #if defined(CONFIG_DEBUG_FS) |
69 | struct dentry *debug_dir; | 98 | struct dentry *debug_dir; |
70 | u8 *raw_buffer; | 99 | u8 *raw_buffer; |
@@ -79,6 +108,9 @@ struct edt_ft5x06_ts_data { | |||
79 | int report_rate; | 108 | int report_rate; |
80 | 109 | ||
81 | char name[EDT_NAME_LEN]; | 110 | char name[EDT_NAME_LEN]; |
111 | |||
112 | struct edt_reg_addr reg_addr; | ||
113 | enum edt_ver version; | ||
82 | }; | 114 | }; |
83 | 115 | ||
84 | static int edt_ft5x06_ts_readwrite(struct i2c_client *client, | 116 | static int edt_ft5x06_ts_readwrite(struct i2c_client *client, |
@@ -136,33 +168,58 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) | |||
136 | { | 168 | { |
137 | struct edt_ft5x06_ts_data *tsdata = dev_id; | 169 | struct edt_ft5x06_ts_data *tsdata = dev_id; |
138 | struct device *dev = &tsdata->client->dev; | 170 | struct device *dev = &tsdata->client->dev; |
139 | u8 cmd = 0xf9; | 171 | u8 cmd; |
140 | u8 rdbuf[26]; | 172 | u8 rdbuf[29]; |
141 | int i, type, x, y, id; | 173 | int i, type, x, y, id; |
174 | int offset, tplen, datalen; | ||
142 | int error; | 175 | int error; |
143 | 176 | ||
177 | switch (tsdata->version) { | ||
178 | case M06: | ||
179 | cmd = 0xf9; /* tell the controller to send touch data */ | ||
180 | offset = 5; /* where the actual touch data starts */ | ||
181 | tplen = 4; /* data comes in so called frames */ | ||
182 | datalen = 26; /* how much bytes to listen for */ | ||
183 | break; | ||
184 | |||
185 | case M09: | ||
186 | cmd = 0x02; | ||
187 | offset = 1; | ||
188 | tplen = 6; | ||
189 | datalen = 29; | ||
190 | break; | ||
191 | |||
192 | default: | ||
193 | goto out; | ||
194 | } | ||
195 | |||
144 | memset(rdbuf, 0, sizeof(rdbuf)); | 196 | memset(rdbuf, 0, sizeof(rdbuf)); |
145 | 197 | ||
146 | error = edt_ft5x06_ts_readwrite(tsdata->client, | 198 | error = edt_ft5x06_ts_readwrite(tsdata->client, |
147 | sizeof(cmd), &cmd, | 199 | sizeof(cmd), &cmd, |
148 | sizeof(rdbuf), rdbuf); | 200 | datalen, rdbuf); |
149 | if (error) { | 201 | if (error) { |
150 | dev_err_ratelimited(dev, "Unable to fetch data, error: %d\n", | 202 | dev_err_ratelimited(dev, "Unable to fetch data, error: %d\n", |
151 | error); | 203 | error); |
152 | goto out; | 204 | goto out; |
153 | } | 205 | } |
154 | 206 | ||
155 | if (rdbuf[0] != 0xaa || rdbuf[1] != 0xaa || rdbuf[2] != 26) { | 207 | /* M09 does not send header or CRC */ |
156 | dev_err_ratelimited(dev, "Unexpected header: %02x%02x%02x!\n", | 208 | if (tsdata->version == M06) { |
157 | rdbuf[0], rdbuf[1], rdbuf[2]); | 209 | if (rdbuf[0] != 0xaa || rdbuf[1] != 0xaa || |
158 | goto out; | 210 | rdbuf[2] != datalen) { |
159 | } | 211 | dev_err_ratelimited(dev, |
212 | "Unexpected header: %02x%02x%02x!\n", | ||
213 | rdbuf[0], rdbuf[1], rdbuf[2]); | ||
214 | goto out; | ||
215 | } | ||
160 | 216 | ||
161 | if (!edt_ft5x06_ts_check_crc(tsdata, rdbuf, 26)) | 217 | if (!edt_ft5x06_ts_check_crc(tsdata, rdbuf, datalen)) |
162 | goto out; | 218 | goto out; |
219 | } | ||
163 | 220 | ||
164 | for (i = 0; i < MAX_SUPPORT_POINTS; i++) { | 221 | for (i = 0; i < MAX_SUPPORT_POINTS; i++) { |
165 | u8 *buf = &rdbuf[i * 4 + 5]; | 222 | u8 *buf = &rdbuf[i * tplen + offset]; |
166 | bool down; | 223 | bool down; |
167 | 224 | ||
168 | type = buf[0] >> 6; | 225 | type = buf[0] >> 6; |
@@ -170,10 +227,14 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) | |||
170 | if (type == TOUCH_EVENT_RESERVED) | 227 | if (type == TOUCH_EVENT_RESERVED) |
171 | continue; | 228 | continue; |
172 | 229 | ||
230 | /* M06 sometimes sends bogus coordinates in TOUCH_DOWN */ | ||
231 | if (tsdata->version == M06 && type == TOUCH_EVENT_DOWN) | ||
232 | continue; | ||
233 | |||
173 | x = ((buf[0] << 8) | buf[1]) & 0x0fff; | 234 | x = ((buf[0] << 8) | buf[1]) & 0x0fff; |
174 | y = ((buf[2] << 8) | buf[3]) & 0x0fff; | 235 | y = ((buf[2] << 8) | buf[3]) & 0x0fff; |
175 | id = (buf[2] >> 4) & 0x0f; | 236 | id = (buf[2] >> 4) & 0x0f; |
176 | down = (type != TOUCH_EVENT_UP); | 237 | down = type != TOUCH_EVENT_UP; |
177 | 238 | ||
178 | input_mt_slot(tsdata->input, id); | 239 | input_mt_slot(tsdata->input, id); |
179 | input_mt_report_slot_state(tsdata->input, MT_TOOL_FINGER, down); | 240 | input_mt_report_slot_state(tsdata->input, MT_TOOL_FINGER, down); |
@@ -197,12 +258,25 @@ static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata, | |||
197 | { | 258 | { |
198 | u8 wrbuf[4]; | 259 | u8 wrbuf[4]; |
199 | 260 | ||
200 | wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; | 261 | switch (tsdata->version) { |
201 | wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; | 262 | case M06: |
202 | wrbuf[2] = value; | 263 | wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; |
203 | wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2]; | 264 | wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; |
204 | 265 | wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; | |
205 | return edt_ft5x06_ts_readwrite(tsdata->client, 4, wrbuf, 0, NULL); | 266 | wrbuf[2] = value; |
267 | wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2]; | ||
268 | return edt_ft5x06_ts_readwrite(tsdata->client, 4, | ||
269 | wrbuf, 0, NULL); | ||
270 | case M09: | ||
271 | wrbuf[0] = addr; | ||
272 | wrbuf[1] = value; | ||
273 | |||
274 | return edt_ft5x06_ts_readwrite(tsdata->client, 3, | ||
275 | wrbuf, 0, NULL); | ||
276 | |||
277 | default: | ||
278 | return -EINVAL; | ||
279 | } | ||
206 | } | 280 | } |
207 | 281 | ||
208 | static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata, | 282 | static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata, |
@@ -211,19 +285,36 @@ static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata, | |||
211 | u8 wrbuf[2], rdbuf[2]; | 285 | u8 wrbuf[2], rdbuf[2]; |
212 | int error; | 286 | int error; |
213 | 287 | ||
214 | wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; | 288 | switch (tsdata->version) { |
215 | wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; | 289 | case M06: |
216 | wrbuf[1] |= tsdata->factory_mode ? 0x80 : 0x40; | 290 | wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; |
291 | wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; | ||
292 | wrbuf[1] |= tsdata->factory_mode ? 0x80 : 0x40; | ||
217 | 293 | ||
218 | error = edt_ft5x06_ts_readwrite(tsdata->client, 2, wrbuf, 2, rdbuf); | 294 | error = edt_ft5x06_ts_readwrite(tsdata->client, 2, wrbuf, 2, |
219 | if (error) | 295 | rdbuf); |
220 | return error; | 296 | if (error) |
297 | return error; | ||
221 | 298 | ||
222 | if ((wrbuf[0] ^ wrbuf[1] ^ rdbuf[0]) != rdbuf[1]) { | 299 | if ((wrbuf[0] ^ wrbuf[1] ^ rdbuf[0]) != rdbuf[1]) { |
223 | dev_err(&tsdata->client->dev, | 300 | dev_err(&tsdata->client->dev, |
224 | "crc error: 0x%02x expected, got 0x%02x\n", | 301 | "crc error: 0x%02x expected, got 0x%02x\n", |
225 | wrbuf[0] ^ wrbuf[1] ^ rdbuf[0], rdbuf[1]); | 302 | wrbuf[0] ^ wrbuf[1] ^ rdbuf[0], |
226 | return -EIO; | 303 | rdbuf[1]); |
304 | return -EIO; | ||
305 | } | ||
306 | break; | ||
307 | |||
308 | case M09: | ||
309 | wrbuf[0] = addr; | ||
310 | error = edt_ft5x06_ts_readwrite(tsdata->client, 1, | ||
311 | wrbuf, 1, rdbuf); | ||
312 | if (error) | ||
313 | return error; | ||
314 | break; | ||
315 | |||
316 | default: | ||
317 | return -EINVAL; | ||
227 | } | 318 | } |
228 | 319 | ||
229 | return rdbuf[0]; | 320 | return rdbuf[0]; |
@@ -234,19 +325,21 @@ struct edt_ft5x06_attribute { | |||
234 | size_t field_offset; | 325 | size_t field_offset; |
235 | u8 limit_low; | 326 | u8 limit_low; |
236 | u8 limit_high; | 327 | u8 limit_high; |
237 | u8 addr; | 328 | u8 addr_m06; |
329 | u8 addr_m09; | ||
238 | }; | 330 | }; |
239 | 331 | ||
240 | #define EDT_ATTR(_field, _mode, _addr, _limit_low, _limit_high) \ | 332 | #define EDT_ATTR(_field, _mode, _addr_m06, _addr_m09, \ |
333 | _limit_low, _limit_high) \ | ||
241 | struct edt_ft5x06_attribute edt_ft5x06_attr_##_field = { \ | 334 | struct edt_ft5x06_attribute edt_ft5x06_attr_##_field = { \ |
242 | .dattr = __ATTR(_field, _mode, \ | 335 | .dattr = __ATTR(_field, _mode, \ |
243 | edt_ft5x06_setting_show, \ | 336 | edt_ft5x06_setting_show, \ |
244 | edt_ft5x06_setting_store), \ | 337 | edt_ft5x06_setting_store), \ |
245 | .field_offset = \ | 338 | .field_offset = offsetof(struct edt_ft5x06_ts_data, _field), \ |
246 | offsetof(struct edt_ft5x06_ts_data, _field), \ | 339 | .addr_m06 = _addr_m06, \ |
340 | .addr_m09 = _addr_m09, \ | ||
247 | .limit_low = _limit_low, \ | 341 | .limit_low = _limit_low, \ |
248 | .limit_high = _limit_high, \ | 342 | .limit_high = _limit_high, \ |
249 | .addr = _addr, \ | ||
250 | } | 343 | } |
251 | 344 | ||
252 | static ssize_t edt_ft5x06_setting_show(struct device *dev, | 345 | static ssize_t edt_ft5x06_setting_show(struct device *dev, |
@@ -257,10 +350,11 @@ static ssize_t edt_ft5x06_setting_show(struct device *dev, | |||
257 | struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); | 350 | struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); |
258 | struct edt_ft5x06_attribute *attr = | 351 | struct edt_ft5x06_attribute *attr = |
259 | container_of(dattr, struct edt_ft5x06_attribute, dattr); | 352 | container_of(dattr, struct edt_ft5x06_attribute, dattr); |
260 | u8 *field = (u8 *)((char *)tsdata + attr->field_offset); | 353 | u8 *field = (u8 *)tsdata + attr->field_offset; |
261 | int val; | 354 | int val; |
262 | size_t count = 0; | 355 | size_t count = 0; |
263 | int error = 0; | 356 | int error = 0; |
357 | u8 addr; | ||
264 | 358 | ||
265 | mutex_lock(&tsdata->mutex); | 359 | mutex_lock(&tsdata->mutex); |
266 | 360 | ||
@@ -269,15 +363,33 @@ static ssize_t edt_ft5x06_setting_show(struct device *dev, | |||
269 | goto out; | 363 | goto out; |
270 | } | 364 | } |
271 | 365 | ||
272 | val = edt_ft5x06_register_read(tsdata, attr->addr); | 366 | switch (tsdata->version) { |
273 | if (val < 0) { | 367 | case M06: |
274 | error = val; | 368 | addr = attr->addr_m06; |
275 | dev_err(&tsdata->client->dev, | 369 | break; |
276 | "Failed to fetch attribute %s, error %d\n", | 370 | |
277 | dattr->attr.name, error); | 371 | case M09: |
372 | addr = attr->addr_m09; | ||
373 | break; | ||
374 | |||
375 | default: | ||
376 | error = -ENODEV; | ||
278 | goto out; | 377 | goto out; |
279 | } | 378 | } |
280 | 379 | ||
380 | if (addr != NO_REGISTER) { | ||
381 | val = edt_ft5x06_register_read(tsdata, addr); | ||
382 | if (val < 0) { | ||
383 | error = val; | ||
384 | dev_err(&tsdata->client->dev, | ||
385 | "Failed to fetch attribute %s, error %d\n", | ||
386 | dattr->attr.name, error); | ||
387 | goto out; | ||
388 | } | ||
389 | } else { | ||
390 | val = *field; | ||
391 | } | ||
392 | |||
281 | if (val != *field) { | 393 | if (val != *field) { |
282 | dev_warn(&tsdata->client->dev, | 394 | dev_warn(&tsdata->client->dev, |
283 | "%s: read (%d) and stored value (%d) differ\n", | 395 | "%s: read (%d) and stored value (%d) differ\n", |
@@ -299,9 +411,10 @@ static ssize_t edt_ft5x06_setting_store(struct device *dev, | |||
299 | struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); | 411 | struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); |
300 | struct edt_ft5x06_attribute *attr = | 412 | struct edt_ft5x06_attribute *attr = |
301 | container_of(dattr, struct edt_ft5x06_attribute, dattr); | 413 | container_of(dattr, struct edt_ft5x06_attribute, dattr); |
302 | u8 *field = (u8 *)((char *)tsdata + attr->field_offset); | 414 | u8 *field = (u8 *)tsdata + attr->field_offset; |
303 | unsigned int val; | 415 | unsigned int val; |
304 | int error; | 416 | int error; |
417 | u8 addr; | ||
305 | 418 | ||
306 | mutex_lock(&tsdata->mutex); | 419 | mutex_lock(&tsdata->mutex); |
307 | 420 | ||
@@ -319,14 +432,29 @@ static ssize_t edt_ft5x06_setting_store(struct device *dev, | |||
319 | goto out; | 432 | goto out; |
320 | } | 433 | } |
321 | 434 | ||
322 | error = edt_ft5x06_register_write(tsdata, attr->addr, val); | 435 | switch (tsdata->version) { |
323 | if (error) { | 436 | case M06: |
324 | dev_err(&tsdata->client->dev, | 437 | addr = attr->addr_m06; |
325 | "Failed to update attribute %s, error: %d\n", | 438 | break; |
326 | dattr->attr.name, error); | 439 | |
440 | case M09: | ||
441 | addr = attr->addr_m09; | ||
442 | break; | ||
443 | |||
444 | default: | ||
445 | error = -ENODEV; | ||
327 | goto out; | 446 | goto out; |
328 | } | 447 | } |
329 | 448 | ||
449 | if (addr != NO_REGISTER) { | ||
450 | error = edt_ft5x06_register_write(tsdata, addr, val); | ||
451 | if (error) { | ||
452 | dev_err(&tsdata->client->dev, | ||
453 | "Failed to update attribute %s, error: %d\n", | ||
454 | dattr->attr.name, error); | ||
455 | goto out; | ||
456 | } | ||
457 | } | ||
330 | *field = val; | 458 | *field = val; |
331 | 459 | ||
332 | out: | 460 | out: |
@@ -334,12 +462,14 @@ out: | |||
334 | return error ?: count; | 462 | return error ?: count; |
335 | } | 463 | } |
336 | 464 | ||
337 | static EDT_ATTR(gain, S_IWUSR | S_IRUGO, WORK_REGISTER_GAIN, 0, 31); | 465 | static EDT_ATTR(gain, S_IWUSR | S_IRUGO, WORK_REGISTER_GAIN, |
338 | static EDT_ATTR(offset, S_IWUSR | S_IRUGO, WORK_REGISTER_OFFSET, 0, 31); | 466 | M09_REGISTER_GAIN, 0, 31); |
339 | static EDT_ATTR(threshold, S_IWUSR | S_IRUGO, | 467 | static EDT_ATTR(offset, S_IWUSR | S_IRUGO, WORK_REGISTER_OFFSET, |
340 | WORK_REGISTER_THRESHOLD, 20, 80); | 468 | M09_REGISTER_OFFSET, 0, 31); |
341 | static EDT_ATTR(report_rate, S_IWUSR | S_IRUGO, | 469 | static EDT_ATTR(threshold, S_IWUSR | S_IRUGO, WORK_REGISTER_THRESHOLD, |
342 | WORK_REGISTER_REPORT_RATE, 3, 14); | 470 | M09_REGISTER_THRESHOLD, 20, 80); |
471 | static EDT_ATTR(report_rate, S_IWUSR | S_IRUGO, WORK_REGISTER_REPORT_RATE, | ||
472 | NO_REGISTER, 3, 14); | ||
343 | 473 | ||
344 | static struct attribute *edt_ft5x06_attrs[] = { | 474 | static struct attribute *edt_ft5x06_attrs[] = { |
345 | &edt_ft5x06_attr_gain.dattr.attr, | 475 | &edt_ft5x06_attr_gain.dattr.attr, |
@@ -374,6 +504,9 @@ static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata) | |||
374 | } | 504 | } |
375 | 505 | ||
376 | /* mode register is 0x3c when in the work mode */ | 506 | /* mode register is 0x3c when in the work mode */ |
507 | if (tsdata->version == M09) | ||
508 | goto m09_out; | ||
509 | |||
377 | error = edt_ft5x06_register_write(tsdata, WORK_REGISTER_OPMODE, 0x03); | 510 | error = edt_ft5x06_register_write(tsdata, WORK_REGISTER_OPMODE, 0x03); |
378 | if (error) { | 511 | if (error) { |
379 | dev_err(&client->dev, | 512 | dev_err(&client->dev, |
@@ -406,12 +539,18 @@ err_out: | |||
406 | enable_irq(client->irq); | 539 | enable_irq(client->irq); |
407 | 540 | ||
408 | return error; | 541 | return error; |
542 | |||
543 | m09_out: | ||
544 | dev_err(&client->dev, "No factory mode support for M09\n"); | ||
545 | return -EINVAL; | ||
546 | |||
409 | } | 547 | } |
410 | 548 | ||
411 | static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata) | 549 | static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata) |
412 | { | 550 | { |
413 | struct i2c_client *client = tsdata->client; | 551 | struct i2c_client *client = tsdata->client; |
414 | int retries = EDT_SWITCH_MODE_RETRIES; | 552 | int retries = EDT_SWITCH_MODE_RETRIES; |
553 | struct edt_reg_addr *reg_addr = &tsdata->reg_addr; | ||
415 | int ret; | 554 | int ret; |
416 | int error; | 555 | int error; |
417 | 556 | ||
@@ -444,13 +583,14 @@ static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata) | |||
444 | tsdata->raw_buffer = NULL; | 583 | tsdata->raw_buffer = NULL; |
445 | 584 | ||
446 | /* restore parameters */ | 585 | /* restore parameters */ |
447 | edt_ft5x06_register_write(tsdata, WORK_REGISTER_THRESHOLD, | 586 | edt_ft5x06_register_write(tsdata, reg_addr->reg_threshold, |
448 | tsdata->threshold); | 587 | tsdata->threshold); |
449 | edt_ft5x06_register_write(tsdata, WORK_REGISTER_GAIN, | 588 | edt_ft5x06_register_write(tsdata, reg_addr->reg_gain, |
450 | tsdata->gain); | 589 | tsdata->gain); |
451 | edt_ft5x06_register_write(tsdata, WORK_REGISTER_OFFSET, | 590 | edt_ft5x06_register_write(tsdata, reg_addr->reg_offset, |
452 | tsdata->offset); | 591 | tsdata->offset); |
453 | edt_ft5x06_register_write(tsdata, WORK_REGISTER_REPORT_RATE, | 592 | if (reg_addr->reg_report_rate) |
593 | edt_ft5x06_register_write(tsdata, reg_addr->reg_report_rate, | ||
454 | tsdata->report_rate); | 594 | tsdata->report_rate); |
455 | 595 | ||
456 | enable_irq(client->irq); | 596 | enable_irq(client->irq); |
@@ -479,7 +619,7 @@ static int edt_ft5x06_debugfs_mode_set(void *data, u64 mode) | |||
479 | 619 | ||
480 | if (mode != tsdata->factory_mode) { | 620 | if (mode != tsdata->factory_mode) { |
481 | retval = mode ? edt_ft5x06_factory_mode(tsdata) : | 621 | retval = mode ? edt_ft5x06_factory_mode(tsdata) : |
482 | edt_ft5x06_work_mode(tsdata); | 622 | edt_ft5x06_work_mode(tsdata); |
483 | } | 623 | } |
484 | 624 | ||
485 | mutex_unlock(&tsdata->mutex); | 625 | mutex_unlock(&tsdata->mutex); |
@@ -568,7 +708,6 @@ out: | |||
568 | return error ?: read; | 708 | return error ?: read; |
569 | }; | 709 | }; |
570 | 710 | ||
571 | |||
572 | static const struct file_operations debugfs_raw_data_fops = { | 711 | static const struct file_operations debugfs_raw_data_fops = { |
573 | .open = simple_open, | 712 | .open = simple_open, |
574 | .read = edt_ft5x06_debugfs_raw_data_read, | 713 | .read = edt_ft5x06_debugfs_raw_data_read, |
@@ -614,58 +753,100 @@ edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata) | |||
614 | 753 | ||
615 | #endif /* CONFIG_DEBUGFS */ | 754 | #endif /* CONFIG_DEBUGFS */ |
616 | 755 | ||
617 | |||
618 | |||
619 | static int edt_ft5x06_ts_reset(struct i2c_client *client, | 756 | static int edt_ft5x06_ts_reset(struct i2c_client *client, |
620 | int reset_pin) | 757 | struct edt_ft5x06_ts_data *tsdata) |
621 | { | 758 | { |
622 | int error; | 759 | int error; |
623 | 760 | ||
624 | if (gpio_is_valid(reset_pin)) { | 761 | if (gpio_is_valid(tsdata->wake_pin)) { |
762 | error = devm_gpio_request_one(&client->dev, | ||
763 | tsdata->wake_pin, GPIOF_OUT_INIT_LOW, | ||
764 | "edt-ft5x06 wake"); | ||
765 | if (error) { | ||
766 | dev_err(&client->dev, | ||
767 | "Failed to request GPIO %d as wake pin, error %d\n", | ||
768 | tsdata->wake_pin, error); | ||
769 | return error; | ||
770 | } | ||
771 | |||
772 | msleep(5); | ||
773 | gpio_set_value(tsdata->wake_pin, 1); | ||
774 | } | ||
775 | if (gpio_is_valid(tsdata->reset_pin)) { | ||
625 | /* this pulls reset down, enabling the low active reset */ | 776 | /* this pulls reset down, enabling the low active reset */ |
626 | error = devm_gpio_request_one(&client->dev, reset_pin, | 777 | error = devm_gpio_request_one(&client->dev, |
627 | GPIOF_OUT_INIT_LOW, | 778 | tsdata->reset_pin, GPIOF_OUT_INIT_LOW, |
628 | "edt-ft5x06 reset"); | 779 | "edt-ft5x06 reset"); |
629 | if (error) { | 780 | if (error) { |
630 | dev_err(&client->dev, | 781 | dev_err(&client->dev, |
631 | "Failed to request GPIO %d as reset pin, error %d\n", | 782 | "Failed to request GPIO %d as reset pin, error %d\n", |
632 | reset_pin, error); | 783 | tsdata->reset_pin, error); |
633 | return error; | 784 | return error; |
634 | } | 785 | } |
635 | 786 | ||
636 | mdelay(50); | 787 | msleep(5); |
637 | gpio_set_value(reset_pin, 1); | 788 | gpio_set_value(tsdata->reset_pin, 1); |
638 | mdelay(100); | 789 | msleep(300); |
639 | } | 790 | } |
640 | 791 | ||
641 | return 0; | 792 | return 0; |
642 | } | 793 | } |
643 | 794 | ||
644 | static int edt_ft5x06_ts_identify(struct i2c_client *client, | 795 | static int edt_ft5x06_ts_identify(struct i2c_client *client, |
645 | char *model_name, | 796 | struct edt_ft5x06_ts_data *tsdata, |
646 | char *fw_version) | 797 | char *fw_version) |
647 | { | 798 | { |
648 | u8 rdbuf[EDT_NAME_LEN]; | 799 | u8 rdbuf[EDT_NAME_LEN]; |
649 | char *p; | 800 | char *p; |
650 | int error; | 801 | int error; |
802 | char *model_name = tsdata->name; | ||
651 | 803 | ||
804 | /* see what we find if we assume it is a M06 * | ||
805 | * if we get less than EDT_NAME_LEN, we don't want | ||
806 | * to have garbage in there | ||
807 | */ | ||
808 | memset(rdbuf, 0, sizeof(rdbuf)); | ||
652 | error = edt_ft5x06_ts_readwrite(client, 1, "\xbb", | 809 | error = edt_ft5x06_ts_readwrite(client, 1, "\xbb", |
653 | EDT_NAME_LEN - 1, rdbuf); | 810 | EDT_NAME_LEN - 1, rdbuf); |
654 | if (error) | 811 | if (error) |
655 | return error; | 812 | return error; |
656 | 813 | ||
657 | /* remove last '$' end marker */ | 814 | /* if we find something consistent, stay with that assumption |
658 | rdbuf[EDT_NAME_LEN - 1] = '\0'; | 815 | * at least M09 won't send 3 bytes here |
659 | if (rdbuf[EDT_NAME_LEN - 2] == '$') | 816 | */ |
660 | rdbuf[EDT_NAME_LEN - 2] = '\0'; | 817 | if (!(strnicmp(rdbuf + 1, "EP0", 3))) { |
818 | tsdata->version = M06; | ||
819 | |||
820 | /* remove last '$' end marker */ | ||
821 | rdbuf[EDT_NAME_LEN - 1] = '\0'; | ||
822 | if (rdbuf[EDT_NAME_LEN - 2] == '$') | ||
823 | rdbuf[EDT_NAME_LEN - 2] = '\0'; | ||
824 | |||
825 | /* look for Model/Version separator */ | ||
826 | p = strchr(rdbuf, '*'); | ||
827 | if (p) | ||
828 | *p++ = '\0'; | ||
829 | strlcpy(model_name, rdbuf + 1, EDT_NAME_LEN); | ||
830 | strlcpy(fw_version, p ? p : "", EDT_NAME_LEN); | ||
831 | } else { | ||
832 | /* since there are only two versions around (M06, M09) */ | ||
833 | tsdata->version = M09; | ||
834 | |||
835 | error = edt_ft5x06_ts_readwrite(client, 1, "\xA6", | ||
836 | 2, rdbuf); | ||
837 | if (error) | ||
838 | return error; | ||
839 | |||
840 | strlcpy(fw_version, rdbuf, 2); | ||
661 | 841 | ||
662 | /* look for Model/Version separator */ | 842 | error = edt_ft5x06_ts_readwrite(client, 1, "\xA8", |
663 | p = strchr(rdbuf, '*'); | 843 | 1, rdbuf); |
664 | if (p) | 844 | if (error) |
665 | *p++ = '\0'; | 845 | return error; |
666 | 846 | ||
667 | strlcpy(model_name, rdbuf + 1, EDT_NAME_LEN); | 847 | snprintf(model_name, EDT_NAME_LEN, "EP0%i%i0M09", |
668 | strlcpy(fw_version, p ? p : "", EDT_NAME_LEN); | 848 | rdbuf[0] >> 4, rdbuf[0] & 0x0F); |
849 | } | ||
669 | 850 | ||
670 | return 0; | 851 | return 0; |
671 | } | 852 | } |
@@ -675,33 +856,104 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client, | |||
675 | pdata->name <= edt_ft5x06_attr_##name.limit_high) \ | 856 | pdata->name <= edt_ft5x06_attr_##name.limit_high) \ |
676 | edt_ft5x06_register_write(tsdata, reg, pdata->name) | 857 | edt_ft5x06_register_write(tsdata, reg, pdata->name) |
677 | 858 | ||
859 | #define EDT_GET_PROP(name, reg) { \ | ||
860 | u32 val; \ | ||
861 | if (of_property_read_u32(np, #name, &val) == 0) \ | ||
862 | edt_ft5x06_register_write(tsdata, reg, val); \ | ||
863 | } | ||
864 | |||
865 | static void edt_ft5x06_ts_get_dt_defaults(struct device_node *np, | ||
866 | struct edt_ft5x06_ts_data *tsdata) | ||
867 | { | ||
868 | struct edt_reg_addr *reg_addr = &tsdata->reg_addr; | ||
869 | |||
870 | EDT_GET_PROP(threshold, reg_addr->reg_threshold); | ||
871 | EDT_GET_PROP(gain, reg_addr->reg_gain); | ||
872 | EDT_GET_PROP(offset, reg_addr->reg_offset); | ||
873 | } | ||
874 | |||
678 | static void | 875 | static void |
679 | edt_ft5x06_ts_get_defaults(struct edt_ft5x06_ts_data *tsdata, | 876 | edt_ft5x06_ts_get_defaults(struct edt_ft5x06_ts_data *tsdata, |
680 | const struct edt_ft5x06_platform_data *pdata) | 877 | const struct edt_ft5x06_platform_data *pdata) |
681 | { | 878 | { |
879 | struct edt_reg_addr *reg_addr = &tsdata->reg_addr; | ||
880 | |||
682 | if (!pdata->use_parameters) | 881 | if (!pdata->use_parameters) |
683 | return; | 882 | return; |
684 | 883 | ||
685 | /* pick up defaults from the platform data */ | 884 | /* pick up defaults from the platform data */ |
686 | EDT_ATTR_CHECKSET(threshold, WORK_REGISTER_THRESHOLD); | 885 | EDT_ATTR_CHECKSET(threshold, reg_addr->reg_threshold); |
687 | EDT_ATTR_CHECKSET(gain, WORK_REGISTER_GAIN); | 886 | EDT_ATTR_CHECKSET(gain, reg_addr->reg_gain); |
688 | EDT_ATTR_CHECKSET(offset, WORK_REGISTER_OFFSET); | 887 | EDT_ATTR_CHECKSET(offset, reg_addr->reg_offset); |
689 | EDT_ATTR_CHECKSET(report_rate, WORK_REGISTER_REPORT_RATE); | 888 | if (reg_addr->reg_report_rate != NO_REGISTER) |
889 | EDT_ATTR_CHECKSET(report_rate, reg_addr->reg_report_rate); | ||
690 | } | 890 | } |
691 | 891 | ||
692 | static void | 892 | static void |
693 | edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata) | 893 | edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata) |
694 | { | 894 | { |
895 | struct edt_reg_addr *reg_addr = &tsdata->reg_addr; | ||
896 | |||
695 | tsdata->threshold = edt_ft5x06_register_read(tsdata, | 897 | tsdata->threshold = edt_ft5x06_register_read(tsdata, |
696 | WORK_REGISTER_THRESHOLD); | 898 | reg_addr->reg_threshold); |
697 | tsdata->gain = edt_ft5x06_register_read(tsdata, WORK_REGISTER_GAIN); | 899 | tsdata->gain = edt_ft5x06_register_read(tsdata, reg_addr->reg_gain); |
698 | tsdata->offset = edt_ft5x06_register_read(tsdata, WORK_REGISTER_OFFSET); | 900 | tsdata->offset = edt_ft5x06_register_read(tsdata, reg_addr->reg_offset); |
699 | tsdata->report_rate = edt_ft5x06_register_read(tsdata, | 901 | if (reg_addr->reg_report_rate != NO_REGISTER) |
700 | WORK_REGISTER_REPORT_RATE); | 902 | tsdata->report_rate = edt_ft5x06_register_read(tsdata, |
701 | tsdata->num_x = edt_ft5x06_register_read(tsdata, WORK_REGISTER_NUM_X); | 903 | reg_addr->reg_report_rate); |
702 | tsdata->num_y = edt_ft5x06_register_read(tsdata, WORK_REGISTER_NUM_Y); | 904 | tsdata->num_x = edt_ft5x06_register_read(tsdata, reg_addr->reg_num_x); |
905 | tsdata->num_y = edt_ft5x06_register_read(tsdata, reg_addr->reg_num_y); | ||
906 | } | ||
907 | |||
908 | static void | ||
909 | edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata) | ||
910 | { | ||
911 | struct edt_reg_addr *reg_addr = &tsdata->reg_addr; | ||
912 | |||
913 | switch (tsdata->version) { | ||
914 | case M06: | ||
915 | reg_addr->reg_threshold = WORK_REGISTER_THRESHOLD; | ||
916 | reg_addr->reg_report_rate = WORK_REGISTER_REPORT_RATE; | ||
917 | reg_addr->reg_gain = WORK_REGISTER_GAIN; | ||
918 | reg_addr->reg_offset = WORK_REGISTER_OFFSET; | ||
919 | reg_addr->reg_num_x = WORK_REGISTER_NUM_X; | ||
920 | reg_addr->reg_num_y = WORK_REGISTER_NUM_Y; | ||
921 | break; | ||
922 | |||
923 | case M09: | ||
924 | reg_addr->reg_threshold = M09_REGISTER_THRESHOLD; | ||
925 | reg_addr->reg_gain = M09_REGISTER_GAIN; | ||
926 | reg_addr->reg_offset = M09_REGISTER_OFFSET; | ||
927 | reg_addr->reg_num_x = M09_REGISTER_NUM_X; | ||
928 | reg_addr->reg_num_y = M09_REGISTER_NUM_Y; | ||
929 | break; | ||
930 | } | ||
703 | } | 931 | } |
704 | 932 | ||
933 | #ifdef CONFIG_OF | ||
934 | static int edt_ft5x06_i2c_ts_probe_dt(struct device *dev, | ||
935 | struct edt_ft5x06_ts_data *tsdata) | ||
936 | { | ||
937 | struct device_node *np = dev->of_node; | ||
938 | |||
939 | /* | ||
940 | * irq_pin is not needed for DT setup. | ||
941 | * irq is associated via 'interrupts' property in DT | ||
942 | */ | ||
943 | tsdata->irq_pin = -EINVAL; | ||
944 | tsdata->reset_pin = of_get_named_gpio(np, "reset-gpios", 0); | ||
945 | tsdata->wake_pin = of_get_named_gpio(np, "wake-gpios", 0); | ||
946 | |||
947 | return 0; | ||
948 | } | ||
949 | #else | ||
950 | static inline int edt_ft5x06_i2c_ts_probe_dt(struct device *dev, | ||
951 | struct edt_ft5x06_ts_data *tsdata) | ||
952 | { | ||
953 | return -ENODEV; | ||
954 | } | ||
955 | #endif | ||
956 | |||
705 | static int edt_ft5x06_ts_probe(struct i2c_client *client, | 957 | static int edt_ft5x06_ts_probe(struct i2c_client *client, |
706 | const struct i2c_device_id *id) | 958 | const struct i2c_device_id *id) |
707 | { | 959 | { |
@@ -714,32 +966,40 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, | |||
714 | 966 | ||
715 | dev_dbg(&client->dev, "probing for EDT FT5x06 I2C\n"); | 967 | dev_dbg(&client->dev, "probing for EDT FT5x06 I2C\n"); |
716 | 968 | ||
969 | tsdata = devm_kzalloc(&client->dev, sizeof(*tsdata), GFP_KERNEL); | ||
970 | if (!tsdata) { | ||
971 | dev_err(&client->dev, "failed to allocate driver data.\n"); | ||
972 | return -ENOMEM; | ||
973 | } | ||
974 | |||
717 | if (!pdata) { | 975 | if (!pdata) { |
718 | dev_err(&client->dev, "no platform data?\n"); | 976 | error = edt_ft5x06_i2c_ts_probe_dt(&client->dev, tsdata); |
719 | return -EINVAL; | 977 | if (error) { |
978 | dev_err(&client->dev, | ||
979 | "DT probe failed and no platform data present\n"); | ||
980 | return error; | ||
981 | } | ||
982 | } else { | ||
983 | tsdata->reset_pin = pdata->reset_pin; | ||
984 | tsdata->irq_pin = pdata->irq_pin; | ||
985 | tsdata->wake_pin = -EINVAL; | ||
720 | } | 986 | } |
721 | 987 | ||
722 | error = edt_ft5x06_ts_reset(client, pdata->reset_pin); | 988 | error = edt_ft5x06_ts_reset(client, tsdata); |
723 | if (error) | 989 | if (error) |
724 | return error; | 990 | return error; |
725 | 991 | ||
726 | if (gpio_is_valid(pdata->irq_pin)) { | 992 | if (gpio_is_valid(tsdata->irq_pin)) { |
727 | error = devm_gpio_request_one(&client->dev, pdata->irq_pin, | 993 | error = devm_gpio_request_one(&client->dev, tsdata->irq_pin, |
728 | GPIOF_IN, "edt-ft5x06 irq"); | 994 | GPIOF_IN, "edt-ft5x06 irq"); |
729 | if (error) { | 995 | if (error) { |
730 | dev_err(&client->dev, | 996 | dev_err(&client->dev, |
731 | "Failed to request GPIO %d, error %d\n", | 997 | "Failed to request GPIO %d, error %d\n", |
732 | pdata->irq_pin, error); | 998 | tsdata->irq_pin, error); |
733 | return error; | 999 | return error; |
734 | } | 1000 | } |
735 | } | 1001 | } |
736 | 1002 | ||
737 | tsdata = devm_kzalloc(&client->dev, sizeof(*tsdata), GFP_KERNEL); | ||
738 | if (!tsdata) { | ||
739 | dev_err(&client->dev, "failed to allocate driver data.\n"); | ||
740 | return -ENOMEM; | ||
741 | } | ||
742 | |||
743 | input = devm_input_allocate_device(&client->dev); | 1003 | input = devm_input_allocate_device(&client->dev); |
744 | if (!input) { | 1004 | if (!input) { |
745 | dev_err(&client->dev, "failed to allocate input device.\n"); | 1005 | dev_err(&client->dev, "failed to allocate input device.\n"); |
@@ -751,13 +1011,19 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, | |||
751 | tsdata->input = input; | 1011 | tsdata->input = input; |
752 | tsdata->factory_mode = false; | 1012 | tsdata->factory_mode = false; |
753 | 1013 | ||
754 | error = edt_ft5x06_ts_identify(client, tsdata->name, fw_version); | 1014 | error = edt_ft5x06_ts_identify(client, tsdata, fw_version); |
755 | if (error) { | 1015 | if (error) { |
756 | dev_err(&client->dev, "touchscreen probe failed\n"); | 1016 | dev_err(&client->dev, "touchscreen probe failed\n"); |
757 | return error; | 1017 | return error; |
758 | } | 1018 | } |
759 | 1019 | ||
760 | edt_ft5x06_ts_get_defaults(tsdata, pdata); | 1020 | edt_ft5x06_ts_set_regs(tsdata); |
1021 | |||
1022 | if (!pdata) | ||
1023 | edt_ft5x06_ts_get_dt_defaults(client->dev.of_node, tsdata); | ||
1024 | else | ||
1025 | edt_ft5x06_ts_get_defaults(tsdata, pdata); | ||
1026 | |||
761 | edt_ft5x06_ts_get_parameters(tsdata); | 1027 | edt_ft5x06_ts_get_parameters(tsdata); |
762 | 1028 | ||
763 | dev_dbg(&client->dev, | 1029 | dev_dbg(&client->dev, |
@@ -787,10 +1053,10 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, | |||
787 | input_set_drvdata(input, tsdata); | 1053 | input_set_drvdata(input, tsdata); |
788 | i2c_set_clientdata(client, tsdata); | 1054 | i2c_set_clientdata(client, tsdata); |
789 | 1055 | ||
790 | error = devm_request_threaded_irq(&client->dev, client->irq, | 1056 | error = devm_request_threaded_irq(&client->dev, client->irq, NULL, |
791 | NULL, edt_ft5x06_ts_isr, | 1057 | edt_ft5x06_ts_isr, |
792 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | 1058 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, |
793 | client->name, tsdata); | 1059 | client->name, tsdata); |
794 | if (error) { | 1060 | if (error) { |
795 | dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); | 1061 | dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); |
796 | return error; | 1062 | return error; |
@@ -801,19 +1067,21 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, | |||
801 | return error; | 1067 | return error; |
802 | 1068 | ||
803 | error = input_register_device(input); | 1069 | error = input_register_device(input); |
804 | if (error) { | 1070 | if (error) |
805 | sysfs_remove_group(&client->dev.kobj, &edt_ft5x06_attr_group); | 1071 | goto err_remove_attrs; |
806 | return error; | ||
807 | } | ||
808 | 1072 | ||
809 | edt_ft5x06_ts_prepare_debugfs(tsdata, dev_driver_string(&client->dev)); | 1073 | edt_ft5x06_ts_prepare_debugfs(tsdata, dev_driver_string(&client->dev)); |
810 | device_init_wakeup(&client->dev, 1); | 1074 | device_init_wakeup(&client->dev, 1); |
811 | 1075 | ||
812 | dev_dbg(&client->dev, | 1076 | dev_dbg(&client->dev, |
813 | "EDT FT5x06 initialized: IRQ pin %d, Reset pin %d.\n", | 1077 | "EDT FT5x06 initialized: IRQ %d, WAKE pin %d, Reset pin %d.\n", |
814 | pdata->irq_pin, pdata->reset_pin); | 1078 | client->irq, tsdata->wake_pin, tsdata->reset_pin); |
815 | 1079 | ||
816 | return 0; | 1080 | return 0; |
1081 | |||
1082 | err_remove_attrs: | ||
1083 | sysfs_remove_group(&client->dev.kobj, &edt_ft5x06_attr_group); | ||
1084 | return error; | ||
817 | } | 1085 | } |
818 | 1086 | ||
819 | static int edt_ft5x06_ts_remove(struct i2c_client *client) | 1087 | static int edt_ft5x06_ts_remove(struct i2c_client *client) |
@@ -852,15 +1120,26 @@ static SIMPLE_DEV_PM_OPS(edt_ft5x06_ts_pm_ops, | |||
852 | edt_ft5x06_ts_suspend, edt_ft5x06_ts_resume); | 1120 | edt_ft5x06_ts_suspend, edt_ft5x06_ts_resume); |
853 | 1121 | ||
854 | static const struct i2c_device_id edt_ft5x06_ts_id[] = { | 1122 | static const struct i2c_device_id edt_ft5x06_ts_id[] = { |
855 | { "edt-ft5x06", 0 }, | 1123 | { "edt-ft5x06", 0, }, |
856 | { } | 1124 | { /* sentinel */ } |
857 | }; | 1125 | }; |
858 | MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id); | 1126 | MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id); |
859 | 1127 | ||
1128 | #ifdef CONFIG_OF | ||
1129 | static const struct of_device_id edt_ft5x06_of_match[] = { | ||
1130 | { .compatible = "edt,edt-ft5206", }, | ||
1131 | { .compatible = "edt,edt-ft5306", }, | ||
1132 | { .compatible = "edt,edt-ft5406", }, | ||
1133 | { /* sentinel */ } | ||
1134 | }; | ||
1135 | MODULE_DEVICE_TABLE(of, edt_ft5x06_of_match); | ||
1136 | #endif | ||
1137 | |||
860 | static struct i2c_driver edt_ft5x06_ts_driver = { | 1138 | static struct i2c_driver edt_ft5x06_ts_driver = { |
861 | .driver = { | 1139 | .driver = { |
862 | .owner = THIS_MODULE, | 1140 | .owner = THIS_MODULE, |
863 | .name = "edt_ft5x06", | 1141 | .name = "edt_ft5x06", |
1142 | .of_match_table = of_match_ptr(edt_ft5x06_of_match), | ||
864 | .pm = &edt_ft5x06_ts_pm_ops, | 1143 | .pm = &edt_ft5x06_ts_pm_ops, |
865 | }, | 1144 | }, |
866 | .id_table = edt_ft5x06_ts_id, | 1145 | .id_table = edt_ft5x06_ts_id, |
diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c deleted file mode 100644 index c47827a26e3c..000000000000 --- a/drivers/input/touchscreen/tnetv107x-ts.c +++ /dev/null | |||
@@ -1,384 +0,0 @@ | |||
1 | /* | ||
2 | * Texas Instruments TNETV107X Touchscreen Driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Texas Instruments | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation version 2. | ||
9 | * | ||
10 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
11 | * kind, whether express or implied; without even the implied warranty | ||
12 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/err.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/input.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/ctype.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/clk.h> | ||
28 | |||
29 | #include <mach/tnetv107x.h> | ||
30 | |||
31 | #define TSC_PENUP_POLL (HZ / 5) | ||
32 | #define IDLE_TIMEOUT 100 /* msec */ | ||
33 | |||
34 | /* | ||
35 | * The first and last samples of a touch interval are usually garbage and need | ||
36 | * to be filtered out with these devices. The following definitions control | ||
37 | * the number of samples skipped. | ||
38 | */ | ||
39 | #define TSC_HEAD_SKIP 1 | ||
40 | #define TSC_TAIL_SKIP 1 | ||
41 | #define TSC_SKIP (TSC_HEAD_SKIP + TSC_TAIL_SKIP + 1) | ||
42 | #define TSC_SAMPLES (TSC_SKIP + 1) | ||
43 | |||
44 | /* Register Offsets */ | ||
45 | struct tsc_regs { | ||
46 | u32 rev; | ||
47 | u32 tscm; | ||
48 | u32 bwcm; | ||
49 | u32 swc; | ||
50 | u32 adcchnl; | ||
51 | u32 adcdata; | ||
52 | u32 chval[4]; | ||
53 | }; | ||
54 | |||
55 | /* TSC Mode Configuration Register (tscm) bits */ | ||
56 | #define WMODE BIT(0) | ||
57 | #define TSKIND BIT(1) | ||
58 | #define ZMEASURE_EN BIT(2) | ||
59 | #define IDLE BIT(3) | ||
60 | #define TSC_EN BIT(4) | ||
61 | #define STOP BIT(5) | ||
62 | #define ONE_SHOT BIT(6) | ||
63 | #define SINGLE BIT(7) | ||
64 | #define AVG BIT(8) | ||
65 | #define AVGNUM(x) (((x) & 0x03) << 9) | ||
66 | #define PVSTC(x) (((x) & 0x07) << 11) | ||
67 | #define PON BIT(14) | ||
68 | #define PONBG BIT(15) | ||
69 | #define AFERST BIT(16) | ||
70 | |||
71 | /* ADC DATA Capture Register bits */ | ||
72 | #define DATA_VALID BIT(16) | ||
73 | |||
74 | /* Register Access Macros */ | ||
75 | #define tsc_read(ts, reg) __raw_readl(&(ts)->regs->reg) | ||
76 | #define tsc_write(ts, reg, val) __raw_writel(val, &(ts)->regs->reg); | ||
77 | #define tsc_set_bits(ts, reg, val) \ | ||
78 | tsc_write(ts, reg, tsc_read(ts, reg) | (val)) | ||
79 | #define tsc_clr_bits(ts, reg, val) \ | ||
80 | tsc_write(ts, reg, tsc_read(ts, reg) & ~(val)) | ||
81 | |||
82 | struct sample { | ||
83 | int x, y, p; | ||
84 | }; | ||
85 | |||
86 | struct tsc_data { | ||
87 | struct input_dev *input_dev; | ||
88 | struct resource *res; | ||
89 | struct tsc_regs __iomem *regs; | ||
90 | struct timer_list timer; | ||
91 | spinlock_t lock; | ||
92 | struct clk *clk; | ||
93 | struct device *dev; | ||
94 | int sample_count; | ||
95 | struct sample samples[TSC_SAMPLES]; | ||
96 | int tsc_irq; | ||
97 | }; | ||
98 | |||
99 | static int tsc_read_sample(struct tsc_data *ts, struct sample* sample) | ||
100 | { | ||
101 | int x, y, z1, z2, t, p = 0; | ||
102 | u32 val; | ||
103 | |||
104 | val = tsc_read(ts, chval[0]); | ||
105 | if (val & DATA_VALID) | ||
106 | x = val & 0xffff; | ||
107 | else | ||
108 | return -EINVAL; | ||
109 | |||
110 | y = tsc_read(ts, chval[1]) & 0xffff; | ||
111 | z1 = tsc_read(ts, chval[2]) & 0xffff; | ||
112 | z2 = tsc_read(ts, chval[3]) & 0xffff; | ||
113 | |||
114 | if (z1) { | ||
115 | t = ((600 * x) * (z2 - z1)); | ||
116 | p = t / (u32) (z1 << 12); | ||
117 | if (p < 0) | ||
118 | p = 0; | ||
119 | } | ||
120 | |||
121 | sample->x = x; | ||
122 | sample->y = y; | ||
123 | sample->p = p; | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | static void tsc_poll(unsigned long data) | ||
129 | { | ||
130 | struct tsc_data *ts = (struct tsc_data *)data; | ||
131 | unsigned long flags; | ||
132 | int i, val, x, y, p; | ||
133 | |||
134 | spin_lock_irqsave(&ts->lock, flags); | ||
135 | |||
136 | if (ts->sample_count >= TSC_SKIP) { | ||
137 | input_report_abs(ts->input_dev, ABS_PRESSURE, 0); | ||
138 | input_report_key(ts->input_dev, BTN_TOUCH, 0); | ||
139 | input_sync(ts->input_dev); | ||
140 | } else if (ts->sample_count > 0) { | ||
141 | /* | ||
142 | * A touch event lasted less than our skip count. Salvage and | ||
143 | * report anyway. | ||
144 | */ | ||
145 | for (i = 0, val = 0; i < ts->sample_count; i++) | ||
146 | val += ts->samples[i].x; | ||
147 | x = val / ts->sample_count; | ||
148 | |||
149 | for (i = 0, val = 0; i < ts->sample_count; i++) | ||
150 | val += ts->samples[i].y; | ||
151 | y = val / ts->sample_count; | ||
152 | |||
153 | for (i = 0, val = 0; i < ts->sample_count; i++) | ||
154 | val += ts->samples[i].p; | ||
155 | p = val / ts->sample_count; | ||
156 | |||
157 | input_report_abs(ts->input_dev, ABS_X, x); | ||
158 | input_report_abs(ts->input_dev, ABS_Y, y); | ||
159 | input_report_abs(ts->input_dev, ABS_PRESSURE, p); | ||
160 | input_report_key(ts->input_dev, BTN_TOUCH, 1); | ||
161 | input_sync(ts->input_dev); | ||
162 | } | ||
163 | |||
164 | ts->sample_count = 0; | ||
165 | |||
166 | spin_unlock_irqrestore(&ts->lock, flags); | ||
167 | } | ||
168 | |||
169 | static irqreturn_t tsc_irq(int irq, void *dev_id) | ||
170 | { | ||
171 | struct tsc_data *ts = (struct tsc_data *)dev_id; | ||
172 | struct sample *sample; | ||
173 | int index; | ||
174 | |||
175 | spin_lock(&ts->lock); | ||
176 | |||
177 | index = ts->sample_count % TSC_SAMPLES; | ||
178 | sample = &ts->samples[index]; | ||
179 | if (tsc_read_sample(ts, sample) < 0) | ||
180 | goto out; | ||
181 | |||
182 | if (++ts->sample_count >= TSC_SKIP) { | ||
183 | index = (ts->sample_count - TSC_TAIL_SKIP - 1) % TSC_SAMPLES; | ||
184 | sample = &ts->samples[index]; | ||
185 | |||
186 | input_report_abs(ts->input_dev, ABS_X, sample->x); | ||
187 | input_report_abs(ts->input_dev, ABS_Y, sample->y); | ||
188 | input_report_abs(ts->input_dev, ABS_PRESSURE, sample->p); | ||
189 | if (ts->sample_count == TSC_SKIP) | ||
190 | input_report_key(ts->input_dev, BTN_TOUCH, 1); | ||
191 | input_sync(ts->input_dev); | ||
192 | } | ||
193 | mod_timer(&ts->timer, jiffies + TSC_PENUP_POLL); | ||
194 | out: | ||
195 | spin_unlock(&ts->lock); | ||
196 | return IRQ_HANDLED; | ||
197 | } | ||
198 | |||
199 | static int tsc_start(struct input_dev *dev) | ||
200 | { | ||
201 | struct tsc_data *ts = input_get_drvdata(dev); | ||
202 | unsigned long timeout = jiffies + msecs_to_jiffies(IDLE_TIMEOUT); | ||
203 | u32 val; | ||
204 | |||
205 | clk_enable(ts->clk); | ||
206 | |||
207 | /* Go to idle mode, before any initialization */ | ||
208 | while (time_after(timeout, jiffies)) { | ||
209 | if (tsc_read(ts, tscm) & IDLE) | ||
210 | break; | ||
211 | } | ||
212 | |||
213 | if (time_before(timeout, jiffies)) { | ||
214 | dev_warn(ts->dev, "timeout waiting for idle\n"); | ||
215 | clk_disable(ts->clk); | ||
216 | return -EIO; | ||
217 | } | ||
218 | |||
219 | /* Configure TSC Control register*/ | ||
220 | val = (PONBG | PON | PVSTC(4) | ONE_SHOT | ZMEASURE_EN); | ||
221 | tsc_write(ts, tscm, val); | ||
222 | |||
223 | /* Bring TSC out of reset: Clear AFE reset bit */ | ||
224 | val &= ~(AFERST); | ||
225 | tsc_write(ts, tscm, val); | ||
226 | |||
227 | /* Configure all pins for hardware control*/ | ||
228 | tsc_write(ts, bwcm, 0); | ||
229 | |||
230 | /* Finally enable the TSC */ | ||
231 | tsc_set_bits(ts, tscm, TSC_EN); | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static void tsc_stop(struct input_dev *dev) | ||
237 | { | ||
238 | struct tsc_data *ts = input_get_drvdata(dev); | ||
239 | |||
240 | tsc_clr_bits(ts, tscm, TSC_EN); | ||
241 | synchronize_irq(ts->tsc_irq); | ||
242 | del_timer_sync(&ts->timer); | ||
243 | clk_disable(ts->clk); | ||
244 | } | ||
245 | |||
246 | static int tsc_probe(struct platform_device *pdev) | ||
247 | { | ||
248 | struct device *dev = &pdev->dev; | ||
249 | struct tsc_data *ts; | ||
250 | int error = 0; | ||
251 | u32 rev = 0; | ||
252 | |||
253 | ts = kzalloc(sizeof(struct tsc_data), GFP_KERNEL); | ||
254 | if (!ts) { | ||
255 | dev_err(dev, "cannot allocate device info\n"); | ||
256 | return -ENOMEM; | ||
257 | } | ||
258 | |||
259 | ts->dev = dev; | ||
260 | spin_lock_init(&ts->lock); | ||
261 | setup_timer(&ts->timer, tsc_poll, (unsigned long)ts); | ||
262 | platform_set_drvdata(pdev, ts); | ||
263 | |||
264 | ts->tsc_irq = platform_get_irq(pdev, 0); | ||
265 | if (ts->tsc_irq < 0) { | ||
266 | dev_err(dev, "cannot determine device interrupt\n"); | ||
267 | error = -ENODEV; | ||
268 | goto error_res; | ||
269 | } | ||
270 | |||
271 | ts->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
272 | if (!ts->res) { | ||
273 | dev_err(dev, "cannot determine register area\n"); | ||
274 | error = -ENODEV; | ||
275 | goto error_res; | ||
276 | } | ||
277 | |||
278 | if (!request_mem_region(ts->res->start, resource_size(ts->res), | ||
279 | pdev->name)) { | ||
280 | dev_err(dev, "cannot claim register memory\n"); | ||
281 | ts->res = NULL; | ||
282 | error = -EINVAL; | ||
283 | goto error_res; | ||
284 | } | ||
285 | |||
286 | ts->regs = ioremap(ts->res->start, resource_size(ts->res)); | ||
287 | if (!ts->regs) { | ||
288 | dev_err(dev, "cannot map register memory\n"); | ||
289 | error = -ENOMEM; | ||
290 | goto error_map; | ||
291 | } | ||
292 | |||
293 | ts->clk = clk_get(dev, NULL); | ||
294 | if (IS_ERR(ts->clk)) { | ||
295 | dev_err(dev, "cannot claim device clock\n"); | ||
296 | error = PTR_ERR(ts->clk); | ||
297 | goto error_clk; | ||
298 | } | ||
299 | |||
300 | error = request_threaded_irq(ts->tsc_irq, NULL, tsc_irq, IRQF_ONESHOT, | ||
301 | dev_name(dev), ts); | ||
302 | if (error < 0) { | ||
303 | dev_err(ts->dev, "Could not allocate ts irq\n"); | ||
304 | goto error_irq; | ||
305 | } | ||
306 | |||
307 | ts->input_dev = input_allocate_device(); | ||
308 | if (!ts->input_dev) { | ||
309 | dev_err(dev, "cannot allocate input device\n"); | ||
310 | error = -ENOMEM; | ||
311 | goto error_input; | ||
312 | } | ||
313 | input_set_drvdata(ts->input_dev, ts); | ||
314 | |||
315 | ts->input_dev->name = pdev->name; | ||
316 | ts->input_dev->id.bustype = BUS_HOST; | ||
317 | ts->input_dev->dev.parent = &pdev->dev; | ||
318 | ts->input_dev->open = tsc_start; | ||
319 | ts->input_dev->close = tsc_stop; | ||
320 | |||
321 | clk_enable(ts->clk); | ||
322 | rev = tsc_read(ts, rev); | ||
323 | ts->input_dev->id.product = ((rev >> 8) & 0x07); | ||
324 | ts->input_dev->id.version = ((rev >> 16) & 0xfff); | ||
325 | clk_disable(ts->clk); | ||
326 | |||
327 | __set_bit(EV_KEY, ts->input_dev->evbit); | ||
328 | __set_bit(EV_ABS, ts->input_dev->evbit); | ||
329 | __set_bit(BTN_TOUCH, ts->input_dev->keybit); | ||
330 | |||
331 | input_set_abs_params(ts->input_dev, ABS_X, 0, 0xffff, 5, 0); | ||
332 | input_set_abs_params(ts->input_dev, ABS_Y, 0, 0xffff, 5, 0); | ||
333 | input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 4095, 128, 0); | ||
334 | |||
335 | error = input_register_device(ts->input_dev); | ||
336 | if (error < 0) { | ||
337 | dev_err(dev, "failed input device registration\n"); | ||
338 | goto error_reg; | ||
339 | } | ||
340 | |||
341 | return 0; | ||
342 | |||
343 | error_reg: | ||
344 | input_free_device(ts->input_dev); | ||
345 | error_input: | ||
346 | free_irq(ts->tsc_irq, ts); | ||
347 | error_irq: | ||
348 | clk_put(ts->clk); | ||
349 | error_clk: | ||
350 | iounmap(ts->regs); | ||
351 | error_map: | ||
352 | release_mem_region(ts->res->start, resource_size(ts->res)); | ||
353 | error_res: | ||
354 | kfree(ts); | ||
355 | |||
356 | return error; | ||
357 | } | ||
358 | |||
359 | static int tsc_remove(struct platform_device *pdev) | ||
360 | { | ||
361 | struct tsc_data *ts = platform_get_drvdata(pdev); | ||
362 | |||
363 | input_unregister_device(ts->input_dev); | ||
364 | free_irq(ts->tsc_irq, ts); | ||
365 | clk_put(ts->clk); | ||
366 | iounmap(ts->regs); | ||
367 | release_mem_region(ts->res->start, resource_size(ts->res)); | ||
368 | kfree(ts); | ||
369 | |||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | static struct platform_driver tsc_driver = { | ||
374 | .probe = tsc_probe, | ||
375 | .remove = tsc_remove, | ||
376 | .driver.name = "tnetv107x-ts", | ||
377 | .driver.owner = THIS_MODULE, | ||
378 | }; | ||
379 | module_platform_driver(tsc_driver); | ||
380 | |||
381 | MODULE_AUTHOR("Cyril Chemparathy"); | ||
382 | MODULE_DESCRIPTION("TNETV107X Touchscreen Driver"); | ||
383 | MODULE_ALIAS("platform:tnetv107x-ts"); | ||
384 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c index 2175f3419002..01d30cedde46 100644 --- a/drivers/input/touchscreen/zforce_ts.c +++ b/drivers/input/touchscreen/zforce_ts.c | |||
@@ -29,10 +29,13 @@ | |||
29 | #include <linux/sysfs.h> | 29 | #include <linux/sysfs.h> |
30 | #include <linux/input/mt.h> | 30 | #include <linux/input/mt.h> |
31 | #include <linux/platform_data/zforce_ts.h> | 31 | #include <linux/platform_data/zforce_ts.h> |
32 | #include <linux/of.h> | ||
33 | #include <linux/of_gpio.h> | ||
32 | 34 | ||
33 | #define WAIT_TIMEOUT msecs_to_jiffies(1000) | 35 | #define WAIT_TIMEOUT msecs_to_jiffies(1000) |
34 | 36 | ||
35 | #define FRAME_START 0xee | 37 | #define FRAME_START 0xee |
38 | #define FRAME_MAXSIZE 257 | ||
36 | 39 | ||
37 | /* Offsets of the different parts of the payload the controller sends */ | 40 | /* Offsets of the different parts of the payload the controller sends */ |
38 | #define PAYLOAD_HEADER 0 | 41 | #define PAYLOAD_HEADER 0 |
@@ -64,7 +67,7 @@ | |||
64 | #define RESPONSE_STATUS 0X1e | 67 | #define RESPONSE_STATUS 0X1e |
65 | 68 | ||
66 | /* | 69 | /* |
67 | * Notifications are send by the touch controller without | 70 | * Notifications are sent by the touch controller without |
68 | * being requested by the driver and include for example | 71 | * being requested by the driver and include for example |
69 | * touch indications | 72 | * touch indications |
70 | */ | 73 | */ |
@@ -103,8 +106,8 @@ struct zforce_point { | |||
103 | * @suspended device suspended | 106 | * @suspended device suspended |
104 | * @access_mutex serialize i2c-access, to keep multipart reads together | 107 | * @access_mutex serialize i2c-access, to keep multipart reads together |
105 | * @command_done completion to wait for the command result | 108 | * @command_done completion to wait for the command result |
106 | * @command_mutex serialize commands send to the ic | 109 | * @command_mutex serialize commands sent to the ic |
107 | * @command_waiting the id of the command that that is currently waiting | 110 | * @command_waiting the id of the command that is currently waiting |
108 | * for a result | 111 | * for a result |
109 | * @command_result returned result of the command | 112 | * @command_result returned result of the command |
110 | */ | 113 | */ |
@@ -235,7 +238,8 @@ static int zforce_scan_frequency(struct zforce_ts *ts, u16 idle, u16 finger, | |||
235 | (finger & 0xff), ((finger >> 8) & 0xff), | 238 | (finger & 0xff), ((finger >> 8) & 0xff), |
236 | (stylus & 0xff), ((stylus >> 8) & 0xff) }; | 239 | (stylus & 0xff), ((stylus >> 8) & 0xff) }; |
237 | 240 | ||
238 | dev_dbg(&client->dev, "set scan frequency to (idle: %d, finger: %d, stylus: %d)\n", | 241 | dev_dbg(&client->dev, |
242 | "set scan frequency to (idle: %d, finger: %d, stylus: %d)\n", | ||
239 | idle, finger, stylus); | 243 | idle, finger, stylus); |
240 | 244 | ||
241 | return zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf)); | 245 | return zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf)); |
@@ -255,7 +259,7 @@ static int zforce_setconfig(struct zforce_ts *ts, char b1) | |||
255 | static int zforce_start(struct zforce_ts *ts) | 259 | static int zforce_start(struct zforce_ts *ts) |
256 | { | 260 | { |
257 | struct i2c_client *client = ts->client; | 261 | struct i2c_client *client = ts->client; |
258 | const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev); | 262 | const struct zforce_ts_platdata *pdata = ts->pdata; |
259 | int ret; | 263 | int ret; |
260 | 264 | ||
261 | dev_dbg(&client->dev, "starting device\n"); | 265 | dev_dbg(&client->dev, "starting device\n"); |
@@ -326,13 +330,14 @@ static int zforce_stop(struct zforce_ts *ts) | |||
326 | static int zforce_touch_event(struct zforce_ts *ts, u8 *payload) | 330 | static int zforce_touch_event(struct zforce_ts *ts, u8 *payload) |
327 | { | 331 | { |
328 | struct i2c_client *client = ts->client; | 332 | struct i2c_client *client = ts->client; |
329 | const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev); | 333 | const struct zforce_ts_platdata *pdata = ts->pdata; |
330 | struct zforce_point point; | 334 | struct zforce_point point; |
331 | int count, i, num = 0; | 335 | int count, i, num = 0; |
332 | 336 | ||
333 | count = payload[0]; | 337 | count = payload[0]; |
334 | if (count > ZFORCE_REPORT_POINTS) { | 338 | if (count > ZFORCE_REPORT_POINTS) { |
335 | dev_warn(&client->dev, "to many coordinates %d, expected max %d\n", | 339 | dev_warn(&client->dev, |
340 | "too many coordinates %d, expected max %d\n", | ||
336 | count, ZFORCE_REPORT_POINTS); | 341 | count, ZFORCE_REPORT_POINTS); |
337 | count = ZFORCE_REPORT_POINTS; | 342 | count = ZFORCE_REPORT_POINTS; |
338 | } | 343 | } |
@@ -421,7 +426,7 @@ static int zforce_read_packet(struct zforce_ts *ts, u8 *buf) | |||
421 | goto unlock; | 426 | goto unlock; |
422 | } | 427 | } |
423 | 428 | ||
424 | if (buf[PAYLOAD_LENGTH] <= 0 || buf[PAYLOAD_LENGTH] > 255) { | 429 | if (buf[PAYLOAD_LENGTH] == 0) { |
425 | dev_err(&client->dev, "invalid payload length: %d\n", | 430 | dev_err(&client->dev, "invalid payload length: %d\n", |
426 | buf[PAYLOAD_LENGTH]); | 431 | buf[PAYLOAD_LENGTH]); |
427 | ret = -EIO; | 432 | ret = -EIO; |
@@ -471,9 +476,9 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id) | |||
471 | { | 476 | { |
472 | struct zforce_ts *ts = dev_id; | 477 | struct zforce_ts *ts = dev_id; |
473 | struct i2c_client *client = ts->client; | 478 | struct i2c_client *client = ts->client; |
474 | const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev); | 479 | const struct zforce_ts_platdata *pdata = ts->pdata; |
475 | int ret; | 480 | int ret; |
476 | u8 payload_buffer[512]; | 481 | u8 payload_buffer[FRAME_MAXSIZE]; |
477 | u8 *payload; | 482 | u8 *payload; |
478 | 483 | ||
479 | /* | 484 | /* |
@@ -494,8 +499,8 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id) | |||
494 | while (!gpio_get_value(pdata->gpio_int)) { | 499 | while (!gpio_get_value(pdata->gpio_int)) { |
495 | ret = zforce_read_packet(ts, payload_buffer); | 500 | ret = zforce_read_packet(ts, payload_buffer); |
496 | if (ret < 0) { | 501 | if (ret < 0) { |
497 | dev_err(&client->dev, "could not read packet, ret: %d\n", | 502 | dev_err(&client->dev, |
498 | ret); | 503 | "could not read packet, ret: %d\n", ret); |
499 | break; | 504 | break; |
500 | } | 505 | } |
501 | 506 | ||
@@ -539,7 +544,8 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id) | |||
539 | payload[RESPONSE_DATA + 4]; | 544 | payload[RESPONSE_DATA + 4]; |
540 | ts->version_rev = (payload[RESPONSE_DATA + 7] << 8) | | 545 | ts->version_rev = (payload[RESPONSE_DATA + 7] << 8) | |
541 | payload[RESPONSE_DATA + 6]; | 546 | payload[RESPONSE_DATA + 6]; |
542 | dev_dbg(&ts->client->dev, "Firmware Version %04x:%04x %04x:%04x\n", | 547 | dev_dbg(&ts->client->dev, |
548 | "Firmware Version %04x:%04x %04x:%04x\n", | ||
543 | ts->version_major, ts->version_minor, | 549 | ts->version_major, ts->version_minor, |
544 | ts->version_build, ts->version_rev); | 550 | ts->version_build, ts->version_rev); |
545 | 551 | ||
@@ -552,7 +558,8 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id) | |||
552 | break; | 558 | break; |
553 | 559 | ||
554 | default: | 560 | default: |
555 | dev_err(&ts->client->dev, "unrecognized response id: 0x%x\n", | 561 | dev_err(&ts->client->dev, |
562 | "unrecognized response id: 0x%x\n", | ||
556 | payload[RESPONSE_ID]); | 563 | payload[RESPONSE_ID]); |
557 | break; | 564 | break; |
558 | } | 565 | } |
@@ -618,7 +625,8 @@ static int zforce_suspend(struct device *dev) | |||
618 | 625 | ||
619 | enable_irq_wake(client->irq); | 626 | enable_irq_wake(client->irq); |
620 | } else if (input->users) { | 627 | } else if (input->users) { |
621 | dev_dbg(&client->dev, "suspend without being a wakeup source\n"); | 628 | dev_dbg(&client->dev, |
629 | "suspend without being a wakeup source\n"); | ||
622 | 630 | ||
623 | ret = zforce_stop(ts); | 631 | ret = zforce_stop(ts); |
624 | if (ret) | 632 | if (ret) |
@@ -684,6 +692,45 @@ static void zforce_reset(void *data) | |||
684 | gpio_set_value(ts->pdata->gpio_rst, 0); | 692 | gpio_set_value(ts->pdata->gpio_rst, 0); |
685 | } | 693 | } |
686 | 694 | ||
695 | static struct zforce_ts_platdata *zforce_parse_dt(struct device *dev) | ||
696 | { | ||
697 | struct zforce_ts_platdata *pdata; | ||
698 | struct device_node *np = dev->of_node; | ||
699 | |||
700 | if (!np) | ||
701 | return ERR_PTR(-ENOENT); | ||
702 | |||
703 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
704 | if (!pdata) { | ||
705 | dev_err(dev, "failed to allocate platform data\n"); | ||
706 | return ERR_PTR(-ENOMEM); | ||
707 | } | ||
708 | |||
709 | pdata->gpio_int = of_get_gpio(np, 0); | ||
710 | if (!gpio_is_valid(pdata->gpio_int)) { | ||
711 | dev_err(dev, "failed to get interrupt gpio\n"); | ||
712 | return ERR_PTR(-EINVAL); | ||
713 | } | ||
714 | |||
715 | pdata->gpio_rst = of_get_gpio(np, 1); | ||
716 | if (!gpio_is_valid(pdata->gpio_rst)) { | ||
717 | dev_err(dev, "failed to get reset gpio\n"); | ||
718 | return ERR_PTR(-EINVAL); | ||
719 | } | ||
720 | |||
721 | if (of_property_read_u32(np, "x-size", &pdata->x_max)) { | ||
722 | dev_err(dev, "failed to get x-size property\n"); | ||
723 | return ERR_PTR(-EINVAL); | ||
724 | } | ||
725 | |||
726 | if (of_property_read_u32(np, "y-size", &pdata->y_max)) { | ||
727 | dev_err(dev, "failed to get y-size property\n"); | ||
728 | return ERR_PTR(-EINVAL); | ||
729 | } | ||
730 | |||
731 | return pdata; | ||
732 | } | ||
733 | |||
687 | static int zforce_probe(struct i2c_client *client, | 734 | static int zforce_probe(struct i2c_client *client, |
688 | const struct i2c_device_id *id) | 735 | const struct i2c_device_id *id) |
689 | { | 736 | { |
@@ -692,8 +739,11 @@ static int zforce_probe(struct i2c_client *client, | |||
692 | struct input_dev *input_dev; | 739 | struct input_dev *input_dev; |
693 | int ret; | 740 | int ret; |
694 | 741 | ||
695 | if (!pdata) | 742 | if (!pdata) { |
696 | return -EINVAL; | 743 | pdata = zforce_parse_dt(&client->dev); |
744 | if (IS_ERR(pdata)) | ||
745 | return PTR_ERR(pdata); | ||
746 | } | ||
697 | 747 | ||
698 | ts = devm_kzalloc(&client->dev, sizeof(struct zforce_ts), GFP_KERNEL); | 748 | ts = devm_kzalloc(&client->dev, sizeof(struct zforce_ts), GFP_KERNEL); |
699 | if (!ts) | 749 | if (!ts) |
@@ -798,7 +848,7 @@ static int zforce_probe(struct i2c_client *client, | |||
798 | return ret; | 848 | return ret; |
799 | } | 849 | } |
800 | 850 | ||
801 | /* this gets the firmware version among other informations */ | 851 | /* this gets the firmware version among other information */ |
802 | ret = zforce_command_wait(ts, COMMAND_STATUS); | 852 | ret = zforce_command_wait(ts, COMMAND_STATUS); |
803 | if (ret < 0) { | 853 | if (ret < 0) { |
804 | dev_err(&client->dev, "couldn't get status, %d\n", ret); | 854 | dev_err(&client->dev, "couldn't get status, %d\n", ret); |
@@ -829,11 +879,20 @@ static struct i2c_device_id zforce_idtable[] = { | |||
829 | }; | 879 | }; |
830 | MODULE_DEVICE_TABLE(i2c, zforce_idtable); | 880 | MODULE_DEVICE_TABLE(i2c, zforce_idtable); |
831 | 881 | ||
882 | #ifdef CONFIG_OF | ||
883 | static struct of_device_id zforce_dt_idtable[] = { | ||
884 | { .compatible = "neonode,zforce" }, | ||
885 | {}, | ||
886 | }; | ||
887 | MODULE_DEVICE_TABLE(of, zforce_dt_idtable); | ||
888 | #endif | ||
889 | |||
832 | static struct i2c_driver zforce_driver = { | 890 | static struct i2c_driver zforce_driver = { |
833 | .driver = { | 891 | .driver = { |
834 | .owner = THIS_MODULE, | 892 | .owner = THIS_MODULE, |
835 | .name = "zforce-ts", | 893 | .name = "zforce-ts", |
836 | .pm = &zforce_pm_ops, | 894 | .pm = &zforce_pm_ops, |
895 | .of_match_table = of_match_ptr(zforce_dt_idtable), | ||
837 | }, | 896 | }, |
838 | .probe = zforce_probe, | 897 | .probe = zforce_probe, |
839 | .id_table = zforce_idtable, | 898 | .id_table = zforce_idtable, |