diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-04-01 14:09:45 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-04-02 06:54:00 -0400 |
commit | 9dd5e53d9d2f933039eb2d5e4052afa249f638ba (patch) | |
tree | 68c984efef69cce9f1e8f70097b01ff357a5f690 | |
parent | 2643fd641af28603ccd42244011a5ebc66016f8f (diff) |
extcon: arizona: Retry HPDET identification for high impedance
Sometimes we can trigger measurements early if contacts are shorted during
a slow insertion. As well as debouncing add further robustness by retrying
if we get a high impedance measurement for headphones as this can indicate
that the headphones were not yet connected.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r-- | drivers/extcon/extcon-arizona.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index 5344f435f689..c18cf14067c6 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 ARIZONA_HPDET_MAX 10000 | ||
43 | |||
42 | #define HPDET_DEBOUNCE 500 | 44 | #define HPDET_DEBOUNCE 500 |
43 | 45 | ||
44 | struct arizona_extcon_info { | 46 | struct arizona_extcon_info { |
@@ -64,6 +66,7 @@ struct arizona_extcon_info { | |||
64 | 66 | ||
65 | bool hpdet_active; | 67 | bool hpdet_active; |
66 | bool hpdet_done; | 68 | bool hpdet_done; |
69 | bool hpdet_retried; | ||
67 | 70 | ||
68 | int num_hpdet_res; | 71 | int num_hpdet_res; |
69 | unsigned int hpdet_res[3]; | 72 | unsigned int hpdet_res[3]; |
@@ -112,6 +115,8 @@ static const char *arizona_cable[] = { | |||
112 | NULL, | 115 | NULL, |
113 | }; | 116 | }; |
114 | 117 | ||
118 | static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info); | ||
119 | |||
115 | static void arizona_extcon_do_magic(struct arizona_extcon_info *info, | 120 | static void arizona_extcon_do_magic(struct arizona_extcon_info *info, |
116 | unsigned int magic) | 121 | unsigned int magic) |
117 | { | 122 | { |
@@ -393,7 +398,7 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info) | |||
393 | /* If we go out of range report top of range */ | 398 | /* If we go out of range report top of range */ |
394 | if (val < 100 || val > 0x3fb) { | 399 | if (val < 100 || val > 0x3fb) { |
395 | dev_dbg(arizona->dev, "Measurement out of range\n"); | 400 | dev_dbg(arizona->dev, "Measurement out of range\n"); |
396 | return 10000; | 401 | return ARIZONA_HPDET_MAX; |
397 | } | 402 | } |
398 | 403 | ||
399 | dev_dbg(arizona->dev, "HPDET read %d in range %d\n", | 404 | dev_dbg(arizona->dev, "HPDET read %d in range %d\n", |
@@ -518,6 +523,16 @@ static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading) | |||
518 | /* Take the headphone impedance for the main report */ | 523 | /* Take the headphone impedance for the main report */ |
519 | *reading = info->hpdet_res[0]; | 524 | *reading = info->hpdet_res[0]; |
520 | 525 | ||
526 | /* Sometimes we get false readings due to slow insert */ | ||
527 | if (*reading >= ARIZONA_HPDET_MAX && !info->hpdet_retried) { | ||
528 | dev_dbg(arizona->dev, "Retrying high impedance\n"); | ||
529 | info->num_hpdet_res = 0; | ||
530 | info->hpdet_retried = true; | ||
531 | arizona_start_hpdet_acc_id(info); | ||
532 | pm_runtime_put(info->dev); | ||
533 | return -EAGAIN; | ||
534 | } | ||
535 | |||
521 | /* | 536 | /* |
522 | * Either the two grounds measure differently or we | 537 | * Either the two grounds measure differently or we |
523 | * measure the mic as high impedance. | 538 | * measure the mic as high impedance. |
@@ -953,6 +968,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data) | |||
953 | info->hpdet_res[i] = 0; | 968 | info->hpdet_res[i] = 0; |
954 | info->mic = false; | 969 | info->mic = false; |
955 | info->hpdet_done = false; | 970 | info->hpdet_done = false; |
971 | info->hpdet_retried = false; | ||
956 | 972 | ||
957 | for (i = 0; i < info->num_micd_ranges; i++) | 973 | for (i = 0; i < info->num_micd_ranges; i++) |
958 | input_report_key(info->input, | 974 | input_report_key(info->input, |