| Rabin Vincent | 76f1084 | 2010-07-02 16:52:10 +0530 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (C) ST-Ericsson SA 2010 | 
|  | 3 | * | 
|  | 4 | * License Terms: GNU General Public License, version 2 | 
|  | 5 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | 
|  | 6 | */ | 
|  | 7 |  | 
|  | 8 | #include <linux/module.h> | 
|  | 9 | #include <linux/init.h> | 
|  | 10 | #include <linux/slab.h> | 
|  | 11 | #include <linux/input.h> | 
|  | 12 | #include <linux/interrupt.h> | 
|  | 13 | #include <linux/platform_device.h> | 
|  | 14 | #include <linux/input/matrix_keypad.h> | 
|  | 15 | #include <linux/mfd/stmpe.h> | 
|  | 16 |  | 
|  | 17 | /* These are at the same addresses in all STMPE variants */ | 
|  | 18 | #define STMPE_KPC_COL			0x60 | 
|  | 19 | #define STMPE_KPC_ROW_MSB		0x61 | 
|  | 20 | #define STMPE_KPC_ROW_LSB		0x62 | 
|  | 21 | #define STMPE_KPC_CTRL_MSB		0x63 | 
|  | 22 | #define STMPE_KPC_CTRL_LSB		0x64 | 
|  | 23 | #define STMPE_KPC_COMBI_KEY_0		0x65 | 
|  | 24 | #define STMPE_KPC_COMBI_KEY_1		0x66 | 
|  | 25 | #define STMPE_KPC_COMBI_KEY_2		0x67 | 
|  | 26 | #define STMPE_KPC_DATA_BYTE0		0x68 | 
|  | 27 | #define STMPE_KPC_DATA_BYTE1		0x69 | 
|  | 28 | #define STMPE_KPC_DATA_BYTE2		0x6a | 
|  | 29 | #define STMPE_KPC_DATA_BYTE3		0x6b | 
|  | 30 | #define STMPE_KPC_DATA_BYTE4		0x6c | 
|  | 31 |  | 
|  | 32 | #define STMPE_KPC_CTRL_LSB_SCAN		(0x1 << 0) | 
|  | 33 | #define STMPE_KPC_CTRL_LSB_DEBOUNCE	(0x7f << 1) | 
|  | 34 | #define STMPE_KPC_CTRL_MSB_SCAN_COUNT	(0xf << 4) | 
|  | 35 |  | 
|  | 36 | #define STMPE_KPC_ROW_MSB_ROWS		0xff | 
|  | 37 |  | 
|  | 38 | #define STMPE_KPC_DATA_UP		(0x1 << 7) | 
|  | 39 | #define STMPE_KPC_DATA_ROW		(0xf << 3) | 
|  | 40 | #define STMPE_KPC_DATA_COL		(0x7 << 0) | 
|  | 41 | #define STMPE_KPC_DATA_NOKEY_MASK	0x78 | 
|  | 42 |  | 
|  | 43 | #define STMPE_KEYPAD_MAX_DEBOUNCE	127 | 
|  | 44 | #define STMPE_KEYPAD_MAX_SCAN_COUNT	15 | 
|  | 45 |  | 
|  | 46 | #define STMPE_KEYPAD_MAX_ROWS		8 | 
|  | 47 | #define STMPE_KEYPAD_MAX_COLS		8 | 
|  | 48 | #define STMPE_KEYPAD_ROW_SHIFT		3 | 
|  | 49 | #define STMPE_KEYPAD_KEYMAP_SIZE	\ | 
|  | 50 | (STMPE_KEYPAD_MAX_ROWS * STMPE_KEYPAD_MAX_COLS) | 
|  | 51 |  | 
|  | 52 | /** | 
|  | 53 | * struct stmpe_keypad_variant - model-specific attributes | 
|  | 54 | * @auto_increment: whether the KPC_DATA_BYTE register address | 
|  | 55 | *		    auto-increments on multiple read | 
|  | 56 | * @num_data: number of data bytes | 
|  | 57 | * @num_normal_data: number of normal keys' data bytes | 
|  | 58 | * @max_cols: maximum number of columns supported | 
|  | 59 | * @max_rows: maximum number of rows supported | 
|  | 60 | * @col_gpios: bitmask of gpios which can be used for columns | 
|  | 61 | * @row_gpios: bitmask of gpios which can be used for rows | 
|  | 62 | */ | 
|  | 63 | struct stmpe_keypad_variant { | 
|  | 64 | bool		auto_increment; | 
|  | 65 | int		num_data; | 
|  | 66 | int		num_normal_data; | 
|  | 67 | int		max_cols; | 
|  | 68 | int		max_rows; | 
|  | 69 | unsigned int	col_gpios; | 
|  | 70 | unsigned int	row_gpios; | 
|  | 71 | }; | 
|  | 72 |  | 
|  | 73 | static const struct stmpe_keypad_variant stmpe_keypad_variants[] = { | 
|  | 74 | [STMPE1601] = { | 
|  | 75 | .auto_increment		= true, | 
|  | 76 | .num_data		= 5, | 
|  | 77 | .num_normal_data	= 3, | 
|  | 78 | .max_cols		= 8, | 
|  | 79 | .max_rows		= 8, | 
|  | 80 | .col_gpios		= 0x000ff,	/* GPIO 0 - 7 */ | 
|  | 81 | .row_gpios		= 0x0ff00,	/* GPIO 8 - 15 */ | 
|  | 82 | }, | 
|  | 83 | [STMPE2401] = { | 
|  | 84 | .auto_increment		= false, | 
|  | 85 | .num_data		= 3, | 
|  | 86 | .num_normal_data	= 2, | 
|  | 87 | .max_cols		= 8, | 
|  | 88 | .max_rows		= 12, | 
|  | 89 | .col_gpios		= 0x0000ff,	/* GPIO 0 - 7*/ | 
|  | 90 | .row_gpios		= 0x1fef00,	/* GPIO 8-14, 16-20 */ | 
|  | 91 | }, | 
|  | 92 | [STMPE2403] = { | 
|  | 93 | .auto_increment		= true, | 
|  | 94 | .num_data		= 5, | 
|  | 95 | .num_normal_data	= 3, | 
|  | 96 | .max_cols		= 8, | 
|  | 97 | .max_rows		= 12, | 
|  | 98 | .col_gpios		= 0x0000ff,	/* GPIO 0 - 7*/ | 
|  | 99 | .row_gpios		= 0x1fef00,	/* GPIO 8-14, 16-20 */ | 
|  | 100 | }, | 
|  | 101 | }; | 
|  | 102 |  | 
|  | 103 | struct stmpe_keypad { | 
|  | 104 | struct stmpe *stmpe; | 
|  | 105 | struct input_dev *input; | 
|  | 106 | const struct stmpe_keypad_variant *variant; | 
|  | 107 | const struct stmpe_keypad_platform_data *plat; | 
|  | 108 |  | 
|  | 109 | unsigned int rows; | 
|  | 110 | unsigned int cols; | 
|  | 111 |  | 
|  | 112 | unsigned short keymap[STMPE_KEYPAD_KEYMAP_SIZE]; | 
|  | 113 | }; | 
|  | 114 |  | 
|  | 115 | static int stmpe_keypad_read_data(struct stmpe_keypad *keypad, u8 *data) | 
|  | 116 | { | 
|  | 117 | const struct stmpe_keypad_variant *variant = keypad->variant; | 
|  | 118 | struct stmpe *stmpe = keypad->stmpe; | 
|  | 119 | int ret; | 
|  | 120 | int i; | 
|  | 121 |  | 
|  | 122 | if (variant->auto_increment) | 
|  | 123 | return stmpe_block_read(stmpe, STMPE_KPC_DATA_BYTE0, | 
|  | 124 | variant->num_data, data); | 
|  | 125 |  | 
|  | 126 | for (i = 0; i < variant->num_data; i++) { | 
|  | 127 | ret = stmpe_reg_read(stmpe, STMPE_KPC_DATA_BYTE0 + i); | 
|  | 128 | if (ret < 0) | 
|  | 129 | return ret; | 
|  | 130 |  | 
|  | 131 | data[i] = ret; | 
|  | 132 | } | 
|  | 133 |  | 
|  | 134 | return 0; | 
|  | 135 | } | 
|  | 136 |  | 
|  | 137 | static irqreturn_t stmpe_keypad_irq(int irq, void *dev) | 
|  | 138 | { | 
|  | 139 | struct stmpe_keypad *keypad = dev; | 
|  | 140 | struct input_dev *input = keypad->input; | 
|  | 141 | const struct stmpe_keypad_variant *variant = keypad->variant; | 
|  | 142 | u8 fifo[variant->num_data]; | 
|  | 143 | int ret; | 
|  | 144 | int i; | 
|  | 145 |  | 
|  | 146 | ret = stmpe_keypad_read_data(keypad, fifo); | 
|  | 147 | if (ret < 0) | 
|  | 148 | return IRQ_NONE; | 
|  | 149 |  | 
|  | 150 | for (i = 0; i < variant->num_normal_data; i++) { | 
|  | 151 | u8 data = fifo[i]; | 
|  | 152 | int row = (data & STMPE_KPC_DATA_ROW) >> 3; | 
|  | 153 | int col = data & STMPE_KPC_DATA_COL; | 
|  | 154 | int code = MATRIX_SCAN_CODE(row, col, STMPE_KEYPAD_ROW_SHIFT); | 
|  | 155 | bool up = data & STMPE_KPC_DATA_UP; | 
|  | 156 |  | 
|  | 157 | if ((data & STMPE_KPC_DATA_NOKEY_MASK) | 
|  | 158 | == STMPE_KPC_DATA_NOKEY_MASK) | 
|  | 159 | continue; | 
|  | 160 |  | 
|  | 161 | input_event(input, EV_MSC, MSC_SCAN, code); | 
|  | 162 | input_report_key(input, keypad->keymap[code], !up); | 
|  | 163 | input_sync(input); | 
|  | 164 | } | 
|  | 165 |  | 
|  | 166 | return IRQ_HANDLED; | 
|  | 167 | } | 
|  | 168 |  | 
|  | 169 | static int __devinit stmpe_keypad_altfunc_init(struct stmpe_keypad *keypad) | 
|  | 170 | { | 
|  | 171 | const struct stmpe_keypad_variant *variant = keypad->variant; | 
|  | 172 | unsigned int col_gpios = variant->col_gpios; | 
|  | 173 | unsigned int row_gpios = variant->row_gpios; | 
|  | 174 | struct stmpe *stmpe = keypad->stmpe; | 
|  | 175 | unsigned int pins = 0; | 
|  | 176 | int i; | 
|  | 177 |  | 
|  | 178 | /* | 
|  | 179 | * Figure out which pins need to be set to the keypad alternate | 
|  | 180 | * function. | 
|  | 181 | * | 
|  | 182 | * {cols,rows}_gpios are bitmasks of which pins on the chip can be used | 
|  | 183 | * for the keypad. | 
|  | 184 | * | 
|  | 185 | * keypad->{cols,rows} are a bitmask of which pins (of the ones useable | 
|  | 186 | * for the keypad) are used on the board. | 
|  | 187 | */ | 
|  | 188 |  | 
|  | 189 | for (i = 0; i < variant->max_cols; i++) { | 
|  | 190 | int num = __ffs(col_gpios); | 
|  | 191 |  | 
|  | 192 | if (keypad->cols & (1 << i)) | 
|  | 193 | pins |= 1 << num; | 
|  | 194 |  | 
|  | 195 | col_gpios &= ~(1 << num); | 
|  | 196 | } | 
|  | 197 |  | 
|  | 198 | for (i = 0; i < variant->max_rows; i++) { | 
|  | 199 | int num = __ffs(row_gpios); | 
|  | 200 |  | 
|  | 201 | if (keypad->rows & (1 << i)) | 
|  | 202 | pins |= 1 << num; | 
|  | 203 |  | 
|  | 204 | row_gpios &= ~(1 << num); | 
|  | 205 | } | 
|  | 206 |  | 
|  | 207 | return stmpe_set_altfunc(stmpe, pins, STMPE_BLOCK_KEYPAD); | 
|  | 208 | } | 
|  | 209 |  | 
|  | 210 | static int __devinit stmpe_keypad_chip_init(struct stmpe_keypad *keypad) | 
|  | 211 | { | 
|  | 212 | const struct stmpe_keypad_platform_data *plat = keypad->plat; | 
|  | 213 | const struct stmpe_keypad_variant *variant = keypad->variant; | 
|  | 214 | struct stmpe *stmpe = keypad->stmpe; | 
|  | 215 | int ret; | 
|  | 216 |  | 
|  | 217 | if (plat->debounce_ms > STMPE_KEYPAD_MAX_DEBOUNCE) | 
|  | 218 | return -EINVAL; | 
|  | 219 |  | 
|  | 220 | if (plat->scan_count > STMPE_KEYPAD_MAX_SCAN_COUNT) | 
|  | 221 | return -EINVAL; | 
|  | 222 |  | 
|  | 223 | ret = stmpe_enable(stmpe, STMPE_BLOCK_KEYPAD); | 
|  | 224 | if (ret < 0) | 
|  | 225 | return ret; | 
|  | 226 |  | 
|  | 227 | ret = stmpe_keypad_altfunc_init(keypad); | 
|  | 228 | if (ret < 0) | 
|  | 229 | return ret; | 
|  | 230 |  | 
|  | 231 | ret = stmpe_reg_write(stmpe, STMPE_KPC_COL, keypad->cols); | 
|  | 232 | if (ret < 0) | 
|  | 233 | return ret; | 
|  | 234 |  | 
|  | 235 | ret = stmpe_reg_write(stmpe, STMPE_KPC_ROW_LSB, keypad->rows); | 
|  | 236 | if (ret < 0) | 
|  | 237 | return ret; | 
|  | 238 |  | 
|  | 239 | if (variant->max_rows > 8) { | 
|  | 240 | ret = stmpe_set_bits(stmpe, STMPE_KPC_ROW_MSB, | 
|  | 241 | STMPE_KPC_ROW_MSB_ROWS, | 
|  | 242 | keypad->rows >> 8); | 
|  | 243 | if (ret < 0) | 
|  | 244 | return ret; | 
|  | 245 | } | 
|  | 246 |  | 
|  | 247 | ret = stmpe_set_bits(stmpe, STMPE_KPC_CTRL_MSB, | 
|  | 248 | STMPE_KPC_CTRL_MSB_SCAN_COUNT, | 
|  | 249 | plat->scan_count << 4); | 
|  | 250 | if (ret < 0) | 
|  | 251 | return ret; | 
|  | 252 |  | 
|  | 253 | return stmpe_set_bits(stmpe, STMPE_KPC_CTRL_LSB, | 
|  | 254 | STMPE_KPC_CTRL_LSB_SCAN | | 
|  | 255 | STMPE_KPC_CTRL_LSB_DEBOUNCE, | 
|  | 256 | STMPE_KPC_CTRL_LSB_SCAN | | 
|  | 257 | (plat->debounce_ms << 1)); | 
|  | 258 | } | 
|  | 259 |  | 
|  | 260 | static int __devinit stmpe_keypad_probe(struct platform_device *pdev) | 
|  | 261 | { | 
|  | 262 | struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); | 
|  | 263 | struct stmpe_keypad_platform_data *plat; | 
|  | 264 | struct stmpe_keypad *keypad; | 
|  | 265 | struct input_dev *input; | 
|  | 266 | int ret; | 
|  | 267 | int irq; | 
|  | 268 | int i; | 
|  | 269 |  | 
|  | 270 | plat = stmpe->pdata->keypad; | 
|  | 271 | if (!plat) | 
|  | 272 | return -ENODEV; | 
|  | 273 |  | 
|  | 274 | irq = platform_get_irq(pdev, 0); | 
|  | 275 | if (irq < 0) | 
|  | 276 | return irq; | 
|  | 277 |  | 
|  | 278 | keypad = kzalloc(sizeof(struct stmpe_keypad), GFP_KERNEL); | 
|  | 279 | if (!keypad) | 
|  | 280 | return -ENOMEM; | 
|  | 281 |  | 
|  | 282 | input = input_allocate_device(); | 
|  | 283 | if (!input) { | 
|  | 284 | ret = -ENOMEM; | 
|  | 285 | goto out_freekeypad; | 
|  | 286 | } | 
|  | 287 |  | 
|  | 288 | input->name = "STMPE keypad"; | 
|  | 289 | input->id.bustype = BUS_I2C; | 
|  | 290 | input->dev.parent = &pdev->dev; | 
|  | 291 |  | 
|  | 292 | input_set_capability(input, EV_MSC, MSC_SCAN); | 
|  | 293 |  | 
|  | 294 | __set_bit(EV_KEY, input->evbit); | 
|  | 295 | if (!plat->no_autorepeat) | 
|  | 296 | __set_bit(EV_REP, input->evbit); | 
|  | 297 |  | 
|  | 298 | input->keycode = keypad->keymap; | 
|  | 299 | input->keycodesize = sizeof(keypad->keymap[0]); | 
|  | 300 | input->keycodemax = ARRAY_SIZE(keypad->keymap); | 
|  | 301 |  | 
|  | 302 | matrix_keypad_build_keymap(plat->keymap_data, STMPE_KEYPAD_ROW_SHIFT, | 
|  | 303 | input->keycode, input->keybit); | 
|  | 304 |  | 
|  | 305 | for (i = 0; i < plat->keymap_data->keymap_size; i++) { | 
|  | 306 | unsigned int key = plat->keymap_data->keymap[i]; | 
|  | 307 |  | 
|  | 308 | keypad->cols |= 1 << KEY_COL(key); | 
|  | 309 | keypad->rows |= 1 << KEY_ROW(key); | 
|  | 310 | } | 
|  | 311 |  | 
|  | 312 | keypad->stmpe = stmpe; | 
|  | 313 | keypad->plat = plat; | 
|  | 314 | keypad->input = input; | 
|  | 315 | keypad->variant = &stmpe_keypad_variants[stmpe->partnum]; | 
|  | 316 |  | 
|  | 317 | ret = stmpe_keypad_chip_init(keypad); | 
|  | 318 | if (ret < 0) | 
|  | 319 | goto out_freeinput; | 
|  | 320 |  | 
|  | 321 | ret = input_register_device(input); | 
|  | 322 | if (ret) { | 
|  | 323 | dev_err(&pdev->dev, | 
|  | 324 | "unable to register input device: %d\n", ret); | 
|  | 325 | goto out_freeinput; | 
|  | 326 | } | 
|  | 327 |  | 
|  | 328 | ret = request_threaded_irq(irq, NULL, stmpe_keypad_irq, IRQF_ONESHOT, | 
|  | 329 | "stmpe-keypad", keypad); | 
|  | 330 | if (ret) { | 
|  | 331 | dev_err(&pdev->dev, "unable to get irq: %d\n", ret); | 
|  | 332 | goto out_unregisterinput; | 
|  | 333 | } | 
|  | 334 |  | 
|  | 335 | platform_set_drvdata(pdev, keypad); | 
|  | 336 |  | 
|  | 337 | return 0; | 
|  | 338 |  | 
|  | 339 | out_unregisterinput: | 
|  | 340 | input_unregister_device(input); | 
|  | 341 | input = NULL; | 
|  | 342 | out_freeinput: | 
|  | 343 | input_free_device(input); | 
|  | 344 | out_freekeypad: | 
|  | 345 | kfree(keypad); | 
|  | 346 | return ret; | 
|  | 347 | } | 
|  | 348 |  | 
|  | 349 | static int __devexit stmpe_keypad_remove(struct platform_device *pdev) | 
|  | 350 | { | 
|  | 351 | struct stmpe_keypad *keypad = platform_get_drvdata(pdev); | 
|  | 352 | struct stmpe *stmpe = keypad->stmpe; | 
|  | 353 | int irq = platform_get_irq(pdev, 0); | 
|  | 354 |  | 
|  | 355 | stmpe_disable(stmpe, STMPE_BLOCK_KEYPAD); | 
|  | 356 |  | 
|  | 357 | free_irq(irq, keypad); | 
|  | 358 | input_unregister_device(keypad->input); | 
|  | 359 | platform_set_drvdata(pdev, NULL); | 
|  | 360 | kfree(keypad); | 
|  | 361 |  | 
|  | 362 | return 0; | 
|  | 363 | } | 
|  | 364 |  | 
|  | 365 | static struct platform_driver stmpe_keypad_driver = { | 
|  | 366 | .driver.name	= "stmpe-keypad", | 
|  | 367 | .driver.owner	= THIS_MODULE, | 
|  | 368 | .probe		= stmpe_keypad_probe, | 
|  | 369 | .remove		= __devexit_p(stmpe_keypad_remove), | 
|  | 370 | }; | 
|  | 371 |  | 
|  | 372 | static int __init stmpe_keypad_init(void) | 
|  | 373 | { | 
|  | 374 | return platform_driver_register(&stmpe_keypad_driver); | 
|  | 375 | } | 
|  | 376 | module_init(stmpe_keypad_init); | 
|  | 377 |  | 
|  | 378 | static void __exit stmpe_keypad_exit(void) | 
|  | 379 | { | 
|  | 380 | platform_driver_unregister(&stmpe_keypad_driver); | 
|  | 381 | } | 
|  | 382 | module_exit(stmpe_keypad_exit); | 
|  | 383 |  | 
|  | 384 | MODULE_LICENSE("GPL v2"); | 
|  | 385 | MODULE_DESCRIPTION("STMPExxxx keypad driver"); | 
|  | 386 | MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>"); |