Commit df8b6771 authored by Charles Keepax's avatar Charles Keepax Committed by Chanwoo Choi

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: default avatarCharles Keepax <ckeepax@opensource.wolfsonmicro.com>
Acked-by: default avatarChanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: default avatarChanwoo Choi <cw00.choi@samsung.com>
parent b8ba9edb
...@@ -48,6 +48,10 @@ ...@@ -48,6 +48,10 @@
#define HPDET_DEBOUNCE 500 #define HPDET_DEBOUNCE 500
#define DEFAULT_MICD_TIMEOUT 2000 #define DEFAULT_MICD_TIMEOUT 2000
#define QUICK_HEADPHONE_MAX_OHM 3
#define MICROPHONE_MIN_OHM 1257
#define MICROPHONE_MAX_OHM 30000
#define MICD_DBTIME_TWO_READINGS 2 #define MICD_DBTIME_TWO_READINGS 2
#define MICD_DBTIME_FOUR_READINGS 4 #define MICD_DBTIME_FOUR_READINGS 4
...@@ -117,12 +121,15 @@ static const struct arizona_micd_range micd_default_ranges[] = { ...@@ -117,12 +121,15 @@ static const struct arizona_micd_range micd_default_ranges[] = {
{ .max = 430, .key = BTN_5 }, { .max = 430, .key = BTN_5 },
}; };
/* The number of levels in arizona_micd_levels valid for button thresholds */
#define ARIZONA_NUM_MICD_BUTTON_LEVELS 64
static const int arizona_micd_levels[] = { static const int arizona_micd_levels[] = {
3, 6, 8, 11, 13, 16, 18, 21, 23, 26, 28, 31, 34, 36, 39, 41, 44, 46, 3, 6, 8, 11, 13, 16, 18, 21, 23, 26, 28, 31, 34, 36, 39, 41, 44, 46,
49, 52, 54, 57, 60, 62, 65, 67, 70, 73, 75, 78, 81, 83, 89, 94, 100, 49, 52, 54, 57, 60, 62, 65, 67, 70, 73, 75, 78, 81, 83, 89, 94, 100,
105, 111, 116, 122, 127, 139, 150, 161, 173, 186, 196, 209, 220, 245, 105, 111, 116, 122, 127, 139, 150, 161, 173, 186, 196, 209, 220, 245,
270, 295, 321, 348, 375, 402, 430, 489, 550, 614, 681, 752, 903, 1071, 270, 295, 321, 348, 375, 402, 430, 489, 550, 614, 681, 752, 903, 1071,
1257, 1257, 30000,
}; };
static const unsigned int arizona_cable[] = { static const unsigned int arizona_cable[] = {
...@@ -270,6 +277,7 @@ static void arizona_start_mic(struct arizona_extcon_info *info) ...@@ -270,6 +277,7 @@ static void arizona_start_mic(struct arizona_extcon_info *info)
struct arizona *arizona = info->arizona; struct arizona *arizona = info->arizona;
bool change; bool change;
int ret; int ret;
unsigned int mode;
/* Microphone detection can't use idle mode */ /* Microphone detection can't use idle mode */
pm_runtime_get(info->dev); pm_runtime_get(info->dev);
...@@ -295,9 +303,14 @@ static void arizona_start_mic(struct arizona_extcon_info *info) ...@@ -295,9 +303,14 @@ static void arizona_start_mic(struct arizona_extcon_info *info)
regmap_write(arizona->regmap, 0x80, 0x0); regmap_write(arizona->regmap, 0x80, 0x0);
} }
if (info->detecting && arizona->pdata.micd_software_compare)
mode = ARIZONA_ACCDET_MODE_ADC;
else
mode = ARIZONA_ACCDET_MODE_MIC;
regmap_update_bits(arizona->regmap, regmap_update_bits(arizona->regmap,
ARIZONA_ACCESSORY_DETECT_MODE_1, ARIZONA_ACCESSORY_DETECT_MODE_1,
ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC); ARIZONA_ACCDET_MODE_MASK, mode);
arizona_extcon_pulse_micbias(info); arizona_extcon_pulse_micbias(info);
...@@ -804,6 +817,37 @@ static void arizona_micd_detect(struct work_struct *work) ...@@ -804,6 +817,37 @@ static void arizona_micd_detect(struct work_struct *work)
return; return;
} }
if (info->detecting && arizona->pdata.micd_software_compare) {
/* Must disable MICD before we read the ADCVAL */
regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
ARIZONA_MICD_ENA, 0);
ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_4, &val);
if (ret != 0) {
dev_err(arizona->dev,
"Failed to read MICDET_ADCVAL: %d\n",
ret);
mutex_unlock(&info->lock);
return;
}
dev_dbg(arizona->dev, "MICDET_ADCVAL: %x\n", val);
val &= ARIZONA_MICDET_ADCVAL_MASK;
if (val < ARRAY_SIZE(arizona_micd_levels))
val = arizona_micd_levels[val];
else
val = INT_MAX;
if (val <= QUICK_HEADPHONE_MAX_OHM)
val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_0;
else if (val <= MICROPHONE_MIN_OHM)
val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_1;
else if (val <= MICROPHONE_MAX_OHM)
val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_8;
else
val = ARIZONA_MICD_LVL_8;
}
for (i = 0; i < 10 && !(val & MICD_LVL_0_TO_8); i++) { for (i = 0; i < 10 && !(val & MICD_LVL_0_TO_8); i++) {
ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val); ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
if (ret != 0) { if (ret != 0) {
...@@ -932,10 +976,17 @@ static void arizona_micd_detect(struct work_struct *work) ...@@ -932,10 +976,17 @@ static void arizona_micd_detect(struct work_struct *work)
} }
handled: handled:
if (info->detecting) if (info->detecting) {
if (arizona->pdata.micd_software_compare)
regmap_update_bits(arizona->regmap,
ARIZONA_MIC_DETECT_1,
ARIZONA_MICD_ENA,
ARIZONA_MICD_ENA);
queue_delayed_work(system_power_efficient_wq, queue_delayed_work(system_power_efficient_wq,
&info->micd_timeout_work, &info->micd_timeout_work,
msecs_to_jiffies(info->micd_timeout)); msecs_to_jiffies(info->micd_timeout));
}
pm_runtime_mark_last_busy(info->dev); pm_runtime_mark_last_busy(info->dev);
mutex_unlock(&info->lock); mutex_unlock(&info->lock);
...@@ -1335,7 +1386,8 @@ static int arizona_extcon_probe(struct platform_device *pdev) ...@@ -1335,7 +1386,8 @@ static int arizona_extcon_probe(struct platform_device *pdev)
break; break;
} }
BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) != 0x40); BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) <
ARIZONA_NUM_MICD_BUTTON_LEVELS);
if (arizona->pdata.num_micd_ranges) { if (arizona->pdata.num_micd_ranges) {
info->micd_ranges = pdata->micd_ranges; info->micd_ranges = pdata->micd_ranges;
...@@ -1368,11 +1420,11 @@ static int arizona_extcon_probe(struct platform_device *pdev) ...@@ -1368,11 +1420,11 @@ static int arizona_extcon_probe(struct platform_device *pdev)
/* Set up all the buttons the user specified */ /* Set up all the buttons the user specified */
for (i = 0; i < info->num_micd_ranges; i++) { for (i = 0; i < info->num_micd_ranges; i++) {
for (j = 0; j < ARRAY_SIZE(arizona_micd_levels); j++) for (j = 0; j < ARIZONA_NUM_MICD_BUTTON_LEVELS; j++)
if (arizona_micd_levels[j] >= info->micd_ranges[i].max) if (arizona_micd_levels[j] >= info->micd_ranges[i].max)
break; break;
if (j == ARRAY_SIZE(arizona_micd_levels)) { if (j == ARIZONA_NUM_MICD_BUTTON_LEVELS) {
dev_err(arizona->dev, "Unsupported MICD level %d\n", dev_err(arizona->dev, "Unsupported MICD level %d\n",
info->micd_ranges[i].max); info->micd_ranges[i].max);
ret = -EINVAL; ret = -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment