aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8988.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-22 16:00:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-22 16:00:13 -0400
commitb2094ef840697bc8ca5d17a83b7e30fad5f1e9fa (patch)
tree64e5f7253b6a85b6d5d36f95c0d3c67c1798918d /sound/soc/codecs/wm8988.c
parent424a6f6ef990b7e9f56f6627bfc6c46b493faeb4 (diff)
parent6681bc0deba495fad0d6fb349e40524abd1b1732 (diff)
Merge tag 'sound-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull updates of sound stuff from Takashi Iwai: "Here is the first big update chunk of sound stuff for 3.4-rc1. In the common sound infrastructure, there are a few changes for dynamic PCM support (used in ASoC) and a few clean-ups. Majority of changes are found, as usual, in HD-audio and ASoC. Some highlights of HD-audio changes: - All the long-standing static quirk codes for Realtek codec were finally removed by fixing and extending the Realtek auto-parser. - The mute-LED control is standardized over all HD-audio codec drivers using the extended vmaster hook. - The vmaster slave mixer elements are initialized to 0dB as default so that the user won't be annoyed by the silent output after updates, e.g. due to the additions of new elements. - Other many fix-ups for the misc HD-audio devices. In the ASoC side, this is a very active release, including a quite a few framework enhancements. Some highlights: - Support for widgets not associated with a CODEC, an important part of the dynamic PCM framework. - A library factoring out the common code shared by dmaengine based DMA drivers contributed by Lars-Peter Clausen. This will save a lot of code and make it much easier to deploy enhancements to dmaengine. - Support for binary controls, used for providing runtime configuration of algorithm coefficients. - A new DAPM widget type for regulator supplies allowing drivers for devices that can power down unused supplies while active to do without any per-driver code. - DAPM widgets for DAIs, initially giving a speed boost for playback startup and shutdown and also the basis for CODEC<->CODEC DAI link support. - Support for specifying the number of significant bits on audio interfaces, useful for allowing applications to know how much effort to put into generating data for a larger sample format. - Conversion of the FSI driver used on some SH processors to DMAEngine. - Conversion of EP93xx drivers to DMAEngine. - New CODEC drivers for Maxim MAX9768 and Wolfson Microelectronics WM2200. - Move audmux driver from arc/arm to sound/soc - McBSP move from arch/ to sound/ and updates Also, a few small updates and fixes for other drivers like au88x0, ymfpci, USB 6fire, USB usx2yaudio are included." * tag 'sound-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (446 commits) ASoC: wm8994: Provide VMID mode control and fix default sequence ASoC: wm8994: Add missing break in resume ASoC: wm_hubs: Don't actively manage LINEOUT_VMID_BUF ASoC: pxa-ssp: atomically set stream active masks ASoC: fsl: p1022ds: tell the WM8776 codec driver that it's the master ASoC: Samsung: Added to support mono recording ALSA: hda - Fix build with CONFIG_PM=n ALSA: au88x0 - Avoid possible Oops at unbinding ALSA: usb-audio - Fix build error by consitification of rate list ASoC: core: Fix obscure leak of runtime array ALSA: pcm - Avoid GFP_ATOMIC in snd_pcm_link() ALSA: pcm: Constify the list in snd_pcm_hw_constraint_list ASoC: wm8996: Add 44.1kHz support ALSA: hda - Fix build of patch_sigmatel.c without CONFIG_SND_HDA_POWER_SAVE ASoC: mx27vis-aic32x4: Convert it to platform driver ALSA: hda - fix printing of high HDMI sample rates ALSA: ymfpci - Fix legacy registers on S3/S4 resume ALSA: control - Fixe a trailing white space error ALSA: hda - Add expose_enum_ctl flag to snd_hda_add_vmaster_hook() ALSA: hda - Add "Mute-LED Mode" enum control ...
Diffstat (limited to 'sound/soc/codecs/wm8988.c')
-rw-r--r--sound/soc/codecs/wm8988.c171
1 files changed, 134 insertions, 37 deletions
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index ab52963dd04c..6cdf6a2bc283 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -33,24 +33,89 @@
33 * We can't read the WM8988 register space when we 33 * We can't read the WM8988 register space when we
34 * are using 2 wire for device control, so we cache them instead. 34 * are using 2 wire for device control, so we cache them instead.
35 */ 35 */
36static const u16 wm8988_reg[] = { 36static const struct reg_default wm8988_reg_defaults[] = {
37 0x0097, 0x0097, 0x0079, 0x0079, /* 0 */ 37 { 0, 0x0097 },
38 0x0000, 0x0008, 0x0000, 0x000a, /* 4 */ 38 { 1, 0x0097 },
39 0x0000, 0x0000, 0x00ff, 0x00ff, /* 8 */ 39 { 2, 0x0079 },
40 0x000f, 0x000f, 0x0000, 0x0000, /* 12 */ 40 { 3, 0x0079 },
41 0x0000, 0x007b, 0x0000, 0x0032, /* 16 */ 41 { 5, 0x0008 },
42 0x0000, 0x00c3, 0x00c3, 0x00c0, /* 20 */ 42 { 7, 0x000a },
43 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */ 43 { 8, 0x0000 },
44 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */ 44 { 10, 0x00ff },
45 0x0000, 0x0000, 0x0050, 0x0050, /* 32 */ 45 { 11, 0x00ff },
46 0x0050, 0x0050, 0x0050, 0x0050, /* 36 */ 46 { 12, 0x000f },
47 0x0079, 0x0079, 0x0079, /* 40 */ 47 { 13, 0x000f },
48 { 16, 0x0000 },
49 { 17, 0x007b },
50 { 18, 0x0000 },
51 { 19, 0x0032 },
52 { 20, 0x0000 },
53 { 21, 0x00c3 },
54 { 22, 0x00c3 },
55 { 23, 0x00c0 },
56 { 24, 0x0000 },
57 { 25, 0x0000 },
58 { 26, 0x0000 },
59 { 27, 0x0000 },
60 { 31, 0x0000 },
61 { 32, 0x0000 },
62 { 33, 0x0000 },
63 { 34, 0x0050 },
64 { 35, 0x0050 },
65 { 36, 0x0050 },
66 { 37, 0x0050 },
67 { 40, 0x0079 },
68 { 41, 0x0079 },
69 { 42, 0x0079 },
48}; 70};
49 71
72static bool wm8988_writeable(struct device *dev, unsigned int reg)
73{
74 switch (reg) {
75 case WM8988_LINVOL:
76 case WM8988_RINVOL:
77 case WM8988_LOUT1V:
78 case WM8988_ROUT1V:
79 case WM8988_ADCDAC:
80 case WM8988_IFACE:
81 case WM8988_SRATE:
82 case WM8988_LDAC:
83 case WM8988_RDAC:
84 case WM8988_BASS:
85 case WM8988_TREBLE:
86 case WM8988_RESET:
87 case WM8988_3D:
88 case WM8988_ALC1:
89 case WM8988_ALC2:
90 case WM8988_ALC3:
91 case WM8988_NGATE:
92 case WM8988_LADC:
93 case WM8988_RADC:
94 case WM8988_ADCTL1:
95 case WM8988_ADCTL2:
96 case WM8988_PWR1:
97 case WM8988_PWR2:
98 case WM8988_ADCTL3:
99 case WM8988_ADCIN:
100 case WM8988_LADCIN:
101 case WM8988_RADCIN:
102 case WM8988_LOUTM1:
103 case WM8988_LOUTM2:
104 case WM8988_ROUTM1:
105 case WM8988_ROUTM2:
106 case WM8988_LOUT2V:
107 case WM8988_ROUT2V:
108 case WM8988_LPPB:
109 return true;
110 default:
111 return false;
112 }
113}
114
50/* codec private data */ 115/* codec private data */
51struct wm8988_priv { 116struct wm8988_priv {
117 struct regmap *regmap;
52 unsigned int sysclk; 118 unsigned int sysclk;
53 enum snd_soc_control_type control_type;
54 struct snd_pcm_hw_constraint_list *sysclk_constraints; 119 struct snd_pcm_hw_constraint_list *sysclk_constraints;
55}; 120};
56 121
@@ -317,7 +382,7 @@ static const struct snd_soc_dapm_widget wm8988_dapm_widgets[] = {
317 SND_SOC_DAPM_INPUT("RINPUT2"), 382 SND_SOC_DAPM_INPUT("RINPUT2"),
318}; 383};
319 384
320static const struct snd_soc_dapm_route audio_map[] = { 385static const struct snd_soc_dapm_route wm8988_dapm_routes[] = {
321 386
322 { "Left Line Mux", "Line 1", "LINPUT1" }, 387 { "Left Line Mux", "Line 1", "LINPUT1" },
323 { "Left Line Mux", "Line 2", "LINPUT2" }, 388 { "Left Line Mux", "Line 2", "LINPUT2" },
@@ -661,6 +726,7 @@ static int wm8988_mute(struct snd_soc_dai *dai, int mute)
661static int wm8988_set_bias_level(struct snd_soc_codec *codec, 726static int wm8988_set_bias_level(struct snd_soc_codec *codec,
662 enum snd_soc_bias_level level) 727 enum snd_soc_bias_level level)
663{ 728{
729 struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
664 u16 pwr_reg = snd_soc_read(codec, WM8988_PWR1) & ~0x1c1; 730 u16 pwr_reg = snd_soc_read(codec, WM8988_PWR1) & ~0x1c1;
665 731
666 switch (level) { 732 switch (level) {
@@ -674,7 +740,7 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec,
674 740
675 case SND_SOC_BIAS_STANDBY: 741 case SND_SOC_BIAS_STANDBY:
676 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { 742 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
677 snd_soc_cache_sync(codec); 743 regcache_sync(wm8988->regmap);
678 744
679 /* VREF, VMID=2x5k */ 745 /* VREF, VMID=2x5k */
680 snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1); 746 snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1);
@@ -730,7 +796,10 @@ static struct snd_soc_dai_driver wm8988_dai = {
730 796
731static int wm8988_suspend(struct snd_soc_codec *codec) 797static int wm8988_suspend(struct snd_soc_codec *codec)
732{ 798{
799 struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
800
733 wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF); 801 wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF);
802 regcache_mark_dirty(wm8988->regmap);
734 return 0; 803 return 0;
735} 804}
736 805
@@ -743,10 +812,10 @@ static int wm8988_resume(struct snd_soc_codec *codec)
743static int wm8988_probe(struct snd_soc_codec *codec) 812static int wm8988_probe(struct snd_soc_codec *codec)
744{ 813{
745 struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); 814 struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
746 struct snd_soc_dapm_context *dapm = &codec->dapm;
747 int ret = 0; 815 int ret = 0;
748 816
749 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8988->control_type); 817 codec->control_data = wm8988->regmap;
818 ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
750 if (ret < 0) { 819 if (ret < 0) {
751 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 820 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
752 return ret; 821 return ret;
@@ -767,12 +836,6 @@ static int wm8988_probe(struct snd_soc_codec *codec)
767 836
768 wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 837 wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
769 838
770 snd_soc_add_controls(codec, wm8988_snd_controls,
771 ARRAY_SIZE(wm8988_snd_controls));
772 snd_soc_dapm_new_controls(dapm, wm8988_dapm_widgets,
773 ARRAY_SIZE(wm8988_dapm_widgets));
774 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
775
776 return 0; 839 return 0;
777} 840}
778 841
@@ -788,9 +851,25 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8988 = {
788 .suspend = wm8988_suspend, 851 .suspend = wm8988_suspend,
789 .resume = wm8988_resume, 852 .resume = wm8988_resume,
790 .set_bias_level = wm8988_set_bias_level, 853 .set_bias_level = wm8988_set_bias_level,
791 .reg_cache_size = ARRAY_SIZE(wm8988_reg), 854
792 .reg_word_size = sizeof(u16), 855 .controls = wm8988_snd_controls,
793 .reg_cache_default = wm8988_reg, 856 .num_controls = ARRAY_SIZE(wm8988_snd_controls),
857 .dapm_widgets = wm8988_dapm_widgets,
858 .num_dapm_widgets = ARRAY_SIZE(wm8988_dapm_widgets),
859 .dapm_routes = wm8988_dapm_routes,
860 .num_dapm_routes = ARRAY_SIZE(wm8988_dapm_routes),
861};
862
863static struct regmap_config wm8988_regmap = {
864 .reg_bits = 7,
865 .val_bits = 9,
866
867 .max_register = WM8988_LPPB,
868 .writeable_reg = wm8988_writeable,
869
870 .cache_type = REGCACHE_RBTREE,
871 .reg_defaults = wm8988_reg_defaults,
872 .num_reg_defaults = ARRAY_SIZE(wm8988_reg_defaults),
794}; 873};
795 874
796#if defined(CONFIG_SPI_MASTER) 875#if defined(CONFIG_SPI_MASTER)
@@ -799,24 +878,33 @@ static int __devinit wm8988_spi_probe(struct spi_device *spi)
799 struct wm8988_priv *wm8988; 878 struct wm8988_priv *wm8988;
800 int ret; 879 int ret;
801 880
802 wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL); 881 wm8988 = devm_kzalloc(&spi->dev, sizeof(struct wm8988_priv),
882 GFP_KERNEL);
803 if (wm8988 == NULL) 883 if (wm8988 == NULL)
804 return -ENOMEM; 884 return -ENOMEM;
805 885
806 wm8988->control_type = SND_SOC_SPI; 886 wm8988->regmap = regmap_init_spi(spi, &wm8988_regmap);
887 if (IS_ERR(wm8988->regmap)) {
888 ret = PTR_ERR(wm8988->regmap);
889 dev_err(&spi->dev, "Failed to init regmap: %d\n", ret);
890 return ret;
891 }
892
807 spi_set_drvdata(spi, wm8988); 893 spi_set_drvdata(spi, wm8988);
808 894
809 ret = snd_soc_register_codec(&spi->dev, 895 ret = snd_soc_register_codec(&spi->dev,
810 &soc_codec_dev_wm8988, &wm8988_dai, 1); 896 &soc_codec_dev_wm8988, &wm8988_dai, 1);
811 if (ret < 0) 897 if (ret != 0)
812 kfree(wm8988); 898 regmap_exit(wm8988->regmap);
899
813 return ret; 900 return ret;
814} 901}
815 902
816static int __devexit wm8988_spi_remove(struct spi_device *spi) 903static int __devexit wm8988_spi_remove(struct spi_device *spi)
817{ 904{
905 struct wm8988_priv *wm8988 = spi_get_drvdata(spi);
818 snd_soc_unregister_codec(&spi->dev); 906 snd_soc_unregister_codec(&spi->dev);
819 kfree(spi_get_drvdata(spi)); 907 regmap_exit(wm8988->regmap);
820 return 0; 908 return 0;
821} 909}
822 910
@@ -837,24 +925,33 @@ static __devinit int wm8988_i2c_probe(struct i2c_client *i2c,
837 struct wm8988_priv *wm8988; 925 struct wm8988_priv *wm8988;
838 int ret; 926 int ret;
839 927
840 wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL); 928 wm8988 = devm_kzalloc(&i2c->dev, sizeof(struct wm8988_priv),
929 GFP_KERNEL);
841 if (wm8988 == NULL) 930 if (wm8988 == NULL)
842 return -ENOMEM; 931 return -ENOMEM;
843 932
844 i2c_set_clientdata(i2c, wm8988); 933 i2c_set_clientdata(i2c, wm8988);
845 wm8988->control_type = SND_SOC_I2C; 934
935 wm8988->regmap = regmap_init_i2c(i2c, &wm8988_regmap);
936 if (IS_ERR(wm8988->regmap)) {
937 ret = PTR_ERR(wm8988->regmap);
938 dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
939 return ret;
940 }
846 941
847 ret = snd_soc_register_codec(&i2c->dev, 942 ret = snd_soc_register_codec(&i2c->dev,
848 &soc_codec_dev_wm8988, &wm8988_dai, 1); 943 &soc_codec_dev_wm8988, &wm8988_dai, 1);
849 if (ret < 0) 944 if (ret != 0)
850 kfree(wm8988); 945 regmap_exit(wm8988->regmap);
946
851 return ret; 947 return ret;
852} 948}
853 949
854static __devexit int wm8988_i2c_remove(struct i2c_client *client) 950static __devexit int wm8988_i2c_remove(struct i2c_client *client)
855{ 951{
952 struct wm8988_priv *wm8988 = i2c_get_clientdata(client);
856 snd_soc_unregister_codec(&client->dev); 953 snd_soc_unregister_codec(&client->dev);
857 kfree(i2c_get_clientdata(client)); 954 regmap_exit(wm8988->regmap);
858 return 0; 955 return 0;
859} 956}
860 957
@@ -866,7 +963,7 @@ MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id);
866 963
867static struct i2c_driver wm8988_i2c_driver = { 964static struct i2c_driver wm8988_i2c_driver = {
868 .driver = { 965 .driver = {
869 .name = "wm8988-codec", 966 .name = "wm8988",
870 .owner = THIS_MODULE, 967 .owner = THIS_MODULE,
871 }, 968 },
872 .probe = wm8988_i2c_probe, 969 .probe = wm8988_i2c_probe,