Commit 7e14fc43 authored by Charles Keepax's avatar Charles Keepax Committed by Chanwoo Choi

extcon: arizona: Factor out microphone impedance into a function

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: default avatarCharles Keepax <ckeepax@opensource.cirrus.com>
Signed-off-by: default avatarChanwoo Choi <cw00.choi@samsung.com>
parent 3dfa743d
......@@ -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");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment