extcon: arizona: Factor out microphone impedance into a function
authorCharles Keepax <ckeepax@opensource.cirrus.com>
Mon, 9 Dec 2019 11:09:15 +0000 (11:09 +0000)
committerChanwoo Choi <cw00.choi@samsung.com>
Mon, 9 Dec 2019 11:18:15 +0000 (20:18 +0900)
The microphone detection handler is very long, start breaking it up
by factoring out the actual reading of the impedance value into a
separate functions. Additionally, this also fixes a minor bug and
ensures that the microphone timeout will be rescheduled in all error
cases.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
drivers/extcon/extcon-arizona.c

index a0135f4..b09a9a8 100644 (file)
@@ -804,70 +804,55 @@ static void arizona_micd_timeout_work(struct work_struct *work)
        mutex_unlock(&info->lock);
 }
 
-static void arizona_micd_detect(struct work_struct *work)
+static int arizona_micd_adc_read(struct arizona_extcon_info *info)
 {
-       struct arizona_extcon_info *info = container_of(work,
-                                               struct arizona_extcon_info,
-                                               micd_detect_work.work);
        struct arizona *arizona = info->arizona;
-       unsigned int val = 0, lvl;
-       int ret, i, key;
-
-       cancel_delayed_work_sync(&info->micd_timeout_work);
+       unsigned int val;
+       int ret;
 
-       mutex_lock(&info->lock);
+       /* Must disable MICD before we read the ADCVAL */
+       regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
+                          ARIZONA_MICD_ENA, 0);
 
-       /* If the cable was removed while measuring ignore the result */
-       ret = extcon_get_state(info->edev, EXTCON_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;
+       ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_4, &val);
+       if (ret != 0) {
+               dev_err(arizona->dev,
+                       "Failed to read MICDET_ADCVAL: %d\n", ret);
+               return ret;
        }
 
-       if (info->detecting && arizona->pdata.micd_software_compare) {
-               /* Must disable MICD before we read the ADCVAL */
-               regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
-                                  ARIZONA_MICD_ENA, 0);
-               ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_4, &val);
-               if (ret != 0) {
-                       dev_err(arizona->dev,
-                               "Failed to read MICDET_ADCVAL: %d\n",
-                               ret);
-                       mutex_unlock(&info->lock);
-                       return;
-               }
+       dev_dbg(arizona->dev, "MICDET_ADCVAL: %x\n", val);
 
-               dev_dbg(arizona->dev, "MICDET_ADCVAL: %x\n", val);
+       val &= ARIZONA_MICDET_ADCVAL_MASK;
+       if (val < ARRAY_SIZE(arizona_micd_levels))
+               val = arizona_micd_levels[val];
+       else
+               val = INT_MAX;
+
+       if (val <= QUICK_HEADPHONE_MAX_OHM)
+               val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_0;
+       else if (val <= MICROPHONE_MIN_OHM)
+               val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_1;
+       else if (val <= MICROPHONE_MAX_OHM)
+               val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_8;
+       else
+               val = ARIZONA_MICD_LVL_8;
 
-               val &= ARIZONA_MICDET_ADCVAL_MASK;
-               if (val < ARRAY_SIZE(arizona_micd_levels))
-                       val = arizona_micd_levels[val];
-               else
-                       val = INT_MAX;
-
-               if (val <= QUICK_HEADPHONE_MAX_OHM)
-                       val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_0;
-               else if (val <= MICROPHONE_MIN_OHM)
-                       val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_1;
-               else if (val <= MICROPHONE_MAX_OHM)
-                       val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_8;
-               else
-                       val = ARIZONA_MICD_LVL_8;
-       }
+       return val;
+}
+
+static int arizona_micd_read(struct arizona_extcon_info *info)
+{
+       struct arizona *arizona = info->arizona;
+       unsigned int val = 0;
+       int ret, i;
 
        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) {
                        dev_err(arizona->dev,
                                "Failed to read MICDET: %d\n", ret);
-                       mutex_unlock(&info->lock);
-                       return;
+                       return ret;
                }
 
                dev_dbg(arizona->dev, "MICDET: %x\n", val);
@@ -875,17 +860,53 @@ static void arizona_micd_detect(struct work_struct *work)
                if (!(val & ARIZONA_MICD_VALID)) {
                        dev_warn(arizona->dev,
                                 "Microphone detection state invalid\n");
-                       mutex_unlock(&info->lock);
-                       return;
+                       return -EINVAL;
                }
        }
 
        if (i == 10 && !(val & MICD_LVL_0_TO_8)) {
                dev_err(arizona->dev, "Failed to get valid MICDET value\n");
+               return -EINVAL;
+       }
+
+       return val;
+}
+
+static void arizona_micd_detect(struct work_struct *work)
+{
+       struct arizona_extcon_info *info = container_of(work,
+                                               struct arizona_extcon_info,
+                                               micd_detect_work.work);
+       struct arizona *arizona = info->arizona;
+       unsigned int val = 0, lvl;
+       int ret, i, key;
+
+       cancel_delayed_work_sync(&info->micd_timeout_work);
+
+       mutex_lock(&info->lock);
+
+       /* If the cable was removed while measuring ignore the result */
+       ret = extcon_get_state(info->edev, EXTCON_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;
        }
 
+       if (info->detecting && arizona->pdata.micd_software_compare)
+               ret = arizona_micd_adc_read(info);
+       else
+               ret = arizona_micd_read(info);
+       if (ret < 0)
+               goto handled;
+
+       val = ret;
+
        /* Due to jack detect this should never happen */
        if (!(val & ARIZONA_MICD_STS)) {
                dev_warn(arizona->dev, "Detected open circuit\n");