aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/extcon
diff options
context:
space:
mode:
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