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

ASoC: wm5110: Add additional analogue input enable for early revs

Earlier revisions of the wm5110/8280 silicon require a slightly more
complex procedure to enable analogue inputs. This patch adds this into
the driver.

Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Charles Keepax and committed by
Mark Brown
ccaadda3 a54e22f4

+163 -24
+163 -24
sound/soc/codecs/wm5110.c
··· 38 38 struct wm5110_priv { 39 39 struct arizona_priv core; 40 40 struct arizona_fll fll[2]; 41 + 42 + unsigned int in_value; 43 + int in_pre_pending; 44 + int in_post_pending; 45 + 46 + unsigned int in_pga_cache[6]; 41 47 }; 42 48 43 49 static const struct wm_adsp_region wm5110_dsp1_regions[] = { ··· 434 428 return ret; 435 429 } 436 430 431 + static int wm5110_in_pga_get(struct snd_kcontrol *kcontrol, 432 + struct snd_ctl_elem_value *ucontrol) 433 + { 434 + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); 435 + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); 436 + struct snd_soc_card *card = dapm->card; 437 + int ret; 438 + 439 + /* 440 + * PGA Volume is also used as part of the enable sequence, so 441 + * usage of it should be avoided whilst that is running. 442 + */ 443 + mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 444 + 445 + ret = snd_soc_get_volsw_range(kcontrol, ucontrol); 446 + 447 + mutex_unlock(&card->dapm_mutex); 448 + 449 + return ret; 450 + } 451 + 452 + static int wm5110_in_pga_put(struct snd_kcontrol *kcontrol, 453 + struct snd_ctl_elem_value *ucontrol) 454 + { 455 + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); 456 + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); 457 + struct snd_soc_card *card = dapm->card; 458 + int ret; 459 + 460 + /* 461 + * PGA Volume is also used as part of the enable sequence, so 462 + * usage of it should be avoided whilst that is running. 463 + */ 464 + mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 465 + 466 + ret = snd_soc_put_volsw_range(kcontrol, ucontrol); 467 + 468 + mutex_unlock(&card->dapm_mutex); 469 + 470 + return ret; 471 + } 472 + 473 + static int wm5110_in_analog_ev(struct snd_soc_dapm_widget *w, 474 + struct snd_kcontrol *kcontrol, int event) 475 + { 476 + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 477 + struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); 478 + struct wm5110_priv *wm5110 = snd_soc_codec_get_drvdata(codec); 479 + struct arizona *arizona = priv->arizona; 480 + unsigned int reg, mask; 481 + struct reg_sequence analog_seq[] = { 482 + { 0x80, 0x3 }, 483 + { 0x35d, 0 }, 484 + { 0x80, 0x0 }, 485 + }; 486 + 487 + reg = ARIZONA_IN1L_CONTROL + ((w->shift ^ 0x1) * 4); 488 + mask = ARIZONA_IN1L_PGA_VOL_MASK; 489 + 490 + switch (event) { 491 + case SND_SOC_DAPM_WILL_PMU: 492 + wm5110->in_value |= 0x3 << ((w->shift ^ 0x1) * 2); 493 + wm5110->in_pre_pending++; 494 + wm5110->in_post_pending++; 495 + return 0; 496 + case SND_SOC_DAPM_PRE_PMU: 497 + wm5110->in_pga_cache[w->shift] = snd_soc_read(codec, reg); 498 + 499 + snd_soc_update_bits(codec, reg, mask, 500 + 0x40 << ARIZONA_IN1L_PGA_VOL_SHIFT); 501 + 502 + wm5110->in_pre_pending--; 503 + if (wm5110->in_pre_pending == 0) { 504 + analog_seq[1].def = wm5110->in_value; 505 + regmap_multi_reg_write_bypassed(arizona->regmap, 506 + analog_seq, 507 + ARRAY_SIZE(analog_seq)); 508 + 509 + msleep(55); 510 + 511 + wm5110->in_value = 0; 512 + } 513 + 514 + break; 515 + case SND_SOC_DAPM_POST_PMU: 516 + snd_soc_update_bits(codec, reg, mask, 517 + wm5110->in_pga_cache[w->shift]); 518 + 519 + wm5110->in_post_pending--; 520 + if (wm5110->in_post_pending == 0) 521 + regmap_multi_reg_write_bypassed(arizona->regmap, 522 + analog_seq, 523 + ARRAY_SIZE(analog_seq)); 524 + break; 525 + default: 526 + break; 527 + } 528 + 529 + return 0; 530 + } 531 + 532 + static int wm5110_in_ev(struct snd_soc_dapm_widget *w, 533 + struct snd_kcontrol *kcontrol, int event) 534 + { 535 + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 536 + struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); 537 + struct arizona *arizona = priv->arizona; 538 + 539 + switch (arizona->rev) { 540 + case 0 ... 4: 541 + if (arizona_input_analog(codec, w->shift)) 542 + wm5110_in_analog_ev(w, kcontrol, event); 543 + 544 + break; 545 + default: 546 + break; 547 + } 548 + 549 + return arizona_in_ev(w, kcontrol, event); 550 + } 551 + 437 552 static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); 438 553 static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); 439 554 static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); ··· 581 454 SOC_ENUM("IN3 OSR", arizona_in_dmic_osr[2]), 582 455 SOC_ENUM("IN4 OSR", arizona_in_dmic_osr[3]), 583 456 584 - SOC_SINGLE_RANGE_TLV("IN1L Volume", ARIZONA_IN1L_CONTROL, 585 - ARIZONA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), 586 - SOC_SINGLE_RANGE_TLV("IN1R Volume", ARIZONA_IN1R_CONTROL, 587 - ARIZONA_IN1R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), 588 - SOC_SINGLE_RANGE_TLV("IN2L Volume", ARIZONA_IN2L_CONTROL, 589 - ARIZONA_IN2L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), 590 - SOC_SINGLE_RANGE_TLV("IN2R Volume", ARIZONA_IN2R_CONTROL, 591 - ARIZONA_IN2R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), 592 - SOC_SINGLE_RANGE_TLV("IN3L Volume", ARIZONA_IN3L_CONTROL, 593 - ARIZONA_IN3L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), 594 - SOC_SINGLE_RANGE_TLV("IN3R Volume", ARIZONA_IN3R_CONTROL, 595 - ARIZONA_IN3R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), 457 + SOC_SINGLE_RANGE_EXT_TLV("IN1L Volume", ARIZONA_IN1L_CONTROL, 458 + ARIZONA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, 459 + wm5110_in_pga_get, wm5110_in_pga_put, ana_tlv), 460 + SOC_SINGLE_RANGE_EXT_TLV("IN1R Volume", ARIZONA_IN1R_CONTROL, 461 + ARIZONA_IN1R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, 462 + wm5110_in_pga_get, wm5110_in_pga_put, ana_tlv), 463 + SOC_SINGLE_RANGE_EXT_TLV("IN2L Volume", ARIZONA_IN2L_CONTROL, 464 + ARIZONA_IN2L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, 465 + wm5110_in_pga_get, wm5110_in_pga_put, ana_tlv), 466 + SOC_SINGLE_RANGE_EXT_TLV("IN2R Volume", ARIZONA_IN2R_CONTROL, 467 + ARIZONA_IN2R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, 468 + wm5110_in_pga_get, wm5110_in_pga_put, ana_tlv), 469 + SOC_SINGLE_RANGE_EXT_TLV("IN3L Volume", ARIZONA_IN3L_CONTROL, 470 + ARIZONA_IN3L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, 471 + wm5110_in_pga_get, wm5110_in_pga_put, ana_tlv), 472 + SOC_SINGLE_RANGE_EXT_TLV("IN3R Volume", ARIZONA_IN3R_CONTROL, 473 + ARIZONA_IN3R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, 474 + wm5110_in_pga_get, wm5110_in_pga_put, ana_tlv), 596 475 597 476 SOC_ENUM("IN HPF Cutoff Frequency", arizona_in_hpf_cut_enum), 598 477 ··· 1029 896 SND_SOC_DAPM_OUTPUT("DRC2 Signal Activity"), 1030 897 1031 898 SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, 1032 - 0, NULL, 0, arizona_in_ev, 899 + 0, NULL, 0, wm5110_in_ev, 1033 900 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | 1034 - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), 901 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 902 + SND_SOC_DAPM_WILL_PMU), 1035 903 SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT, 1036 - 0, NULL, 0, arizona_in_ev, 904 + 0, NULL, 0, wm5110_in_ev, 1037 905 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | 1038 - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), 906 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 907 + SND_SOC_DAPM_WILL_PMU), 1039 908 SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT, 1040 - 0, NULL, 0, arizona_in_ev, 909 + 0, NULL, 0, wm5110_in_ev, 1041 910 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | 1042 - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), 911 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 912 + SND_SOC_DAPM_WILL_PMU), 1043 913 SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT, 1044 - 0, NULL, 0, arizona_in_ev, 914 + 0, NULL, 0, wm5110_in_ev, 1045 915 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | 1046 - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), 916 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 917 + SND_SOC_DAPM_WILL_PMU), 1047 918 SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT, 1048 - 0, NULL, 0, arizona_in_ev, 919 + 0, NULL, 0, wm5110_in_ev, 1049 920 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | 1050 - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), 921 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 922 + SND_SOC_DAPM_WILL_PMU), 1051 923 SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT, 1052 - 0, NULL, 0, arizona_in_ev, 924 + 0, NULL, 0, wm5110_in_ev, 1053 925 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | 1054 - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), 926 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 927 + SND_SOC_DAPM_WILL_PMU), 1055 928 SND_SOC_DAPM_PGA_E("IN4L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4L_ENA_SHIFT, 1056 929 0, NULL, 0, arizona_in_ev, 1057 930 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |