ASoC: es8328: error handling and resume fixes

Merge series from Hsieh Hung-En <hungen3108@gmail.com>:

This series fixes some issues and improves robustness in the es8328
driver.
This commit is contained in:
Mark Brown 2026-02-02 23:31:48 +00:00
commit d83039b5dc
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0

View File

@ -163,12 +163,11 @@ static int es8328_put_deemph(struct snd_kcontrol *kcontrol,
if (es8328->deemph == deemph)
return 0;
es8328->deemph = deemph;
ret = es8328_set_deemph(component);
if (ret < 0)
return ret;
es8328->deemph = deemph;
return 1;
}
@ -530,7 +529,9 @@ static int es8328_hw_params(struct snd_pcm_substream *substream,
return ret;
es8328->playback_fs = params_rate(params);
es8328_set_deemph(component);
ret = es8328_set_deemph(component);
if (ret < 0)
return ret;
} else {
ret = snd_soc_component_update_bits(component, ES8328_ADCCONTROL4,
ES8328_ADCCONTROL4_ADCWL_MASK,
@ -591,21 +592,26 @@ static int es8328_set_dai_fmt(struct snd_soc_dai *codec_dai,
{
struct snd_soc_component *component = codec_dai->component;
struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component);
int ret;
u8 dac_mode = 0;
u8 adc_mode = 0;
switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
case SND_SOC_DAIFMT_CBP_CFP:
/* Master serial port mode, with BCLK generated automatically */
snd_soc_component_update_bits(component, ES8328_MASTERMODE,
ES8328_MASTERMODE_MSC,
ES8328_MASTERMODE_MSC);
ret = snd_soc_component_update_bits(component, ES8328_MASTERMODE,
ES8328_MASTERMODE_MSC,
ES8328_MASTERMODE_MSC);
if (ret < 0)
return ret;
es8328->provider = true;
break;
case SND_SOC_DAIFMT_CBC_CFC:
/* Slave serial port mode */
snd_soc_component_update_bits(component, ES8328_MASTERMODE,
ES8328_MASTERMODE_MSC, 0);
ret = snd_soc_component_update_bits(component, ES8328_MASTERMODE,
ES8328_MASTERMODE_MSC, 0);
if (ret < 0)
return ret;
es8328->provider = false;
break;
default:
@ -634,10 +640,17 @@ static int es8328_set_dai_fmt(struct snd_soc_dai *codec_dai,
if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF)
return -EINVAL;
snd_soc_component_update_bits(component, ES8328_DACCONTROL1,
ES8328_DACCONTROL1_DACFORMAT_MASK, dac_mode);
snd_soc_component_update_bits(component, ES8328_ADCCONTROL4,
ES8328_ADCCONTROL4_ADCFORMAT_MASK, adc_mode);
ret = snd_soc_component_update_bits(component, ES8328_DACCONTROL1,
ES8328_DACCONTROL1_DACFORMAT_MASK,
dac_mode);
if (ret < 0)
return ret;
ret = snd_soc_component_update_bits(component, ES8328_ADCCONTROL4,
ES8328_ADCCONTROL4_ADCFORMAT_MASK,
adc_mode);
if (ret < 0)
return ret;
return 0;
}
@ -646,6 +659,7 @@ static int es8328_set_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level)
{
struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
int ret;
switch (level) {
case SND_SOC_BIAS_ON:
@ -653,43 +667,56 @@ static int es8328_set_bias_level(struct snd_soc_component *component,
case SND_SOC_BIAS_PREPARE:
/* VREF, VMID=2x50k, digital enabled */
snd_soc_component_write(component, ES8328_CHIPPOWER, 0);
snd_soc_component_update_bits(component, ES8328_CONTROL1,
ES8328_CONTROL1_VMIDSEL_MASK |
ES8328_CONTROL1_ENREF,
ES8328_CONTROL1_VMIDSEL_50k |
ES8328_CONTROL1_ENREF);
ret = snd_soc_component_write(component, ES8328_CHIPPOWER, 0);
if (ret < 0)
return ret;
ret = snd_soc_component_update_bits(component, ES8328_CONTROL1,
ES8328_CONTROL1_VMIDSEL_MASK |
ES8328_CONTROL1_ENREF,
ES8328_CONTROL1_VMIDSEL_50k |
ES8328_CONTROL1_ENREF);
if (ret < 0)
return ret;
break;
case SND_SOC_BIAS_STANDBY:
if (snd_soc_dapm_get_bias_level(dapm) == SND_SOC_BIAS_OFF) {
snd_soc_component_update_bits(component, ES8328_CONTROL1,
ES8328_CONTROL1_VMIDSEL_MASK |
ES8328_CONTROL1_ENREF,
ES8328_CONTROL1_VMIDSEL_5k |
ES8328_CONTROL1_ENREF);
ret = snd_soc_component_update_bits(component, ES8328_CONTROL1,
ES8328_CONTROL1_VMIDSEL_MASK |
ES8328_CONTROL1_ENREF,
ES8328_CONTROL1_VMIDSEL_5k |
ES8328_CONTROL1_ENREF);
if (ret < 0)
return ret;
/* Charge caps */
msleep(100);
}
snd_soc_component_write(component, ES8328_CONTROL2,
ES8328_CONTROL2_OVERCURRENT_ON |
ES8328_CONTROL2_THERMAL_SHUTDOWN_ON);
ret = snd_soc_component_write(component, ES8328_CONTROL2,
ES8328_CONTROL2_OVERCURRENT_ON |
ES8328_CONTROL2_THERMAL_SHUTDOWN_ON);
if (ret < 0)
return ret;
/* VREF, VMID=2*500k, digital stopped */
snd_soc_component_update_bits(component, ES8328_CONTROL1,
ES8328_CONTROL1_VMIDSEL_MASK |
ES8328_CONTROL1_ENREF,
ES8328_CONTROL1_VMIDSEL_500k |
ES8328_CONTROL1_ENREF);
ret = snd_soc_component_update_bits(component, ES8328_CONTROL1,
ES8328_CONTROL1_VMIDSEL_MASK |
ES8328_CONTROL1_ENREF,
ES8328_CONTROL1_VMIDSEL_500k |
ES8328_CONTROL1_ENREF);
if (ret < 0)
return ret;
break;
case SND_SOC_BIAS_OFF:
snd_soc_component_update_bits(component, ES8328_CONTROL1,
ES8328_CONTROL1_VMIDSEL_MASK |
ES8328_CONTROL1_ENREF,
0);
ret = snd_soc_component_update_bits(component, ES8328_CONTROL1,
ES8328_CONTROL1_VMIDSEL_MASK |
ES8328_CONTROL1_ENREF,
0);
if (ret < 0)
return ret;
break;
}
return 0;
@ -744,12 +771,9 @@ static int es8328_suspend(struct snd_soc_component *component)
static int es8328_resume(struct snd_soc_component *component)
{
struct regmap *regmap = dev_get_regmap(component->dev, NULL);
struct es8328_priv *es8328;
struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component);
int ret;
es8328 = snd_soc_component_get_drvdata(component);
ret = clk_prepare_enable(es8328->clk);
if (ret) {
dev_err(component->dev, "unable to enable clock\n");
@ -760,17 +784,23 @@ static int es8328_resume(struct snd_soc_component *component)
es8328->supplies);
if (ret) {
dev_err(component->dev, "unable to enable regulators\n");
return ret;
goto err_clk;
}
regcache_mark_dirty(regmap);
ret = regcache_sync(regmap);
regcache_mark_dirty(es8328->regmap);
ret = regcache_sync(es8328->regmap);
if (ret) {
dev_err(component->dev, "unable to sync regcache\n");
return ret;
goto err_regulators;
}
return 0;
err_regulators:
regulator_bulk_disable(ARRAY_SIZE(es8328->supplies), es8328->supplies);
err_clk:
clk_disable_unprepare(es8328->clk);
return ret;
}
static int es8328_component_probe(struct snd_soc_component *component)