summaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/arizona.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-07-04 18:32:05 +0200
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-07-04 20:15:45 +0200
commit5b2eec3f98e08a8442ada41c4a63658b95a355f2 (patch)
tree50ab53b1ab5496a232c753095cee31d51dc4465a /sound/soc/codecs/arizona.c
parentASoC: arizona: Rename current rates tables to bclk_rates (diff)
downloadlinux-5b2eec3f98e08a8442ada41c4a63658b95a355f2.tar.xz
linux-5b2eec3f98e08a8442ada41c4a63658b95a355f2.zip
ASoC: arizona: Implement AIF clock configuration
Allow the user to select which of the system clocks each AIF is referenced to and constran the DAI to the set of frequencies which can be generated from that clock. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/arizona.c')
-rw-r--r--sound/soc/codecs/arizona.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index 67760b4ea24c..8e5246ca5550 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -385,6 +385,29 @@ static const int arizona_48k_bclk_rates[] = {
24576000,
};
+static const unsigned int arizona_48k_rates[] = {
+ 12000,
+ 24000,
+ 48000,
+ 96000,
+ 192000,
+ 384000,
+ 768000,
+ 4000,
+ 8000,
+ 16000,
+ 32000,
+ 64000,
+ 128000,
+ 256000,
+ 512000,
+};
+
+static const struct snd_pcm_hw_constraint_list arizona_48k_constraint = {
+ .count = ARRAY_SIZE(arizona_48k_rates),
+ .list = arizona_48k_rates,
+};
+
static const int arizona_44k1_bclk_rates[] = {
-1,
44100,
@@ -407,6 +430,21 @@ static const int arizona_44k1_bclk_rates[] = {
22579200,
};
+static const unsigned int arizona_44k1_rates[] = {
+ 11025,
+ 22050,
+ 44100,
+ 88200,
+ 176400,
+ 352800,
+ 705600,
+};
+
+static const struct snd_pcm_hw_constraint_list arizona_44k1_constraint = {
+ .count = ARRAY_SIZE(arizona_44k1_rates),
+ .list = arizona_44k1_rates,
+};
+
static int arizona_sr_vals[] = {
0,
12000,
@@ -434,6 +472,36 @@ static int arizona_sr_vals[] = {
512000,
};
+static int arizona_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+ struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
+ const struct snd_pcm_hw_constraint_list *constraint;
+ unsigned int base_rate;
+
+ switch (dai_priv->clk) {
+ case ARIZONA_CLK_SYSCLK:
+ base_rate = priv->sysclk;
+ break;
+ case ARIZONA_CLK_ASYNCCLK:
+ base_rate = priv->asyncclk;
+ break;
+ default:
+ return 0;
+ }
+
+ if (base_rate % 8000)
+ constraint = &arizona_44k1_constraint;
+ else
+ constraint = &arizona_48k_constraint;
+
+ return snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ constraint);
+}
+
static int arizona_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -501,11 +569,49 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
return 0;
}
+static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+ struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
+
+ switch (clk_id) {
+ case ARIZONA_CLK_SYSCLK:
+ case ARIZONA_CLK_ASYNCCLK:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (clk_id != dai_priv->clk && dai->active) {
+ dev_err(codec->dev, "Can't change clock on active DAI %d\n",
+ dai->id);
+ return -EBUSY;
+ }
+
+ dai_priv->clk = clk_id;
+
+ return 0;
+}
+
const struct snd_soc_dai_ops arizona_dai_ops = {
+ .startup = arizona_startup,
.set_fmt = arizona_set_fmt,
.hw_params = arizona_hw_params,
+ .set_sysclk = arizona_dai_set_sysclk,
};
+int arizona_init_dai(struct arizona_priv *priv, int id)
+{
+ struct arizona_dai_priv *dai_priv = &priv->dai[id];
+
+ dai_priv->clk = ARIZONA_CLK_SYSCLK;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(arizona_init_dai);
+
static irqreturn_t arizona_fll_lock(int irq, void *data)
{
struct arizona_fll *fll = data;