static int pmic8058_kp_scan_matrix(struct pmic8058_kp *kp, unsigned int events) { u16 new_state[PM8058_MAX_ROWS]; u16 old_state[PM8058_MAX_ROWS]; int rc; switch (events) { case 0x1: rc = pmic8058_kp_read_matrix(kp, new_state, NULL); if (pmic8058_detect_ghost_keys(kp, new_state)) return -EINVAL; __pmic8058_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 = pmic8058_kp_read_matrix(kp, new_state, old_state); __pmic8058_kp_scan_matrix(kp, old_state, kp->keystate); __pmic8058_kp_scan_matrix(kp, new_state, old_state); memcpy(kp->keystate, new_state, sizeof(new_state)); break; case 0x2: dev_dbg(kp->dev, "Some key events are missed\n"); rc = pmic8058_kp_read_matrix(kp, new_state, old_state); __pmic8058_kp_scan_matrix(kp, old_state, kp->keystate); __pmic8058_kp_scan_matrix(kp, new_state, old_state); memcpy(kp->keystate, new_state, sizeof(new_state)); break; default: rc = -1; } return rc; }
static int pmic8058_kp_scan_matrix(struct pmic8058_kp *kp, unsigned int events) { u16 new_state[MATRIX_MAX_ROWS]; u16 old_state[MATRIX_MAX_ROWS]; int rc; dev_dbg(kp->dev, "events reported are %d\n", events); switch (events) { case 0x1: rc = pmic8058_kp_read_matrix(kp, new_state, NULL); __pmic8058_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 = pmic8058_kp_read_matrix(kp, new_state, old_state); __pmic8058_kp_scan_matrix(kp, old_state, kp->keystate); __pmic8058_kp_scan_matrix(kp, new_state, old_state); memcpy(kp->keystate, new_state, sizeof(new_state)); break; case 0x2: dev_dbg(kp->dev, "Some key events are missed\n"); rc = pmic8058_kp_read_matrix(kp, new_state, old_state); __pmic8058_kp_scan_matrix(kp, old_state, kp->keystate); __pmic8058_kp_scan_matrix(kp, new_state, old_state); memcpy(kp->keystate, new_state, sizeof(new_state)); break; default: rc = -1; } 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 pmic8058_kp_stuck_irq(int irq, void *data) { u16 new_state[PM8058_MAX_ROWS]; u16 old_state[PM8058_MAX_ROWS]; int rc; struct pmic8058_kp *kp = data; rc = pmic8058_kp_read_matrix(kp, new_state, old_state); __pmic8058_kp_scan_matrix(kp, new_state, kp->stuckstate); return IRQ_HANDLED; }
static int __pmic8058_kp_scan_matrix(struct pmic8058_kp *kp, u16 *new_state, u16 *old_state) { int row, col, code; #ifdef CONFIG_KEYBOARD_ZTE for (row = 0; row < KEYP_NUM_ROWS; row++) { #else for (row = 0; row < kp->pdata->num_rows; row++) { #endif int bits_changed = new_state[row] ^ old_state[row]; if (!bits_changed) continue; #ifdef CONFIG_KEYBOARD_ZTE for (col = 0; col < KEYP_NUM_COLS; col++) { #else for (col = 0; col < kp->pdata->num_cols; col++) { #endif if (!(bits_changed & (1 << col))) continue; dev_dbg(kp->dev, "key [%d:%d] %s\n", row, col, !(new_state[row] & (1 << col)) ? "pressed" : "released"); code = MATRIX_SCAN_CODE(row, col, PM8058_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); } } return 0; } static int pmic8058_detect_ghost_keys(struct pmic8058_kp *kp, u16 *new_state) { int row, found_first = -1; u16 check, row_state; check = 0; for (row = 0; row < kp->pdata->num_rows; row++) { row_state = (~new_state[row]) & ((1 << kp->pdata->num_cols) - 1); if (hweight16(row_state) > 1) { if (found_first == -1) found_first = row; if (check & row_state) { dev_dbg(kp->dev, "detected ghost key on row[%d]" "row[%d]\n", found_first, row); return 1; } } check |= row_state; } return 0; } static int pmic8058_kp_scan_matrix(struct pmic8058_kp *kp, unsigned int events) { u16 new_state[PM8058_MAX_ROWS]; u16 old_state[PM8058_MAX_ROWS]; int rc; switch (events) { case 0x1: rc = pmic8058_kp_read_matrix(kp, new_state, NULL); if (pmic8058_detect_ghost_keys(kp, new_state)) return -EINVAL; __pmic8058_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 = pmic8058_kp_read_matrix(kp, new_state, old_state); __pmic8058_kp_scan_matrix(kp, old_state, kp->keystate); __pmic8058_kp_scan_matrix(kp, new_state, old_state); memcpy(kp->keystate, new_state, sizeof(new_state)); break; case 0x2: dev_dbg(kp->dev, "Some key events are missed\n"); rc = pmic8058_kp_read_matrix(kp, new_state, old_state); __pmic8058_kp_scan_matrix(kp, old_state, kp->keystate); __pmic8058_kp_scan_matrix(kp, new_state, old_state); memcpy(kp->keystate, new_state, sizeof(new_state)); break; default: rc = -1; } return rc; }