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

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
Loading
Loading
Loading
Loading
+73 −52
Original line number Diff line number Diff line
@@ -804,43 +804,21 @@ 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);

	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;
	}
	unsigned int val;
	int 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;
			"Failed to read MICDET_ADCVAL: %d\n", ret);
		return ret;
	}

	dev_dbg(arizona->dev, "MICDET_ADCVAL: %x\n", val);
@@ -859,15 +837,22 @@ static void arizona_micd_detect(struct work_struct *work)
		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");