Commit ec4ee52a authored by Mark Brown's avatar Mark Brown

ASoC: Provide CODEC clocking operations and API calls

When multi component systems use DAIless amplifiers which require clocking
configuration it is at best hard to use the current clocking API as this
requires a DAI even though the device may not even have one. Address this
by adding set_sysclk() and set_pll() operations and APIs for CODECs.

In order to avoid issues with devices which could be used either with or
without DAIs make the DAI variants call through to their CODEC counterparts
if there is no DAI specific operation. Converting over entirely would create
problems for multi-DAI devices which offer per-DAI clocking setup.
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: default avatarLiam Girdwood <lrg@ti.com>
parent b993f92b
...@@ -259,6 +259,11 @@ enum snd_soc_compress_type { ...@@ -259,6 +259,11 @@ enum snd_soc_compress_type {
SND_SOC_RBTREE_COMPRESSION SND_SOC_RBTREE_COMPRESSION
}; };
int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id,
unsigned int freq, int dir);
int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
unsigned int freq_in, unsigned int freq_out);
int snd_soc_register_card(struct snd_soc_card *card); int snd_soc_register_card(struct snd_soc_card *card);
int snd_soc_unregister_card(struct snd_soc_card *card); int snd_soc_unregister_card(struct snd_soc_card *card);
int snd_soc_suspend(struct device *dev); int snd_soc_suspend(struct device *dev);
...@@ -568,6 +573,12 @@ struct snd_soc_codec_driver { ...@@ -568,6 +573,12 @@ struct snd_soc_codec_driver {
const struct snd_soc_dapm_route *dapm_routes; const struct snd_soc_dapm_route *dapm_routes;
int num_dapm_routes; int num_dapm_routes;
/* codec wide operations */
int (*set_sysclk)(struct snd_soc_codec *codec,
int clk_id, unsigned int freq, int dir);
int (*set_pll)(struct snd_soc_codec *codec, int pll_id, int source,
unsigned int freq_in, unsigned int freq_out);
/* codec IO */ /* codec IO */
unsigned int (*read)(struct snd_soc_codec *, unsigned int); unsigned int (*read)(struct snd_soc_codec *, unsigned int);
int (*write)(struct snd_soc_codec *, unsigned int, unsigned int); int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
......
...@@ -3064,11 +3064,33 @@ int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, ...@@ -3064,11 +3064,33 @@ int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
{ {
if (dai->driver && dai->driver->ops->set_sysclk) if (dai->driver && dai->driver->ops->set_sysclk)
return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir); return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir);
else if (dai->codec && dai->codec->driver->set_sysclk)
return dai->codec->driver->set_sysclk(dai->codec, clk_id,
freq, dir);
else else
return -EINVAL; return -EINVAL;
} }
EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk); EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
/**
* snd_soc_codec_set_sysclk - configure CODEC system or master clock.
* @codec: CODEC
* @clk_id: DAI specific clock ID
* @freq: new clock frequency in Hz
* @dir: new clock direction - input/output.
*
* Configures the CODEC master (MCLK) or system (SYSCLK) clocking.
*/
int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id,
unsigned int freq, int dir)
{
if (codec->driver->set_sysclk)
return codec->driver->set_sysclk(codec, clk_id, freq, dir);
else
return -EINVAL;
}
EXPORT_SYMBOL_GPL(snd_soc_codec_set_sysclk);
/** /**
* snd_soc_dai_set_clkdiv - configure DAI clock dividers. * snd_soc_dai_set_clkdiv - configure DAI clock dividers.
* @dai: DAI * @dai: DAI
...@@ -3105,11 +3127,35 @@ int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source, ...@@ -3105,11 +3127,35 @@ int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
if (dai->driver && dai->driver->ops->set_pll) if (dai->driver && dai->driver->ops->set_pll)
return dai->driver->ops->set_pll(dai, pll_id, source, return dai->driver->ops->set_pll(dai, pll_id, source,
freq_in, freq_out); freq_in, freq_out);
else if (dai->codec && dai->codec->driver->set_pll)
return dai->codec->driver->set_pll(dai->codec, pll_id, source,
freq_in, freq_out);
else else
return -EINVAL; return -EINVAL;
} }
EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll); EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
/*
* snd_soc_codec_set_pll - configure codec PLL.
* @codec: CODEC
* @pll_id: DAI specific PLL ID
* @source: DAI specific source for the PLL
* @freq_in: PLL input clock frequency in Hz
* @freq_out: requested PLL output clock frequency in Hz
*
* Configures and enables PLL to generate output clock based on input clock.
*/
int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
unsigned int freq_in, unsigned int freq_out)
{
if (codec->driver->set_pll)
return codec->driver->set_pll(codec, pll_id, source,
freq_in, freq_out);
else
return -EINVAL;
}
EXPORT_SYMBOL_GPL(snd_soc_codec_set_pll);
/** /**
* snd_soc_dai_set_fmt - configure DAI hardware audio format. * snd_soc_dai_set_fmt - configure DAI hardware audio format.
* @dai: DAI * @dai: DAI
......
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