[alsa-devel] [PATCH 002/002] ASoC: Replace max98090 Device Driver

Mark Brown broonie at opensource.wolfsonmicro.com
Thu Jan 17 03:53:33 CET 2013


On Mon, Jan 14, 2013 at 07:13:30AM -0800, Jerry Wong wrote:

> I have updated most per the review comments, except...
> "External MIC Mux" is a mux with 0=power down, and exists in DAPM as well
> "Digital Sidetone Source", with a master SHDN has no power impact, so was left out of DAPM

Sidetone should have an impact on routing though?  DAPM needs routing to
do power.

> "Quick Setup System Clock" was just a question what they do... they override the
>  clock settings for common use cases.
> "VCM bandgap reference", with a master SHDN has no power impact, so was left out of DAPM
> 

Please have this sort of discussion in line with the previous review -
discuss why you don't agree with the feedback rather than just sending a
new patch.  That tends to be less time consuming and it's easier to
follow the discusssion.

> +static const char * max98090_extmic_mux_text[] = { "MIC1", "MIC2" };
> +
> +static const struct soc_enum max98090_extmic_mux_enum =
> +       SOC_ENUM_SINGLE(M98090_REG_CFG_LINE, M98090_EXTMIC_SHIFT,
> +               ARRAY_SIZE(max98090_extmic_mux_text),
> +               max98090_extmic_mux_text);

This looks like routing control which I'd expect to be in DAPM - I'd not
expect duplication between DAPM and non-DAPM to work very well.

> +static const char * max98090_mixg_text[] = { "Normal", "6dB" };

> +static const struct soc_enum max98090_mixg135_enum =
> +       SOC_ENUM_SINGLE(M98090_REG_LVL_LINE, M98090_MIXG135_SHIFT,
> +               ARRAY_SIZE(max98090_mixg_text), max98090_mixg_text);
> +
> +static const struct soc_enum max98090_mixg246_enum =
> +       SOC_ENUM_SINGLE(M98090_REG_LVL_LINE, M98090_MIXT246_SHIFT,
> +               ARRAY_SIZE(max98090_mixg_text), max98090_mixg_text);

This looks like it should be a volume control with two steps of 0dB and
6dB?

> +static const char * max98090_enableddisabled_text[] =
> +       { "Disabled", "Enabled" };
> +static const char * max98090_enableddisabled_inv_text[] =
> +       { "Enabled", "Disabled" };
> +/* Note: Inverted Logic (0 = Enabled) */
> +
> +static const struct soc_enum max98090_eqclpn_enum =
> +       SOC_ENUM_SINGLE(M98090_REG_DAI_LVL_EQ, M98090_DAI_LVL_EQCLPN_SHIFT,
> +               ARRAY_SIZE(max98090_enableddisabled_inv_text),
> +               max98090_enableddisabled_inv_text);

These look like they should be Switch controls (which will help UIs
render them).

