summaryrefslogtreecommitdiff
path: root/sound/soc/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r--sound/soc/codecs/arizona.c106
-rw-r--r--sound/soc/codecs/arizona.h9
-rw-r--r--sound/soc/codecs/wm5102.c3
3 files changed, 118 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;
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h
index 8c2ca1d9dbae..896711e19baa 100644
--- a/sound/soc/codecs/arizona.h
+++ b/sound/soc/codecs/arizona.h
@@ -44,12 +44,19 @@
#define ARIZONA_MIXER_VOL_SHIFT 1
#define ARIZONA_MIXER_VOL_WIDTH 7
+#define ARIZONA_MAX_DAI 3
+
struct arizona;
+struct arizona_dai_priv {
+ int clk;
+};
+
struct arizona_priv {
struct arizona *arizona;
int sysclk;
int asyncclk;
+ struct arizona_dai_priv dai[ARIZONA_MAX_DAI];
};
#define ARIZONA_NUM_MIXER_INPUTS 55
@@ -146,4 +153,6 @@ extern int arizona_init_fll(struct arizona *arizona, int id, int base,
extern int arizona_set_fll(struct arizona_fll *fll, int source,
unsigned int Fref, unsigned int Fout);
+extern int arizona_init_dai(struct arizona_priv *priv, int dai);
+
#endif
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
index e76c41e1f847..be74a78e1aea 100644
--- a/sound/soc/codecs/wm5102.c
+++ b/sound/soc/codecs/wm5102.c
@@ -832,6 +832,9 @@ static int __devinit wm5102_probe(struct platform_device *pdev)
ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK,
&wm5102->fll[1]);
+ for (i = 0; i < ARRAY_SIZE(wm5102_dai); i++)
+ arizona_init_dai(&wm5102->core, i);
+
/* Latch volume update bits */
for (i = 0; i < ARRAY_SIZE(wm5102_digital_vu); i++)
regmap_update_bits(arizona->regmap, wm5102_digital_vu[i],