diff options
author | Charles Keepax <ckeepax@opensource.wolfsonmicro.com> | 2015-09-16 05:42:16 -0400 |
---|---|---|
committer | Chanwoo Choi <cw00.choi@samsung.com> | 2015-09-22 02:27:57 -0400 |
commit | df8b6771bdd4004c743ad8ffff6fb7059d6687d1 (patch) | |
tree | 64c3980f2840abe09b2a452992130944716ed0e3 /drivers/extcon/extcon-arizona.c | |
parent | b8ba9edb911102b452c815879f520bfe2713fab6 (diff) |
extcon: arizona: Add support for new ADC value mic detect
Newer devices give users the option to make the 3/4 pole jack
determination using a software comparison rather than a hardware one.
This patch adds support for this functionality.
Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Acked-by: Chanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Diffstat (limited to 'drivers/extcon/extcon-arizona.c')
-rw-r--r-- | drivers/extcon/extcon-arizona.c | 64 |
1 files changed, 58 insertions, 6 deletions
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index 4b9f09cc38d8..f213e14ff93f 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c | |||
@@ -48,6 +48,10 @@ | |||
48 | #define HPDET_DEBOUNCE 500 | 48 | #define HPDET_DEBOUNCE 500 |
49 | #define DEFAULT_MICD_TIMEOUT 2000 | 49 | #define DEFAULT_MICD_TIMEOUT 2000 |
50 | 50 | ||
51 | #define QUICK_HEADPHONE_MAX_OHM 3 | ||
52 | #define MICROPHONE_MIN_OHM 1257 | ||
53 | #define MICROPHONE_MAX_OHM 30000 | ||
54 | |||
51 | #define MICD_DBTIME_TWO_READINGS 2 | 55 | #define MICD_DBTIME_TWO_READINGS 2 |
52 | #define MICD_DBTIME_FOUR_READINGS 4 | 56 | #define MICD_DBTIME_FOUR_READINGS 4 |
53 | 57 | ||
@@ -117,12 +121,15 @@ static const struct arizona_micd_range micd_default_ranges[] = { | |||
117 | { .max = 430, .key = BTN_5 }, | 121 | { .max = 430, .key = BTN_5 }, |
118 | }; | 122 | }; |
119 | 123 | ||
124 | /* The number of levels in arizona_micd_levels valid for button thresholds */ | ||
125 | #define ARIZONA_NUM_MICD_BUTTON_LEVELS 64 | ||
126 | |||
120 | static const int arizona_micd_levels[] = { | 127 | static const int arizona_micd_levels[] = { |
121 | 3, 6, 8, 11, 13, 16, 18, 21, 23, 26, 28, 31, 34, 36, 39, 41, 44, 46, | 128 | 3, 6, 8, 11, 13, 16, 18, 21, 23, 26, 28, 31, 34, 36, 39, 41, 44, 46, |
122 | 49, 52, 54, 57, 60, 62, 65, 67, 70, 73, 75, 78, 81, 83, 89, 94, 100, | 129 | 49, 52, 54, 57, 60, 62, 65, 67, 70, 73, 75, 78, 81, 83, 89, 94, 100, |
123 | 105, 111, 116, 122, 127, 139, 150, 161, 173, 186, 196, 209, 220, 245, | 130 | 105, 111, 116, 122, 127, 139, 150, 161, 173, 186, 196, 209, 220, 245, |
124 | 270, 295, 321, 348, 375, 402, 430, 489, 550, 614, 681, 752, 903, 1071, | 131 | 270, 295, 321, 348, 375, 402, 430, 489, 550, 614, 681, 752, 903, 1071, |
125 | 1257, | 132 | 1257, 30000, |
126 | }; | 133 | }; |
127 | 134 | ||
128 | static const unsigned int arizona_cable[] = { | 135 | static const unsigned int arizona_cable[] = { |
@@ -270,6 +277,7 @@ static void arizona_start_mic(struct arizona_extcon_info *info) | |||
270 | struct arizona *arizona = info->arizona; | 277 | struct arizona *arizona = info->arizona; |
271 | bool change; | 278 | bool change; |
272 | int ret; | 279 | int ret; |
280 | unsigned int mode; | ||
273 | 281 | ||
274 | /* Microphone detection can't use idle mode */ | 282 | /* Microphone detection can't use idle mode */ |
275 | pm_runtime_get(info->dev); | 283 | pm_runtime_get(info->dev); |
@@ -295,9 +303,14 @@ static void arizona_start_mic(struct arizona_extcon_info *info) | |||
295 | regmap_write(arizona->regmap, 0x80, 0x0); | 303 | regmap_write(arizona->regmap, 0x80, 0x0); |
296 | } | 304 | } |
297 | 305 | ||
306 | if (info->detecting && arizona->pdata.micd_software_compare) | ||
307 | mode = ARIZONA_ACCDET_MODE_ADC; | ||
308 | else | ||
309 | mode = ARIZONA_ACCDET_MODE_MIC; | ||
310 | |||
298 | regmap_update_bits(arizona->regmap, | 311 | regmap_update_bits(arizona->regmap, |
299 | ARIZONA_ACCESSORY_DETECT_MODE_1, | 312 | ARIZONA_ACCESSORY_DETECT_MODE_1, |
300 | ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC); | 313 | ARIZONA_ACCDET_MODE_MASK, mode); |
301 | 314 | ||
302 | arizona_extcon_pulse_micbias(info); | 315 | arizona_extcon_pulse_micbias(info); |
303 | 316 | ||
@@ -804,6 +817,37 @@ static void arizona_micd_detect(struct work_struct *work) | |||
804 | return; | 817 | return; |
805 | } | 818 | } |
806 | 819 | ||
820 | if (info->detecting && arizona->pdata.micd_software_compare) { | ||
821 | /* Must disable MICD before we read the ADCVAL */ | ||
822 | regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, | ||
823 | ARIZONA_MICD_ENA, 0); | ||
824 | ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_4, &val); | ||
825 | if (ret != 0) { | ||
826 | dev_err(arizona->dev, | ||
827 | "Failed to read MICDET_ADCVAL: %d\n", | ||
828 | ret); | ||
829 | mutex_unlock(&info->lock); | ||
830 | return; | ||
831 | } | ||
832 | |||
833 | dev_dbg(arizona->dev, "MICDET_ADCVAL: %x\n", val); | ||
834 | |||
835 | val &= ARIZONA_MICDET_ADCVAL_MASK; | ||
836 | if (val < ARRAY_SIZE(arizona_micd_levels)) | ||
837 | val = arizona_micd_levels[val]; | ||
838 | else | ||
839 | val = INT_MAX; | ||
840 | |||
841 | if (val <= QUICK_HEADPHONE_MAX_OHM) | ||
842 | val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_0; | ||
843 | else if (val <= MICROPHONE_MIN_OHM) | ||
844 | val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_1; | ||
845 | else if (val <= MICROPHONE_MAX_OHM) | ||
846 | val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_8; | ||
847 | else | ||
848 | val = ARIZONA_MICD_LVL_8; | ||
849 | } | ||
850 | |||
807 | for (i = 0; i < 10 && !(val & MICD_LVL_0_TO_8); i++) { | 851 | for (i = 0; i < 10 && !(val & MICD_LVL_0_TO_8); i++) { |
808 | ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val); | 852 | ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val); |
809 | if (ret != 0) { | 853 | if (ret != 0) { |
@@ -932,10 +976,17 @@ static void arizona_micd_detect(struct work_struct *work) | |||
932 | } | 976 | } |
933 | 977 | ||
934 | handled: | 978 | handled: |
935 | if (info->detecting) | 979 | if (info->detecting) { |
980 | if (arizona->pdata.micd_software_compare) | ||
981 | regmap_update_bits(arizona->regmap, | ||
982 | ARIZONA_MIC_DETECT_1, | ||
983 | ARIZONA_MICD_ENA, | ||
984 | ARIZONA_MICD_ENA); | ||
985 | |||
936 | queue_delayed_work(system_power_efficient_wq, | 986 | queue_delayed_work(system_power_efficient_wq, |
937 | &info->micd_timeout_work, | 987 | &info->micd_timeout_work, |
938 | msecs_to_jiffies(info->micd_timeout)); | 988 | msecs_to_jiffies(info->micd_timeout)); |
989 | } | ||
939 | 990 | ||
940 | pm_runtime_mark_last_busy(info->dev); | 991 | pm_runtime_mark_last_busy(info->dev); |
941 | mutex_unlock(&info->lock); | 992 | mutex_unlock(&info->lock); |
@@ -1335,7 +1386,8 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
1335 | break; | 1386 | break; |
1336 | } | 1387 | } |
1337 | 1388 | ||
1338 | BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) != 0x40); | 1389 | BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) < |
1390 | ARIZONA_NUM_MICD_BUTTON_LEVELS); | ||
1339 | 1391 | ||
1340 | if (arizona->pdata.num_micd_ranges) { | 1392 | if (arizona->pdata.num_micd_ranges) { |
1341 | info->micd_ranges = pdata->micd_ranges; | 1393 | info->micd_ranges = pdata->micd_ranges; |
@@ -1368,11 +1420,11 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
1368 | 1420 | ||
1369 | /* Set up all the buttons the user specified */ | 1421 | /* Set up all the buttons the user specified */ |
1370 | for (i = 0; i < info->num_micd_ranges; i++) { | 1422 | for (i = 0; i < info->num_micd_ranges; i++) { |
1371 | for (j = 0; j < ARRAY_SIZE(arizona_micd_levels); j++) | 1423 | for (j = 0; j < ARIZONA_NUM_MICD_BUTTON_LEVELS; j++) |
1372 | if (arizona_micd_levels[j] >= info->micd_ranges[i].max) | 1424 | if (arizona_micd_levels[j] >= info->micd_ranges[i].max) |
1373 | break; | 1425 | break; |
1374 | 1426 | ||
1375 | if (j == ARRAY_SIZE(arizona_micd_levels)) { | 1427 | if (j == ARIZONA_NUM_MICD_BUTTON_LEVELS) { |
1376 | dev_err(arizona->dev, "Unsupported MICD level %d\n", | 1428 | dev_err(arizona->dev, "Unsupported MICD level %d\n", |
1377 | info->micd_ranges[i].max); | 1429 | info->micd_ranges[i].max); |
1378 | ret = -EINVAL; | 1430 | ret = -EINVAL; |