ASoC: wm_hubs: Factor out class W management
Since the analogue portions of the checks for class W are the same over all the devices factor out these checks into wm_hubs and while we're at it also use wm_hubs_dac_hp_direct() to enable class W optimisations on more paths. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
This commit is contained in:
@@ -218,7 +218,6 @@ struct wm8993_priv {
|
||||
unsigned int sysclk_rate;
|
||||
unsigned int fs;
|
||||
unsigned int bclk;
|
||||
int class_w_users;
|
||||
unsigned int fll_fref;
|
||||
unsigned int fll_fout;
|
||||
int fll_src;
|
||||
@@ -824,82 +823,6 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* When used with DAC outputs only the WM8993 charge pump supports
|
||||
* operation in class W mode, providing very low power consumption
|
||||
* when used with digital sources. Enable and disable this mode
|
||||
* automatically depending on the mixer configuration.
|
||||
*
|
||||
* Currently the only supported paths are the direct DAC->headphone
|
||||
* paths (which provide minimum power consumption anyway).
|
||||
*/
|
||||
static int class_w_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
|
||||
struct snd_soc_dapm_widget *widget = wlist->widgets[0];
|
||||
struct snd_soc_codec *codec = widget->codec;
|
||||
struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
/* Turn it off if we're using the main output mixer */
|
||||
if (ucontrol->value.integer.value[0] == 0) {
|
||||
if (wm8993->class_w_users == 0) {
|
||||
dev_dbg(codec->dev, "Disabling Class W\n");
|
||||
snd_soc_update_bits(codec, WM8993_CLASS_W_0,
|
||||
WM8993_CP_DYN_FREQ |
|
||||
WM8993_CP_DYN_V,
|
||||
0);
|
||||
}
|
||||
wm8993->class_w_users++;
|
||||
}
|
||||
|
||||
/* Implement the change */
|
||||
ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
|
||||
|
||||
/* Enable it if we're using the direct DAC path */
|
||||
if (ucontrol->value.integer.value[0] == 1) {
|
||||
if (wm8993->class_w_users == 1) {
|
||||
dev_dbg(codec->dev, "Enabling Class W\n");
|
||||
snd_soc_update_bits(codec, WM8993_CLASS_W_0,
|
||||
WM8993_CP_DYN_FREQ |
|
||||
WM8993_CP_DYN_V,
|
||||
WM8993_CP_DYN_FREQ |
|
||||
WM8993_CP_DYN_V);
|
||||
}
|
||||
wm8993->class_w_users--;
|
||||
}
|
||||
|
||||
dev_dbg(codec->dev, "Indirect DAC use count now %d\n",
|
||||
wm8993->class_w_users);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define SOC_DAPM_ENUM_W(xname, xenum) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_enum_double, \
|
||||
.get = snd_soc_dapm_get_enum_double, \
|
||||
.put = class_w_put, \
|
||||
.private_value = (unsigned long)&xenum }
|
||||
|
||||
static const char *hp_mux_text[] = {
|
||||
"Mixer",
|
||||
"DAC",
|
||||
};
|
||||
|
||||
static const struct soc_enum hpl_enum =
|
||||
SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER1, 8, 2, hp_mux_text);
|
||||
|
||||
static const struct snd_kcontrol_new hpl_mux =
|
||||
SOC_DAPM_ENUM_W("Left Headphone Mux", hpl_enum);
|
||||
|
||||
static const struct soc_enum hpr_enum =
|
||||
SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER2, 8, 2, hp_mux_text);
|
||||
|
||||
static const struct snd_kcontrol_new hpr_mux =
|
||||
SOC_DAPM_ENUM_W("Right Headphone Mux", hpr_enum);
|
||||
|
||||
static const struct snd_kcontrol_new left_speaker_mixer[] = {
|
||||
SOC_DAPM_SINGLE("Input Switch", WM8993_SPEAKER_MIXER, 7, 1, 0),
|
||||
SOC_DAPM_SINGLE("IN1LP Switch", WM8993_SPEAKER_MIXER, 5, 1, 0),
|
||||
@@ -986,8 +909,8 @@ SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &sidetoner_mux),
|
||||
SND_SOC_DAPM_DAC("DACL", NULL, WM8993_POWER_MANAGEMENT_3, 1, 0),
|
||||
SND_SOC_DAPM_DAC("DACR", NULL, WM8993_POWER_MANAGEMENT_3, 0, 0),
|
||||
|
||||
SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux),
|
||||
SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux),
|
||||
SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &wm_hubs_hpl_mux),
|
||||
SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &wm_hubs_hpr_mux),
|
||||
|
||||
SND_SOC_DAPM_MIXER("SPKL", WM8993_POWER_MANAGEMENT_3, 8, 0,
|
||||
left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)),
|
||||
@@ -1577,9 +1500,6 @@ static int wm8993_probe(struct snd_soc_codec *codec)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* By default we're using the output mixers */
|
||||
wm8993->class_w_users = 2;
|
||||
|
||||
/* Latch volume update bits and default ZC on */
|
||||
snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME,
|
||||
WM8993_DAC_VU, WM8993_DAC_VU);
|
||||
|
Reference in New Issue
Block a user