diff options
Diffstat (limited to 'sound/soc/codecs/wm8580.c')
-rw-r--r-- | sound/soc/codecs/wm8580.c | 154 |
1 files changed, 44 insertions, 110 deletions
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 97b9ed95d289..d5473473a1e3 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c | |||
@@ -205,73 +205,6 @@ struct wm8580_priv { | |||
205 | struct pll_state b; | 205 | struct pll_state b; |
206 | }; | 206 | }; |
207 | 207 | ||
208 | /* | ||
209 | * read wm8580 register cache | ||
210 | */ | ||
211 | static inline unsigned int wm8580_read_reg_cache(struct snd_soc_codec *codec, | ||
212 | unsigned int reg) | ||
213 | { | ||
214 | u16 *cache = codec->reg_cache; | ||
215 | BUG_ON(reg >= ARRAY_SIZE(wm8580_reg)); | ||
216 | return cache[reg]; | ||
217 | } | ||
218 | |||
219 | /* | ||
220 | * write wm8580 register cache | ||
221 | */ | ||
222 | static inline void wm8580_write_reg_cache(struct snd_soc_codec *codec, | ||
223 | unsigned int reg, unsigned int value) | ||
224 | { | ||
225 | u16 *cache = codec->reg_cache; | ||
226 | |||
227 | cache[reg] = value; | ||
228 | } | ||
229 | |||
230 | /* | ||
231 | * write to the WM8580 register space | ||
232 | */ | ||
233 | static int wm8580_write(struct snd_soc_codec *codec, unsigned int reg, | ||
234 | unsigned int value) | ||
235 | { | ||
236 | u8 data[2]; | ||
237 | |||
238 | BUG_ON(reg >= ARRAY_SIZE(wm8580_reg)); | ||
239 | |||
240 | /* Registers are 9 bits wide */ | ||
241 | value &= 0x1ff; | ||
242 | |||
243 | switch (reg) { | ||
244 | case WM8580_RESET: | ||
245 | /* Uncached */ | ||
246 | break; | ||
247 | default: | ||
248 | if (value == wm8580_read_reg_cache(codec, reg)) | ||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | /* data is | ||
253 | * D15..D9 WM8580 register offset | ||
254 | * D8...D0 register data | ||
255 | */ | ||
256 | data[0] = (reg << 1) | ((value >> 8) & 0x0001); | ||
257 | data[1] = value & 0x00ff; | ||
258 | |||
259 | wm8580_write_reg_cache(codec, reg, value); | ||
260 | if (codec->hw_write(codec->control_data, data, 2) == 2) | ||
261 | return 0; | ||
262 | else | ||
263 | return -EIO; | ||
264 | } | ||
265 | |||
266 | static inline unsigned int wm8580_read(struct snd_soc_codec *codec, | ||
267 | unsigned int reg) | ||
268 | { | ||
269 | switch (reg) { | ||
270 | default: | ||
271 | return wm8580_read_reg_cache(codec, reg); | ||
272 | } | ||
273 | } | ||
274 | |||
275 | static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); | 208 | static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); |
276 | 209 | ||
277 | static int wm8580_out_vu(struct snd_kcontrol *kcontrol, | 210 | static int wm8580_out_vu(struct snd_kcontrol *kcontrol, |
@@ -280,25 +213,22 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol, | |||
280 | struct soc_mixer_control *mc = | 213 | struct soc_mixer_control *mc = |
281 | (struct soc_mixer_control *)kcontrol->private_value; | 214 | (struct soc_mixer_control *)kcontrol->private_value; |
282 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 215 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
216 | u16 *reg_cache = codec->reg_cache; | ||
283 | unsigned int reg = mc->reg; | 217 | unsigned int reg = mc->reg; |
284 | unsigned int reg2 = mc->rreg; | 218 | unsigned int reg2 = mc->rreg; |
285 | int ret; | 219 | int ret; |
286 | u16 val; | ||
287 | 220 | ||
288 | /* Clear the register cache so we write without VU set */ | 221 | /* Clear the register cache so we write without VU set */ |
289 | wm8580_write_reg_cache(codec, reg, 0); | 222 | reg_cache[reg] = 0; |
290 | wm8580_write_reg_cache(codec, reg2, 0); | 223 | reg_cache[reg2] = 0; |
291 | 224 | ||
292 | ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); | 225 | ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); |
293 | if (ret < 0) | 226 | if (ret < 0) |
294 | return ret; | 227 | return ret; |
295 | 228 | ||
296 | /* Now write again with the volume update bit set */ | 229 | /* Now write again with the volume update bit set */ |
297 | val = wm8580_read_reg_cache(codec, reg); | 230 | snd_soc_update_bits(codec, reg, 0x100, 0x100); |
298 | wm8580_write(codec, reg, val | 0x0100); | 231 | snd_soc_update_bits(codec, reg2, 0x100, 0x100); |
299 | |||
300 | val = wm8580_read_reg_cache(codec, reg2); | ||
301 | wm8580_write(codec, reg2, val | 0x0100); | ||
302 | 232 | ||
303 | return 0; | 233 | return 0; |
304 | } | 234 | } |
@@ -521,27 +451,27 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, | |||
521 | /* Always disable the PLL - it is not safe to leave it running | 451 | /* Always disable the PLL - it is not safe to leave it running |
522 | * while reprogramming it. | 452 | * while reprogramming it. |
523 | */ | 453 | */ |
524 | reg = wm8580_read(codec, WM8580_PWRDN2); | 454 | reg = snd_soc_read(codec, WM8580_PWRDN2); |
525 | wm8580_write(codec, WM8580_PWRDN2, reg | pwr_mask); | 455 | snd_soc_write(codec, WM8580_PWRDN2, reg | pwr_mask); |
526 | 456 | ||
527 | if (!freq_in || !freq_out) | 457 | if (!freq_in || !freq_out) |
528 | return 0; | 458 | return 0; |
529 | 459 | ||
530 | wm8580_write(codec, WM8580_PLLA1 + offset, pll_div.k & 0x1ff); | 460 | snd_soc_write(codec, WM8580_PLLA1 + offset, pll_div.k & 0x1ff); |
531 | wm8580_write(codec, WM8580_PLLA2 + offset, (pll_div.k >> 9) & 0xff); | 461 | snd_soc_write(codec, WM8580_PLLA2 + offset, (pll_div.k >> 9) & 0xff); |
532 | wm8580_write(codec, WM8580_PLLA3 + offset, | 462 | snd_soc_write(codec, WM8580_PLLA3 + offset, |
533 | (pll_div.k >> 18 & 0xf) | (pll_div.n << 4)); | 463 | (pll_div.k >> 18 & 0xf) | (pll_div.n << 4)); |
534 | 464 | ||
535 | reg = wm8580_read(codec, WM8580_PLLA4 + offset); | 465 | reg = snd_soc_read(codec, WM8580_PLLA4 + offset); |
536 | reg &= ~0x3f; | 466 | reg &= ~0x3f; |
537 | reg |= pll_div.prescale | pll_div.postscale << 1 | | 467 | reg |= pll_div.prescale | pll_div.postscale << 1 | |
538 | pll_div.freqmode << 3; | 468 | pll_div.freqmode << 3; |
539 | 469 | ||
540 | wm8580_write(codec, WM8580_PLLA4 + offset, reg); | 470 | snd_soc_write(codec, WM8580_PLLA4 + offset, reg); |
541 | 471 | ||
542 | /* All done, turn it on */ | 472 | /* All done, turn it on */ |
543 | reg = wm8580_read(codec, WM8580_PWRDN2); | 473 | reg = snd_soc_read(codec, WM8580_PWRDN2); |
544 | wm8580_write(codec, WM8580_PWRDN2, reg & ~pwr_mask); | 474 | snd_soc_write(codec, WM8580_PWRDN2, reg & ~pwr_mask); |
545 | 475 | ||
546 | return 0; | 476 | return 0; |
547 | } | 477 | } |
@@ -556,7 +486,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, | |||
556 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 486 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
557 | struct snd_soc_device *socdev = rtd->socdev; | 487 | struct snd_soc_device *socdev = rtd->socdev; |
558 | struct snd_soc_codec *codec = socdev->card->codec; | 488 | struct snd_soc_codec *codec = socdev->card->codec; |
559 | u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->id); | 489 | u16 paifb = snd_soc_read(codec, WM8580_PAIF3 + dai->id); |
560 | 490 | ||
561 | paifb &= ~WM8580_AIF_LENGTH_MASK; | 491 | paifb &= ~WM8580_AIF_LENGTH_MASK; |
562 | /* bit size */ | 492 | /* bit size */ |
@@ -576,7 +506,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, | |||
576 | return -EINVAL; | 506 | return -EINVAL; |
577 | } | 507 | } |
578 | 508 | ||
579 | wm8580_write(codec, WM8580_PAIF3 + dai->id, paifb); | 509 | snd_soc_write(codec, WM8580_PAIF3 + dai->id, paifb); |
580 | return 0; | 510 | return 0; |
581 | } | 511 | } |
582 | 512 | ||
@@ -588,8 +518,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai, | |||
588 | unsigned int aifb; | 518 | unsigned int aifb; |
589 | int can_invert_lrclk; | 519 | int can_invert_lrclk; |
590 | 520 | ||
591 | aifa = wm8580_read(codec, WM8580_PAIF1 + codec_dai->id); | 521 | aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->id); |
592 | aifb = wm8580_read(codec, WM8580_PAIF3 + codec_dai->id); | 522 | aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->id); |
593 | 523 | ||
594 | aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP); | 524 | aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP); |
595 | 525 | ||
@@ -655,8 +585,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai, | |||
655 | return -EINVAL; | 585 | return -EINVAL; |
656 | } | 586 | } |
657 | 587 | ||
658 | wm8580_write(codec, WM8580_PAIF1 + codec_dai->id, aifa); | 588 | snd_soc_write(codec, WM8580_PAIF1 + codec_dai->id, aifa); |
659 | wm8580_write(codec, WM8580_PAIF3 + codec_dai->id, aifb); | 589 | snd_soc_write(codec, WM8580_PAIF3 + codec_dai->id, aifb); |
660 | 590 | ||
661 | return 0; | 591 | return 0; |
662 | } | 592 | } |
@@ -669,7 +599,7 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai, | |||
669 | 599 | ||
670 | switch (div_id) { | 600 | switch (div_id) { |
671 | case WM8580_MCLK: | 601 | case WM8580_MCLK: |
672 | reg = wm8580_read(codec, WM8580_PLLB4); | 602 | reg = snd_soc_read(codec, WM8580_PLLB4); |
673 | reg &= ~WM8580_PLLB4_MCLKOUTSRC_MASK; | 603 | reg &= ~WM8580_PLLB4_MCLKOUTSRC_MASK; |
674 | 604 | ||
675 | switch (div) { | 605 | switch (div) { |
@@ -691,11 +621,11 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai, | |||
691 | default: | 621 | default: |
692 | return -EINVAL; | 622 | return -EINVAL; |
693 | } | 623 | } |
694 | wm8580_write(codec, WM8580_PLLB4, reg); | 624 | snd_soc_write(codec, WM8580_PLLB4, reg); |
695 | break; | 625 | break; |
696 | 626 | ||
697 | case WM8580_DAC_CLKSEL: | 627 | case WM8580_DAC_CLKSEL: |
698 | reg = wm8580_read(codec, WM8580_CLKSEL); | 628 | reg = snd_soc_read(codec, WM8580_CLKSEL); |
699 | reg &= ~WM8580_CLKSEL_DAC_CLKSEL_MASK; | 629 | reg &= ~WM8580_CLKSEL_DAC_CLKSEL_MASK; |
700 | 630 | ||
701 | switch (div) { | 631 | switch (div) { |
@@ -713,11 +643,11 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai, | |||
713 | default: | 643 | default: |
714 | return -EINVAL; | 644 | return -EINVAL; |
715 | } | 645 | } |
716 | wm8580_write(codec, WM8580_CLKSEL, reg); | 646 | snd_soc_write(codec, WM8580_CLKSEL, reg); |
717 | break; | 647 | break; |
718 | 648 | ||
719 | case WM8580_CLKOUTSRC: | 649 | case WM8580_CLKOUTSRC: |
720 | reg = wm8580_read(codec, WM8580_PLLB4); | 650 | reg = snd_soc_read(codec, WM8580_PLLB4); |
721 | reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK; | 651 | reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK; |
722 | 652 | ||
723 | switch (div) { | 653 | switch (div) { |
@@ -739,7 +669,7 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai, | |||
739 | default: | 669 | default: |
740 | return -EINVAL; | 670 | return -EINVAL; |
741 | } | 671 | } |
742 | wm8580_write(codec, WM8580_PLLB4, reg); | 672 | snd_soc_write(codec, WM8580_PLLB4, reg); |
743 | break; | 673 | break; |
744 | 674 | ||
745 | default: | 675 | default: |
@@ -754,14 +684,14 @@ static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute) | |||
754 | struct snd_soc_codec *codec = codec_dai->codec; | 684 | struct snd_soc_codec *codec = codec_dai->codec; |
755 | unsigned int reg; | 685 | unsigned int reg; |
756 | 686 | ||
757 | reg = wm8580_read(codec, WM8580_DAC_CONTROL5); | 687 | reg = snd_soc_read(codec, WM8580_DAC_CONTROL5); |
758 | 688 | ||
759 | if (mute) | 689 | if (mute) |
760 | reg |= WM8580_DAC_CONTROL5_MUTEALL; | 690 | reg |= WM8580_DAC_CONTROL5_MUTEALL; |
761 | else | 691 | else |
762 | reg &= ~WM8580_DAC_CONTROL5_MUTEALL; | 692 | reg &= ~WM8580_DAC_CONTROL5_MUTEALL; |
763 | 693 | ||
764 | wm8580_write(codec, WM8580_DAC_CONTROL5, reg); | 694 | snd_soc_write(codec, WM8580_DAC_CONTROL5, reg); |
765 | 695 | ||
766 | return 0; | 696 | return 0; |
767 | } | 697 | } |
@@ -778,20 +708,20 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec, | |||
778 | case SND_SOC_BIAS_STANDBY: | 708 | case SND_SOC_BIAS_STANDBY: |
779 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | 709 | if (codec->bias_level == SND_SOC_BIAS_OFF) { |
780 | /* Power up and get individual control of the DACs */ | 710 | /* Power up and get individual control of the DACs */ |
781 | reg = wm8580_read(codec, WM8580_PWRDN1); | 711 | reg = snd_soc_read(codec, WM8580_PWRDN1); |
782 | reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD); | 712 | reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD); |
783 | wm8580_write(codec, WM8580_PWRDN1, reg); | 713 | snd_soc_write(codec, WM8580_PWRDN1, reg); |
784 | 714 | ||
785 | /* Make VMID high impedence */ | 715 | /* Make VMID high impedence */ |
786 | reg = wm8580_read(codec, WM8580_ADC_CONTROL1); | 716 | reg = snd_soc_read(codec, WM8580_ADC_CONTROL1); |
787 | reg &= ~0x100; | 717 | reg &= ~0x100; |
788 | wm8580_write(codec, WM8580_ADC_CONTROL1, reg); | 718 | snd_soc_write(codec, WM8580_ADC_CONTROL1, reg); |
789 | } | 719 | } |
790 | break; | 720 | break; |
791 | 721 | ||
792 | case SND_SOC_BIAS_OFF: | 722 | case SND_SOC_BIAS_OFF: |
793 | reg = wm8580_read(codec, WM8580_PWRDN1); | 723 | reg = snd_soc_read(codec, WM8580_PWRDN1); |
794 | wm8580_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN); | 724 | snd_soc_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN); |
795 | break; | 725 | break; |
796 | } | 726 | } |
797 | codec->bias_level = level; | 727 | codec->bias_level = level; |
@@ -902,7 +832,8 @@ struct snd_soc_codec_device soc_codec_dev_wm8580 = { | |||
902 | }; | 832 | }; |
903 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580); | 833 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580); |
904 | 834 | ||
905 | static int wm8580_register(struct wm8580_priv *wm8580) | 835 | static int wm8580_register(struct wm8580_priv *wm8580, |
836 | enum snd_soc_control_type control) | ||
906 | { | 837 | { |
907 | int ret, i; | 838 | int ret, i; |
908 | struct snd_soc_codec *codec = &wm8580->codec; | 839 | struct snd_soc_codec *codec = &wm8580->codec; |
@@ -920,8 +851,6 @@ static int wm8580_register(struct wm8580_priv *wm8580) | |||
920 | codec->private_data = wm8580; | 851 | codec->private_data = wm8580; |
921 | codec->name = "WM8580"; | 852 | codec->name = "WM8580"; |
922 | codec->owner = THIS_MODULE; | 853 | codec->owner = THIS_MODULE; |
923 | codec->read = wm8580_read_reg_cache; | ||
924 | codec->write = wm8580_write; | ||
925 | codec->bias_level = SND_SOC_BIAS_OFF; | 854 | codec->bias_level = SND_SOC_BIAS_OFF; |
926 | codec->set_bias_level = wm8580_set_bias_level; | 855 | codec->set_bias_level = wm8580_set_bias_level; |
927 | codec->dai = wm8580_dai; | 856 | codec->dai = wm8580_dai; |
@@ -931,6 +860,12 @@ static int wm8580_register(struct wm8580_priv *wm8580) | |||
931 | 860 | ||
932 | memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg)); | 861 | memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg)); |
933 | 862 | ||
863 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | ||
864 | if (ret < 0) { | ||
865 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
866 | goto err; | ||
867 | } | ||
868 | |||
934 | for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) | 869 | for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) |
935 | wm8580->supplies[i].supply = wm8580_supply_names[i]; | 870 | wm8580->supplies[i].supply = wm8580_supply_names[i]; |
936 | 871 | ||
@@ -949,7 +884,7 @@ static int wm8580_register(struct wm8580_priv *wm8580) | |||
949 | } | 884 | } |
950 | 885 | ||
951 | /* Get the codec into a known state */ | 886 | /* Get the codec into a known state */ |
952 | ret = wm8580_write(codec, WM8580_RESET, 0); | 887 | ret = snd_soc_write(codec, WM8580_RESET, 0); |
953 | if (ret != 0) { | 888 | if (ret != 0) { |
954 | dev_err(codec->dev, "Failed to reset codec: %d\n", ret); | 889 | dev_err(codec->dev, "Failed to reset codec: %d\n", ret); |
955 | goto err_regulator_enable; | 890 | goto err_regulator_enable; |
@@ -1010,14 +945,13 @@ static int wm8580_i2c_probe(struct i2c_client *i2c, | |||
1010 | return -ENOMEM; | 945 | return -ENOMEM; |
1011 | 946 | ||
1012 | codec = &wm8580->codec; | 947 | codec = &wm8580->codec; |
1013 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
1014 | 948 | ||
1015 | i2c_set_clientdata(i2c, wm8580); | 949 | i2c_set_clientdata(i2c, wm8580); |
1016 | codec->control_data = i2c; | 950 | codec->control_data = i2c; |
1017 | 951 | ||
1018 | codec->dev = &i2c->dev; | 952 | codec->dev = &i2c->dev; |
1019 | 953 | ||
1020 | return wm8580_register(wm8580); | 954 | return wm8580_register(wm8580, SND_SOC_I2C); |
1021 | } | 955 | } |
1022 | 956 | ||
1023 | static int wm8580_i2c_remove(struct i2c_client *client) | 957 | static int wm8580_i2c_remove(struct i2c_client *client) |