diff options
Diffstat (limited to 'sound/soc/codecs/wm8580.c')
-rw-r--r-- | sound/soc/codecs/wm8580.c | 69 |
1 files changed, 30 insertions, 39 deletions
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 4bbc0a79f01e..8212b3c8bfdd 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/regulator/consumer.h> | 27 | #include <linux/regulator/consumer.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/of_device.h> | ||
29 | 30 | ||
30 | #include <sound/core.h> | 31 | #include <sound/core.h> |
31 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
@@ -212,7 +213,7 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol, | |||
212 | reg_cache[reg] = 0; | 213 | reg_cache[reg] = 0; |
213 | reg_cache[reg2] = 0; | 214 | reg_cache[reg2] = 0; |
214 | 215 | ||
215 | ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); | 216 | ret = snd_soc_put_volsw(kcontrol, ucontrol); |
216 | if (ret < 0) | 217 | if (ret < 0) |
217 | return ret; | 218 | return ret; |
218 | 219 | ||
@@ -223,31 +224,19 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol, | |||
223 | return 0; | 224 | return 0; |
224 | } | 225 | } |
225 | 226 | ||
226 | #define SOC_WM8580_OUT_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, \ | ||
227 | xinvert, tlv_array) \ | ||
228 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | ||
229 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | ||
230 | SNDRV_CTL_ELEM_ACCESS_READWRITE, \ | ||
231 | .tlv.p = (tlv_array), \ | ||
232 | .info = snd_soc_info_volsw_2r, \ | ||
233 | .get = snd_soc_get_volsw_2r, .put = wm8580_out_vu, \ | ||
234 | .private_value = (unsigned long)&(struct soc_mixer_control) \ | ||
235 | {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ | ||
236 | .max = xmax, .invert = xinvert} } | ||
237 | |||
238 | static const struct snd_kcontrol_new wm8580_snd_controls[] = { | 227 | static const struct snd_kcontrol_new wm8580_snd_controls[] = { |
239 | SOC_WM8580_OUT_DOUBLE_R_TLV("DAC1 Playback Volume", | 228 | SOC_DOUBLE_R_EXT_TLV("DAC1 Playback Volume", |
240 | WM8580_DIGITAL_ATTENUATION_DACL1, | 229 | WM8580_DIGITAL_ATTENUATION_DACL1, |
241 | WM8580_DIGITAL_ATTENUATION_DACR1, | 230 | WM8580_DIGITAL_ATTENUATION_DACR1, |
242 | 0, 0xff, 0, dac_tlv), | 231 | 0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv), |
243 | SOC_WM8580_OUT_DOUBLE_R_TLV("DAC2 Playback Volume", | 232 | SOC_DOUBLE_R_EXT_TLV("DAC2 Playback Volume", |
244 | WM8580_DIGITAL_ATTENUATION_DACL2, | 233 | WM8580_DIGITAL_ATTENUATION_DACL2, |
245 | WM8580_DIGITAL_ATTENUATION_DACR2, | 234 | WM8580_DIGITAL_ATTENUATION_DACR2, |
246 | 0, 0xff, 0, dac_tlv), | 235 | 0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv), |
247 | SOC_WM8580_OUT_DOUBLE_R_TLV("DAC3 Playback Volume", | 236 | SOC_DOUBLE_R_EXT_TLV("DAC3 Playback Volume", |
248 | WM8580_DIGITAL_ATTENUATION_DACL3, | 237 | WM8580_DIGITAL_ATTENUATION_DACL3, |
249 | WM8580_DIGITAL_ATTENUATION_DACR3, | 238 | WM8580_DIGITAL_ATTENUATION_DACR3, |
250 | 0, 0xff, 0, dac_tlv), | 239 | 0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv), |
251 | 240 | ||
252 | SOC_SINGLE("DAC1 Deemphasis Switch", WM8580_DAC_CONTROL3, 0, 1, 0), | 241 | SOC_SINGLE("DAC1 Deemphasis Switch", WM8580_DAC_CONTROL3, 0, 1, 0), |
253 | SOC_SINGLE("DAC2 Deemphasis Switch", WM8580_DAC_CONTROL3, 1, 1, 0), | 242 | SOC_SINGLE("DAC2 Deemphasis Switch", WM8580_DAC_CONTROL3, 1, 1, 0), |
@@ -441,8 +430,7 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, | |||
441 | /* Always disable the PLL - it is not safe to leave it running | 430 | /* Always disable the PLL - it is not safe to leave it running |
442 | * while reprogramming it. | 431 | * while reprogramming it. |
443 | */ | 432 | */ |
444 | reg = snd_soc_read(codec, WM8580_PWRDN2); | 433 | snd_soc_update_bits(codec, WM8580_PWRDN2, pwr_mask, pwr_mask); |
445 | snd_soc_write(codec, WM8580_PWRDN2, reg | pwr_mask); | ||
446 | 434 | ||
447 | if (!freq_in || !freq_out) | 435 | if (!freq_in || !freq_out) |
448 | return 0; | 436 | return 0; |
@@ -460,8 +448,7 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, | |||
460 | snd_soc_write(codec, WM8580_PLLA4 + offset, reg); | 448 | snd_soc_write(codec, WM8580_PLLA4 + offset, reg); |
461 | 449 | ||
462 | /* All done, turn it on */ | 450 | /* All done, turn it on */ |
463 | reg = snd_soc_read(codec, WM8580_PWRDN2); | 451 | snd_soc_update_bits(codec, WM8580_PWRDN2, pwr_mask, 0); |
464 | snd_soc_write(codec, WM8580_PWRDN2, reg & ~pwr_mask); | ||
465 | 452 | ||
466 | return 0; | 453 | return 0; |
467 | } | 454 | } |
@@ -759,7 +746,6 @@ static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute) | |||
759 | static int wm8580_set_bias_level(struct snd_soc_codec *codec, | 746 | static int wm8580_set_bias_level(struct snd_soc_codec *codec, |
760 | enum snd_soc_bias_level level) | 747 | enum snd_soc_bias_level level) |
761 | { | 748 | { |
762 | u16 reg; | ||
763 | switch (level) { | 749 | switch (level) { |
764 | case SND_SOC_BIAS_ON: | 750 | case SND_SOC_BIAS_ON: |
765 | case SND_SOC_BIAS_PREPARE: | 751 | case SND_SOC_BIAS_PREPARE: |
@@ -768,20 +754,19 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec, | |||
768 | case SND_SOC_BIAS_STANDBY: | 754 | case SND_SOC_BIAS_STANDBY: |
769 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 755 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
770 | /* Power up and get individual control of the DACs */ | 756 | /* Power up and get individual control of the DACs */ |
771 | reg = snd_soc_read(codec, WM8580_PWRDN1); | 757 | snd_soc_update_bits(codec, WM8580_PWRDN1, |
772 | reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD); | 758 | WM8580_PWRDN1_PWDN | |
773 | snd_soc_write(codec, WM8580_PWRDN1, reg); | 759 | WM8580_PWRDN1_ALLDACPD, 0); |
774 | 760 | ||
775 | /* Make VMID high impedance */ | 761 | /* Make VMID high impedance */ |
776 | reg = snd_soc_read(codec, WM8580_ADC_CONTROL1); | 762 | snd_soc_update_bits(codec, WM8580_ADC_CONTROL1, |
777 | reg &= ~0x100; | 763 | 0x100, 0); |
778 | snd_soc_write(codec, WM8580_ADC_CONTROL1, reg); | ||
779 | } | 764 | } |
780 | break; | 765 | break; |
781 | 766 | ||
782 | case SND_SOC_BIAS_OFF: | 767 | case SND_SOC_BIAS_OFF: |
783 | reg = snd_soc_read(codec, WM8580_PWRDN1); | 768 | snd_soc_update_bits(codec, WM8580_PWRDN1, |
784 | snd_soc_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN); | 769 | WM8580_PWRDN1_PWDN, WM8580_PWRDN1_PWDN); |
785 | break; | 770 | break; |
786 | } | 771 | } |
787 | codec->dapm.bias_level = level; | 772 | codec->dapm.bias_level = level; |
@@ -907,6 +892,11 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8580 = { | |||
907 | .reg_cache_default = wm8580_reg, | 892 | .reg_cache_default = wm8580_reg, |
908 | }; | 893 | }; |
909 | 894 | ||
895 | static const struct of_device_id wm8580_of_match[] = { | ||
896 | { .compatible = "wlf,wm8580" }, | ||
897 | { }, | ||
898 | }; | ||
899 | |||
910 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 900 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
911 | static int wm8580_i2c_probe(struct i2c_client *i2c, | 901 | static int wm8580_i2c_probe(struct i2c_client *i2c, |
912 | const struct i2c_device_id *id) | 902 | const struct i2c_device_id *id) |
@@ -943,8 +933,9 @@ MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id); | |||
943 | 933 | ||
944 | static struct i2c_driver wm8580_i2c_driver = { | 934 | static struct i2c_driver wm8580_i2c_driver = { |
945 | .driver = { | 935 | .driver = { |
946 | .name = "wm8580-codec", | 936 | .name = "wm8580", |
947 | .owner = THIS_MODULE, | 937 | .owner = THIS_MODULE, |
938 | .of_match_table = wm8580_of_match, | ||
948 | }, | 939 | }, |
949 | .probe = wm8580_i2c_probe, | 940 | .probe = wm8580_i2c_probe, |
950 | .remove = wm8580_i2c_remove, | 941 | .remove = wm8580_i2c_remove, |