| @@ -20,8 +20,8 @@ · 19 unmodified lines |
| 20 | 20 | #include <linux/delay.h> |
| 21 | 21 | #include <linux/mutex.h> |
| 22 | 22 | #include <linux/regmap.h> |
| 23 | | − |
| 24 | | −#include <linux/input/pmic8xxx-keypad.h> |
| 23 | +#include <linux/of.h> |
| 24 | +#include <linux/input/matrix_keypad.h> |
| 25 | 25 | |
| 26 | 26 | #define PM8XXX_MAX_ROWS 18 |
| 27 | 27 | #define PM8XXX_MAX_COLS 8 |
| @@ -84,7 +84,8 @@ · 56 unmodified lines |
| 84 | 84 | |
| 85 | 85 | /** |
| 86 | 86 | * struct pmic8xxx_kp - internal keypad data structure |
| 87 | | − * @pdata - keypad platform data pointer |
| 87 | + * @num_cols - number of columns of keypad |
| 88 | + * @num_rows - number of row of keypad |
| 88 | 89 | * @input - input device pointer for keypad |
| 89 | 90 | * @regmap - regmap handle |
| 90 | 91 | * @key_sense_irq - key press/release irq number |
| @@ -96,7 +97,8 @@ · 5 unmodified lines |
| 96 | 97 | * @ctrl_reg - control register value |
| 97 | 98 | */ |
| 98 | 99 | struct pmic8xxx_kp { |
| 99 | | − const struct pm8xxx_keypad_platform_data *pdata; |
| 100 | + unsigned int num_rows; |
| 101 | + unsigned int num_cols; |
| 100 | 102 | struct input_dev *input; |
| 101 | 103 | struct regmap *regmap; |
| 102 | 104 | int key_sense_irq; |
| @@ -115,9 +117,9 @@ static u8 pmic8xxx_col_state(struct pmic8xxx_kp *kp, u8 col) · 12 unmodified lines |
| 115 | 117 | { |
| 116 | 118 | /* all keys pressed on that particular row? */ |
| 117 | 119 | if (col == 0x00) |
| 118 | | − return 1 << kp->pdata->num_cols; |
| 120 | + return 1 << kp->num_cols; |
| 119 | 121 | else |
| 120 | | − return col & ((1 << kp->pdata->num_cols) - 1); |
| 122 | + return col & ((1 << kp->num_cols) - 1); |
| 121 | 123 | } |
| 122 | 124 | |
| 123 | 125 | /* |
| @@ -180,10 +182,10 @@ static int pmic8xxx_kp_read_matrix(struct pmic8xxx_kp *kp, u16 *new_state, · 56 unmodified lines |
| 180 | 182 | int rc, read_rows; |
| 181 | 183 | unsigned int scan_val; |
| 182 | 184 | |
| 183 | | − if (kp->pdata->num_rows < PM8XXX_MIN_ROWS) |
| 185 | + if (kp->num_rows < PM8XXX_MIN_ROWS) |
| 184 | 186 | read_rows = PM8XXX_MIN_ROWS; |
| 185 | 187 | else |
| 186 | | − read_rows = kp->pdata->num_rows; |
| 188 | + read_rows = kp->num_rows; |
| 187 | 189 | |
| 188 | 190 | pmic8xxx_chk_sync_read(kp); |
| 189 | 191 | |
| @@ -227,13 +229,13 @@ static void __pmic8xxx_kp_scan_matrix(struct pmic8xxx_kp *kp, u16 *new_state, · 37 unmodified lines |
| 227 | 229 | { |
| 228 | 230 | int row, col, code; |
| 229 | 231 | |
| 230 | | − for (row = 0; row < kp->pdata->num_rows; row++) { |
| 232 | + for (row = 0; row < kp->num_rows; row++) { |
| 231 | 233 | int bits_changed = new_state[row] ^ old_state[row]; |
| 232 | 234 | |
| 233 | 235 | if (!bits_changed) |
| 234 | 236 | continue; |
| 235 | 237 | |
| 236 | | − for (col = 0; col < kp->pdata->num_cols; col++) { |
| 238 | + for (col = 0; col < kp->num_cols; col++) { |
| 237 | 239 | if (!(bits_changed & (1 << col))) |
| 238 | 240 | continue; |
| 239 | 241 | |
| @@ -259,9 +261,9 @@ static bool pmic8xxx_detect_ghost_keys(struct pmic8xxx_kp *kp, u16 *new_state) · 19 unmodified lines |
| 259 | 261 | u16 check, row_state; |
| 260 | 262 | |
| 261 | 263 | check = 0; |
| 262 | | − for (row = 0; row < kp->pdata->num_rows; row++) { |
| 264 | + for (row = 0; row < kp->num_rows; row++) { |
| 263 | 265 | row_state = (~new_state[row]) & |
| 264 | | − ((1 << kp->pdata->num_cols) - 1); |
| 266 | + ((1 << kp->num_cols) - 1); |
| 265 | 267 | |
| 266 | 268 | if (hweight16(row_state) > 1) { |
| 267 | 269 | if (found_first == -1) |
| @@ -369,8 +371,13 @@ static irqreturn_t pmic8xxx_kp_irq(int irq, void *data) · 101 unmodified lines |
| 369 | 371 | return IRQ_HANDLED; |
| 370 | 372 | } |
| 371 | 373 | |
| 372 | | −static int pmic8xxx_kpd_init(struct pmic8xxx_kp *kp) |
| 374 | +static int pmic8xxx_kpd_init(struct pmic8xxx_kp *kp, |
| 375 | + struct platform_device *pdev) |
| 373 | 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; |
| 374 | 381 | int bits, rc, cycles; |
| 375 | 382 | u8 scan_val = 0, ctrl_val = 0; |
| 376 | 383 | static const u8 row_bits[] = { |
| @@ -378,18 +385,18 @@ static int pmic8xxx_kpd_init(struct pmic8xxx_kp *kp) · 1 unmodified line |
| 378 | 385 | }; |
| 379 | 386 | |
| 380 | 387 | /* Find column bits */ |
| 381 | | − if (kp->pdata->num_cols < KEYP_CTRL_SCAN_COLS_MIN) |
| 388 | + if (kp->num_cols < KEYP_CTRL_SCAN_COLS_MIN) |
| 382 | 389 | bits = 0; |
| 383 | 390 | else |
| 384 | | − bits = kp->pdata->num_cols - KEYP_CTRL_SCAN_COLS_MIN; |
| 391 | + bits = kp->num_cols - KEYP_CTRL_SCAN_COLS_MIN; |
| 385 | 392 | ctrl_val = (bits & KEYP_CTRL_SCAN_COLS_BITS) << |
| 386 | 393 | KEYP_CTRL_SCAN_COLS_SHIFT; |
| 387 | 394 | |
| 388 | 395 | /* Find row bits */ |
| 389 | | − if (kp->pdata->num_rows < KEYP_CTRL_SCAN_ROWS_MIN) |
| 396 | + if (kp->num_rows < KEYP_CTRL_SCAN_ROWS_MIN) |
| 390 | 397 | bits = 0; |
| 391 | 398 | else |
| 392 | | − bits = row_bits[kp->pdata->num_rows - KEYP_CTRL_SCAN_ROWS_MIN]; |
| 399 | + bits = row_bits[kp->num_rows - KEYP_CTRL_SCAN_ROWS_MIN]; |
| 393 | 400 | |
| 394 | 401 | ctrl_val |= (bits << KEYP_CTRL_SCAN_ROWS_SHIFT); |
| 395 | 402 | |
| @@ -399,15 +406,44 @@ static int pmic8xxx_kpd_init(struct pmic8xxx_kp *kp) · 3 unmodified lines |
| 399 | 406 | return rc; |
| 400 | 407 | } |
| 401 | 408 | |
| 402 | | − 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; |
| 403 | 439 | |
| 404 | 440 | scan_val |= (bits << KEYP_SCAN_DBOUNCE_SHIFT); |
| 405 | 441 | |
| 406 | | − bits = fls(kp->pdata->scan_delay_ms) - 1; |
| 442 | + bits = fls(scan_delay_ms) - 1; |
| 407 | 443 | scan_val |= (bits << KEYP_SCAN_PAUSE_SHIFT); |
| 408 | 444 | |
| 409 | 445 | /* Row hold time is a multiple of 32KHz cycles. */ |
| 410 | | − cycles = (kp->pdata->row_hold_ns * KEYP_CLOCK_FREQ) / NSEC_PER_SEC; |
| 446 | + cycles = (row_hold_ns * KEYP_CLOCK_FREQ) / NSEC_PER_SEC; |
| 411 | 447 | |
| 412 | 448 | scan_val |= (cycles << KEYP_SCAN_ROW_HOLD_SHIFT); |
| 413 | 449 | |
| @@ -471,50 +507,27 @@ static void pmic8xxx_kp_close(struct input_dev *dev) · 57 unmodified lines |
| 471 | 507 | */ |
| 472 | 508 | static int pmic8xxx_kp_probe(struct platform_device *pdev) |
| 473 | 509 | { |
| 474 | | − const struct pm8xxx_keypad_platform_data *pdata = |
| 475 | | − dev_get_platdata(&pdev->dev); |
| 476 | | − const struct matrix_keymap_data *keymap_data; |
| 510 | + unsigned int rows, cols; |
| 511 | + bool repeat; |
| 512 | + bool wakeup; |
| 477 | 513 | struct pmic8xxx_kp *kp; |
| 478 | 514 | int rc; |
| 479 | 515 | unsigned int ctrl_val; |
| 480 | 516 | |
| 481 | | − if (!pdata || !pdata->num_cols || !pdata->num_rows || |
| 482 | | − pdata->num_cols > PM8XXX_MAX_COLS || |
| 483 | | − pdata->num_rows > PM8XXX_MAX_ROWS || |
| 484 | | − pdata->num_cols < PM8XXX_MIN_COLS) { |
| 485 | | − dev_err(&pdev->dev, "invalid platform data\n"); |
| 486 | | − return -EINVAL; |
| 487 | | − } |
| 488 | | − |
| 489 | | − if (!pdata->scan_delay_ms || |
| 490 | | − pdata->scan_delay_ms > MAX_SCAN_DELAY || |
| 491 | | − pdata->scan_delay_ms < MIN_SCAN_DELAY || |
| 492 | | − !is_power_of_2(pdata->scan_delay_ms)) { |
| 493 | | − dev_err(&pdev->dev, "invalid keypad scan time supplied\n"); |
| 494 | | − return -EINVAL; |
| 495 | | − } |
| 496 | | − |
| 497 | | − if (!pdata->row_hold_ns || |
| 498 | | − pdata->row_hold_ns > MAX_ROW_HOLD_DELAY || |
| 499 | | − pdata->row_hold_ns < MIN_ROW_HOLD_DELAY || |
| 500 | | − ((pdata->row_hold_ns % MIN_ROW_HOLD_DELAY) != 0)) { |
| 501 | | − dev_err(&pdev->dev, "invalid keypad row hold time supplied\n"); |
| 502 | | − return -EINVAL; |
| 503 | | − } |
| 517 | + rc = matrix_keypad_parse_of_params(&pdev->dev, &rows, &cols); |
| 518 | + if (rc) |
| 519 | + return rc; |
| 504 | 520 | |
| 505 | | − if (!pdata->debounce_ms || |
| 506 | | − ((pdata->debounce_ms % 5) != 0) || |
| 507 | | − pdata->debounce_ms > MAX_DEBOUNCE_TIME || |
| 508 | | − pdata->debounce_ms < MIN_DEBOUNCE_TIME) { |
| 509 | | − dev_err(&pdev->dev, "invalid debounce time supplied\n"); |
| 521 | + if (cols > PM8XXX_MAX_COLS || rows > PM8XXX_MAX_ROWS || |
| 522 | + cols < PM8XXX_MIN_COLS) { |
| 523 | + dev_err(&pdev->dev, "invalid platform data\n"); |
| 510 | 524 | return -EINVAL; |
| 511 | 525 | } |
| 512 | 526 | |
| 513 | | − keymap_data = pdata->keymap_data; |
| 514 | | − if (!keymap_data) { |
| 515 | | − dev_err(&pdev->dev, "no keymap data supplied\n"); |
| 516 | | − return -EINVAL; |
| 517 | | − } |
| 527 | + repeat = !of_property_read_bool(pdev->dev.of_node, |
| 528 | + "linux,input-no-autorepeat"); |
| 529 | + wakeup = of_property_read_bool(pdev->dev.of_node, |
| 530 | + "linux,keypad-wakeup"); |
| 518 | 531 | |
| 519 | 532 | kp = devm_kzalloc(&pdev->dev, sizeof(*kp), GFP_KERNEL); |
| 520 | 533 | if (!kp) |
| @@ -526,7 +539,8 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev) · 5 unmodified lines |
| 526 | 539 | |
| 527 | 540 | platform_set_drvdata(pdev, kp); |
| 528 | 541 | |
| 529 | | − kp->pdata = pdata; |
| 542 | + kp->num_rows = rows; |
| 543 | + kp->num_cols = cols; |
| 530 | 544 | kp->dev = &pdev->dev; |
| 531 | 545 | |
| 532 | 546 | kp->input = devm_input_allocate_device(&pdev->dev); |
| @@ -547,8 +561,8 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev) · 14 unmodified lines |
| 547 | 561 | return kp->key_stuck_irq; |
| 548 | 562 | } |
| 549 | 563 | |
| 550 | | − kp->input->name = pdata->input_name ? : "PMIC8XXX keypad"; |
| 551 | | − kp->input->phys = pdata->input_phys_device ? : "pmic8xxx_keypad/input0"; |
| 564 | + kp->input->name = "PMIC8XXX keypad"; |
| 565 | + kp->input->phys = "pmic8xxx_keypad/input0"; |
| 552 | 566 | |
| 553 | 567 | kp->input->id.bustype = BUS_I2C; |
| 554 | 568 | kp->input->id.version = 0x0001; |
| @@ -558,7 +572,7 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev) · 3 unmodified lines |
| 558 | 572 | kp->input->open = pmic8xxx_kp_open; |
| 559 | 573 | kp->input->close = pmic8xxx_kp_close; |
| 560 | 574 | |
| 561 | | − rc = matrix_keypad_build_keymap(keymap_data, NULL, |
| 575 | + rc = matrix_keypad_build_keymap(NULL, NULL, |
| 562 | 576 | PM8XXX_MAX_ROWS, PM8XXX_MAX_COLS, |
| 563 | 577 | kp->keycodes, kp->input); |
| 564 | 578 | if (rc) { |
| @@ -566,7 +580,7 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev) · 1 unmodified line |
| 566 | 580 | return rc; |
| 567 | 581 | } |
| 568 | 582 | |
| 569 | | − if (pdata->rep) |
| 583 | + if (repeat) |
| 570 | 584 | __set_bit(EV_REP, kp->input->evbit); |
| 571 | 585 | input_set_capability(kp->input, EV_MSC, MSC_SCAN); |
| 572 | 586 | |
| @@ -576,7 +590,7 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev) · 3 unmodified lines |
| 576 | 590 | memset(kp->keystate, 0xff, sizeof(kp->keystate)); |
| 577 | 591 | memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate)); |
| 578 | 592 | |
| 579 | | − rc = pmic8xxx_kpd_init(kp); |
| 593 | + rc = pmic8xxx_kpd_init(kp, pdev); |
| 580 | 594 | if (rc < 0) { |
| 581 | 595 | dev_err(&pdev->dev, "unable to initialize keypad controller\n"); |
| 582 | 596 | return rc; |
| @@ -612,7 +626,7 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev) · 29 unmodified lines |
| 612 | 626 | return rc; |
| 613 | 627 | } |
| 614 | 628 | |
| 615 | | − device_init_wakeup(&pdev->dev, pdata->wakeup); |
| 629 | + device_init_wakeup(&pdev->dev, wakeup); |
| 616 | 630 | |
| 617 | 631 | return 0; |
| 618 | 632 | } |
| @@ -662,12 +676,20 @@ static int pmic8xxx_kp_resume(struct device *dev) · 43 unmodified lines |
| 662 | 676 | static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops, |
| 663 | 677 | pmic8xxx_kp_suspend, pmic8xxx_kp_resume); |
| 664 | 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 | + |
| 665 | 686 | static struct platform_driver pmic8xxx_kp_driver = { |
| 666 | 687 | .probe = pmic8xxx_kp_probe, |
| 667 | 688 | .driver = { |
| 668 | | − .name = PM8XXX_KEYPAD_DEV_NAME, |
| 689 | + .name = "pm8xxx-keypad", |
| 669 | 690 | .owner = THIS_MODULE, |
| 670 | 691 | .pm = &pm8xxx_kp_pm_ops, |
| 692 | + .of_match_table = pm8xxx_match_table, |
| 671 | 693 | }, |
| 672 | 694 | }; |
| 673 | 695 | module_platform_driver(pmic8xxx_kp_driver); |