aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/extcon/extcon-arizona.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/extcon/extcon-arizona.c')
-rw-r--r--drivers/extcon/extcon-arizona.c73
1 files changed, 53 insertions, 20 deletions
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index a287cece0593..c20602f601ee 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -44,6 +44,15 @@
44#define HPDET_DEBOUNCE 500 44#define HPDET_DEBOUNCE 500
45#define DEFAULT_MICD_TIMEOUT 2000 45#define DEFAULT_MICD_TIMEOUT 2000
46 46
47#define MICD_LVL_1_TO_7 (ARIZONA_MICD_LVL_1 | ARIZONA_MICD_LVL_2 | \
48 ARIZONA_MICD_LVL_3 | ARIZONA_MICD_LVL_4 | \
49 ARIZONA_MICD_LVL_5 | ARIZONA_MICD_LVL_6 | \
50 ARIZONA_MICD_LVL_7)
51
52#define MICD_LVL_0_TO_7 (ARIZONA_MICD_LVL_0 | MICD_LVL_1_TO_7)
53
54#define MICD_LVL_0_TO_8 (MICD_LVL_0_TO_7 | ARIZONA_MICD_LVL_8)
55
47struct arizona_extcon_info { 56struct arizona_extcon_info {
48 struct device *dev; 57 struct device *dev;
49 struct arizona *arizona; 58 struct arizona *arizona;
@@ -426,26 +435,15 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info)
426 } 435 }
427 436
428 val &= ARIZONA_HP_LVL_B_MASK; 437 val &= ARIZONA_HP_LVL_B_MASK;
438 /* Convert to ohms, the value is in 0.5 ohm increments */
439 val /= 2;
429 440
430 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1, 441 regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
431 &range); 442 &range);
432 range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK) 443 range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
433 >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT; 444 >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
434 445
435 /* Skip up or down a range? */ 446 /* Skip up a range, or report? */
436 if (range && (val < arizona_hpdet_c_ranges[range].min)) {
437 range--;
438 dev_dbg(arizona->dev, "Moving to HPDET range %d-%d\n",
439 arizona_hpdet_c_ranges[range].min,
440 arizona_hpdet_c_ranges[range].max);
441 regmap_update_bits(arizona->regmap,
442 ARIZONA_HEADPHONE_DETECT_1,
443 ARIZONA_HP_IMPEDANCE_RANGE_MASK,
444 range <<
445 ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
446 return -EAGAIN;
447 }
448
449 if (range < ARRAY_SIZE(arizona_hpdet_c_ranges) - 1 && 447 if (range < ARRAY_SIZE(arizona_hpdet_c_ranges) - 1 &&
450 (val >= arizona_hpdet_c_ranges[range].max)) { 448 (val >= arizona_hpdet_c_ranges[range].max)) {
451 range++; 449 range++;
@@ -459,6 +457,12 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info)
459 ARIZONA_HP_IMPEDANCE_RANGE_SHIFT); 457 ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
460 return -EAGAIN; 458 return -EAGAIN;
461 } 459 }
460
461 if (range && (val < arizona_hpdet_c_ranges[range].min)) {
462 dev_dbg(arizona->dev, "Reporting range boundary %d\n",
463 arizona_hpdet_c_ranges[range].min);
464 val = arizona_hpdet_c_ranges[range].min;
465 }
462 } 466 }
463 467
464 dev_dbg(arizona->dev, "HP impedance %d ohms\n", val); 468 dev_dbg(arizona->dev, "HP impedance %d ohms\n", val);
@@ -594,9 +598,15 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data)
594 dev_err(arizona->dev, "Failed to report HP/line: %d\n", 598 dev_err(arizona->dev, "Failed to report HP/line: %d\n",
595 ret); 599 ret);
596 600
601done:
602 /* Reset back to starting range */
603 regmap_update_bits(arizona->regmap,
604 ARIZONA_HEADPHONE_DETECT_1,
605 ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
606 0);
607
597 arizona_extcon_do_magic(info, 0); 608 arizona_extcon_do_magic(info, 0);
598 609
599done:
600 if (id_gpio) 610 if (id_gpio)
601 gpio_set_value_cansleep(id_gpio, 0); 611 gpio_set_value_cansleep(id_gpio, 0);
602 612
@@ -765,7 +775,20 @@ static void arizona_micd_detect(struct work_struct *work)
765 775
766 mutex_lock(&info->lock); 776 mutex_lock(&info->lock);
767 777
768 for (i = 0; i < 10 && !(val & 0x7fc); i++) { 778 /* If the cable was removed while measuring ignore the result */
779 ret = extcon_get_cable_state_(&info->edev, ARIZONA_CABLE_MECHANICAL);
780 if (ret < 0) {
781 dev_err(arizona->dev, "Failed to check cable state: %d\n",
782 ret);
783 mutex_unlock(&info->lock);
784 return;
785 } else if (!ret) {
786 dev_dbg(arizona->dev, "Ignoring MICDET for removed cable\n");
787 mutex_unlock(&info->lock);
788 return;
789 }
790
791 for (i = 0; i < 10 && !(val & MICD_LVL_0_TO_8); i++) {
769 ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val); 792 ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
770 if (ret != 0) { 793 if (ret != 0) {
771 dev_err(arizona->dev, 794 dev_err(arizona->dev,
@@ -784,7 +807,7 @@ static void arizona_micd_detect(struct work_struct *work)
784 } 807 }
785 } 808 }
786 809
787 if (i == 10 && !(val & 0x7fc)) { 810 if (i == 10 && !(val & MICD_LVL_0_TO_8)) {
788 dev_err(arizona->dev, "Failed to get valid MICDET value\n"); 811 dev_err(arizona->dev, "Failed to get valid MICDET value\n");
789 mutex_unlock(&info->lock); 812 mutex_unlock(&info->lock);
790 return; 813 return;
@@ -798,7 +821,7 @@ static void arizona_micd_detect(struct work_struct *work)
798 } 821 }
799 822
800 /* If we got a high impedence we should have a headset, report it. */ 823 /* If we got a high impedence we should have a headset, report it. */
801 if (info->detecting && (val & 0x400)) { 824 if (info->detecting && (val & ARIZONA_MICD_LVL_8)) {
802 arizona_identify_headphone(info); 825 arizona_identify_headphone(info);
803 826
804 ret = extcon_update_state(&info->edev, 827 ret = extcon_update_state(&info->edev,
@@ -827,7 +850,7 @@ static void arizona_micd_detect(struct work_struct *work)
827 * plain headphones. If both polarities report a low 850 * plain headphones. If both polarities report a low
828 * impedence then give up and report headphones. 851 * impedence then give up and report headphones.
829 */ 852 */
830 if (info->detecting && (val & 0x3f8)) { 853 if (info->detecting && (val & MICD_LVL_1_TO_7)) {
831 if (info->jack_flips >= info->micd_num_modes * 10) { 854 if (info->jack_flips >= info->micd_num_modes * 10) {
832 dev_dbg(arizona->dev, "Detected HP/line\n"); 855 dev_dbg(arizona->dev, "Detected HP/line\n");
833 arizona_identify_headphone(info); 856 arizona_identify_headphone(info);
@@ -851,7 +874,7 @@ static void arizona_micd_detect(struct work_struct *work)
851 * If we're still detecting and we detect a short then we've 874 * If we're still detecting and we detect a short then we've
852 * got a headphone. Otherwise it's a button press. 875 * got a headphone. Otherwise it's a button press.
853 */ 876 */
854 if (val & 0x3fc) { 877 if (val & MICD_LVL_0_TO_7) {
855 if (info->mic) { 878 if (info->mic) {
856 dev_dbg(arizona->dev, "Mic button detected\n"); 879 dev_dbg(arizona->dev, "Mic button detected\n");
857 880
@@ -1126,6 +1149,16 @@ static int arizona_extcon_probe(struct platform_device *pdev)
1126 break; 1149 break;
1127 } 1150 }
1128 break; 1151 break;
1152 case WM5110:
1153 switch (arizona->rev) {
1154 case 0 ... 2:
1155 break;
1156 default:
1157 info->micd_clamp = true;
1158 info->hpdet_ip = 2;
1159 break;
1160 }
1161 break;
1129 default: 1162 default:
1130 break; 1163 break;
1131 } 1164 }