Commit 6bba63b6 authored by Misael Lopez Cruz's avatar Misael Lopez Cruz Committed by Peter Ujfalusi

ASoC: twl6040: Remove pll and headset mode dependency

Remove dependency between pll (hppll, lppll) and headset power
mode (low-power, high-performance), as headset power mode can
be used with any pll.

A new control is created to allow headset power mode configuration
from userspace. Changing headset power mode during earpiece related
usecases is not propagated down to the codec as earpiece requires
HS DAC in HP mode.
Signed-off-by: default avatarMisael Lopez Cruz <misael.lopez@ti.com>
Signed-off-by: default avatarPeter Ujfalusi <peter.ujfalusi@ti.com>
Acked-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent e17e4ab8
...@@ -79,6 +79,8 @@ struct twl6040_data { ...@@ -79,6 +79,8 @@ struct twl6040_data {
int codec_powered; int codec_powered;
int pll; int pll;
int non_lp; int non_lp;
int hs_power_mode;
int hs_power_mode_locked;
unsigned int clk_in; unsigned int clk_in;
unsigned int sysclk; unsigned int sysclk;
struct snd_pcm_hw_constraint_list *sysclk_constraints; struct snd_pcm_hw_constraint_list *sysclk_constraints;
...@@ -651,15 +653,26 @@ static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w, ...@@ -651,15 +653,26 @@ static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w,
{ {
struct snd_soc_codec *codec = w->codec; struct snd_soc_codec *codec = w->codec;
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
int ret = 0;
if (SND_SOC_DAPM_EVENT_ON(event)) if (SND_SOC_DAPM_EVENT_ON(event)) {
priv->non_lp++; priv->non_lp++;
else if (!strcmp(w->name, "Earphone Driver")) {
/* Earphone doesn't support low power mode */
priv->hs_power_mode_locked = 1;
ret = headset_power_mode(codec, 1);
}
} else {
priv->non_lp--; priv->non_lp--;
if (!strcmp(w->name, "Earphone Driver")) {
priv->hs_power_mode_locked = 0;
ret = headset_power_mode(codec, priv->hs_power_mode);
}
}
msleep(1); msleep(1);
return 0; return ret;
} }
static void twl6040_hs_jack_report(struct snd_soc_codec *codec, static void twl6040_hs_jack_report(struct snd_soc_codec *codec,
...@@ -964,6 +977,43 @@ static const struct snd_kcontrol_new hfr_mux_controls = ...@@ -964,6 +977,43 @@ static const struct snd_kcontrol_new hfr_mux_controls =
static const struct snd_kcontrol_new ep_driver_switch_controls = static const struct snd_kcontrol_new ep_driver_switch_controls =
SOC_DAPM_SINGLE("Switch", TWL6040_REG_EARCTL, 0, 1, 0); SOC_DAPM_SINGLE("Switch", TWL6040_REG_EARCTL, 0, 1, 0);
/* Headset power mode */
static const char *twl6040_headset_power_texts[] = {
"Low-Power", "High-Perfomance",
};
static const struct soc_enum twl6040_headset_power_enum =
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl6040_headset_power_texts),
twl6040_headset_power_texts);
static int twl6040_headset_power_get_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = priv->hs_power_mode;
return 0;
}
static int twl6040_headset_power_put_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
int high_perf = ucontrol->value.enumerated.item[0];
int ret = 0;
if (!priv->hs_power_mode_locked)
ret = headset_power_mode(codec, high_perf);
if (!ret)
priv->hs_power_mode = high_perf;
return ret;
}
static const struct snd_kcontrol_new twl6040_snd_controls[] = { static const struct snd_kcontrol_new twl6040_snd_controls[] = {
/* Capture gains */ /* Capture gains */
SOC_DOUBLE_TLV("Capture Preamplifier Volume", SOC_DOUBLE_TLV("Capture Preamplifier Volume",
...@@ -982,6 +1032,10 @@ static const struct snd_kcontrol_new twl6040_snd_controls[] = { ...@@ -982,6 +1032,10 @@ static const struct snd_kcontrol_new twl6040_snd_controls[] = {
TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv), TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv),
SOC_SINGLE_TLV("Earphone Playback Volume", SOC_SINGLE_TLV("Earphone Playback Volume",
TWL6040_REG_EARCTL, 1, 0xF, 1, ep_tlv), TWL6040_REG_EARCTL, 1, 0xF, 1, ep_tlv),
SOC_ENUM_EXT("Headset Power Mode", twl6040_headset_power_enum,
twl6040_headset_power_get_enum,
twl6040_headset_power_put_enum),
}; };
static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
...@@ -1339,7 +1393,6 @@ static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai, ...@@ -1339,7 +1393,6 @@ static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai,
if (ret) if (ret)
return ret; return ret;
headset_power_mode(codec, 0);
priv->sysclk_constraints = &lp_constraints; priv->sysclk_constraints = &lp_constraints;
break; break;
case TWL6040_SYSCLK_SEL_HPPLL: case TWL6040_SYSCLK_SEL_HPPLL:
...@@ -1348,7 +1401,6 @@ static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai, ...@@ -1348,7 +1401,6 @@ static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai,
if (ret) if (ret)
return ret; return ret;
headset_power_mode(codec, 1);
priv->sysclk_constraints = &hp_constraints; priv->sysclk_constraints = &hp_constraints;
break; break;
default: default:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment