aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8580.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm8580.c')
-rw-r--r--sound/soc/codecs/wm8580.c154
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 */
211static 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 */
222static 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 */
233static 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
266static 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
275static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); 208static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
276 209
277static int wm8580_out_vu(struct snd_kcontrol *kcontrol, 210static 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};
903EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580); 833EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580);
904 834
905static int wm8580_register(struct wm8580_priv *wm8580) 835static 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
1023static int wm8580_i2c_remove(struct i2c_client *client) 957static int wm8580_i2c_remove(struct i2c_client *client)