Commit 949531d9 authored by Mark Brown's avatar Mark Brown

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
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:
......
......@@ -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,
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment