[PATCH v3 16/20] ASoC: fsl_micfil: rework quality setting

Shengjiu Wang shengjiu.wang at gmail.com
Thu Apr 7 07:24:37 CEST 2022


On Tue, Apr 5, 2022 at 4:00 PM Sascha Hauer <s.hauer at pengutronix.de> wrote:

> For the quality setting the quality setting register values are directly
> exposed to the kcontrol and thus to userspace. This is unfortunate
> because the register settings contains invalid bit combinations marked
> as "N/A". For userspace it doesn't make much sense to be able to set
> these just to see that the driver responds with "Please make sure you
> select a valid quality." in the kernel log.
>
> Work around this by adding get/set functions for the quality setting.
>
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  sound/soc/fsl/fsl_micfil.c | 109 ++++++++++++++++++++++++++-----------
>  1 file changed, 77 insertions(+), 32 deletions(-)
>
> diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c
> index fd3b168a38661..e28a2e2ba5c97 100644
> --- a/sound/soc/fsl/fsl_micfil.c
> +++ b/sound/soc/fsl/fsl_micfil.c
> @@ -31,6 +31,15 @@
>
>  #define MICFIL_OSR_DEFAULT     16
>
> +enum quality {
> +       QUALITY_HIGH,
> +       QUALITY_MEDIUM,
> +       QUALITY_LOW,
> +       QUALITY_VLOW0,
> +       QUALITY_VLOW1,
> +       QUALITY_VLOW2,
> +};
> +
>  struct fsl_micfil {
>         struct platform_device *pdev;
>         struct regmap *regmap;
> @@ -42,7 +51,7 @@ struct fsl_micfil {
>         unsigned int dataline;
>         char name[32];
>         int irq[MICFIL_IRQ_LINES];
> -       int quality;    /*QUALITY 2-0 bits */
> +       enum quality quality;
>         unsigned int osr;
>  };
>
> @@ -66,29 +75,73 @@ static const struct of_device_id fsl_micfil_dt_ids[] =
> {
>  };
>  MODULE_DEVICE_TABLE(of, fsl_micfil_dt_ids);
>
> -/* Table 5. Quality Modes
> - * Medium      0 0 0
> - * High                0 0 1
> - * Very Low 2  1 0 0
> - * Very Low 1  1 0 1
> - * Very Low 0  1 1 0
> - * Low         1 1 1
> - */
>  static const char * const micfil_quality_select_texts[] = {
> -       "Medium", "High",
> -       "N/A", "N/A",
> -       "VLow2", "VLow1",
> -       "VLow0", "Low",
> +       [QUALITY_HIGH] = "High",
> +       [QUALITY_MEDIUM] = "Medium",
> +       [QUALITY_LOW] = "Low",
> +       [QUALITY_VLOW0] = "VLow0",
> +       [QUALITY_VLOW1] = "Vlow1",
> +       [QUALITY_VLOW2] = "Vlow2",
>  };
>
>  static const struct soc_enum fsl_micfil_quality_enum =
> -       SOC_ENUM_SINGLE(REG_MICFIL_CTRL2,
> -                       MICFIL_CTRL2_QSEL_SHIFT,
> -                       ARRAY_SIZE(micfil_quality_select_texts),
> -                       micfil_quality_select_texts);
> +       SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(micfil_quality_select_texts),
> +                           micfil_quality_select_texts);
>
>  static DECLARE_TLV_DB_SCALE(gain_tlv, 0, 100, 0);
>
> +static int micfil_set_quality(struct fsl_micfil *micfil)
> +{
> +       u32 qsel;
> +
> +       switch (micfil->quality) {
> +       case QUALITY_HIGH:
> +               qsel = MICFIL_QSEL_HIGH_QUALITY;
> +               break;
> +       case QUALITY_MEDIUM:
> +               qsel = MICFIL_QSEL_MEDIUM_QUALITY;
> +               break;
> +       case QUALITY_LOW:
> +               qsel = MICFIL_QSEL_LOW_QUALITY;
> +               break;
> +       case QUALITY_VLOW0:
> +               qsel = MICFIL_QSEL_VLOW0_QUALITY;
> +               break;
> +       case QUALITY_VLOW1:
> +               qsel = MICFIL_QSEL_VLOW1_QUALITY;
> +               break;
> +       case QUALITY_VLOW2:
> +               qsel = MICFIL_QSEL_VLOW2_QUALITY;
> +               break;
> +       }
> +
> +       return regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL2,
> +                                MICFIL_CTRL2_QSEL,
> +                                FIELD_PREP(MICFIL_CTRL2_QSEL, qsel));
>

 Alignment should match open parenthesis?

