@@ -19,6 +19,8 @@
struct asoc_simple_dai {
const char *name;
unsigned int sysclk;
+ int sysclk_id;
+ int sysclk_source;
int clk_direction;
int slots;
int slot_width;
@@ -186,10 +186,37 @@ int asoc_simple_parse_clk(struct device *dev,
if (of_property_read_bool(node, "system-clock-direction-out"))
simple_dai->clk_direction = SND_SOC_CLOCK_OUT;
+ of_property_read_u32(node, "system-clock-id", &simple_dai->sysclk_id);
+
+ of_property_read_u32(node, "system-clock-source", &simple_dai->sysclk_source);
+
return 0;
}
EXPORT_SYMBOL_GPL(asoc_simple_parse_clk);
+static int asoc_simple_set_sysclk(struct snd_soc_dai *dai,
+ struct asoc_simple_dai *simple_dai,
+ unsigned int sysclk,
+ int dir)
+{
+ int sysclk_id = 0, sysclk_source = 0;
+ int ret;
+
+ if (simple_dai) {
+ sysclk_id = simple_dai->sysclk_id;
+ sysclk_source = simple_dai->sysclk_source;
+ }
+
+ ret = snd_soc_dai_set_sysclk(dai, sysclk_id, sysclk_source, sysclk,
+ dir);
+ if (ret && ret != -ENOTSUPP) {
+ dev_err(dai->dev, "set_sysclk error\n");
+ return ret;
+ }
+
+ return 0;
+}
+
int asoc_simple_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
@@ -219,8 +246,10 @@ void asoc_simple_shutdown(struct snd_pcm_substream *substream)
simple_priv_to_props(priv, rtd->num);
if (dai_props->mclk_fs) {
- snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0, SND_SOC_CLOCK_IN);
- snd_soc_dai_set_sysclk(cpu_dai, 0, 0, 0, SND_SOC_CLOCK_OUT);
+ asoc_simple_set_sysclk(codec_dai, dai_props->codec_dai, 0,
+ SND_SOC_CLOCK_IN);
+ asoc_simple_set_sysclk(cpu_dai, dai_props->cpu_dai, 0,
+ SND_SOC_CLOCK_OUT);
}
asoc_simple_clk_disable(dai_props->cpu_dai);
@@ -270,19 +299,18 @@ int asoc_simple_hw_params(struct snd_pcm_substream *substream,
if (ret < 0)
return ret;
- ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, mclk,
- SND_SOC_CLOCK_IN);
- if (ret && ret != -ENOTSUPP)
- goto err;
+ ret = asoc_simple_set_sysclk(codec_dai, dai_props->codec_dai,
+ mclk, SND_SOC_CLOCK_IN);
+ if (ret)
+ return ret;
- ret = snd_soc_dai_set_sysclk(cpu_dai, 0, 0, mclk,
- SND_SOC_CLOCK_OUT);
- if (ret && ret != -ENOTSUPP)
- goto err;
+ ret = asoc_simple_set_sysclk(cpu_dai, dai_props->cpu_dai,
+ mclk, SND_SOC_CLOCK_OUT);
+ if (ret)
+ return ret;
}
+
return 0;
-err:
- return ret;
}
EXPORT_SYMBOL_GPL(asoc_simple_hw_params);
@@ -307,12 +335,11 @@ static int asoc_simple_init_dai(struct snd_soc_dai *dai,
return 0;
if (simple_dai->sysclk) {
- ret = snd_soc_dai_set_sysclk(dai, 0, 0, simple_dai->sysclk,
+ ret = asoc_simple_set_sysclk(dai, simple_dai,
+ simple_dai->sysclk,
simple_dai->clk_direction);
- if (ret && ret != -ENOTSUPP) {
- dev_err(dai->dev, "simple-card: set_sysclk error\n");
+ if (ret)
return ret;
- }
}
if (simple_dai->slots) {
Currently a default value of 0 is used for system clock (sysclk) source and id. This may not be the case always when a DAI supports multiple clocks and multiple sources for sysclk. A specific configuration may be needed depending on the platform. Use DT properties "system-clock-id" and "system-clock-source" from CPU/Codec DAI or endpoint subnode to explicitly mention about the sysclk id and source. The DAI callback can take necessary action depending on this. In doing so expose a helper function asoc_simple_set_sysclk() to setup the sysclk. This way configuration can be driven from DT and driver need not program specific values explicitly. For example, RT5658 Codec has multiple sources for MCLK. The exact source can be specified in Codec DAI or endpoint subnode in DT. codec-subnode { ... system-clock-id = <...>; system-clock-source = <...>; ... }; The default sysclk id and source are 0 in the driver and hence nothing needs to be specified if default values are good enough. Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Sameer Pujar <spujar@nvidia.com> --- include/sound/simple_card_utils.h | 2 ++ sound/soc/generic/simple-card-utils.c | 59 +++++++++++++++++++++++++---------- 2 files changed, 45 insertions(+), 16 deletions(-)