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

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
......@@ -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 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data)
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;
......
......@@ -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);
......
......@@ -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)
......
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