aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8994.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2010-11-30 12:03:39 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-12-01 06:47:29 -0500
commit131d81061eba5ffd436b5d132530ac5205b16892 (patch)
tree16e0df193581d982c541fd531347e07fb360059b /sound/soc/codecs/wm8994.c
parentb2822a8c22d13bc8c441e1c0492baa40ae974b51 (diff)
ASoC: Allow user-specified WM8958 multiband compressor configurations
The paramters of the WM8958 multiband compressor can be tuned by the user for their system using a graphical configuration tool on the host. Allow the user to specify a set of such paramters in platform data and select between them at runtime. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'sound/soc/codecs/wm8994.c')
-rw-r--r--sound/soc/codecs/wm8994.c84
1 files changed, 82 insertions, 2 deletions
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 51f5cf16b425..59d361145b15 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -92,6 +92,11 @@ struct wm8994_priv {
92 int retune_mobile_cfg[WM8994_NUM_EQ]; 92 int retune_mobile_cfg[WM8994_NUM_EQ];
93 struct soc_enum retune_mobile_enum; 93 struct soc_enum retune_mobile_enum;
94 94
95 /* Platform dependant MBC configuration */
96 int mbc_cfg;
97 const char **mbc_texts;
98 struct soc_enum mbc_enum;
99
95 struct wm8994_micdet micdet[2]; 100 struct wm8994_micdet micdet[2];
96 101
97 wm8958_micdet_cb jack_cb; 102 wm8958_micdet_cb jack_cb;
@@ -543,8 +548,9 @@ static const struct soc_enum aif2dacr_src =
543static void wm8958_mbc_apply(struct snd_soc_codec *codec, int mbc, int start) 548static void wm8958_mbc_apply(struct snd_soc_codec *codec, int mbc, int start)
544{ 549{
545 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); 550 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
551 struct wm8994_pdata *pdata = wm8994->pdata;
546 int pwr_reg = snd_soc_read(codec, WM8994_POWER_MANAGEMENT_5); 552 int pwr_reg = snd_soc_read(codec, WM8994_POWER_MANAGEMENT_5);
547 int ena, reg, aif; 553 int ena, reg, aif, i;
548 554
549 switch (mbc) { 555 switch (mbc) {
550 case 0: 556 case 0:
@@ -587,7 +593,20 @@ static void wm8958_mbc_apply(struct snd_soc_codec *codec, int mbc, int start)
587 snd_soc_update_bits(codec, WM8958_DSP2_PROGRAM, 593 snd_soc_update_bits(codec, WM8958_DSP2_PROGRAM,
588 WM8958_DSP2_ENA, WM8958_DSP2_ENA); 594 WM8958_DSP2_ENA, WM8958_DSP2_ENA);
589 595
590 /* TODO: Apply any user specified MBC settings */ 596 /* If we've got user supplied MBC settings use them */
597 if (pdata && pdata->num_mbc_cfgs) {
598 struct wm8958_mbc_cfg *cfg
599 = &pdata->mbc_cfgs[wm8994->mbc_cfg];
600
601 for (i = 0; i < ARRAY_SIZE(cfg->coeff_regs); i++)
602 snd_soc_write(codec, i + WM8958_MBC_BAND_1_K_1,
603 cfg->coeff_regs[i]);
604
605 for (i = 0; i < ARRAY_SIZE(cfg->cutoff_regs); i++)
606 snd_soc_write(codec,
607 i + WM8958_MBC_BAND_2_LOWER_CUTOFF_C1_1,
608 cfg->cutoff_regs[i]);
609 }
591 610
592 /* Run the DSP */ 611 /* Run the DSP */
593 snd_soc_write(codec, WM8958_DSP2_EXECCONTROL, 612 snd_soc_write(codec, WM8958_DSP2_EXECCONTROL,
@@ -648,6 +667,39 @@ static int wm8958_aif_ev(struct snd_soc_dapm_widget *w,
648 return 0; 667 return 0;
649} 668}
650 669
670static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol,
671 struct snd_ctl_elem_value *ucontrol)
672{
673 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
674 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
675 struct wm8994_pdata *pdata = wm8994->pdata;
676 int value = ucontrol->value.integer.value[0];
677 int reg;
678
679 /* Don't allow on the fly reconfiguration */
680 reg = snd_soc_read(codec, WM8994_CLOCKING_1);
681 if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
682 return -EBUSY;
683
684 if (value >= pdata->num_mbc_cfgs)
685 return -EINVAL;
686
687 wm8994->mbc_cfg = value;
688
689 return 0;
690}
691
692static int wm8958_get_mbc_enum(struct snd_kcontrol *kcontrol,
693 struct snd_ctl_elem_value *ucontrol)
694{
695 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
696 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
697
698 ucontrol->value.enumerated.item[0] = wm8994->mbc_cfg;
699
700 return 0;
701}
702
651static int wm8958_mbc_info(struct snd_kcontrol *kcontrol, 703static int wm8958_mbc_info(struct snd_kcontrol *kcontrol,
652 struct snd_ctl_elem_info *uinfo) 704 struct snd_ctl_elem_info *uinfo)
653{ 705{
@@ -2539,6 +2591,34 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
2539 dev_dbg(codec->dev, "%d ReTune Mobile configurations\n", 2591 dev_dbg(codec->dev, "%d ReTune Mobile configurations\n",
2540 pdata->num_retune_mobile_cfgs); 2592 pdata->num_retune_mobile_cfgs);
2541 2593
2594 if (pdata->num_mbc_cfgs) {
2595 struct snd_kcontrol_new control[] = {
2596 SOC_ENUM_EXT("MBC Mode", wm8994->mbc_enum,
2597 wm8958_get_mbc_enum, wm8958_put_mbc_enum),
2598 };
2599
2600 /* We need an array of texts for the enum API */
2601 wm8994->mbc_texts = kmalloc(sizeof(char *)
2602 * pdata->num_mbc_cfgs, GFP_KERNEL);
2603 if (!wm8994->mbc_texts) {
2604 dev_err(wm8994->codec->dev,
2605 "Failed to allocate %d MBC config texts\n",
2606 pdata->num_mbc_cfgs);
2607 return;
2608 }
2609
2610 for (i = 0; i < pdata->num_mbc_cfgs; i++)
2611 wm8994->mbc_texts[i] = pdata->mbc_cfgs[i].name;
2612
2613 wm8994->mbc_enum.max = pdata->num_mbc_cfgs;
2614 wm8994->mbc_enum.texts = wm8994->mbc_texts;
2615
2616 ret = snd_soc_add_controls(wm8994->codec, control, 1);
2617 if (ret != 0)
2618 dev_err(wm8994->codec->dev,
2619 "Failed to add MBC mode controls: %d\n", ret);
2620 }
2621
2542 if (pdata->num_retune_mobile_cfgs) 2622 if (pdata->num_retune_mobile_cfgs)
2543 wm8994_handle_retune_mobile_pdata(wm8994); 2623 wm8994_handle_retune_mobile_pdata(wm8994);
2544 else 2624 else