Unverified Commit 949531d9 authored by Mark Brown's avatar Mark Brown
Browse files

Merge series "ASoC: da7213: support for usage with simple-card" from Sebastian...

Merge series "ASoC: da7213: support for usage with simple-card" from Sebastian Reichel <sebastian.reichel@collabora.com>:

Hi,

This extends the da7213 driver to be used with simple-audio-card in
combination with a fixed clock. Here is a snippet of the downstream
board's DT, that is supposed to be supported by this patchset.

---------------------------------------------------------------------
/ {
	sound {
		compatible = "simple-audio-card";
		simple-audio-card,name = "audio-card";
		simple-audio-card,format = "i2s";
		simple-audio-card,bitclock-master = <&dailink_master>;
		simple-audio-card,frame-master = <&dailink_master>;

		simple-audio-card,widgets = "Speaker", "Ext Spk";
		simple-audio-card,audio-routing = "Ext Spk", "LINE";

		simple-audio-card,cpu {
			sound-dai = <&ssi1>;
		};

		dailink_master: simple-audio-card,codec {
			sound-dai = <&codec>;
		};
	};

	clk_ext_audio_codec: clock-codec {
		compatible = "fixed-clock";
		#clock-cells = <0>;
		clock-frequency = <12288000>;
	};
};

&i2c1 {
	codec: audio-codec@1a {
		compatible = "dlg,da7212";
		reg = <0x1a>;
		#sound-dai-cells = <0>;
		VDDA-supply = <&reg_2v5_audio>;
		VDDSP-supply = <&reg_5v0_audio>;
		VDDMIC-supply = <&reg_3v3_audio>;
		VDDIO-supply = <&reg_3v3_audio>;
		clocks = <&clk_ext_audio_codec>;
		clock-names = "mclk";
	};
};
---------------------------------------------------------------------

This is mostly a resend of PATCHv2. There was quite a bit of discussion
for the last patch. As far as I can see no better solution was found and
the patch is fine as is. Sorry for the delay in sending another revision.

Changes since PATCHv2:
 * https://lore.kernel.org/alsa-devel/20191120152406.2744-1-sebastian.reichel@collabora.com/
 * dropped patch converting DA7213 into selectable Kconfig option (merged)
 * fix compatible string in patch 1 (DT binding) as pointed out by Adam Thomson
 * collected Reviewed-by from Adam Thomson for patch 2-4

Changes since PATCHv1:
 * https://lore.kernel.org/alsa-devel/20191108174843.11227-1-sebastian.reichel@collabora.com/
 * add patch adding da7212 compatible to DT bindings
 * update regulator patch, so that VDDA is enabled together with VDDIO
   while the device is enabled to avoid device reset
 * update clock patch, so that automatic PLL handling is not enabled
   when PLL is configured manually
 * update clock patch, so that automatic PLL is disabled when the device
   is suspended
 * update clock patch, so that automatic PLL is configured into bypass
   mode when possible

-- Sebastian

Sebastian Reichel (5):
  ASoC: da7213: Add da7212 DT compatible
  ASoC: da7213: Add regulator support
  ASoC: da7213: move set_sysclk to codec level
  ASoC: da7213: move set_pll to codec level
  ASoC: da7213: add default clock handling

 .../devicetree/bindings/sound/da7213.txt      |   8 +-
 sound/soc/codecs/da7213.c                     | 172 ++++++++++++++++--
 sound/soc/codecs/da7213.h                     |  11 ++
 3 files changed, 175 insertions(+), 16 deletions(-)

--
2.26.2
parents 15b5c496 f7a8ae29
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
Dialog Semiconductor DA7213 Audio Codec bindings
Dialog Semiconductor DA7212/DA7213 Audio Codec bindings

======

Required properties:
- compatible : Should be "dlg,da7213"
- compatible : Should be "dlg,da7212" or "dlg,da7213"
- reg: Specifies the I2C slave address

Optional properties:
@@ -21,6 +21,10 @@ Optional properties:
- dlg,dmic-clkrate : DMIC clock frequency (Hz).
	[<1500000>, <3000000>]

 - VDDA-supply : Regulator phandle for Analogue power supply
 - VDDMIC-supply : Regulator phandle for Mic Bias
 - VDDIO-supply : Regulator phandle for I/O power supply

======

