extcon: max14577: Add extcon-max14577 driver to support MUIC device
[firefly-linux-kernel-4.4.55.git] / drivers / extcon / extcon-arizona.c
index fefb8563db9eb760a1941483092b535022225e14..c20602f601ee22732635aa3fa04fe94e44ed6020 100644 (file)
@@ -435,26 +435,15 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info)
                }
 
                val &= ARIZONA_HP_LVL_B_MASK;
+               /* Convert to ohms, the value is in 0.5 ohm increments */
+               val /= 2;
 
                regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
                            &range);
                range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
                           >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
 
-               /* Skip up or down a range? */
-               if (range && (val < arizona_hpdet_c_ranges[range].min)) {
-                       range--;
-                       dev_dbg(arizona->dev, "Moving to HPDET range %d-%d\n",
-                               arizona_hpdet_c_ranges[range].min,
-                               arizona_hpdet_c_ranges[range].max);
-                       regmap_update_bits(arizona->regmap,
-                                          ARIZONA_HEADPHONE_DETECT_1,
-                                          ARIZONA_HP_IMPEDANCE_RANGE_MASK,
-                                          range <<
-                                          ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
-                       return -EAGAIN;
-               }
-
+               /* Skip up a range, or report? */
                if (range < ARRAY_SIZE(arizona_hpdet_c_ranges) - 1 &&
                    (val >= arizona_hpdet_c_ranges[range].max)) {
                        range++;
@@ -468,6 +457,12 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info)
                                           ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
                        return -EAGAIN;
                }
+
+               if (range && (val < arizona_hpdet_c_ranges[range].min)) {
+                       dev_dbg(arizona->dev, "Reporting range boundary %d\n",
+                               arizona_hpdet_c_ranges[range].min);
+                       val = arizona_hpdet_c_ranges[range].min;
+               }
        }
 
        dev_dbg(arizona->dev, "HP impedance %d ohms\n", val);
@@ -780,6 +775,19 @@ static void arizona_micd_detect(struct work_struct *work)
 
        mutex_lock(&info->lock);
 
+       /* If the cable was removed while measuring ignore the result */
+       ret = extcon_get_cable_state_(&info->edev, ARIZONA_CABLE_MECHANICAL);
+       if (ret < 0) {
+               dev_err(arizona->dev, "Failed to check cable state: %d\n",
+                               ret);
+               mutex_unlock(&info->lock);
+               return;
+       } else if (!ret) {
+               dev_dbg(arizona->dev, "Ignoring MICDET for removed cable\n");
+               mutex_unlock(&info->lock);
+               return;
+       }
+
        for (i = 0; i < 10 && !(val & MICD_LVL_0_TO_8); i++) {
                ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
                if (ret != 0) {
@@ -1141,6 +1149,16 @@ static int arizona_extcon_probe(struct platform_device *pdev)
                        break;
                }
                break;
+       case WM5110:
+               switch (arizona->rev) {
+               case 0 ... 2:
+                       break;
+               default:
+                       info->micd_clamp = true;
+                       info->hpdet_ip = 2;
+                       break;
+               }
+               break;
        default:
                break;
        }