2 * Copyright (C) 2010 Motorola, Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 #include <linux/delay.h>
20 #include <linux/errno.h>
21 #include <linux/err.h>
22 #include <linux/gpio.h>
23 #include <linux/module.h>
24 #include <linux/platform_device.h>
25 #include <linux/switch.h>
26 #include <linux/wakelock.h>
27 #include <linux/workqueue.h>
29 #include <linux/regulator/consumer.h>
30 #include <linux/usb/otg.h>
32 #include <linux/spi/cpcap.h>
33 #include <linux/spi/cpcap-regbits.h>
34 #include <linux/spi/spi.h>
36 void tegra_cpcap_audio_dock_state(bool connected);
38 #define SENSE_USB_CLIENT (CPCAP_BIT_ID_FLOAT_S | \
39 CPCAP_BIT_VBUSVLD_S | \
42 #define SENSE_USB_FLASH (CPCAP_BIT_VBUSVLD_S | \
45 #define SENSE_USB_HOST (CPCAP_BIT_ID_GROUND_S)
46 #define SENSE_USB_HOST_MASK (~CPCAP_BIT_SE1_S)
48 #define SENSE_FACTORY (CPCAP_BIT_ID_FLOAT_S | \
49 CPCAP_BIT_ID_GROUND_S | \
50 CPCAP_BIT_VBUSVLD_S | \
53 #define SENSE_WHISPER_SPD (CPCAP_BIT_SE1_S)
55 #define SENSE_WHISPER_PPD (0)
57 #define SENSE_WHISPER_SMART (CPCAP_BIT_ID_GROUND_S | \
58 CPCAP_BIT_VBUSVLD_S | \
61 #define SENSE_CHARGER_FLOAT (CPCAP_BIT_ID_FLOAT_S | \
62 CPCAP_BIT_VBUSVLD_S | \
63 CPCAP_BIT_SESSVLD_S | \
66 #define SENSE_CHARGER (CPCAP_BIT_VBUSVLD_S | \
67 CPCAP_BIT_SESSVLD_S | \
70 /* TODO: Update with appropriate value. */
71 #define ADC_AUDIO_THRES 0x12C
73 enum cpcap_det_state {
89 CPCAP_ACCY_WHISPER_SMART,
93 /* Used while debouncing the accessory. */
105 struct cpcap_whisper_data {
106 struct cpcap_device *cpcap;
107 struct cpcap_whisper_pdata *pdata;
108 struct delayed_work work;
109 struct workqueue_struct *wq;
110 unsigned short sense;
111 unsigned short prev_sense;
112 enum cpcap_det_state state;
113 struct regulator *regulator;
114 struct wake_lock wake_lock;
115 unsigned char is_vusb_enabled;
116 struct switch_dev wsdev; /* Whisper switch */
117 struct switch_dev dsdev; /* Dock switch */
118 struct switch_dev asdev; /* Audio switch */
119 struct switch_dev csdev; /* Invalid charger switch */
120 char dock_id[CPCAP_WHISPER_ID_SIZE];
121 char dock_prop[CPCAP_WHISPER_PROP_SIZE];
122 struct otg_transceiver *otg;
125 static struct cpcap_whisper_data *whisper_di;
127 static int whisper_debug;
128 module_param(whisper_debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
130 static ssize_t print_name(struct switch_dev *dsdev, char *buf)
132 switch (switch_get_state(dsdev)) {
134 return sprintf(buf, "None\n");
136 return sprintf(buf, "DESK\n");
138 return sprintf(buf, "CAR\n");
140 return sprintf(buf, "LE\n");
142 return sprintf(buf, "HE\n");
148 static ssize_t dock_id_show(struct device *dev, struct device_attribute *attr,
151 struct switch_dev *dsdev = dev_get_drvdata(dev);
152 struct cpcap_whisper_data *data =
153 container_of(dsdev, struct cpcap_whisper_data, dsdev);
155 return snprintf(buf, PAGE_SIZE, "%s\n", data->dock_id);
157 static DEVICE_ATTR(dock_addr, S_IRUGO | S_IWUSR, dock_id_show, NULL);
159 static ssize_t dock_prop_show(struct device *dev, struct device_attribute *attr,
162 struct switch_dev *dsdev = dev_get_drvdata(dev);
163 struct cpcap_whisper_data *data =
164 container_of(dsdev, struct cpcap_whisper_data, dsdev);
166 return snprintf(buf, PAGE_SIZE, "%s\n", data->dock_prop);
168 static DEVICE_ATTR(dock_prop, S_IRUGO | S_IWUSR, dock_prop_show, NULL);
170 static void vusb_enable(struct cpcap_whisper_data *data)
172 if (!data->is_vusb_enabled) {
173 regulator_enable(data->regulator);
174 data->is_vusb_enabled = 1;
178 static void vusb_disable(struct cpcap_whisper_data *data)
180 if (data->is_vusb_enabled) {
181 regulator_disable(data->regulator);
182 data->is_vusb_enabled = 0;
186 static int get_sense(struct cpcap_whisper_data *data)
188 int retval = -EFAULT;
189 unsigned short value;
190 struct cpcap_device *cpcap;
196 retval = cpcap_regacc_read(cpcap, CPCAP_REG_INTS1, &value);
200 /* Clear ASAP after read. */
201 retval = cpcap_regacc_write(cpcap, CPCAP_REG_INT1,
202 (CPCAP_BIT_CHRG_DET_I |
203 CPCAP_BIT_ID_FLOAT_I |
204 CPCAP_BIT_ID_GROUND_I),
205 (CPCAP_BIT_CHRG_DET_I |
206 CPCAP_BIT_ID_FLOAT_I |
207 CPCAP_BIT_ID_GROUND_I));
211 data->sense = value & (CPCAP_BIT_ID_FLOAT_S |
212 CPCAP_BIT_ID_GROUND_S);
214 retval = cpcap_regacc_read(cpcap, CPCAP_REG_INTS2, &value);
218 /* Clear ASAP after read. */
219 retval = cpcap_regacc_write(cpcap, CPCAP_REG_INT2,
220 (CPCAP_BIT_VBUSVLD_I |
221 CPCAP_BIT_SESSVLD_I |
223 (CPCAP_BIT_VBUSVLD_I |
224 CPCAP_BIT_SESSVLD_I |
229 data->sense |= value & (CPCAP_BIT_VBUSVLD_S |
230 CPCAP_BIT_SESSVLD_S |
235 static int configure_hardware(struct cpcap_whisper_data *data,
236 enum cpcap_accy accy)
240 retval = cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC1,
242 (CPCAP_BIT_DP150KPU | CPCAP_BIT_DP1K5PU |
243 CPCAP_BIT_DM1K5PU | CPCAP_BIT_DPPD |
248 retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC1, 0,
250 gpio_set_value(data->pdata->data_gpio, 1);
252 blocking_notifier_call_chain(&data->otg->notifier,
253 USB_EVENT_VBUS, NULL);
256 case CPCAP_ACCY_USB_HOST:
257 retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC1, 0,
259 gpio_set_value(data->pdata->data_gpio, 1);
261 blocking_notifier_call_chain(&data->otg->notifier,
265 case CPCAP_ACCY_WHISPER:
266 retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC1, 0,
270 case CPCAP_ACCY_WHISPER_SMART:
271 retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC1, 0,
273 gpio_set_value(data->pdata->data_gpio, 1);
275 blocking_notifier_call_chain(&data->otg->notifier,
279 case CPCAP_ACCY_UNKNOWN:
280 gpio_set_value(data->pdata->pwr_gpio, 0);
281 gpio_set_value(data->pdata->data_gpio, 0);
282 retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC1, 0,
284 CPCAP_BIT_ID100KPU));
285 retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC2, 0,
286 (CPCAP_BIT_EMUMODE2 |
288 CPCAP_BIT_EMUMODE0));
291 case CPCAP_ACCY_CHARGER:
292 retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC1,
297 case CPCAP_ACCY_NONE:
299 gpio_set_value(data->pdata->pwr_gpio, 0);
300 retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC1,
303 retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC2, 0,
304 CPCAP_BIT_USBXCVREN);
307 blocking_notifier_call_chain(&data->otg->notifier,
308 USB_EVENT_NONE, NULL);
318 static const char *accy_names[6] = {"USB", "USB host", "whisper",
319 "whisper_smart", "charger", "none"};
321 static void whisper_notify(struct cpcap_whisper_data *di, enum cpcap_accy accy)
323 pr_info("%s: accy=%s\n", __func__, accy_names[accy]);
325 configure_hardware(di, accy);
327 if (accy == CPCAP_ACCY_WHISPER)
328 switch_set_state(&di->wsdev, 1);
329 else if (accy == CPCAP_ACCY_CHARGER)
330 switch_set_state(&di->csdev, 1);
332 switch_set_state(&di->wsdev, 0);
333 switch_set_state(&di->dsdev, NO_DOCK);
334 switch_set_state(&di->asdev, 0);
335 switch_set_state(&di->csdev, 0);
336 memset(di->dock_id, 0, CPCAP_WHISPER_ID_SIZE);
337 memset(di->dock_prop, 0, CPCAP_WHISPER_PROP_SIZE);
338 tegra_cpcap_audio_dock_state(false);
341 wake_lock_timeout(&di->wake_lock, HZ / 2);
344 static void whisper_audio_check(struct cpcap_whisper_data *di)
346 struct cpcap_adc_request req;
348 unsigned short value;
351 if (!switch_get_state(&di->dsdev))
354 cpcap_regacc_read(di->cpcap, CPCAP_REG_USBC1, &value);
355 value &= CPCAP_BIT_ID100KPU;
357 cpcap_regacc_write(di->cpcap, CPCAP_REG_USBC1, CPCAP_BIT_IDPUCNTRL,
358 (CPCAP_BIT_ID100KPU | CPCAP_BIT_IDPUCNTRL));
362 req.format = CPCAP_ADC_FORMAT_RAW;
363 req.timing = CPCAP_ADC_TIMING_IMM;
364 req.type = CPCAP_ADC_TYPE_BANK_0;
366 ret = cpcap_adc_sync_read(di->cpcap, &req);
368 cpcap_regacc_write(di->cpcap, CPCAP_REG_USBC1, value,
369 (CPCAP_BIT_ID100KPU | CPCAP_BIT_IDPUCNTRL));
372 pr_info("%s: ADC result=0x%X (ret=%d, status=%d)\n", __func__,
373 req.result[CPCAP_ADC_USB_ID], ret, req.status);
375 audio = (req.result[CPCAP_ADC_USB_ID] > ADC_AUDIO_THRES) ? 1 : 0;
376 switch_set_state(&di->asdev, audio);
377 tegra_cpcap_audio_dock_state(!!audio);
379 pr_info("%s: Audio cable %s present\n", __func__,
380 (audio ? "is" : "not"));
383 static void whisper_det_work(struct work_struct *work)
385 struct cpcap_whisper_data *data =
386 container_of(work, struct cpcap_whisper_data, work.work);
388 switch (data->state) {
390 wake_lock(&data->wake_lock);
392 cpcap_irq_mask(data->cpcap, CPCAP_IRQ_CHRG_DET);
393 cpcap_irq_mask(data->cpcap, CPCAP_IRQ_IDFLOAT);
394 cpcap_irq_mask(data->cpcap, CPCAP_IRQ_IDGND);
396 configure_hardware(data, CPCAP_ACCY_UNKNOWN);
398 data->state = SAMPLE_1;
399 queue_delayed_work(data->wq, &data->work, msecs_to_jiffies(11));
404 data->state = SAMPLE_2;
405 queue_delayed_work(data->wq, &data->work,
406 msecs_to_jiffies(100));
410 data->prev_sense = data->sense;
413 if (data->prev_sense != data->sense) {
414 /* Stay in this state */
415 data->state = SAMPLE_2;
417 data->state = IDENTIFY;
419 queue_delayed_work(data->wq, &data->work,
420 msecs_to_jiffies(100));
425 data->state = CONFIG;
428 pr_info("%s: sense=0x%04x\n", __func__, data->sense);
430 if ((data->sense == SENSE_USB_CLIENT) ||
431 (data->sense == SENSE_USB_FLASH) ||
432 (data->sense == SENSE_FACTORY)) {
433 whisper_notify(data, CPCAP_ACCY_USB);
435 cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_CHRG_DET);
436 cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_IDGND);
438 /* Special handling of USB undetect. */
440 } else if ((data->sense & SENSE_USB_HOST_MASK) ==
442 whisper_notify(data, CPCAP_ACCY_USB_HOST);
444 data->state = USB_POWER;
445 queue_delayed_work(data->wq, &data->work,
446 msecs_to_jiffies(200));
447 } else if ((data->sense == SENSE_WHISPER_SPD) ||
448 (data->sense == SENSE_WHISPER_PPD)) {
449 gpio_set_value(data->pdata->pwr_gpio, 1);
451 /* Extra identification step for Whisper. */
452 data->state = IDENTIFY_WHISPER;
453 queue_delayed_work(data->wq, &data->work,
454 msecs_to_jiffies(47));
455 } else if (data->sense == SENSE_WHISPER_SMART) {
456 whisper_notify(data, CPCAP_ACCY_WHISPER_SMART);
458 cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_CHRG_DET);
459 cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_IDGND);
461 /* Special handling of Whisper Smart accessories. */
462 data->state = WHISPER_SMART;
463 } else if ((data->sense == SENSE_CHARGER_FLOAT) ||
464 (data->sense == SENSE_CHARGER)) {
465 whisper_notify(data, CPCAP_ACCY_CHARGER);
467 cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_CHRG_DET);
469 whisper_notify(data, CPCAP_ACCY_NONE);
471 cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_CHRG_DET);
472 cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_IDFLOAT);
476 case IDENTIFY_WHISPER:
478 data->state = CONFIG;
481 pr_info("%s: sense=0x%04x\n", __func__, data->sense);
483 if (data->sense & CPCAP_BIT_SE1_S) {
484 whisper_notify(data, CPCAP_ACCY_WHISPER);
486 cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_IDFLOAT);
487 cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_IDGND);
489 /* Special handling of Whisper undetect. */
490 data->state = WHISPER;
492 whisper_notify(data, CPCAP_ACCY_NONE);
494 cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_CHRG_DET);
495 cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_IDFLOAT);
502 /* Check if Smart Whisper accessory fully inserted. */
503 if (data->sense == SENSE_WHISPER_SMART) {
504 data->state = WHISPER_SMART;
506 whisper_notify(data, CPCAP_ACCY_NONE);
507 whisper_notify(data, CPCAP_ACCY_WHISPER_SMART);
509 cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_CHRG_DET);
510 cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_IDGND);
512 data->state = CONFIG;
513 queue_delayed_work(data->wq, &data->work, 0);
519 gpio_set_value(data->pdata->pwr_gpio, 1);
520 data->state = CONFIG;
521 cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_IDFLOAT);
527 /* The removal of a Whisper accessory can only be detected
530 if (data->sense & CPCAP_BIT_ID_FLOAT_S) {
531 data->state = CONFIG;
532 queue_delayed_work(data->wq, &data->work, 0);
534 if (!(data->sense & CPCAP_BIT_ID_GROUND_S))
535 whisper_audio_check(data);
537 cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_IDFLOAT);
538 cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_IDGND);
545 /* The removal of a Whisper Smart accessory can only be detected
546 * when VBUS disappears.
548 if (!(data->sense & CPCAP_BIT_VBUSVLD_S)) {
549 data->state = CONFIG;
550 queue_delayed_work(data->wq, &data->work, 0);
552 if (!(data->sense & CPCAP_BIT_ID_GROUND_S))
553 pr_info("%s: ID no longer ground\n", __func__);
555 cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_CHRG_DET);
560 /* This shouldn't happen. Need to reset state machine. */
562 data->state = CONFIG;
563 queue_delayed_work(data->wq, &data->work, 0);
568 static void whisper_int_handler(enum cpcap_irqs int_event, void *data)
570 struct cpcap_whisper_data *di = data;
573 pr_info("%s: irq=%d\n", __func__, int_event);
575 queue_delayed_work(di->wq, &(di->work), 0);
578 int cpcap_accy_whisper(struct cpcap_device *cpcap,
579 struct cpcap_whisper_request *req)
581 struct cpcap_whisper_data *di = cpcap->accydata;
582 int retval = -EAGAIN;
583 unsigned short value = 0;
589 /* Can only change settings if not debouncing and whisper device
591 if (di->state == WHISPER) {
592 if (req->cmd & CPCAP_WHISPER_ENABLE_UART)
593 value = CPCAP_BIT_EMUMODE0;
594 retval = cpcap_regacc_write(cpcap, CPCAP_REG_USBC2, value,
595 (CPCAP_BIT_EMUMODE2 |
597 CPCAP_BIT_EMUMODE0));
599 value = (req->cmd & CPCAP_WHISPER_MODE_PU) ?
600 CPCAP_BIT_ID100KPU : 0;
601 retval |= cpcap_regacc_write(cpcap, CPCAP_REG_USBC1,
602 value, CPCAP_BIT_ID100KPU);
604 retval |= cpcap_regacc_write(cpcap, CPCAP_REG_USBC2,
605 (CPCAP_BIT_EMUMODE2 |
607 (CPCAP_BIT_EMUMODE2 |
609 CPCAP_BIT_EMUMODE0));
612 /* Report dock type to system. */
613 dock = (req->cmd & CPCAP_WHISPER_ACCY_MASK) >>
614 CPCAP_WHISPER_ACCY_SHFT;
615 if (dock && (strlen(req->dock_id) < CPCAP_WHISPER_ID_SIZE))
616 strncpy(di->dock_id, req->dock_id,
617 CPCAP_WHISPER_ID_SIZE);
618 if (dock && (strlen(req->dock_prop) < CPCAP_WHISPER_PROP_SIZE))
619 strncpy(di->dock_prop, req->dock_prop,
620 CPCAP_WHISPER_PROP_SIZE);
621 switch_set_state(&di->dsdev, dock);
623 whisper_audio_check(di);
624 } else if (di->state == WHISPER_SMART) {
625 /* Report dock type to system. */
626 dock = (req->cmd & CPCAP_WHISPER_ACCY_MASK) >>
627 CPCAP_WHISPER_ACCY_SHFT;
628 if (dock && (strlen(req->dock_id) < CPCAP_WHISPER_ID_SIZE))
629 strncpy(di->dock_id, req->dock_id,
630 CPCAP_WHISPER_ID_SIZE);
631 if (dock && (strlen(req->dock_prop) < CPCAP_WHISPER_PROP_SIZE))
632 strncpy(di->dock_prop, req->dock_prop,
633 CPCAP_WHISPER_PROP_SIZE);
634 switch_set_state(&di->dsdev, dock);
641 void cpcap_accy_whisper_spdif_set_state(int state)
646 if (!switch_get_state(&whisper_di->dsdev))
649 state = ((state > 0) ? 2 : 0);
650 switch_set_state(&whisper_di->asdev, state);
652 pr_info("%s: Audio cable %s present\n", __func__,
653 (state ? "is" : "not"));
656 static int cpcap_whisper_probe(struct platform_device *pdev)
659 struct cpcap_whisper_data *data;
661 if (pdev->dev.platform_data == NULL) {
662 dev_err(&pdev->dev, "no platform_data\n");
666 data = kzalloc(sizeof(*data), GFP_KERNEL);
670 data->pdata = pdev->dev.platform_data;
671 data->cpcap = platform_get_drvdata(pdev);
672 data->state = CONFIG;
673 data->wq = create_singlethread_workqueue("cpcap_whisper");
674 INIT_DELAYED_WORK(&data->work, whisper_det_work);
675 wake_lock_init(&data->wake_lock, WAKE_LOCK_SUSPEND, "whisper");
677 data->wsdev.name = "whisper";
678 switch_dev_register(&data->wsdev);
680 data->asdev.name = "usb_audio";
681 switch_dev_register(&data->asdev);
683 data->csdev.name = "invalid_charger";
684 switch_dev_register(&data->csdev);
686 data->dsdev.name = "dock";
687 data->dsdev.print_name = print_name;
688 switch_dev_register(&data->dsdev);
689 retval = device_create_file(data->dsdev.dev, &dev_attr_dock_addr);
691 dev_err(&pdev->dev, "Failed to create dock_addr file\n");
694 retval = device_create_file(data->dsdev.dev, &dev_attr_dock_prop);
696 dev_err(&pdev->dev, "Failed to create dock_prop file\n");
700 platform_set_drvdata(pdev, data);
702 data->regulator = regulator_get(&pdev->dev, "vusb");
703 if (IS_ERR(data->regulator)) {
705 "Could not get regulator for cpcap_whisper\n");
706 retval = PTR_ERR(data->regulator);
709 regulator_set_voltage(data->regulator, 3300000, 3300000);
711 retval = cpcap_irq_clear(data->cpcap, CPCAP_IRQ_CHRG_DET);
712 retval |= cpcap_irq_clear(data->cpcap, CPCAP_IRQ_IDFLOAT);
713 retval |= cpcap_irq_clear(data->cpcap, CPCAP_IRQ_IDGND);
715 retval |= cpcap_irq_register(data->cpcap, CPCAP_IRQ_CHRG_DET,
716 whisper_int_handler, data);
717 retval |= cpcap_irq_register(data->cpcap, CPCAP_IRQ_IDFLOAT,
718 whisper_int_handler, data);
719 retval |= cpcap_irq_register(data->cpcap, CPCAP_IRQ_IDGND,
720 whisper_int_handler, data);
722 retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC2,
723 (data->pdata->uartmux << 8),
724 (CPCAP_BIT_UARTMUX1 | CPCAP_BIT_UARTMUX0));
727 dev_err(&pdev->dev, "Initialization Error\n");
732 #ifdef CONFIG_USB_CPCAP_OTG
733 data->otg = otg_get_transceiver();
736 data->cpcap->accydata = data;
738 dev_info(&pdev->dev, "CPCAP Whisper detection probed\n");
740 /* Perform initial detection */
741 whisper_det_work(&(data->work.work));
746 cpcap_irq_free(data->cpcap, CPCAP_IRQ_IDGND);
747 cpcap_irq_free(data->cpcap, CPCAP_IRQ_IDFLOAT);
748 cpcap_irq_free(data->cpcap, CPCAP_IRQ_CHRG_DET);
749 regulator_put(data->regulator);
751 device_remove_file(data->dsdev.dev, &dev_attr_dock_prop);
753 device_remove_file(data->dsdev.dev, &dev_attr_dock_addr);
755 switch_dev_unregister(&data->wsdev);
756 switch_dev_unregister(&data->dsdev);
757 switch_dev_unregister(&data->asdev);
758 switch_dev_unregister(&data->csdev);
759 wake_lock_destroy(&data->wake_lock);
765 static int __exit cpcap_whisper_remove(struct platform_device *pdev)
767 struct cpcap_whisper_data *data = platform_get_drvdata(pdev);
769 cpcap_irq_free(data->cpcap, CPCAP_IRQ_CHRG_DET);
770 cpcap_irq_free(data->cpcap, CPCAP_IRQ_IDFLOAT);
771 cpcap_irq_free(data->cpcap, CPCAP_IRQ_IDGND);
773 configure_hardware(data, CPCAP_ACCY_NONE);
774 cancel_delayed_work_sync(&data->work);
775 destroy_workqueue(data->wq);
777 device_remove_file(data->dsdev.dev, &dev_attr_dock_prop);
778 device_remove_file(data->dsdev.dev, &dev_attr_dock_addr);
779 switch_dev_unregister(&data->wsdev);
780 switch_dev_unregister(&data->dsdev);
781 switch_dev_unregister(&data->asdev);
782 switch_dev_unregister(&data->csdev);
784 gpio_set_value(data->pdata->data_gpio, 1);
787 regulator_put(data->regulator);
789 #ifdef CONFIG_USB_CPCAP_OTG
791 otg_put_transceiver(data->otg);
794 wake_lock_destroy(&data->wake_lock);
796 data->cpcap->accydata = NULL;
802 static struct platform_driver cpcap_whisper_driver = {
803 .probe = cpcap_whisper_probe,
804 .remove = __exit_p(cpcap_whisper_remove),
806 .name = "cpcap_whisper",
807 .owner = THIS_MODULE,
811 static int __init cpcap_whisper_init(void)
813 return cpcap_driver_register(&cpcap_whisper_driver);
815 late_initcall(cpcap_whisper_init);
817 static void __exit cpcap_whisper_exit(void)
819 cpcap_driver_unregister(&cpcap_whisper_driver);
821 module_exit(cpcap_whisper_exit);
823 MODULE_ALIAS("platform:cpcap_whisper");
824 MODULE_DESCRIPTION("CPCAP Whisper detection driver");
825 MODULE_AUTHOR("Motorola");
826 MODULE_LICENSE("GPL");