Skip to content

Commit 733a763

Browse files
pfiserbroonie
authored andcommitted
ASoC: tlv320aic3x: Fix class-D initialization for tlv320aic3007
The problem of having class-D initialization sequence in probe using regmap_register_patch() is that it will do hardware register writes immediately after being called as it bypasses regcache. Afterwards, in aic3x_init() we also perform codec soft reset, rendering class-D init sequence pointless. This issue is even more apparent when using reset GPIO line, since in that case class-D amplifier initialization fails with "Failed to init class D: -5" message as codec is already held in reset state after requesting the reset GPIO and hence hardware I/O fails with -EIO errno. Thus move class-D amplifier initialization sequence from probe function to aic3x_set_power() just before the usual regcache sync. Use bypassed regmap_multi_reg_write_bypassed() function to make sure, class-D init sequence is performed in proper order as described in the datasheet. Signed-off-by: Primoz Fiser <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent ba0c67d commit 733a763

1 file changed

Lines changed: 14 additions & 18 deletions

File tree

sound/soc/codecs/tlv320aic3x.c

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,16 @@ static const struct reg_default aic3x_reg[] = {
121121
{ 108, 0x00 }, { 109, 0x00 },
122122
};
123123

124+
static const struct reg_sequence aic3007_class_d[] = {
125+
/* Class-D speaker driver init; datasheet p. 46 */
126+
{ AIC3X_PAGE_SELECT, 0x0D },
127+
{ 0xD, 0x0D },
128+
{ 0x8, 0x5C },
129+
{ 0x8, 0x5D },
130+
{ 0x8, 0x5C },
131+
{ AIC3X_PAGE_SELECT, 0x00 },
132+
};
133+
124134
static bool aic3x_volatile_reg(struct device *dev, unsigned int reg)
125135
{
126136
switch (reg) {
@@ -1393,6 +1403,10 @@ static int aic3x_set_power(struct snd_soc_component *component, int power)
13931403
gpiod_set_value(aic3x->gpio_reset, 0);
13941404
}
13951405

1406+
if (aic3x->model == AIC3X_MODEL_3007)
1407+
regmap_multi_reg_write_bypassed(aic3x->regmap, aic3007_class_d,
1408+
ARRAY_SIZE(aic3007_class_d));
1409+
13961410
/* Sync reg_cache with the hardware */
13971411
regcache_cache_only(aic3x->regmap, false);
13981412
regcache_sync(aic3x->regmap);
@@ -1723,17 +1737,6 @@ static void aic3x_configure_ocmv(struct device *dev, struct aic3x_priv *aic3x)
17231737
}
17241738
}
17251739

1726-
1727-
static const struct reg_sequence aic3007_class_d[] = {
1728-
/* Class-D speaker driver init; datasheet p. 46 */
1729-
{ AIC3X_PAGE_SELECT, 0x0D },
1730-
{ 0xD, 0x0D },
1731-
{ 0x8, 0x5C },
1732-
{ 0x8, 0x5D },
1733-
{ 0x8, 0x5C },
1734-
{ AIC3X_PAGE_SELECT, 0x00 },
1735-
};
1736-
17371740
int aic3x_probe(struct device *dev, struct regmap *regmap, kernel_ulong_t driver_data)
17381741
{
17391742
struct aic3x_priv *aic3x;
@@ -1823,13 +1826,6 @@ int aic3x_probe(struct device *dev, struct regmap *regmap, kernel_ulong_t driver
18231826

18241827
aic3x_configure_ocmv(dev, aic3x);
18251828

1826-
if (aic3x->model == AIC3X_MODEL_3007) {
1827-
ret = regmap_register_patch(aic3x->regmap, aic3007_class_d,
1828-
ARRAY_SIZE(aic3007_class_d));
1829-
if (ret != 0)
1830-
dev_err(dev, "Failed to init class D: %d\n", ret);
1831-
}
1832-
18331829
ret = devm_snd_soc_register_component(dev, &soc_component_dev_aic3x, &aic3x_dai, 1);
18341830
if (ret)
18351831
return ret;

0 commit comments

Comments
 (0)