Commit 7d785025 authored by Peter Ujfalusi's avatar Peter Ujfalusi Committed by Mark Brown

ASoC: tas2552: Implement startup/stop sequence as per TRM

Certain sequence need to be followed in order to have smooth power up and
power down performance.
Execute this sequence via DAPM_POST widget.
Remove patching the RESERVED_0D register at probe time since it has to be
handled every time when we stop or start the amplifier.
In order to be able to execute the sequence at the correct time, the driver
need to request to ignore the pmdown time.
Signed-off-by: default avatarPeter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent dd6ae3bc
...@@ -46,7 +46,7 @@ static struct reg_default tas2552_reg_defs[] = { ...@@ -46,7 +46,7 @@ static struct reg_default tas2552_reg_defs[] = {
{TAS2552_PDM_CFG, 0x01}, {TAS2552_PDM_CFG, 0x01},
{TAS2552_PGA_GAIN, 0x00}, {TAS2552_PGA_GAIN, 0x00},
{TAS2552_BOOST_PT_CTRL, 0x0f}, {TAS2552_BOOST_PT_CTRL, 0x0f},
{TAS2552_RESERVED_0D, 0x00}, {TAS2552_RESERVED_0D, 0xbe},
{TAS2552_LIMIT_RATE_HYS, 0x08}, {TAS2552_LIMIT_RATE_HYS, 0x08},
{TAS2552_CFG_2, 0xef}, {TAS2552_CFG_2, 0xef},
{TAS2552_SER_CTRL_1, 0x00}, {TAS2552_SER_CTRL_1, 0x00},
...@@ -83,6 +83,29 @@ struct tas2552_data { ...@@ -83,6 +83,29 @@ struct tas2552_data {
unsigned int tdm_delay; unsigned int tdm_delay;
}; };
static int tas2552_post_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
snd_soc_write(codec, TAS2552_RESERVED_0D, 0xc0);
snd_soc_update_bits(codec, TAS2552_LIMIT_RATE_HYS, (1 << 5),
(1 << 5));
snd_soc_update_bits(codec, TAS2552_CFG_2, 1, 0);
snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_SWS, 0);
break;
case SND_SOC_DAPM_POST_PMD:
snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_SWS,
TAS2552_SWS);
snd_soc_update_bits(codec, TAS2552_CFG_2, 1, 1);
snd_soc_update_bits(codec, TAS2552_LIMIT_RATE_HYS, (1 << 5), 0);
snd_soc_write(codec, TAS2552_RESERVED_0D, 0xbe);
break;
}
return 0;
}
/* Input mux controls */ /* Input mux controls */
static const char * const tas2552_input_texts[] = { static const char * const tas2552_input_texts[] = {
...@@ -105,6 +128,7 @@ static const struct snd_soc_dapm_widget tas2552_dapm_widgets[] = ...@@ -105,6 +128,7 @@ static const struct snd_soc_dapm_widget tas2552_dapm_widgets[] =
SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_OUT_DRV("ClassD", TAS2552_CFG_2, 7, 0, NULL, 0), SND_SOC_DAPM_OUT_DRV("ClassD", TAS2552_CFG_2, 7, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("PLL", TAS2552_CFG_2, 3, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("PLL", TAS2552_CFG_2, 3, 0, NULL, 0),
SND_SOC_DAPM_POST("Post Event", tas2552_post_event),
SND_SOC_DAPM_OUTPUT("OUT") SND_SOC_DAPM_OUTPUT("OUT")
}; };
...@@ -413,10 +437,6 @@ static const struct snd_kcontrol_new tas2552_snd_controls[] = { ...@@ -413,10 +437,6 @@ static const struct snd_kcontrol_new tas2552_snd_controls[] = {
TAS2552_PGA_GAIN, 0, 0x1f, 0, dac_tlv), TAS2552_PGA_GAIN, 0, 0x1f, 0, dac_tlv),
}; };
static const struct reg_default tas2552_init_regs[] = {
{ TAS2552_RESERVED_0D, 0xc0 },
};
static int tas2552_codec_probe(struct snd_soc_codec *codec) static int tas2552_codec_probe(struct snd_soc_codec *codec)
{ {
struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec); struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
...@@ -443,7 +463,7 @@ static int tas2552_codec_probe(struct snd_soc_codec *codec) ...@@ -443,7 +463,7 @@ static int tas2552_codec_probe(struct snd_soc_codec *codec)
goto probe_fail; goto probe_fail;
} }
snd_soc_write(codec, TAS2552_CFG_1, TAS2552_MUTE); snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_MUTE, TAS2552_MUTE);
snd_soc_write(codec, TAS2552_CFG_3, TAS2552_I2S_OUT_SEL | snd_soc_write(codec, TAS2552_CFG_3, TAS2552_I2S_OUT_SEL |
TAS2552_DIN_SRC_SEL_AVG_L_R | TAS2552_88_96KHZ); TAS2552_DIN_SRC_SEL_AVG_L_R | TAS2552_88_96KHZ);
snd_soc_write(codec, TAS2552_DOUT, TAS2552_PDM_DATA_I); snd_soc_write(codec, TAS2552_DOUT, TAS2552_PDM_DATA_I);
...@@ -451,21 +471,11 @@ static int tas2552_codec_probe(struct snd_soc_codec *codec) ...@@ -451,21 +471,11 @@ static int tas2552_codec_probe(struct snd_soc_codec *codec)
snd_soc_write(codec, TAS2552_BOOST_PT_CTRL, TAS2552_APT_DELAY_200 | snd_soc_write(codec, TAS2552_BOOST_PT_CTRL, TAS2552_APT_DELAY_200 |
TAS2552_APT_THRESH_2_1_7); TAS2552_APT_THRESH_2_1_7);
ret = regmap_register_patch(tas2552->regmap, tas2552_init_regs,
ARRAY_SIZE(tas2552_init_regs));
if (ret != 0) {
dev_err(codec->dev, "Failed to write init registers: %d\n",
ret);
goto patch_fail;
}
snd_soc_write(codec, TAS2552_CFG_2, TAS2552_BOOST_EN | snd_soc_write(codec, TAS2552_CFG_2, TAS2552_BOOST_EN |
TAS2552_APT_EN | TAS2552_LIM_EN); TAS2552_APT_EN | TAS2552_LIM_EN);
return 0; return 0;
patch_fail:
pm_runtime_put(codec->dev);
probe_fail: probe_fail:
if (tas2552->enable_gpio) if (tas2552->enable_gpio)
gpiod_set_value(tas2552->enable_gpio, 0); gpiod_set_value(tas2552->enable_gpio, 0);
...@@ -527,6 +537,8 @@ static struct snd_soc_codec_driver soc_codec_dev_tas2552 = { ...@@ -527,6 +537,8 @@ static struct snd_soc_codec_driver soc_codec_dev_tas2552 = {
.remove = tas2552_codec_remove, .remove = tas2552_codec_remove,
.suspend = tas2552_suspend, .suspend = tas2552_suspend,
.resume = tas2552_resume, .resume = tas2552_resume,
.ignore_pmdown_time = true,
.controls = tas2552_snd_controls, .controls = tas2552_snd_controls,
.num_controls = ARRAY_SIZE(tas2552_snd_controls), .num_controls = ARRAY_SIZE(tas2552_snd_controls),
.dapm_widgets = tas2552_dapm_widgets, .dapm_widgets = tas2552_dapm_widgets,
......
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