diff options
author | 2016-04-11 10:41:07 +0300 | |
---|---|---|
committer | 2016-04-13 08:17:18 +0300 | |
commit | e09b41010ba33a20a87472ee821fa407a5b8da36 (patch) | |
tree | d10dc367189862e7ca5c592f033dc3726e1df4e3 /kernel/drivers/extcon/extcon-arizona.c | |
parent | f93b97fd65072de626c074dbe099a1fff05ce060 (diff) |
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
are taken from kernel.org, and rt patch from the rt wiki download page.
During the rebasing, the following patch collided:
Force tick interrupt and get rid of softirq magic(I70131fb85).
Collisions have been removed because its logic was found on the
source already.
Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769
Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'kernel/drivers/extcon/extcon-arizona.c')
-rw-r--r-- | kernel/drivers/extcon/extcon-arizona.c | 321 |
1 files changed, 242 insertions, 79 deletions
diff --git a/kernel/drivers/extcon/extcon-arizona.c b/kernel/drivers/extcon/extcon-arizona.c index a0ed35b33..e4890dd4f 100644 --- a/kernel/drivers/extcon/extcon-arizona.c +++ b/kernel/drivers/extcon/extcon-arizona.c @@ -1,7 +1,7 @@ /* * extcon-arizona.c - Extcon driver Wolfson Arizona devices * - * Copyright (C) 2012 Wolfson Microelectronics plc + * Copyright (C) 2012-2014 Wolfson Microelectronics plc * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,10 +20,12 @@ #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/err.h> +#include <linux/gpio/consumer.h> #include <linux/gpio.h> #include <linux/input.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> +#include <linux/property.h> #include <linux/regulator/consumer.h> #include <linux/extcon.h> @@ -32,23 +34,30 @@ #include <linux/mfd/arizona/core.h> #include <linux/mfd/arizona/pdata.h> #include <linux/mfd/arizona/registers.h> +#include <dt-bindings/mfd/arizona.h> #define ARIZONA_MAX_MICD_RANGE 8 -#define ARIZONA_ACCDET_MODE_MIC 0 -#define ARIZONA_ACCDET_MODE_HPL 1 -#define ARIZONA_ACCDET_MODE_HPR 2 - #define ARIZONA_MICD_CLAMP_MODE_JDL 0x4 #define ARIZONA_MICD_CLAMP_MODE_JDH 0x5 #define ARIZONA_MICD_CLAMP_MODE_JDL_GP5H 0x9 #define ARIZONA_MICD_CLAMP_MODE_JDH_GP5H 0xb +#define ARIZONA_TST_CAP_DEFAULT 0x3 +#define ARIZONA_TST_CAP_CLAMP 0x1 + #define ARIZONA_HPDET_MAX 10000 #define HPDET_DEBOUNCE 500 #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_FOUR_READINGS 4 + #define MICD_LVL_1_TO_7 (ARIZONA_MICD_LVL_1 | ARIZONA_MICD_LVL_2 | \ ARIZONA_MICD_LVL_3 | ARIZONA_MICD_LVL_4 | \ ARIZONA_MICD_LVL_5 | ARIZONA_MICD_LVL_6 | \ @@ -94,9 +103,11 @@ struct arizona_extcon_info { bool detecting; int jack_flips; - int hpdet_ip; + int hpdet_ip_version; struct extcon_dev *edev; + + struct gpio_desc *micd_pol_gpio; }; static const struct arizona_micd_config micd_default_modes[] = { @@ -113,25 +124,23 @@ static const struct arizona_micd_range micd_default_ranges[] = { { .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[] = { 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, 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, - 1257, + 1257, 30000, }; -#define ARIZONA_CABLE_MECHANICAL 0 -#define ARIZONA_CABLE_MICROPHONE 1 -#define ARIZONA_CABLE_HEADPHONE 2 -#define ARIZONA_CABLE_LINEOUT 3 - -static const char *arizona_cable[] = { - "Mechanical", - "Microphone", - "Headphone", - "Line-out", - NULL, +static const unsigned int arizona_cable[] = { + EXTCON_MECHANICAL, + EXTCON_JACK_MICROPHONE, + EXTCON_JACK_HEADPHONE, + EXTCON_JACK_LINE_OUT, + EXTCON_NONE, }; static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info); @@ -141,16 +150,33 @@ static void arizona_extcon_hp_clamp(struct arizona_extcon_info *info, { struct arizona *arizona = info->arizona; unsigned int mask = 0, val = 0; + unsigned int cap_sel = 0; int ret; switch (arizona->type) { + case WM8998: + case WM1814: + mask = 0; + break; case WM5110: + case WM8280: mask = ARIZONA_HP1L_SHRTO | ARIZONA_HP1L_FLWR | ARIZONA_HP1L_SHRTI; - if (clamp) + if (clamp) { val = ARIZONA_HP1L_SHRTO; - else + cap_sel = ARIZONA_TST_CAP_CLAMP; + } else { val = ARIZONA_HP1L_FLWR | ARIZONA_HP1L_SHRTI; + cap_sel = ARIZONA_TST_CAP_DEFAULT; + } + + ret = regmap_update_bits(arizona->regmap, + ARIZONA_HP_TEST_CTRL_1, + ARIZONA_HP1_TST_CAP_SEL_MASK, + cap_sel); + if (ret != 0) + dev_warn(arizona->dev, + "Failed to set TST_CAP_SEL: %d\n", ret); break; default: mask = ARIZONA_RMV_SHRT_HP1L; @@ -175,17 +201,19 @@ static void arizona_extcon_hp_clamp(struct arizona_extcon_info *info, ret); } - ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1L, - mask, val); - if (ret != 0) - dev_warn(arizona->dev, "Failed to do clamp: %d\n", + if (mask) { + ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1L, + mask, val); + if (ret != 0) + dev_warn(arizona->dev, "Failed to do clamp: %d\n", ret); - ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1R, - mask, val); - if (ret != 0) - dev_warn(arizona->dev, "Failed to do clamp: %d\n", - ret); + ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1R, + mask, val); + if (ret != 0) + dev_warn(arizona->dev, "Failed to do clamp: %d\n", + ret); + } /* Restore the desired state while not doing the clamp */ if (!clamp) { @@ -211,6 +239,10 @@ static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode) if (arizona->pdata.micd_pol_gpio > 0) gpio_set_value_cansleep(arizona->pdata.micd_pol_gpio, info->micd_modes[mode].gpio); + else + gpiod_set_value_cansleep(info->micd_pol_gpio, + info->micd_modes[mode].gpio); + regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, ARIZONA_MICD_BIAS_SRC_MASK, info->micd_modes[mode].bias << @@ -266,6 +298,7 @@ static void arizona_start_mic(struct arizona_extcon_info *info) struct arizona *arizona = info->arizona; bool change; int ret; + unsigned int mode; /* Microphone detection can't use idle mode */ pm_runtime_get(info->dev); @@ -291,9 +324,14 @@ static void arizona_start_mic(struct arizona_extcon_info *info) 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, ARIZONA_ACCESSORY_DETECT_MODE_1, - ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC); + ARIZONA_ACCDET_MODE_MASK, mode); arizona_extcon_pulse_micbias(info); @@ -380,7 +418,7 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info) return ret; } - switch (info->hpdet_ip) { + switch (info->hpdet_ip_version) { case 0: if (!(val & ARIZONA_HP_DONE)) { dev_err(arizona->dev, "HPDET did not complete: %x\n", @@ -439,9 +477,6 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info) arizona_hpdet_b_ranges[range].factor_a); break; - default: - dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n", - info->hpdet_ip); case 2: if (!(val & ARIZONA_HP_DONE_B)) { dev_err(arizona->dev, "HPDET did not complete: %x\n", @@ -478,6 +513,12 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info) arizona_hpdet_c_ranges[range].min); val = arizona_hpdet_c_ranges[range].min; } + break; + + default: + dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n", + info->hpdet_ip_version); + return -EINVAL; } dev_dbg(arizona->dev, "HP impedance %d ohms\n", val); @@ -559,7 +600,7 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data) struct arizona_extcon_info *info = data; struct arizona *arizona = info->arizona; int id_gpio = arizona->pdata.hpdet_id_gpio; - int report = ARIZONA_CABLE_HEADPHONE; + unsigned int report = EXTCON_JACK_HEADPHONE; int ret, reading; bool mic = false; @@ -573,7 +614,7 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data) } /* If the cable was removed while measuring ignore the result */ - ret = extcon_get_cable_state_(info->edev, ARIZONA_CABLE_MECHANICAL); + ret = extcon_get_cable_state_(info->edev, EXTCON_MECHANICAL); if (ret < 0) { dev_err(arizona->dev, "Failed to check cable state: %d\n", ret); @@ -604,9 +645,9 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data) /* Report high impedence cables as line outputs */ if (reading >= 5000) - report = ARIZONA_CABLE_LINEOUT; + report = EXTCON_JACK_LINE_OUT; else - report = ARIZONA_CABLE_HEADPHONE; + report = EXTCON_JACK_HEADPHONE; ret = extcon_set_cable_state_(info->edev, report, true); if (ret != 0) @@ -670,9 +711,9 @@ static void arizona_identify_headphone(struct arizona_extcon_info *info) ret = regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1, ARIZONA_ACCDET_MODE_MASK, - ARIZONA_ACCDET_MODE_HPL); + arizona->pdata.hpdet_channel); if (ret != 0) { - dev_err(arizona->dev, "Failed to set HPDETL mode: %d\n", ret); + dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret); goto err; } @@ -691,8 +732,7 @@ err: ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC); /* Just report headphone */ - ret = extcon_set_cable_state_(info->edev, - ARIZONA_CABLE_HEADPHONE, true); + ret = extcon_set_cable_state_(info->edev, EXTCON_JACK_HEADPHONE, true); if (ret != 0) dev_err(arizona->dev, "Failed to report headphone: %d\n", ret); @@ -722,9 +762,9 @@ static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info) ARIZONA_ACCESSORY_DETECT_MODE_1, ARIZONA_ACCDET_SRC | ARIZONA_ACCDET_MODE_MASK, info->micd_modes[0].src | - ARIZONA_ACCDET_MODE_HPL); + arizona->pdata.hpdet_channel); if (ret != 0) { - dev_err(arizona->dev, "Failed to set HPDETL mode: %d\n", ret); + dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret); goto err; } @@ -749,8 +789,7 @@ err: ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC); /* Just report headphone */ - ret = extcon_set_cable_state_(info->edev, - ARIZONA_CABLE_HEADPHONE, true); + ret = extcon_set_cable_state_(info->edev, EXTCON_JACK_HEADPHONE, true); if (ret != 0) dev_err(arizona->dev, "Failed to report headphone: %d\n", ret); @@ -766,10 +805,11 @@ static void arizona_micd_timeout_work(struct work_struct *work) mutex_lock(&info->lock); dev_dbg(info->arizona->dev, "MICD timed out, reporting HP\n"); - arizona_identify_headphone(info); info->detecting = false; + arizona_identify_headphone(info); + arizona_stop_mic(info); mutex_unlock(&info->lock); @@ -789,7 +829,7 @@ static void arizona_micd_detect(struct work_struct *work) mutex_lock(&info->lock); /* If the cable was removed while measuring ignore the result */ - ret = extcon_get_cable_state_(info->edev, ARIZONA_CABLE_MECHANICAL); + ret = extcon_get_cable_state_(info->edev, EXTCON_MECHANICAL); if (ret < 0) { dev_err(arizona->dev, "Failed to check cable state: %d\n", ret); @@ -801,6 +841,37 @@ static void arizona_micd_detect(struct work_struct *work) 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++) { ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val); if (ret != 0) { @@ -829,17 +900,22 @@ static void arizona_micd_detect(struct work_struct *work) /* Due to jack detect this should never happen */ if (!(val & ARIZONA_MICD_STS)) { dev_warn(arizona->dev, "Detected open circuit\n"); + info->mic = false; + arizona_stop_mic(info); info->detecting = false; + arizona_identify_headphone(info); goto handled; } /* If we got a high impedence we should have a headset, report it. */ if (info->detecting && (val & ARIZONA_MICD_LVL_8)) { + info->mic = true; + info->detecting = false; + arizona_identify_headphone(info); ret = extcon_set_cable_state_(info->edev, - ARIZONA_CABLE_MICROPHONE, true); - + EXTCON_JACK_MICROPHONE, true); if (ret != 0) dev_err(arizona->dev, "Headset report failed: %d\n", ret); @@ -851,8 +927,6 @@ static void arizona_micd_detect(struct work_struct *work) ret); } - info->mic = true; - info->detecting = false; goto handled; } @@ -865,10 +939,11 @@ static void arizona_micd_detect(struct work_struct *work) if (info->detecting && (val & MICD_LVL_1_TO_7)) { if (info->jack_flips >= info->micd_num_modes * 10) { dev_dbg(arizona->dev, "Detected HP/line\n"); - arizona_identify_headphone(info); info->detecting = false; + arizona_identify_headphone(info); + arizona_stop_mic(info); } else { info->micd_mode++; @@ -925,10 +1000,17 @@ static void arizona_micd_detect(struct work_struct *work) } 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, &info->micd_timeout_work, msecs_to_jiffies(info->micd_timeout)); + } pm_runtime_mark_last_busy(info->dev); mutex_unlock(&info->lock); @@ -984,12 +1066,9 @@ static irqreturn_t arizona_jackdet(int irq, void *data) mutex_lock(&info->lock); - if (arizona->pdata.jd_gpio5) { + if (info->micd_clamp) { mask = ARIZONA_MICD_CLAMP_STS; - if (arizona->pdata.jd_invert) - present = ARIZONA_MICD_CLAMP_STS; - else - present = 0; + present = 0; } else { mask = ARIZONA_JD1_STS; if (arizona->pdata.jd_invert) @@ -1030,7 +1109,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data) if (info->last_jackdet == present) { dev_dbg(arizona->dev, "Detected jack\n"); ret = extcon_set_cable_state_(info->edev, - ARIZONA_CABLE_MECHANICAL, true); + EXTCON_MECHANICAL, true); if (ret != 0) dev_err(arizona->dev, "Mechanical report failed: %d\n", @@ -1048,9 +1127,11 @@ static irqreturn_t arizona_jackdet(int irq, void *data) msecs_to_jiffies(HPDET_DEBOUNCE)); } - regmap_update_bits(arizona->regmap, - ARIZONA_JACK_DETECT_DEBOUNCE, - ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB, 0); + if (info->micd_clamp || !arizona->pdata.jd_invert) + regmap_update_bits(arizona->regmap, + ARIZONA_JACK_DETECT_DEBOUNCE, + ARIZONA_MICD_CLAMP_DB | + ARIZONA_JD1_DB, 0); } else { dev_dbg(arizona->dev, "Detected jack removal\n"); @@ -1120,6 +1201,44 @@ static void arizona_micd_set_level(struct arizona *arizona, int index, regmap_update_bits(arizona->regmap, reg, mask, level); } +static int arizona_extcon_device_get_pdata(struct arizona *arizona) +{ + struct arizona_pdata *pdata = &arizona->pdata; + unsigned int val = ARIZONA_ACCDET_MODE_HPL; + + device_property_read_u32(arizona->dev, "wlf,hpdet-channel", &val); + switch (val) { + case ARIZONA_ACCDET_MODE_HPL: + case ARIZONA_ACCDET_MODE_HPR: + pdata->hpdet_channel = val; + break; + default: + dev_err(arizona->dev, + "Wrong wlf,hpdet-channel DT value %d\n", val); + pdata->hpdet_channel = ARIZONA_ACCDET_MODE_HPL; + } + + device_property_read_u32(arizona->dev, "wlf,micd-detect-debounce", + &pdata->micd_detect_debounce); + + device_property_read_u32(arizona->dev, "wlf,micd-bias-start-time", + &pdata->micd_bias_start_time); + + device_property_read_u32(arizona->dev, "wlf,micd-rate", + &pdata->micd_rate); + + device_property_read_u32(arizona->dev, "wlf,micd-dbtime", + &pdata->micd_dbtime); + + device_property_read_u32(arizona->dev, "wlf,micd-timeout", + &pdata->micd_timeout); + + pdata->micd_force_micbias = device_property_read_bool(arizona->dev, + "wlf,micd-force-micbias"); + + return 0; +} + static int arizona_extcon_probe(struct platform_device *pdev) { struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); @@ -1137,6 +1256,9 @@ static int arizona_extcon_probe(struct platform_device *pdev) if (!info) return -ENOMEM; + if (!dev_get_platdata(arizona->dev)) + arizona_extcon_device_get_pdata(arizona); + info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD"); if (IS_ERR(info->micvdd)) { ret = PTR_ERR(info->micvdd); @@ -1161,7 +1283,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) break; default: info->micd_clamp = true; - info->hpdet_ip = 1; + info->hpdet_ip_version = 1; break; } break; @@ -1172,10 +1294,15 @@ static int arizona_extcon_probe(struct platform_device *pdev) break; default: info->micd_clamp = true; - info->hpdet_ip = 2; + info->hpdet_ip_version = 2; break; } break; + case WM8998: + case WM1814: + info->micd_clamp = true; + info->hpdet_ip_version = 2; + break; default: break; } @@ -1185,7 +1312,6 @@ static int arizona_extcon_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to allocate extcon device\n"); return -ENOMEM; } - info->edev->name = "Headset Jack"; ret = devm_extcon_dev_register(&pdev->dev, info->edev); if (ret < 0) { @@ -1212,6 +1338,10 @@ static int arizona_extcon_probe(struct platform_device *pdev) info->micd_num_modes = ARRAY_SIZE(micd_default_modes); } + if (arizona->pdata.gpsw > 0) + regmap_update_bits(arizona->regmap, ARIZONA_GP_SWITCH_1, + ARIZONA_SW1_MODE_MASK, arizona->pdata.gpsw); + if (arizona->pdata.micd_pol_gpio > 0) { if (info->micd_modes[0].gpio) mode = GPIOF_OUT_INIT_HIGH; @@ -1227,6 +1357,27 @@ static int arizona_extcon_probe(struct platform_device *pdev) arizona->pdata.micd_pol_gpio, ret); goto err_register; } + } else { + if (info->micd_modes[0].gpio) + mode = GPIOD_OUT_HIGH; + else + mode = GPIOD_OUT_LOW; + + /* We can't use devm here because we need to do the get + * against the MFD device, as that is where the of_node + * will reside, but if we devm against that the GPIO + * will not be freed if the extcon driver is unloaded. + */ + info->micd_pol_gpio = gpiod_get_optional(arizona->dev, + "wlf,micd-pol", + GPIOD_OUT_LOW); + if (IS_ERR(info->micd_pol_gpio)) { + ret = PTR_ERR(info->micd_pol_gpio); + dev_err(arizona->dev, + "Failed to get microphone polarity GPIO: %d\n", + ret); + goto err_register; + } } if (arizona->pdata.hpdet_id_gpio > 0) { @@ -1237,7 +1388,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) if (ret != 0) { dev_err(arizona->dev, "Failed to request GPIO%d: %d\n", arizona->pdata.hpdet_id_gpio, ret); - goto err_register; + goto err_gpio; } } @@ -1253,13 +1404,22 @@ static int arizona_extcon_probe(struct platform_device *pdev) arizona->pdata.micd_rate << ARIZONA_MICD_RATE_SHIFT); - if (arizona->pdata.micd_dbtime) + switch (arizona->pdata.micd_dbtime) { + case MICD_DBTIME_FOUR_READINGS: regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, ARIZONA_MICD_DBTIME_MASK, - arizona->pdata.micd_dbtime - << ARIZONA_MICD_DBTIME_SHIFT); + ARIZONA_MICD_DBTIME); + break; + case MICD_DBTIME_TWO_READINGS: + regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, + ARIZONA_MICD_DBTIME_MASK, 0); + break; + default: + 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) { info->micd_ranges = pdata->micd_ranges; @@ -1281,7 +1441,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) dev_err(arizona->dev, "MICD ranges must be sorted\n"); ret = -EINVAL; - goto err_input; + goto err_gpio; } } } @@ -1292,15 +1452,15 @@ static int arizona_extcon_probe(struct platform_device *pdev) /* Set up all the buttons the user specified */ 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) break; - if (j == ARRAY_SIZE(arizona_micd_levels)) { + if (j == ARIZONA_NUM_MICD_BUTTON_LEVELS) { dev_err(arizona->dev, "Unsupported MICD level %d\n", info->micd_ranges[i].max); ret = -EINVAL; - goto err_input; + goto err_gpio; } dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n", @@ -1360,7 +1520,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) pm_runtime_idle(&pdev->dev); pm_runtime_get_sync(&pdev->dev); - if (arizona->pdata.jd_gpio5) { + if (info->micd_clamp) { jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE; jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL; } else { @@ -1373,7 +1533,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) if (ret != 0) { dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n", ret); - goto err_input; + goto err_gpio; } ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1); @@ -1444,7 +1604,8 @@ err_rise_wake: arizona_set_irq_wake(arizona, jack_irq_rise, 0); err_rise: arizona_free_irq(arizona, jack_irq_rise, info); -err_input: +err_gpio: + gpiod_put(info->micd_pol_gpio); err_register: pm_runtime_disable(&pdev->dev); return ret; @@ -1456,13 +1617,15 @@ static int arizona_extcon_remove(struct platform_device *pdev) struct arizona *arizona = info->arizona; int jack_irq_rise, jack_irq_fall; + gpiod_put(info->micd_pol_gpio); + pm_runtime_disable(&pdev->dev); regmap_update_bits(arizona->regmap, ARIZONA_MICD_CLAMP_CONTROL, ARIZONA_MICD_CLAMP_MODE_MASK, 0); - if (arizona->pdata.jd_gpio5) { + if (info->micd_clamp) { jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE; jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL; } else { |