> +static const struct snd_kcontrol_new max98090_snd_controls[] = {
> +       SOC_SINGLE("MIC Bias VCM Bandgap", M98090_REG_BIAS_CNTL,
> +               M98090_VCM_MODE_SHIFT, M98090_VCM_MODE_NUM - 1, 0),

Why is this a user visible control?

> +       SOC_SINGLE("Quick Setup Sample Rate", M98090_REG_QCFG_RATE,
> +               M98090_SR_ALL_SHIFT, M98090_SR_ALL_NUM - 1, 0),
> +       SOC_SINGLE("Quick Setup DAI Interface", M98090_REG_QCFG_DAI,
> +               M98090_DAI_ALL_SHIFT, M98090_DAI_ALL_NUM - 1, 0),
> +       SOC_SINGLE("Quick Setup DAC Path", M98090_REG_QCFG_DAC,
> +               M98090_DIG2_ALL_SHIFT, M98090_DIG2_ALL_NUM - 1, 0),
> +       SOC_SINGLE("Quick Setup MIC/Direct ADC", M98090_REG_QCFG_MIC_PATH,
> +               M98090_MIC_ALL_SHIFT, M98090_MIC_ALL_NUM - 1, 0),
> +       SOC_SINGLE("Quick Setup Line ADC", M98090_REG_QCFG_LINE_PATH,
> +               M98090_LINE_ALL_SHIFT, M98090_LINE_ALL_NUM - 1, 0),
> +       SOC_SINGLE("Quick Setup Analog MIC Loop", M98090_REG_QCFG_MIC_LOOP,
> +               M98090_AMIC_ALL_SHIFT, M98090_AMIC_ALL_NUM - 1, 0),
> +       SOC_SINGLE("Quick Setup Analog Line Loop",
> +               M98090_REG_QCFG_LINE_LOOP, M98090_ALIN_ALL_SHIFT,
> +               M98090_ALIN_ALL_NUM - 1, 0),

What do these controls do?

> +       SOC_SINGLE("Rev ID", M98090_REG_REV_ID,
> +               M98090_REVID_SHIFT, M98090_REVID_NUM - 1, 0),

Hrm, this needs to be read only I think but we don't support that via
standard macros.  I'd expect exposing via a sysfs file rather than an
ALSA control, or just logging on startup - it'll be exposed via the
regmap debugfs interface anyway.

> +static const struct snd_soc_dapm_route max98090_dapm_routes[] = {
> +
> +       {"MIC1 Input", NULL, "MIC1"},
> +       {"MIC2 Input", NULL, "MIC2"},
> +       {"MIC1 Input", NULL, "MICBIAS"},
> +       {"MIC2 Input", NULL, "MICBIAS"},

Is this really an internal connection in the device and not something
that's done in the system?

> +/*
> + * This accommodates an inverted logic in the MAX98090 chip
> + * for Bit Clock Invert (BCI). The inverted logic is only seen
> + * for the case of TDM mode. The remaining cases have normal logic.
> + */
> +               if (max98090->tdm_slots > 1) {
> +                       regval ^= M98090_DAI_BCI_MASK;

Coding style, your comment is misaligned.

> +
> +       switch (reg & (M98090_LSNS_MASK | M98090_JKSNS_MASK)) {
> +               case M98090_LSNS_MASK | M98090_JKSNS_MASK:
> +               {

You don't need the { } and they make the code look unusual.

> +                       dev_info(codec->dev, "No Headset Detected\n");
> +
> +                       max98090->jack_state = M98090_JACK_STATE_NO_HEADSET;
> +
> +                       max98090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);

The issues I mentioned last time with the lack of sync between this code
and DAPM still apply - DAPM is likely to just come along and override
you here.

> +       if (active & M98090_IRQ_ULK_MASK) {
> +               dev_dbg(codec->dev, "M98090_IRQ_ULK_MASK\n");
> +       }

Should things like this be dev_err() - they look like real error
reports from the device?

> +                                const struct i2c_device_id *id)
> +{
> +       struct max98090_priv *max98090;
> +       int ret;
> +
> +       pr_info("max98090_i2c_probe\n");

No need for log messages like this - dev_dbg() at most.

> +       max98090 = kzalloc(sizeof(struct max98090_priv), GFP_KERNEL);
> +       if (max98090 == NULL)
> +               return -ENOMEM;

devm_kzalloc() then you don't need to explicitly free() which will fix
leaks on error.

> +static int max98090_runtime_resume(struct device *dev)
> +{
> +       struct max98090_priv *max98090 = dev_get_drvdata(dev);
> +
> +       regcache_cache_only(max98090->regmap, false);
> +
> +       max98090_reset(max98090);
> +
> +       regcache_sync(max98090->regmap);

Do you realy need to reset the device here?  If anything I'd expect it
on suspend since the reset state is probably the lowest power state.


More information about the Alsa-devel mailing list