diff options
-rw-r--r-- | arch/arm/mach-w90x900/include/mach/w90p910_keypad.h | 5 | ||||
-rw-r--r-- | drivers/input/keyboard/w90p910_keypad.c | 144 |
2 files changed, 66 insertions, 83 deletions
diff --git a/arch/arm/mach-w90x900/include/mach/w90p910_keypad.h b/arch/arm/mach-w90x900/include/mach/w90p910_keypad.h index 79462faaa189..556778e8ddaa 100644 --- a/arch/arm/mach-w90x900/include/mach/w90p910_keypad.h +++ b/arch/arm/mach-w90x900/include/mach/w90p910_keypad.h | |||
@@ -6,13 +6,10 @@ | |||
6 | extern void mfp_set_groupi(struct device *dev); | 6 | extern void mfp_set_groupi(struct device *dev); |
7 | 7 | ||
8 | struct w90p910_keypad_platform_data { | 8 | struct w90p910_keypad_platform_data { |
9 | const struct matrix_keymap_data *keymap_data; | ||
9 | 10 | ||
10 | unsigned int prescale; | 11 | unsigned int prescale; |
11 | unsigned int debounce; | 12 | unsigned int debounce; |
12 | unsigned int matrix_key_rows; | ||
13 | unsigned int matrix_key_cols; | ||
14 | unsigned int *matrix_key_map; | ||
15 | int matrix_key_map_size; | ||
16 | }; | 13 | }; |
17 | 14 | ||
18 | #endif /* __ASM_ARCH_W90P910_KEYPAD_H */ | 15 | #endif /* __ASM_ARCH_W90P910_KEYPAD_H */ |
diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c index 472c70514af0..24096cdfcb6f 100644 --- a/drivers/input/keyboard/w90p910_keypad.c +++ b/drivers/input/keyboard/w90p910_keypad.c | |||
@@ -41,58 +41,34 @@ | |||
41 | #define KGET_RAW(n) (((n) & KEY0R) >> 3) | 41 | #define KGET_RAW(n) (((n) & KEY0R) >> 3) |
42 | #define KGET_COLUMN(n) ((n) & KEY0C) | 42 | #define KGET_COLUMN(n) ((n) & KEY0C) |
43 | 43 | ||
44 | #define MAX_MATRIX_KEY_NUM (8 * 8) | 44 | #define W90P910_MAX_KEY_NUM (8 * 8) |
45 | #define W90P910_ROW_SHIFT 3 | ||
45 | 46 | ||
46 | struct w90p910_keypad { | 47 | struct w90p910_keypad { |
47 | struct w90p910_keypad_platform_data *pdata; | 48 | const struct w90p910_keypad_platform_data *pdata; |
48 | struct clk *clk; | 49 | struct clk *clk; |
49 | struct input_dev *input_dev; | 50 | struct input_dev *input_dev; |
50 | void __iomem *mmio_base; | 51 | void __iomem *mmio_base; |
51 | int irq; | 52 | int irq; |
52 | unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM]; | 53 | unsigned short keymap[W90P910_MAX_KEY_NUM]; |
53 | }; | 54 | }; |
54 | 55 | ||
55 | static void w90p910_keypad_build_keycode(struct w90p910_keypad *keypad) | ||
56 | { | ||
57 | struct w90p910_keypad_platform_data *pdata = keypad->pdata; | ||
58 | struct input_dev *input_dev = keypad->input_dev; | ||
59 | unsigned int *key; | ||
60 | int i; | ||
61 | |||
62 | key = &pdata->matrix_key_map[0]; | ||
63 | for (i = 0; i < pdata->matrix_key_map_size; i++, key++) { | ||
64 | int row = KEY_ROW(*key); | ||
65 | int col = KEY_COL(*key); | ||
66 | int code = KEY_VAL(*key); | ||
67 | |||
68 | keypad->matrix_keycodes[(row << 3) + col] = code; | ||
69 | __set_bit(code, input_dev->keybit); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | static inline unsigned int lookup_matrix_keycode( | ||
74 | struct w90p910_keypad *keypad, int row, int col) | ||
75 | { | ||
76 | return keypad->matrix_keycodes[(row << 3) + col]; | ||
77 | } | ||
78 | |||
79 | static void w90p910_keypad_scan_matrix(struct w90p910_keypad *keypad, | 56 | static void w90p910_keypad_scan_matrix(struct w90p910_keypad *keypad, |
80 | unsigned int status) | 57 | unsigned int status) |
81 | { | 58 | { |
82 | unsigned int row, col, val; | 59 | struct input_dev *input_dev = keypad->input_dev; |
83 | 60 | unsigned int row = KGET_RAW(status); | |
84 | row = KGET_RAW(status); | 61 | unsigned int col = KGET_COLUMN(status); |
85 | col = KGET_COLUMN(status); | 62 | unsigned int code = MATRIX_SCAN_CODE(row, col, W90P910_ROW_SHIFT); |
86 | 63 | unsigned int key = keypad->keymap[code]; | |
87 | val = lookup_matrix_keycode(keypad, row, col); | 64 | |
88 | 65 | input_event(input_dev, EV_MSC, MSC_SCAN, code); | |
89 | input_report_key(keypad->input_dev, val, 1); | 66 | input_report_key(input_dev, key, 1); |
90 | 67 | input_sync(input_dev); | |
91 | input_sync(keypad->input_dev); | 68 | |
92 | 69 | input_event(input_dev, EV_MSC, MSC_SCAN, code); | |
93 | input_report_key(keypad->input_dev, val, 0); | 70 | input_report_key(input_dev, key, 0); |
94 | 71 | input_sync(input_dev); | |
95 | input_sync(keypad->input_dev); | ||
96 | } | 72 | } |
97 | 73 | ||
98 | static irqreturn_t w90p910_keypad_irq_handler(int irq, void *dev_id) | 74 | static irqreturn_t w90p910_keypad_irq_handler(int irq, void *dev_id) |
@@ -113,7 +89,7 @@ static irqreturn_t w90p910_keypad_irq_handler(int irq, void *dev_id) | |||
113 | static int w90p910_keypad_open(struct input_dev *dev) | 89 | static int w90p910_keypad_open(struct input_dev *dev) |
114 | { | 90 | { |
115 | struct w90p910_keypad *keypad = input_get_drvdata(dev); | 91 | struct w90p910_keypad *keypad = input_get_drvdata(dev); |
116 | struct w90p910_keypad_platform_data *pdata = keypad->pdata; | 92 | const struct w90p910_keypad_platform_data *pdata = keypad->pdata; |
117 | unsigned int val, config; | 93 | unsigned int val, config; |
118 | 94 | ||
119 | /* Enable unit clock */ | 95 | /* Enable unit clock */ |
@@ -142,31 +118,39 @@ static void w90p910_keypad_close(struct input_dev *dev) | |||
142 | 118 | ||
143 | static int __devinit w90p910_keypad_probe(struct platform_device *pdev) | 119 | static int __devinit w90p910_keypad_probe(struct platform_device *pdev) |
144 | { | 120 | { |
121 | const struct w90p910_keypad_platform_data *pdata = | ||
122 | pdev->dev.platform_data; | ||
123 | const struct matrix_keymap_data *keymap_data = pdata->keymap_data; | ||
145 | struct w90p910_keypad *keypad; | 124 | struct w90p910_keypad *keypad; |
146 | struct input_dev *input_dev; | 125 | struct input_dev *input_dev; |
147 | struct resource *res; | 126 | struct resource *res; |
148 | int irq, error; | 127 | int irq; |
149 | 128 | int error; | |
150 | keypad = kzalloc(sizeof(struct w90p910_keypad), GFP_KERNEL); | 129 | int i; |
151 | if (keypad == NULL) { | ||
152 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | ||
153 | return -ENOMEM; | ||
154 | } | ||
155 | 130 | ||
156 | keypad->pdata = pdev->dev.platform_data; | 131 | if (!pdata) { |
157 | if (keypad->pdata == NULL) { | ||
158 | dev_err(&pdev->dev, "no platform data defined\n"); | 132 | dev_err(&pdev->dev, "no platform data defined\n"); |
159 | error = -EINVAL; | 133 | return -EINVAL; |
160 | goto failed_free; | ||
161 | } | 134 | } |
162 | 135 | ||
163 | irq = platform_get_irq(pdev, 0); | 136 | irq = platform_get_irq(pdev, 0); |
164 | if (irq < 0) { | 137 | if (irq < 0) { |
165 | dev_err(&pdev->dev, "failed to get keypad irq\n"); | 138 | dev_err(&pdev->dev, "failed to get keypad irq\n"); |
166 | error = -ENXIO; | 139 | return -ENXIO; |
140 | } | ||
141 | |||
142 | keypad = kzalloc(sizeof(struct w90p910_keypad), GFP_KERNEL); | ||
143 | input_dev = input_allocate_device(); | ||
144 | if (!keypad || !input_dev) { | ||
145 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | ||
146 | error = -ENOMEM; | ||
167 | goto failed_free; | 147 | goto failed_free; |
168 | } | 148 | } |
169 | 149 | ||
150 | keypad->pdata = pdata; | ||
151 | keypad->input_dev = input_dev; | ||
152 | keypad->irq = irq; | ||
153 | |||
170 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 154 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
171 | if (res == NULL) { | 155 | if (res == NULL) { |
172 | dev_err(&pdev->dev, "failed to get I/O memory\n"); | 156 | dev_err(&pdev->dev, "failed to get I/O memory\n"); |
@@ -185,7 +169,7 @@ static int __devinit w90p910_keypad_probe(struct platform_device *pdev) | |||
185 | if (keypad->mmio_base == NULL) { | 169 | if (keypad->mmio_base == NULL) { |
186 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | 170 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); |
187 | error = -ENXIO; | 171 | error = -ENXIO; |
188 | goto failed_free_mem; | 172 | goto failed_free_res; |
189 | } | 173 | } |
190 | 174 | ||
191 | keypad->clk = clk_get(&pdev->dev, NULL); | 175 | keypad->clk = clk_get(&pdev->dev, NULL); |
@@ -195,14 +179,6 @@ static int __devinit w90p910_keypad_probe(struct platform_device *pdev) | |||
195 | goto failed_free_io; | 179 | goto failed_free_io; |
196 | } | 180 | } |
197 | 181 | ||
198 | /* Create and register the input driver. */ | ||
199 | input_dev = input_allocate_device(); | ||
200 | if (!input_dev) { | ||
201 | dev_err(&pdev->dev, "failed to allocate input device\n"); | ||
202 | error = -ENOMEM; | ||
203 | goto failed_put_clk; | ||
204 | } | ||
205 | |||
206 | /* set multi-function pin for w90p910 kpi. */ | 182 | /* set multi-function pin for w90p910 kpi. */ |
207 | mfp_set_groupi(&pdev->dev); | 183 | mfp_set_groupi(&pdev->dev); |
208 | 184 | ||
@@ -211,26 +187,37 @@ static int __devinit w90p910_keypad_probe(struct platform_device *pdev) | |||
211 | input_dev->open = w90p910_keypad_open; | 187 | input_dev->open = w90p910_keypad_open; |
212 | input_dev->close = w90p910_keypad_close; | 188 | input_dev->close = w90p910_keypad_close; |
213 | input_dev->dev.parent = &pdev->dev; | 189 | input_dev->dev.parent = &pdev->dev; |
214 | input_dev->keycode = keypad->matrix_keycodes; | ||
215 | input_dev->keycodesize = sizeof(keypad->matrix_keycodes[0]); | ||
216 | input_dev->keycodemax = ARRAY_SIZE(keypad->matrix_keycodes); | ||
217 | 190 | ||
218 | keypad->input_dev = input_dev; | 191 | input_dev->keycode = keypad->keymap; |
192 | input_dev->keycodesize = sizeof(keypad->keymap[0]); | ||
193 | input_dev->keycodemax = ARRAY_SIZE(keypad->keymap); | ||
194 | |||
219 | input_set_drvdata(input_dev, keypad); | 195 | input_set_drvdata(input_dev, keypad); |
220 | 196 | ||
221 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | 197 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); |
222 | w90p910_keypad_build_keycode(keypad); | 198 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); |
223 | platform_set_drvdata(pdev, keypad); | 199 | |
200 | for (i = 0; i < keymap_data->keymap_size; i++) { | ||
201 | unsigned int key = keymap_data->keymap[i]; | ||
202 | unsigned int row = KEY_ROW(key); | ||
203 | unsigned int col = KEY_COL(key); | ||
204 | unsigned short keycode = KEY_VAL(key); | ||
205 | unsigned int scancode = MATRIX_SCAN_CODE(row, col, | ||
206 | W90P910_ROW_SHIFT); | ||
207 | |||
208 | keypad->keymap[scancode] = keycode; | ||
209 | __set_bit(keycode, input_dev->keybit); | ||
210 | } | ||
211 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
212 | |||
224 | 213 | ||
225 | error = request_irq(irq, w90p910_keypad_irq_handler, IRQF_DISABLED, | 214 | error = request_irq(keypad->irq, w90p910_keypad_irq_handler, |
226 | pdev->name, keypad); | 215 | IRQF_DISABLED, pdev->name, keypad); |
227 | if (error) { | 216 | if (error) { |
228 | dev_err(&pdev->dev, "failed to request IRQ\n"); | 217 | dev_err(&pdev->dev, "failed to request IRQ\n"); |
229 | goto failed_free_dev; | 218 | goto failed_put_clk; |
230 | } | 219 | } |
231 | 220 | ||
232 | keypad->irq = irq; | ||
233 | |||
234 | /* Register the input device */ | 221 | /* Register the input device */ |
235 | error = input_register_device(input_dev); | 222 | error = input_register_device(input_dev); |
236 | if (error) { | 223 | if (error) { |
@@ -238,20 +225,19 @@ static int __devinit w90p910_keypad_probe(struct platform_device *pdev) | |||
238 | goto failed_free_irq; | 225 | goto failed_free_irq; |
239 | } | 226 | } |
240 | 227 | ||
228 | platform_set_drvdata(pdev, keypad); | ||
241 | return 0; | 229 | return 0; |
242 | 230 | ||
243 | failed_free_irq: | 231 | failed_free_irq: |
244 | free_irq(irq, pdev); | 232 | free_irq(irq, pdev); |
245 | platform_set_drvdata(pdev, NULL); | ||
246 | failed_free_dev: | ||
247 | input_free_device(input_dev); | ||
248 | failed_put_clk: | 233 | failed_put_clk: |
249 | clk_put(keypad->clk); | 234 | clk_put(keypad->clk); |
250 | failed_free_io: | 235 | failed_free_io: |
251 | iounmap(keypad->mmio_base); | 236 | iounmap(keypad->mmio_base); |
252 | failed_free_mem: | 237 | failed_free_res: |
253 | release_mem_region(res->start, resource_size(res)); | 238 | release_mem_region(res->start, resource_size(res)); |
254 | failed_free: | 239 | failed_free: |
240 | input_free_device(input_dev); | ||
255 | kfree(keypad); | 241 | kfree(keypad); |
256 | return error; | 242 | return error; |
257 | } | 243 | } |
@@ -268,12 +254,12 @@ static int __devexit w90p910_keypad_remove(struct platform_device *pdev) | |||
268 | input_unregister_device(keypad->input_dev); | 254 | input_unregister_device(keypad->input_dev); |
269 | 255 | ||
270 | iounmap(keypad->mmio_base); | 256 | iounmap(keypad->mmio_base); |
271 | |||
272 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 257 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
273 | release_mem_region(res->start, resource_size(res)); | 258 | release_mem_region(res->start, resource_size(res)); |
274 | 259 | ||
275 | platform_set_drvdata(pdev, NULL); | 260 | platform_set_drvdata(pdev, NULL); |
276 | kfree(keypad); | 261 | kfree(keypad); |
262 | |||
277 | return 0; | 263 | return 0; |
278 | } | 264 | } |
279 | 265 | ||