aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-03-07 15:58:11 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-03-08 13:56:16 -0500
commitec4ee52a8f5fb5b8e235ae9f02589d60d54740cc (patch)
tree329a7b4031c899b67f86a28b1ae77f295f3bfbec
parentb993f92b99288d4b3a1a1237f3e40fa6460e4b47 (diff)
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: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by: Liam Girdwood <lrg@ti.com>
-rw-r--r--include/sound/soc.h11
-rw-r--r--sound/soc/soc-core.c46
2 files changed, 57 insertions, 0 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 6f197589b6d7..14f601f3e189 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -259,6 +259,11 @@ enum snd_soc_compress_type {
259 SND_SOC_RBTREE_COMPRESSION 259 SND_SOC_RBTREE_COMPRESSION
260}; 260};
261 261
262int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id,
263 unsigned int freq, int dir);
264int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
265 unsigned int freq_in, unsigned int freq_out);
266
262int snd_soc_register_card(struct snd_soc_card *card); 267int snd_soc_register_card(struct snd_soc_card *card);
263int snd_soc_unregister_card(struct snd_soc_card *card); 268int snd_soc_unregister_card(struct snd_soc_card *card);
264int snd_soc_suspend(struct device *dev); 269int snd_soc_suspend(struct device *dev);
@@ -568,6 +573,12 @@ struct snd_soc_codec_driver {
568 const struct snd_soc_dapm_route *dapm_routes; 573 const struct snd_soc_dapm_route *dapm_routes;
569 int num_dapm_routes; 574 int num_dapm_routes;
570 575
576 /* codec wide operations */
577 int (*set_sysclk)(struct snd_soc_codec *codec,
578 int clk_id, unsigned int freq, int dir);
579 int (*set_pll)(struct snd_soc_codec *codec, int pll_id, int source,
580 unsigned int freq_in, unsigned int freq_out);
581
571 /* codec IO */ 582 /* codec IO */
572 unsigned int (*read)(struct snd_soc_codec *, unsigned int); 583 unsigned int (*read)(struct snd_soc_codec *, unsigned int);
573 int (*write)(struct snd_soc_codec *, unsigned int, unsigned int); 584 int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index c12f2bd23a4e..c2ec6cb05631 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3064,12 +3064,34 @@ int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
3064{ 3064{
3065 if (dai->driver && dai->driver->ops->set_sysclk) 3065 if (dai->driver && dai->driver->ops->set_sysclk)
3066 return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir); 3066 return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir);
3067 else if (dai->codec && dai->codec->driver->set_sysclk)
3068 return dai->codec->driver->set_sysclk(dai->codec, clk_id,
3069 freq, dir);
3067 else 3070 else
3068 return -EINVAL; 3071 return -EINVAL;
3069} 3072}
3070EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk); 3073EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
3071 3074
3072/** 3075/**
3076 * snd_soc_codec_set_sysclk - configure CODEC system or master clock.
3077 * @codec: CODEC
3078 * @clk_id: DAI specific clock ID
3079 * @freq: new clock frequency in Hz
3080 * @dir: new clock direction - input/output.
3081 *
3082 * Configures the CODEC master (MCLK) or system (SYSCLK) clocking.
3083 */
3084int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id,
3085 unsigned int freq, int dir)
3086{
3087 if (codec->driver->set_sysclk)
3088 return codec->driver->set_sysclk(codec, clk_id, freq, dir);
3089 else
3090 return -EINVAL;
3091}
3092EXPORT_SYMBOL_GPL(snd_soc_codec_set_sysclk);
3093
3094/**
3073 * snd_soc_dai_set_clkdiv - configure DAI clock dividers. 3095 * snd_soc_dai_set_clkdiv - configure DAI clock dividers.
3074 * @dai: DAI 3096 * @dai: DAI
3075 * @div_id: DAI specific clock divider ID 3097 * @div_id: DAI specific clock divider ID
@@ -3105,11 +3127,35 @@ int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
3105 if (dai->driver && dai->driver->ops->set_pll) 3127 if (dai->driver && dai->driver->ops->set_pll)
3106 return dai->driver->ops->set_pll(dai, pll_id, source, 3128 return dai->driver->ops->set_pll(dai, pll_id, source,
3107 freq_in, freq_out); 3129 freq_in, freq_out);
3130 else if (dai->codec && dai->codec->driver->set_pll)
3131 return dai->codec->driver->set_pll(dai->codec, pll_id, source,
3132 freq_in, freq_out);
3108 else 3133 else
3109 return -EINVAL; 3134 return -EINVAL;
3110} 3135}
3111EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll); 3136EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
3112 3137
3138/*
3139 * snd_soc_codec_set_pll - configure codec PLL.
3140 * @codec: CODEC
3141 * @pll_id: DAI specific PLL ID
3142 * @source: DAI specific source for the PLL
3143 * @freq_in: PLL input clock frequency in Hz
3144 * @freq_out: requested PLL output clock frequency in Hz
3145 *
3146 * Configures and enables PLL to generate output clock based on input clock.
3147 */
3148int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
3149 unsigned int freq_in, unsigned int freq_out)
3150{
3151 if (codec->driver->set_pll)
3152 return codec->driver->set_pll(codec, pll_id, source,
3153 freq_in, freq_out);
3154 else
3155 return -EINVAL;
3156}
3157EXPORT_SYMBOL_GPL(snd_soc_codec_set_pll);
3158
3113/** 3159/**
3114 * snd_soc_dai_set_fmt - configure DAI hardware audio format. 3160 * snd_soc_dai_set_fmt - configure DAI hardware audio format.
3115 * @dai: DAI 3161 * @dai: DAI