diff options
-rw-r--r-- | sound/soc/codecs/arizona.c | 106 | ||||
-rw-r--r-- | sound/soc/codecs/arizona.h | 9 | ||||
-rw-r--r-- | sound/soc/codecs/wm5102.c | 3 |
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 | ||
388 | static 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 | |||
406 | static const struct snd_pcm_hw_constraint_list arizona_48k_constraint = { | ||
407 | .count = ARRAY_SIZE(arizona_48k_rates), | ||
408 | .list = arizona_48k_rates, | ||
409 | }; | ||
410 | |||
388 | static const int arizona_44k1_bclk_rates[] = { | 411 | static 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 | ||
433 | static const unsigned int arizona_44k1_rates[] = { | ||
434 | 11025, | ||
435 | 22050, | ||
436 | 44100, | ||
437 | 88200, | ||
438 | 176400, | ||
439 | 352800, | ||
440 | 705600, | ||
441 | }; | ||
442 | |||
443 | static const struct snd_pcm_hw_constraint_list arizona_44k1_constraint = { | ||
444 | .count = ARRAY_SIZE(arizona_44k1_rates), | ||
445 | .list = arizona_44k1_rates, | ||
446 | }; | ||
447 | |||
410 | static int arizona_sr_vals[] = { | 448 | static 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 | ||
475 | static 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 | |||
437 | static int arizona_hw_params(struct snd_pcm_substream *substream, | 505 | static 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 | ||
572 | static 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 | |||
504 | const struct snd_soc_dai_ops arizona_dai_ops = { | 598 | const 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 | ||
605 | int 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 | } | ||
613 | EXPORT_SYMBOL_GPL(arizona_init_dai); | ||
614 | |||
509 | static irqreturn_t arizona_fll_lock(int irq, void *data) | 615 | static 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 | |||
47 | struct arizona; | 49 | struct arizona; |
48 | 50 | ||
51 | struct arizona_dai_priv { | ||
52 | int clk; | ||
53 | }; | ||
54 | |||
49 | struct arizona_priv { | 55 | struct 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, | |||
146 | extern int arizona_set_fll(struct arizona_fll *fll, int source, | 153 | extern 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 | ||
156 | extern 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], |