aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/extcon
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2013-04-01 14:05:27 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-04-02 06:53:56 -0400
commita3e2078d6a14bc67e733f7dbd32d1bc4051c9d90 (patch)
tree0a6bc938ed9080b82d0f2d66a7b0243b7fc6663a /drivers/extcon
parent82e2e0fd3fcf2aec9d5796e31d7f29c738331f6b (diff)
extcon: arizona: Suppress duplicate JACKDET reports
In cases where we see a brief (dis)connection of the jack detection signals we may see a noop jack insertion or removal where the jack has returned to the original state by the time the interrupt is serviced. Suppress these events in order to save work and avoid confusing the rest of the code. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/extcon')
-rw-r--r--drivers/extcon/extcon-arizona.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index 2f0bd4938fcc..9e4bffe610b6 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -39,6 +39,8 @@
39#define ARIZONA_ACCDET_MODE_HPL 1 39#define ARIZONA_ACCDET_MODE_HPL 1
40#define ARIZONA_ACCDET_MODE_HPR 2 40#define ARIZONA_ACCDET_MODE_HPR 2
41 41
42#define HPDET_DEBOUNCE 250
43
42struct arizona_extcon_info { 44struct arizona_extcon_info {
43 struct device *dev; 45 struct device *dev;
44 struct arizona *arizona; 46 struct arizona *arizona;
@@ -46,6 +48,8 @@ struct arizona_extcon_info {
46 struct regulator *micvdd; 48 struct regulator *micvdd;
47 struct input_dev *input; 49 struct input_dev *input;
48 50
51 u16 last_jackdet;
52
49 int micd_mode; 53 int micd_mode;
50 const struct arizona_micd_config *micd_modes; 54 const struct arizona_micd_config *micd_modes;
51 int micd_num_modes; 55 int micd_num_modes;
@@ -871,11 +875,12 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
871 struct arizona_extcon_info *info = data; 875 struct arizona_extcon_info *info = data;
872 struct arizona *arizona = info->arizona; 876 struct arizona *arizona = info->arizona;
873 unsigned int val, present, mask; 877 unsigned int val, present, mask;
878 bool cancelled;
874 int ret, i; 879 int ret, i;
875 880
876 pm_runtime_get_sync(info->dev); 881 cancelled = cancel_delayed_work_sync(&info->hpdet_work);
877 882
878 cancel_delayed_work_sync(&info->hpdet_work); 883 pm_runtime_get_sync(info->dev);
879 884
880 mutex_lock(&info->lock); 885 mutex_lock(&info->lock);
881 886
@@ -896,7 +901,18 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
896 return IRQ_NONE; 901 return IRQ_NONE;
897 } 902 }
898 903
899 if ((val & mask) == present) { 904 val &= mask;
905 if (val == info->last_jackdet) {
906 dev_dbg(arizona->dev, "Suppressing duplicate JACKDET\n");
907 if (cancelled)
908 schedule_delayed_work(&info->hpdet_work,
909 msecs_to_jiffies(HPDET_DEBOUNCE));
910
911 goto out;
912 }
913 info->last_jackdet = val;
914
915 if (info->last_jackdet == present) {
900 dev_dbg(arizona->dev, "Detected jack\n"); 916 dev_dbg(arizona->dev, "Detected jack\n");
901 ret = extcon_set_cable_state_(&info->edev, 917 ret = extcon_set_cable_state_(&info->edev,
902 ARIZONA_CABLE_MECHANICAL, true); 918 ARIZONA_CABLE_MECHANICAL, true);
@@ -913,7 +929,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
913 arizona_start_mic(info); 929 arizona_start_mic(info);
914 } else { 930 } else {
915 schedule_delayed_work(&info->hpdet_work, 931 schedule_delayed_work(&info->hpdet_work,
916 msecs_to_jiffies(250)); 932 msecs_to_jiffies(HPDET_DEBOUNCE));
917 } 933 }
918 934
919 regmap_update_bits(arizona->regmap, 935 regmap_update_bits(arizona->regmap,
@@ -953,6 +969,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
953 ARIZONA_JD1_FALL_TRIG_STS | 969 ARIZONA_JD1_FALL_TRIG_STS |
954 ARIZONA_JD1_RISE_TRIG_STS); 970 ARIZONA_JD1_RISE_TRIG_STS);
955 971
972out:
956 mutex_unlock(&info->lock); 973 mutex_unlock(&info->lock);
957 974
958 pm_runtime_mark_last_busy(info->dev); 975 pm_runtime_mark_last_busy(info->dev);
@@ -1012,6 +1029,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
1012 mutex_init(&info->lock); 1029 mutex_init(&info->lock);
1013 info->arizona = arizona; 1030 info->arizona = arizona;
1014 info->dev = &pdev->dev; 1031 info->dev = &pdev->dev;
1032 info->last_jackdet = ~(ARIZONA_MICD_CLAMP_STS | ARIZONA_JD1_STS);
1015 INIT_DELAYED_WORK(&info->hpdet_work, arizona_hpdet_work); 1033 INIT_DELAYED_WORK(&info->hpdet_work, arizona_hpdet_work);
1016 platform_set_drvdata(pdev, info); 1034 platform_set_drvdata(pdev, info);
1017 1035