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, 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; }