123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853 |
- /* Copyright (c) 2013, The Linux Foundation. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/interrupt.h>
- #include <linux/slab.h>
- #include <linux/input.h>
- #include <linux/bitops.h>
- #include <linux/delay.h>
- #include <linux/mutex.h>
- #include <linux/of.h>
- #include <linux/of_device.h>
- #include <linux/input/matrix_keypad.h>
- #include <linux/spmi.h>
- #define QPNP_MAX_ROWS 10
- #define QPNP_MAX_COLS 8
- #define QPNP_MIN_ROWS 2
- #define QPNP_MIN_COLS 1
- #define QPNP_ROW_SHIFT 3
- #define QPNP_MATRIX_MAX_SIZE (QPNP_MAX_ROWS * QPNP_MAX_COLS)
- /* in ms */
- #define MAX_SCAN_DELAY 128
- #define MIN_SCAN_DELAY 1
- #define KEYP_DEFAULT_SCAN_DELAY 32
- /* in ns */
- #define MAX_ROW_HOLD_DELAY 250000
- #define MIN_ROW_HOLD_DELAY 31250
- /* in ms */
- #define MAX_DEBOUNCE_TIME 20
- #define MIN_DEBOUNCE_TIME 5
- #define KEYP_DEFAULT_DEBOUNCE 15
- /* register offsets */
- #define KEYP_STATUS(base) (base + 0x08)
- #define KEYP_SIZE_CTRL(base) (base + 0x40)
- #define KEYP_SCAN_CTRL(base) (base + 0x42)
- #define KEYP_FSM_CNTL(base) (base + 0x44)
- #define KEYP_EN_CTRL(base) (base + 0x46)
- #define KEYP_CTRL_KEYP_EN BIT(7)
- #define KEYP_CTRL_EVNTS BIT(0)
- #define KEYP_CTRL_EVNTS_MASK 0x3
- #define KEYP_SIZE_COLS_SHIFT 4
- #define KEYP_SIZE_COLS_MASK 0x70
- #define KEYP_SIZE_ROWS_MASK 0x0F
- #define KEYP_SCAN_DBC_MASK 0x03
- #define KEYP_SCAN_SCNP_MASK 0x38
- #define KEYP_SCAN_ROWP_MASK 0xC0
- #define KEYP_SCAN_SCNP_SHIFT 3
- #define KEYP_SCAN_ROWP_SHIFT 6
- #define KEYP_CTRL_SCAN_ROWS_BITS 0x7
- #define KEYP_SCAN_DBOUNCE_SHIFT 1
- #define KEYP_SCAN_PAUSE_SHIFT 3
- #define KEYP_SCAN_ROW_HOLD_SHIFT 6
- #define KEYP_FSM_READ_EN BIT(0)
- /* bits of these registers represent
- * '0' for key press
- * '1' for key release
- */
- #define KEYP_RECENT_DATA(base) (base + 0x7C)
- #define KEYP_OLD_DATA(base) (base + 0x5C)
- #define KEYP_CLOCK_FREQ 32768
- struct qpnp_kp {
- const struct matrix_keymap_data *keymap_data;
- struct input_dev *input;
- struct spmi_device *spmi;
- int key_sense_irq;
- int key_stuck_irq;
- u16 base;
- u32 num_rows;
- u32 num_cols;
- u32 debounce_ms;
- u32 row_hold_ns;
- u32 scan_delay_ms;
- bool wakeup;
- bool rep;
- unsigned short keycodes[QPNP_MATRIX_MAX_SIZE];
- u16 keystate[QPNP_MAX_ROWS];
- u16 stuckstate[QPNP_MAX_ROWS];
- };
- static int qpnp_kp_write_u8(struct qpnp_kp *kp, u8 data, u16 reg)
- {
- int rc;
- rc = spmi_ext_register_writel(kp->spmi->ctrl, kp->spmi->sid,
- reg, &data, 1);
- if (rc < 0)
- dev_err(&kp->spmi->dev,
- "Error writing to address: %X - ret %d\n", reg, rc);
- return rc;
- }
- static int qpnp_kp_read(struct qpnp_kp *kp,
- u8 *data, u16 reg, unsigned num_bytes)
- {
- int rc;
- rc = spmi_ext_register_readl(kp->spmi->ctrl, kp->spmi->sid,
- reg, data, num_bytes);
- if (rc < 0)
- dev_err(&kp->spmi->dev,
- "Error reading from address : %X - ret %d\n", reg, rc);
- return rc;
- }
- static int qpnp_kp_read_u8(struct qpnp_kp *kp, u8 *data, u16 reg)
- {
- int rc;
- rc = qpnp_kp_read(kp, data, reg, 1);
- if (rc < 0)
- dev_err(&kp->spmi->dev, "Error reading qpnp: %X - ret %d\n",
- reg, rc);
- return rc;
- }
- static u8 qpnp_col_state(struct qpnp_kp *kp, u8 col)
- {
- /* all keys pressed on that particular row? */
- if (col == 0x00)
- return 1 << kp->num_cols;
- else
- return col & ((1 << kp->num_cols) - 1);
- }
- /*
- * Synchronous read protocol
- *
- * 1. Write '1' to ReadState bit in KEYP_FSM_CNTL register
- * 2. Wait 2*32KHz clocks, so that HW can successfully enter read mode
- * synchronously
- * 3. Read rows in old array first if events are more than one
- * 4. Read rows in recent array
- * 5. Wait 4*32KHz clocks
- * 6. Write '0' to ReadState bit of KEYP_FSM_CNTL register so that hw can
- * synchronously exit read mode.
- */
- static int qpnp_sync_read(struct qpnp_kp *kp, bool enable)
- {
- int rc;
- u8 fsm_ctl;
- rc = qpnp_kp_read_u8(kp, &fsm_ctl, KEYP_FSM_CNTL(kp->base));
- if (rc < 0) {
- dev_err(&kp->spmi->dev,
- "Error reading KEYP_FSM_CNTL reg, rc=%d\n", rc);
- return rc;
- }
- if (enable)
- fsm_ctl |= KEYP_FSM_READ_EN;
- else
- fsm_ctl &= ~KEYP_FSM_READ_EN;
- rc = qpnp_kp_write_u8(kp, fsm_ctl, KEYP_FSM_CNTL(kp->base));
- if (rc < 0) {
- dev_err(&kp->spmi->dev,
- "Error writing KEYP_FSM_CNTL reg, rc=%d\n", rc);
- return rc;
- }
- /* 2 * 32KHz clocks */
- udelay((2 * DIV_ROUND_UP(USEC_PER_SEC, KEYP_CLOCK_FREQ)) + 1);
- return rc;
- }
- static int qpnp_kp_read_data(struct qpnp_kp *kp, u16 *state,
- u16 data_reg, int read_rows)
- {
- int rc, row;
- u8 new_data[QPNP_MAX_ROWS];
- /*
- * Check if last row will be scanned. If not, scan to clear key event
- * counter
- */
- if (kp->num_rows < QPNP_MAX_ROWS) {
- rc = qpnp_kp_read_u8(kp, &new_data[QPNP_MAX_ROWS - 1],
- data_reg + (QPNP_MAX_ROWS - 1) * 2);
- if (rc)
- return rc;
- }
- for (row = 0; row < kp->num_rows; row++) {
- rc = qpnp_kp_read_u8(kp, &new_data[row], data_reg + row * 2);
- if (rc)
- return rc;
- dev_dbg(&kp->spmi->dev, "new_data[%d] = %d\n", row,
- new_data[row]);
- state[row] = qpnp_col_state(kp, new_data[row]);
- }
- return 0;
- }
- static int qpnp_kp_read_matrix(struct qpnp_kp *kp, u16 *new_state,
- u16 *old_state)
- {
- int rc, read_rows;
- read_rows = kp->num_rows;
- rc = qpnp_sync_read(kp, true);
- if (rc < 0) {
- dev_err(&kp->spmi->dev,
- "Error setting the FSM read enable bit rc=%d\n", rc);
- return rc;
- }
- if (old_state) {
- rc = qpnp_kp_read_data(kp, old_state, KEYP_OLD_DATA(kp->base),
- read_rows);
- if (rc < 0) {
- dev_err(&kp->spmi->dev,
- "Error reading KEYP_OLD_DATA, rc=%d\n", rc);
- return rc;
- }
- }
- rc = qpnp_kp_read_data(kp, new_state, KEYP_RECENT_DATA(kp->base),
- read_rows);
- if (rc < 0) {
- dev_err(&kp->spmi->dev,
- "Error reading KEYP_RECENT_DATA, rc=%d\n", rc);
- return rc;
- }
- /* 4 * 32KHz clocks */
- udelay((4 * DIV_ROUND_UP(USEC_PER_SEC, KEYP_CLOCK_FREQ)) + 1);
- rc = qpnp_sync_read(kp, false);
- if (rc < 0) {
- dev_err(&kp->spmi->dev,
- "Error resetting the FSM read enable bit rc=%d\n", rc);
- return rc;
- }
- return rc;
- }
- static void __qpnp_kp_scan_matrix(struct qpnp_kp *kp, u16 *new_state,
- u16 *old_state)
- {
- int row, col, code;
- for (row = 0; row < kp->num_rows; row++) {
- int bits_changed = new_state[row] ^ old_state[row];
- if (!bits_changed)
- continue;
- for (col = 0; col < kp->num_cols; col++) {
- if (!(bits_changed & (1 << col)))
- continue;
- dev_dbg(&kp->spmi->dev, "key [%d:%d] %s\n", row, col,
- !(new_state[row] & (1 << col)) ?
- "pressed" : "released");
- code = MATRIX_SCAN_CODE(row, col, QPNP_ROW_SHIFT);
- input_event(kp->input, EV_MSC, MSC_SCAN, code);
- input_report_key(kp->input,
- kp->keycodes[code],
- !(new_state[row] & (1 << col)));
- input_sync(kp->input);
- }
- }
- }
- static bool qpnp_detect_ghost_keys(struct qpnp_kp *kp, u16 *new_state)
- {
- int row, found_first = -1;
- u16 check, row_state;
- check = 0;
- for (row = 0; row < kp->num_rows; row++) {
- row_state = (~new_state[row]) &
- ((1 << kp->num_cols) - 1);
- if (hweight16(row_state) > 1) {
- if (found_first == -1)
- found_first = row;
- if (check & row_state) {
- dev_dbg(&kp->spmi->dev,
- "detected ghost key row[%d],row[%d]\n",
- found_first, row);
- return true;
- }
- }
- check |= row_state;
- }
- return false;
- }
- static int qpnp_kp_scan_matrix(struct qpnp_kp *kp, unsigned int events)
- {
- u16 new_state[QPNP_MAX_ROWS];
- u16 old_state[QPNP_MAX_ROWS];
- int rc;
- switch (events) {
- case 0x1:
- rc = qpnp_kp_read_matrix(kp, new_state, NULL);
- if (rc < 0)
- return rc;
- /* detecting ghost key is not an error */
- if (qpnp_detect_ghost_keys(kp, new_state))
- return 0;
- __qpnp_kp_scan_matrix(kp, new_state, kp->keystate);
- memcpy(kp->keystate, new_state, sizeof(new_state));
- break;
- case 0x3: /* two events - eventcounter is gray-coded */
- rc = qpnp_kp_read_matrix(kp, new_state, old_state);
- if (rc < 0)
- return rc;
- __qpnp_kp_scan_matrix(kp, old_state, kp->keystate);
- __qpnp_kp_scan_matrix(kp, new_state, old_state);
- memcpy(kp->keystate, new_state, sizeof(new_state));
- break;
- case 0x2:
- dev_dbg(&kp->spmi->dev, "Some key events were lost\n");
- rc = qpnp_kp_read_matrix(kp, new_state, old_state);
- if (rc < 0)
- return rc;
- __qpnp_kp_scan_matrix(kp, old_state, kp->keystate);
- __qpnp_kp_scan_matrix(kp, new_state, old_state);
- memcpy(kp->keystate, new_state, sizeof(new_state));
- break;
- default:
- rc = -EINVAL;
- }
- return rc;
- }
- /*
- * NOTE: We are reading recent and old data registers blindly
- * whenever key-stuck interrupt happens, because events counter doesn't
- * get updated when this interrupt happens due to key stuck doesn't get
- * considered as key state change.
- *
- * We are not using old data register contents after they are being read
- * because it might report the key which was pressed before the key being stuck
- * as stuck key because it's pressed status is stored in the old data
- * register.
- */
- static irqreturn_t qpnp_kp_stuck_irq(int irq, void *data)
- {
- u16 new_state[QPNP_MAX_ROWS];
- u16 old_state[QPNP_MAX_ROWS];
- int rc;
- struct qpnp_kp *kp = data;
- rc = qpnp_kp_read_matrix(kp, new_state, old_state);
- if (rc < 0) {
- dev_err(&kp->spmi->dev, "failed to read keypad matrix\n");
- return IRQ_HANDLED;
- }
- __qpnp_kp_scan_matrix(kp, new_state, kp->stuckstate);
- return IRQ_HANDLED;
- }
- static irqreturn_t qpnp_kp_irq(int irq, void *data)
- {
- struct qpnp_kp *kp = data;
- u8 ctrl_val, events;
- int rc;
- rc = qpnp_kp_read_u8(kp, &ctrl_val, KEYP_STATUS(kp->base));
- if (rc < 0) {
- dev_err(&kp->spmi->dev,
- "Error reading KEYP_STATUS register\n");
- return IRQ_HANDLED;
- }
- events = ctrl_val & KEYP_CTRL_EVNTS_MASK;
- rc = qpnp_kp_scan_matrix(kp, events);
- if (rc < 0)
- dev_err(&kp->spmi->dev, "failed to scan matrix\n");
- return IRQ_HANDLED;
- }
- static int __devinit qpnp_kpd_init(struct qpnp_kp *kp)
- {
- int bits, rc, cycles;
- u8 kpd_scan_cntl, kpd_size_cntl;
- /* Configure the SIZE register, #rows and #columns */
- rc = qpnp_kp_read_u8(kp, &kpd_size_cntl, KEYP_SIZE_CTRL(kp->base));
- if (rc < 0) {
- dev_err(&kp->spmi->dev,
- "Error reading KEYP_SIZE_CTRL reg, rc=%d\n", rc);
- return rc;
- }
- kpd_size_cntl &= (~KEYP_SIZE_COLS_MASK | ~KEYP_SIZE_ROWS_MASK);
- kpd_size_cntl |= (((kp->num_cols - 1) << KEYP_SIZE_COLS_SHIFT) &
- KEYP_SIZE_COLS_MASK);
- kpd_size_cntl |= ((kp->num_rows - 1) & KEYP_SIZE_ROWS_MASK);
- rc = qpnp_kp_write_u8(kp, kpd_size_cntl, KEYP_SIZE_CTRL(kp->base));
- if (rc < 0) {
- dev_err(&kp->spmi->dev,
- "Error writing to KEYP_SIZE_CTRL reg, rc=%d\n", rc);
- return rc;
- }
- /* Configure the SCAN CTL register, debounce, row pause, scan delay */
- rc = qpnp_kp_read_u8(kp, &kpd_scan_cntl, KEYP_SCAN_CTRL(kp->base));
- if (rc < 0) {
- dev_err(&kp->spmi->dev,
- "Error reading KEYP_SCAN_CTRL reg, rc=%d\n", rc);
- return rc;
- }
- kpd_scan_cntl &= (~KEYP_SCAN_DBC_MASK | ~KEYP_SCAN_SCNP_MASK |
- ~KEYP_SCAN_ROWP_MASK);
- kpd_scan_cntl |= (((kp->debounce_ms / 5) - 1) & KEYP_SCAN_DBC_MASK);
- bits = fls(kp->scan_delay_ms) - 1;
- kpd_scan_cntl |= ((bits << KEYP_SCAN_SCNP_SHIFT) & KEYP_SCAN_SCNP_MASK);
- /* Row hold time is a multiple of 32KHz cycles. */
- cycles = (kp->row_hold_ns * KEYP_CLOCK_FREQ) / NSEC_PER_SEC;
- if (cycles)
- cycles = ilog2(cycles);
- kpd_scan_cntl |= ((cycles << KEYP_SCAN_ROW_HOLD_SHIFT) &
- KEYP_SCAN_ROWP_MASK);
- rc = qpnp_kp_write_u8(kp, kpd_scan_cntl, KEYP_SCAN_CTRL(kp->base));
- if (rc)
- dev_err(&kp->spmi->dev,
- "Error writing KEYP_SCAN reg, rc=%d\n", rc);
- return rc;
- }
- static int qpnp_kp_enable(struct qpnp_kp *kp)
- {
- int rc;
- u8 kpd_cntl;
- rc = qpnp_kp_read_u8(kp, &kpd_cntl, KEYP_EN_CTRL(kp->base));
- if (rc < 0) {
- dev_err(&kp->spmi->dev,
- "Error reading KEYP_EN_CTRL reg, rc=%d\n", rc);
- return rc;
- }
- kpd_cntl |= KEYP_CTRL_KEYP_EN;
- rc = qpnp_kp_write_u8(kp, kpd_cntl, KEYP_EN_CTRL(kp->base));
- if (rc < 0)
- dev_err(&kp->spmi->dev,
- "Error writing KEYP_CTRL reg, rc=%d\n", rc);
- return rc;
- }
- static int qpnp_kp_disable(struct qpnp_kp *kp)
- {
- int rc;
- u8 kpd_cntl;
- rc = qpnp_kp_read_u8(kp, &kpd_cntl, KEYP_EN_CTRL(kp->base));
- if (rc < 0) {
- dev_err(&kp->spmi->dev,
- "Error reading KEYP_EN_CTRL reg, rc=%d\n", rc);
- return rc;
- }
- kpd_cntl &= ~KEYP_CTRL_KEYP_EN;
- rc = qpnp_kp_write_u8(kp, kpd_cntl, KEYP_EN_CTRL(kp->base));
- if (rc < 0)
- dev_err(&kp->spmi->dev,
- "Error writing KEYP_CTRL reg, rc=%d\n", rc);
- return rc;
- }
- static int qpnp_kp_open(struct input_dev *dev)
- {
- struct qpnp_kp *kp = input_get_drvdata(dev);
- return qpnp_kp_enable(kp);
- }
- static void qpnp_kp_close(struct input_dev *dev)
- {
- struct qpnp_kp *kp = input_get_drvdata(dev);
- qpnp_kp_disable(kp);
- }
- static int __devinit qpnp_keypad_parse_dt(struct qpnp_kp *kp)
- {
- struct matrix_keymap_data *keymap_data;
- int rc, keymap_len, i;
- u32 *keymap;
- const __be32 *map;
- rc = of_property_read_u32(kp->spmi->dev.of_node,
- "keypad,num-rows", &kp->num_rows);
- if (rc) {
- dev_err(&kp->spmi->dev, "Unable to parse 'num-rows'\n");
- return rc;
- }
- rc = of_property_read_u32(kp->spmi->dev.of_node,
- "keypad,num-cols", &kp->num_cols);
- if (rc) {
- dev_err(&kp->spmi->dev, "Unable to parse 'num-cols'\n");
- return rc;
- }
- rc = of_property_read_u32(kp->spmi->dev.of_node,
- "qcom,scan-delay-ms", &kp->scan_delay_ms);
- if (rc && rc != -EINVAL) {
- dev_err(&kp->spmi->dev, "Unable to parse 'scan-delay-ms'\n");
- return rc;
- }
- rc = of_property_read_u32(kp->spmi->dev.of_node,
- "qcom,row-hold-ns", &kp->row_hold_ns);
- if (rc && rc != -EINVAL) {
- dev_err(&kp->spmi->dev, "Unable to parse 'row-hold-ns'\n");
- return rc;
- }
- rc = of_property_read_u32(kp->spmi->dev.of_node,
- "qcom,debounce-ms", &kp->debounce_ms);
- if (rc && rc != -EINVAL) {
- dev_err(&kp->spmi->dev, "Unable to parse 'debounce-ms'\n");
- return rc;
- }
- kp->wakeup = of_property_read_bool(kp->spmi->dev.of_node,
- "qcom,wakeup");
- kp->rep = !of_property_read_bool(kp->spmi->dev.of_node,
- "linux,keypad-no-autorepeat");
- map = of_get_property(kp->spmi->dev.of_node,
- "linux,keymap", &keymap_len);
- if (!map) {
- dev_err(&kp->spmi->dev, "Keymap not specified\n");
- return -EINVAL;
- }
- keymap_data = devm_kzalloc(&kp->spmi->dev,
- sizeof(*keymap_data), GFP_KERNEL);
- if (!keymap_data) {
- dev_err(&kp->spmi->dev, "Unable to allocate memory\n");
- return -ENOMEM;
- }
- keymap_data->keymap_size = keymap_len / sizeof(u32);
- keymap = devm_kzalloc(&kp->spmi->dev,
- sizeof(uint32_t) * keymap_data->keymap_size, GFP_KERNEL);
- if (!keymap) {
- dev_err(&kp->spmi->dev, "could not allocate memory for keymap\n");
- return -ENOMEM;
- }
- for (i = 0; i < keymap_data->keymap_size; i++) {
- unsigned int key = be32_to_cpup(map + i);
- int keycode, row, col;
- row = (key >> 24) & 0xff;
- col = (key >> 16) & 0xff;
- keycode = key & 0xffff;
- keymap[i] = KEY(row, col, keycode);
- }
- keymap_data->keymap = keymap;
- kp->keymap_data = keymap_data;
- return 0;
- }
- static int __devinit qpnp_kp_probe(struct spmi_device *spmi)
- {
- struct qpnp_kp *kp;
- struct resource *keypad_base;
- int rc = 0;
- kp = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_kp), GFP_KERNEL);
- if (!kp) {
- dev_err(&spmi->dev, "%s: Can't allocate qpnp_kp\n",
- __func__);
- return -ENOMEM;
- }
- kp->spmi = spmi;
- rc = qpnp_keypad_parse_dt(kp);
- if (rc < 0) {
- dev_err(&spmi->dev, "Error parsing device tree\n");
- return rc;
- }
- /* the #rows and #columns are compulsary */
- if (!kp->num_cols || !kp->num_rows ||
- kp->num_cols > QPNP_MAX_COLS ||
- kp->num_rows > QPNP_MAX_ROWS ||
- kp->num_cols < QPNP_MIN_COLS ||
- kp->num_rows < QPNP_MIN_ROWS) {
- dev_err(&spmi->dev, "invalid rows/cols input data\n");
- return -EINVAL;
- }
- if (!kp->keymap_data) {
- dev_err(&spmi->dev, "keymap not specified\n");
- return -EINVAL;
- }
- /* the below parameters are optional*/
- if (!kp->scan_delay_ms) {
- kp->scan_delay_ms = KEYP_DEFAULT_SCAN_DELAY;
- } else {
- if (kp->scan_delay_ms > MAX_SCAN_DELAY ||
- kp->scan_delay_ms < MIN_SCAN_DELAY) {
- dev_err(&spmi->dev,
- "invalid keypad scan time supplied\n");
- return -EINVAL;
- }
- }
- if (!kp->row_hold_ns) {
- kp->row_hold_ns = MIN_ROW_HOLD_DELAY;
- } else {
- if (kp->row_hold_ns > MAX_ROW_HOLD_DELAY ||
- kp->row_hold_ns < MIN_ROW_HOLD_DELAY) {
- dev_err(&spmi->dev,
- "invalid keypad row hold time supplied\n");
- return -EINVAL;
- }
- }
- if (!kp->debounce_ms) {
- kp->debounce_ms = KEYP_DEFAULT_DEBOUNCE;
- } else {
- if (kp->debounce_ms > MAX_DEBOUNCE_TIME ||
- kp->debounce_ms < MIN_DEBOUNCE_TIME ||
- (kp->debounce_ms % 5 != 0)) {
- dev_err(&spmi->dev,
- "invalid debounce time supplied\n");
- return -EINVAL;
- }
- }
- kp->input = input_allocate_device();
- if (!kp->input) {
- dev_err(&spmi->dev, "Can't allocate keypad input device\n");
- return -ENOMEM;
- }
- kp->key_sense_irq = spmi_get_irq_byname(spmi, NULL, "kp-sense");
- if (kp->key_sense_irq < 0) {
- dev_err(&spmi->dev, "Unable to get keypad sense irq\n");
- return kp->key_sense_irq;
- }
- kp->key_stuck_irq = spmi_get_irq_byname(spmi, NULL, "kp-stuck");
- if (kp->key_stuck_irq < 0) {
- dev_err(&spmi->dev, "Unable to get stuck irq\n");
- return kp->key_stuck_irq;
- }
- keypad_base = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
- if (!keypad_base) {
- dev_err(&spmi->dev, "Unable to get keypad base address\n");
- return -ENXIO;
- }
- kp->base = keypad_base->start;
- kp->input->name = "qpnp_keypad";
- kp->input->phys = "qpnp_keypad/input0";
- kp->input->id.version = 0x0001;
- kp->input->id.product = 0x0001;
- kp->input->id.vendor = 0x0001;
- kp->input->evbit[0] = BIT_MASK(EV_KEY);
- if (kp->rep)
- set_bit(EV_REP, kp->input->evbit);
- kp->input->keycode = kp->keycodes;
- kp->input->keycodemax = QPNP_MATRIX_MAX_SIZE;
- kp->input->keycodesize = sizeof(kp->keycodes);
- kp->input->open = qpnp_kp_open;
- kp->input->close = qpnp_kp_close;
- matrix_keypad_build_keymap(kp->keymap_data, QPNP_ROW_SHIFT,
- kp->keycodes, kp->input->keybit);
- input_set_capability(kp->input, EV_MSC, MSC_SCAN);
- input_set_drvdata(kp->input, kp);
- /* initialize keypad state */
- memset(kp->keystate, 0xff, sizeof(kp->keystate));
- memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate));
- rc = qpnp_kpd_init(kp);
- if (rc < 0) {
- dev_err(&spmi->dev, "unable to initialize keypad controller\n");
- return rc;
- }
- rc = input_register_device(kp->input);
- if (rc < 0) {
- dev_err(&spmi->dev, "unable to register keypad input device\n");
- return rc;
- }
- rc = devm_request_irq(&spmi->dev, kp->key_sense_irq, qpnp_kp_irq,
- IRQF_TRIGGER_RISING, "qpnp-keypad-sense", kp);
- if (rc < 0) {
- dev_err(&spmi->dev, "failed to request keypad sense irq\n");
- return rc;
- }
- rc = devm_request_irq(&spmi->dev, kp->key_stuck_irq, qpnp_kp_stuck_irq,
- IRQF_TRIGGER_RISING, "qpnp-keypad-stuck", kp);
- if (rc < 0) {
- dev_err(&spmi->dev, "failed to request keypad stuck irq\n");
- return rc;
- }
- device_init_wakeup(&spmi->dev, kp->wakeup);
- return rc;
- }
- static int qpnp_kp_remove(struct spmi_device *spmi)
- {
- struct qpnp_kp *kp = dev_get_drvdata(&spmi->dev);
- device_init_wakeup(&spmi->dev, 0);
- input_unregister_device(kp->input);
- return 0;
- }
- #ifdef CONFIG_PM_SLEEP
- static int qpnp_kp_suspend(struct device *dev)
- {
- struct qpnp_kp *kp = dev_get_drvdata(dev);
- struct input_dev *input_dev = kp->input;
- if (device_may_wakeup(dev)) {
- enable_irq_wake(kp->key_sense_irq);
- } else {
- mutex_lock(&input_dev->mutex);
- if (input_dev->users)
- qpnp_kp_disable(kp);
- mutex_unlock(&input_dev->mutex);
- }
- return 0;
- }
- static int qpnp_kp_resume(struct device *dev)
- {
- struct qpnp_kp *kp = dev_get_drvdata(dev);
- struct input_dev *input_dev = kp->input;
- if (device_may_wakeup(dev)) {
- disable_irq_wake(kp->key_sense_irq);
- } else {
- mutex_lock(&input_dev->mutex);
- if (input_dev->users)
- qpnp_kp_enable(kp);
- mutex_unlock(&input_dev->mutex);
- }
- return 0;
- }
- #endif
- static SIMPLE_DEV_PM_OPS(qpnp_kp_pm_ops,
- qpnp_kp_suspend, qpnp_kp_resume);
- static struct of_device_id spmi_match_table[] = {
- { .compatible = "qcom,qpnp-keypad",
- },
- {}
- };
- static struct spmi_driver qpnp_kp_driver = {
- .probe = qpnp_kp_probe,
- .remove = __devexit_p(qpnp_kp_remove),
- .driver = {
- .name = "qcom,qpnp-keypad",
- .of_match_table = spmi_match_table,
- .owner = THIS_MODULE,
- .pm = &qpnp_kp_pm_ops,
- },
- };
- static int __init qpnp_kp_init(void)
- {
- return spmi_driver_register(&qpnp_kp_driver);
- }
- module_init(qpnp_kp_init);
- static void __exit qpnp_kp_exit(void)
- {
- spmi_driver_unregister(&qpnp_kp_driver);
- }
- module_exit(qpnp_kp_exit);
- MODULE_LICENSE("GPL v2");
- MODULE_DESCRIPTION("QPNP keypad driver");
|