mirror of https://gitee.com/openkylin/linux.git
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 = <®_2v5_audio>; VDDSP-supply = <®_5v0_audio>; VDDMIC-supply = <®_3v3_audio>; VDDIO-supply = <®_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
This commit is contained in:
commit
949531d9b8
|
@ -1,9 +1,9 @@
|
|||
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;
|
||||
|
|
Loading…
Reference in New Issue