Commit 1660557b authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'extcon-next-for-5.6' of...

Merge tag 'extcon-next-for-5.6' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon into char-misc-next

Chanwoo writes:

Update extcon for 5.6

Detailed description for this pull request:
1. Remove unneeded 'extern' keyword from extcon.h header file
2. Clean-up the extcon provider
- Clean-up the code for readability of extcon-arizona/sm5502.c

* tag 'extcon-next-for-5.6' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon:
  extcon: Remove unneeded extern keyword from extcon.h
  extcon: sm5502: Remove unneeded semicolon
  extcon: arizona: Factor out microphone and button detection
  extcon: arizona: Factor out microphone impedance into a function
  extcon: arizona: Invert logic of check in arizona_hpdet_do_id
  extcon: arizona: Remove excessive WARN_ON
  extcon: arizona: Remove unnecessary sets of ACCDET_MODE
  extcon: arizona: Tidy up transition from mic to headphone detect
  extcon: arizona: Clear jack status regardless of detection type
  extcon: arizona: Move pdata extraction to probe
  extcon: arizona: Make rev A register sequences atomic
  extcon: arizona: Correct clean up if arizona_identify_headphone fails
parents 40ce9798 b7365587
Loading
Loading
Loading
Loading
+194 −160
Original line number Diff line number Diff line
@@ -77,8 +77,6 @@ struct arizona_extcon_info {
	const struct arizona_micd_range *micd_ranges;
	int num_micd_ranges;

	int micd_timeout;

	bool micd_reva;
	bool micd_clamp;

@@ -310,9 +308,13 @@ static void arizona_start_mic(struct arizona_extcon_info *info)
	}

	if (info->micd_reva) {
		regmap_write(arizona->regmap, 0x80, 0x3);
		regmap_write(arizona->regmap, 0x294, 0);
		regmap_write(arizona->regmap, 0x80, 0x0);
		const struct reg_sequence reva[] = {
			{ 0x80,  0x3 },
			{ 0x294, 0x0 },
			{ 0x80,  0x0 },
		};

		regmap_multi_reg_write(arizona->regmap, reva, ARRAY_SIZE(reva));
	}

	if (info->detecting && arizona->pdata.micd_software_compare)
@@ -361,9 +363,13 @@ static void arizona_stop_mic(struct arizona_extcon_info *info)
	snd_soc_dapm_sync(dapm);

	if (info->micd_reva) {
		regmap_write(arizona->regmap, 0x80, 0x3);
		regmap_write(arizona->regmap, 0x294, 2);
		regmap_write(arizona->regmap, 0x80, 0x0);
		const struct reg_sequence reva[] = {
			{ 0x80,  0x3 },
			{ 0x294, 0x2 },
			{ 0x80,  0x0 },
		};

		regmap_multi_reg_write(arizona->regmap, reva, ARRAY_SIZE(reva));
	}

	ret = regulator_allow_bypass(info->micvdd, true);
@@ -527,11 +533,13 @@ static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading,
	struct arizona *arizona = info->arizona;
	int id_gpio = arizona->pdata.hpdet_id_gpio;

	if (!arizona->pdata.hpdet_acc_id)
		return 0;

	/*
	 * If we're using HPDET for accessory identification we need
	 * to take multiple measurements, step through them in sequence.
	 */
	if (arizona->pdata.hpdet_acc_id) {
	info->hpdet_res[info->num_hpdet_res++] = *reading;

	/* Only check the mic directly if we didn't already ID it */
@@ -547,8 +555,7 @@ static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading,

		gpio_set_value_cansleep(id_gpio, 1);

			regmap_update_bits(arizona->regmap,
					   ARIZONA_HEADPHONE_DETECT_1,
		regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
				   ARIZONA_HP_POLL, ARIZONA_HP_POLL);
		return -EAGAIN;
	}
@@ -582,11 +589,8 @@ static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading,
	}

	/* Make sure everything is reset back to the real polarity */
		regmap_update_bits(arizona->regmap,
				   ARIZONA_ACCESSORY_DETECT_MODE_1,
				   ARIZONA_ACCDET_SRC,
				   info->micd_modes[0].src);
	}
	regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
			   ARIZONA_ACCDET_SRC, info->micd_modes[0].src);

	return 0;
}
@@ -662,11 +666,6 @@ done:
	if (id_gpio)
		gpio_set_value_cansleep(id_gpio, 0);

	/* Revert back to MICDET mode */
	regmap_update_bits(arizona->regmap,
			   ARIZONA_ACCESSORY_DETECT_MODE_1,
			   ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);

	/* If we have a mic then reenable MICDET */
	if (mic || info->mic)
		arizona_start_mic(info);