Example:
+90 −12
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <linux/pm_runtime.h>
#include <sound/soc.h>
#include <sound/initval.h>
#include <sound/tlv.h>
@@ -806,6 +807,11 @@ static int da7213_dai_event(struct snd_soc_dapm_widget *w,
 */

static const struct snd_soc_dapm_widget da7213_dapm_widgets[] = {
	/*
	 * Power Supply
	 */
	SND_SOC_DAPM_REGULATOR_SUPPLY("VDDMIC", 0, 0),

	/*
	 * Input & Output
	 */
@@ -932,6 +938,9 @@ static const struct snd_soc_dapm_route da7213_audio_map[] = {
	/* Dest       Connecting Widget    source */

	/* Input path */
	{"Mic Bias 1", NULL, "VDDMIC"},
	{"Mic Bias 2", NULL, "VDDMIC"},

	{"MIC1", NULL, "Mic Bias 1"},
	{"MIC2", NULL, "Mic Bias 2"},

@@ -1334,10 +1343,10 @@ static int da7213_mute(struct snd_soc_dai *dai, int mute)
#define DA7213_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)

static int da7213_set_dai_sysclk(struct snd_soc_dai *codec_dai,
				 int clk_id, unsigned int freq, int dir)
static int da7213_set_component_sysclk(struct snd_soc_component *component,
				       int clk_id, int source,
				       unsigned int freq, int dir)
{
	struct snd_soc_component *component = codec_dai->component;
	struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component);
	int ret = 0;

@@ -1345,7 +1354,7 @@ static int da7213_set_dai_sysclk(struct snd_soc_dai *codec_dai,
		return 0;

	if (((freq < 5000000) && (freq != 32768)) || (freq > 54000000)) {
		dev_err(codec_dai->dev, "Unsupported MCLK value %d\n",
		dev_err(component->dev, "Unsupported MCLK value %d\n",
			freq);
		return -EINVAL;
	}
@@ -1361,7 +1370,7 @@ static int da7213_set_dai_sysclk(struct snd_soc_dai *codec_dai,
				    DA7213_PLL_MCLK_SQR_EN);
		break;
	default:
		dev_err(codec_dai->dev, "Unknown clock source %d\n", clk_id);
		dev_err(component->dev, "Unknown clock source %d\n", clk_id);
		return -EINVAL;
	}

@@ -1371,7 +1380,7 @@ static int da7213_set_dai_sysclk(struct snd_soc_dai *codec_dai,
		freq = clk_round_rate(da7213->mclk, freq);
		ret = clk_set_rate(da7213->mclk, freq);
		if (ret) {
			dev_err(codec_dai->dev, "Failed to set clock rate %d\n",
			dev_err(component->dev, "Failed to set clock rate %d\n",
				freq);
			return ret;
		}
@@ -1383,10 +1392,10 @@ static int da7213_set_dai_sysclk(struct snd_soc_dai *codec_dai,
}

/* Supported PLL input frequencies are 32KHz, 5MHz - 54MHz. */
static int da7213_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
			      int source, unsigned int fref, unsigned int fout)
static int da7213_set_component_pll(struct snd_soc_component *component,
				    int pll_id, int source,
				    unsigned int fref, unsigned int fout)
{
	struct snd_soc_component *component = codec_dai->component;
	struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component);

	u8 pll_ctrl, indiv_bits, indiv;
@@ -1498,8 +1507,6 @@ static int da7213_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
static const struct snd_soc_dai_ops da7213_dai_ops = {
	.hw_params	= da7213_hw_params,
	.set_fmt	= da7213_set_dai_fmt,
	.set_sysclk	= da7213_set_dai_sysclk,
	.set_pll	= da7213_set_dai_pll,
	.digital_mute	= da7213_mute,
};

@@ -1571,6 +1578,7 @@ static int da7213_set_bias_level(struct snd_soc_component *component,
#if defined(CONFIG_OF)
/* DT */
static const struct of_device_id da7213_of_match[] = {
	{ .compatible = "dlg,da7212", },
	{ .compatible = "dlg,da7213", },
	{ }
};
@@ -1690,6 +1698,8 @@ static int da7213_probe(struct snd_soc_component *component)
{
	struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component);

	pm_runtime_get_sync(component->dev);

	/* Default to using ALC auto offset calibration mode. */
	snd_soc_component_update_bits(component, DA7213_ALC_CTRL1,
			    DA7213_ALC_CALIB_MODE_MAN, 0);
@@ -1810,6 +1820,8 @@ static int da7213_probe(struct snd_soc_component *component)
				    DA7213_DMIC_CLK_RATE_MASK, dmic_cfg);
	}

	pm_runtime_put_sync(component->dev);

	/* Check if MCLK provided */
	da7213->mclk = devm_clk_get(component->dev, "mclk");
	if (IS_ERR(da7213->mclk)) {
@@ -1831,6 +1843,8 @@ static const struct snd_soc_component_driver soc_component_dev_da7213 = {
	.num_dapm_widgets	= ARRAY_SIZE(da7213_dapm_widgets),
	.dapm_routes		= da7213_audio_map,
	.num_dapm_routes	= ARRAY_SIZE(da7213_audio_map),
	.set_sysclk		= da7213_set_component_sysclk,
	.set_pll		= da7213_set_component_pll,
	.idle_bias_on		= 1,
	.use_pmdown_time	= 1,
	.endianness		= 1,
@@ -1847,11 +1861,22 @@ static const struct regmap_config da7213_regmap_config = {
	.cache_type = REGCACHE_RBTREE,
};

static void da7213_power_off(void *data)
{
	struct da7213_priv *da7213 = data;
	regulator_bulk_disable(DA7213_NUM_SUPPLIES, da7213->supplies);
}

static const char *da7213_supply_names[DA7213_NUM_SUPPLIES] = {
	[DA7213_SUPPLY_VDDA] = "VDDA",
	[DA7213_SUPPLY_VDDIO] = "VDDIO",
};

static int da7213_i2c_probe(struct i2c_client *i2c,
			    const struct i2c_device_id *id)
{
	struct da7213_priv *da7213;
	int ret;
	int i, ret;

	da7213 = devm_kzalloc(&i2c->dev, sizeof(*da7213), GFP_KERNEL);
	if (!da7213)
@@ -1859,6 +1884,25 @@ static int da7213_i2c_probe(struct i2c_client *i2c,

	i2c_set_clientdata(i2c, da7213);

	/* Get required supplies */
	for (i = 0; i < DA7213_NUM_SUPPLIES; ++i)
		da7213->supplies[i].supply = da7213_supply_names[i];

	ret = devm_regulator_bulk_get(&i2c->dev, DA7213_NUM_SUPPLIES,
				      da7213->supplies);
	if (ret) {
		dev_err(&i2c->dev, "Failed to get supplies: %d\n", ret);
		return ret;
	}

	ret = regulator_bulk_enable(DA7213_NUM_SUPPLIES, da7213->supplies);
	if (ret < 0)
		return ret;

	ret = devm_add_action_or_reset(&i2c->dev, da7213_power_off, da7213);
	if (ret < 0)
		return ret;

	da7213->regmap = devm_regmap_init_i2c(i2c, &da7213_regmap_config);
	if (IS_ERR(da7213->regmap)) {
		ret = PTR_ERR(da7213->regmap);
@@ -1866,6 +1910,11 @@ static int da7213_i2c_probe(struct i2c_client *i2c,
		return ret;
	}

	pm_runtime_set_autosuspend_delay(&i2c->dev, 100);
	pm_runtime_use_autosuspend(&i2c->dev);
	pm_runtime_set_active(&i2c->dev);
	pm_runtime_enable(&i2c->dev);

	ret = devm_snd_soc_register_component(&i2c->dev,
			&soc_component_dev_da7213, &da7213_dai, 1);
	if (ret < 0) {
@@ -1875,6 +1924,34 @@ static int da7213_i2c_probe(struct i2c_client *i2c,
	return ret;
}

static int __maybe_unused da7213_runtime_suspend(struct device *dev)
{
	struct da7213_priv *da7213 = dev_get_drvdata(dev);

	regcache_cache_only(da7213->regmap, true);
	regcache_mark_dirty(da7213->regmap);
	regulator_bulk_disable(DA7213_NUM_SUPPLIES, da7213->supplies);

	return 0;
}

static int __maybe_unused da7213_runtime_resume(struct device *dev)
{
	struct da7213_priv *da7213 = dev_get_drvdata(dev);
	int ret;

	ret = regulator_bulk_enable(DA7213_NUM_SUPPLIES, da7213->supplies);
	if (ret < 0)
		return ret;
	regcache_cache_only(da7213->regmap, false);
	regcache_sync(da7213->regmap);
	return 0;
}

static const struct dev_pm_ops da7213_pm = {
	SET_RUNTIME_PM_OPS(da7213_runtime_suspend, da7213_runtime_resume, NULL)
};

static const struct i2c_device_id da7213_i2c_id[] = {
	{ "da7213", 0 },
	{ }
@@ -1887,6 +1964,7 @@ static struct i2c_driver da7213_i2c_driver = {
		.name = "da7213",
		.of_match_table = of_match_ptr(da7213_of_match),
		.acpi_match_table = ACPI_PTR(da7213_acpi_match),
		.pm = &da7213_pm,
	},
	.probe		= da7213_i2c_probe,
	.id_table	= da7213_i2c_id,
+9 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@

#include <linux/clk.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <sound/da7213.h>

/*
@@ -521,9 +522,17 @@ enum da7213_sys_clk {
	DA7213_SYSCLK_PLL_32KHZ
};

/* Regulators */
enum da7213_supplies {
	DA7213_SUPPLY_VDDA = 0,
	DA7213_SUPPLY_VDDIO,
	DA7213_NUM_SUPPLIES,
};

/* Codec private data */
struct da7213_priv {
	struct regmap *regmap;
	struct regulator_bulk_data supplies[DA7213_NUM_SUPPLIES];
	struct clk *mclk;
	unsigned int mclk_rate;
	int clk_src;