aboutsummaryrefslogtreecommitdiff
path: root/drivers/extcon
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2013-04-01 19:21:48 +0100
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-04-02 11:54:06 +0100
commitcd59e79656f4e7137909166248a935d422b1245a (patch)
tree008f928dbea75080e8498ae48b9af2ebac8c4b04 /drivers/extcon
parent41a57850b5e5c450da351465efcc41383def7f8a (diff)
extcon: arizona: Allow additional debounce during microphone detection
Help mitigate against mechanical bounce during the initial detection by allowing the configuration of an additional debounce on top of that the hardware does during the initial phase of microphone detection operation. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/extcon')
-rw-r--r--drivers/extcon/extcon-arizona.c35
1 files changed, 30 insertions, 5 deletions
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index 26f9a1ae15c..c7f8eb4299d 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -64,6 +64,7 @@ struct arizona_extcon_info {
bool micd_clamp;
struct delayed_work hpdet_work;
+ struct delayed_work micd_detect_work;
struct delayed_work micd_timeout_work;
bool hpdet_active;
@@ -750,9 +751,11 @@ static void arizona_micd_timeout_work(struct work_struct *work)
mutex_unlock(&info->lock);
}
-static irqreturn_t arizona_micdet(int irq, void *data)
+static void arizona_micd_detect(struct work_struct *work)
{
- struct arizona_extcon_info *info = data;
+ 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;
@@ -766,7 +769,7 @@ static irqreturn_t arizona_micdet(int irq, void *data)
if (ret != 0) {
dev_err(arizona->dev, "Failed to read MICDET: %d\n", ret);
mutex_unlock(&info->lock);
- return IRQ_NONE;
+ return;
}
dev_dbg(arizona->dev, "MICDET: %x\n", val);
@@ -774,14 +777,14 @@ static irqreturn_t arizona_micdet(int irq, void *data)
if (!(val & ARIZONA_MICD_VALID)) {
dev_warn(arizona->dev, "Microphone detection state invalid\n");
mutex_unlock(&info->lock);
- return IRQ_NONE;
+ return;
}
}
if (i == 10 && !(val & 0x7fc)) {
dev_err(arizona->dev, "Failed to get valid MICDET value\n");
mutex_unlock(&info->lock);
- return IRQ_NONE;
+ return;
}
/* Due to jack detect this should never happen */
@@ -890,6 +893,27 @@ handled:
pm_runtime_mark_last_busy(info->dev);
mutex_unlock(&info->lock);
+}
+
+static irqreturn_t arizona_micdet(int irq, void *data)
+{
+ struct arizona_extcon_info *info = data;
+ struct arizona *arizona = info->arizona;
+ int debounce = arizona->pdata.micd_detect_debounce;
+
+ cancel_delayed_work_sync(&info->micd_detect_work);
+ cancel_delayed_work_sync(&info->micd_timeout_work);
+
+ mutex_lock(&info->lock);
+ if (!info->detecting)
+ debounce = 0;
+ mutex_unlock(&info->lock);
+
+ if (debounce)
+ schedule_delayed_work(&info->micd_detect_work,
+ msecs_to_jiffies(debounce));
+ else
+ arizona_micd_detect(&info->micd_detect_work.work);
return IRQ_HANDLED;
}
@@ -1072,6 +1096,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
info->dev = &pdev->dev;
info->last_jackdet = ~(ARIZONA_MICD_CLAMP_STS | ARIZONA_JD1_STS);
INIT_DELAYED_WORK(&info->hpdet_work, arizona_hpdet_work);
+ INIT_DELAYED_WORK(&info->micd_detect_work, arizona_micd_detect);
INIT_DELAYED_WORK(&info->micd_timeout_work, arizona_micd_timeout_work);
platform_set_drvdata(pdev, info);