1658 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * extcon-arizona.c - Extcon driver Wolfson Arizona devices4 *5 * Copyright (C) 2012-2014 Wolfson Microelectronics plc6 */7 8#include <linux/kernel.h>9#include <linux/module.h>10#include <linux/slab.h>11#include <linux/interrupt.h>12#include <linux/err.h>13#include <linux/gpio/consumer.h>14#include <linux/gpio.h>15#include <linux/input.h>16#include <linux/pm_runtime.h>17#include <linux/property.h>18#include <linux/regulator/consumer.h>19 20#include <sound/jack.h>21#include <sound/soc.h>22 23#include <linux/mfd/arizona/core.h>24#include <linux/mfd/arizona/pdata.h>25#include <linux/mfd/arizona/registers.h>26#include <dt-bindings/mfd/arizona.h>27 28#include "arizona.h"29 30#define ARIZONA_MAX_MICD_RANGE 831 32/*33 * The hardware supports 8 ranges / buttons, but the snd-jack interface34 * only supports 6 buttons (button 0-5).35 */36#define ARIZONA_MAX_MICD_BUTTONS 637 38#define ARIZONA_MICD_CLAMP_MODE_JDL 0x439#define ARIZONA_MICD_CLAMP_MODE_JDH 0x540#define ARIZONA_MICD_CLAMP_MODE_JDL_GP5H 0x941#define ARIZONA_MICD_CLAMP_MODE_JDH_GP5H 0xb42 43#define ARIZONA_TST_CAP_DEFAULT 0x344#define ARIZONA_TST_CAP_CLAMP 0x145 46#define ARIZONA_HPDET_MAX 1000047 48#define HPDET_DEBOUNCE 50049#define DEFAULT_MICD_TIMEOUT 200050 51#define ARIZONA_HPDET_WAIT_COUNT 1552#define ARIZONA_HPDET_WAIT_DELAY_MS 2053 54#define QUICK_HEADPHONE_MAX_OHM 355#define MICROPHONE_MIN_OHM 125756#define MICROPHONE_MAX_OHM 3000057 58#define MICD_DBTIME_TWO_READINGS 259#define MICD_DBTIME_FOUR_READINGS 460 61#define MICD_LVL_1_TO_7 (ARIZONA_MICD_LVL_1 | ARIZONA_MICD_LVL_2 | \62 ARIZONA_MICD_LVL_3 | ARIZONA_MICD_LVL_4 | \63 ARIZONA_MICD_LVL_5 | ARIZONA_MICD_LVL_6 | \64 ARIZONA_MICD_LVL_7)65 66#define MICD_LVL_0_TO_7 (ARIZONA_MICD_LVL_0 | MICD_LVL_1_TO_7)67 68#define MICD_LVL_0_TO_8 (MICD_LVL_0_TO_7 | ARIZONA_MICD_LVL_8)69 70static const struct arizona_micd_config micd_default_modes[] = {71 { ARIZONA_ACCDET_SRC, 1, 0 },72 { 0, 2, 1 },73};74 75static const struct arizona_micd_range micd_default_ranges[] = {76 { .max = 11, .key = BTN_0 },77 { .max = 28, .key = BTN_1 },78 { .max = 54, .key = BTN_2 },79 { .max = 100, .key = BTN_3 },80 { .max = 186, .key = BTN_4 },81 { .max = 430, .key = BTN_5 },82};83 84/* The number of levels in arizona_micd_levels valid for button thresholds */85#define ARIZONA_NUM_MICD_BUTTON_LEVELS 6486 87static const int arizona_micd_levels[] = {88 3, 6, 8, 11, 13, 16, 18, 21, 23, 26, 28, 31, 34, 36, 39, 41, 44, 46,89 49, 52, 54, 57, 60, 62, 65, 67, 70, 73, 75, 78, 81, 83, 89, 94, 100,90 105, 111, 116, 122, 127, 139, 150, 161, 173, 186, 196, 209, 220, 245,91 270, 295, 321, 348, 375, 402, 430, 489, 550, 614, 681, 752, 903, 1071,92 1257, 30000,93};94 95static void arizona_start_hpdet_acc_id(struct arizona_priv *info);96 97static void arizona_extcon_hp_clamp(struct arizona_priv *info,98 bool clamp)99{100 struct arizona *arizona = info->arizona;101 unsigned int mask = 0, val = 0;102 unsigned int cap_sel = 0;103 int ret;104 105 switch (arizona->type) {106 case WM8998:107 case WM1814:108 mask = 0;109 break;110 case WM5110:111 case WM8280:112 mask = ARIZONA_HP1L_SHRTO | ARIZONA_HP1L_FLWR |113 ARIZONA_HP1L_SHRTI;114 if (clamp) {115 val = ARIZONA_HP1L_SHRTO;116 cap_sel = ARIZONA_TST_CAP_CLAMP;117 } else {118 val = ARIZONA_HP1L_FLWR | ARIZONA_HP1L_SHRTI;119 cap_sel = ARIZONA_TST_CAP_DEFAULT;120 }121 122 ret = regmap_update_bits(arizona->regmap,123 ARIZONA_HP_TEST_CTRL_1,124 ARIZONA_HP1_TST_CAP_SEL_MASK,125 cap_sel);126 if (ret)127 dev_warn(arizona->dev, "Failed to set TST_CAP_SEL: %d\n", ret);128 break;129 default:130 mask = ARIZONA_RMV_SHRT_HP1L;131 if (clamp)132 val = ARIZONA_RMV_SHRT_HP1L;133 break;134 }135 136 snd_soc_dapm_mutex_lock(arizona->dapm);137 138 arizona->hpdet_clamp = clamp;139 140 /* Keep the HP output stages disabled while doing the clamp */141 if (clamp) {142 ret = regmap_update_bits(arizona->regmap,143 ARIZONA_OUTPUT_ENABLES_1,144 ARIZONA_OUT1L_ENA |145 ARIZONA_OUT1R_ENA, 0);146 if (ret)147 dev_warn(arizona->dev, "Failed to disable headphone outputs: %d\n", ret);148 }149 150 if (mask) {151 ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1L,152 mask, val);153 if (ret)154 dev_warn(arizona->dev, "Failed to do clamp: %d\n", ret);155 156 ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1R,157 mask, val);158 if (ret)159 dev_warn(arizona->dev, "Failed to do clamp: %d\n", ret);160 }161 162 /* Restore the desired state while not doing the clamp */163 if (!clamp) {164 ret = regmap_update_bits(arizona->regmap,165 ARIZONA_OUTPUT_ENABLES_1,166 ARIZONA_OUT1L_ENA |167 ARIZONA_OUT1R_ENA, arizona->hp_ena);168 if (ret)169 dev_warn(arizona->dev, "Failed to restore headphone outputs: %d\n", ret);170 }171 172 snd_soc_dapm_mutex_unlock(arizona->dapm);173}174 175static void arizona_extcon_set_mode(struct arizona_priv *info, int mode)176{177 struct arizona *arizona = info->arizona;178 179 mode %= info->micd_num_modes;180 181 gpiod_set_value_cansleep(info->micd_pol_gpio,182 info->micd_modes[mode].gpio);183 184 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,185 ARIZONA_MICD_BIAS_SRC_MASK,186 info->micd_modes[mode].bias <<187 ARIZONA_MICD_BIAS_SRC_SHIFT);188 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,189 ARIZONA_ACCDET_SRC, info->micd_modes[mode].src);190 191 info->micd_mode = mode;192 193 dev_dbg(arizona->dev, "Set jack polarity to %d\n", mode);194}195 196static const char *arizona_extcon_get_micbias(struct arizona_priv *info)197{198 switch (info->micd_modes[0].bias) {199 case 1:200 return "MICBIAS1";201 case 2:202 return "MICBIAS2";203 case 3:204 return "MICBIAS3";205 default:206 return "MICVDD";207 }208}209 210static void arizona_extcon_pulse_micbias(struct arizona_priv *info)211{212 struct arizona *arizona = info->arizona;213 const char *widget = arizona_extcon_get_micbias(info);214 struct snd_soc_dapm_context *dapm = arizona->dapm;215 struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);216 int ret;217 218 ret = snd_soc_component_force_enable_pin(component, widget);219 if (ret)220 dev_warn(arizona->dev, "Failed to enable %s: %d\n", widget, ret);221 222 snd_soc_dapm_sync(dapm);223 224 if (!arizona->pdata.micd_force_micbias) {225 ret = snd_soc_component_disable_pin(component, widget);226 if (ret)227 dev_warn(arizona->dev, "Failed to disable %s: %d\n", widget, ret);228 229 snd_soc_dapm_sync(dapm);230 }231}232 233static void arizona_start_mic(struct arizona_priv *info)234{235 struct arizona *arizona = info->arizona;236 bool change;237 int ret;238 unsigned int mode;239 240 /* Microphone detection can't use idle mode */241 pm_runtime_get_sync(arizona->dev);242 243 if (info->detecting) {244 ret = regulator_allow_bypass(info->micvdd, false);245 if (ret)246 dev_err(arizona->dev, "Failed to regulate MICVDD: %d\n", ret);247 }248 249 ret = regulator_enable(info->micvdd);250 if (ret)251 dev_err(arizona->dev, "Failed to enable MICVDD: %d\n", ret);252 253 if (info->micd_reva) {254 const struct reg_sequence reva[] = {255 { 0x80, 0x3 },256 { 0x294, 0x0 },257 { 0x80, 0x0 },258 };259 260 regmap_multi_reg_write(arizona->regmap, reva, ARRAY_SIZE(reva));261 }262 263 if (info->detecting && arizona->pdata.micd_software_compare)264 mode = ARIZONA_ACCDET_MODE_ADC;265 else266 mode = ARIZONA_ACCDET_MODE_MIC;267 268 regmap_update_bits(arizona->regmap,269 ARIZONA_ACCESSORY_DETECT_MODE_1,270 ARIZONA_ACCDET_MODE_MASK, mode);271 272 arizona_extcon_pulse_micbias(info);273 274 ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,275 ARIZONA_MICD_ENA, ARIZONA_MICD_ENA,276 &change);277 if (ret < 0) {278 dev_err(arizona->dev, "Failed to enable micd: %d\n", ret);279 } else if (!change) {280 regulator_disable(info->micvdd);281 pm_runtime_put_autosuspend(arizona->dev);282 }283}284 285static void arizona_stop_mic(struct arizona_priv *info)286{287 struct arizona *arizona = info->arizona;288 const char *widget = arizona_extcon_get_micbias(info);289 struct snd_soc_dapm_context *dapm = arizona->dapm;290 struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);291 bool change = false;292 int ret;293 294 ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,295 ARIZONA_MICD_ENA, 0,296 &change);297 if (ret < 0)298 dev_err(arizona->dev, "Failed to disable micd: %d\n", ret);299 300 ret = snd_soc_component_disable_pin(component, widget);301 if (ret)302 dev_warn(arizona->dev, "Failed to disable %s: %d\n", widget, ret);303 304 snd_soc_dapm_sync(dapm);305 306 if (info->micd_reva) {307 const struct reg_sequence reva[] = {308 { 0x80, 0x3 },309 { 0x294, 0x2 },310 { 0x80, 0x0 },311 };312 313 regmap_multi_reg_write(arizona->regmap, reva, ARRAY_SIZE(reva));314 }315 316 ret = regulator_allow_bypass(info->micvdd, true);317 if (ret)318 dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n", ret);319 320 if (change) {321 regulator_disable(info->micvdd);322 pm_runtime_mark_last_busy(arizona->dev);323 pm_runtime_put_autosuspend(arizona->dev);324 }325}326 327static struct {328 unsigned int threshold;329 unsigned int factor_a;330 unsigned int factor_b;331} arizona_hpdet_b_ranges[] = {332 { 100, 5528, 362464 },333 { 169, 11084, 6186851 },334 { 169, 11065, 65460395 },335};336 337#define ARIZONA_HPDET_B_RANGE_MAX 0x3fb338 339static struct {340 int min;341 int max;342} arizona_hpdet_c_ranges[] = {343 { 0, 30 },344 { 8, 100 },345 { 100, 1000 },346 { 1000, 10000 },347};348 349static int arizona_hpdet_read(struct arizona_priv *info)350{351 struct arizona *arizona = info->arizona;352 unsigned int val, range;353 int ret;354 355 ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2, &val);356 if (ret) {357 dev_err(arizona->dev, "Failed to read HPDET status: %d\n", ret);358 return ret;359 }360 361 switch (info->hpdet_ip_version) {362 case 0:363 if (!(val & ARIZONA_HP_DONE)) {364 dev_err(arizona->dev, "HPDET did not complete: %x\n", val);365 return -EAGAIN;366 }367 368 val &= ARIZONA_HP_LVL_MASK;369 break;370 371 case 1:372 if (!(val & ARIZONA_HP_DONE_B)) {373 dev_err(arizona->dev, "HPDET did not complete: %x\n", val);374 return -EAGAIN;375 }376 377 ret = regmap_read(arizona->regmap, ARIZONA_HP_DACVAL, &val);378 if (ret) {379 dev_err(arizona->dev, "Failed to read HP value: %d\n", ret);380 return -EAGAIN;381 }382 383 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,384 &range);385 range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)386 >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;387 388 if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 &&389 (val < arizona_hpdet_b_ranges[range].threshold ||390 val >= ARIZONA_HPDET_B_RANGE_MAX)) {391 range++;392 dev_dbg(arizona->dev, "Moving to HPDET range %d\n", range);393 regmap_update_bits(arizona->regmap,394 ARIZONA_HEADPHONE_DETECT_1,395 ARIZONA_HP_IMPEDANCE_RANGE_MASK,396 range <<397 ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);398 return -EAGAIN;399 }400 401 /* If we go out of range report top of range */402 if (val < arizona_hpdet_b_ranges[range].threshold ||403 val >= ARIZONA_HPDET_B_RANGE_MAX) {404 dev_dbg(arizona->dev, "Measurement out of range\n");405 return ARIZONA_HPDET_MAX;406 }407 408 dev_dbg(arizona->dev, "HPDET read %d in range %d\n", val, range);409 410 val = arizona_hpdet_b_ranges[range].factor_b411 / ((val * 100) -412 arizona_hpdet_b_ranges[range].factor_a);413 break;414 415 case 2:416 if (!(val & ARIZONA_HP_DONE_B)) {417 dev_err(arizona->dev, "HPDET did not complete: %x\n", val);418 return -EAGAIN;419 }420 421 val &= ARIZONA_HP_LVL_B_MASK;422 /* Convert to ohms, the value is in 0.5 ohm increments */423 val /= 2;424 425 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,426 &range);427 range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)428 >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;429 430 /* Skip up a range, or report? */431 if (range < ARRAY_SIZE(arizona_hpdet_c_ranges) - 1 &&432 (val >= arizona_hpdet_c_ranges[range].max)) {433 range++;434 dev_dbg(arizona->dev, "Moving to HPDET range %d-%d\n",435 arizona_hpdet_c_ranges[range].min,436 arizona_hpdet_c_ranges[range].max);437 regmap_update_bits(arizona->regmap,438 ARIZONA_HEADPHONE_DETECT_1,439 ARIZONA_HP_IMPEDANCE_RANGE_MASK,440 range <<441 ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);442 return -EAGAIN;443 }444 445 if (range && (val < arizona_hpdet_c_ranges[range].min)) {446 dev_dbg(arizona->dev, "Reporting range boundary %d\n",447 arizona_hpdet_c_ranges[range].min);448 val = arizona_hpdet_c_ranges[range].min;449 }450 break;451 452 default:453 dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n", info->hpdet_ip_version);454 return -EINVAL;455 }456 457 dev_dbg(arizona->dev, "HP impedance %d ohms\n", val);458 return val;459}460 461static int arizona_hpdet_do_id(struct arizona_priv *info, int *reading,462 bool *mic)463{464 struct arizona *arizona = info->arizona;465 int id_gpio = arizona->pdata.hpdet_id_gpio;466 467 if (!arizona->pdata.hpdet_acc_id)468 return 0;469 470 /*471 * If we're using HPDET for accessory identification we need472 * to take multiple measurements, step through them in sequence.473 */474 info->hpdet_res[info->num_hpdet_res++] = *reading;475 476 /* Only check the mic directly if we didn't already ID it */477 if (id_gpio && info->num_hpdet_res == 1) {478 dev_dbg(arizona->dev, "Measuring mic\n");479 480 regmap_update_bits(arizona->regmap,481 ARIZONA_ACCESSORY_DETECT_MODE_1,482 ARIZONA_ACCDET_MODE_MASK |483 ARIZONA_ACCDET_SRC,484 ARIZONA_ACCDET_MODE_HPR |485 info->micd_modes[0].src);486 487 gpio_set_value_cansleep(id_gpio, 1);488 489 regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,490 ARIZONA_HP_POLL, ARIZONA_HP_POLL);491 return -EAGAIN;492 }493 494 /* OK, got both. Now, compare... */495 dev_dbg(arizona->dev, "HPDET measured %d %d\n",496 info->hpdet_res[0], info->hpdet_res[1]);497 498 /* Take the headphone impedance for the main report */499 *reading = info->hpdet_res[0];500 501 /* Sometimes we get false readings due to slow insert */502 if (*reading >= ARIZONA_HPDET_MAX && !info->hpdet_retried) {503 dev_dbg(arizona->dev, "Retrying high impedance\n");504 info->num_hpdet_res = 0;505 info->hpdet_retried = true;506 arizona_start_hpdet_acc_id(info);507 pm_runtime_put(arizona->dev);508 return -EAGAIN;509 }510 511 /*512 * If we measure the mic as high impedance513 */514 if (!id_gpio || info->hpdet_res[1] > 50) {515 dev_dbg(arizona->dev, "Detected mic\n");516 *mic = true;517 info->detecting = true;518 } else {519 dev_dbg(arizona->dev, "Detected headphone\n");520 }521 522 /* Make sure everything is reset back to the real polarity */523 regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,524 ARIZONA_ACCDET_SRC, info->micd_modes[0].src);525 526 return 0;527}528 529static irqreturn_t arizona_hpdet_irq(int irq, void *data)530{531 struct arizona_priv *info = data;532 struct arizona *arizona = info->arizona;533 int id_gpio = arizona->pdata.hpdet_id_gpio;534 int ret, reading, state, report;535 bool mic = false;536 537 mutex_lock(&info->lock);538 539 /* If we got a spurious IRQ for some reason then ignore it */540 if (!info->hpdet_active) {541 dev_warn(arizona->dev, "Spurious HPDET IRQ\n");542 mutex_unlock(&info->lock);543 return IRQ_NONE;544 }545 546 /* If the cable was removed while measuring ignore the result */547 state = info->jack->status & SND_JACK_MECHANICAL;548 if (!state) {549 dev_dbg(arizona->dev, "Ignoring HPDET for removed cable\n");550 goto done;551 }552 553 ret = arizona_hpdet_read(info);554 if (ret == -EAGAIN)555 goto out;556 else if (ret < 0)557 goto done;558 reading = ret;559 560 /* Reset back to starting range */561 regmap_update_bits(arizona->regmap,562 ARIZONA_HEADPHONE_DETECT_1,563 ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,564 0);565 566 ret = arizona_hpdet_do_id(info, &reading, &mic);567 if (ret == -EAGAIN)568 goto out;569 else if (ret < 0)570 goto done;571 572 /* Report high impedence cables as line outputs */573 if (reading >= 5000)574 report = SND_JACK_LINEOUT;575 else576 report = SND_JACK_HEADPHONE;577 578 snd_soc_jack_report(info->jack, report, SND_JACK_LINEOUT | SND_JACK_HEADPHONE);579 580done:581 /* Reset back to starting range */582 regmap_update_bits(arizona->regmap,583 ARIZONA_HEADPHONE_DETECT_1,584 ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,585 0);586 587 arizona_extcon_hp_clamp(info, false);588 589 if (id_gpio)590 gpio_set_value_cansleep(id_gpio, 0);591 592 /* If we have a mic then reenable MICDET */593 if (state && (mic || info->mic))594 arizona_start_mic(info);595 596 if (info->hpdet_active) {597 pm_runtime_put_autosuspend(arizona->dev);598 info->hpdet_active = false;599 }600 601 /* Do not set hp_det done when the cable has been unplugged */602 if (state)603 info->hpdet_done = true;604 605out:606 mutex_unlock(&info->lock);607 608 return IRQ_HANDLED;609}610 611static void arizona_identify_headphone(struct arizona_priv *info)612{613 struct arizona *arizona = info->arizona;614 int ret;615 616 if (info->hpdet_done)617 return;618 619 dev_dbg(arizona->dev, "Starting HPDET\n");620 621 /* Make sure we keep the device enabled during the measurement */622 pm_runtime_get_sync(arizona->dev);623 624 info->hpdet_active = true;625 626 arizona_stop_mic(info);627 628 arizona_extcon_hp_clamp(info, true);629 630 ret = regmap_update_bits(arizona->regmap,631 ARIZONA_ACCESSORY_DETECT_MODE_1,632 ARIZONA_ACCDET_MODE_MASK,633 arizona->pdata.hpdet_channel);634 if (ret != 0) {635 dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret);636 goto err;637 }638 639 ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,640 ARIZONA_HP_POLL, ARIZONA_HP_POLL);641 if (ret) {642 dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n", ret);643 goto err;644 }645 646 return;647 648err:649 arizona_extcon_hp_clamp(info, false);650 pm_runtime_put_autosuspend(arizona->dev);651 652 /* Just report headphone */653 snd_soc_jack_report(info->jack, SND_JACK_HEADPHONE,654 SND_JACK_LINEOUT | SND_JACK_HEADPHONE);655 656 if (info->mic)657 arizona_start_mic(info);658 659 info->hpdet_active = false;660}661 662static void arizona_start_hpdet_acc_id(struct arizona_priv *info)663{664 struct arizona *arizona = info->arizona;665 int hp_reading = 32;666 bool mic;667 int ret;668 669 dev_dbg(arizona->dev, "Starting identification via HPDET\n");670 671 /* Make sure we keep the device enabled during the measurement */672 pm_runtime_get_sync(arizona->dev);673 674 info->hpdet_active = true;675 676 arizona_extcon_hp_clamp(info, true);677 678 ret = regmap_update_bits(arizona->regmap,679 ARIZONA_ACCESSORY_DETECT_MODE_1,680 ARIZONA_ACCDET_SRC | ARIZONA_ACCDET_MODE_MASK,681 info->micd_modes[0].src |682 arizona->pdata.hpdet_channel);683 if (ret != 0) {684 dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret);685 goto err;686 }687 688 if (arizona->pdata.hpdet_acc_id_line) {689 ret = regmap_update_bits(arizona->regmap,690 ARIZONA_HEADPHONE_DETECT_1,691 ARIZONA_HP_POLL, ARIZONA_HP_POLL);692 if (ret) {693 dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n", ret);694 goto err;695 }696 } else {697 arizona_hpdet_do_id(info, &hp_reading, &mic);698 }699 700 return;701 702err:703 /* Just report headphone */704 snd_soc_jack_report(info->jack, SND_JACK_HEADPHONE,705 SND_JACK_LINEOUT | SND_JACK_HEADPHONE);706 707 info->hpdet_active = false;708}709 710static void arizona_micd_timeout_work(struct work_struct *work)711{712 struct arizona_priv *info = container_of(work,713 struct arizona_priv,714 micd_timeout_work.work);715 716 mutex_lock(&info->lock);717 718 dev_dbg(info->arizona->dev, "MICD timed out, reporting HP\n");719 720 info->detecting = false;721 722 arizona_identify_headphone(info);723 724 mutex_unlock(&info->lock);725}726 727static int arizona_micd_adc_read(struct arizona_priv *info)728{729 struct arizona *arizona = info->arizona;730 unsigned int val;731 int ret;732 733 /* Must disable MICD before we read the ADCVAL */734 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,735 ARIZONA_MICD_ENA, 0);736 737 ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_4, &val);738 if (ret) {739 dev_err(arizona->dev, "Failed to read MICDET_ADCVAL: %d\n", ret);740 return ret;741 }742 743 dev_dbg(arizona->dev, "MICDET_ADCVAL: %x\n", val);744 745 val &= ARIZONA_MICDET_ADCVAL_MASK;746 if (val < ARRAY_SIZE(arizona_micd_levels))747 val = arizona_micd_levels[val];748 else749 val = INT_MAX;750 751 if (val <= QUICK_HEADPHONE_MAX_OHM)752 val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_0;753 else if (val <= MICROPHONE_MIN_OHM)754 val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_1;755 else if (val <= MICROPHONE_MAX_OHM)756 val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_8;757 else758 val = ARIZONA_MICD_LVL_8;759 760 return val;761}762 763static int arizona_micd_read(struct arizona_priv *info)764{765 struct arizona *arizona = info->arizona;766 unsigned int val = 0;767 int ret, i;768 769 for (i = 0; i < 10 && !(val & MICD_LVL_0_TO_8); i++) {770 ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);771 if (ret) {772 dev_err(arizona->dev, "Failed to read MICDET: %d\n", ret);773 return ret;774 }775 776 dev_dbg(arizona->dev, "MICDET: %x\n", val);777 778 if (!(val & ARIZONA_MICD_VALID)) {779 dev_warn(arizona->dev, "Microphone detection state invalid\n");780 return -EINVAL;781 }782 }783 784 if (i == 10 && !(val & MICD_LVL_0_TO_8)) {785 dev_err(arizona->dev, "Failed to get valid MICDET value\n");786 return -EINVAL;787 }788 789 return val;790}791 792static int arizona_micdet_reading(void *priv)793{794 struct arizona_priv *info = priv;795 struct arizona *arizona = info->arizona;796 int ret, val;797 798 if (info->detecting && arizona->pdata.micd_software_compare)799 ret = arizona_micd_adc_read(info);800 else801 ret = arizona_micd_read(info);802 if (ret < 0)803 return ret;804 805 val = ret;806 807 /* Due to jack detect this should never happen */808 if (!(val & ARIZONA_MICD_STS)) {809 dev_warn(arizona->dev, "Detected open circuit\n");810 info->mic = false;811 info->detecting = false;812 arizona_identify_headphone(info);813 return 0;814 }815 816 /* If we got a high impedence we should have a headset, report it. */817 if (val & ARIZONA_MICD_LVL_8) {818 info->mic = true;819 info->detecting = false;820 821 arizona_identify_headphone(info);822 823 snd_soc_jack_report(info->jack, SND_JACK_MICROPHONE, SND_JACK_MICROPHONE);824 825 /* Don't need to regulate for button detection */826 ret = regulator_allow_bypass(info->micvdd, true);827 if (ret)828 dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n", ret);829 830 return 0;831 }832 833 /* If we detected a lower impedence during initial startup834 * then we probably have the wrong polarity, flip it. Don't835 * do this for the lowest impedences to speed up detection of836 * plain headphones. If both polarities report a low837 * impedence then give up and report headphones.838 */839 if (val & MICD_LVL_1_TO_7) {840 if (info->jack_flips >= info->micd_num_modes * 10) {841 dev_dbg(arizona->dev, "Detected HP/line\n");842 843 info->detecting = false;844 845 arizona_identify_headphone(info);846 } else {847 info->micd_mode++;848 if (info->micd_mode == info->micd_num_modes)849 info->micd_mode = 0;850 arizona_extcon_set_mode(info, info->micd_mode);851 852 info->jack_flips++;853 854 if (arizona->pdata.micd_software_compare)855 regmap_update_bits(arizona->regmap,856 ARIZONA_MIC_DETECT_1,857 ARIZONA_MICD_ENA,858 ARIZONA_MICD_ENA);859 860 queue_delayed_work(system_power_efficient_wq,861 &info->micd_timeout_work,862 msecs_to_jiffies(arizona->pdata.micd_timeout));863 }864 865 return 0;866 }867 868 /*869 * If we're still detecting and we detect a short then we've870 * got a headphone.871 */872 dev_dbg(arizona->dev, "Headphone detected\n");873 info->detecting = false;874 875 arizona_identify_headphone(info);876 877 return 0;878}879 880static int arizona_button_reading(void *priv)881{882 struct arizona_priv *info = priv;883 struct arizona *arizona = info->arizona;884 int val, key, lvl;885 886 val = arizona_micd_read(info);887 if (val < 0)888 return val;889 890 /*891 * If we're still detecting and we detect a short then we've892 * got a headphone. Otherwise it's a button press.893 */894 if (val & MICD_LVL_0_TO_7) {895 if (info->mic) {896 dev_dbg(arizona->dev, "Mic button detected\n");897 898 lvl = val & ARIZONA_MICD_LVL_MASK;899 lvl >>= ARIZONA_MICD_LVL_SHIFT;900 901 if (lvl && ffs(lvl) - 1 < info->num_micd_ranges) {902 key = ffs(lvl) - 1;903 snd_soc_jack_report(info->jack,904 SND_JACK_BTN_0 >> key,905 info->micd_button_mask);906 } else {907 dev_err(arizona->dev, "Button out of range\n");908 }909 } else {910 dev_warn(arizona->dev, "Button with no mic: %x\n", val);911 }912 } else {913 dev_dbg(arizona->dev, "Mic button released\n");914 snd_soc_jack_report(info->jack, 0, info->micd_button_mask);915 arizona_extcon_pulse_micbias(info);916 }917 918 return 0;919}920 921static void arizona_micd_detect(struct work_struct *work)922{923 struct arizona_priv *info = container_of(work,924 struct arizona_priv,925 micd_detect_work.work);926 struct arizona *arizona = info->arizona;927 928 cancel_delayed_work_sync(&info->micd_timeout_work);929 930 mutex_lock(&info->lock);931 932 /* If the cable was removed while measuring ignore the result */933 if (!(info->jack->status & SND_JACK_MECHANICAL)) {934 dev_dbg(arizona->dev, "Ignoring MICDET for removed cable\n");935 mutex_unlock(&info->lock);936 return;937 }938 939 if (info->detecting)940 arizona_micdet_reading(info);941 else942 arizona_button_reading(info);943 944 pm_runtime_mark_last_busy(arizona->dev);945 mutex_unlock(&info->lock);946}947 948static irqreturn_t arizona_micdet(int irq, void *data)949{950 struct arizona_priv *info = data;951 struct arizona *arizona = info->arizona;952 int debounce = arizona->pdata.micd_detect_debounce;953 954 cancel_delayed_work_sync(&info->micd_detect_work);955 cancel_delayed_work_sync(&info->micd_timeout_work);956 957 mutex_lock(&info->lock);958 if (!info->detecting)959 debounce = 0;960 mutex_unlock(&info->lock);961 962 if (debounce)963 queue_delayed_work(system_power_efficient_wq,964 &info->micd_detect_work,965 msecs_to_jiffies(debounce));966 else967 arizona_micd_detect(&info->micd_detect_work.work);968 969 return IRQ_HANDLED;970}971 972static void arizona_hpdet_work(struct work_struct *work)973{974 struct arizona_priv *info = container_of(work,975 struct arizona_priv,976 hpdet_work.work);977 978 mutex_lock(&info->lock);979 arizona_start_hpdet_acc_id(info);980 mutex_unlock(&info->lock);981}982 983static int arizona_hpdet_wait(struct arizona_priv *info)984{985 struct arizona *arizona = info->arizona;986 unsigned int val;987 int i, ret;988 989 for (i = 0; i < ARIZONA_HPDET_WAIT_COUNT; i++) {990 ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2,991 &val);992 if (ret) {993 dev_err(arizona->dev, "Failed to read HPDET state: %d\n", ret);994 return ret;995 }996 997 switch (info->hpdet_ip_version) {998 case 0:999 if (val & ARIZONA_HP_DONE)1000 return 0;1001 break;1002 default:1003 if (val & ARIZONA_HP_DONE_B)1004 return 0;1005 break;1006 }1007 1008 msleep(ARIZONA_HPDET_WAIT_DELAY_MS);1009 }1010 1011 dev_warn(arizona->dev, "HPDET did not appear to complete\n");1012 1013 return -ETIMEDOUT;1014}1015 1016static irqreturn_t arizona_jackdet(int irq, void *data)1017{1018 struct arizona_priv *info = data;1019 struct arizona *arizona = info->arizona;1020 unsigned int val, present, mask;1021 bool cancelled_hp, cancelled_mic;1022 int ret, i;1023 1024 cancelled_hp = cancel_delayed_work_sync(&info->hpdet_work);1025 cancelled_mic = cancel_delayed_work_sync(&info->micd_timeout_work);1026 1027 pm_runtime_get_sync(arizona->dev);1028 1029 mutex_lock(&info->lock);1030 1031 if (info->micd_clamp) {1032 mask = ARIZONA_MICD_CLAMP_STS;1033 present = 0;1034 } else {1035 mask = ARIZONA_JD1_STS;1036 if (arizona->pdata.jd_invert)1037 present = 0;1038 else1039 present = ARIZONA_JD1_STS;1040 }1041 1042 ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val);1043 if (ret) {1044 dev_err(arizona->dev, "Failed to read jackdet status: %d\n", ret);1045 mutex_unlock(&info->lock);1046 pm_runtime_put_autosuspend(arizona->dev);1047 return IRQ_NONE;1048 }1049 1050 val &= mask;1051 if (val == info->last_jackdet) {1052 dev_dbg(arizona->dev, "Suppressing duplicate JACKDET\n");1053 if (cancelled_hp)1054 queue_delayed_work(system_power_efficient_wq,1055 &info->hpdet_work,1056 msecs_to_jiffies(HPDET_DEBOUNCE));1057 1058 if (cancelled_mic) {1059 int micd_timeout = arizona->pdata.micd_timeout;1060 1061 queue_delayed_work(system_power_efficient_wq,1062 &info->micd_timeout_work,1063 msecs_to_jiffies(micd_timeout));1064 }1065 1066 goto out;1067 }1068 info->last_jackdet = val;1069 1070 if (info->last_jackdet == present) {1071 dev_dbg(arizona->dev, "Detected jack\n");1072 snd_soc_jack_report(info->jack, SND_JACK_MECHANICAL, SND_JACK_MECHANICAL);1073 1074 info->detecting = true;1075 info->mic = false;1076 info->jack_flips = 0;1077 1078 if (!arizona->pdata.hpdet_acc_id) {1079 arizona_start_mic(info);1080 } else {1081 queue_delayed_work(system_power_efficient_wq,1082 &info->hpdet_work,1083 msecs_to_jiffies(HPDET_DEBOUNCE));1084 }1085 1086 if (info->micd_clamp || !arizona->pdata.jd_invert)1087 regmap_update_bits(arizona->regmap,1088 ARIZONA_JACK_DETECT_DEBOUNCE,1089 ARIZONA_MICD_CLAMP_DB |1090 ARIZONA_JD1_DB, 0);1091 } else {1092 dev_dbg(arizona->dev, "Detected jack removal\n");1093 1094 arizona_stop_mic(info);1095 1096 info->num_hpdet_res = 0;1097 for (i = 0; i < ARRAY_SIZE(info->hpdet_res); i++)1098 info->hpdet_res[i] = 0;1099 info->mic = false;1100 info->hpdet_done = false;1101 info->hpdet_retried = false;1102 1103 snd_soc_jack_report(info->jack, 0, ARIZONA_JACK_MASK | info->micd_button_mask);1104 1105 /*1106 * If the jack was removed during a headphone detection we1107 * need to wait for the headphone detection to finish, as1108 * it can not be aborted. We don't want to be able to start1109 * a new headphone detection from a fresh insert until this1110 * one is finished.1111 */1112 arizona_hpdet_wait(info);1113 1114 regmap_update_bits(arizona->regmap,1115 ARIZONA_JACK_DETECT_DEBOUNCE,1116 ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB,1117 ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB);1118 }1119 1120out:1121 /* Clear trig_sts to make sure DCVDD is not forced up */1122 regmap_write(arizona->regmap, ARIZONA_AOD_WKUP_AND_TRIG,1123 ARIZONA_MICD_CLAMP_FALL_TRIG_STS |1124 ARIZONA_MICD_CLAMP_RISE_TRIG_STS |1125 ARIZONA_JD1_FALL_TRIG_STS |1126 ARIZONA_JD1_RISE_TRIG_STS);1127 1128 mutex_unlock(&info->lock);1129 1130 pm_runtime_mark_last_busy(arizona->dev);1131 pm_runtime_put_autosuspend(arizona->dev);1132 1133 return IRQ_HANDLED;1134}1135 1136/* Map a level onto a slot in the register bank */1137static void arizona_micd_set_level(struct arizona *arizona, int index,1138 unsigned int level)1139{1140 int reg;1141 unsigned int mask;1142 1143 reg = ARIZONA_MIC_DETECT_LEVEL_4 - (index / 2);1144 1145 if (!(index % 2)) {1146 mask = 0x3f00;1147 level <<= 8;1148 } else {1149 mask = 0x3f;1150 }1151 1152 /* Program the level itself */1153 regmap_update_bits(arizona->regmap, reg, mask, level);1154}1155 1156static int arizona_extcon_get_micd_configs(struct device *dev,1157 struct arizona *arizona)1158{1159 const char * const prop = "wlf,micd-configs";1160 const int entries_per_config = 3;1161 struct arizona_micd_config *micd_configs;1162 int nconfs, ret;1163 int i, j;1164 u32 *vals;1165 1166 nconfs = device_property_count_u32(arizona->dev, prop);1167 if (nconfs <= 0)1168 return 0;1169 1170 vals = kcalloc(nconfs, sizeof(u32), GFP_KERNEL);1171 if (!vals)1172 return -ENOMEM;1173 1174 ret = device_property_read_u32_array(arizona->dev, prop, vals, nconfs);1175 if (ret < 0)1176 goto out;1177 1178 nconfs /= entries_per_config;1179 micd_configs = devm_kcalloc(dev, nconfs, sizeof(*micd_configs),1180 GFP_KERNEL);1181 if (!micd_configs) {1182 ret = -ENOMEM;1183 goto out;1184 }1185 1186 for (i = 0, j = 0; i < nconfs; ++i) {1187 micd_configs[i].src = vals[j++] ? ARIZONA_ACCDET_SRC : 0;1188 micd_configs[i].bias = vals[j++];1189 micd_configs[i].gpio = vals[j++];1190 }1191 1192 arizona->pdata.micd_configs = micd_configs;1193 arizona->pdata.num_micd_configs = nconfs;1194 1195out:1196 kfree(vals);1197 return ret;1198}1199 1200static int arizona_extcon_device_get_pdata(struct device *dev,1201 struct arizona *arizona)1202{1203 struct arizona_pdata *pdata = &arizona->pdata;1204 unsigned int val = ARIZONA_ACCDET_MODE_HPL;1205 int ret;1206 1207 device_property_read_u32(arizona->dev, "wlf,hpdet-channel", &val);1208 switch (val) {1209 case ARIZONA_ACCDET_MODE_HPL:1210 case ARIZONA_ACCDET_MODE_HPR:1211 pdata->hpdet_channel = val;1212 break;1213 default:1214 dev_err(arizona->dev, "Wrong wlf,hpdet-channel DT value %d\n", val);1215 pdata->hpdet_channel = ARIZONA_ACCDET_MODE_HPL;1216 }1217 1218 device_property_read_u32(arizona->dev, "wlf,micd-detect-debounce",1219 &pdata->micd_detect_debounce);1220 1221 device_property_read_u32(arizona->dev, "wlf,micd-bias-start-time",1222 &pdata->micd_bias_start_time);1223 1224 device_property_read_u32(arizona->dev, "wlf,micd-rate",1225 &pdata->micd_rate);1226 1227 device_property_read_u32(arizona->dev, "wlf,micd-dbtime",1228 &pdata->micd_dbtime);1229 1230 device_property_read_u32(arizona->dev, "wlf,micd-timeout-ms",1231 &pdata->micd_timeout);1232 1233 pdata->micd_force_micbias = device_property_read_bool(arizona->dev,1234 "wlf,micd-force-micbias");1235 1236 pdata->micd_software_compare = device_property_read_bool(arizona->dev,1237 "wlf,micd-software-compare");1238 1239 pdata->jd_invert = device_property_read_bool(arizona->dev,1240 "wlf,jd-invert");1241 1242 device_property_read_u32(arizona->dev, "wlf,gpsw", &pdata->gpsw);1243 1244 pdata->jd_gpio5 = device_property_read_bool(arizona->dev,1245 "wlf,use-jd2");1246 pdata->jd_gpio5_nopull = device_property_read_bool(arizona->dev,1247 "wlf,use-jd2-nopull");1248 1249 ret = arizona_extcon_get_micd_configs(dev, arizona);1250 if (ret < 0)1251 dev_err(arizona->dev, "Failed to read micd configs: %d\n", ret);1252 1253 return 0;1254}1255 1256int arizona_jack_codec_dev_probe(struct arizona_priv *info, struct device *dev)1257{1258 struct arizona *arizona = info->arizona;1259 struct arizona_pdata *pdata = &arizona->pdata;1260 int ret, mode;1261 1262 if (!dev_get_platdata(arizona->dev))1263 arizona_extcon_device_get_pdata(dev, arizona);1264 1265 info->micvdd = devm_regulator_get(dev, "MICVDD");1266 if (IS_ERR(info->micvdd))1267 return dev_err_probe(arizona->dev, PTR_ERR(info->micvdd), "getting MICVDD\n");1268 1269 mutex_init(&info->lock);1270 info->last_jackdet = ~(ARIZONA_MICD_CLAMP_STS | ARIZONA_JD1_STS);1271 INIT_DELAYED_WORK(&info->hpdet_work, arizona_hpdet_work);1272 INIT_DELAYED_WORK(&info->micd_detect_work, arizona_micd_detect);1273 INIT_DELAYED_WORK(&info->micd_timeout_work, arizona_micd_timeout_work);1274 1275 switch (arizona->type) {1276 case WM5102:1277 switch (arizona->rev) {1278 case 0:1279 info->micd_reva = true;1280 break;1281 default:1282 info->micd_clamp = true;1283 info->hpdet_ip_version = 1;1284 break;1285 }1286 break;1287 case WM5110:1288 case WM8280:1289 switch (arizona->rev) {1290 case 0 ... 2:1291 break;1292 default:1293 info->micd_clamp = true;1294 info->hpdet_ip_version = 2;1295 break;1296 }1297 break;1298 case WM8998:1299 case WM1814:1300 info->micd_clamp = true;1301 info->hpdet_ip_version = 2;1302 break;1303 default:1304 break;1305 }1306 1307 if (!pdata->micd_timeout)1308 pdata->micd_timeout = DEFAULT_MICD_TIMEOUT;1309 1310 if (pdata->num_micd_configs) {1311 info->micd_modes = pdata->micd_configs;1312 info->micd_num_modes = pdata->num_micd_configs;1313 } else {1314 info->micd_modes = micd_default_modes;1315 info->micd_num_modes = ARRAY_SIZE(micd_default_modes);1316 }1317 1318 if (arizona->pdata.gpsw > 0)1319 regmap_update_bits(arizona->regmap, ARIZONA_GP_SWITCH_1,1320 ARIZONA_SW1_MODE_MASK, arizona->pdata.gpsw);1321 1322 if (pdata->micd_pol_gpio > 0) {1323 if (info->micd_modes[0].gpio)1324 mode = GPIOF_OUT_INIT_HIGH;1325 else1326 mode = GPIOF_OUT_INIT_LOW;1327 1328 ret = devm_gpio_request_one(dev, pdata->micd_pol_gpio,1329 mode, "MICD polarity");1330 if (ret != 0) {1331 dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",1332 pdata->micd_pol_gpio, ret);1333 return ret;1334 }1335 1336 info->micd_pol_gpio = gpio_to_desc(pdata->micd_pol_gpio);1337 } else {1338 if (info->micd_modes[0].gpio)1339 mode = GPIOD_OUT_HIGH;1340 else1341 mode = GPIOD_OUT_LOW;1342 1343 /* We can't use devm here because we need to do the get1344 * against the MFD device, as that is where the of_node1345 * will reside, but if we devm against that the GPIO1346 * will not be freed if the extcon driver is unloaded.1347 */1348 info->micd_pol_gpio = gpiod_get_optional(arizona->dev,1349 "wlf,micd-pol",1350 mode);1351 if (IS_ERR(info->micd_pol_gpio)) {1352 ret = PTR_ERR(info->micd_pol_gpio);1353 dev_err_probe(arizona->dev, ret, "getting microphone polarity GPIO\n");1354 return ret;1355 }1356 }1357 1358 if (arizona->pdata.hpdet_id_gpio > 0) {1359 ret = devm_gpio_request_one(dev, arizona->pdata.hpdet_id_gpio,1360 GPIOF_OUT_INIT_LOW,1361 "HPDET");1362 if (ret != 0) {1363 dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",1364 arizona->pdata.hpdet_id_gpio, ret);1365 gpiod_put(info->micd_pol_gpio);1366 return ret;1367 }1368 }1369 1370 return 0;1371}1372EXPORT_SYMBOL_GPL(arizona_jack_codec_dev_probe);1373 1374int arizona_jack_codec_dev_remove(struct arizona_priv *info)1375{1376 gpiod_put(info->micd_pol_gpio);1377 return 0;1378}1379EXPORT_SYMBOL_GPL(arizona_jack_codec_dev_remove);1380 1381static int arizona_jack_enable_jack_detect(struct arizona_priv *info,1382 struct snd_soc_jack *jack)1383{1384 struct arizona *arizona = info->arizona;1385 struct arizona_pdata *pdata = &arizona->pdata;1386 unsigned int val;1387 unsigned int clamp_mode;1388 int jack_irq_fall, jack_irq_rise;1389 int ret, i, j;1390 1391 if (arizona->pdata.micd_bias_start_time)1392 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,1393 ARIZONA_MICD_BIAS_STARTTIME_MASK,1394 arizona->pdata.micd_bias_start_time1395 << ARIZONA_MICD_BIAS_STARTTIME_SHIFT);1396 1397 if (arizona->pdata.micd_rate)1398 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,1399 ARIZONA_MICD_RATE_MASK,1400 arizona->pdata.micd_rate1401 << ARIZONA_MICD_RATE_SHIFT);1402 1403 switch (arizona->pdata.micd_dbtime) {1404 case MICD_DBTIME_FOUR_READINGS:1405 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,1406 ARIZONA_MICD_DBTIME_MASK,1407 ARIZONA_MICD_DBTIME);1408 break;1409 case MICD_DBTIME_TWO_READINGS:1410 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,1411 ARIZONA_MICD_DBTIME_MASK, 0);1412 break;1413 default:1414 break;1415 }1416 1417 BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) <1418 ARIZONA_NUM_MICD_BUTTON_LEVELS);1419 1420 if (arizona->pdata.num_micd_ranges) {1421 info->micd_ranges = pdata->micd_ranges;1422 info->num_micd_ranges = pdata->num_micd_ranges;1423 } else {1424 info->micd_ranges = micd_default_ranges;1425 info->num_micd_ranges = ARRAY_SIZE(micd_default_ranges);1426 }1427 1428 if (arizona->pdata.num_micd_ranges > ARIZONA_MAX_MICD_BUTTONS) {1429 dev_err(arizona->dev, "Too many MICD ranges: %d > %d\n",1430 arizona->pdata.num_micd_ranges, ARIZONA_MAX_MICD_BUTTONS);1431 return -EINVAL;1432 }1433 1434 if (info->num_micd_ranges > 1) {1435 for (i = 1; i < info->num_micd_ranges; i++) {1436 if (info->micd_ranges[i - 1].max >1437 info->micd_ranges[i].max) {1438 dev_err(arizona->dev, "MICD ranges must be sorted\n");1439 return -EINVAL;1440 }1441 }1442 }1443 1444 /* Disable all buttons by default */1445 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,1446 ARIZONA_MICD_LVL_SEL_MASK, 0x81);1447 1448 /* Set up all the buttons the user specified */1449 for (i = 0; i < info->num_micd_ranges; i++) {1450 for (j = 0; j < ARIZONA_NUM_MICD_BUTTON_LEVELS; j++)1451 if (arizona_micd_levels[j] >= info->micd_ranges[i].max)1452 break;1453 1454 if (j == ARIZONA_NUM_MICD_BUTTON_LEVELS) {1455 dev_err(arizona->dev, "Unsupported MICD level %d\n",1456 info->micd_ranges[i].max);1457 return -EINVAL;1458 }1459 1460 dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n",1461 arizona_micd_levels[j], i);1462 1463 arizona_micd_set_level(arizona, i, j);1464 1465 /* SND_JACK_BTN_# masks start with the most significant bit */1466 info->micd_button_mask |= SND_JACK_BTN_0 >> i;1467 snd_jack_set_key(jack->jack, SND_JACK_BTN_0 >> i,1468 info->micd_ranges[i].key);1469 1470 /* Enable reporting of that range */1471 regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,1472 1 << i, 1 << i);1473 }1474 1475 /* Set all the remaining keys to a maximum */1476 for (; i < ARIZONA_MAX_MICD_RANGE; i++)1477 arizona_micd_set_level(arizona, i, 0x3f);1478 1479 /*1480 * If we have a clamp use it, activating in conjunction with1481 * GPIO5 if that is connected for jack detect operation.1482 */1483 if (info->micd_clamp) {1484 if (arizona->pdata.jd_gpio5) {1485 /* Put the GPIO into input mode with optional pull */1486 val = 0xc101;1487 if (arizona->pdata.jd_gpio5_nopull)1488 val &= ~ARIZONA_GPN_PU;1489 1490 regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL,1491 val);1492 1493 if (arizona->pdata.jd_invert)1494 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH_GP5H;1495 else1496 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL_GP5H;1497 } else {1498 if (arizona->pdata.jd_invert)1499 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH;1500 else1501 clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL;1502 }1503 1504 regmap_update_bits(arizona->regmap,1505 ARIZONA_MICD_CLAMP_CONTROL,1506 ARIZONA_MICD_CLAMP_MODE_MASK, clamp_mode);1507 1508 regmap_update_bits(arizona->regmap,1509 ARIZONA_JACK_DETECT_DEBOUNCE,1510 ARIZONA_MICD_CLAMP_DB,1511 ARIZONA_MICD_CLAMP_DB);1512 }1513 1514 arizona_extcon_set_mode(info, 0);1515 1516 info->jack = jack;1517 1518 pm_runtime_get_sync(arizona->dev);1519 1520 if (info->micd_clamp) {1521 jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;1522 jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;1523 } else {1524 jack_irq_rise = ARIZONA_IRQ_JD_RISE;1525 jack_irq_fall = ARIZONA_IRQ_JD_FALL;1526 }1527 1528 ret = arizona_request_irq(arizona, jack_irq_rise,1529 "JACKDET rise", arizona_jackdet, info);1530 if (ret != 0) {1531 dev_err(arizona->dev, "Failed to get JACKDET rise IRQ: %d\n", ret);1532 goto err_pm;1533 }1534 1535 ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1);1536 if (ret != 0) {1537 dev_err(arizona->dev, "Failed to set JD rise IRQ wake: %d\n", ret);1538 goto err_rise;1539 }1540 1541 ret = arizona_request_irq(arizona, jack_irq_fall,1542 "JACKDET fall", arizona_jackdet, info);1543 if (ret != 0) {1544 dev_err(arizona->dev, "Failed to get JD fall IRQ: %d\n", ret);1545 goto err_rise_wake;1546 }1547 1548 ret = arizona_set_irq_wake(arizona, jack_irq_fall, 1);1549 if (ret != 0) {1550 dev_err(arizona->dev, "Failed to set JD fall IRQ wake: %d\n", ret);1551 goto err_fall;1552 }1553 1554 ret = arizona_request_irq(arizona, ARIZONA_IRQ_MICDET,1555 "MICDET", arizona_micdet, info);1556 if (ret != 0) {1557 dev_err(arizona->dev, "Failed to get MICDET IRQ: %d\n", ret);1558 goto err_fall_wake;1559 }1560 1561 ret = arizona_request_irq(arizona, ARIZONA_IRQ_HPDET,1562 "HPDET", arizona_hpdet_irq, info);1563 if (ret != 0) {1564 dev_err(arizona->dev, "Failed to get HPDET IRQ: %d\n", ret);1565 goto err_micdet;1566 }1567 1568 arizona_clk32k_enable(arizona);1569 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_DEBOUNCE,1570 ARIZONA_JD1_DB, ARIZONA_JD1_DB);1571 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,1572 ARIZONA_JD1_ENA, ARIZONA_JD1_ENA);1573 1574 ret = regulator_allow_bypass(info->micvdd, true);1575 if (ret != 0)1576 dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n", ret);1577 1578 pm_runtime_put(arizona->dev);1579 1580 return 0;1581 1582err_micdet:1583 arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);1584err_fall_wake:1585 arizona_set_irq_wake(arizona, jack_irq_fall, 0);1586err_fall:1587 arizona_free_irq(arizona, jack_irq_fall, info);1588err_rise_wake:1589 arizona_set_irq_wake(arizona, jack_irq_rise, 0);1590err_rise:1591 arizona_free_irq(arizona, jack_irq_rise, info);1592err_pm:1593 pm_runtime_put(arizona->dev);1594 info->jack = NULL;1595 return ret;1596}1597 1598static int arizona_jack_disable_jack_detect(struct arizona_priv *info)1599{1600 struct arizona *arizona = info->arizona;1601 int jack_irq_rise, jack_irq_fall;1602 bool change;1603 int ret;1604 1605 if (!info->jack)1606 return 0;1607 1608 if (info->micd_clamp) {1609 jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;1610 jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;1611 } else {1612 jack_irq_rise = ARIZONA_IRQ_JD_RISE;1613 jack_irq_fall = ARIZONA_IRQ_JD_FALL;1614 }1615 1616 arizona_set_irq_wake(arizona, jack_irq_rise, 0);1617 arizona_set_irq_wake(arizona, jack_irq_fall, 0);1618 arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);1619 arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);1620 arizona_free_irq(arizona, jack_irq_rise, info);1621 arizona_free_irq(arizona, jack_irq_fall, info);1622 cancel_delayed_work_sync(&info->hpdet_work);1623 cancel_delayed_work_sync(&info->micd_detect_work);1624 cancel_delayed_work_sync(&info->micd_timeout_work);1625 1626 ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,1627 ARIZONA_MICD_ENA, 0,1628 &change);1629 if (ret < 0) {1630 dev_err(arizona->dev, "Failed to disable micd on remove: %d\n", ret);1631 } else if (change) {1632 regulator_disable(info->micvdd);1633 pm_runtime_put(arizona->dev);1634 }1635 1636 regmap_update_bits(arizona->regmap,1637 ARIZONA_MICD_CLAMP_CONTROL,1638 ARIZONA_MICD_CLAMP_MODE_MASK, 0);1639 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,1640 ARIZONA_JD1_ENA, 0);1641 arizona_clk32k_disable(arizona);1642 info->jack = NULL;1643 1644 return 0;1645}1646 1647int arizona_jack_set_jack(struct snd_soc_component *component,1648 struct snd_soc_jack *jack, void *data)1649{1650 struct arizona_priv *info = snd_soc_component_get_drvdata(component);1651 1652 if (jack)1653 return arizona_jack_enable_jack_detect(info, jack);1654 else1655 return arizona_jack_disable_jack_detect(info);1656}1657EXPORT_SYMBOL_GPL(arizona_jack_set_jack);1658