diff options
Diffstat (limited to 'sound/soc')
-rw-r--r-- | sound/soc/codecs/wm8741.c | 62 | ||||
-rw-r--r-- | sound/soc/codecs/wm8753.c | 6 | ||||
-rw-r--r-- | sound/soc/codecs/wm8904.c | 4 | ||||
-rw-r--r-- | sound/soc/codecs/wm8960.c | 220 | ||||
-rw-r--r-- | sound/soc/codecs/wm8960.h | 1 | ||||
-rw-r--r-- | sound/soc/codecs/wm8983.c | 80 |
6 files changed, 211 insertions, 162 deletions
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 430fa7ded713..de42c0388772 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c | |||
@@ -61,25 +61,6 @@ static const struct reg_default wm8741_reg_defaults[] = { | |||
61 | { 32, 0x0002 }, /* R32 - ADDITONAL_CONTROL_1 */ | 61 | { 32, 0x0002 }, /* R32 - ADDITONAL_CONTROL_1 */ |
62 | }; | 62 | }; |
63 | 63 | ||
64 | static bool wm8741_readable(struct device *dev, unsigned int reg) | ||
65 | { | ||
66 | switch (reg) { | ||
67 | case WM8741_DACLLSB_ATTENUATION: | ||
68 | case WM8741_DACLMSB_ATTENUATION: | ||
69 | case WM8741_DACRLSB_ATTENUATION: | ||
70 | case WM8741_DACRMSB_ATTENUATION: | ||
71 | case WM8741_VOLUME_CONTROL: | ||
72 | case WM8741_FORMAT_CONTROL: | ||
73 | case WM8741_FILTER_CONTROL: | ||
74 | case WM8741_MODE_CONTROL_1: | ||
75 | case WM8741_MODE_CONTROL_2: | ||
76 | case WM8741_ADDITIONAL_CONTROL_1: | ||
77 | return true; | ||
78 | default: | ||
79 | return false; | ||
80 | } | ||
81 | } | ||
82 | |||
83 | static int wm8741_reset(struct snd_soc_codec *codec) | 64 | static int wm8741_reset(struct snd_soc_codec *codec) |
84 | { | 65 | { |
85 | return snd_soc_write(codec, WM8741_RESET, 0); | 66 | return snd_soc_write(codec, WM8741_RESET, 0); |
@@ -278,51 +259,38 @@ static int wm8741_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
278 | switch (freq) { | 259 | switch (freq) { |
279 | case 0: | 260 | case 0: |
280 | wm8741->sysclk_constraints = NULL; | 261 | wm8741->sysclk_constraints = NULL; |
281 | wm8741->sysclk = freq; | 262 | break; |
282 | return 0; | ||
283 | |||
284 | case 11289600: | 263 | case 11289600: |
285 | wm8741->sysclk_constraints = &constraints_11289; | 264 | wm8741->sysclk_constraints = &constraints_11289; |
286 | wm8741->sysclk = freq; | 265 | break; |
287 | return 0; | ||
288 | |||
289 | case 12288000: | 266 | case 12288000: |
290 | wm8741->sysclk_constraints = &constraints_12288; | 267 | wm8741->sysclk_constraints = &constraints_12288; |
291 | wm8741->sysclk = freq; | 268 | break; |
292 | return 0; | ||
293 | |||
294 | case 16384000: | 269 | case 16384000: |
295 | wm8741->sysclk_constraints = &constraints_16384; | 270 | wm8741->sysclk_constraints = &constraints_16384; |
296 | wm8741->sysclk = freq; | 271 | break; |
297 | return 0; | ||
298 | |||
299 | case 16934400: | 272 | case 16934400: |
300 | wm8741->sysclk_constraints = &constraints_16934; | 273 | wm8741->sysclk_constraints = &constraints_16934; |
301 | wm8741->sysclk = freq; | 274 | break; |
302 | return 0; | ||
303 | |||
304 | case 18432000: | 275 | case 18432000: |
305 | wm8741->sysclk_constraints = &constraints_18432; | 276 | wm8741->sysclk_constraints = &constraints_18432; |
306 | wm8741->sysclk = freq; | 277 | break; |
307 | return 0; | ||
308 | |||
309 | case 22579200: | 278 | case 22579200: |
310 | case 33868800: | 279 | case 33868800: |
311 | wm8741->sysclk_constraints = &constraints_22579; | 280 | wm8741->sysclk_constraints = &constraints_22579; |
312 | wm8741->sysclk = freq; | 281 | break; |
313 | return 0; | ||
314 | |||
315 | case 24576000: | 282 | case 24576000: |
316 | wm8741->sysclk_constraints = &constraints_24576; | 283 | wm8741->sysclk_constraints = &constraints_24576; |
317 | wm8741->sysclk = freq; | 284 | break; |
318 | return 0; | ||
319 | |||
320 | case 36864000: | 285 | case 36864000: |
321 | wm8741->sysclk_constraints = &constraints_36864; | 286 | wm8741->sysclk_constraints = &constraints_36864; |
322 | wm8741->sysclk = freq; | 287 | break; |
323 | return 0; | 288 | default: |
289 | return -EINVAL; | ||
324 | } | 290 | } |
325 | return -EINVAL; | 291 | |
292 | wm8741->sysclk = freq; | ||
293 | return 0; | ||
326 | } | 294 | } |
327 | 295 | ||
328 | static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai, | 296 | static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai, |
@@ -554,8 +522,6 @@ static const struct regmap_config wm8741_regmap = { | |||
554 | .reg_defaults = wm8741_reg_defaults, | 522 | .reg_defaults = wm8741_reg_defaults, |
555 | .num_reg_defaults = ARRAY_SIZE(wm8741_reg_defaults), | 523 | .num_reg_defaults = ARRAY_SIZE(wm8741_reg_defaults), |
556 | .cache_type = REGCACHE_RBTREE, | 524 | .cache_type = REGCACHE_RBTREE, |
557 | |||
558 | .readable_reg = wm8741_readable, | ||
559 | }; | 525 | }; |
560 | 526 | ||
561 | static int wm8741_set_pdata(struct device *dev, struct wm8741_priv *wm8741) | 527 | static int wm8741_set_pdata(struct device *dev, struct wm8741_priv *wm8741) |
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 0e946f3da1c0..a801c6d75436 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c | |||
@@ -138,11 +138,6 @@ static bool wm8753_volatile(struct device *dev, unsigned int reg) | |||
138 | return reg == WM8753_RESET; | 138 | return reg == WM8753_RESET; |
139 | } | 139 | } |
140 | 140 | ||
141 | static bool wm8753_writeable(struct device *dev, unsigned int reg) | ||
142 | { | ||
143 | return reg <= WM8753_ADCTL2; | ||
144 | } | ||
145 | |||
146 | /* codec private data */ | 141 | /* codec private data */ |
147 | struct wm8753_priv { | 142 | struct wm8753_priv { |
148 | struct regmap *regmap; | 143 | struct regmap *regmap; |
@@ -1509,7 +1504,6 @@ static const struct regmap_config wm8753_regmap = { | |||
1509 | .val_bits = 9, | 1504 | .val_bits = 9, |
1510 | 1505 | ||
1511 | .max_register = WM8753_ADCTL2, | 1506 | .max_register = WM8753_ADCTL2, |
1512 | .writeable_reg = wm8753_writeable, | ||
1513 | .volatile_reg = wm8753_volatile, | 1507 | .volatile_reg = wm8753_volatile, |
1514 | 1508 | ||
1515 | .cache_type = REGCACHE_RBTREE, | 1509 | .cache_type = REGCACHE_RBTREE, |
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 145f5f9d581b..b783743dc97e 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c | |||
@@ -1837,7 +1837,9 @@ static int wm8904_set_bias_level(struct snd_soc_codec *codec, | |||
1837 | 1837 | ||
1838 | switch (level) { | 1838 | switch (level) { |
1839 | case SND_SOC_BIAS_ON: | 1839 | case SND_SOC_BIAS_ON: |
1840 | clk_prepare_enable(wm8904->mclk); | 1840 | ret = clk_prepare_enable(wm8904->mclk); |
1841 | if (ret) | ||
1842 | return ret; | ||
1841 | break; | 1843 | break; |
1842 | 1844 | ||
1843 | case SND_SOC_BIAS_PREPARE: | 1845 | case SND_SOC_BIAS_PREPARE: |
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 1ed0720b41f0..e3b7d0c57411 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c | |||
@@ -48,6 +48,9 @@ | |||
48 | #define WM8960_DISOP 0x40 | 48 | #define WM8960_DISOP 0x40 |
49 | #define WM8960_DRES_MASK 0x30 | 49 | #define WM8960_DRES_MASK 0x30 |
50 | 50 | ||
51 | static bool is_pll_freq_available(unsigned int source, unsigned int target); | ||
52 | static int wm8960_set_pll(struct snd_soc_codec *codec, | ||
53 | unsigned int freq_in, unsigned int freq_out); | ||
51 | /* | 54 | /* |
52 | * wm8960 register cache | 55 | * wm8960 register cache |
53 | * We can't read the WM8960 register space when we are | 56 | * We can't read the WM8960 register space when we are |
@@ -126,9 +129,12 @@ struct wm8960_priv { | |||
126 | struct snd_soc_dapm_widget *rout1; | 129 | struct snd_soc_dapm_widget *rout1; |
127 | struct snd_soc_dapm_widget *out3; | 130 | struct snd_soc_dapm_widget *out3; |
128 | bool deemph; | 131 | bool deemph; |
129 | int playback_fs; | 132 | int lrclk; |
130 | int bclk; | 133 | int bclk; |
131 | int sysclk; | 134 | int sysclk; |
135 | int clk_id; | ||
136 | int freq_in; | ||
137 | bool is_stream_in_use[2]; | ||
132 | struct wm8960_data pdata; | 138 | struct wm8960_data pdata; |
133 | }; | 139 | }; |
134 | 140 | ||
@@ -164,8 +170,8 @@ static int wm8960_set_deemph(struct snd_soc_codec *codec) | |||
164 | if (wm8960->deemph) { | 170 | if (wm8960->deemph) { |
165 | best = 1; | 171 | best = 1; |
166 | for (i = 2; i < ARRAY_SIZE(deemph_settings); i++) { | 172 | for (i = 2; i < ARRAY_SIZE(deemph_settings); i++) { |
167 | if (abs(deemph_settings[i] - wm8960->playback_fs) < | 173 | if (abs(deemph_settings[i] - wm8960->lrclk) < |
168 | abs(deemph_settings[best] - wm8960->playback_fs)) | 174 | abs(deemph_settings[best] - wm8960->lrclk)) |
169 | best = i; | 175 | best = i; |
170 | } | 176 | } |
171 | 177 | ||
@@ -565,6 +571,9 @@ static struct { | |||
565 | { 8000, 5 }, | 571 | { 8000, 5 }, |
566 | }; | 572 | }; |
567 | 573 | ||
574 | /* -1 for reserved value */ | ||
575 | static const int sysclk_divs[] = { 1, -1, 2, -1 }; | ||
576 | |||
568 | /* Multiply 256 for internal 256 div */ | 577 | /* Multiply 256 for internal 256 div */ |
569 | static const int dac_divs[] = { 256, 384, 512, 768, 1024, 1408, 1536 }; | 578 | static const int dac_divs[] = { 256, 384, 512, 768, 1024, 1408, 1536 }; |
570 | 579 | ||
@@ -574,61 +583,110 @@ static const int bclk_divs[] = { | |||
574 | 120, 160, 220, 240, 320, 320, 320 | 583 | 120, 160, 220, 240, 320, 320, 320 |
575 | }; | 584 | }; |
576 | 585 | ||
577 | static void wm8960_configure_clocking(struct snd_soc_codec *codec, | 586 | static int wm8960_configure_clocking(struct snd_soc_codec *codec) |
578 | bool tx, int lrclk) | ||
579 | { | 587 | { |
580 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | 588 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
589 | int sysclk, bclk, lrclk, freq_out, freq_in; | ||
581 | u16 iface1 = snd_soc_read(codec, WM8960_IFACE1); | 590 | u16 iface1 = snd_soc_read(codec, WM8960_IFACE1); |
582 | u16 iface2 = snd_soc_read(codec, WM8960_IFACE2); | 591 | int i, j, k; |
583 | u32 sysclk; | ||
584 | int i, j; | ||
585 | 592 | ||
586 | if (!(iface1 & (1<<6))) { | 593 | if (!(iface1 & (1<<6))) { |
587 | dev_dbg(codec->dev, | 594 | dev_dbg(codec->dev, |
588 | "Codec is slave mode, no need to configure clock\n"); | 595 | "Codec is slave mode, no need to configure clock\n"); |
589 | return; | 596 | return 0; |
597 | } | ||
598 | |||
599 | if (wm8960->clk_id != WM8960_SYSCLK_MCLK && !wm8960->freq_in) { | ||
600 | dev_err(codec->dev, "No MCLK configured\n"); | ||
601 | return -EINVAL; | ||
590 | } | 602 | } |
591 | 603 | ||
592 | if (!wm8960->sysclk) { | 604 | freq_in = wm8960->freq_in; |
593 | dev_dbg(codec->dev, "No SYSCLK configured\n"); | 605 | bclk = wm8960->bclk; |
594 | return; | 606 | lrclk = wm8960->lrclk; |
607 | /* | ||
608 | * If it's sysclk auto mode, check if the MCLK can provide sysclk or | ||
609 | * not. If MCLK can provide sysclk, using MCLK to provide sysclk | ||
610 | * directly. Otherwise, auto select a available pll out frequency | ||
611 | * and set PLL. | ||
612 | */ | ||
613 | if (wm8960->clk_id == WM8960_SYSCLK_AUTO) { | ||
614 | /* disable the PLL and using MCLK to provide sysclk */ | ||
615 | wm8960_set_pll(codec, 0, 0); | ||
616 | freq_out = freq_in; | ||
617 | } else if (wm8960->sysclk) { | ||
618 | freq_out = wm8960->sysclk; | ||
619 | } else { | ||
620 | dev_err(codec->dev, "No SYSCLK configured\n"); | ||
621 | return -EINVAL; | ||
595 | } | 622 | } |
596 | 623 | ||
597 | if (!wm8960->bclk || !lrclk) { | 624 | /* check if the sysclk frequency is available. */ |
598 | dev_dbg(codec->dev, "No audio clocks configured\n"); | 625 | for (i = 0; i < ARRAY_SIZE(sysclk_divs); ++i) { |
599 | return; | 626 | if (sysclk_divs[i] == -1) |
627 | continue; | ||
628 | sysclk = freq_out / sysclk_divs[i]; | ||
629 | for (j = 0; j < ARRAY_SIZE(dac_divs); ++j) { | ||
630 | if (sysclk == dac_divs[j] * lrclk) { | ||
631 | for (k = 0; k < ARRAY_SIZE(bclk_divs); ++k) | ||
632 | if (sysclk == bclk * bclk_divs[k] / 10) | ||
633 | break; | ||
634 | if (k != ARRAY_SIZE(bclk_divs)) | ||
635 | break; | ||
636 | } | ||
637 | } | ||
638 | if (j != ARRAY_SIZE(dac_divs)) | ||
639 | break; | ||
600 | } | 640 | } |
601 | 641 | ||
602 | for (i = 0; i < ARRAY_SIZE(dac_divs); ++i) { | 642 | if (i != ARRAY_SIZE(sysclk_divs)) { |
603 | if (wm8960->sysclk == lrclk * dac_divs[i]) { | 643 | goto configure_clock; |
604 | for (j = 0; j < ARRAY_SIZE(bclk_divs); ++j) { | 644 | } else if (wm8960->clk_id != WM8960_SYSCLK_AUTO) { |
605 | sysclk = wm8960->bclk * bclk_divs[j] / 10; | 645 | dev_err(codec->dev, "failed to configure clock\n"); |
606 | if (wm8960->sysclk == sysclk) | 646 | return -EINVAL; |
647 | } | ||
648 | /* get a available pll out frequency and set pll */ | ||
649 | for (i = 0; i < ARRAY_SIZE(sysclk_divs); ++i) { | ||
650 | if (sysclk_divs[i] == -1) | ||
651 | continue; | ||
652 | for (j = 0; j < ARRAY_SIZE(dac_divs); ++j) { | ||
653 | sysclk = lrclk * dac_divs[j]; | ||
654 | freq_out = sysclk * sysclk_divs[i]; | ||
655 | |||
656 | for (k = 0; k < ARRAY_SIZE(bclk_divs); ++k) { | ||
657 | if (sysclk == bclk * bclk_divs[k] / 10 && | ||
658 | is_pll_freq_available(freq_in, freq_out)) { | ||
659 | wm8960_set_pll(codec, | ||
660 | freq_in, freq_out); | ||
607 | break; | 661 | break; |
662 | } else { | ||
663 | continue; | ||
664 | } | ||
608 | } | 665 | } |
609 | if(j != ARRAY_SIZE(bclk_divs)) | 666 | if (k != ARRAY_SIZE(bclk_divs)) |
610 | break; | 667 | break; |
611 | } | 668 | } |
669 | if (j != ARRAY_SIZE(dac_divs)) | ||
670 | break; | ||
612 | } | 671 | } |
613 | 672 | ||
614 | if (i == ARRAY_SIZE(dac_divs)) { | 673 | if (i == ARRAY_SIZE(sysclk_divs)) { |
615 | dev_err(codec->dev, "Unsupported sysclk %d\n", wm8960->sysclk); | 674 | dev_err(codec->dev, "failed to configure clock\n"); |
616 | return; | 675 | return -EINVAL; |
617 | } | 676 | } |
618 | 677 | ||
619 | /* | 678 | configure_clock: |
620 | * configure frame clock. If ADCLRC configure as GPIO pin, DACLRC | 679 | /* configure sysclk clock */ |
621 | * pin is used as a frame clock for ADCs and DACs. | 680 | snd_soc_update_bits(codec, WM8960_CLOCK1, 3 << 1, i << 1); |
622 | */ | 681 | |
623 | if (iface2 & (1<<6)) | 682 | /* configure frame clock */ |
624 | snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 3, i << 3); | 683 | snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 3, j << 3); |
625 | else if (tx) | 684 | snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 6, j << 6); |
626 | snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 3, i << 3); | ||
627 | else if (!tx) | ||
628 | snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 6, i << 6); | ||
629 | 685 | ||
630 | /* configure bit clock */ | 686 | /* configure bit clock */ |
631 | snd_soc_update_bits(codec, WM8960_CLOCK2, 0xf, j); | 687 | snd_soc_update_bits(codec, WM8960_CLOCK2, 0xf, k); |
688 | |||
689 | return 0; | ||
632 | } | 690 | } |
633 | 691 | ||
634 | static int wm8960_hw_params(struct snd_pcm_substream *substream, | 692 | static int wm8960_hw_params(struct snd_pcm_substream *substream, |
@@ -667,9 +725,9 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, | |||
667 | return -EINVAL; | 725 | return -EINVAL; |
668 | } | 726 | } |
669 | 727 | ||
728 | wm8960->lrclk = params_rate(params); | ||
670 | /* Update filters for the new rate */ | 729 | /* Update filters for the new rate */ |
671 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 730 | if (tx) { |
672 | wm8960->playback_fs = params_rate(params); | ||
673 | wm8960_set_deemph(codec); | 731 | wm8960_set_deemph(codec); |
674 | } else { | 732 | } else { |
675 | for (i = 0; i < ARRAY_SIZE(alc_rates); i++) | 733 | for (i = 0; i < ARRAY_SIZE(alc_rates); i++) |
@@ -682,7 +740,23 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, | |||
682 | /* set iface */ | 740 | /* set iface */ |
683 | snd_soc_write(codec, WM8960_IFACE1, iface); | 741 | snd_soc_write(codec, WM8960_IFACE1, iface); |
684 | 742 | ||
685 | wm8960_configure_clocking(codec, tx, params_rate(params)); | 743 | wm8960->is_stream_in_use[tx] = true; |
744 | |||
745 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON && | ||
746 | !wm8960->is_stream_in_use[!tx]) | ||
747 | return wm8960_configure_clocking(codec); | ||
748 | |||
749 | return 0; | ||
750 | } | ||
751 | |||
752 | static int wm8960_hw_free(struct snd_pcm_substream *substream, | ||
753 | struct snd_soc_dai *dai) | ||
754 | { | ||
755 | struct snd_soc_codec *codec = dai->codec; | ||
756 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | ||
757 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
758 | |||
759 | wm8960->is_stream_in_use[tx] = false; | ||
686 | 760 | ||
687 | return 0; | 761 | return 0; |
688 | } | 762 | } |
@@ -702,6 +776,7 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, | |||
702 | enum snd_soc_bias_level level) | 776 | enum snd_soc_bias_level level) |
703 | { | 777 | { |
704 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | 778 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
779 | u16 pm2 = snd_soc_read(codec, WM8960_POWER2); | ||
705 | int ret; | 780 | int ret; |
706 | 781 | ||
707 | switch (level) { | 782 | switch (level) { |
@@ -721,11 +796,22 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, | |||
721 | } | 796 | } |
722 | } | 797 | } |
723 | 798 | ||
799 | ret = wm8960_configure_clocking(codec); | ||
800 | if (ret) | ||
801 | return ret; | ||
802 | |||
724 | /* Set VMID to 2x50k */ | 803 | /* Set VMID to 2x50k */ |
725 | snd_soc_update_bits(codec, WM8960_POWER1, 0x180, 0x80); | 804 | snd_soc_update_bits(codec, WM8960_POWER1, 0x180, 0x80); |
726 | break; | 805 | break; |
727 | 806 | ||
728 | case SND_SOC_BIAS_ON: | 807 | case SND_SOC_BIAS_ON: |
808 | /* | ||
809 | * If it's sysclk auto mode, and the pll is enabled, | ||
810 | * disable the pll | ||
811 | */ | ||
812 | if (wm8960->clk_id == WM8960_SYSCLK_AUTO && (pm2 & 0x1)) | ||
813 | wm8960_set_pll(codec, 0, 0); | ||
814 | |||
729 | if (!IS_ERR(wm8960->mclk)) | 815 | if (!IS_ERR(wm8960->mclk)) |
730 | clk_disable_unprepare(wm8960->mclk); | 816 | clk_disable_unprepare(wm8960->mclk); |
731 | break; | 817 | break; |
@@ -780,6 +866,7 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, | |||
780 | enum snd_soc_bias_level level) | 866 | enum snd_soc_bias_level level) |
781 | { | 867 | { |
782 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | 868 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
869 | u16 pm2 = snd_soc_read(codec, WM8960_POWER2); | ||
783 | int reg, ret; | 870 | int reg, ret; |
784 | 871 | ||
785 | switch (level) { | 872 | switch (level) { |
@@ -831,9 +918,21 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, | |||
831 | return ret; | 918 | return ret; |
832 | } | 919 | } |
833 | } | 920 | } |
921 | |||
922 | ret = wm8960_configure_clocking(codec); | ||
923 | if (ret) | ||
924 | return ret; | ||
925 | |||
834 | break; | 926 | break; |
835 | 927 | ||
836 | case SND_SOC_BIAS_ON: | 928 | case SND_SOC_BIAS_ON: |
929 | /* | ||
930 | * If it's sysclk auto mode, and the pll is enabled, | ||
931 | * disable the pll | ||
932 | */ | ||
933 | if (wm8960->clk_id == WM8960_SYSCLK_AUTO && (pm2 & 0x1)) | ||
934 | wm8960_set_pll(codec, 0, 0); | ||
935 | |||
837 | if (!IS_ERR(wm8960->mclk)) | 936 | if (!IS_ERR(wm8960->mclk)) |
838 | clk_disable_unprepare(wm8960->mclk); | 937 | clk_disable_unprepare(wm8960->mclk); |
839 | 938 | ||
@@ -892,6 +991,28 @@ struct _pll_div { | |||
892 | u32 k:24; | 991 | u32 k:24; |
893 | }; | 992 | }; |
894 | 993 | ||
994 | static bool is_pll_freq_available(unsigned int source, unsigned int target) | ||
995 | { | ||
996 | unsigned int Ndiv; | ||
997 | |||
998 | if (source == 0 || target == 0) | ||
999 | return false; | ||
1000 | |||
1001 | /* Scale up target to PLL operating frequency */ | ||
1002 | target *= 4; | ||
1003 | Ndiv = target / source; | ||
1004 | |||
1005 | if (Ndiv < 6) { | ||
1006 | source >>= 1; | ||
1007 | Ndiv = target / source; | ||
1008 | } | ||
1009 | |||
1010 | if ((Ndiv < 6) || (Ndiv > 12)) | ||
1011 | return false; | ||
1012 | |||
1013 | return true; | ||
1014 | } | ||
1015 | |||
895 | /* The size in bits of the pll divide multiplied by 10 | 1016 | /* The size in bits of the pll divide multiplied by 10 |
896 | * to allow rounding later */ | 1017 | * to allow rounding later */ |
897 | #define FIXED_PLL_SIZE ((1 << 24) * 10) | 1018 | #define FIXED_PLL_SIZE ((1 << 24) * 10) |
@@ -943,10 +1064,9 @@ static int pll_factors(unsigned int source, unsigned int target, | |||
943 | return 0; | 1064 | return 0; |
944 | } | 1065 | } |
945 | 1066 | ||
946 | static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, | 1067 | static int wm8960_set_pll(struct snd_soc_codec *codec, |
947 | int source, unsigned int freq_in, unsigned int freq_out) | 1068 | unsigned int freq_in, unsigned int freq_out) |
948 | { | 1069 | { |
949 | struct snd_soc_codec *codec = codec_dai->codec; | ||
950 | u16 reg; | 1070 | u16 reg; |
951 | static struct _pll_div pll_div; | 1071 | static struct _pll_div pll_div; |
952 | int ret; | 1072 | int ret; |
@@ -986,6 +1106,20 @@ static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, | |||
986 | return 0; | 1106 | return 0; |
987 | } | 1107 | } |
988 | 1108 | ||
1109 | static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, | ||
1110 | int source, unsigned int freq_in, unsigned int freq_out) | ||
1111 | { | ||
1112 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1113 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | ||
1114 | |||
1115 | wm8960->freq_in = freq_in; | ||
1116 | |||
1117 | if (pll_id == WM8960_SYSCLK_AUTO) | ||
1118 | return 0; | ||
1119 | |||
1120 | return wm8960_set_pll(codec, freq_in, freq_out); | ||
1121 | } | ||
1122 | |||
989 | static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai, | 1123 | static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai, |
990 | int div_id, int div) | 1124 | int div_id, int div) |
991 | { | 1125 | { |
@@ -1043,11 +1177,14 @@ static int wm8960_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, | |||
1043 | snd_soc_update_bits(codec, WM8960_CLOCK1, | 1177 | snd_soc_update_bits(codec, WM8960_CLOCK1, |
1044 | 0x1, WM8960_SYSCLK_PLL); | 1178 | 0x1, WM8960_SYSCLK_PLL); |
1045 | break; | 1179 | break; |
1180 | case WM8960_SYSCLK_AUTO: | ||
1181 | break; | ||
1046 | default: | 1182 | default: |
1047 | return -EINVAL; | 1183 | return -EINVAL; |
1048 | } | 1184 | } |
1049 | 1185 | ||
1050 | wm8960->sysclk = freq; | 1186 | wm8960->sysclk = freq; |
1187 | wm8960->clk_id = clk_id; | ||
1051 | 1188 | ||
1052 | return 0; | 1189 | return 0; |
1053 | } | 1190 | } |
@@ -1060,6 +1197,7 @@ static int wm8960_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, | |||
1060 | 1197 | ||
1061 | static const struct snd_soc_dai_ops wm8960_dai_ops = { | 1198 | static const struct snd_soc_dai_ops wm8960_dai_ops = { |
1062 | .hw_params = wm8960_hw_params, | 1199 | .hw_params = wm8960_hw_params, |
1200 | .hw_free = wm8960_hw_free, | ||
1063 | .digital_mute = wm8960_mute, | 1201 | .digital_mute = wm8960_mute, |
1064 | .set_fmt = wm8960_set_dai_fmt, | 1202 | .set_fmt = wm8960_set_dai_fmt, |
1065 | .set_clkdiv = wm8960_set_dai_clkdiv, | 1203 | .set_clkdiv = wm8960_set_dai_clkdiv, |
diff --git a/sound/soc/codecs/wm8960.h b/sound/soc/codecs/wm8960.h index 2d8163d7004b..ab3220d3411d 100644 --- a/sound/soc/codecs/wm8960.h +++ b/sound/soc/codecs/wm8960.h | |||
@@ -82,6 +82,7 @@ | |||
82 | 82 | ||
83 | #define WM8960_SYSCLK_MCLK (0 << 0) | 83 | #define WM8960_SYSCLK_MCLK (0 << 0) |
84 | #define WM8960_SYSCLK_PLL (1 << 0) | 84 | #define WM8960_SYSCLK_PLL (1 << 0) |
85 | #define WM8960_SYSCLK_AUTO (2 << 0) | ||
85 | 86 | ||
86 | #define WM8960_DAC_DIV_1 (0 << 3) | 87 | #define WM8960_DAC_DIV_1 (0 << 3) |
87 | #define WM8960_DAC_DIV_1_5 (1 << 3) | 88 | #define WM8960_DAC_DIV_1_5 (1 << 3) |
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index f6861cc4c321..f3193fb751cc 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c | |||
@@ -84,66 +84,6 @@ static const struct reg_default wm8983_defaults[] = { | |||
84 | { 0x3D, 0x0000 }, /* R61 - BIAS CTRL */ | 84 | { 0x3D, 0x0000 }, /* R61 - BIAS CTRL */ |
85 | }; | 85 | }; |
86 | 86 | ||
87 | static const struct wm8983_reg_access { | ||
88 | u16 read; /* Mask of readable bits */ | ||
89 | u16 write; /* Mask of writable bits */ | ||
90 | } wm8983_access_masks[WM8983_MAX_REGISTER + 1] = { | ||
91 | [0x00] = { 0x0000, 0x01FF }, /* R0 - Software Reset */ | ||
92 | [0x01] = { 0x0000, 0x01FF }, /* R1 - Power management 1 */ | ||
93 | [0x02] = { 0x0000, 0x01FF }, /* R2 - Power management 2 */ | ||
94 | [0x03] = { 0x0000, 0x01EF }, /* R3 - Power management 3 */ | ||
95 | [0x04] = { 0x0000, 0x01FF }, /* R4 - Audio Interface */ | ||
96 | [0x05] = { 0x0000, 0x003F }, /* R5 - Companding control */ | ||
97 | [0x06] = { 0x0000, 0x01FD }, /* R6 - Clock Gen control */ | ||
98 | [0x07] = { 0x0000, 0x000F }, /* R7 - Additional control */ | ||
99 | [0x08] = { 0x0000, 0x003F }, /* R8 - GPIO Control */ | ||
100 | [0x09] = { 0x0000, 0x0070 }, /* R9 - Jack Detect Control 1 */ | ||
101 | [0x0A] = { 0x0000, 0x004F }, /* R10 - DAC Control */ | ||
102 | [0x0B] = { 0x0000, 0x01FF }, /* R11 - Left DAC digital Vol */ | ||
103 | [0x0C] = { 0x0000, 0x01FF }, /* R12 - Right DAC digital vol */ | ||
104 | [0x0D] = { 0x0000, 0x00FF }, /* R13 - Jack Detect Control 2 */ | ||
105 | [0x0E] = { 0x0000, 0x01FB }, /* R14 - ADC Control */ | ||
106 | [0x0F] = { 0x0000, 0x01FF }, /* R15 - Left ADC Digital Vol */ | ||
107 | [0x10] = { 0x0000, 0x01FF }, /* R16 - Right ADC Digital Vol */ | ||
108 | [0x12] = { 0x0000, 0x017F }, /* R18 - EQ1 - low shelf */ | ||
109 | [0x13] = { 0x0000, 0x017F }, /* R19 - EQ2 - peak 1 */ | ||
110 | [0x14] = { 0x0000, 0x017F }, /* R20 - EQ3 - peak 2 */ | ||
111 | [0x15] = { 0x0000, 0x017F }, /* R21 - EQ4 - peak 3 */ | ||
112 | [0x16] = { 0x0000, 0x007F }, /* R22 - EQ5 - high shelf */ | ||
113 | [0x18] = { 0x0000, 0x01FF }, /* R24 - DAC Limiter 1 */ | ||
114 | [0x19] = { 0x0000, 0x007F }, /* R25 - DAC Limiter 2 */ | ||
115 | [0x1B] = { 0x0000, 0x01FF }, /* R27 - Notch Filter 1 */ | ||
116 | [0x1C] = { 0x0000, 0x017F }, /* R28 - Notch Filter 2 */ | ||
117 | [0x1D] = { 0x0000, 0x017F }, /* R29 - Notch Filter 3 */ | ||
118 | [0x1E] = { 0x0000, 0x017F }, /* R30 - Notch Filter 4 */ | ||
119 | [0x20] = { 0x0000, 0x01BF }, /* R32 - ALC control 1 */ | ||
120 | [0x21] = { 0x0000, 0x00FF }, /* R33 - ALC control 2 */ | ||
121 | [0x22] = { 0x0000, 0x01FF }, /* R34 - ALC control 3 */ | ||
122 | [0x23] = { 0x0000, 0x000F }, /* R35 - Noise Gate */ | ||
123 | [0x24] = { 0x0000, 0x001F }, /* R36 - PLL N */ | ||
124 | [0x25] = { 0x0000, 0x003F }, /* R37 - PLL K 1 */ | ||
125 | [0x26] = { 0x0000, 0x01FF }, /* R38 - PLL K 2 */ | ||
126 | [0x27] = { 0x0000, 0x01FF }, /* R39 - PLL K 3 */ | ||
127 | [0x29] = { 0x0000, 0x000F }, /* R41 - 3D control */ | ||
128 | [0x2A] = { 0x0000, 0x01E7 }, /* R42 - OUT4 to ADC */ | ||
129 | [0x2B] = { 0x0000, 0x01BF }, /* R43 - Beep control */ | ||
130 | [0x2C] = { 0x0000, 0x0177 }, /* R44 - Input ctrl */ | ||
131 | [0x2D] = { 0x0000, 0x01FF }, /* R45 - Left INP PGA gain ctrl */ | ||
132 | [0x2E] = { 0x0000, 0x01FF }, /* R46 - Right INP PGA gain ctrl */ | ||
133 | [0x2F] = { 0x0000, 0x0177 }, /* R47 - Left ADC BOOST ctrl */ | ||
134 | [0x30] = { 0x0000, 0x0177 }, /* R48 - Right ADC BOOST ctrl */ | ||
135 | [0x31] = { 0x0000, 0x007F }, /* R49 - Output ctrl */ | ||
136 | [0x32] = { 0x0000, 0x01FF }, /* R50 - Left mixer ctrl */ | ||
137 | [0x33] = { 0x0000, 0x01FF }, /* R51 - Right mixer ctrl */ | ||
138 | [0x34] = { 0x0000, 0x01FF }, /* R52 - LOUT1 (HP) volume ctrl */ | ||
139 | [0x35] = { 0x0000, 0x01FF }, /* R53 - ROUT1 (HP) volume ctrl */ | ||
140 | [0x36] = { 0x0000, 0x01FF }, /* R54 - LOUT2 (SPK) volume ctrl */ | ||
141 | [0x37] = { 0x0000, 0x01FF }, /* R55 - ROUT2 (SPK) volume ctrl */ | ||
142 | [0x38] = { 0x0000, 0x004F }, /* R56 - OUT3 mixer ctrl */ | ||
143 | [0x39] = { 0x0000, 0x00FF }, /* R57 - OUT4 (MONO) mix ctrl */ | ||
144 | [0x3D] = { 0x0000, 0x0100 } /* R61 - BIAS CTRL */ | ||
145 | }; | ||
146 | |||
147 | /* vol/gain update regs */ | 87 | /* vol/gain update regs */ |
148 | static const int vol_update_regs[] = { | 88 | static const int vol_update_regs[] = { |
149 | WM8983_LEFT_DAC_DIGITAL_VOL, | 89 | WM8983_LEFT_DAC_DIGITAL_VOL, |
@@ -605,12 +545,19 @@ static int eqmode_put(struct snd_kcontrol *kcontrol, | |||
605 | return 0; | 545 | return 0; |
606 | } | 546 | } |
607 | 547 | ||
608 | static bool wm8983_readable(struct device *dev, unsigned int reg) | 548 | static bool wm8983_writeable(struct device *dev, unsigned int reg) |
609 | { | 549 | { |
610 | if (reg > WM8983_MAX_REGISTER) | 550 | switch (reg) { |
611 | return 0; | 551 | case WM8983_SOFTWARE_RESET ... WM8983_RIGHT_ADC_DIGITAL_VOL: |
612 | 552 | case WM8983_EQ1_LOW_SHELF ... WM8983_DAC_LIMITER_2: | |
613 | return wm8983_access_masks[reg].read != 0; | 553 | case WM8983_NOTCH_FILTER_1 ... WM8983_NOTCH_FILTER_4: |
554 | case WM8983_ALC_CONTROL_1 ... WM8983_PLL_K_3: | ||
555 | case WM8983_3D_CONTROL ... WM8983_OUT4_MONO_MIX_CTRL: | ||
556 | case WM8983_BIAS_CTRL: | ||
557 | return true; | ||
558 | default: | ||
559 | return false; | ||
560 | } | ||
614 | } | 561 | } |
615 | 562 | ||
616 | static int wm8983_dac_mute(struct snd_soc_dai *dai, int mute) | 563 | static int wm8983_dac_mute(struct snd_soc_dai *dai, int mute) |
@@ -1048,8 +995,9 @@ static const struct regmap_config wm8983_regmap = { | |||
1048 | .reg_defaults = wm8983_defaults, | 995 | .reg_defaults = wm8983_defaults, |
1049 | .num_reg_defaults = ARRAY_SIZE(wm8983_defaults), | 996 | .num_reg_defaults = ARRAY_SIZE(wm8983_defaults), |
1050 | .cache_type = REGCACHE_RBTREE, | 997 | .cache_type = REGCACHE_RBTREE, |
998 | .max_register = WM8983_MAX_REGISTER, | ||
1051 | 999 | ||
1052 | .readable_reg = wm8983_readable, | 1000 | .writeable_reg = wm8983_writeable, |
1053 | }; | 1001 | }; |
1054 | 1002 | ||
1055 | #if defined(CONFIG_SPI_MASTER) | 1003 | #if defined(CONFIG_SPI_MASTER) |