Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 202181
b: refs/heads/master
c: 69a4af6
h: refs/heads/master
i:
  202179: 7f72508
v: v3
  • Loading branch information
Xiaolong CHEN authored and Dmitry Torokhov committed Jun 25, 2010
1 parent 0ef9570 commit f1fc4f9
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 8 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e725a4945d6eedd400dd5d0ead293d980a2f76ec
refs/heads/master: 69a4af606ed4836faa2ec69b1d217f384b8235e7
134 changes: 127 additions & 7 deletions trunk/drivers/input/keyboard/adp5588-keys.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ struct adp5588_kpad {
struct delayed_work work;
unsigned long delay;
unsigned short keycode[ADP5588_KEYMAPSIZE];
const struct adp5588_gpi_map *gpimap;
unsigned short gpimapsize;
};

static int adp5588_read(struct i2c_client *client, u8 reg)
Expand All @@ -84,12 +86,37 @@ static int adp5588_write(struct i2c_client *client, u8 reg, u8 val)
return i2c_smbus_write_byte_data(client, reg, val);
}

static void adp5588_report_events(struct adp5588_kpad *kpad, int ev_cnt)
{
int i, j;

for (i = 0; i < ev_cnt; i++) {
int key = adp5588_read(kpad->client, Key_EVENTA + i);
int key_val = key & KEY_EV_MASK;

if (key_val >= GPI_PIN_BASE && key_val <= GPI_PIN_END) {
for (j = 0; j < kpad->gpimapsize; j++) {
if (key_val == kpad->gpimap[j].pin) {
input_report_switch(kpad->input,
kpad->gpimap[j].sw_evt,
key & KEY_EV_PRESSED);
break;
}
}
} else {
input_report_key(kpad->input,
kpad->keycode[key_val - 1],
key & KEY_EV_PRESSED);
}
}
}

static void adp5588_work(struct work_struct *work)
{
struct adp5588_kpad *kpad = container_of(work,
struct adp5588_kpad, work.work);
struct i2c_client *client = kpad->client;
int i, key, status, ev_cnt;
int status, ev_cnt;

status = adp5588_read(client, INT_STAT);

Expand All @@ -99,12 +126,7 @@ static void adp5588_work(struct work_struct *work)
if (status & KE_INT) {
ev_cnt = adp5588_read(client, KEY_LCK_EC_STAT) & KEC;
if (ev_cnt) {
for (i = 0; i < ev_cnt; i++) {
key = adp5588_read(client, Key_EVENTA + i);
input_report_key(kpad->input,
kpad->keycode[(key & KEY_EV_MASK) - 1],
key & KEY_EV_PRESSED);
}
adp5588_report_events(kpad, ev_cnt);
input_sync(kpad->input);
}
}
Expand All @@ -130,6 +152,7 @@ static int __devinit adp5588_setup(struct i2c_client *client)
{
struct adp5588_kpad_platform_data *pdata = client->dev.platform_data;
int i, ret;
unsigned char evt_mode1 = 0, evt_mode2 = 0, evt_mode3 = 0;

ret = adp5588_write(client, KP_GPIO1, KP_SEL(pdata->rows));
ret |= adp5588_write(client, KP_GPIO2, KP_SEL(pdata->cols) & 0xFF);
Expand All @@ -144,6 +167,23 @@ static int __devinit adp5588_setup(struct i2c_client *client)
for (i = 0; i < KEYP_MAX_EVENT; i++)
ret |= adp5588_read(client, Key_EVENTA);

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

if (pdata->gpimapsize) {
ret |= adp5588_write(client, GPI_EM1, evt_mode1);
ret |= adp5588_write(client, GPI_EM2, evt_mode2);
ret |= adp5588_write(client, GPI_EM3, evt_mode3);
}

ret |= adp5588_write(client, INT_STAT, CMP2_INT | CMP1_INT |
OVR_FLOW_INT | K_LCK_INT |
GPI_INT | KE_INT); /* Status is W1C */
Expand All @@ -158,6 +198,44 @@ static int __devinit adp5588_setup(struct i2c_client *client)
return 0;
}

static void __devinit adp5588_report_switch_state(struct adp5588_kpad *kpad)
{
int gpi_stat1 = adp5588_read(kpad->client, GPIO_DAT_STAT1);
int gpi_stat2 = adp5588_read(kpad->client, GPIO_DAT_STAT2);
int gpi_stat3 = adp5588_read(kpad->client, GPIO_DAT_STAT3);
int gpi_stat_tmp, pin_loc;
int i;

for (i = 0; i < kpad->gpimapsize; i++) {
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(&kpad->client->dev,
"Can't read GPIO_DAT_STAT switch %d default to OFF\n",
pin);
gpi_stat_tmp = 0;
}

input_report_switch(kpad->input,
kpad->gpimap[i].sw_evt,
!(gpi_stat_tmp & (1 << pin_loc)));
}

input_sync(kpad->input);
}


static int __devinit adp5588_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
Expand Down Expand Up @@ -189,6 +267,37 @@ static int __devinit adp5588_probe(struct i2c_client *client,
return -EINVAL;
}

if (!pdata->gpimap && pdata->gpimapsize) {
dev_err(&client->dev, "invalid 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;
}
}
}

if (!client->irq) {
dev_err(&client->dev, "no IRQ?\n");
return -EINVAL;
Expand Down Expand Up @@ -233,6 +342,9 @@ static int __devinit adp5588_probe(struct i2c_client *client,
memcpy(kpad->keycode, pdata->keymap,
pdata->keymapsize * input->keycodesize);

kpad->gpimap = pdata->gpimap;
kpad->gpimapsize = pdata->gpimapsize;

/* setup input device */
__set_bit(EV_KEY, input->evbit);

Expand All @@ -243,6 +355,11 @@ static int __devinit adp5588_probe(struct i2c_client *client,
__set_bit(kpad->keycode[i] & KEY_MAX, input->keybit);
__clear_bit(KEY_RESERVED, input->keybit);

if (kpad->gpimapsize)
__set_bit(EV_SW, input->evbit);
for (i = 0; i < kpad->gpimapsize; i++)
__set_bit(kpad->gpimap[i].sw_evt, input->swbit);

error = input_register_device(input);
if (error) {
dev_err(&client->dev, "unable to register input device\n");
Expand All @@ -261,6 +378,9 @@ static int __devinit adp5588_probe(struct i2c_client *client,
if (error)
goto err_free_irq;

if (kpad->gpimapsize)
adp5588_report_switch_state(kpad);

device_init_wakeup(&client->dev, 1);
i2c_set_clientdata(client, kpad);

Expand Down
36 changes: 36 additions & 0 deletions trunk/include/linux/i2c/adp5588.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,40 @@

#define ADP5588_KEYMAPSIZE 80

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

struct adp5588_kpad_platform_data {
int rows; /* Number of rows */
int cols; /* Number of columns */
Expand All @@ -87,6 +121,8 @@ 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 */
const struct adp5588_gpi_map *gpimap;
unsigned short gpimapsize;
};

struct adp5588_gpio_platform_data {
Expand Down

0 comments on commit f1fc4f9

Please sign in to comment.