@@ -699,7 +698,6 @@ static void arizona_identify_headphone(struct arizona_extcon_info *info)

	info->hpdet_active = true;

	if (info->mic)
	arizona_stop_mic(info);

	arizona_extcon_hp_clamp(info, true);
@@ -724,8 +722,8 @@ static void arizona_identify_headphone(struct arizona_extcon_info *info)
	return;

err:
	regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
			   ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
	arizona_extcon_hp_clamp(info, false);
	pm_runtime_put_autosuspend(info->dev);

	/* Just report headphone */
	ret = extcon_set_state_sync(info->edev, EXTCON_JACK_HEADPHONE, true);
@@ -781,9 +779,6 @@ static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
	return;

err:
	regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
			   ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);

	/* Just report headphone */
	ret = extcon_set_state_sync(info->edev, EXTCON_JACK_HEADPHONE, true);
	if (ret != 0)
@@ -806,48 +801,24 @@ static void arizona_micd_timeout_work(struct work_struct *work)

	arizona_identify_headphone(info);

	arizona_stop_mic(info);

	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);
@@ -866,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);
@@ -882,29 +860,44 @@ 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");
		mutex_unlock(&info->lock);
		return;
		return -EINVAL;
	}

	return val;
}

static int arizona_micdet_reading(void *priv)
{
	struct arizona_extcon_info *info = priv;
	struct arizona *arizona = info->arizona;
	int ret, val;

	if (info->detecting && arizona->pdata.micd_software_compare)
		ret = arizona_micd_adc_read(info);
	else
		ret = arizona_micd_read(info);
	if (ret < 0)
		return ret;

	val = ret;

	/* Due to jack detect this should never happen */
	if (!(val & ARIZONA_MICD_STS)) {
		dev_warn(arizona->dev, "Detected open circuit\n");
		info->mic = false;
		arizona_stop_mic(info);
		info->detecting = false;
		arizona_identify_headphone(info);
		goto handled;
		return 0;
	}

	/* If we got a high impedence we should have a headset, report it. */
	if (info->detecting && (val & ARIZONA_MICD_LVL_8)) {
	if (val & ARIZONA_MICD_LVL_8) {
		info->mic = true;
		info->detecting = false;

@@ -923,7 +916,7 @@ static void arizona_micd_detect(struct work_struct *work)
				ret);
		}

		goto handled;
		return 0;
	}

	/* If we detected a lower impedence during initial startup
@@ -932,15 +925,13 @@ static void arizona_micd_detect(struct work_struct *work)
	 * plain headphones.  If both polarities report a low
	 * impedence then give up and report headphones.
	 */
	if (info->detecting && (val & MICD_LVL_1_TO_7)) {
	if (val & MICD_LVL_1_TO_7) {
		if (info->jack_flips >= info->micd_num_modes * 10) {
			dev_dbg(arizona->dev, "Detected HP/line\n");

			info->detecting = false;

			arizona_identify_headphone(info);

			arizona_stop_mic(info);
		} else {
			info->micd_mode++;
			if (info->micd_mode == info->micd_num_modes)
@@ -948,11 +939,43 @@ static void arizona_micd_detect(struct work_struct *work)
			arizona_extcon_set_mode(info, info->micd_mode);

			info->jack_flips++;

			if (arizona->pdata.micd_software_compare)
				regmap_update_bits(arizona->regmap,
						   ARIZONA_MIC_DETECT_1,
						   ARIZONA_MICD_ENA,
						   ARIZONA_MICD_ENA);

			queue_delayed_work(system_power_efficient_wq,
					   &info->micd_timeout_work,
					   msecs_to_jiffies(arizona->pdata.micd_timeout));
		}

		goto handled;
		return 0;
	}

	/*
	 * If we're still detecting and we detect a short then we've
	 * got a headphone.
	 */
	dev_dbg(arizona->dev, "Headphone detected\n");
	info->detecting = false;

	arizona_identify_headphone(info);

	return 0;
}

