mfd: cpcap-whisper: Accessory detection updates
authorGreg Meiste <w30289@motorola.com>
Thu, 10 Jun 2010 16:31:33 +0000 (11:31 -0500)
committerColin Cross <ccross@android.com>
Wed, 6 Oct 2010 23:33:10 +0000 (16:33 -0700)
1) Added detection of Whisper Smart dock
2) Now enable VBUS for USB hosts
3) Added support for Whisper daemon to enable/disable UART
4) Fixed issue resulting in extra ID Float interrupt

Change-Id: I1531429bc90241de6139390eb7a2ac19f13ca78b
Signed-off-by: Greg Meiste <w30289@motorola.com>
drivers/mfd/cpcap-whisper.c
include/linux/spi/cpcap.h

index f874f51848b5acbfd45e7a6eb150260a2305e5da..8e41c7c165cdc5d9b1e50f1e118486674889ae96 100644 (file)
 
 #define SENSE_WHISPER_PPD   (0)
 
+#define SENSE_WHISPER_SMART (CPCAP_BIT_ID_GROUND_S | \
+                            CPCAP_BIT_VBUSVLD_S   | \
+                            CPCAP_BIT_SESSVLD_S)
+
 /* TODO: Update with appropriate value. */
 #define ADC_AUDIO_THRES     0x12C
 
@@ -63,6 +67,7 @@ enum cpcap_det_state {
 
 enum cpcap_accy {
        CPCAP_ACCY_USB,
+       CPCAP_ACCY_USB_HOST,
        CPCAP_ACCY_WHISPER,
        CPCAP_ACCY_NONE,
 
@@ -149,8 +154,10 @@ static int get_sense(struct cpcap_whisper_data *data)
        /* Clear ASAP after read. */
        retval = cpcap_regacc_write(cpcap, CPCAP_REG_INT1,
                                     (CPCAP_BIT_CHRG_DET_I |
+                                     CPCAP_BIT_ID_FLOAT_I |
                                      CPCAP_BIT_ID_GROUND_I),
                                     (CPCAP_BIT_CHRG_DET_I |
+                                     CPCAP_BIT_ID_FLOAT_I |
                                      CPCAP_BIT_ID_GROUND_I));
        if (retval)
                return retval;
@@ -195,20 +202,18 @@ static int configure_hardware(struct cpcap_whisper_data *data,
                retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC1, 0,
                                             CPCAP_BIT_VBUSPD);
                gpio_set_value(data->pdata->data_gpio, 1);
-               /* TODO: Does this driver enable "reverse mode" for hosts? */
+               break;
+
+       case CPCAP_ACCY_USB_HOST:
+               retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC1, 0,
+                                            CPCAP_BIT_VBUSPD);
+               gpio_set_value(data->pdata->pwr_gpio, 1);
+               gpio_set_value(data->pdata->data_gpio, 1);
                break;
 
        case CPCAP_ACCY_WHISPER:
                retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC1, 0,
                                             CPCAP_BIT_VBUSPD);
-               retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC2,
-                                            ((data->pdata->uartmux << 8) |
-                                             CPCAP_BIT_EMUMODE0),
-                                            (CPCAP_BIT_UARTMUX1 |
-                                             CPCAP_BIT_UARTMUX0 |
-                                             CPCAP_BIT_EMUMODE2 |
-                                             CPCAP_BIT_EMUMODE1 |
-                                             CPCAP_BIT_EMUMODE0));
                break;
 
        case CPCAP_ACCY_UNKNOWN:
@@ -241,7 +246,7 @@ static int configure_hardware(struct cpcap_whisper_data *data,
        return retval;
 }
 
