aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-07-04 12:32:05 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-07-04 14:15:45 -0400
commit5b2eec3f98e08a8442ada41c4a63658b95a355f2 (patch)
tree50ab53b1ab5496a232c753095cee31d51dc4465a /sound/soc/codecs
parent949e6bc75fea779b433679601641ea641456283b (diff)
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')
-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[] = {
385 24576000, 385 24576000,
386}; 386};
387 387
388static const unsigned int arizona_48k_rates[] = {
389 12000,
390 24000,
391 48000,
392 96000,
393 192000,
394 384000,
395 768000,
396 4000,
397 8000,
398 16000,
399 32000,
400 64000,
401 128000,
402 256000,
403 512000,
404};
405
406static const struct snd_pcm_hw_constraint_list arizona_48k_constraint = {
407 .count = ARRAY_SIZE(arizona_48k_rates),
408 .list = arizona_48k_rates,
409};
410
388static const int arizona_44k1_bclk_rates[] = { 411static const int arizona_44k1_bclk_rates[] = {
389 -1, 412 -1,
390 44100, 413 44100,
@@ -407,6 +430,21 @@ static const int arizona_44k1_bclk_rates[] = {
407 22579200, 430 22579200,
408}; 431};
409 432
433static const unsigned int arizona_44k1_rates[] = {
434 11025,
435 22050,
436 44100,
437 88200,
438 176400,
439 352800,
440 705600,
441};
442
443static const struct snd_pcm_hw_constraint_list arizona_44k1_constraint = {
444 .count = ARRAY_SIZE(arizona_44k1_rates),
445 .list = arizona_44k1_rates,
446};
447
410static int arizona_sr_vals[] = { 448static int arizona_sr_vals[] = {
411 0, 449 0,
412 12000, 450 12000,
@@ -434,6 +472,36 @@ static int arizona_sr_vals[] = {
434 512000, 472 512000,
435}; 473};
436 474
475static int arizona_startup(struct snd_pcm_substream *substream,
476 struct snd_soc_dai *dai)
477{
478 struct snd_soc_codec *codec = dai->codec;
479 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
480 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
481 const struct snd_pcm_hw_constraint_list *constraint;
482 unsigned int base_rate;
483
484 switch (dai_priv->clk) {
485 case ARIZONA_CLK_SYSCLK:
486 base_rate = priv->sysclk;
487 break;
488 case ARIZONA_CLK_ASYNCCLK:
489 base_rate = priv->asyncclk;
490 break;
491 default:
492 return 0;
493 }
494
495 if (base_rate % 8000)
496 constraint = &arizona_44k1_constraint;
497 else
498 constraint = &arizona_48k_constraint;
499
500 return snd_pcm_hw_constraint_list(substream->runtime, 0,
501 SNDRV_PCM_HW_PARAM_RATE,
502 constraint);
503}
504
437static int arizona_hw_params(struct snd_pcm_substream *substream, 505static int arizona_hw_params(struct snd_pcm_substream *substream,
438 struct snd_pcm_hw_params *params, 506 struct snd_pcm_hw_params *params,
439 struct snd_soc_dai *dai) 507 struct snd_soc_dai *dai)
@@ -501,11 +569,49 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
501 return 0; 569 return 0;
502} 570}
503 571
572static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
573 int clk_id, unsigned int freq, int dir)
574{
575 struct snd_soc_codec *codec = dai->codec;
576 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
577 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
578
579 switch (clk_id) {
580 case ARIZONA_CLK_SYSCLK:
581 case ARIZONA_CLK_ASYNCCLK:
582 break;
583 default:
584 return -EINVAL;
585 }
586
587 if (clk_id != dai_priv->clk && dai->active) {
588 dev_err(codec->dev, "Can't change clock on active DAI %d\n",
589 dai->id);
590 return -EBUSY;
591 }
592
593 dai_priv->clk = clk_id;
594
595 return 0;
596}
597
504const struct snd_soc_dai_ops arizona_dai_ops = { 598const struct snd_soc_dai_ops arizona_dai_ops = {
599 .startup = arizona_startup,
505 .set_fmt = arizona_set_fmt, 600 .set_fmt = arizona_set_fmt,
506 .hw_params = arizona_hw_params, 601 .hw_params = arizona_hw_params,
602 .set_sysclk = arizona_dai_set_sysclk,
507}; 603};
508 604
605int arizona_init_dai(struct arizona_priv *priv, int id)
606{
607 struct arizona_dai_priv *dai_priv = &priv->dai[id];
608
609 dai_priv->clk = ARIZONA_CLK_SYSCLK;
610
611 return 0;
612}
613EXPORT_SYMBOL_GPL(arizona_init_dai);
614
509static irqreturn_t arizona_fll_lock(int irq, void *data) 615static irqreturn_t arizona_fll_lock(int irq, void *data)
510{ 616{
511 struct arizona_fll *fll = data; 617 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 @@
44#define ARIZONA_MIXER_VOL_SHIFT 1 44#define ARIZONA_MIXER_VOL_SHIFT 1
45#define ARIZONA_MIXER_VOL_WIDTH 7 45#define ARIZONA_MIXER_VOL_WIDTH 7
46 46
47#define ARIZONA_MAX_DAI 3
48
47struct arizona; 49struct arizona;
48 50
51struct arizona_dai_priv {
52 int clk;
53};
54
49struct arizona_priv { 55struct arizona_priv {
50 struct arizona *arizona; 56 struct arizona *arizona;
51 int sysclk; 57 int sysclk;
52 int asyncclk; 58 int asyncclk;
59 struct arizona_dai_priv dai[ARIZONA_MAX_DAI];
53}; 60};
54 61
55#define ARIZONA_NUM_MIXER_INPUTS 55 62#define ARIZONA_NUM_MIXER_INPUTS 55
@@ -146,4 +153,6 @@ extern int arizona_init_fll(struct arizona *arizona, int id, int base,
146extern int arizona_set_fll(struct arizona_fll *fll, int source, 153extern int arizona_set_fll(struct arizona_fll *fll, int source,
147 unsigned int Fref, unsigned int Fout); 154 unsigned int Fref, unsigned int Fout);
148 155
156extern int arizona_init_dai(struct arizona_priv *priv, int dai);
157
149#endif 158#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)
832 ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK, 832 ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK,
833 &wm5102->fll[1]); 833 &wm5102->fll[1]);
834 834
835 for (i = 0; i < ARRAY_SIZE(wm5102_dai); i++)
836 arizona_init_dai(&wm5102->core, i);
837
835 /* Latch volume update bits */ 838 /* Latch volume update bits */
836 for (i = 0; i < ARRAY_SIZE(wm5102_digital_vu); i++) 839 for (i = 0; i < ARRAY_SIZE(wm5102_digital_vu); i++)
837 regmap_update_bits(arizona->regmap, wm5102_digital_vu[i], 840 regmap_update_bits(arizona->regmap, wm5102_digital_vu[i],