static int arizona_button_reading(void *priv)
{
	struct arizona_extcon_info *info = priv;
	struct arizona *arizona = info->arizona;
	int val, key, lvl, i;

	val = arizona_micd_read(info);
	if (val < 0)
		return val;

	/*
	 * If we're still detecting and we detect a short then we've
	 * got a headphone.  Otherwise it's a button press.
@@ -968,20 +991,13 @@ static void arizona_micd_detect(struct work_struct *work)
				input_report_key(info->input,
						 info->micd_ranges[i].key, 0);

			WARN_ON(!lvl);
			WARN_ON(ffs(lvl) - 1 >= info->num_micd_ranges);
			if (lvl && ffs(lvl) - 1 < info->num_micd_ranges) {
				key = info->micd_ranges[ffs(lvl) - 1].key;
				input_report_key(info->input, key, 1);
				input_sync(info->input);
			} else {
				dev_err(arizona->dev, "Button out of range\n");
			}

		} else if (info->detecting) {
			dev_dbg(arizona->dev, "Headphone detected\n");
			info->detecting = false;
			arizona_stop_mic(info);

			arizona_identify_headphone(info);
		} else {
			dev_warn(arizona->dev, "Button with no mic: %x\n",
				 val);
@@ -995,19 +1011,39 @@ static void arizona_micd_detect(struct work_struct *work)
		arizona_extcon_pulse_micbias(info);
	}

handled:
	if (info->detecting) {
		if (arizona->pdata.micd_software_compare)
			regmap_update_bits(arizona->regmap,
					   ARIZONA_MIC_DETECT_1,
					   ARIZONA_MICD_ENA,
					   ARIZONA_MICD_ENA);
	return 0;
}

		queue_delayed_work(system_power_efficient_wq,
				   &info->micd_timeout_work,
				   msecs_to_jiffies(info->micd_timeout));
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;
	int ret;

	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_micdet_reading(info);
	else
		arizona_button_reading(info);

	pm_runtime_mark_last_busy(info->dev);
	mutex_unlock(&info->lock);
}
@@ -1125,7 +1161,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
					   msecs_to_jiffies(HPDET_DEBOUNCE));

		if (cancelled_mic) {
			int micd_timeout = info->micd_timeout;
			int micd_timeout = arizona->pdata.micd_timeout;

			queue_delayed_work(system_power_efficient_wq,
					   &info->micd_timeout_work,
@@ -1145,11 +1181,11 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
			dev_err(arizona->dev, "Mechanical report failed: %d\n",
				ret);

		if (!arizona->pdata.hpdet_acc_id) {
		info->detecting = true;
		info->mic = false;
		info->jack_flips = 0;

		if (!arizona->pdata.hpdet_acc_id) {
			arizona_start_mic(info);
		} else {
			queue_delayed_work(system_power_efficient_wq,
@@ -1202,11 +1238,6 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
				   ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB);
	}

	if (arizona->pdata.micd_timeout)
		info->micd_timeout = arizona->pdata.micd_timeout;
	else
		info->micd_timeout = DEFAULT_MICD_TIMEOUT;

out:
	/* Clear trig_sts to make sure DCVDD is not forced up */
	regmap_write(arizona->regmap, ARIZONA_AOD_WKUP_AND_TRIG,
@@ -1435,6 +1466,9 @@ static int arizona_extcon_probe(struct platform_device *pdev)
	info->input->name = "Headset";
	info->input->phys = "arizona/extcon";

	if (!pdata->micd_timeout)
		pdata->micd_timeout = DEFAULT_MICD_TIMEOUT;

	if (pdata->num_micd_configs) {
		info->micd_modes = pdata->micd_configs;
		info->micd_num_modes = pdata->num_micd_configs;
+5 −5
Original line number Diff line number Diff line
@@ -249,7 +249,7 @@ static int sm5502_muic_set_path(struct sm5502_muic_info *info,
		dev_err(info->dev, "Unknown DM_CON/DP_CON switch type (%d)\n",
				con_sw);
		return -EINVAL;
	};
	}

	switch (vbus_sw) {
	case VBUSIN_SWITCH_OPEN:
@@ -268,7 +268,7 @@ static int sm5502_muic_set_path(struct sm5502_muic_info *info,
	default:
		dev_err(info->dev, "Unknown VBUS switch type (%d)\n", vbus_sw);
		return -EINVAL;
	};
	}

	return 0;
}
@@ -357,13 +357,13 @@ static unsigned int sm5502_muic_get_cable_type(struct sm5502_muic_info *info)
				"cannot identify the cable type: adc(0x%x)\n",
				adc);
			return -EINVAL;
		};
		}
		break;
	default:
		dev_err(info->dev,
			"failed to identify the cable type: adc(0x%x)\n", adc);
		return -EINVAL;
	};
	}

	return cable_type;
}
@@ -405,7 +405,7 @@ static int sm5502_muic_cable_handler(struct sm5502_muic_info *info,
		dev_dbg(info->dev,
			"cannot handle this cable_type (0x%x)\n", cable_type);
		return 0;
	};
	}

	/* Change internal hardware path(DM_CON/DP_CON, VBUSIN) */
	ret = sm5502_muic_set_path(info, con_sw, vbus_sw, attached);