-static const char *accy_names[3] = {"USB", "whisper", "none"};
+static const char *accy_names[4] = {"USB", "USB host", "whisper", "none"};
 
 static void whisper_notify(struct cpcap_whisper_data *di, enum cpcap_accy accy)
 {
@@ -351,12 +356,13 @@ static void whisper_det_work(struct work_struct *work)
 
                if ((data->sense == SENSE_USB_CLIENT) ||
                    (data->sense == SENSE_USB_FLASH) ||
-                   (data->sense == SENSE_FACTORY)) {
+                   (data->sense == SENSE_FACTORY) ||
+                   (data->sense == SENSE_WHISPER_SMART)) {
                        whisper_notify(data, CPCAP_ACCY_USB);
 
                        cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_CHRG_DET);
                } else if (data->sense == SENSE_USB_HOST) {
-                       whisper_notify(data, CPCAP_ACCY_USB);
+                       whisper_notify(data, CPCAP_ACCY_USB_HOST);
 
                        cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_IDFLOAT);
                } else if (data->sense == SENSE_WHISPER_PPD) {
@@ -407,9 +413,8 @@ static void whisper_det_work(struct work_struct *work)
                        data->state = CONFIG;
                        schedule_delayed_work(&data->work, 0);
                } else {
-                       if (!(data->sense & CPCAP_BIT_ID_GROUND_S)) {
+                       if (!(data->sense & CPCAP_BIT_ID_GROUND_S))
                                whisper_audio_check(data);
-                       }
 
                        cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_IDFLOAT);
                        cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_IDGND);
@@ -439,7 +444,7 @@ int cpcap_accy_whisper(struct cpcap_device *cpcap, unsigned long cmd)
 {
        struct cpcap_whisper_data *di = cpcap->accydata;
        int retval = -EAGAIN;
-       unsigned short value;
+       unsigned short value = 0;
        int dock;
 
        if (!di)
@@ -448,10 +453,16 @@ int cpcap_accy_whisper(struct cpcap_device *cpcap, unsigned long cmd)
        /* Can only change settings if not debouncing and whisper device
         * is present. */
        if (di->state == WHISPER) {
-               value = (cmd & CPCAP_WHISPER_MODE_PU) ? CPCAP_BIT_ID100KPU : 0;
+               if (cmd & CPCAP_WHISPER_ENABLE_UART)
+                       value = CPCAP_BIT_EMUMODE0;
+               retval = cpcap_regacc_write(cpcap, CPCAP_REG_USBC2, value,
+                                           (CPCAP_BIT_EMUMODE2 |
+                                            CPCAP_BIT_EMUMODE1 |
+                                            CPCAP_BIT_EMUMODE0));
 
-               retval = cpcap_regacc_write(cpcap, CPCAP_REG_USBC1,
-                                           value, CPCAP_BIT_ID100KPU);
+               value = (cmd & CPCAP_WHISPER_MODE_PU) ? CPCAP_BIT_ID100KPU : 0;
+               retval |= cpcap_regacc_write(cpcap, CPCAP_REG_USBC1,
+                                            value, CPCAP_BIT_ID100KPU);
 
                /* Report dock type to system. */
                dock = (cmd & CPCAP_WHISPER_ACCY_MASK) >>
@@ -517,6 +528,10 @@ static int __init cpcap_whisper_probe(struct platform_device *pdev)
        retval |= cpcap_irq_register(data->cpcap, CPCAP_IRQ_IDGND,
                                     whisper_int_handler, data);
 
+       retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC2,
+                                    (data->pdata->uartmux << 8),
+                                    (CPCAP_BIT_UARTMUX1 | CPCAP_BIT_UARTMUX0));
+
        if (retval != 0) {
                dev_err(&pdev->dev, "Initialization Error\n");
                retval = -ENODEV;
index 13df90046c35312818b0b39853fbccd4b0e81d91..d0d82c4291ba2bce8ebb5671a5b8abd2ea88fd65 100644 (file)
 #define CPCAP_IRQ_INT4_INDEX 48
 #define CPCAP_IRQ_INT5_INDEX 64
 
-#define CPCAP_WHISPER_MODE_PU   0x00000001
-#define CPCAP_WHISPER_ACCY_MASK 0xF1000000
-#define CPCAP_WHISPER_ACCY_SHFT 27
+#define CPCAP_WHISPER_MODE_PU       0x00000001
+#define CPCAP_WHISPER_ENABLE_UART   0x00000002
+#define CPCAP_WHISPER_ACCY_MASK     0xF1000000
+#define CPCAP_WHISPER_ACCY_SHFT     27
 
 enum cpcap_regulator_id {
        CPCAP_SW2,