aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/input/keyboard/adp5588-keys.c134
-rw-r--r--include/linux/i2c/adp5588.h36
2 files changed, 163 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
diff --git a/include/linux/i2c/adp5588.h b/include/linux/i2c/adp5588.h
index 02c9af374741..b5f57c498e24 100644
--- a/include/linux/i2c/adp5588.h
+++ b/include/linux/i2c/adp5588.h
@@ -78,6 +78,40 @@
78 78
79#define ADP5588_KEYMAPSIZE 80 79#define ADP5588_KEYMAPSIZE 80
80 80
81#define GPI_PIN_ROW0 97
82#define GPI_PIN_ROW1 98
83#define GPI_PIN_ROW2 99
84#define GPI_PIN_ROW3 100
85#define GPI_PIN_ROW4 101
86#define GPI_PIN_ROW5 102
87#define GPI_PIN_ROW6 103
88#define GPI_PIN_ROW7 104
89#define GPI_PIN_COL0 105
90#define GPI_PIN_COL1 106
91#define GPI_PIN_COL2 107
92#define GPI_PIN_COL3 108
93#define GPI_PIN_COL4 109
94#define GPI_PIN_COL5 110
95#define GPI_PIN_COL6 111
96#define GPI_PIN_COL7 112
97#define GPI_PIN_COL8 113
98#define GPI_PIN_COL9 114
99
100#define GPI_PIN_ROW_BASE GPI_PIN_ROW0
101#define GPI_PIN_ROW_END GPI_PIN_ROW7
102#define GPI_PIN_COL_BASE GPI_PIN_COL0
103#define GPI_PIN_COL_END GPI_PIN_COL9
104
105#define GPI_PIN_BASE GPI_PIN_ROW_BASE
106#define GPI_PIN_END GPI_PIN_COL_END
107
108#define ADP5588_GPIMAPSIZE_MAX (GPI_PIN_END - GPI_PIN_BASE + 1)
109
110struct adp5588_gpi_map {
111 unsigned short pin;
112 unsigned short sw_evt;
113};
114
81struct adp5588_kpad_platform_data { 115struct adp5588_kpad_platform_data {
82 int rows; /* Number of rows */ 116 int rows; /* Number of rows */
83 int cols; /* Number of columns */ 117 int cols; /* Number of columns */
@@ -87,6 +121,8 @@ struct adp5588_kpad_platform_data {
87 unsigned en_keylock:1; /* Enable Key Lock feature */ 121 unsigned en_keylock:1; /* Enable Key Lock feature */
88 unsigned short unlock_key1; /* Unlock Key 1 */ 122 unsigned short unlock_key1; /* Unlock Key 1 */
89 unsigned short unlock_key2; /* Unlock Key 2 */ 123 unsigned short unlock_key2; /* Unlock Key 2 */
124 const struct adp5588_gpi_map *gpimap;
125 unsigned short gpimapsize;
90}; 126};
91 127
92struct adp5588_gpio_platform_data { 128struct adp5588_gpio_platform_data {