static void pxa27x_keyboard_event (PXA2xxKeyPadState *kp, int keycode) { int row, col,rel; if(!(kp->kpc & KPC_ME)) /* skip if not enabled */ return; if(kp->kpc & KPC_AS || kp->kpc & KPC_ASACT) { if(kp->kpc & KPC_AS) kp->kpc &= ~(KPC_AS); rel = (keycode & 0x80) ? 1 : 0; /* key release from qemu */ keycode &= ~(0x80); /* strip qemu key release bit */ row = kp->map[keycode].row; col = kp->map[keycode].column; if(row == -1 || col == -1) return; switch (col) { case 0: case 1: if(rel) kp->kpasmkp0 = ~(0xffffffff); else kp->kpasmkp0 |= KPASMKPx_MKC(row,col); break; case 2: case 3: if(rel) kp->kpasmkp1 = ~(0xffffffff); else kp->kpasmkp1 |= KPASMKPx_MKC(row,col); break; case 4: case 5: if(rel) kp->kpasmkp2 = ~(0xffffffff); else kp->kpasmkp2 |= KPASMKPx_MKC(row,col); break; case 6: case 7: if(rel) kp->kpasmkp3 = ~(0xffffffff); else kp->kpasmkp3 |= KPASMKPx_MKC(row,col); break; } /* switch */ goto out; } return; out: if(kp->kpc & KPC_MIE) { kp->kpc |= KPC_MI; qemu_irq_raise(kp->irq); } return; }
static void pxa27x_keyboard_event (PXA2xxKeyPadState *kp, int keycode) { int row, col, rel, assert_irq = 0; uint32_t val; if (keycode == 0xe0) { kp->alt_code = 1; return; } if(!(kp->kpc & KPC_ME)) /* skip if not enabled */ return; rel = (keycode & 0x80) ? 1 : 0; /* key release from qemu */ keycode &= ~0x80; /* strip qemu key release bit */ if (kp->alt_code) { keycode |= 0x80; kp->alt_code = 0; } row = kp->map[keycode].row; col = kp->map[keycode].column; if (row == -1 || col == -1) { return; } val = KPASMKPx_MKC(row, col); if (rel) { if (kp->kpasmkp[col / 2] & val) { kp->kpasmkp[col / 2] &= ~val; kp->pressed_cnt--; assert_irq = 1; } } else { if (!(kp->kpasmkp[col / 2] & val)) { kp->kpasmkp[col / 2] |= val; kp->pressed_cnt++; assert_irq = 1; } } kp->kpas = ((kp->pressed_cnt & 0x1f) << 26) | (0xf << 4) | 0xf; if (kp->pressed_cnt == 1) { kp->kpas &= ~((0xf << 4) | 0xf); if (rel) { pxa27x_keypad_find_pressed_key(kp, &row, &col); } kp->kpas |= ((row & 0xf) << 4) | (col & 0xf); } if (!(kp->kpc & (KPC_AS | KPC_ASACT))) assert_irq = 0; if (assert_irq && (kp->kpc & KPC_MIE)) { kp->kpc |= KPC_MI; qemu_irq_raise(kp->irq); } }
static irqreturn_t pxakbd_irq_handler(int irq, void *dev_id) { struct platform_device *pdev = dev_id; struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data; struct input_dev *input_dev = platform_get_drvdata(pdev); unsigned long kpc = KPC; int p, row, col, rel; if (kpc & KPC_DI) { unsigned long kpdk = KPDK; if (!(kpdk & KPDK_DKP)) { /* better luck next time */ } else if (kpc & KPC_REE0) { unsigned long kprec = KPREC; KPREC = 0x7f; if (kprec & KPREC_OF0) rel = (kprec & 0xff) + 0x7f; else if (kprec & KPREC_UF0) rel = (kprec & 0xff) - 0x7f - 0xff; else rel = (kprec & 0xff) - 0x7f; if (rel) { input_report_rel(input_dev, REL_WHEEL, rel); input_sync(input_dev); } } } if (kpc & KPC_MI) { /* report the status of every button */ for (row = 0; row < pdata->nr_rows; row++) { for (col = 0; col < pdata->nr_cols; col++) { p = KPASMKP(col) & KPASMKPx_MKC(row, col) ? 1 : 0; pr_debug("keycode %x - pressed %x\n", pdata->keycodes[row][col], p); input_report_key(input_dev, pdata->keycodes[row][col], p); } } input_sync(input_dev); } return IRQ_HANDLED; }