+15 −15
Original line number Diff line number Diff line
@@ -170,7 +170,7 @@ struct extcon_dev;
 * Following APIs get the connected state of each external connector.
 * The 'id' argument indicates the defined external connector.
 */
extern int extcon_get_state(struct extcon_dev *edev, unsigned int id);
int extcon_get_state(struct extcon_dev *edev, unsigned int id);

/*
 * Following APIs get the property of each external connector.
@@ -181,10 +181,10 @@ extern int extcon_get_state(struct extcon_dev *edev, unsigned int id);
 * for each external connector. They are used to get the capability of the
 * property of each external connector based on the id and property.
 */
extern int extcon_get_property(struct extcon_dev *edev, unsigned int id,
int extcon_get_property(struct extcon_dev *edev, unsigned int id,
				unsigned int prop,
				union extcon_property_value *prop_val);
extern int extcon_get_property_capability(struct extcon_dev *edev,
int extcon_get_property_capability(struct extcon_dev *edev,
				unsigned int id, unsigned int prop);

/*
@@ -196,38 +196,38 @@ extern int extcon_get_property_capability(struct extcon_dev *edev,
 * extcon_register_notifier_all(*edev, *nb) : Register a notifier block
 *			for all supported external connectors of the extcon.
 */
extern int extcon_register_notifier(struct extcon_dev *edev, unsigned int id,
int extcon_register_notifier(struct extcon_dev *edev, unsigned int id,
				struct notifier_block *nb);
extern int extcon_unregister_notifier(struct extcon_dev *edev, unsigned int id,
int extcon_unregister_notifier(struct extcon_dev *edev, unsigned int id,
				struct notifier_block *nb);
extern int devm_extcon_register_notifier(struct device *dev,
int devm_extcon_register_notifier(struct device *dev,
				struct extcon_dev *edev, unsigned int id,
				struct notifier_block *nb);
extern void devm_extcon_unregister_notifier(struct device *dev,
void devm_extcon_unregister_notifier(struct device *dev,
				struct extcon_dev *edev, unsigned int id,
				struct notifier_block *nb);

extern int extcon_register_notifier_all(struct extcon_dev *edev,
int extcon_register_notifier_all(struct extcon_dev *edev,
				struct notifier_block *nb);
extern int extcon_unregister_notifier_all(struct extcon_dev *edev,
int extcon_unregister_notifier_all(struct extcon_dev *edev,
				struct notifier_block *nb);
extern int devm_extcon_register_notifier_all(struct device *dev,
int devm_extcon_register_notifier_all(struct device *dev,
				struct extcon_dev *edev,
				struct notifier_block *nb);
extern void devm_extcon_unregister_notifier_all(struct device *dev,
void devm_extcon_unregister_notifier_all(struct device *dev,
				struct extcon_dev *edev,
				struct notifier_block *nb);

/*
 * Following APIs get the extcon_dev from devicetree or by through extcon name.
 */
extern struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name);
extern struct extcon_dev *extcon_find_edev_by_node(struct device_node *node);
extern struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev,
struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name);
struct extcon_dev *extcon_find_edev_by_node(struct device_node *node);
struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev,
						     int index);

/* Following API get the name of extcon device. */
extern const char *extcon_get_edev_name(struct extcon_dev *edev);
const char *extcon_get_edev_name(struct extcon_dev *edev);

#else /* CONFIG_EXTCON */
static inline int extcon_get_state(struct extcon_dev *edev, unsigned int id)