Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7590e37b authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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'
  ...
parents 7e6127c1 3d0a352a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -841,7 +841,7 @@ struct snd_soc_component_driver {
	/* bits */
	unsigned int idle_bias_on:1;
	unsigned int suspend_bias_off:1;
	unsigned int pmdown_time:1; /* care pmdown_time at stop */
	unsigned int use_pmdown_time:1; /* care pmdown_time at stop */
	unsigned int endianness:1;
	unsigned int non_legacy_dai_naming:1;
};
+8 −9
Original line number Diff line number Diff line
@@ -110,16 +110,15 @@ static const struct snd_soc_dapm_route intercon[] = {
static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
{
	struct snd_soc_dai *codec_dai = rtd->codec_dai;
	struct device *dev = rtd->dev;
	int ret;

	printk(KERN_DEBUG
			"at91sam9g20ek_wm8731 "
			": at91sam9g20ek_wm8731_init() called\n");
	dev_dbg(dev, "%s called\n", __func__);

	ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_MCLK,
				     MCLK_RATE, SND_SOC_CLOCK_IN);
	if (ret < 0) {
		printk(KERN_ERR "Failed to set WM8731 SYSCLK: %d\n", ret);
		dev_err(dev, "Failed to set WM8731 SYSCLK: %d\n", ret);
		return ret;
	}

@@ -179,21 +178,21 @@ static int at91sam9g20ek_audio_probe(struct platform_device *pdev)
	 */
	mclk = clk_get(NULL, "pck0");
	if (IS_ERR(mclk)) {
		printk(KERN_ERR "ASoC: Failed to get MCLK\n");
		dev_err(&pdev->dev, "Failed to get MCLK\n");
		ret = PTR_ERR(mclk);
		goto err;
	}

	pllb = clk_get(NULL, "pllb");
	if (IS_ERR(pllb)) {
		printk(KERN_ERR "ASoC: Failed to get PLLB\n");
		dev_err(&pdev->dev, "Failed to get PLLB\n");
		ret = PTR_ERR(pllb);
		goto err_mclk;
	}
	ret = clk_set_parent(mclk, pllb);
	clk_put(pllb);
	if (ret != 0) {
		printk(KERN_ERR "ASoC: Failed to set MCLK parent\n");
		dev_err(&pdev->dev, "Failed to set MCLK parent\n");
		goto err_mclk;
	}

@@ -236,7 +235,7 @@ static int at91sam9g20ek_audio_probe(struct platform_device *pdev)

	ret = snd_soc_register_card(card);
	if (ret) {
		printk(KERN_ERR "ASoC: snd_soc_register_card() failed\n");
		dev_err(&pdev->dev, "snd_soc_register_card() failed\n");
	}

	return ret;
+5 −7
Original line number Diff line number Diff line
@@ -49,13 +49,13 @@ static int sam9x5_wm8731_init(struct snd_soc_pcm_runtime *rtd)
	struct device *dev = rtd->dev;
	int ret;

	dev_dbg(dev, "ASoC: %s called\n", __func__);
	dev_dbg(dev, "%s called\n", __func__);

	/* set the codec system clock for DAC and ADC */
	ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL,
				     MCLK_RATE, SND_SOC_CLOCK_IN);
	if (ret < 0) {
		dev_err(dev, "ASoC: Failed to set WM8731 SYSCLK: %d\n", ret);
		dev_err(dev, "Failed to set WM8731 SYSCLK: %d\n", ret);
		return ret;
	}

@@ -146,8 +146,7 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)

	ret = atmel_ssc_set_audio(priv->ssc_id);
	if (ret != 0) {
		dev_err(&pdev->dev,
			"ASoC: Failed to set SSC %d for audio: %d\n",
		dev_err(&pdev->dev, "Failed to set SSC %d for audio: %d\n",
			ret, priv->ssc_id);
		goto out;
	}
@@ -157,12 +156,11 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)

	ret = snd_soc_register_card(card);
	if (ret) {
		dev_err(&pdev->dev,
			"ASoC: Platform device allocation failed\n");
		dev_err(&pdev->dev, "Platform device allocation failed\n");
		goto out_put_audio;
	}

	dev_dbg(&pdev->dev, "ASoC: %s ok\n", __func__);
	dev_dbg(&pdev->dev, "%s ok\n", __func__);

	return ret;

+78 −0
Original line number Diff line number Diff line
@@ -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);

+1 −1
Original line number Diff line number Diff line
@@ -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) {
Loading