diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-07 12:11:09 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-07 12:11:09 -0800 |
commit | 7590e37bdaeec25ae325f4ba450be13e2aac6c8d (patch) | |
tree | 8249846959a09148a467269c65756d4c278d4f07 /sound/soc/codecs | |
parent | 7e6127c1240ed569cdda2a67c8f03836f9f28c05 (diff) | |
parent | 3d0a352a552e6cdf052e8baf66f1fe6418c122fe (diff) | |
download | linux-7590e37bdaeec25ae325f4ba450be13e2aac6c8d.tar.bz2 |
Merge tag 'asoc-v4.16-5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound
Pull more ASoC updates from Mark Brown:
"With the merge window having been delayed for another week here's
another batch of updates that came in during that week.
There's a few important fixes in here, mainly a fix for I/O on a
number of devices caused by some of the component rework and a fix for
a potential issue if more than one component in a link provides
compressed operations. The I/O fixes are particularly important as the
problem causes a power regression on a number of OMAP platforms"
* tag 'asoc-v4.16-5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound: (22 commits)
ASoC: stm32: add of dependency for stm32 drivers
ASoC: mt8173-rt5650: fix child-node lookup
ASoC: dapm: fix debugfs read using path->connected
ASoC: compress: Fixup error messages
ASoC: compress: Remove some extraneous blank lines
ASoC: compress: Correct handling of copy callback
ASoC: Intel: kbl: Enable mclk and ssp sclk early
ASoC: Intel: Skylake: Add extended I2S config blob support in Clock driver
ASoC: Intel: Skylake: Add ssp clock driver
ASoC: Fix twl4030 and 6040 regression by adding back read and write
ASoC: sun8i-codec: Add ADC support for a33
ASoC: rockchip: Use dummy_dai for rt5514 dsp dailink
ASoC: soc-pcm: rename .pmdown_time to .use_pmdown_time for Component
ASoC: ak4613: call dummy write for PW_MGMT1/3 when Playback
ASoC: soc-pcm: don't call flush_delayed_work() many times in soc_pcm_private_free()
ASoC: soc-core: snd_soc_rtdcom_lookup() cares component driver name
ASoC: sam9x5_wm8731: Drop 'ASoC' prefix from error messages
ASoC: sam9g20_wm8731: use dev_*() logging functions
ASoC: max98373 Changed SPDX header in C++ comments style
ASoC: dmic: Fix check of return value from read of 'num-channels'
...
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r-- | sound/soc/codecs/ak4613.c | 78 | ||||
-rw-r--r-- | sound/soc/codecs/dmic.c | 2 | ||||
-rw-r--r-- | sound/soc/codecs/max98373.c | 4 | ||||
-rw-r--r-- | sound/soc/codecs/max98373.h | 5 | ||||
-rw-r--r-- | sound/soc/codecs/sgtl5000.c | 2 | ||||
-rw-r--r-- | sound/soc/codecs/twl4030.c | 2 | ||||
-rw-r--r-- | sound/soc/codecs/twl6040.c | 2 |
7 files changed, 89 insertions, 6 deletions
diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c index b95bb8b52e51..3d1cf4784e87 100644 --- a/sound/soc/codecs/ak4613.c +++ b/sound/soc/codecs/ak4613.c @@ -15,6 +15,7 @@ */ #include <linux/clk.h> +#include <linux/delay.h> #include <linux/i2c.h> #include <linux/slab.h> #include <linux/of_device.h> @@ -95,6 +96,9 @@ struct ak4613_priv { struct mutex lock; const struct ak4613_interface *iface; struct snd_pcm_hw_constraint_list constraint; + struct work_struct dummy_write_work; + struct snd_soc_component *component; + unsigned int rate; unsigned int sysclk; unsigned int fmt; @@ -392,6 +396,7 @@ static int ak4613_dai_hw_params(struct snd_pcm_substream *substream, default: return -EINVAL; } + priv->rate = rate; /* * FIXME @@ -467,11 +472,83 @@ static int ak4613_set_bias_level(struct snd_soc_codec *codec, return 0; } +static void ak4613_dummy_write(struct work_struct *work) +{ + struct ak4613_priv *priv = container_of(work, + struct ak4613_priv, + dummy_write_work); + struct snd_soc_component *component = priv->component; + unsigned int mgmt1; + unsigned int mgmt3; + + /* + * PW_MGMT1 / PW_MGMT3 needs dummy write at least after 5 LR clocks + * + * Note + * + * To avoid extra delay, we want to avoid preemption here, + * but we can't. Because it uses I2C access which is using IRQ + * and sleep. Thus, delay might be more than 5 LR clocks + * see also + * ak4613_dai_trigger() + */ + udelay(5000000 / priv->rate); + + snd_soc_component_read(component, PW_MGMT1, &mgmt1); + snd_soc_component_read(component, PW_MGMT3, &mgmt3); + + snd_soc_component_write(component, PW_MGMT1, mgmt1); + snd_soc_component_write(component, PW_MGMT3, mgmt3); +} + +static int ak4613_dai_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + struct ak4613_priv *priv = snd_soc_codec_get_drvdata(codec); + + /* + * FIXME + * + * PW_MGMT1 / PW_MGMT3 needs dummy write at least after 5 LR clocks + * from Power Down Release. Otherwise, Playback volume will be 0dB. + * To avoid complex multiple delay/dummy_write method from + * ak4613_set_bias_level() / SND_SOC_DAPM_DAC_E("DACx", ...), + * call it once here. + * + * But, unfortunately, we can't "write" here because here is atomic + * context (It uses I2C access for writing). + * Thus, use schedule_work() to switching to normal context + * immediately. + * + * Note + * + * Calling ak4613_dummy_write() function might be delayed. + * In such case, ak4613 volume might be temporarily 0dB when + * beggining of playback. + * see also + * ak4613_dummy_write() + */ + + if ((cmd != SNDRV_PCM_TRIGGER_START) && + (cmd != SNDRV_PCM_TRIGGER_RESUME)) + return 0; + + if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) + return 0; + + priv->component = &codec->component; + schedule_work(&priv->dummy_write_work); + + return 0; +} + static const struct snd_soc_dai_ops ak4613_dai_ops = { .startup = ak4613_dai_startup, .shutdown = ak4613_dai_shutdown, .set_sysclk = ak4613_dai_set_sysclk, .set_fmt = ak4613_dai_set_fmt, + .trigger = ak4613_dai_trigger, .hw_params = ak4613_dai_hw_params, }; @@ -590,6 +667,7 @@ static int ak4613_i2c_probe(struct i2c_client *i2c, priv->iface = NULL; priv->cnt = 0; priv->sysclk = 0; + INIT_WORK(&priv->dummy_write_work, ak4613_dummy_write); mutex_init(&priv->lock); diff --git a/sound/soc/codecs/dmic.c b/sound/soc/codecs/dmic.c index c88f974ebe3e..cf83c423394d 100644 --- a/sound/soc/codecs/dmic.c +++ b/sound/soc/codecs/dmic.c @@ -113,7 +113,7 @@ static int dmic_dev_probe(struct platform_device *pdev) if (pdev->dev.of_node) { err = of_property_read_u32(pdev->dev.of_node, "num-channels", &chans); - if (err && (err != -ENOENT)) + if (err && (err != -EINVAL)) return err; if (!err) { diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c index 31b0864583e8..562e88765129 100644 --- a/sound/soc/codecs/max98373.c +++ b/sound/soc/codecs/max98373.c @@ -1,5 +1,5 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (c) 2017, Maxim Integrated */ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2017, Maxim Integrated #include <linux/acpi.h> #include <linux/i2c.h> diff --git a/sound/soc/codecs/max98373.h b/sound/soc/codecs/max98373.h index d0b359d0cf8c..f6a37aa02f26 100644 --- a/sound/soc/codecs/max98373.h +++ b/sound/soc/codecs/max98373.h @@ -1,5 +1,6 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (c) 2017, Maxim Integrated */ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2017, Maxim Integrated + #ifndef _MAX98373_H #define _MAX98373_H diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 633cdcfc933d..e1ab5537d27a 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -1392,7 +1392,7 @@ static int sgtl5000_i2c_probe(struct i2c_client *client, ana_pwr |= SGTL5000_LINEREG_D_POWERUP; dev_info(&client->dev, - "Using internal LDO instead of VDDD: check ER1\n"); + "Using internal LDO instead of VDDD: check ER1 erratum\n"); } else { /* using external LDO for VDDD * Clear startup powerup and simple powerup diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 8798182959c1..e4d7f397d361 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -2195,6 +2195,8 @@ static int twl4030_soc_remove(struct snd_soc_codec *codec) static const struct snd_soc_codec_driver soc_codec_dev_twl4030 = { .probe = twl4030_soc_probe, .remove = twl4030_soc_remove, + .read = twl4030_read, + .write = twl4030_write, .set_bias_level = twl4030_set_bias_level, .idle_bias_off = true, diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 3b895b4b451c..573a523ed0b3 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -1158,6 +1158,8 @@ static int twl6040_remove(struct snd_soc_codec *codec) static const struct snd_soc_codec_driver soc_codec_dev_twl6040 = { .probe = twl6040_probe, .remove = twl6040_remove, + .read = twl6040_read, + .write = twl6040_write, .set_bias_level = twl6040_set_bias_level, .suspend_bias_off = true, .ignore_pmdown_time = true, |