/*-
* Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by UCHIYAMA Yasushi.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Called by platform specific scan routines to report key events to hpckbd
*/
static void
pfckbd_input(struct pfckbd_core *pc, int column, uint16_t data)
{
int row, type, val;
unsigned int edge, mask;
edge = data ^ pc->pc_column[column];
if (edge == 0)
return; /* no changes in this column */
pc->pc_column[column] = data;
for (row = 0, mask = 1; row < 16; ++row, mask <<= 1) {
if (mask & edge) {
type = mask & data ? /* up */ 0 : /* down */ 1;
DPRINTF("(%2d, %2d) %d \n", row, column, type);
/*
* Disable output on all lines but the n'th line in D.
* Pull the n'th scan line in D low.
*/
#define PD(n) \
{ (uint16_t)(PFCKBD_HP_PDCR_MASK & (~(1 << (2*(n)+1)))), \
(uint16_t)(PFCKBD_HP_PECR_MASK & 0xffff), \
(uint8_t)~(1 << (n)), \
0xff }
/* bits in D/E control regs we do not touch (XXX: can they change?) */
dc = _reg_read_2(SH7709_PDCR) & ~PFCKBD_HP_PDCR_MASK;
ec = _reg_read_2(SH7709_PECR) & ~PFCKBD_HP_PECR_MASK;
for (column = 0; column < 8; column++) {
/* disable output to all lines except the one we scan */
_reg_write_2(SH7709_PDCR, dc | scan[column].dc);
_reg_write_2(SH7709_PECR, ec | scan[column].ec);
delay(5);
/* pull the scan line low */
_reg_write_1(SH7709_PDDR, scan[column].d);
_reg_write_1(SH7709_PEDR, scan[column].e);
delay(50);
/* read sense */
data = _reg_read_1(SH7709_PFDR)
| (_reg_read_1(SH7709_PCDR) << 8);
pfckbd_input(pc, column, data);
}
/* scan no lines */
_reg_write_1(SH7709_PDDR, 0xff);
_reg_write_1(SH7709_PEDR, 0xff);
/* enable all scan lines */
_reg_write_2(SH7709_PDCR, dc | (0x5555 & PFCKBD_HP_PDCR_MASK));
_reg_write_2(SH7709_PECR, ec | (0x5555 & PFCKBD_HP_PECR_MASK));
/*
* Disable output on all lines but the n'th line in C.
* Pull the n'th scan line in C low.
*/
#define PC(n) \
{ (uint16_t)(PFCKBD_HITACHI_PCCR_MASK & (~(1 << (2*(n)+1)))), \
(uint16_t)(PFCKBD_HITACHI_PDCR_MASK & 0xffff), \
(uint16_t)(PFCKBD_HITACHI_PECR_MASK & 0xffff), \
(uint8_t)(PFCKBD_HITACHI_PCDR_SCN_MASK & ~(1 << (n))), \
PFCKBD_HITACHI_PDDR_SCN_MASK, \
PFCKBD_HITACHI_PEDR_SCN_MASK }
/* bits in C/D/E control regs we do not touch (XXX: can they change?) */
cc = _reg_read_2(SH7709_PCCR) & ~PFCKBD_HITACHI_PCCR_MASK;
dc = _reg_read_2(SH7709_PDCR) & ~PFCKBD_HITACHI_PDCR_MASK;
ec = _reg_read_2(SH7709_PECR) & ~PFCKBD_HITACHI_PECR_MASK;
for (i = 0; i < 12; i++) {
/* disable output to all lines except the one we scan */
_reg_write_2(SH7709_PCCR, cc | scan[i].cc);
_reg_write_2(SH7709_PDCR, dc | scan[i].dc);
_reg_write_2(SH7709_PECR, ec | scan[i].ec);
delay(5);
cd = _reg_read_1(SH7709_PCDR) & ~PFCKBD_HITACHI_PCDR_SCN_MASK;
dd = _reg_read_1(SH7709_PDDR) & ~PFCKBD_HITACHI_PDDR_SCN_MASK;
ed = _reg_read_1(SH7709_PEDR) & ~PFCKBD_HITACHI_PEDR_SCN_MASK;
/* pull the scan line low */
_reg_write_1(SH7709_PCDR, cd | scan[i].c);
_reg_write_1(SH7709_PDDR, dd | scan[i].d);
_reg_write_1(SH7709_PEDR, ed | scan[i].e);
delay(50);
/* bits in C/D/E control regs we do not touch (XXX: can they change?) */
cc = _reg_read_2(SH7709_PCCR) & ~PFCKBD_HITACHI_PCCR_MASK;
dc = _reg_read_2(SH7709_PDCR) & ~PFCKBD_HITACHI_PDCR_MASK;
ec = _reg_read_2(SH7709_PECR) & ~PFCKBD_HITACHI_PECR_MASK;
/* disable output to all lines except the one we scan */
_reg_write_2(SH7709_PCCR, cc | poll.cc);
_reg_write_2(SH7709_PDCR, dc | poll.dc);
_reg_write_2(SH7709_PECR, ec | poll.ec);
delay(5);
cd = _reg_read_1(SH7709_PCDR) & ~PFCKBD_HITACHI_PCDR_SCN_MASK;
dd = _reg_read_1(SH7709_PDDR) & ~PFCKBD_HITACHI_PDDR_SCN_MASK;
ed = _reg_read_1(SH7709_PEDR) & ~PFCKBD_HITACHI_PEDR_SCN_MASK;
/* pull the scan line low */
_reg_write_1(SH7709_PCDR, cd | poll.c);
_reg_write_1(SH7709_PDDR, dd | poll.d);
_reg_write_1(SH7709_PEDR, ed | poll.e);
delay(50);
/* poll POWER On */
while (_reg_read_1(SH7709_PCDR) & PFCKBD_HITACHI_PCDR_SNS_MASK & 0x01);
/* enable all scan lines */
_reg_write_2(SH7709_PCCR, cc | (0x5555 & PFCKBD_HITACHI_PCCR_MASK));
_reg_write_2(SH7709_PDCR, dc | (0x5555 & PFCKBD_HITACHI_PDCR_MASK));
_reg_write_2(SH7709_PECR, ec | (0x5555 & PFCKBD_HITACHI_PECR_MASK));
}