Use the type SNDRV_CTL_ELEM_TYPE_IEC958 for iec958 channel status
controls, the original type will cause mixer-test to iterate all 32bit
values, which costs a lot of time. And using IEC958 type can reduce the
control numbers.
Also enable pm runtime before updating registers to make the regmap cache
data align with the value in hardware.
Fixes: 955ac624058f ("ASoC: fsl_easrc: Add EASRC ASoC CPU DAI drivers")
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
---
sound/soc/fsl/fsl_easrc.c | 108 ++++++++++++++++++++++++++------------
1 file changed, 74 insertions(+), 34 deletions(-)
diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
index 3086cb758beb..a6c643a4d51e 100644
--- a/sound/soc/fsl/fsl_easrc.c
+++ b/sound/soc/fsl/fsl_easrc.c
@@ -78,17 +78,47 @@ static int fsl_easrc_iec958_get_bits(struct snd_kcontrol *kcontrol,
return 0;
}
+static int fsl_easrc_iec958_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+ uinfo->count = 1;
+ return 0;
+}
+
static int fsl_easrc_get_reg(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct soc_mreg_control *mc =
(struct soc_mreg_control *)kcontrol->private_value;
- unsigned int regval;
+ struct fsl_asrc *easrc = snd_soc_component_get_drvdata(component);
+ unsigned int *regval = (unsigned int *)ucontrol->value.iec958.status;
+ int ret;
- regval = snd_soc_component_read(component, mc->regbase);
+ ret = regmap_read(easrc->regmap, REG_EASRC_CS0(mc->regbase), ®val[0]);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(easrc->regmap, REG_EASRC_CS1(mc->regbase), ®val[1]);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(easrc->regmap, REG_EASRC_CS2(mc->regbase), ®val[2]);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(easrc->regmap, REG_EASRC_CS3(mc->regbase), ®val[3]);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(easrc->regmap, REG_EASRC_CS4(mc->regbase), ®val[4]);
+ if (ret)
+ return ret;
- ucontrol->value.integer.value[0] = regval;
+ ret = regmap_read(easrc->regmap, REG_EASRC_CS5(mc->regbase), ®val[5]);
+ if (ret)
+ return ret;
return 0;
}
@@ -100,22 +130,52 @@ static int fsl_easrc_set_reg(struct snd_kcontrol *kcontrol,
struct soc_mreg_control *mc =
(struct soc_mreg_control *)kcontrol->private_value;
struct fsl_asrc *easrc = snd_soc_component_get_drvdata(component);
- unsigned int regval = ucontrol->value.integer.value[0];
- bool changed;
+ unsigned int *regval = (unsigned int *)ucontrol->value.iec958.status;
int ret;
- ret = regmap_update_bits_check(easrc->regmap, mc->regbase,
- GENMASK(31, 0), regval, &changed);
- if (ret != 0)
+ ret = pm_runtime_resume_and_get(component->dev);
+ if (ret)
return ret;
- return changed;
+ ret = regmap_update_bits(easrc->regmap, REG_EASRC_CS0(mc->regbase),
+ GENMASK(31, 0), regval[0]);
+ if (ret != 0)
+ goto err;
+
+ ret = regmap_update_bits(easrc->regmap, REG_EASRC_CS1(mc->regbase),
+ GENMASK(31, 0), regval[1]);
+ if (ret != 0)
+ goto err;
+
+ ret = regmap_update_bits(easrc->regmap, REG_EASRC_CS2(mc->regbase),
+ GENMASK(31, 0), regval[2]);
+ if (ret != 0)
+ goto err;
+
+ ret = regmap_update_bits(easrc->regmap, REG_EASRC_CS3(mc->regbase),
+ GENMASK(31, 0), regval[3]);
+ if (ret != 0)
+ goto err;
+
+ ret = regmap_update_bits(easrc->regmap, REG_EASRC_CS4(mc->regbase),
+ GENMASK(31, 0), regval[4]);
+ if (ret != 0)
+ goto err;
+
+ ret = regmap_update_bits(easrc->regmap, REG_EASRC_CS5(mc->regbase),
+ GENMASK(31, 0), regval[5]);
+ if (ret != 0)
+ goto err;
+err:
+ pm_runtime_put_autosuspend(component->dev);
+
+ return ret;
}
#define SOC_SINGLE_REG_RW(xname, xreg) \
{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = (xname), \
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
- .info = snd_soc_info_xr_sx, .get = fsl_easrc_get_reg, \
+ .info = fsl_easrc_iec958_info, .get = fsl_easrc_get_reg, \
.put = fsl_easrc_set_reg, \
.private_value = (unsigned long)&(struct soc_mreg_control) \
{ .regbase = xreg, .regcount = 1, .nbits = 32, \
@@ -146,30 +206,10 @@ static const struct snd_kcontrol_new fsl_easrc_snd_controls[] = {
SOC_SINGLE_VAL_RW("Context 2 IEC958 Bits Per Sample", 2),
SOC_SINGLE_VAL_RW("Context 3 IEC958 Bits Per Sample", 3),
- SOC_SINGLE_REG_RW("Context 0 IEC958 CS0", REG_EASRC_CS0(0)),
- SOC_SINGLE_REG_RW("Context 1 IEC958 CS0", REG_EASRC_CS0(1)),
- SOC_SINGLE_REG_RW("Context 2 IEC958 CS0", REG_EASRC_CS0(2)),
- SOC_SINGLE_REG_RW("Context 3 IEC958 CS0", REG_EASRC_CS0(3)),
- SOC_SINGLE_REG_RW("Context 0 IEC958 CS1", REG_EASRC_CS1(0)),
- SOC_SINGLE_REG_RW("Context 1 IEC958 CS1", REG_EASRC_CS1(1)),
- SOC_SINGLE_REG_RW("Context 2 IEC958 CS1", REG_EASRC_CS1(2)),
- SOC_SINGLE_REG_RW("Context 3 IEC958 CS1", REG_EASRC_CS1(3)),
- SOC_SINGLE_REG_RW("Context 0 IEC958 CS2", REG_EASRC_CS2(0)),
- SOC_SINGLE_REG_RW("Context 1 IEC958 CS2", REG_EASRC_CS2(1)),
- SOC_SINGLE_REG_RW("Context 2 IEC958 CS2", REG_EASRC_CS2(2)),
- SOC_SINGLE_REG_RW("Context 3 IEC958 CS2", REG_EASRC_CS2(3)),
- SOC_SINGLE_REG_RW("Context 0 IEC958 CS3", REG_EASRC_CS3(0)),
- SOC_SINGLE_REG_RW("Context 1 IEC958 CS3", REG_EASRC_CS3(1)),
- SOC_SINGLE_REG_RW("Context 2 IEC958 CS3", REG_EASRC_CS3(2)),
- SOC_SINGLE_REG_RW("Context 3 IEC958 CS3", REG_EASRC_CS3(3)),
- SOC_SINGLE_REG_RW("Context 0 IEC958 CS4", REG_EASRC_CS4(0)),
- SOC_SINGLE_REG_RW("Context 1 IEC958 CS4", REG_EASRC_CS4(1)),
- SOC_SINGLE_REG_RW("Context 2 IEC958 CS4", REG_EASRC_CS4(2)),
- SOC_SINGLE_REG_RW("Context 3 IEC958 CS4", REG_EASRC_CS4(3)),
- SOC_SINGLE_REG_RW("Context 0 IEC958 CS5", REG_EASRC_CS5(0)),
- SOC_SINGLE_REG_RW("Context 1 IEC958 CS5", REG_EASRC_CS5(1)),
- SOC_SINGLE_REG_RW("Context 2 IEC958 CS5", REG_EASRC_CS5(2)),
- SOC_SINGLE_REG_RW("Context 3 IEC958 CS5", REG_EASRC_CS5(3)),
+ SOC_SINGLE_REG_RW("Context 0 IEC958 CS", 0),
+ SOC_SINGLE_REG_RW("Context 1 IEC958 CS", 1),
+ SOC_SINGLE_REG_RW("Context 2 IEC958 CS", 2),
+ SOC_SINGLE_REG_RW("Context 3 IEC958 CS", 3),
};
/*
--
2.34.1
On Mon, Mar 30, 2026 at 07:25:55PM +0800, Shengjiu Wang wrote: > Use the type SNDRV_CTL_ELEM_TYPE_IEC958 for iec958 channel status > controls, the original type will cause mixer-test to iterate all 32bit > values, which costs a lot of time. And using IEC958 type can reduce the > control numbers. > Also enable pm runtime before updating registers to make the regmap cache > data align with the value in hardware. > @@ -100,22 +130,52 @@ static int fsl_easrc_set_reg(struct snd_kcontrol *kcontrol, > - ret = regmap_update_bits_check(easrc->regmap, mc->regbase, > - GENMASK(31, 0), regval, &changed); > - if (ret != 0) > + ret = pm_runtime_resume_and_get(component->dev); > + if (ret) > return ret; > > - return changed; > + ret = regmap_update_bits(easrc->regmap, REG_EASRC_CS0(mc->regbase), > + GENMASK(31, 0), regval[0]); > + if (ret != 0) > + goto err; This drops all the checking for changed values that we used to do so we won't generate notifications to userspace.
On Mon, Mar 30, 2026 at 9:23 PM Mark Brown <broonie@kernel.org> wrote: > > On Mon, Mar 30, 2026 at 07:25:55PM +0800, Shengjiu Wang wrote: > > Use the type SNDRV_CTL_ELEM_TYPE_IEC958 for iec958 channel status > > controls, the original type will cause mixer-test to iterate all 32bit > > values, which costs a lot of time. And using IEC958 type can reduce the > > control numbers. > > > Also enable pm runtime before updating registers to make the regmap cache > > data align with the value in hardware. > > > @@ -100,22 +130,52 @@ static int fsl_easrc_set_reg(struct snd_kcontrol *kcontrol, > > > - ret = regmap_update_bits_check(easrc->regmap, mc->regbase, > > - GENMASK(31, 0), regval, &changed); > > - if (ret != 0) > > + ret = pm_runtime_resume_and_get(component->dev); > > + if (ret) > > return ret; > > > > - return changed; > > + ret = regmap_update_bits(easrc->regmap, REG_EASRC_CS0(mc->regbase), > > + GENMASK(31, 0), regval[0]); > > + if (ret != 0) > > + goto err; > > This drops all the checking for changed values that we used to do so we > won't generate notifications to userspace. Yes, as the type is changed to IEC958, the notification is not acquired by the mixer-test. Do we still need to add the notification? best regards Shengjiu Wang
On Tue, Mar 31, 2026 at 09:58:22AM +0800, Shengjiu Wang wrote: > On Mon, Mar 30, 2026 at 9:23 PM Mark Brown <broonie@kernel.org> wrote: > > This drops all the checking for changed values that we used to do so we > > won't generate notifications to userspace. > Yes, as the type is changed to IEC958, the notification is not > acquired by the mixer-test. > Do we still need to add the notification? Yes, it should be there for all controls - it's just that mixer-test doesn't have support for the IEC958 controls wired up so it's mostly skipping them. Someone should add that! :P
On Tue, Mar 31, 2026 at 9:19 PM Mark Brown <broonie@kernel.org> wrote: > > On Tue, Mar 31, 2026 at 09:58:22AM +0800, Shengjiu Wang wrote: > > On Mon, Mar 30, 2026 at 9:23 PM Mark Brown <broonie@kernel.org> wrote: > > > > This drops all the checking for changed values that we used to do so we > > > won't generate notifications to userspace. > > > Yes, as the type is changed to IEC958, the notification is not > > acquired by the mixer-test. > > > Do we still need to add the notification? > > Yes, it should be there for all controls - it's just that mixer-test > doesn't have support for the IEC958 controls wired up so it's mostly > skipping them. Someone should add that! :P Thanks. I will add the notification back in the next version. Best regards Shengjiu Wang
© 2016 - 2026 Red Hat, Inc.