blob: 6d173fb6629809ce5de01e5aea25ac966126742c [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* arch/arm/mach-msm/rpc_server_handset.c
2 *
Stephen Boyd24db6432012-04-25 11:40:08 -07003 * Copyright (c) 2008-2010,2012 Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 and
7 * only version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <linux/slab.h>
16#include <linux/module.h>
17#include <linux/kernel.h>
18#include <linux/platform_device.h>
19#include <linux/input.h>
20#include <linux/switch.h>
21
22#include <asm/mach-types.h>
23
24#include <mach/msm_rpcrouter.h>
25#include <mach/board.h>
26#include <mach/rpc_server_handset.h>
27
28#define DRIVER_NAME "msm-handset"
29
30#define HS_SERVER_PROG 0x30000062
31#define HS_SERVER_VERS 0x00010001
32
33#define HS_RPC_PROG 0x30000091
34
35#define HS_PROCESS_CMD_PROC 0x02
36#define HS_SUBSCRIBE_SRVC_PROC 0x03
37#define HS_REPORT_EVNT_PROC 0x05
38#define HS_EVENT_CB_PROC 1
39#define HS_EVENT_DATA_VER 1
40
41#define RPC_KEYPAD_NULL_PROC 0
42#define RPC_KEYPAD_PASS_KEY_CODE_PROC 2
43#define RPC_KEYPAD_SET_PWR_KEY_STATE_PROC 3
44
45#define HS_PWR_K 0x6F /* Power key */
46#define HS_END_K 0x51 /* End key or Power key */
47#define HS_STEREO_HEADSET_K 0x82
48#define HS_HEADSET_SWITCH_K 0x84
49#define HS_HEADSET_SWITCH_2_K 0xF0
50#define HS_HEADSET_SWITCH_3_K 0xF1
51#define HS_HEADSET_HEADPHONE_K 0xF6
52#define HS_HEADSET_MICROPHONE_K 0xF7
53#define HS_REL_K 0xFF /* key release */
54
55#define SW_HEADPHONE_INSERT_W_MIC 1 /* HS with mic */
56
57#define KEY(hs_key, input_key) ((hs_key << 24) | input_key)
58
59enum hs_event {
60 HS_EVNT_EXT_PWR = 0, /* External Power status */
61 HS_EVNT_HSD, /* Headset Detection */
62 HS_EVNT_HSTD, /* Headset Type Detection */
63 HS_EVNT_HSSD, /* Headset Switch Detection */
64 HS_EVNT_KPD,
65 HS_EVNT_FLIP, /* Flip / Clamshell status (open/close) */
66 HS_EVNT_CHARGER, /* Battery is being charged or not */
67 HS_EVNT_ENV, /* Events from runtime environment like DEM */
68 HS_EVNT_REM, /* Events received from HS counterpart on a
69 remote processor*/
70 HS_EVNT_DIAG, /* Diag Events */
71 HS_EVNT_LAST, /* Should always be the last event type */
72 HS_EVNT_MAX /* Force enum to be an 32-bit number */
73};
74
75enum hs_src_state {
76 HS_SRC_STATE_UNKWN = 0,
77 HS_SRC_STATE_LO,
78 HS_SRC_STATE_HI,
79};
80
81struct hs_event_data {
82 uint32_t ver; /* Version number */
83 enum hs_event event_type; /* Event Type */
84 enum hs_event enum_disc; /* discriminator */
85 uint32_t data_length; /* length of the next field */
86 enum hs_src_state data; /* Pointer to data */
87 uint32_t data_size; /* Elements to be processed in data */
88};
89
90enum hs_return_value {
91 HS_EKPDLOCKED = -2, /* Operation failed because keypad is locked */
92 HS_ENOTSUPPORTED = -1, /* Functionality not supported */
93 HS_FALSE = 0, /* Inquired condition is not true */
94 HS_FAILURE = 0, /* Requested operation was not successful */
95 HS_TRUE = 1, /* Inquired condition is true */
96 HS_SUCCESS = 1, /* Requested operation was successful */
97 HS_MAX_RETURN = 0x7FFFFFFF/* Force enum to be a 32 bit number */
98};
99
100struct hs_key_data {
101 uint32_t ver; /* Version number to track sturcture changes */
102 uint32_t code; /* which key? */
103 uint32_t parm; /* key status. Up/down or pressed/released */
104};
105
106enum hs_subs_srvc {
107 HS_SUBS_SEND_CMD = 0, /* Subscribe to send commands to HS */
108 HS_SUBS_RCV_EVNT, /* Subscribe to receive Events from HS */
109 HS_SUBS_SRVC_MAX
110};
111
112enum hs_subs_req {
113 HS_SUBS_REGISTER, /* Subscribe */
114 HS_SUBS_CANCEL, /* Unsubscribe */
115 HS_SUB_STATUS_MAX
116};
117
118enum hs_event_class {
119 HS_EVNT_CLASS_ALL = 0, /* All HS events */
120 HS_EVNT_CLASS_LAST, /* Should always be the last class type */
121 HS_EVNT_CLASS_MAX
122};
123
124enum hs_cmd_class {
125 HS_CMD_CLASS_LCD = 0, /* Send LCD related commands */
126 HS_CMD_CLASS_KPD, /* Send KPD related commands */
127 HS_CMD_CLASS_LAST, /* Should always be the last class type */
128 HS_CMD_CLASS_MAX
129};
130
131/*
132 * Receive events or send command
133 */
134union hs_subs_class {
135 enum hs_event_class evnt;
136 enum hs_cmd_class cmd;
137};
138
139struct hs_subs {
140 uint32_t ver;
141 enum hs_subs_srvc srvc; /* commands or events */
142 enum hs_subs_req req; /* subscribe or unsubscribe */
143 uint32_t host_os;
144 enum hs_subs_req disc; /* discriminator */
145 union hs_subs_class id;
146};
147
148struct hs_event_cb_recv {
149 uint32_t cb_id;
150 uint32_t hs_key_data_ptr;
151 struct hs_key_data key;
152};
153enum hs_ext_cmd_type {
154 HS_EXT_CMD_KPD_SEND_KEY = 0, /* Send Key */
155 HS_EXT_CMD_KPD_BKLT_CTRL, /* Keypad backlight intensity */
156 HS_EXT_CMD_LCD_BKLT_CTRL, /* LCD Backlight intensity */
157 HS_EXT_CMD_DIAG_KEYMAP, /* Emulating a Diag key sequence */
158 HS_EXT_CMD_DIAG_LOCK, /* Device Lock/Unlock */
159 HS_EXT_CMD_GET_EVNT_STATUS, /* Get the status for one of the drivers */
160 HS_EXT_CMD_KPD_GET_KEYS_STATUS,/* Get a list of keys status */
161 HS_EXT_CMD_KPD_SET_PWR_KEY_RST_THOLD, /* PWR Key HW Reset duration */
162 HS_EXT_CMD_KPD_SET_PWR_KEY_THOLD, /* Set pwr key threshold duration */
163 HS_EXT_CMD_LAST, /* Should always be the last command type */
164 HS_EXT_CMD_MAX = 0x7FFFFFFF /* Force enum to be an 32-bit number */
165};
166
167struct hs_cmd_data_type {
168 uint32_t hs_cmd_data_type_ptr; /* hs_cmd_data_type ptr length */
169 uint32_t ver; /* version */
170 enum hs_ext_cmd_type id; /* command id */
171 uint32_t handle; /* handle returned from subscribe proc */
172 enum hs_ext_cmd_type disc_id1; /* discriminator id */
173 uint32_t input_ptr; /* input ptr length */
174 uint32_t input_val; /* command specific data */
175 uint32_t input_len; /* length of command input */
176 enum hs_ext_cmd_type disc_id2; /* discriminator id */
177 uint32_t output_len; /* length of output data */
178 uint32_t delayed; /* execution context for modem
179 true - caller context
180 false - hs task context*/
181};
182
183static const uint32_t hs_key_map[] = {
184 KEY(HS_PWR_K, KEY_POWER),
185 KEY(HS_END_K, KEY_END),
186 KEY(HS_STEREO_HEADSET_K, SW_HEADPHONE_INSERT_W_MIC),
187 KEY(HS_HEADSET_HEADPHONE_K, SW_HEADPHONE_INSERT),
188 KEY(HS_HEADSET_MICROPHONE_K, SW_MICROPHONE_INSERT),
189 KEY(HS_HEADSET_SWITCH_K, KEY_MEDIA),
190 KEY(HS_HEADSET_SWITCH_2_K, KEY_VOLUMEUP),
191 KEY(HS_HEADSET_SWITCH_3_K, KEY_VOLUMEDOWN),
192 0
193};
194
195enum {
196 NO_DEVICE = 0,
197 MSM_HEADSET = 1,
198};
199/* Add newer versions at the top of array */
200static const unsigned int rpc_vers[] = {
201 0x00030001,
202 0x00020001,
203 0x00010001,
204};
205/* hs subscription request parameters */
206struct hs_subs_rpc_req {
207 uint32_t hs_subs_ptr;
208 struct hs_subs hs_subs;
209 uint32_t hs_cb_id;
210 uint32_t hs_handle_ptr;
211 uint32_t hs_handle_data;
212};
213
214static struct hs_subs_rpc_req *hs_subs_req;
215
216struct msm_handset {
217 struct input_dev *ipdev;
218 struct switch_dev sdev;
219 struct msm_handset_platform_data *hs_pdata;
220 bool mic_on, hs_on;
221};
222
223static struct msm_rpc_client *rpc_client;
224static struct msm_handset *hs;
225
226static int hs_find_key(uint32_t hscode)
227{
228 int i, key;
229
230 key = KEY(hscode, 0);
231
232 for (i = 0; hs_key_map[i] != 0; i++) {
233 if ((hs_key_map[i] & 0xff000000) == key)
234 return hs_key_map[i] & 0x00ffffff;
235 }
236 return -1;
237}
238
239static void update_state(void)
240{
241 int state;
242
243 if (hs->mic_on && hs->hs_on)
244 state = 1 << 0;
245 else if (hs->hs_on)
246 state = 1 << 1;
247 else if (hs->mic_on)
248 state = 1 << 2;
249 else
250 state = 0;
251
252 switch_set_state(&hs->sdev, state);
253}
254
255/*
256 * tuple format: (key_code, key_param)
257 *
258 * old-architecture:
259 * key-press = (key_code, 0)
260 * key-release = (0xff, key_code)
261 *
262 * new-architecutre:
263 * key-press = (key_code, 0)
264 * key-release = (key_code, 0xff)
265 */
266static void report_hs_key(uint32_t key_code, uint32_t key_parm)
267{
268 int key, temp_key_code;
269
270 if (key_code == HS_REL_K)
271 key = hs_find_key(key_parm);
272 else
273 key = hs_find_key(key_code);
274
275 temp_key_code = key_code;
276
277 if (key_parm == HS_REL_K)
278 key_code = key_parm;
279
280 switch (key) {
281 case KEY_POWER:
282 case KEY_END:
283 case KEY_MEDIA:
284 case KEY_VOLUMEUP:
285 case KEY_VOLUMEDOWN:
286 input_report_key(hs->ipdev, key, (key_code != HS_REL_K));
287 break;
288 case SW_HEADPHONE_INSERT_W_MIC:
289 hs->mic_on = hs->hs_on = (key_code != HS_REL_K) ? 1 : 0;
290 input_report_switch(hs->ipdev, SW_HEADPHONE_INSERT,
291 hs->hs_on);
292 input_report_switch(hs->ipdev, SW_MICROPHONE_INSERT,
293 hs->mic_on);
294 update_state();
295 break;
296
297 case SW_HEADPHONE_INSERT:
298 hs->hs_on = (key_code != HS_REL_K) ? 1 : 0;
299 input_report_switch(hs->ipdev, key, hs->hs_on);
300 update_state();
301 break;
302 case SW_MICROPHONE_INSERT:
303 hs->mic_on = (key_code != HS_REL_K) ? 1 : 0;
304 input_report_switch(hs->ipdev, key, hs->mic_on);
305 update_state();
306 break;
307 case -1:
308 printk(KERN_ERR "%s: No mapping for remote handset event %d\n",
309 __func__, temp_key_code);
310 return;
311 }
312 input_sync(hs->ipdev);
313}
314
315static int handle_hs_rpc_call(struct msm_rpc_server *server,
316 struct rpc_request_hdr *req, unsigned len)
317{
318 struct rpc_keypad_pass_key_code_args {
319 uint32_t key_code;
320 uint32_t key_parm;
321 };
322
323 switch (req->procedure) {
324 case RPC_KEYPAD_NULL_PROC:
325 return 0;
326
327 case RPC_KEYPAD_PASS_KEY_CODE_PROC: {
328 struct rpc_keypad_pass_key_code_args *args;
329
330 args = (struct rpc_keypad_pass_key_code_args *)(req + 1);
331 args->key_code = be32_to_cpu(args->key_code);
332 args->key_parm = be32_to_cpu(args->key_parm);
333
334 report_hs_key(args->key_code, args->key_parm);
335
336 return 0;
337 }
338
339 case RPC_KEYPAD_SET_PWR_KEY_STATE_PROC:
340 /* This RPC function must be available for the ARM9
341 * to function properly. This function is redundant
342 * when RPC_KEYPAD_PASS_KEY_CODE_PROC is handled. So
343 * input_report_key is not needed.
344 */
345 return 0;
346 default:
347 return -ENODEV;
348 }
349}
350
351static struct msm_rpc_server hs_rpc_server = {
352 .prog = HS_SERVER_PROG,
353 .vers = HS_SERVER_VERS,
354 .rpc_call = handle_hs_rpc_call,
355};
356
357static int process_subs_srvc_callback(struct hs_event_cb_recv *recv)
358{
359 if (!recv)
360 return -ENODATA;
361
362 report_hs_key(be32_to_cpu(recv->key.code), be32_to_cpu(recv->key.parm));
363
364 return 0;
365}
366
367static void process_hs_rpc_request(uint32_t proc, void *data)
368{
369 if (proc == HS_EVENT_CB_PROC)
370 process_subs_srvc_callback(data);
371 else
372 pr_err("%s: unknown rpc proc %d\n", __func__, proc);
373}
374
375static int hs_rpc_report_event_arg(struct msm_rpc_client *client,
376 void *buffer, void *data)
377{
378 struct hs_event_rpc_req {
379 uint32_t hs_event_data_ptr;
380 struct hs_event_data data;
381 };
382
383 struct hs_event_rpc_req *req = buffer;
384
385 req->hs_event_data_ptr = cpu_to_be32(0x1);
386 req->data.ver = cpu_to_be32(HS_EVENT_DATA_VER);
387 req->data.event_type = cpu_to_be32(HS_EVNT_HSD);
388 req->data.enum_disc = cpu_to_be32(HS_EVNT_HSD);
389 req->data.data_length = cpu_to_be32(0x1);
390 req->data.data = cpu_to_be32(*(enum hs_src_state *)data);
391 req->data.data_size = cpu_to_be32(sizeof(enum hs_src_state));
392
393 return sizeof(*req);
394}
395
396static int hs_rpc_report_event_res(struct msm_rpc_client *client,
397 void *buffer, void *data)
398{
399 enum hs_return_value result;
400
401 result = be32_to_cpu(*(enum hs_return_value *)buffer);
402 pr_debug("%s: request completed: 0x%x\n", __func__, result);
403
404 if (result == HS_SUCCESS)
405 return 0;
406
407 return 1;
408}
409
410void report_headset_status(bool connected)
411{
412 int rc = -1;
413 enum hs_src_state status;
414
415 if (connected == true)
416 status = HS_SRC_STATE_HI;
417 else
418 status = HS_SRC_STATE_LO;
419
420 rc = msm_rpc_client_req(rpc_client, HS_REPORT_EVNT_PROC,
421 hs_rpc_report_event_arg, &status,
422 hs_rpc_report_event_res, NULL, -1);
423
424 if (rc)
425 pr_err("%s: couldn't send rpc client request\n", __func__);
426}
427EXPORT_SYMBOL(report_headset_status);
428
429static int hs_rpc_pwr_cmd_arg(struct msm_rpc_client *client,
430 void *buffer, void *data)
431{
432 struct hs_cmd_data_type *hs_pwr_cmd = buffer;
433
434 hs_pwr_cmd->hs_cmd_data_type_ptr = cpu_to_be32(0x01);
435
436 hs_pwr_cmd->ver = cpu_to_be32(0x03);
437 hs_pwr_cmd->id = cpu_to_be32(HS_EXT_CMD_KPD_SET_PWR_KEY_THOLD);
438 hs_pwr_cmd->handle = cpu_to_be32(hs_subs_req->hs_handle_data);
439 hs_pwr_cmd->disc_id1 = cpu_to_be32(HS_EXT_CMD_KPD_SET_PWR_KEY_THOLD);
440 hs_pwr_cmd->input_ptr = cpu_to_be32(0x01);
441 hs_pwr_cmd->input_val = cpu_to_be32(hs->hs_pdata->pwr_key_delay_ms);
442 hs_pwr_cmd->input_len = cpu_to_be32(0x01);
443 hs_pwr_cmd->disc_id2 = cpu_to_be32(HS_EXT_CMD_KPD_SET_PWR_KEY_THOLD);
444 hs_pwr_cmd->output_len = cpu_to_be32(0x00);
445 hs_pwr_cmd->delayed = cpu_to_be32(0x00);
446
447 return sizeof(*hs_pwr_cmd);
448}
449
450static int hs_rpc_pwr_cmd_res(struct msm_rpc_client *client,
451 void *buffer, void *data)
452{
453 uint32_t result;
454
455 result = be32_to_cpu(*((uint32_t *)buffer));
456 pr_debug("%s: request completed: 0x%x\n", __func__, result);
457
458 return 0;
459}
460
461static int hs_rpc_register_subs_arg(struct msm_rpc_client *client,
462 void *buffer, void *data)
463{
464 hs_subs_req = buffer;
465
466 hs_subs_req->hs_subs_ptr = cpu_to_be32(0x1);
467 hs_subs_req->hs_subs.ver = cpu_to_be32(0x1);
468 hs_subs_req->hs_subs.srvc = cpu_to_be32(HS_SUBS_RCV_EVNT);
469 hs_subs_req->hs_subs.req = cpu_to_be32(HS_SUBS_REGISTER);
470 hs_subs_req->hs_subs.host_os = cpu_to_be32(0x4); /* linux */
471 hs_subs_req->hs_subs.disc = cpu_to_be32(HS_SUBS_RCV_EVNT);
472 hs_subs_req->hs_subs.id.evnt = cpu_to_be32(HS_EVNT_CLASS_ALL);
473
474 hs_subs_req->hs_cb_id = cpu_to_be32(0x1);
475
476 hs_subs_req->hs_handle_ptr = cpu_to_be32(0x1);
477 hs_subs_req->hs_handle_data = cpu_to_be32(0x0);
478
479 return sizeof(*hs_subs_req);
480}
481
482static int hs_rpc_register_subs_res(struct msm_rpc_client *client,
483 void *buffer, void *data)
484{
485 uint32_t result;
486
487 result = be32_to_cpu(*((uint32_t *)buffer));
488 pr_debug("%s: request completed: 0x%x\n", __func__, result);
489
490 return 0;
491}
492
493static int hs_cb_func(struct msm_rpc_client *client, void *buffer, int in_size)
494{
495 int rc = -1;
496
497 struct rpc_request_hdr *hdr = buffer;
498
499 hdr->type = be32_to_cpu(hdr->type);
500 hdr->xid = be32_to_cpu(hdr->xid);
501 hdr->rpc_vers = be32_to_cpu(hdr->rpc_vers);
502 hdr->prog = be32_to_cpu(hdr->prog);
503 hdr->vers = be32_to_cpu(hdr->vers);
504 hdr->procedure = be32_to_cpu(hdr->procedure);
505
506 process_hs_rpc_request(hdr->procedure,
507 (void *) (hdr + 1));
508
509 msm_rpc_start_accepted_reply(client, hdr->xid,
510 RPC_ACCEPTSTAT_SUCCESS);
511 rc = msm_rpc_send_accepted_reply(client, 0);
512 if (rc) {
513 pr_err("%s: sending reply failed: %d\n", __func__, rc);
514 return rc;
515 }
516
517 return 0;
518}
519
Stephen Boyd24db6432012-04-25 11:40:08 -0700520static int __devinit hs_rpc_cb_init(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700521{
522 int rc = 0, i, num_vers;
523
524 num_vers = ARRAY_SIZE(rpc_vers);
525
526 for (i = 0; i < num_vers; i++) {
527 rpc_client = msm_rpc_register_client("hs",
528 HS_RPC_PROG, rpc_vers[i], 0, hs_cb_func);
529
530 if (IS_ERR(rpc_client))
531 pr_debug("%s: RPC Client version %d failed, fallback\n",
532 __func__, rpc_vers[i]);
533 else
534 break;
535 }
536
537 if (IS_ERR(rpc_client)) {
538 pr_err("%s: Incompatible RPC version error %ld\n",
539 __func__, PTR_ERR(rpc_client));
540 return PTR_ERR(rpc_client);
541 }
542
543 rc = msm_rpc_client_req(rpc_client, HS_SUBSCRIBE_SRVC_PROC,
544 hs_rpc_register_subs_arg, NULL,
545 hs_rpc_register_subs_res, NULL, -1);
546 if (rc) {
547 pr_err("%s: RPC client request failed for subscribe services\n",
548 __func__);
549 goto err_client_req;
550 }
551
552 rc = msm_rpc_client_req(rpc_client, HS_PROCESS_CMD_PROC,
553 hs_rpc_pwr_cmd_arg, NULL,
554 hs_rpc_pwr_cmd_res, NULL, -1);
555 if (rc)
556 pr_err("%s: RPC client request failed for pwr key"
557 " delay cmd, using normal mode\n", __func__);
558 return 0;
559err_client_req:
560 msm_rpc_unregister_client(rpc_client);
561 return rc;
562}
563
564static int __devinit hs_rpc_init(void)
565{
566 int rc;
567
568 rc = hs_rpc_cb_init();
569 if (rc) {
570 pr_err("%s: failed to initialize rpc client, try server...\n",
571 __func__);
572
573 rc = msm_rpc_create_server(&hs_rpc_server);
574 if (rc) {
575 pr_err("%s: failed to create rpc server\n", __func__);
576 return rc;
577 }
578 }
579
580 return rc;
581}
582
583static void __devexit hs_rpc_deinit(void)
584{
585 if (rpc_client)
586 msm_rpc_unregister_client(rpc_client);
587}
588
589static ssize_t msm_headset_print_name(struct switch_dev *sdev, char *buf)
590{
591 switch (switch_get_state(&hs->sdev)) {
592 case NO_DEVICE:
593 return sprintf(buf, "No Device\n");
594 case MSM_HEADSET:
595 return sprintf(buf, "Headset\n");
596 }
597 return -EINVAL;
598}
599
600static int __devinit hs_probe(struct platform_device *pdev)
601{
602 int rc = 0;
603 struct input_dev *ipdev;
604
605 hs = kzalloc(sizeof(struct msm_handset), GFP_KERNEL);
606 if (!hs)
607 return -ENOMEM;
608
609 hs->sdev.name = "h2w";
610 hs->sdev.print_name = msm_headset_print_name;
611
612 rc = switch_dev_register(&hs->sdev);
613 if (rc)
614 goto err_switch_dev_register;
615
616 ipdev = input_allocate_device();
617 if (!ipdev) {
618 rc = -ENOMEM;
619 goto err_alloc_input_dev;
620 }
621 input_set_drvdata(ipdev, hs);
622
623 hs->ipdev = ipdev;
624
625 if (pdev->dev.platform_data)
626 hs->hs_pdata = pdev->dev.platform_data;
627
628 if (hs->hs_pdata->hs_name)
629 ipdev->name = hs->hs_pdata->hs_name;
630 else
631 ipdev->name = DRIVER_NAME;
632
633 ipdev->id.vendor = 0x0001;
634 ipdev->id.product = 1;
635 ipdev->id.version = 1;
636
637 input_set_capability(ipdev, EV_KEY, KEY_MEDIA);
638 input_set_capability(ipdev, EV_KEY, KEY_VOLUMEUP);
639 input_set_capability(ipdev, EV_KEY, KEY_VOLUMEDOWN);
640 input_set_capability(ipdev, EV_SW, SW_HEADPHONE_INSERT);
641 input_set_capability(ipdev, EV_SW, SW_MICROPHONE_INSERT);
642 input_set_capability(ipdev, EV_KEY, KEY_POWER);
643 input_set_capability(ipdev, EV_KEY, KEY_END);
644
645 rc = input_register_device(ipdev);
646 if (rc) {
647 dev_err(&ipdev->dev,
648 "hs_probe: input_register_device rc=%d\n", rc);
649 goto err_reg_input_dev;
650 }
651
652 platform_set_drvdata(pdev, hs);
653
654 rc = hs_rpc_init();
655 if (rc) {
656 dev_err(&ipdev->dev, "rpc init failure\n");
657 goto err_hs_rpc_init;
658 }
659
660 return 0;
661
662err_hs_rpc_init:
663 input_unregister_device(ipdev);
664 ipdev = NULL;
665err_reg_input_dev:
666 input_free_device(ipdev);
667err_alloc_input_dev:
668 switch_dev_unregister(&hs->sdev);
669err_switch_dev_register:
670 kfree(hs);
671 return rc;
672}
673
674static int __devexit hs_remove(struct platform_device *pdev)
675{
676 struct msm_handset *hs = platform_get_drvdata(pdev);
677
678 input_unregister_device(hs->ipdev);
679 switch_dev_unregister(&hs->sdev);
680 kfree(hs);
681 hs_rpc_deinit();
682 return 0;
683}
684
685static struct platform_driver hs_driver = {
686 .probe = hs_probe,
687 .remove = __devexit_p(hs_remove),
688 .driver = {
689 .name = DRIVER_NAME,
690 .owner = THIS_MODULE,
691 },
692};
693
694static int __init hs_init(void)
695{
696 return platform_driver_register(&hs_driver);
697}
698late_initcall(hs_init);
699
700static void __exit hs_exit(void)
701{
702 platform_driver_unregister(&hs_driver);
703}
704module_exit(hs_exit);
705
706MODULE_LICENSE("GPL v2");
707MODULE_ALIAS("platform:msm-handset");