linux/drivers/extcon/extcon-arizona.c
<<
>>
Prefs
   1/*
   2 * extcon-arizona.c - Extcon driver Wolfson Arizona devices
   3 *
   4 *  Copyright (C) 2012 Wolfson Microelectronics plc
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * (at your option) any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 */
  16
  17#include <linux/kernel.h>
  18#include <linux/module.h>
  19#include <linux/i2c.h>
  20#include <linux/slab.h>
  21#include <linux/interrupt.h>
  22#include <linux/err.h>
  23#include <linux/gpio.h>
  24#include <linux/input.h>
  25#include <linux/platform_device.h>
  26#include <linux/pm_runtime.h>
  27#include <linux/regulator/consumer.h>
  28#include <linux/extcon.h>
  29
  30#include <sound/soc.h>
  31
  32#include <linux/mfd/arizona/core.h>
  33#include <linux/mfd/arizona/pdata.h>
  34#include <linux/mfd/arizona/registers.h>
  35
  36#define ARIZONA_NUM_BUTTONS 6
  37
  38#define ARIZONA_ACCDET_MODE_MIC 0
  39#define ARIZONA_ACCDET_MODE_HPL 1
  40#define ARIZONA_ACCDET_MODE_HPR 2
  41
  42struct arizona_extcon_info {
  43        struct device *dev;
  44        struct arizona *arizona;
  45        struct mutex lock;
  46        struct regulator *micvdd;
  47        struct input_dev *input;
  48
  49        int micd_mode;
  50        const struct arizona_micd_config *micd_modes;
  51        int micd_num_modes;
  52
  53        bool micd_reva;
  54        bool micd_clamp;
  55
  56        struct delayed_work hpdet_work;
  57
  58        bool hpdet_active;
  59        bool hpdet_done;
  60
  61        int num_hpdet_res;
  62        unsigned int hpdet_res[3];
  63
  64        bool mic;
  65        bool detecting;
  66        int jack_flips;
  67
  68        int hpdet_ip;
  69
  70        struct extcon_dev edev;
  71};
  72
  73static const struct arizona_micd_config micd_default_modes[] = {
  74        { 0,                  2 << ARIZONA_MICD_BIAS_SRC_SHIFT, 1 },
  75        { ARIZONA_ACCDET_SRC, 1 << ARIZONA_MICD_BIAS_SRC_SHIFT, 0 },
  76};
  77
  78static struct {
  79        u16 status;
  80        int report;
  81} arizona_lvl_to_key[ARIZONA_NUM_BUTTONS] = {
  82        {  0x1, BTN_0 },
  83        {  0x2, BTN_1 },
  84        {  0x4, BTN_2 },
  85        {  0x8, BTN_3 },
  86        { 0x10, BTN_4 },
  87        { 0x20, BTN_5 },
  88};
  89
  90#define ARIZONA_CABLE_MECHANICAL 0
  91#define ARIZONA_CABLE_MICROPHONE 1
  92#define ARIZONA_CABLE_HEADPHONE  2
  93#define ARIZONA_CABLE_LINEOUT    3
  94
  95static const char *arizona_cable[] = {
  96        "Mechanical",
  97        "Microphone",
  98        "Headphone",
  99        "Line-out",
 100        NULL,
 101};
 102
 103static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode)
 104{
 105        struct arizona *arizona = info->arizona;
 106
 107        if (arizona->pdata.micd_pol_gpio > 0)
 108                gpio_set_value_cansleep(arizona->pdata.micd_pol_gpio,
 109                                        info->micd_modes[mode].gpio);
 110        regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
 111                           ARIZONA_MICD_BIAS_SRC_MASK,
 112                           info->micd_modes[mode].bias);
 113        regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
 114                           ARIZONA_ACCDET_SRC, info->micd_modes[mode].src);
 115
 116        info->micd_mode = mode;
 117
 118        dev_dbg(arizona->dev, "Set jack polarity to %d\n", mode);
 119}
 120
 121static const char *arizona_extcon_get_micbias(struct arizona_extcon_info *info)
 122{
 123        switch (info->micd_modes[0].bias >> ARIZONA_MICD_BIAS_SRC_SHIFT) {
 124        case 1:
 125                return "MICBIAS1";
 126        case 2:
 127                return "MICBIAS2";
 128        case 3:
 129                return "MICBIAS3";
 130        default:
 131                return "MICVDD";
 132        }
 133}
 134
 135static void arizona_extcon_pulse_micbias(struct arizona_extcon_info *info)
 136{
 137        struct arizona *arizona = info->arizona;
 138        const char *widget = arizona_extcon_get_micbias(info);
 139        struct snd_soc_dapm_context *dapm = arizona->dapm;
 140        int ret;
 141
 142        mutex_lock(&dapm->card->dapm_mutex);
 143
 144        ret = snd_soc_dapm_force_enable_pin(dapm, widget);
 145        if (ret != 0)
 146                dev_warn(arizona->dev, "Failed to enable %s: %d\n",
 147                         widget, ret);
 148
 149        mutex_unlock(&dapm->card->dapm_mutex);
 150
 151        snd_soc_dapm_sync(dapm);
 152
 153        if (!arizona->pdata.micd_force_micbias) {
 154                mutex_lock(&dapm->card->dapm_mutex);
 155
 156                ret = snd_soc_dapm_disable_pin(arizona->dapm, widget);
 157                if (ret != 0)
 158                        dev_warn(arizona->dev, "Failed to disable %s: %d\n",
 159                                 widget, ret);
 160
 161                mutex_unlock(&dapm->card->dapm_mutex);
 162
 163                snd_soc_dapm_sync(dapm);
 164        }
 165}
 166
 167static void arizona_start_mic(struct arizona_extcon_info *info)
 168{
 169        struct arizona *arizona = info->arizona;
 170        bool change;
 171        int ret;
 172
 173        /* Microphone detection can't use idle mode */
 174        pm_runtime_get(info->dev);
 175
 176        if (info->detecting) {
 177                ret = regulator_allow_bypass(info->micvdd, false);
 178                if (ret != 0) {
 179                        dev_err(arizona->dev,
 180                                "Failed to regulate MICVDD: %d\n",
 181                                ret);
 182                }
 183        }
 184
 185        ret = regulator_enable(info->micvdd);
 186        if (ret != 0) {
 187                dev_err(arizona->dev, "Failed to enable MICVDD: %d\n",
 188                        ret);
 189        }
 190
 191        if (info->micd_reva) {
 192                regmap_write(arizona->regmap, 0x80, 0x3);
 193                regmap_write(arizona->regmap, 0x294, 0);
 194                regmap_write(arizona->regmap, 0x80, 0x0);
 195        }
 196
 197        regmap_update_bits(arizona->regmap,
 198                           ARIZONA_ACCESSORY_DETECT_MODE_1,
 199                           ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
 200
 201        arizona_extcon_pulse_micbias(info);
 202
 203        regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
 204                                 ARIZONA_MICD_ENA, ARIZONA_MICD_ENA,
 205                                 &change);
 206        if (!change) {
 207                regulator_disable(info->micvdd);
 208                pm_runtime_put_autosuspend(info->dev);
 209        }
 210}
 211
 212static void arizona_stop_mic(struct arizona_extcon_info *info)
 213{
 214        struct arizona *arizona = info->arizona;
 215        const char *widget = arizona_extcon_get_micbias(info);
 216        struct snd_soc_dapm_context *dapm = arizona->dapm;
 217        bool change;
 218        int ret;
 219
 220        regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
 221                                 ARIZONA_MICD_ENA, 0,
 222                                 &change);
 223
 224        mutex_lock(&dapm->card->dapm_mutex);
 225
 226        ret = snd_soc_dapm_disable_pin(dapm, widget);
 227        if (ret != 0)
 228                dev_warn(arizona->dev,
 229                         "Failed to disable %s: %d\n",
 230                         widget, ret);
 231
 232        mutex_unlock(&dapm->card->dapm_mutex);
 233
 234        snd_soc_dapm_sync(dapm);
 235
 236        if (info->micd_reva) {
 237                regmap_write(arizona->regmap, 0x80, 0x3);
 238                regmap_write(arizona->regmap, 0x294, 2);
 239                regmap_write(arizona->regmap, 0x80, 0x0);
 240        }
 241
 242        ret = regulator_allow_bypass(info->micvdd, true);
 243        if (ret != 0) {
 244                dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n",
 245                        ret);
 246        }
 247
 248        if (change) {
 249                regulator_disable(info->micvdd);
 250                pm_runtime_mark_last_busy(info->dev);
 251                pm_runtime_put_autosuspend(info->dev);
 252        }
 253}
 254
 255static struct {
 256        unsigned int factor_a;
 257        unsigned int factor_b;
 258} arizona_hpdet_b_ranges[] = {
 259        {  5528,   362464 },
 260        { 11084,  6186851 },
 261        { 11065, 65460395 },
 262};
 263
 264static struct {
 265        int min;
 266        int max;
 267} arizona_hpdet_c_ranges[] = {
 268        { 0,       30 },
 269        { 8,      100 },
 270        { 100,   1000 },
 271        { 1000, 10000 },
 272};
 273
 274static int arizona_hpdet_read(struct arizona_extcon_info *info)
 275{
 276        struct arizona *arizona = info->arizona;
 277        unsigned int val, range;
 278        int ret;
 279
 280        ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2, &val);
 281        if (ret != 0) {
 282                dev_err(arizona->dev, "Failed to read HPDET status: %d\n",
 283                        ret);
 284                return ret;
 285        }
 286
 287        switch (info->hpdet_ip) {
 288        case 0:
 289                if (!(val & ARIZONA_HP_DONE)) {
 290                        dev_err(arizona->dev, "HPDET did not complete: %x\n",
 291                                val);
 292                        return -EAGAIN;
 293                }
 294
 295                val &= ARIZONA_HP_LVL_MASK;
 296                break;
 297
 298        case 1:
 299                if (!(val & ARIZONA_HP_DONE_B)) {
 300                        dev_err(arizona->dev, "HPDET did not complete: %x\n",
 301                                val);
 302                        return -EAGAIN;
 303                }
 304
 305                ret = regmap_read(arizona->regmap, ARIZONA_HP_DACVAL, &val);
 306                if (ret != 0) {
 307                        dev_err(arizona->dev, "Failed to read HP value: %d\n",
 308                                ret);
 309                        return -EAGAIN;
 310                }
 311
 312                regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
 313                            &range);
 314                range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
 315                           >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
 316
 317                if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 &&
 318                    (val < 100 || val > 0x3fb)) {
 319                        range++;
 320                        dev_dbg(arizona->dev, "Moving to HPDET range %d\n",
 321                                range);
 322                        regmap_update_bits(arizona->regmap,
 323                                           ARIZONA_HEADPHONE_DETECT_1,
 324                                           ARIZONA_HP_IMPEDANCE_RANGE_MASK,
 325                                           range <<
 326                                           ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
 327                        return -EAGAIN;
 328                }
 329
 330                /* If we go out of range report top of range */
 331                if (val < 100 || val > 0x3fb) {
 332                        dev_dbg(arizona->dev, "Measurement out of range\n");
 333                        return 10000;
 334                }
 335
 336                dev_dbg(arizona->dev, "HPDET read %d in range %d\n",
 337                        val, range);
 338
 339                val = arizona_hpdet_b_ranges[range].factor_b
 340                        / ((val * 100) -
 341                           arizona_hpdet_b_ranges[range].factor_a);
 342                break;
 343
 344        default:
 345                dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n",
 346                         info->hpdet_ip);
 347        case 2:
 348                if (!(val & ARIZONA_HP_DONE_B)) {
 349                        dev_err(arizona->dev, "HPDET did not complete: %x\n",
 350                                val);
 351                        return -EAGAIN;
 352                }
 353
 354                val &= ARIZONA_HP_LVL_B_MASK;
 355
 356                regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
 357                            &range);
 358                range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
 359                           >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
 360
 361                /* Skip up or down a range? */
 362                if (range && (val < arizona_hpdet_c_ranges[range].min)) {
 363                        range--;
 364                        dev_dbg(arizona->dev, "Moving to HPDET range %d-%d\n",
 365                                arizona_hpdet_c_ranges[range].min,
 366                                arizona_hpdet_c_ranges[range].max);
 367                        regmap_update_bits(arizona->regmap,
 368                                           ARIZONA_HEADPHONE_DETECT_1,
 369                                           ARIZONA_HP_IMPEDANCE_RANGE_MASK,
 370                                           range <<
 371                                           ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
 372                        return -EAGAIN;
 373                }
 374
 375                if (range < ARRAY_SIZE(arizona_hpdet_c_ranges) - 1 &&
 376                    (val >= arizona_hpdet_c_ranges[range].max)) {
 377                        range++;
 378                        dev_dbg(arizona->dev, "Moving to HPDET range %d-%d\n",
 379                                arizona_hpdet_c_ranges[range].min,
 380                                arizona_hpdet_c_ranges[range].max);
 381                        regmap_update_bits(arizona->regmap,
 382                                           ARIZONA_HEADPHONE_DETECT_1,
 383                                           ARIZONA_HP_IMPEDANCE_RANGE_MASK,
 384                                           range <<
 385                                           ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
 386                        return -EAGAIN;
 387                }
 388        }
 389
 390        dev_dbg(arizona->dev, "HP impedance %d ohms\n", val);
 391        return val;
 392}
 393
 394static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading)
 395{
 396        struct arizona *arizona = info->arizona;
 397        int id_gpio = arizona->pdata.hpdet_id_gpio;
 398
 399        /*
 400         * If we're using HPDET for accessory identification we need
 401         * to take multiple measurements, step through them in sequence.
 402         */
 403        if (arizona->pdata.hpdet_acc_id) {
 404                info->hpdet_res[info->num_hpdet_res++] = *reading;
 405
 406                /*
 407                 * If the impedence is too high don't measure the
 408                 * second ground.
 409                 */
 410                if (info->num_hpdet_res == 1 && *reading >= 45) {
 411                        dev_dbg(arizona->dev, "Skipping ground flip\n");
 412                        info->hpdet_res[info->num_hpdet_res++] = *reading;
 413                }
 414
 415                if (info->num_hpdet_res == 1) {
 416                        dev_dbg(arizona->dev, "Flipping ground\n");
 417
 418                        regmap_update_bits(arizona->regmap,
 419                                           ARIZONA_ACCESSORY_DETECT_MODE_1,
 420                                           ARIZONA_ACCDET_SRC,
 421                                           ~info->micd_modes[0].src);
 422
 423                        regmap_update_bits(arizona->regmap,
 424                                           ARIZONA_HEADPHONE_DETECT_1,
 425                                           ARIZONA_HP_POLL, ARIZONA_HP_POLL);
 426                        return -EAGAIN;
 427                }
 428
 429                /* Only check the mic directly if we didn't already ID it */
 430                if (id_gpio && info->num_hpdet_res == 2 &&
 431                    !((info->hpdet_res[0] > info->hpdet_res[1] * 2))) {
 432                        dev_dbg(arizona->dev, "Measuring mic\n");
 433
 434                        regmap_update_bits(arizona->regmap,
 435                                           ARIZONA_ACCESSORY_DETECT_MODE_1,
 436                                           ARIZONA_ACCDET_MODE_MASK |
 437                                           ARIZONA_ACCDET_SRC,
 438                                           ARIZONA_ACCDET_MODE_HPR |
 439                                           info->micd_modes[0].src);
 440
 441                        gpio_set_value_cansleep(id_gpio, 1);
 442
 443                        regmap_update_bits(arizona->regmap,
 444                                           ARIZONA_HEADPHONE_DETECT_1,
 445                                           ARIZONA_HP_POLL, ARIZONA_HP_POLL);
 446                        return -EAGAIN;
 447                }
 448
 449                /* OK, got both.  Now, compare... */
 450                dev_dbg(arizona->dev, "HPDET measured %d %d %d\n",
 451                        info->hpdet_res[0], info->hpdet_res[1],
 452                        info->hpdet_res[2]);
 453
 454
 455                /* Take the headphone impedance for the main report */
 456                *reading = info->hpdet_res[0];
 457
 458                /*
 459                 * Either the two grounds measure differently or we
 460                 * measure the mic as high impedance.
 461                 */
 462                if ((info->hpdet_res[0] > info->hpdet_res[1] * 2) ||
 463                    (id_gpio && info->hpdet_res[2] > 10)) {
 464                        dev_dbg(arizona->dev, "Detected mic\n");
 465                        info->mic = true;
 466                        info->detecting = true;
 467                } else {
 468                        dev_dbg(arizona->dev, "Detected headphone\n");
 469                }
 470
 471                /* Make sure everything is reset back to the real polarity */
 472                regmap_update_bits(arizona->regmap,
 473                                   ARIZONA_ACCESSORY_DETECT_MODE_1,
 474                                   ARIZONA_ACCDET_SRC,
 475                                   info->micd_modes[0].src);
 476        }
 477
 478        return 0;
 479}
 480
 481static irqreturn_t arizona_hpdet_irq(int irq, void *data)
 482{
 483        struct arizona_extcon_info *info = data;
 484        struct arizona *arizona = info->arizona;
 485        int id_gpio = arizona->pdata.hpdet_id_gpio;
 486        int report = ARIZONA_CABLE_HEADPHONE;
 487        unsigned int val;
 488        int ret, reading;
 489
 490        mutex_lock(&info->lock);
 491
 492        /* If we got a spurious IRQ for some reason then ignore it */
 493        if (!info->hpdet_active) {
 494                dev_warn(arizona->dev, "Spurious HPDET IRQ\n");
 495                mutex_unlock(&info->lock);
 496                return IRQ_NONE;
 497        }
 498
 499        /* If the cable was removed while measuring ignore the result */
 500        ret = extcon_get_cable_state_(&info->edev, ARIZONA_CABLE_MECHANICAL);
 501        if (ret < 0) {
 502                dev_err(arizona->dev, "Failed to check cable state: %d\n",
 503                        ret);
 504                goto out;
 505        } else if (!ret) {
 506                dev_dbg(arizona->dev, "Ignoring HPDET for removed cable\n");
 507                goto done;
 508        }
 509
 510        ret = arizona_hpdet_read(info);
 511        if (ret == -EAGAIN) {
 512                goto out;
 513        } else if (ret < 0) {
 514                goto done;
 515        }
 516        reading = ret;
 517
 518        /* Reset back to starting range */
 519        regmap_update_bits(arizona->regmap,
 520                           ARIZONA_HEADPHONE_DETECT_1,
 521                           ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
 522                           0);
 523
 524        ret = arizona_hpdet_do_id(info, &reading);
 525        if (ret == -EAGAIN) {
 526                goto out;
 527        } else if (ret < 0) {
 528                goto done;
 529        }
 530
 531        /* Report high impedence cables as line outputs */
 532        if (reading >= 5000)
 533                report = ARIZONA_CABLE_LINEOUT;
 534        else
 535                report = ARIZONA_CABLE_HEADPHONE;
 536
 537        ret = extcon_set_cable_state_(&info->edev, report, true);
 538        if (ret != 0)
 539                dev_err(arizona->dev, "Failed to report HP/line: %d\n",
 540                        ret);
 541
 542        mutex_lock(&arizona->dapm->card->dapm_mutex);
 543
 544        ret = regmap_read(arizona->regmap, ARIZONA_OUTPUT_ENABLES_1, &val);
 545        if (ret != 0) {
 546                dev_err(arizona->dev, "Failed to read output enables: %d\n",
 547                        ret);
 548                val = 0;
 549        }
 550
 551        if (!(val & (ARIZONA_OUT1L_ENA | ARIZONA_OUT1R_ENA))) {
 552                ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000, 0);
 553                if (ret != 0)
 554                        dev_warn(arizona->dev, "Failed to undo magic: %d\n",
 555                                 ret);
 556
 557                ret = regmap_update_bits(arizona->regmap, 0x226, 0x4000, 0);
 558                if (ret != 0)
 559                        dev_warn(arizona->dev, "Failed to undo magic: %d\n",
 560                                 ret);
 561        }
 562
 563        mutex_unlock(&arizona->dapm->card->dapm_mutex);
 564
 565done:
 566        if (id_gpio)
 567                gpio_set_value_cansleep(id_gpio, 0);
 568
 569        /* Revert back to MICDET mode */
 570        regmap_update_bits(arizona->regmap,
 571                           ARIZONA_ACCESSORY_DETECT_MODE_1,
 572                           ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
 573
 574        /* If we have a mic then reenable MICDET */
 575        if (info->mic)
 576                arizona_start_mic(info);
 577
 578        if (info->hpdet_active) {
 579                pm_runtime_put_autosuspend(info->dev);
 580                info->hpdet_active = false;
 581        }
 582
 583        info->hpdet_done = true;
 584
 585out:
 586        mutex_unlock(&info->lock);
 587
 588        return IRQ_HANDLED;
 589}
 590
 591static void arizona_identify_headphone(struct arizona_extcon_info *info)
 592{
 593        struct arizona *arizona = info->arizona;
 594        int ret;
 595
 596        if (info->hpdet_done)
 597                return;
 598
 599        dev_dbg(arizona->dev, "Starting HPDET\n");
 600
 601        /* Make sure we keep the device enabled during the measurement */
 602        pm_runtime_get(info->dev);
 603
 604        info->hpdet_active = true;
 605
 606        if (info->mic)
 607                arizona_stop_mic(info);
 608
 609        ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000, 0x4000);
 610        if (ret != 0)
 611                dev_warn(arizona->dev, "Failed to do magic: %d\n", ret);
 612
 613        ret = regmap_update_bits(arizona->regmap, 0x226, 0x4000, 0x4000);
 614        if (ret != 0)
 615                dev_warn(arizona->dev, "Failed to do magic: %d\n", ret);
 616
 617        ret = regmap_update_bits(arizona->regmap,
 618                                 ARIZONA_ACCESSORY_DETECT_MODE_1,
 619                                 ARIZONA_ACCDET_MODE_MASK,
 620                                 ARIZONA_ACCDET_MODE_HPL);
 621        if (ret != 0) {
 622                dev_err(arizona->dev, "Failed to set HPDETL mode: %d\n", ret);
 623                goto err;
 624        }
 625
 626        ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
 627                                 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
 628        if (ret != 0) {
 629                dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n",
 630                        ret);
 631                goto err;
 632        }
 633
 634        return;
 635
 636err:
 637        regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
 638                           ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
 639
 640        /* Just report headphone */
 641        ret = extcon_update_state(&info->edev,
 642                                  1 << ARIZONA_CABLE_HEADPHONE,
 643                                  1 << ARIZONA_CABLE_HEADPHONE);
 644        if (ret != 0)
 645                dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
 646
 647        if (info->mic)
 648                arizona_start_mic(info);
 649
 650        info->hpdet_active = false;
 651}
 652
 653static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
 654{
 655        struct arizona *arizona = info->arizona;
 656        unsigned int val;
 657        int ret;
 658
 659        dev_dbg(arizona->dev, "Starting identification via HPDET\n");
 660
 661        /* Make sure we keep the device enabled during the measurement */
 662        pm_runtime_get_sync(info->dev);
 663
 664        info->hpdet_active = true;
 665
 666        arizona_extcon_pulse_micbias(info);
 667
 668        mutex_lock(&arizona->dapm->card->dapm_mutex);
 669
 670        ret = regmap_read(arizona->regmap, ARIZONA_OUTPUT_ENABLES_1, &val);
 671        if (ret != 0) {
 672                dev_err(arizona->dev, "Failed to read output enables: %d\n",
 673                        ret);
 674                val = 0;
 675        }
 676
 677        if (!(val & (ARIZONA_OUT1L_ENA | ARIZONA_OUT1R_ENA))) {
 678                ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000,
 679                                         0x4000);
 680                if (ret != 0)
 681                        dev_warn(arizona->dev, "Failed to do magic: %d\n",
 682                                 ret);
 683
 684                ret = regmap_update_bits(arizona->regmap, 0x226, 0x4000,
 685                                         0x4000);
 686                if (ret != 0)
 687                        dev_warn(arizona->dev, "Failed to do magic: %d\n",
 688                                 ret);
 689        }
 690
 691        mutex_unlock(&arizona->dapm->card->dapm_mutex);
 692
 693        ret = regmap_update_bits(arizona->regmap,
 694                                 ARIZONA_ACCESSORY_DETECT_MODE_1,
 695                                 ARIZONA_ACCDET_SRC | ARIZONA_ACCDET_MODE_MASK,
 696                                 info->micd_modes[0].src |
 697                                 ARIZONA_ACCDET_MODE_HPL);
 698        if (ret != 0) {
 699                dev_err(arizona->dev, "Failed to set HPDETL mode: %d\n", ret);
 700                goto err;
 701        }
 702
 703        ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
 704                                 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
 705        if (ret != 0) {
 706                dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n",
 707                        ret);
 708                goto err;
 709        }
 710
 711        return;
 712
 713err:
 714        regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
 715                           ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
 716
 717        /* Just report headphone */
 718        ret = extcon_update_state(&info->edev,
 719                                  1 << ARIZONA_CABLE_HEADPHONE,
 720                                  1 << ARIZONA_CABLE_HEADPHONE);
 721        if (ret != 0)
 722                dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
 723
 724        info->hpdet_active = false;
 725}
 726
 727static irqreturn_t arizona_micdet(int irq, void *data)
 728{
 729        struct arizona_extcon_info *info = data;
 730        struct arizona *arizona = info->arizona;
 731        unsigned int val, lvl;
 732        int ret, i;
 733
 734        mutex_lock(&info->lock);
 735
 736        ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
 737        if (ret != 0) {
 738                dev_err(arizona->dev, "Failed to read MICDET: %d\n", ret);
 739                mutex_unlock(&info->lock);
 740                return IRQ_NONE;
 741        }
 742
 743        dev_dbg(arizona->dev, "MICDET: %x\n", val);
 744
 745        if (!(val & ARIZONA_MICD_VALID)) {
 746                dev_warn(arizona->dev, "Microphone detection state invalid\n");
 747                mutex_unlock(&info->lock);
 748                return IRQ_NONE;
 749        }
 750
 751        /* Due to jack detect this should never happen */
 752        if (!(val & ARIZONA_MICD_STS)) {
 753                dev_warn(arizona->dev, "Detected open circuit\n");
 754                info->detecting = false;
 755                goto handled;
 756        }
 757
 758        /* If we got a high impedence we should have a headset, report it. */
 759        if (info->detecting && (val & 0x400)) {
 760                arizona_identify_headphone(info);
 761
 762                ret = extcon_update_state(&info->edev,
 763                                          1 << ARIZONA_CABLE_MICROPHONE,
 764                                          1 << ARIZONA_CABLE_MICROPHONE);
 765
 766                if (ret != 0)
 767                        dev_err(arizona->dev, "Headset report failed: %d\n",
 768                                ret);
 769
 770                /* Don't need to regulate for button detection */
 771                ret = regulator_allow_bypass(info->micvdd, false);
 772                if (ret != 0) {
 773                        dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n",
 774                                ret);
 775                }
 776
 777                info->mic = true;
 778                info->detecting = false;
 779                goto handled;
 780        }
 781
 782        /* If we detected a lower impedence during initial startup
 783         * then we probably have the wrong polarity, flip it.  Don't
 784         * do this for the lowest impedences to speed up detection of
 785         * plain headphones.  If both polarities report a low
 786         * impedence then give up and report headphones.
 787         */
 788        if (info->detecting && (val & 0x3f8)) {
 789                if (info->jack_flips >= info->micd_num_modes) {
 790                        dev_dbg(arizona->dev, "Detected HP/line\n");
 791                        arizona_identify_headphone(info);
 792
 793                        info->detecting = false;
 794
 795                        arizona_stop_mic(info);
 796                } else {
 797                        info->micd_mode++;
 798                        if (info->micd_mode == info->micd_num_modes)
 799                                info->micd_mode = 0;
 800                        arizona_extcon_set_mode(info, info->micd_mode);
 801
 802                        info->jack_flips++;
 803                }
 804
 805                goto handled;
 806        }
 807
 808        /*
 809         * If we're still detecting and we detect a short then we've
 810         * got a headphone.  Otherwise it's a button press.
 811         */
 812        if (val & 0x3fc) {
 813                if (info->mic) {
 814                        dev_dbg(arizona->dev, "Mic button detected\n");
 815
 816                        lvl = val & ARIZONA_MICD_LVL_MASK;
 817                        lvl >>= ARIZONA_MICD_LVL_SHIFT;
 818
 819                        for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
 820                                if (lvl & arizona_lvl_to_key[i].status)
 821                                        input_report_key(info->input,
 822                                                         arizona_lvl_to_key[i].report,
 823                                                         1);
 824                        input_sync(info->input);
 825
 826                } else if (info->detecting) {
 827                        dev_dbg(arizona->dev, "Headphone detected\n");
 828                        info->detecting = false;
 829                        arizona_stop_mic(info);
 830
 831                        arizona_identify_headphone(info);
 832                } else {
 833                        dev_warn(arizona->dev, "Button with no mic: %x\n",
 834                                 val);
 835                }
 836        } else {
 837                dev_dbg(arizona->dev, "Mic button released\n");
 838                for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
 839                        input_report_key(info->input,
 840                                         arizona_lvl_to_key[i].report, 0);
 841                input_sync(info->input);
 842                arizona_extcon_pulse_micbias(info);
 843        }
 844
 845handled:
 846        pm_runtime_mark_last_busy(info->dev);
 847        mutex_unlock(&info->lock);
 848
 849        return IRQ_HANDLED;
 850}
 851
 852static void arizona_hpdet_work(struct work_struct *work)
 853{
 854        struct arizona_extcon_info *info = container_of(work,
 855                                                        struct arizona_extcon_info,
 856                                                        hpdet_work.work);
 857
 858        mutex_lock(&info->lock);
 859        arizona_start_hpdet_acc_id(info);
 860        mutex_unlock(&info->lock);
 861}
 862
 863static irqreturn_t arizona_jackdet(int irq, void *data)
 864{
 865        struct arizona_extcon_info *info = data;
 866        struct arizona *arizona = info->arizona;
 867        unsigned int val, present, mask;
 868        int ret, i;
 869
 870        pm_runtime_get_sync(info->dev);
 871
 872        cancel_delayed_work_sync(&info->hpdet_work);
 873
 874        mutex_lock(&info->lock);
 875
 876        if (arizona->pdata.jd_gpio5) {
 877                mask = ARIZONA_MICD_CLAMP_STS;
 878                present = 0;
 879        } else {
 880                mask = ARIZONA_JD1_STS;
 881                present = ARIZONA_JD1_STS;
 882        }
 883
 884        ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val);
 885        if (ret != 0) {
 886                dev_err(arizona->dev, "Failed to read jackdet status: %d\n",
 887                        ret);
 888                mutex_unlock(&info->lock);
 889                pm_runtime_put_autosuspend(info->dev);
 890                return IRQ_NONE;
 891        }
 892
 893        if ((val & mask) == present) {
 894                dev_dbg(arizona->dev, "Detected jack\n");
 895                ret = extcon_set_cable_state_(&info->edev,
 896                                              ARIZONA_CABLE_MECHANICAL, true);
 897
 898                if (ret != 0)
 899                        dev_err(arizona->dev, "Mechanical report failed: %d\n",
 900                                ret);
 901
 902                if (!arizona->pdata.hpdet_acc_id) {
 903                        info->detecting = true;
 904                        info->mic = false;
 905                        info->jack_flips = 0;
 906
 907                        arizona_start_mic(info);
 908                } else {
 909                        schedule_delayed_work(&info->hpdet_work,
 910                                              msecs_to_jiffies(250));
 911                }
 912
 913                regmap_update_bits(arizona->regmap,
 914                                   ARIZONA_JACK_DETECT_DEBOUNCE,
 915                                   ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB, 0);
 916        } else {
 917                dev_dbg(arizona->dev, "Detected jack removal\n");
 918
 919                arizona_stop_mic(info);
 920
 921                info->num_hpdet_res = 0;
 922                for (i = 0; i < ARRAY_SIZE(info->hpdet_res); i++)
 923                        info->hpdet_res[i] = 0;
 924                info->mic = false;
 925                info->hpdet_done = false;
 926
 927                for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
 928                        input_report_key(info->input,
 929                                         arizona_lvl_to_key[i].report, 0);
 930                input_sync(info->input);
 931
 932                ret = extcon_update_state(&info->edev, 0xffffffff, 0);
 933                if (ret != 0)
 934                        dev_err(arizona->dev, "Removal report failed: %d\n",
 935                                ret);
 936
 937                regmap_update_bits(arizona->regmap,
 938                                   ARIZONA_JACK_DETECT_DEBOUNCE,
 939                                   ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB,
 940                                   ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB);
 941        }
 942
 943        /* Clear trig_sts to make sure DCVDD is not forced up */
 944        regmap_write(arizona->regmap, ARIZONA_AOD_WKUP_AND_TRIG,
 945                     ARIZONA_MICD_CLAMP_FALL_TRIG_STS |
 946                     ARIZONA_MICD_CLAMP_RISE_TRIG_STS |
 947                     ARIZONA_JD1_FALL_TRIG_STS |
 948                     ARIZONA_JD1_RISE_TRIG_STS);
 949
 950        mutex_unlock(&info->lock);
 951
 952        pm_runtime_mark_last_busy(info->dev);
 953        pm_runtime_put_autosuspend(info->dev);
 954
 955        return IRQ_HANDLED;
 956}
 957
 958static int arizona_extcon_probe(struct platform_device *pdev)
 959{
 960        struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
 961        struct arizona_pdata *pdata;
 962        struct arizona_extcon_info *info;
 963        int jack_irq_fall, jack_irq_rise;
 964        int ret, mode, i;
 965
 966        if (!arizona->dapm || !arizona->dapm->card)
 967                return -EPROBE_DEFER;
 968
 969        pdata = dev_get_platdata(arizona->dev);
 970
 971        info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
 972        if (!info) {
 973                dev_err(&pdev->dev, "Failed to allocate memory\n");
 974                ret = -ENOMEM;
 975                goto err;
 976        }
 977
 978        info->micvdd = devm_regulator_get(arizona->dev, "MICVDD");
 979        if (IS_ERR(info->micvdd)) {
 980                ret = PTR_ERR(info->micvdd);
 981                dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret);
 982                goto err;
 983        }
 984
 985        mutex_init(&info->lock);
 986        info->arizona = arizona;
 987        info->dev = &pdev->dev;
 988        INIT_DELAYED_WORK(&info->hpdet_work, arizona_hpdet_work);
 989        platform_set_drvdata(pdev, info);
 990
 991        switch (arizona->type) {
 992        case WM5102:
 993                switch (arizona->rev) {
 994                case 0:
 995                        info->micd_reva = true;
 996                        break;
 997                default:
 998                        info->micd_clamp = true;
 999                        info->hpdet_ip = 1;
1000                        break;
1001                }
1002                break;
1003        default:
1004                break;
1005        }
1006
1007        info->edev.name = "Headset Jack";
1008        info->edev.supported_cable = arizona_cable;
1009
1010        ret = extcon_dev_register(&info->edev, arizona->dev);
1011        if (ret < 0) {
1012                dev_err(arizona->dev, "extcon_dev_register() failed: %d\n",
1013                        ret);
1014                goto err;
1015        }
1016
1017        if (pdata->num_micd_configs) {
1018                info->micd_modes = pdata->micd_configs;
1019                info->micd_num_modes = pdata->num_micd_configs;
1020        } else {
1021                info->micd_modes = micd_default_modes;
1022                info->micd_num_modes = ARRAY_SIZE(micd_default_modes);
1023        }
1024
1025        if (arizona->pdata.micd_pol_gpio > 0) {
1026                if (info->micd_modes[0].gpio)
1027                        mode = GPIOF_OUT_INIT_HIGH;
1028                else
1029                        mode = GPIOF_OUT_INIT_LOW;
1030
1031                ret = devm_gpio_request_one(&pdev->dev,
1032                                            arizona->pdata.micd_pol_gpio,
1033                                            mode,
1034                                            "MICD polarity");
1035                if (ret != 0) {
1036                        dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
1037                                arizona->pdata.micd_pol_gpio, ret);
1038                        goto err_register;
1039                }
1040        }
1041
1042        if (arizona->pdata.hpdet_id_gpio > 0) {
1043                ret = devm_gpio_request_one(&pdev->dev,
1044                                            arizona->pdata.hpdet_id_gpio,
1045                                            GPIOF_OUT_INIT_LOW,
1046                                            "HPDET");
1047                if (ret != 0) {
1048                        dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
1049                                arizona->pdata.hpdet_id_gpio, ret);
1050                        goto err_register;
1051                }
1052        }
1053
1054        if (arizona->pdata.micd_bias_start_time)
1055                regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1056                                   ARIZONA_MICD_BIAS_STARTTIME_MASK,
1057                                   arizona->pdata.micd_bias_start_time
1058                                   << ARIZONA_MICD_BIAS_STARTTIME_SHIFT);
1059
1060        if (arizona->pdata.micd_rate)
1061                regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1062                                   ARIZONA_MICD_RATE_MASK,
1063                                   arizona->pdata.micd_rate
1064                                   << ARIZONA_MICD_RATE_SHIFT);
1065
1066        if (arizona->pdata.micd_dbtime)
1067                regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
1068                                   ARIZONA_MICD_DBTIME_MASK,
1069                                   arizona->pdata.micd_dbtime
1070                                   << ARIZONA_MICD_DBTIME_SHIFT);
1071
1072        /*
1073         * If we have a clamp use it, activating in conjunction with
1074         * GPIO5 if that is connected for jack detect operation.
1075         */
1076        if (info->micd_clamp) {
1077                if (arizona->pdata.jd_gpio5) {
1078                        /* Put the GPIO into input mode */
1079                        regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL,
1080                                     0xc101);
1081
1082                        regmap_update_bits(arizona->regmap,
1083                                           ARIZONA_MICD_CLAMP_CONTROL,
1084                                           ARIZONA_MICD_CLAMP_MODE_MASK, 0x9);
1085                } else {
1086                        regmap_update_bits(arizona->regmap,
1087                                           ARIZONA_MICD_CLAMP_CONTROL,
1088                                           ARIZONA_MICD_CLAMP_MODE_MASK, 0x4);
1089                }
1090
1091                regmap_update_bits(arizona->regmap,
1092                                   ARIZONA_JACK_DETECT_DEBOUNCE,
1093                                   ARIZONA_MICD_CLAMP_DB,
1094                                   ARIZONA_MICD_CLAMP_DB);
1095        }
1096
1097        arizona_extcon_set_mode(info, 0);
1098
1099        info->input = devm_input_allocate_device(&pdev->dev);
1100        if (!info->input) {
1101                dev_err(arizona->dev, "Can't allocate input dev\n");
1102                ret = -ENOMEM;
1103                goto err_register;
1104        }
1105
1106        for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
1107                input_set_capability(info->input, EV_KEY,
1108                                     arizona_lvl_to_key[i].report);
1109        info->input->name = "Headset";
1110        info->input->phys = "arizona/extcon";
1111        info->input->dev.parent = &pdev->dev;
1112
1113        pm_runtime_enable(&pdev->dev);
1114        pm_runtime_idle(&pdev->dev);
1115        pm_runtime_get_sync(&pdev->dev);
1116
1117        if (arizona->pdata.jd_gpio5) {
1118                jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
1119                jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
1120        } else {
1121                jack_irq_rise = ARIZONA_IRQ_JD_RISE;
1122                jack_irq_fall = ARIZONA_IRQ_JD_FALL;
1123        }
1124
1125        ret = arizona_request_irq(arizona, jack_irq_rise,
1126                                  "JACKDET rise", arizona_jackdet, info);
1127        if (ret != 0) {
1128                dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n",
1129                        ret);
1130                goto err_input;
1131        }
1132
1133        ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1);
1134        if (ret != 0) {
1135                dev_err(&pdev->dev, "Failed to set JD rise IRQ wake: %d\n",
1136                        ret);
1137                goto err_rise;
1138        }
1139
1140        ret = arizona_request_irq(arizona, jack_irq_fall,
1141                                  "JACKDET fall", arizona_jackdet, info);
1142        if (ret != 0) {
1143                dev_err(&pdev->dev, "Failed to get JD fall IRQ: %d\n", ret);
1144                goto err_rise_wake;
1145        }
1146
1147        ret = arizona_set_irq_wake(arizona, jack_irq_fall, 1);
1148        if (ret != 0) {
1149                dev_err(&pdev->dev, "Failed to set JD fall IRQ wake: %d\n",
1150                        ret);
1151                goto err_fall;
1152        }
1153
1154        ret = arizona_request_irq(arizona, ARIZONA_IRQ_MICDET,
1155                                  "MICDET", arizona_micdet, info);
1156        if (ret != 0) {
1157                dev_err(&pdev->dev, "Failed to get MICDET IRQ: %d\n", ret);
1158                goto err_fall_wake;
1159        }
1160
1161        ret = arizona_request_irq(arizona, ARIZONA_IRQ_HPDET,
1162                                  "HPDET", arizona_hpdet_irq, info);
1163        if (ret != 0) {
1164                dev_err(&pdev->dev, "Failed to get HPDET IRQ: %d\n", ret);
1165                goto err_micdet;
1166        }
1167
1168        arizona_clk32k_enable(arizona);
1169        regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_DEBOUNCE,
1170                           ARIZONA_JD1_DB, ARIZONA_JD1_DB);
1171        regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
1172                           ARIZONA_JD1_ENA, ARIZONA_JD1_ENA);
1173
1174        ret = regulator_allow_bypass(info->micvdd, true);
1175        if (ret != 0)
1176                dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n",
1177                         ret);
1178
1179        pm_runtime_put(&pdev->dev);
1180
1181        ret = input_register_device(info->input);
1182        if (ret) {
1183                dev_err(&pdev->dev, "Can't register input device: %d\n", ret);
1184                goto err_hpdet;
1185        }
1186
1187        return 0;
1188
1189err_hpdet:
1190        arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);
1191err_micdet:
1192        arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
1193err_fall_wake:
1194        arizona_set_irq_wake(arizona, jack_irq_fall, 0);
1195err_fall:
1196        arizona_free_irq(arizona, jack_irq_fall, info);
1197err_rise_wake:
1198        arizona_set_irq_wake(arizona, jack_irq_rise, 0);
1199err_rise:
1200        arizona_free_irq(arizona, jack_irq_rise, info);
1201err_input:
1202err_register:
1203        pm_runtime_disable(&pdev->dev);
1204        extcon_dev_unregister(&info->edev);
1205err:
1206        return ret;
1207}
1208
1209static int arizona_extcon_remove(struct platform_device *pdev)
1210{
1211        struct arizona_extcon_info *info = platform_get_drvdata(pdev);
1212        struct arizona *arizona = info->arizona;
1213        int jack_irq_rise, jack_irq_fall;
1214
1215        pm_runtime_disable(&pdev->dev);
1216
1217        regmap_update_bits(arizona->regmap,
1218                           ARIZONA_MICD_CLAMP_CONTROL,
1219                           ARIZONA_MICD_CLAMP_MODE_MASK, 0);
1220
1221        if (arizona->pdata.jd_gpio5) {
1222                jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
1223                jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
1224        } else {
1225                jack_irq_rise = ARIZONA_IRQ_JD_RISE;
1226                jack_irq_fall = ARIZONA_IRQ_JD_FALL;
1227        }
1228
1229        arizona_set_irq_wake(arizona, jack_irq_rise, 0);
1230        arizona_set_irq_wake(arizona, jack_irq_fall, 0);
1231        arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);
1232        arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
1233        arizona_free_irq(arizona, jack_irq_rise, info);
1234        arizona_free_irq(arizona, jack_irq_fall, info);
1235        cancel_delayed_work_sync(&info->hpdet_work);
1236        regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
1237                           ARIZONA_JD1_ENA, 0);
1238        arizona_clk32k_disable(arizona);
1239        extcon_dev_unregister(&info->edev);
1240
1241        return 0;
1242}
1243
1244static struct platform_driver arizona_extcon_driver = {
1245        .driver         = {
1246                .name   = "arizona-extcon",
1247                .owner  = THIS_MODULE,
1248        },
1249        .probe          = arizona_extcon_probe,
1250        .remove         = arizona_extcon_remove,
1251};
1252
1253module_platform_driver(arizona_extcon_driver);
1254
1255MODULE_DESCRIPTION("Arizona Extcon driver");
1256MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1257MODULE_LICENSE("GPL");
1258MODULE_ALIAS("platform:extcon-arizona");
1259
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.