From: TAO HU <tghk48@motorola.com>
To: Michael Hennerich <hennerich@blackfin.uclinux.org>,
Dmitry Torokhov <dmitry.torokhov@gmail.com>,
Dmitry Torokhov <dtor@mail.ru>
Cc: linux-input@vger.kernel.org,
"Yuan.Bo YE" <yuan-bo.ye@motorola.com>,
Xiaolong CHEN <xiao-long.chen@motorola.com>
Subject: Re: [RFC] Input: ADP5588 - Support GPI event for ADP5588 devices
Date: Fri, 11 Jun 2010 10:39:33 +0800 [thread overview]
Message-ID: <AANLkTimubPIlTrbIBUGHbvOHK1XAhUATbWjEgPIk_QX1@mail.gmail.com> (raw)
In-Reply-To: <AANLkTinaguxmGVrx3lWqNT__xE6S2CIjoLc69TrS-yyN@mail.gmail.com>
Hi, Michael and Dmitry
Any comments?
--
Best Regards
Hu Tao
On Thu, Jun 10, 2010 at 10:36 AM, Xiaolong CHEN
<xiao-long.chen@motorola.com> wrote:
> Hi,
>
> This patch supports GPI event for ADP5588 devices.
>
> Kernel Version: 2.6.34
>
> A column or row configured as a GPI can be programmed to be part of
> the key event table and therefore also capable of generating a key
> event interrupt. A key event interrupt caused by a GPI follows the
> same process flow as a key event interrupt caused by a key press. GPIs
> configured as part of the key event table allow single key switches
> and other GPI interrupts to bemonitored. As part of the event table,
> GPIs are represented by the decimal value 97 (0x61or 1100001) through
> the decimal value 114 (0x72 or 1110010). See Table as below for GPI
> event number assignments for rows and columns.
>
> GPI Event Number Assignments for Rows
> Row0 Row1 Row2 Row3 Row4 Row5 Row6 Row7
> 97 98 99 100 101 102 103 104
>
> GPI Event Number Assignments for Cols
> Col0 Col1 Col2 Col3 Col4 Col5 Col6 Col7 Col8 Col9
> 105 106 107 108 109 110 111 112 113 114
>
> Usage:
> 1. Enable CONFIG_KEYBOARD_ADP5588_GPI_EVENT
> 2. Add gpimap and gpimapsize setting in adp5588_kpad_platform_data
> (The settings should not conflict with rows/cols for keymap)
>
> Patch:
> From 75412f66cc16c19c8b6046ed499ccf6e34db01c3 Mon Sep 17 00:00:00 2001
> From: xiaolong <a21785@motorola.com>
> Date: Thu, 10 Jun 2010 05:13:13 -0400
> Subject: [PATCH] Input: ADP5588 - Support GPI event for ADP5588 devices
>
> A column or row configured as a GPI can be programmed to be part
> of the key event table and therefore also capable of generating a
> key event interrupt. A key event interrupt caused by a GPI follows
> the same process flow as a key event interrupt caused by a key
> press. GPIs configured as part of the key event table allow single
> key switches and other GPI interrupts to bemonitored. As part of
> the event table, GPIs are represented by the decimal value 97 (0x61
> or 1100001) through the decimal value 114 (0x72 or 1110010). See
> Table as below for GPI event number assignments for rows and columns.
>
> GPI Event Number Assignments for Rows
> Row0 Row1 Row2 Row3 Row4 Row5 Row6 Row7
> 97 98 99 100 101 102 103 104
>
> GPI Event Number Assignments for Cols
> Col0 Col1 Col2 Col3 Col4 Col5 Col6 Col7 Col8 Col9
> 105 106 107 108 109 110 111 112 113 114
>
> Signed-off-by: Xiaolong Chen <xiao-long.chen@motorola.com>
> Signed-off-by: Yuanbo Ye <yuan-bo.ye@motorola.com>
> Signed-off-by: Tao Hu <taohu@motorola.com>
> ---
> drivers/input/keyboard/Kconfig | 8 ++
> drivers/input/keyboard/adp5588-keys.c | 126 +++++++++++++++++++++++++++++++++
> include/linux/i2c/adp5588.h | 40 ++++++++++
> 3 files changed, 174 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
> index 64c1023..aebf8de 100644
> --- a/drivers/input/keyboard/Kconfig
> +++ b/drivers/input/keyboard/Kconfig
> @@ -44,6 +44,14 @@ config KEYBOARD_ADP5588
> To compile this driver as a module, choose M here: the
> module will be called adp5588-keys.
>
> +config KEYBOARD_ADP5588_GPI_EVENT
> + tristate "ADP5588 GPI event on key event interrupt"
> + depends on KEYBOARD_ADP5588
> + help
> + Enable GPI events on key event interrupt, GPIs configured
> + as part of the key event table allow single key switches
> + and other GPI interrupts to be monitored.
> +
> config KEYBOARD_AMIGA
> tristate "Amiga keyboard"
> depends on AMIGA
> diff --git a/drivers/input/keyboard/adp5588-keys.c
> b/drivers/input/keyboard/adp5588-keys.c
> index b5142d2..4cd5cee 100644
> --- a/drivers/input/keyboard/adp5588-keys.c
> +++ b/drivers/input/keyboard/adp5588-keys.c
> @@ -66,6 +66,10 @@ struct adp5588_kpad {
> struct delayed_work work;
> unsigned long delay;
> unsigned short keycode[ADP5588_KEYMAPSIZE];
> +#ifdef CONFIG_KEYBOARD_ADP5588_GPI_EVENT
> + const struct adp5588_gpi_map *gpimap;
> + unsigned short gpimapsize;
> +#endif
> };
>
> static int adp5588_read(struct i2c_client *client, u8 reg)
> @@ -99,10 +103,33 @@ static void adp5588_work(struct work_struct *work)
> ev_cnt = adp5588_read(client, KEY_LCK_EC_STAT) & KEC;
> if (ev_cnt) {
> for (i = 0; i < ev_cnt; i++) {
> +#ifdef CONFIG_KEYBOARD_ADP5588_GPI_EVENT
> + int j, key_val, pin;
> +#endif
> key = adp5588_read(client, Key_EVENTA + i);
> +#ifdef CONFIG_KEYBOARD_ADP5588_GPI_EVENT
> + key_val = key & (~KEY_EV_PRESSED);
> +
> + if ((key_val >= GPI_PIN_BASE) &&
> + (key_val <= GPI_PIN_END)) {
> + for (j = 0; j < kpad->gpimapsize; j++) {
> + pin = kpad->gpimap[j].pin;
> + if (key_val != pin)
> + continue;
> +
> + input_report_switch(kpad->input,
> + kpad->gpimap[j].sw_evt,
> + key & KEY_EV_PRESSED);
> + break;
> + }
> + } else {
> +#endif
> input_report_key(kpad->input,
> kpad->keycode[(key & KEY_EV_MASK) - 1],
> key & KEY_EV_PRESSED);
> +#ifdef CONFIG_KEYBOARD_ADP5588_GPI_EVENT
> + }
> +#endif
> }
> input_sync(kpad->input);
> }
> @@ -129,6 +156,9 @@ static int __devinit adp5588_setup(struct
> i2c_client *client)
> {
> struct adp5588_kpad_platform_data *pdata = client->dev.platform_data;
> int i, ret;
> +#ifdef CONFIG_KEYBOARD_ADP5588_GPI_EVENT
> + unsigned char evt_mode1 = 0, evt_mode2 = 0, evt_mode3 = 0;
> +#endif
>
> ret = adp5588_write(client, KP_GPIO1, KP_SEL(pdata->rows));
> ret |= adp5588_write(client, KP_GPIO2, KP_SEL(pdata->cols) & 0xFF);
> @@ -143,6 +173,23 @@ static int __devinit adp5588_setup(struct
> i2c_client *client)
> for (i = 0; i < KEYP_MAX_EVENT; i++)
> ret |= adp5588_read(client, Key_EVENTA);
>
> +#ifdef CONFIG_KEYBOARD_ADP5588_GPI_EVENT
> + for (i = 0; i < pdata->gpimapsize; i++) {
> + unsigned short pin = pdata->gpimap[i].pin;
> +
> + if (pin <= GPI_PIN_ROW_END) {
> + evt_mode1 |= (1 << (pin - GPI_PIN_ROW_BASE));
> + } else {
> + evt_mode2 |= ((1 << (pin - GPI_PIN_COL_BASE)) & 0xFF);
> + evt_mode3 |= ((1 << (pin - GPI_PIN_COL_BASE)) >> 8);
> + }
> + }
> +
> + ret |= adp5588_write(client, GPI_EM1, evt_mode1);
> + ret |= adp5588_write(client, GPI_EM2, evt_mode2);
> + ret |= adp5588_write(client, GPI_EM3, evt_mode3);
> +#endif
> +
> ret |= adp5588_write(client, INT_STAT, CMP2_INT | CMP1_INT |
> OVR_FLOW_INT | K_LCK_INT |
> GPI_INT | KE_INT); /* Status is W1C */
> @@ -166,6 +213,9 @@ static int __devinit adp5588_probe(struct
> i2c_client *client,
> unsigned int revid;
> int ret, i;
> int error;
> +#ifdef CONFIG_KEYBOARD_ADP5588_GPI_EVENT
> + int gpi_stat1 = 0, gpi_stat2 = 0, gpi_stat3 = 0;
> +#endif
>
> if (!i2c_check_functionality(client->adapter,
> I2C_FUNC_SMBUS_BYTE_DATA)) {
> @@ -188,6 +238,39 @@ static int __devinit adp5588_probe(struct
> i2c_client *client,
> return -EINVAL;
> }
>
> +#ifdef CONFIG_KEYBOARD_ADP5588_GPI_EVENT
> + if (!pdata->gpimap) {
> + dev_err(&client->dev, "no gpimap from pdata\n");
> + return -EINVAL;
> + }
> +
> + if (pdata->gpimapsize > ADP5588_GPIMAPSIZE_MAX) {
> + dev_err(&client->dev, "invalid gpimapsize\n");
> + return -EINVAL;
> + }
> +
> + for (i = 0; i < pdata->gpimapsize; i++) {
> + unsigned short pin = pdata->gpimap[i].pin;
> +
> + if ((pin < GPI_PIN_BASE) || (pin > GPI_PIN_END)) {
> + dev_err(&client->dev, "invalid gpi pin data\n");
> + return -EINVAL;
> + }
> +
> + if (pin <= GPI_PIN_ROW_END) {
> + if ((pin - GPI_PIN_ROW_BASE + 1) <= pdata->rows) {
> + dev_err(&client->dev, "invalid gpi row data\n");
> + return -EINVAL;
> + }
> + } else {
> + if ((pin - GPI_PIN_COL_BASE + 1) <= pdata->cols) {
> + dev_err(&client->dev, "invalid gpi col data\n");
> + return -EINVAL;
> + }
> + }
> + }
> +#endif
> +
> if (!client->irq) {
> dev_err(&client->dev, "no IRQ?\n");
> return -EINVAL;
> @@ -232,6 +315,11 @@ static int __devinit adp5588_probe(struct
> i2c_client *client,
> memcpy(kpad->keycode, pdata->keymap,
> pdata->keymapsize * input->keycodesize);
>
> +#ifdef CONFIG_KEYBOARD_ADP5588_GPI_EVENT
> + kpad->gpimap = pdata->gpimap;
> + kpad->gpimapsize = pdata->gpimapsize;
> +#endif
> +
> /* setup input device */
> __set_bit(EV_KEY, input->evbit);
>
> @@ -242,6 +330,12 @@ static int __devinit adp5588_probe(struct
> i2c_client *client,
> __set_bit(kpad->keycode[i] & KEY_MAX, input->keybit);
> __clear_bit(KEY_RESERVED, input->keybit);
>
> +#ifdef CONFIG_KEYBOARD_ADP5588_GPI_EVENT
> + __set_bit(EV_SW, input->evbit);
> + for (i = 0; i < kpad->gpimapsize; i++)
> + __set_bit(kpad->gpimap[i].sw_evt, input->swbit);
> +#endif
> +
> error = input_register_device(input);
> if (error) {
> dev_err(&client->dev, "unable to register input device\n");
> @@ -263,6 +357,38 @@ static int __devinit adp5588_probe(struct
> i2c_client *client,
> device_init_wakeup(&client->dev, 1);
> i2c_set_clientdata(client, kpad);
>
> +#ifdef CONFIG_KEYBOARD_ADP5588_GPI_EVENT
> + gpi_stat1 = adp5588_read(client, GPIO_DAT_STAT1);
> + gpi_stat2 = adp5588_read(client, GPIO_DAT_STAT2);
> + gpi_stat3 = adp5588_read(client, GPIO_DAT_STAT3);
> +
> + for (i = 0; i < kpad->gpimapsize; i++) {
> + int gpi_stat_tmp, pin_loc;
> + unsigned short pin = kpad->gpimap[i].pin;
> +
> + if (pin <= GPI_PIN_ROW_END) {
> + gpi_stat_tmp = gpi_stat1;
> + pin_loc = pin - GPI_PIN_ROW_BASE;
> + } else if ((pin - GPI_PIN_COL_BASE) < 8) {
> + gpi_stat_tmp = gpi_stat2;
> + pin_loc = pin - GPI_PIN_COL_BASE;
> + } else {
> + gpi_stat_tmp = gpi_stat3;
> + pin_loc = pin - GPI_PIN_COL_BASE - 8;
> + }
> +
> + if (gpi_stat_tmp < 0) {
> + dev_err(&client->dev, "Can't read GPIO_DAT_STAT "
> + "switch %d default to OFF\n", pin);
> + gpi_stat_tmp = 0;
> + }
> +
> + input_report_switch(input, kpad->gpimap[i].sw_evt,
> + !(gpi_stat_tmp & (1 << pin_loc)));
> + input_sync(input);
> + }
> +#endif
> +
> dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq);
> return 0;
>
> diff --git a/include/linux/i2c/adp5588.h b/include/linux/i2c/adp5588.h
> index 02c9af3..bb6365d 100644
> --- a/include/linux/i2c/adp5588.h
> +++ b/include/linux/i2c/adp5588.h
> @@ -78,6 +78,42 @@
>
> #define ADP5588_KEYMAPSIZE 80
>
> +#ifdef CONFIG_KEYBOARD_ADP5588_GPI_EVENT
> +#define GPI_PIN_ROW0 97
> +#define GPI_PIN_ROW1 98
> +#define GPI_PIN_ROW2 99
> +#define GPI_PIN_ROW3 100
> +#define GPI_PIN_ROW4 101
> +#define GPI_PIN_ROW5 102
> +#define GPI_PIN_ROW6 103
> +#define GPI_PIN_ROW7 104
> +#define GPI_PIN_COL0 105
> +#define GPI_PIN_COL1 106
> +#define GPI_PIN_COL2 107
> +#define GPI_PIN_COL3 108
> +#define GPI_PIN_COL4 109
> +#define GPI_PIN_COL5 110
> +#define GPI_PIN_COL6 111
> +#define GPI_PIN_COL7 112
> +#define GPI_PIN_COL8 113
> +#define GPI_PIN_COL9 114
> +
> +#define GPI_PIN_ROW_BASE GPI_PIN_ROW0
> +#define GPI_PIN_ROW_END GPI_PIN_ROW7
> +#define GPI_PIN_COL_BASE GPI_PIN_COL0
> +#define GPI_PIN_COL_END GPI_PIN_COL9
> +
> +#define GPI_PIN_BASE GPI_PIN_ROW_BASE
> +#define GPI_PIN_END GPI_PIN_COL_END
> +
> +#define ADP5588_GPIMAPSIZE_MAX (GPI_PIN_END - GPI_PIN_BASE + 1)
> +
> +struct adp5588_gpi_map {
> + unsigned short pin;
> + unsigned short sw_evt;
> +};
> +#endif
> +
> struct adp5588_kpad_platform_data {
> int rows; /* Number of rows */
> int cols; /* Number of columns */
> @@ -87,6 +123,10 @@ struct adp5588_kpad_platform_data {
> unsigned en_keylock:1; /* Enable Key Lock feature */
> unsigned short unlock_key1; /* Unlock Key 1 */
> unsigned short unlock_key2; /* Unlock Key 2 */
> +#ifdef CONFIG_KEYBOARD_ADP5588_GPI_EVENT
> + const struct adp5588_gpi_map *gpimap;
> + unsigned short gpimapsize;
> +#endif
> };
>
> struct adp5588_gpio_platform_data {
> --
> 1.5.4.3
>
> If there is any comments and suggestion, please let me know.
>
> Thanks,
> Xiaolong
>
--
Best Regards
Hu Tao
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2010-06-11 3:33 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-06-10 2:36 [RFC] Input: ADP5588 - Support GPI event for ADP5588 devices Xiaolong CHEN
2010-06-10 19:28 ` Dmitry Torokhov
2010-06-17 7:33 ` Xiaolong CHEN
2010-06-22 11:12 ` [PATCH] " Xiaolong CHEN
2010-06-24 4:11 ` [RFC] " TAO HU
2010-06-25 8:15 ` Dmitry Torokhov
2010-06-11 2:39 ` TAO HU [this message]
[not found] ` <544AC56F16B56944AEC3BD4E3D5917712E66C5BE31@LIMKCMBX1.ad.analog.com>
2010-06-11 12:04 ` TAO HU
-- strict thread matches above, loose matches on Subject: below --
2010-06-09 10:37 Xiaolong CHEN
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=AANLkTimubPIlTrbIBUGHbvOHK1XAhUATbWjEgPIk_QX1@mail.gmail.com \
--to=tghk48@motorola.com \
--cc=dmitry.torokhov@gmail.com \
--cc=dtor@mail.ru \
--cc=hennerich@blackfin.uclinux.org \
--cc=linux-input@vger.kernel.org \
--cc=xiao-long.chen@motorola.com \
--cc=yuan-bo.ye@motorola.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).