aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/extcon/extcon-arizona.c
diff options
context:
space:
mode:
authorCharles Keepax <ckeepax@opensource.wolfsonmicro.com>2015-09-16 05:42:16 -0400
committerChanwoo Choi <cw00.choi@samsung.com>2015-09-22 02:27:57 -0400
commitdf8b6771bdd4004c743ad8ffff6fb7059d6687d1 (patch)
tree64c3980f2840abe09b2a452992130944716ed0e3 /drivers/extcon/extcon-arizona.c
parentb8ba9edb911102b452c815879f520bfe2713fab6 (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.c64
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
120static const int arizona_micd_levels[] = { 127static 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
128static const unsigned int arizona_cable[] = { 135static 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
934handled: 978handled:
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;