+}
> +
> +static int micfil_quality_get(struct snd_kcontrol *kcontrol,
> +                            struct snd_ctl_elem_value *ucontrol)
> +{
> +       struct snd_soc_component *cmpnt =
> snd_soc_kcontrol_component(kcontrol);
> +       struct fsl_micfil *micfil = snd_soc_component_get_drvdata(cmpnt);
> +
> +       ucontrol->value.integer.value[0] = micfil->quality;
> +
> +       return 0;
> +}
> +
> +static int micfil_quality_set(struct snd_kcontrol *kcontrol,
> +                             struct snd_ctl_elem_value *ucontrol)
> +{
> +       struct snd_soc_component *cmpnt =
> snd_soc_kcontrol_component(kcontrol);
> +       struct fsl_micfil *micfil = snd_soc_component_get_drvdata(cmpnt);
> +
> +       micfil->quality = ucontrol->value.integer.value[0];
> +
> +       return micfil_set_quality(micfil);
> +}
> +
>  static const struct snd_kcontrol_new fsl_micfil_snd_controls[] = {
>         SOC_SINGLE_SX_TLV("CH0 Volume", REG_MICFIL_OUT_CTRL,
>                           MICFIL_OUTGAIN_CHX_SHIFT(0), 0xF, 0x7, gain_tlv),
> @@ -108,7 +161,7 @@ static const struct snd_kcontrol_new
> fsl_micfil_snd_controls[] = {
>                           MICFIL_OUTGAIN_CHX_SHIFT(7), 0xF, 0x7, gain_tlv),
>         SOC_ENUM_EXT("MICFIL Quality Select",
>                      fsl_micfil_quality_enum,
> -                    snd_soc_get_enum_double, snd_soc_put_enum_double),
> +                    micfil_quality_get, micfil_quality_set),
>  };
>
>  /* The SRES is a self-negated bit which provides the CPU with the
> @@ -208,22 +261,21 @@ static int fsl_set_clock_params(struct device *dev,
> unsigned int rate)
>  {
>         struct fsl_micfil *micfil = dev_get_drvdata(dev);
>         int clk_div = 8;
> +       int osr = MICFIL_OSR_DEFAULT;
>         int ret;
>
> -       ret = clk_set_rate(micfil->mclk, rate * clk_div * micfil->osr * 8);
> +       ret = clk_set_rate(micfil->mclk, rate * clk_div * osr * 8);
>         if (ret)
>                 return ret;
>
> -       /* set CICOSR */
> -       ret = regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL2,
> -                                MICFIL_CTRL2_CICOSR,
> -                                FIELD_PREP(MICFIL_CTRL2_CICOSR, 16 -
> MICFIL_OSR_DEFAULT));
> +       ret = micfil_set_quality(micfil);
>         if (ret)
>                 return ret;
>
>         ret = regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL2,
> -                                MICFIL_CTRL2_CLKDIV,
> -                                FIELD_PREP(MICFIL_CTRL2_CLKDIV, clk_div));
> +                                MICFIL_CTRL2_CLKDIV | MICFIL_CTRL2_CICOSR,
> +                                FIELD_PREP(MICFIL_CTRL2_CLKDIV, clk_div) |
> +                                FIELD_PREP(MICFIL_CTRL2_CICOSR, 16 -
> osr));
>
>         return ret;
>  }
> @@ -276,13 +328,6 @@ static int fsl_micfil_dai_probe(struct snd_soc_dai
> *cpu_dai)
>         struct fsl_micfil *micfil = dev_get_drvdata(cpu_dai->dev);
>         int ret;
>
> -       /* set qsel to medium */
> -       ret = regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL2,
> -                       MICFIL_CTRL2_QSEL,
> -                       FIELD_PREP(MICFIL_CTRL2_QSEL,
> MICFIL_QSEL_MEDIUM_QUALITY));
> -       if (ret)
> -               return ret;
> -
>

The default qsel is medium,  with this change, it seems the default qsel is
changed to
HIGH. it is better to keep medium in this patch.


>         /* set default gain to max_gain */
>         regmap_write(micfil->regmap, REG_MICFIL_OUT_CTRL, 0x77777777);
>
> --
> 2.30.2
>
>


More information about the Alsa-devel mailing list