aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8988.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-09-10 09:32:40 -0400
committerTakashi Iwai <tiwai@suse.de>2009-09-10 09:32:40 -0400
commite0b3032bcdf1419d97de636d5fb1c9469da75776 (patch)
tree30252bef7afdad1f789b215c99909104a1d5cfa1 /sound/soc/codecs/wm8988.c
parent45fae5c78d873b10c66dfc04db6701e05c493791 (diff)
parentcdc65fbe18aef15e92d2ebb410a189fbf956fb06 (diff)
Merge branch 'topic/asoc' into for-linus
* topic/asoc: (226 commits) ASoC: au1x: PSC-AC97 bugfixes ASoC: Fix WM835x Out4 capture enumeration ASoC: Remove unuused hw_read_t ASoC: fix pxa2xx-ac97.c breakage ASoC: Fully specify DC servo bits to update in wm_hubs ASoC: Debugged improper setting of PLL fields in WM8580 driver ASoC: new board driver to connect bfin-5xx with ad1836 codec ASoC: OMAP: Add functionality to set CLKR and FSR sources in McBSP DAI ASoC: davinci: i2c device creation moved into board files ASoC: Don't reconfigure WM8350 FLL if not needed ASoC: Fix s3c-i2s-v2 build ASoC: Make platform data optional for TLV320AIC3x ASoC: Add S3C24xx dependencies for Simtec machines ASoC: SDP3430: Fix TWL GPIO6 pin mux request ASoC: S3C platform: Fix s3c2410_dma_started() called at improper time ARM: OMAP: McBSP: Merge two functions into omap_mcbsp_start/_stop ASoC: OMAP: Fix setup of XCCR and RCCR registers in McBSP DAI OMAP: McBSP: Use textual values in DMA operating mode sysfs files ARM: OMAP: DMA: Add support for DMA channel self linking on OMAP1510 ASoC: Select core DMA when building for S3C64xx ...
Diffstat (limited to 'sound/soc/codecs/wm8988.c')
-rw-r--r--sound/soc/codecs/wm8988.c180
1 files changed, 76 insertions, 104 deletions
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index 8c0fdf84aac3..3f530f8a972a 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -57,50 +57,7 @@ struct wm8988_priv {
57}; 57};
58 58
59 59
60/* 60#define wm8988_reset(c) snd_soc_write(c, WM8988_RESET, 0)
61 * read wm8988 register cache
62 */
63static inline unsigned int wm8988_read_reg_cache(struct snd_soc_codec *codec,
64 unsigned int reg)
65{
66 u16 *cache = codec->reg_cache;
67 if (reg > WM8988_NUM_REG)
68 return -1;
69 return cache[reg];
70}
71
72/*
73 * write wm8988 register cache
74 */
75static inline void wm8988_write_reg_cache(struct snd_soc_codec *codec,
76 unsigned int reg, unsigned int value)
77{
78 u16 *cache = codec->reg_cache;
79 if (reg > WM8988_NUM_REG)
80 return;
81 cache[reg] = value;
82}
83
84static int wm8988_write(struct snd_soc_codec *codec, unsigned int reg,
85 unsigned int value)
86{
87 u8 data[2];
88
89 /* data is
90 * D15..D9 WM8753 register offset
91 * D8...D0 register data
92 */
93 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
94 data[1] = value & 0x00ff;
95
96 wm8988_write_reg_cache(codec, reg, value);
97 if (codec->hw_write(codec->control_data, data, 2) == 2)
98 return 0;
99 else
100 return -EIO;
101}
102
103#define wm8988_reset(c) wm8988_write(c, WM8988_RESET, 0)
104 61
105/* 62/*
106 * WM8988 Controls 63 * WM8988 Controls
@@ -226,15 +183,15 @@ static int wm8988_lrc_control(struct snd_soc_dapm_widget *w,
226 struct snd_kcontrol *kcontrol, int event) 183 struct snd_kcontrol *kcontrol, int event)
227{ 184{
228 struct snd_soc_codec *codec = w->codec; 185 struct snd_soc_codec *codec = w->codec;
229 u16 adctl2 = wm8988_read_reg_cache(codec, WM8988_ADCTL2); 186 u16 adctl2 = snd_soc_read(codec, WM8988_ADCTL2);
230 187
231 /* Use the DAC to gate LRC if active, otherwise use ADC */ 188 /* Use the DAC to gate LRC if active, otherwise use ADC */
232 if (wm8988_read_reg_cache(codec, WM8988_PWR2) & 0x180) 189 if (snd_soc_read(codec, WM8988_PWR2) & 0x180)
233 adctl2 &= ~0x4; 190 adctl2 &= ~0x4;
234 else 191 else
235 adctl2 |= 0x4; 192 adctl2 |= 0x4;
236 193
237 return wm8988_write(codec, WM8988_ADCTL2, adctl2); 194 return snd_soc_write(codec, WM8988_ADCTL2, adctl2);
238} 195}
239 196
240static const char *wm8988_line_texts[] = { 197static const char *wm8988_line_texts[] = {
@@ -619,7 +576,7 @@ static int wm8988_set_dai_fmt(struct snd_soc_dai *codec_dai,
619 return -EINVAL; 576 return -EINVAL;
620 } 577 }
621 578
622 wm8988_write(codec, WM8988_IFACE, iface); 579 snd_soc_write(codec, WM8988_IFACE, iface);
623 return 0; 580 return 0;
624} 581}
625 582
@@ -653,8 +610,8 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
653 struct snd_soc_device *socdev = rtd->socdev; 610 struct snd_soc_device *socdev = rtd->socdev;
654 struct snd_soc_codec *codec = socdev->card->codec; 611 struct snd_soc_codec *codec = socdev->card->codec;
655 struct wm8988_priv *wm8988 = codec->private_data; 612 struct wm8988_priv *wm8988 = codec->private_data;
656 u16 iface = wm8988_read_reg_cache(codec, WM8988_IFACE) & 0x1f3; 613 u16 iface = snd_soc_read(codec, WM8988_IFACE) & 0x1f3;
657 u16 srate = wm8988_read_reg_cache(codec, WM8988_SRATE) & 0x180; 614 u16 srate = snd_soc_read(codec, WM8988_SRATE) & 0x180;
658 int coeff; 615 int coeff;
659 616
660 coeff = get_coeff(wm8988->sysclk, params_rate(params)); 617 coeff = get_coeff(wm8988->sysclk, params_rate(params));
@@ -685,9 +642,9 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
685 } 642 }
686 643
687 /* set iface & srate */ 644 /* set iface & srate */
688 wm8988_write(codec, WM8988_IFACE, iface); 645 snd_soc_write(codec, WM8988_IFACE, iface);
689 if (coeff >= 0) 646 if (coeff >= 0)
690 wm8988_write(codec, WM8988_SRATE, srate | 647 snd_soc_write(codec, WM8988_SRATE, srate |
691 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); 648 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
692 649
693 return 0; 650 return 0;
@@ -696,19 +653,19 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
696static int wm8988_mute(struct snd_soc_dai *dai, int mute) 653static int wm8988_mute(struct snd_soc_dai *dai, int mute)
697{ 654{
698 struct snd_soc_codec *codec = dai->codec; 655 struct snd_soc_codec *codec = dai->codec;
699 u16 mute_reg = wm8988_read_reg_cache(codec, WM8988_ADCDAC) & 0xfff7; 656 u16 mute_reg = snd_soc_read(codec, WM8988_ADCDAC) & 0xfff7;
700 657
701 if (mute) 658 if (mute)
702 wm8988_write(codec, WM8988_ADCDAC, mute_reg | 0x8); 659 snd_soc_write(codec, WM8988_ADCDAC, mute_reg | 0x8);
703 else 660 else
704 wm8988_write(codec, WM8988_ADCDAC, mute_reg); 661 snd_soc_write(codec, WM8988_ADCDAC, mute_reg);
705 return 0; 662 return 0;
706} 663}
707 664
708static int wm8988_set_bias_level(struct snd_soc_codec *codec, 665static int wm8988_set_bias_level(struct snd_soc_codec *codec,
709 enum snd_soc_bias_level level) 666 enum snd_soc_bias_level level)
710{ 667{
711 u16 pwr_reg = wm8988_read_reg_cache(codec, WM8988_PWR1) & ~0x1c1; 668 u16 pwr_reg = snd_soc_read(codec, WM8988_PWR1) & ~0x1c1;
712 669
713 switch (level) { 670 switch (level) {
714 case SND_SOC_BIAS_ON: 671 case SND_SOC_BIAS_ON:
@@ -716,24 +673,24 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec,
716 673
717 case SND_SOC_BIAS_PREPARE: 674 case SND_SOC_BIAS_PREPARE:
718 /* VREF, VMID=2x50k, digital enabled */ 675 /* VREF, VMID=2x50k, digital enabled */
719 wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x00c0); 676 snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x00c0);
720 break; 677 break;
721 678
722 case SND_SOC_BIAS_STANDBY: 679 case SND_SOC_BIAS_STANDBY:
723 if (codec->bias_level == SND_SOC_BIAS_OFF) { 680 if (codec->bias_level == SND_SOC_BIAS_OFF) {
724 /* VREF, VMID=2x5k */ 681 /* VREF, VMID=2x5k */
725 wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x1c1); 682 snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1);
726 683
727 /* Charge caps */ 684 /* Charge caps */
728 msleep(100); 685 msleep(100);
729 } 686 }
730 687
731 /* VREF, VMID=2*500k, digital stopped */ 688 /* VREF, VMID=2*500k, digital stopped */
732 wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x0141); 689 snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x0141);
733 break; 690 break;
734 691
735 case SND_SOC_BIAS_OFF: 692 case SND_SOC_BIAS_OFF:
736 wm8988_write(codec, WM8988_PWR1, 0x0000); 693 snd_soc_write(codec, WM8988_PWR1, 0x0000);
737 break; 694 break;
738 } 695 }
739 codec->bias_level = level; 696 codec->bias_level = level;
@@ -868,7 +825,8 @@ struct snd_soc_codec_device soc_codec_dev_wm8988 = {
868}; 825};
869EXPORT_SYMBOL_GPL(soc_codec_dev_wm8988); 826EXPORT_SYMBOL_GPL(soc_codec_dev_wm8988);
870 827
871static int wm8988_register(struct wm8988_priv *wm8988) 828static int wm8988_register(struct wm8988_priv *wm8988,
829 enum snd_soc_control_type control)
872{ 830{
873 struct snd_soc_codec *codec = &wm8988->codec; 831 struct snd_soc_codec *codec = &wm8988->codec;
874 int ret; 832 int ret;
@@ -887,8 +845,6 @@ static int wm8988_register(struct wm8988_priv *wm8988)
887 codec->private_data = wm8988; 845 codec->private_data = wm8988;
888 codec->name = "WM8988"; 846 codec->name = "WM8988";
889 codec->owner = THIS_MODULE; 847 codec->owner = THIS_MODULE;
890 codec->read = wm8988_read_reg_cache;
891 codec->write = wm8988_write;
892 codec->dai = &wm8988_dai; 848 codec->dai = &wm8988_dai;
893 codec->num_dai = 1; 849 codec->num_dai = 1;
894 codec->reg_cache_size = ARRAY_SIZE(wm8988->reg_cache); 850 codec->reg_cache_size = ARRAY_SIZE(wm8988->reg_cache);
@@ -899,23 +855,29 @@ static int wm8988_register(struct wm8988_priv *wm8988)
899 memcpy(codec->reg_cache, wm8988_reg, 855 memcpy(codec->reg_cache, wm8988_reg,
900 sizeof(wm8988_reg)); 856 sizeof(wm8988_reg));
901 857
858 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
859 if (ret < 0) {
860 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
861 goto err;
862 }
863
902 ret = wm8988_reset(codec); 864 ret = wm8988_reset(codec);
903 if (ret < 0) { 865 if (ret < 0) {
904 dev_err(codec->dev, "Failed to issue reset\n"); 866 dev_err(codec->dev, "Failed to issue reset\n");
905 return ret; 867 goto err;
906 } 868 }
907 869
908 /* set the update bits (we always update left then right) */ 870 /* set the update bits (we always update left then right) */
909 reg = wm8988_read_reg_cache(codec, WM8988_RADC); 871 reg = snd_soc_read(codec, WM8988_RADC);
910 wm8988_write(codec, WM8988_RADC, reg | 0x100); 872 snd_soc_write(codec, WM8988_RADC, reg | 0x100);
911 reg = wm8988_read_reg_cache(codec, WM8988_RDAC); 873 reg = snd_soc_read(codec, WM8988_RDAC);
912 wm8988_write(codec, WM8988_RDAC, reg | 0x0100); 874 snd_soc_write(codec, WM8988_RDAC, reg | 0x0100);
913 reg = wm8988_read_reg_cache(codec, WM8988_ROUT1V); 875 reg = snd_soc_read(codec, WM8988_ROUT1V);
914 wm8988_write(codec, WM8988_ROUT1V, reg | 0x0100); 876 snd_soc_write(codec, WM8988_ROUT1V, reg | 0x0100);
915 reg = wm8988_read_reg_cache(codec, WM8988_ROUT2V); 877 reg = snd_soc_read(codec, WM8988_ROUT2V);
916 wm8988_write(codec, WM8988_ROUT2V, reg | 0x0100); 878 snd_soc_write(codec, WM8988_ROUT2V, reg | 0x0100);
917 reg = wm8988_read_reg_cache(codec, WM8988_RINVOL); 879 reg = snd_soc_read(codec, WM8988_RINVOL);
918 wm8988_write(codec, WM8988_RINVOL, reg | 0x0100); 880 snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100);
919 881
920 wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_STANDBY); 882 wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_STANDBY);
921 883
@@ -926,18 +888,20 @@ static int wm8988_register(struct wm8988_priv *wm8988)
926 ret = snd_soc_register_codec(codec); 888 ret = snd_soc_register_codec(codec);
927 if (ret != 0) { 889 if (ret != 0) {
928 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 890 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
929 return ret; 891 goto err;
930 } 892 }
931 893
932 ret = snd_soc_register_dai(&wm8988_dai); 894 ret = snd_soc_register_dai(&wm8988_dai);
933 if (ret != 0) { 895 if (ret != 0) {
934 dev_err(codec->dev, "Failed to register DAI: %d\n", ret); 896 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
935 snd_soc_unregister_codec(codec); 897 snd_soc_unregister_codec(codec);
936 return ret; 898 goto err_codec;
937 } 899 }
938 900
939 return 0; 901 return 0;
940 902
903err_codec:
904 snd_soc_unregister_codec(codec);
941err: 905err:
942 kfree(wm8988); 906 kfree(wm8988);
943 return ret; 907 return ret;
@@ -964,14 +928,13 @@ static int wm8988_i2c_probe(struct i2c_client *i2c,
964 return -ENOMEM; 928 return -ENOMEM;
965 929
966 codec = &wm8988->codec; 930 codec = &wm8988->codec;
967 codec->hw_write = (hw_write_t)i2c_master_send;
968 931
969 i2c_set_clientdata(i2c, wm8988); 932 i2c_set_clientdata(i2c, wm8988);
970 codec->control_data = i2c; 933 codec->control_data = i2c;
971 934
972 codec->dev = &i2c->dev; 935 codec->dev = &i2c->dev;
973 936
974 return wm8988_register(wm8988); 937 return wm8988_register(wm8988, SND_SOC_I2C);
975} 938}
976 939
977static int wm8988_i2c_remove(struct i2c_client *client) 940static int wm8988_i2c_remove(struct i2c_client *client)
@@ -981,6 +944,21 @@ static int wm8988_i2c_remove(struct i2c_client *client)
981 return 0; 944 return 0;
982} 945}
983 946
947#ifdef CONFIG_PM
948static int wm8988_i2c_suspend(struct i2c_client *client, pm_message_t msg)
949{
950 return snd_soc_suspend_device(&client->dev);
951}
952
953static int wm8988_i2c_resume(struct i2c_client *client)
954{
955 return snd_soc_resume_device(&client->dev);
956}
957#else
958#define wm8988_i2c_suspend NULL
959#define wm8988_i2c_resume NULL
960#endif
961
984static const struct i2c_device_id wm8988_i2c_id[] = { 962static const struct i2c_device_id wm8988_i2c_id[] = {
985 { "wm8988", 0 }, 963 { "wm8988", 0 },
986 { } 964 { }
@@ -994,35 +972,13 @@ static struct i2c_driver wm8988_i2c_driver = {
994 }, 972 },
995 .probe = wm8988_i2c_probe, 973 .probe = wm8988_i2c_probe,
996 .remove = wm8988_i2c_remove, 974 .remove = wm8988_i2c_remove,
975 .suspend = wm8988_i2c_suspend,
976 .resume = wm8988_i2c_resume,
997 .id_table = wm8988_i2c_id, 977 .id_table = wm8988_i2c_id,
998}; 978};
999#endif 979#endif
1000 980
1001#if defined(CONFIG_SPI_MASTER) 981#if defined(CONFIG_SPI_MASTER)
1002static int wm8988_spi_write(struct spi_device *spi, const char *data, int len)
1003{
1004 struct spi_transfer t;
1005 struct spi_message m;
1006 u8 msg[2];
1007
1008 if (len <= 0)
1009 return 0;
1010
1011 msg[0] = data[0];
1012 msg[1] = data[1];
1013
1014 spi_message_init(&m);
1015 memset(&t, 0, (sizeof t));
1016
1017 t.tx_buf = &msg[0];
1018 t.len = len;
1019
1020 spi_message_add_tail(&t, &m);
1021 spi_sync(spi, &m);
1022
1023 return len;
1024}
1025
1026static int __devinit wm8988_spi_probe(struct spi_device *spi) 982static int __devinit wm8988_spi_probe(struct spi_device *spi)
1027{ 983{
1028 struct wm8988_priv *wm8988; 984 struct wm8988_priv *wm8988;
@@ -1033,13 +989,12 @@ static int __devinit wm8988_spi_probe(struct spi_device *spi)
1033 return -ENOMEM; 989 return -ENOMEM;
1034 990
1035 codec = &wm8988->codec; 991 codec = &wm8988->codec;
1036 codec->hw_write = (hw_write_t)wm8988_spi_write;
1037 codec->control_data = spi; 992 codec->control_data = spi;
1038 codec->dev = &spi->dev; 993 codec->dev = &spi->dev;
1039 994
1040 dev_set_drvdata(&spi->dev, wm8988); 995 dev_set_drvdata(&spi->dev, wm8988);
1041 996
1042 return wm8988_register(wm8988); 997 return wm8988_register(wm8988, SND_SOC_SPI);
1043} 998}
1044 999
1045static int __devexit wm8988_spi_remove(struct spi_device *spi) 1000static int __devexit wm8988_spi_remove(struct spi_device *spi)
@@ -1051,6 +1006,21 @@ static int __devexit wm8988_spi_remove(struct spi_device *spi)
1051 return 0; 1006 return 0;
1052} 1007}
1053 1008
1009#ifdef CONFIG_PM
1010static int wm8988_spi_suspend(struct spi_device *spi, pm_message_t msg)
1011{
1012 return snd_soc_suspend_device(&spi->dev);
1013}
1014
1015static int wm8988_spi_resume(struct spi_device *spi)
1016{
1017 return snd_soc_resume_device(&spi->dev);
1018}
1019#else
1020#define wm8988_spi_suspend NULL
1021#define wm8988_spi_resume NULL
1022#endif
1023
1054static struct spi_driver wm8988_spi_driver = { 1024static struct spi_driver wm8988_spi_driver = {
1055 .driver = { 1025 .driver = {
1056 .name = "wm8988", 1026 .name = "wm8988",
@@ -1059,6 +1029,8 @@ static struct spi_driver wm8988_spi_driver = {
1059 }, 1029 },
1060 .probe = wm8988_spi_probe, 1030 .probe = wm8988_spi_probe,
1061 .remove = __devexit_p(wm8988_spi_remove), 1031 .remove = __devexit_p(wm8988_spi_remove),
1032 .suspend = wm8988_spi_suspend,
1033 .resume = wm8988_spi_resume,
1062}; 1034};
1063#endif 1035#endif
1064 1036