summaryrefslogtreecommitdiffstats
path: root/drivers/extcon
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2013-02-05 21:00:15 +0000
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-02-11 16:06:22 +0000
commit0e27bd3137778ac9e856fec99b1752bf054a987c (patch)
tree22370d1d7cf24b52bd48cc6e9dd8a83a27c43091 /drivers/extcon
parente339af1c4567b1e63209329e2665781e598709f2 (diff)
extcon: arizona: Add some debounce time before starting HPDET identification
The HPDET identification method does not have the same natural debounce built into it that the standard MICDET method does so add some extra on top of what the jack detection does in hardware to make sure we get a robust result. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/extcon')
-rw-r--r--drivers/extcon/extcon-arizona.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index c17a41ff60e..2ad0e4a35a2 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -53,6 +53,8 @@ struct arizona_extcon_info {
bool micd_reva;
bool micd_clamp;
+ struct delayed_work hpdet_work;
+
bool hpdet_active;
int num_hpdet_res;
@@ -640,7 +642,7 @@ static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
dev_dbg(arizona->dev, "Starting identification via HPDET\n");
/* Make sure we keep the device enabled during the measurement */
- pm_runtime_get(info->dev);
+ pm_runtime_get_sync(info->dev);
info->hpdet_active = true;
@@ -813,6 +815,17 @@ handled:
return IRQ_HANDLED;
}
+static void arizona_hpdet_work(struct work_struct *work)
+{
+ struct arizona_extcon_info *info = container_of(work,
+ struct arizona_extcon_info,
+ hpdet_work.work);
+
+ mutex_lock(&info->lock);
+ arizona_start_hpdet_acc_id(info);
+ mutex_unlock(&info->lock);
+}
+
static irqreturn_t arizona_jackdet(int irq, void *data)
{
struct arizona_extcon_info *info = data;
@@ -822,6 +835,8 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
pm_runtime_get_sync(info->dev);
+ cancel_delayed_work_sync(&info->hpdet_work);
+
mutex_lock(&info->lock);
if (arizona->pdata.jd_gpio5) {
@@ -857,7 +872,8 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
arizona_start_mic(info);
} else {
- arizona_start_hpdet_acc_id(info);
+ schedule_delayed_work(&info->hpdet_work,
+ msecs_to_jiffies(250));
}
regmap_update_bits(arizona->regmap,
@@ -927,6 +943,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
mutex_init(&info->lock);
info->arizona = arizona;
info->dev = &pdev->dev;
+ INIT_DELAYED_WORK(&info->hpdet_work, arizona_hpdet_work);
platform_set_drvdata(pdev, info);
switch (arizona->type) {
@@ -1173,6 +1190,7 @@ static int arizona_extcon_remove(struct platform_device *pdev)
arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
arizona_free_irq(arizona, jack_irq_rise, info);
arizona_free_irq(arizona, jack_irq_fall, info);
+ cancel_delayed_work_sync(&info->hpdet_work);
regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
ARIZONA_JD1_ENA, 0);
arizona_clk32k_disable(arizona);