aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-04-26 17:08:50 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-04-27 13:42:12 -0400
commit04de57c15354252ac816154ad66666240883fc52 (patch)
tree0c46642ca40c48b1b2c99e553039717809a030fa /sound/soc/codecs
parentc340304dd8855a61a2e1bcdd5bde6b90408481a9 (diff)
ASoC: wm_hubs: Enable class W for output mixer paths
Class W can be used for any path where only data from the DAC is routed to the headphones. Currently we only enable it when the direct DAC to headphone path is used but it can also be enabled for paths that go via the output mixer providing the DAC is the only input to the output mixer. Implement support for this, including updates to the class W status when the output mixer configuration is changed. This also allows us to enable the DC servo optimisations for DAC to headphone paths where the output mixer is used. In general the direct DAC path is still preferred as this will offer better performance on most wm_hubs devices but these additional paths can simplify use case management. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r--sound/soc/codecs/wm_hubs.c61
1 files changed, 40 insertions, 21 deletions
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index 9106334216c4..484ec22ca6f4 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -122,7 +122,6 @@ static bool wm_hubs_dac_hp_direct(struct snd_soc_codec *codec)
122 return false; 122 return false;
123 } else { 123 } else {
124 dev_vdbg(codec->dev, "HPL connected to mixer\n"); 124 dev_vdbg(codec->dev, "HPL connected to mixer\n");
125 return false;
126 } 125 }
127 } else { 126 } else {
128 dev_vdbg(codec->dev, "HPL connected to DAC\n"); 127 dev_vdbg(codec->dev, "HPL connected to DAC\n");
@@ -136,7 +135,6 @@ static bool wm_hubs_dac_hp_direct(struct snd_soc_codec *codec)
136 return false; 135 return false;
137 } else { 136 } else {
138 dev_vdbg(codec->dev, "HPR connected to mixer\n"); 137 dev_vdbg(codec->dev, "HPR connected to mixer\n");
139 return false;
140 } 138 }
141 } else { 139 } else {
142 dev_vdbg(codec->dev, "HPR connected to DAC\n"); 140 dev_vdbg(codec->dev, "HPR connected to DAC\n");
@@ -584,15 +582,36 @@ void wm_hubs_update_class_w(struct snd_soc_codec *codec)
584} 582}
585EXPORT_SYMBOL_GPL(wm_hubs_update_class_w); 583EXPORT_SYMBOL_GPL(wm_hubs_update_class_w);
586 584
585#define WM_HUBS_SINGLE_W(xname, reg, shift, max, invert) \
586{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
587 .info = snd_soc_info_volsw, \
588 .get = snd_soc_dapm_get_volsw, .put = class_w_put_volsw, \
589 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
590
591static int class_w_put_volsw(struct snd_kcontrol *kcontrol,
592 struct snd_ctl_elem_value *ucontrol)
593{
594 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
595 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
596 struct snd_soc_codec *codec = widget->codec;
597 int ret;
598
599 ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol);
600
601 wm_hubs_update_class_w(codec);
602
603 return ret;
604}
605
587#define WM_HUBS_ENUM_W(xname, xenum) \ 606#define WM_HUBS_ENUM_W(xname, xenum) \
588{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 607{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
589 .info = snd_soc_info_enum_double, \ 608 .info = snd_soc_info_enum_double, \
590 .get = snd_soc_dapm_get_enum_double, \ 609 .get = snd_soc_dapm_get_enum_double, \
591 .put = class_w_put, \ 610 .put = class_w_put_double, \
592 .private_value = (unsigned long)&xenum } 611 .private_value = (unsigned long)&xenum }
593 612
594static int class_w_put(struct snd_kcontrol *kcontrol, 613static int class_w_put_double(struct snd_kcontrol *kcontrol,
595 struct snd_ctl_elem_value *ucontrol) 614 struct snd_ctl_elem_value *ucontrol)
596{ 615{
597 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 616 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
598 struct snd_soc_dapm_widget *widget = wlist->widgets[0]; 617 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
@@ -656,25 +675,25 @@ SOC_DAPM_SINGLE("IN1R Switch", WM8993_INPUT_MIXER4, 5, 1, 0),
656}; 675};
657 676
658static const struct snd_kcontrol_new left_output_mixer[] = { 677static const struct snd_kcontrol_new left_output_mixer[] = {
659SOC_DAPM_SINGLE("Right Input Switch", WM8993_OUTPUT_MIXER1, 7, 1, 0), 678WM_HUBS_SINGLE_W("Right Input Switch", WM8993_OUTPUT_MIXER1, 7, 1, 0),
660SOC_DAPM_SINGLE("Left Input Switch", WM8993_OUTPUT_MIXER1, 6, 1, 0), 679WM_HUBS_SINGLE_W("Left Input Switch", WM8993_OUTPUT_MIXER1, 6, 1, 0),
661SOC_DAPM_SINGLE("IN2RN Switch", WM8993_OUTPUT_MIXER1, 5, 1, 0), 680WM_HUBS_SINGLE_W("IN2RN Switch", WM8993_OUTPUT_MIXER1, 5, 1, 0),
662SOC_DAPM_SINGLE("IN2LN Switch", WM8993_OUTPUT_MIXER1, 4, 1, 0), 681WM_HUBS_SINGLE_W("IN2LN Switch", WM8993_OUTPUT_MIXER1, 4, 1, 0),
663SOC_DAPM_SINGLE("IN2LP Switch", WM8993_OUTPUT_MIXER1, 1, 1, 0), 682WM_HUBS_SINGLE_W("IN2LP Switch", WM8993_OUTPUT_MIXER1, 1, 1, 0),
664SOC_DAPM_SINGLE("IN1R Switch", WM8993_OUTPUT_MIXER1, 3, 1, 0), 683WM_HUBS_SINGLE_W("IN1R Switch", WM8993_OUTPUT_MIXER1, 3, 1, 0),
665SOC_DAPM_SINGLE("IN1L Switch", WM8993_OUTPUT_MIXER1, 2, 1, 0), 684WM_HUBS_SINGLE_W("IN1L Switch", WM8993_OUTPUT_MIXER1, 2, 1, 0),
666SOC_DAPM_SINGLE("DAC Switch", WM8993_OUTPUT_MIXER1, 0, 1, 0), 685WM_HUBS_SINGLE_W("DAC Switch", WM8993_OUTPUT_MIXER1, 0, 1, 0),
667}; 686};
668 687
669static const struct snd_kcontrol_new right_output_mixer[] = { 688static const struct snd_kcontrol_new right_output_mixer[] = {
670SOC_DAPM_SINGLE("Left Input Switch", WM8993_OUTPUT_MIXER2, 7, 1, 0), 689WM_HUBS_SINGLE_W("Left Input Switch", WM8993_OUTPUT_MIXER2, 7, 1, 0),
671SOC_DAPM_SINGLE("Right Input Switch", WM8993_OUTPUT_MIXER2, 6, 1, 0), 690WM_HUBS_SINGLE_W("Right Input Switch", WM8993_OUTPUT_MIXER2, 6, 1, 0),
672SOC_DAPM_SINGLE("IN2LN Switch", WM8993_OUTPUT_MIXER2, 5, 1, 0), 691WM_HUBS_SINGLE_W("IN2LN Switch", WM8993_OUTPUT_MIXER2, 5, 1, 0),
673SOC_DAPM_SINGLE("IN2RN Switch", WM8993_OUTPUT_MIXER2, 4, 1, 0), 692WM_HUBS_SINGLE_W("IN2RN Switch", WM8993_OUTPUT_MIXER2, 4, 1, 0),
674SOC_DAPM_SINGLE("IN1L Switch", WM8993_OUTPUT_MIXER2, 3, 1, 0), 693WM_HUBS_SINGLE_W("IN1L Switch", WM8993_OUTPUT_MIXER2, 3, 1, 0),
675SOC_DAPM_SINGLE("IN1R Switch", WM8993_OUTPUT_MIXER2, 2, 1, 0), 694WM_HUBS_SINGLE_W("IN1R Switch", WM8993_OUTPUT_MIXER2, 2, 1, 0),
676SOC_DAPM_SINGLE("IN2RP Switch", WM8993_OUTPUT_MIXER2, 1, 1, 0), 695WM_HUBS_SINGLE_W("IN2RP Switch", WM8993_OUTPUT_MIXER2, 1, 1, 0),
677SOC_DAPM_SINGLE("DAC Switch", WM8993_OUTPUT_MIXER2, 0, 1, 0), 696WM_HUBS_SINGLE_W("DAC Switch", WM8993_OUTPUT_MIXER2, 0, 1, 0),
678}; 697};
679 698
680static const struct snd_kcontrol_new earpiece_mixer[] = { 699static const struct snd_kcontrol_new earpiece_mixer[] = {