[alsa-devel] [PATCH 0/7] ASoC: max98090: Couple improvements and ACPI probing support
Here are couple improvements to MAX98090 codec driver. I think only 1/7 is a real fix and rest 2-7/7 are regular updates that make codec resume working and add ACPI probing support on Intel Baytrail platform.
Jarkko Nikula (2): ASoC: max98090: Move microphone bias voltage setting to probe function ASoC: max98090: Add ACPI probing support
Liam Girdwood (5): ASoC: max98090: Fix digital sidetone gain TLV ASoC: max98090: Fix reset at resume time. ASoC: max98090: Reset codec on resume ASoC: max98090: Mark cache as dirty prior to restoring ASoC: max98090: Make sure we configure BCLK in one place
sound/soc/codecs/max98090.c | 77 +++++++++++++++++++++++++++++++++++++-------- sound/soc/codecs/max98090.h | 1 + 2 files changed, 65 insertions(+), 13 deletions(-)
From: Liam Girdwood liam.r.girdwood@linux.intel.com
TLV for digital sidetone volume is wrong, this fix matches it to the datasheet.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com Signed-off-by: Jarkko Nikula jarkko.nikula@linux.intel.com --- sound/soc/codecs/max98090.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index f3dd9791e736..9e08c4768bc0 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -390,6 +390,7 @@ static const DECLARE_TLV_DB_SCALE(max98090_alc_tlv, -1500, 100, 0); static const DECLARE_TLV_DB_SCALE(max98090_alcmakeup_tlv, 0, 100, 0); static const DECLARE_TLV_DB_SCALE(max98090_alccomp_tlv, -3100, 100, 0); static const DECLARE_TLV_DB_SCALE(max98090_drcexp_tlv, -6600, 100, 0); +static const DECLARE_TLV_DB_SCALE(max98090_sdg_tlv, 50, 200, 0);
static const unsigned int max98090_mixout_tlv[] = { TLV_DB_RANGE_HEAD(2), @@ -666,7 +667,7 @@ static const struct snd_kcontrol_new max98090_snd_controls[] = { SOC_SINGLE_EXT_TLV("Digital Sidetone Volume", M98090_REG_ADC_SIDETONE, M98090_DVST_SHIFT, M98090_DVST_NUM - 1, 1, max98090_get_enab_tlv, - max98090_put_enab_tlv, max98090_micboost_tlv), + max98090_put_enab_tlv, max98090_sdg_tlv), SOC_SINGLE_TLV("Digital Coarse Volume", M98090_REG_DAI_PLAYBACK_LEVEL, M98090_DVG_SHIFT, M98090_DVG_NUM - 1, 0, max98090_dvg_tlv),
From: Liam Girdwood liam.r.girdwood@linux.intel.com
Reset needs to wait 20ms before other codec IO is performed. This wait was not being performed. Fix this by making sure the reset register is not restored with the cache, but use the manual reset method in resume with the wait.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com Signed-off-by: Jarkko Nikula jarkko.nikula@linux.intel.com --- sound/soc/codecs/max98090.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 9e08c4768bc0..4accf9ba447e 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -256,6 +256,7 @@ static struct reg_default max98090_reg[] = { static bool max98090_volatile_register(struct device *dev, unsigned int reg) { switch (reg) { + case M98090_REG_SOFTWARE_RESET: case M98090_REG_DEVICE_STATUS: case M98090_REG_JACK_STATUS: case M98090_REG_REVISION_ID: @@ -2374,6 +2375,8 @@ static int max98090_runtime_resume(struct device *dev)
regcache_cache_only(max98090->regmap, false);
+ max98090_reset(max98090); + regcache_sync(max98090->regmap);
return 0;
From: Liam Girdwood liam.r.girdwood@linux.intel.com
Make sure we reset codec and clear any IRQs on resume. This matches the init sequence in probe.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com Signed-off-by: Jarkko Nikula jarkko.nikula@linux.intel.com --- sound/soc/codecs/max98090.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 4accf9ba447e..b3f447cc050c 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -2392,9 +2392,32 @@ static int max98090_runtime_suspend(struct device *dev) } #endif
+#ifdef CONFIG_PM +static int max98090_resume(struct device *dev) +{ + struct max98090_priv *max98090 = dev_get_drvdata(dev); + unsigned int status; + + max98090_reset(max98090); + + /* clear IRQ status */ + regmap_read(max98090->regmap, M98090_REG_DEVICE_STATUS, &status); + + regcache_sync(max98090->regmap); + + return 0; +} + +static int max98090_suspend(struct device *dev) +{ + return 0; +} +#endif + static const struct dev_pm_ops max98090_pm = { SET_RUNTIME_PM_OPS(max98090_runtime_suspend, max98090_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(max98090_suspend, max98090_resume) };
static const struct i2c_device_id max98090_i2c_id[] = {
From: Liam Girdwood liam.r.girdwood@linux.intel.com
Make sure the cache is fully flushed at resume time.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com Signed-off-by: Jarkko Nikula jarkko.nikula@linux.intel.com --- sound/soc/codecs/max98090.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index b3f447cc050c..8c88b4448f7e 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -2398,6 +2398,8 @@ static int max98090_resume(struct device *dev) struct max98090_priv *max98090 = dev_get_drvdata(dev); unsigned int status;
+ regcache_mark_dirty(max98090->regmap); + max98090_reset(max98090);
/* clear IRQ status */
From: Liam Girdwood liam.r.girdwood@linux.intel.com
BCL is being configured in two places producing a warning message. Make sure we only configure BCLK once and when we are master.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com Signed-off-by: Jarkko Nikula jarkko.nikula@linux.intel.com --- sound/soc/codecs/max98090.c | 8 +++++--- sound/soc/codecs/max98090.h | 1 + 2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 8c88b4448f7e..14d42cde9235 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -1675,6 +1675,7 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai, M98090_REG_CLOCK_RATIO_NI_LSB, 0x00); snd_soc_update_bits(codec, M98090_REG_CLOCK_MODE, M98090_USE_M1_MASK, 0); + max98090->master = false; break; case SND_SOC_DAIFMT_CBM_CFM: /* Set to master mode */ @@ -1691,6 +1692,7 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai, regval |= M98090_MAS_MASK | M98090_BSEL_32; } + max98090->master = true; break; case SND_SOC_DAIFMT_CBS_CFM: case SND_SOC_DAIFMT_CBM_CFS: @@ -1874,7 +1876,8 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream, return -EINVAL; }
- max98090_configure_bclk(codec); + if (max98090->master) + max98090_configure_bclk(codec);
cdata->rate = max98090->lrclk;
@@ -1953,8 +1956,6 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai,
max98090->sysclk = freq;
- max98090_configure_bclk(codec); - return 0; }
@@ -2226,6 +2227,7 @@ static int max98090_probe(struct snd_soc_codec *codec) /* Initialize private data */
max98090->sysclk = (unsigned)-1; + max98090->master = false;
cdata = &max98090->dai[0]; cdata->rate = (unsigned)-1; diff --git a/sound/soc/codecs/max98090.h b/sound/soc/codecs/max98090.h index 1a4e2334a7b2..5a3c8d0613cb 100644 --- a/sound/soc/codecs/max98090.h +++ b/sound/soc/codecs/max98090.h @@ -1540,6 +1540,7 @@ struct max98090_priv { unsigned int pa2en; unsigned int extmic_mux; unsigned int sidetone; + bool master; };
int max98090_mic_detect(struct snd_soc_codec *codec,
Microphone bias level configuration register can configure voltage between 2.2 V and 2.8 V but doesn't manage is voltage on or off. Microphone bias on/off state is controlled by "MICBIAS" DAPM widget.
Therefore there is no need to update bias voltage conditionally depending on jack state each time when codec goes to SND_SOC_BIAS_ON state and setting can be moved to max98090_probe() as driver currently doesn't support other levels than 2.8 V.
Signed-off-by: Jarkko Nikula jarkko.nikula@linux.intel.com --- sound/soc/codecs/max98090.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 14d42cde9235..0c8315270e8e 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -1796,13 +1796,6 @@ static int max98090_set_bias_level(struct snd_soc_codec *codec,
switch (level) { case SND_SOC_BIAS_ON: - if (max98090->jack_state == M98090_JACK_STATE_HEADSET) { - /* - * Set to normal bias level. - */ - snd_soc_update_bits(codec, M98090_REG_MIC_BIAS_VOLTAGE, - M98090_MBVSEL_MASK, M98090_MBVSEL_2V8); - } break;
case SND_SOC_BIAS_PREPARE: @@ -2297,6 +2290,9 @@ static int max98090_probe(struct snd_soc_codec *codec) snd_soc_write(codec, M98090_REG_BIAS_CONTROL, M98090_VCM_MODE_MASK);
+ snd_soc_update_bits(codec, M98090_REG_MIC_BIAS_VOLTAGE, + M98090_MBVSEL_MASK, M98090_MBVSEL_2V8); + max98090_handle_pdata(codec);
max98090_add_widgets(codec);
Add ACPI ID for MAX98090 and ACPI 5 I2C device probing support.
Signed-off-by: Jarkko Nikula jarkko.nikula@linux.intel.com --- sound/soc/codecs/max98090.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 0c8315270e8e..9b76f5a45115 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -16,6 +16,7 @@ #include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/slab.h> +#include <linux/acpi.h> #include <sound/jack.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -2329,9 +2330,11 @@ static const struct regmap_config max98090_regmap = { };
static int max98090_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) + const struct i2c_device_id *i2c_id) { struct max98090_priv *max98090; + const struct acpi_device_id *acpi_id; + kernel_ulong_t driver_data = 0; int ret;
pr_debug("max98090_i2c_probe\n"); @@ -2341,7 +2344,19 @@ static int max98090_i2c_probe(struct i2c_client *i2c, if (max98090 == NULL) return -ENOMEM;
- max98090->devtype = id->driver_data; + if (ACPI_HANDLE(&i2c->dev)) { + acpi_id = acpi_match_device(i2c->dev.driver->acpi_match_table, + &i2c->dev); + if (!acpi_id) { + dev_err(&i2c->dev, "No driver data\n"); + return -EINVAL; + } + driver_data = acpi_id->driver_data; + } else if (i2c_id) { + driver_data = i2c_id->driver_data; + } + + max98090->devtype = driver_data; i2c_set_clientdata(i2c, max98090); max98090->pdata = i2c->dev.platform_data; max98090->irq = i2c->irq; @@ -2432,12 +2447,21 @@ static const struct of_device_id max98090_of_match[] = { }; MODULE_DEVICE_TABLE(of, max98090_of_match);
+#ifdef CONFIG_ACPI +static struct acpi_device_id max98090_acpi_match[] = { + { "193C9890", MAX98090 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, max98090_acpi_match); +#endif + static struct i2c_driver max98090_i2c_driver = { .driver = { .name = "max98090", .owner = THIS_MODULE, .pm = &max98090_pm, .of_match_table = of_match_ptr(max98090_of_match), + .acpi_match_table = ACPI_PTR(max98090_acpi_match), }, .probe = max98090_i2c_probe, .remove = max98090_i2c_remove,
On Fri, May 16, 2014 at 04:55:18PM +0300, Jarkko Nikula wrote:
Here are couple improvements to MAX98090 codec driver. I think only 1/7 is a real fix and rest 2-7/7 are regular updates that make codec resume working and add ACPI probing support on Intel Baytrail platform.
Applied all, thanks. All the patches up to 4 look like good fixes, being out of spec on reset is a definite fix which I've maked to stable and making sure that the cache is synced correctly is going to be required if power was lost. The initialisation on resume might not be 100% required but definitely seems safer too.
participants (2)
-
Jarkko Nikula
-
Mark Brown