Commit 570c70a6 authored by Fabio Estevam's avatar Fabio Estevam Committed by Mark Brown

ASoC: sgtl5000: Allow LRCLK pad drive strength to be changed

Introduce the "lrclk-strength" property to allow LRCLK pad drive strength
to be changed via device tree.

When running a stress playback loop test on a mx6dl wandboard channel
swap can be noticed on about 10% of the times.

While debugging this issue I noticed that when probing the SGTL5000
LRCLK pin with the scope the swap did not happen. After removing
the probe the swap started to happen again.

After changing the LRCLK pad drive strength to the maximum value the
issue is gone.

Same fix works on a mx6dl Colibri board as well.
Signed-off-by: default avatarFabio Estevam <fabio.estevam@nxp.com>
Tested-by: default avatarMax Krummenacher <max.krummenacher@toradex.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent a5de5b74
...@@ -26,6 +26,15 @@ Optional properties: ...@@ -26,6 +26,15 @@ Optional properties:
If this node is not mentioned or the value is unknown, then If this node is not mentioned or the value is unknown, then
the value is set to 1.25V. the value is set to 1.25V.
- lrclk-strength: the LRCLK pad strength. Possible values are:
0, 1, 2 and 3 as per the table below:
VDDIO 1.8V 2.5V 3.3V
0 = Disable
1 = 1.66 mA 2.87 mA 4.02 mA
2 = 3.33 mA 5.74 mA 8.03 mA
3 = 4.99 mA 8.61 mA 12.05 mA
Example: Example:
codec: sgtl5000@0a { codec: sgtl5000@0a {
......
...@@ -99,6 +99,13 @@ enum sgtl5000_micbias_resistor { ...@@ -99,6 +99,13 @@ enum sgtl5000_micbias_resistor {
SGTL5000_MICBIAS_8K = 8, SGTL5000_MICBIAS_8K = 8,
}; };
enum {
I2S_LRCLK_STRENGTH_DISABLE,
I2S_LRCLK_STRENGTH_LOW,
I2S_LRCLK_STRENGTH_MEDIUM,
I2S_LRCLK_STRENGTH_HIGH,
};
/* sgtl5000 private structure in codec */ /* sgtl5000 private structure in codec */
struct sgtl5000_priv { struct sgtl5000_priv {
int sysclk; /* sysclk rate */ int sysclk; /* sysclk rate */
...@@ -111,6 +118,7 @@ struct sgtl5000_priv { ...@@ -111,6 +118,7 @@ struct sgtl5000_priv {
int revision; int revision;
u8 micbias_resistor; u8 micbias_resistor;
u8 micbias_voltage; u8 micbias_voltage;
u8 lrclk_strength;
}; };
/* /*
...@@ -1089,6 +1097,7 @@ static int sgtl5000_enable_regulators(struct i2c_client *client) ...@@ -1089,6 +1097,7 @@ static int sgtl5000_enable_regulators(struct i2c_client *client)
static int sgtl5000_probe(struct snd_soc_codec *codec) static int sgtl5000_probe(struct snd_soc_codec *codec)
{ {
int ret; int ret;
u16 reg;
struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
/* power up sgtl5000 */ /* power up sgtl5000 */
...@@ -1118,7 +1127,8 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) ...@@ -1118,7 +1127,8 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)
SGTL5000_DAC_MUTE_RIGHT | SGTL5000_DAC_MUTE_RIGHT |
SGTL5000_DAC_MUTE_LEFT); SGTL5000_DAC_MUTE_LEFT);
snd_soc_write(codec, SGTL5000_CHIP_PAD_STRENGTH, 0x015f); reg = ((sgtl5000->lrclk_strength) << SGTL5000_PAD_I2S_LRCLK_SHIFT | 0x5f);
snd_soc_write(codec, SGTL5000_CHIP_PAD_STRENGTH, reg);
snd_soc_write(codec, SGTL5000_CHIP_ANA_CTRL, snd_soc_write(codec, SGTL5000_CHIP_ANA_CTRL,
SGTL5000_HP_ZCD_EN | SGTL5000_HP_ZCD_EN |
...@@ -1347,6 +1357,13 @@ static int sgtl5000_i2c_probe(struct i2c_client *client, ...@@ -1347,6 +1357,13 @@ static int sgtl5000_i2c_probe(struct i2c_client *client,
} }
} }
sgtl5000->lrclk_strength = I2S_LRCLK_STRENGTH_LOW;
if (!of_property_read_u32(np, "lrclk-strength", &value)) {
if (value > I2S_LRCLK_STRENGTH_HIGH)
value = I2S_LRCLK_STRENGTH_LOW;
sgtl5000->lrclk_strength = value;
}
/* Ensure sgtl5000 will start with sane register values */ /* Ensure sgtl5000 will start with sane register values */
sgtl5000_fill_defaults(client); sgtl5000_fill_defaults(client);
......
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