aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorXiaolong CHEN <a21785@motorola.com>2010-06-24 22:10:40 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2010-06-24 22:13:10 -0400
commit69a4af606ed4836faa2ec69b1d217f384b8235e7 (patch)
tree56ca639c35e5eaa2029c900ced2a989bf5476375 /drivers/input
parente725a4945d6eedd400dd5d0ead293d980a2f76ec (diff)
Input: adp5588-keys - support GPI events 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 be monitored. 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 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> Acked-by: Michael Hennerich <michael.hennerich@analog.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/keyboard/adp5588-keys.c134
1 files changed, 127 insertions, 7 deletions
diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c
index 4771ab172b59..4ef789ef1042 100644
--- a/drivers/input/keyboard/adp5588-keys.c
+++ b/drivers/input/keyboard/adp5588-keys.c
@@ -67,6 +67,8 @@ struct adp5588_kpad {
67 struct delayed_work work; 67 struct delayed_work work;
68 unsigned long delay; 68 unsigned long delay;
69 unsigned short keycode[ADP5588_KEYMAPSIZE]; 69 unsigned short keycode[ADP5588_KEYMAPSIZE];
70 const struct adp5588_gpi_map *gpimap;
71 unsigned short gpimapsize;
70}; 72};
71 73
72static int adp5588_read(struct i2c_client *client, u8 reg) 74static int adp5588_read(struct i2c_client *client, u8 reg)
@@ -84,12 +86,37 @@ static int adp5588_write(struct i2c_client *client, u8 reg, u8 val)
84 return i2c_smbus_write_byte_data(client, reg, val); 86 return i2c_smbus_write_byte_data(client, reg, val);
85} 87}
86 88
89static void adp5588_report_events(struct adp5588_kpad *kpad, int ev_cnt)
90{
91 int i, j;
92
93 for (i = 0; i < ev_cnt; i++) {
94 int key = adp5588_read(kpad->client, Key_EVENTA + i);
95 int key_val = key & KEY_EV_MASK;
96
97 if (key_val >= GPI_PIN_BASE && key_val <= GPI_PIN_END) {
98 for (j = 0; j < kpad->gpimapsize; j++) {
99 if (key_val == kpad->gpimap[j].pin) {
100 input_report_switch(kpad->input,
101 kpad->gpimap[j].sw_evt,
102 key & KEY_EV_PRESSED);
103 break;
104 }
105 }
106 } else {
107 input_report_key(kpad->input,
108 kpad->keycode[key_val - 1],
109 key & KEY_EV_PRESSED);
110 }
111 }
112}
113
87static void adp5588_work(struct work_struct *work) 114static void adp5588_work(struct work_struct *work)
88{ 115{
89 struct adp5588_kpad *kpad = container_of(work, 116 struct adp5588_kpad *kpad = container_of(work,
90 struct adp5588_kpad, work.work); 117 struct adp5588_kpad, work.work);
91 struct i2c_client *client = kpad->client; 118 struct i2c_client *client = kpad->client;
92 int i, key, status, ev_cnt; 119 int status, ev_cnt;
93 120
94 status = adp5588_read(client, INT_STAT); 121 status = adp5588_read(client, INT_STAT);
95 122
@@ -99,12 +126,7 @@ static void adp5588_work(struct work_struct *work)
99 if (status & KE_INT) { 126 if (status & KE_INT) {
100 ev_cnt = adp5588_read(client, KEY_LCK_EC_STAT) & KEC; 127 ev_cnt = adp5588_read(client, KEY_LCK_EC_STAT) & KEC;
101 if (ev_cnt) { 128 if (ev_cnt) {
102 for (i = 0; i < ev_cnt; i++) { 129 adp5588_report_events(kpad, ev_cnt);
103 key = adp5588_read(client, Key_EVENTA + i);
104 input_report_key(kpad->input,
105 kpad->keycode[(key & KEY_EV_MASK) - 1],
106 key & KEY_EV_PRESSED);
107 }
108 input_sync(kpad->input); 130 input_sync(kpad->input);
109 } 131 }
110 } 132 }
@@ -130,6 +152,7 @@ static int __devinit adp5588_setup(struct i2c_client *client)
130{ 152{
131 struct adp5588_kpad_platform_data *pdata = client->dev.platform_data; 153 struct adp5588_kpad_platform_data *pdata = client->dev.platform_data;
132 int i, ret; 154 int i, ret;
155 unsigned char evt_mode1 = 0, evt_mode2 = 0, evt_mode3 = 0;
133 156
134 ret = adp5588_write(client, KP_GPIO1, KP_SEL(pdata->rows)); 157 ret = adp5588_write(client, KP_GPIO1, KP_SEL(pdata->rows));
135 ret |= adp5588_write(client, KP_GPIO2, KP_SEL(pdata->cols) & 0xFF); 158 ret |= adp5588_write(client, KP_GPIO2, KP_SEL(pdata->cols) & 0xFF);
@@ -144,6 +167,23 @@ static int __devinit adp5588_setup(struct i2c_client *client)
144 for (i = 0; i < KEYP_MAX_EVENT; i++) 167 for (i = 0; i < KEYP_MAX_EVENT; i++)
145 ret |= adp5588_read(client, Key_EVENTA); 168 ret |= adp5588_read(client, Key_EVENTA);
146 169
170 for (i = 0; i < pdata->gpimapsize; i++) {
171 unsigned short pin = pdata->gpimap[i].pin;
172
173 if (pin <= GPI_PIN_ROW_END) {
174 evt_mode1 |= (1 << (pin - GPI_PIN_ROW_BASE));
175 } else {
176 evt_mode2 |= ((1 << (pin - GPI_PIN_COL_BASE)) & 0xFF);
177 evt_mode3 |= ((1 << (pin - GPI_PIN_COL_BASE)) >> 8);
178 }
179 }
180
181 if (pdata->gpimapsize) {
182 ret |= adp5588_write(client, GPI_EM1, evt_mode1);
183 ret |= adp5588_write(client, GPI_EM2, evt_mode2);
184 ret |= adp5588_write(client, GPI_EM3, evt_mode3);
185 }
186
147 ret |= adp5588_write(client, INT_STAT, CMP2_INT | CMP1_INT | 187 ret |= adp5588_write(client, INT_STAT, CMP2_INT | CMP1_INT |
148 OVR_FLOW_INT | K_LCK_INT | 188 OVR_FLOW_INT | K_LCK_INT |
149 GPI_INT | KE_INT); /* Status is W1C */ 189 GPI_INT | KE_INT); /* Status is W1C */
@@ -158,6 +198,44 @@ static int __devinit adp5588_setup(struct i2c_client *client)
158 return 0; 198 return 0;
159} 199}
160 200
201static void __devinit adp5588_report_switch_state(struct adp5588_kpad *kpad)
202{
203 int gpi_stat1 = adp5588_read(kpad->client, GPIO_DAT_STAT1);
204 int gpi_stat2 = adp5588_read(kpad->client, GPIO_DAT_STAT2);
205 int gpi_stat3 = adp5588_read(kpad->client, GPIO_DAT_STAT3);
206 int gpi_stat_tmp, pin_loc;
207 int i;
208
209 for (i = 0; i < kpad->gpimapsize; i++) {
210 unsigned short pin = kpad->gpimap[i].pin;
211
212 if (pin <= GPI_PIN_ROW_END) {
213 gpi_stat_tmp = gpi_stat1;
214 pin_loc = pin - GPI_PIN_ROW_BASE;
215 } else if ((pin - GPI_PIN_COL_BASE) < 8) {
216 gpi_stat_tmp = gpi_stat2;
217 pin_loc = pin - GPI_PIN_COL_BASE;
218 } else {
219 gpi_stat_tmp = gpi_stat3;
220 pin_loc = pin - GPI_PIN_COL_BASE - 8;
221 }
222
223 if (gpi_stat_tmp < 0) {
224 dev_err(&kpad->client->dev,
225 "Can't read GPIO_DAT_STAT switch %d default to OFF\n",
226 pin);
227 gpi_stat_tmp = 0;
228 }
229
230 input_report_switch(kpad->input,
231 kpad->gpimap[i].sw_evt,
232 !(gpi_stat_tmp & (1 << pin_loc)));
233 }
234
235 input_sync(kpad->input);
236}
237
238
161static int __devinit adp5588_probe(struct i2c_client *client, 239static int __devinit adp5588_probe(struct i2c_client *client,
162 const struct i2c_device_id *id) 240 const struct i2c_device_id *id)
163{ 241{
@@ -189,6 +267,37 @@ static int __devinit adp5588_probe(struct i2c_client *client,
189 return -EINVAL; 267 return -EINVAL;
190 } 268 }
191 269
270 if (!pdata->gpimap && pdata->gpimapsize) {
271 dev_err(&client->dev, "invalid gpimap from pdata\n");
272 return -EINVAL;
273 }
274
275 if (pdata->gpimapsize > ADP5588_GPIMAPSIZE_MAX) {
276 dev_err(&client->dev, "invalid gpimapsize\n");
277 return -EINVAL;
278 }
279
280 for (i = 0; i < pdata->gpimapsize; i++) {
281 unsigned short pin = pdata->gpimap[i].pin;
282
283 if (pin < GPI_PIN_BASE || pin > GPI_PIN_END) {
284 dev_err(&client->dev, "invalid gpi pin data\n");
285 return -EINVAL;
286 }
287
288 if (pin <= GPI_PIN_ROW_END) {
289 if (pin - GPI_PIN_ROW_BASE + 1 <= pdata->rows) {
290 dev_err(&client->dev, "invalid gpi row data\n");
291 return -EINVAL;
292 }
293 } else {
294 if (pin - GPI_PIN_COL_BASE + 1 <= pdata->cols) {
295 dev_err(&client->dev, "invalid gpi col data\n");
296 return -EINVAL;
297 }
298 }
299 }
300
192 if (!client->irq) { 301 if (!client->irq) {
193 dev_err(&client->dev, "no IRQ?\n"); 302 dev_err(&client->dev, "no IRQ?\n");
194 return -EINVAL; 303 return -EINVAL;
@@ -233,6 +342,9 @@ static int __devinit adp5588_probe(struct i2c_client *client,
233 memcpy(kpad->keycode, pdata->keymap, 342 memcpy(kpad->keycode, pdata->keymap,
234 pdata->keymapsize * input->keycodesize); 343 pdata->keymapsize * input->keycodesize);
235 344
345 kpad->gpimap = pdata->gpimap;
346 kpad->gpimapsize = pdata->gpimapsize;
347
236 /* setup input device */ 348 /* setup input device */
237 __set_bit(EV_KEY, input->evbit); 349 __set_bit(EV_KEY, input->evbit);
238 350
@@ -243,6 +355,11 @@ static int __devinit adp5588_probe(struct i2c_client *client,
243 __set_bit(kpad->keycode[i] & KEY_MAX, input->keybit); 355 __set_bit(kpad->keycode[i] & KEY_MAX, input->keybit);
244 __clear_bit(KEY_RESERVED, input->keybit); 356 __clear_bit(KEY_RESERVED, input->keybit);
245 357
358 if (kpad->gpimapsize)
359 __set_bit(EV_SW, input->evbit);
360 for (i = 0; i < kpad->gpimapsize; i++)
361 __set_bit(kpad->gpimap[i].sw_evt, input->swbit);
362
246 error = input_register_device(input); 363 error = input_register_device(input);
247 if (error) { 364 if (error) {
248 dev_err(&client->dev, "unable to register input device\n"); 365 dev_err(&client->dev, "unable to register input device\n");
@@ -261,6 +378,9 @@ static int __devinit adp5588_probe(struct i2c_client *client,
261 if (error) 378 if (error)
262 goto err_free_irq; 379 goto err_free_irq;
263 380
381 if (kpad->gpimapsize)
382 adp5588_report_switch_state(kpad);
383
264 device_init_wakeup(&client->dev, 1); 384 device_init_wakeup(&client->dev, 1);
265 i2c_set_clientdata(client, kpad); 385 i2c_set_clientdata(client, kpad);
266 386