Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.9-rc4 1258 lines 32 kB view raw
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");